diff options
author | Martin Braun <martin.braun@ettus.com> | 2019-06-05 16:37:20 -0700 |
---|---|---|
committer | Martin Braun <martin.braun@ettus.com> | 2019-11-26 11:49:25 -0800 |
commit | 67ea15ad4b57c36f8b0dc80a87cf0ac16b585d34 (patch) | |
tree | 542b19787085fec32022cd8ef8d70def39885003 /host/lib/include/uhdlib | |
parent | d420f4968f7bd78afa4f27aaf5abcf26d0f61f4c (diff) | |
download | uhd-67ea15ad4b57c36f8b0dc80a87cf0ac16b585d34.tar.gz uhd-67ea15ad4b57c36f8b0dc80a87cf0ac16b585d34.tar.bz2 uhd-67ea15ad4b57c36f8b0dc80a87cf0ac16b585d34.zip |
rfnoc: add reg_iface_adapter
This converts from register_iface& to wb_iface::sptr. Useful for
connecting new block controllers with older interfaces.
Diffstat (limited to 'host/lib/include/uhdlib')
-rw-r--r-- | host/lib/include/uhdlib/rfnoc/reg_iface_adapter.hpp | 121 |
1 files changed, 121 insertions, 0 deletions
diff --git a/host/lib/include/uhdlib/rfnoc/reg_iface_adapter.hpp b/host/lib/include/uhdlib/rfnoc/reg_iface_adapter.hpp new file mode 100644 index 000000000..55153c229 --- /dev/null +++ b/host/lib/include/uhdlib/rfnoc/reg_iface_adapter.hpp @@ -0,0 +1,121 @@ +// +// Copyright 2019 Ettus Research, a National Instruments Brand +// +// SPDX-License-Identifier: GPL-3.0-or-later +// + +#ifndef INCLUDED_LIBUHD_RFNOC_REG2WBIF_ADAPTER_HPP +#define INCLUDED_LIBUHD_RFNOC_REG2WBIF_ADAPTER_HPP + +#include <uhd/config.hpp> +#include <uhd/rfnoc/register_iface.hpp> +#include <uhd/types/wb_iface.hpp> +#include <boost/make_shared.hpp> + +//! Convenience macro to generate a reg_iface_adapter from within an RFNoC block +#define RFNOC_MAKE_WB_IFACE(BASE_OFFSET, CHAN) \ + boost::make_shared<reg_iface_adapter>( \ + [this]() -> register_iface& { return regs(); }, \ + [this, chan = CHAN]() { return get_command_time(chan); }, \ + [this, chan = CHAN]( \ + const uhd::time_spec_t& time) { set_command_time(time, chan); }, \ + BASE_OFFSET) + +namespace uhd { namespace rfnoc { + +/*! register_iface to wb_iface adapter + * + * From within a noc_block_base derivative, this call will work to create a + * wb_iface: + * + * wb_iface::sptr ctrl = boost::make_shared<reg_iface_adapter>( + * [this]() -> register_iface& { return regs(); }, offset); + * + * Or you use the macro: + * wb_iface::sptr ctrl = RFNOC_MAKE_WB_IFACE(offset, chan); + */ +class UHD_API reg_iface_adapter : public uhd::timed_wb_iface +{ +public: + using regs_accessor_t = std::function<register_iface&(void)>; + using time_accessor_t = std::function<uhd::time_spec_t(void)>; + using time_setter_t = std::function<void(const uhd::time_spec_t&)>; + + /*! + * \param regs_accessor Function object to retrieve the register_iface + * reference + * \param time_accessor Function object to get the current command time + * \param time_setter Function object to set the command time + * \param base_offset Base offset for all peeks and pokes. If base_offset + * is set to 0x80000, peek32(4) will poke 0x80004. + */ + reg_iface_adapter(regs_accessor_t&& regs_accessor, + time_accessor_t&& time_accessor, + time_setter_t&& time_setter, + const uint32_t base_offset = 0) + : _regs_accessor(std::move(regs_accessor)) + , _time_accessor(std::move(time_accessor)) + , _time_setter(std::move(time_setter)) + , _base_offset(base_offset) + { + // nop + } + + /*! Timeless constructor: All command times will be executed ASAP, setting + * time does nothing + * + * \param regs_accessor Function object to retrieve the register_iface + * reference + * \param base_offset Base offset for all peeks and pokes. If base_offset + * is set to 0x80000, peek32(4) will poke 0x80004. + */ + reg_iface_adapter(regs_accessor_t&& regs_accessor, const uint32_t base_offset = 0) + : _regs_accessor(std::move(regs_accessor)) + , _time_accessor([]() { return uhd::time_spec_t::ASAP; }) + , _time_setter([](const uhd::time_spec_t&) { /* nop */ }) + , _base_offset(base_offset) + { + // nop + } + + void poke32(const uhd::wb_iface::wb_addr_type addr, const uint32_t data) + { + _regs_accessor().poke32(_base_offset + addr, data, _time_accessor()); + } + + void poke64(const uhd::wb_iface::wb_addr_type addr, const uint64_t data) + { + _regs_accessor().poke64(_base_offset + addr, data, _time_accessor()); + } + + uint32_t peek32(const uhd::wb_iface::wb_addr_type addr) + { + return _regs_accessor().peek32(_base_offset + addr, _time_accessor()); + } + + uint64_t peek64(const uhd::wb_iface::wb_addr_type addr) + { + return _regs_accessor().peek64(_base_offset + addr, _time_accessor()); + } + + uhd::time_spec_t get_time(void) + { + return _time_accessor(); + } + + void set_time(const uhd::time_spec_t& t) + { + _time_setter(t); + } + +private: + regs_accessor_t _regs_accessor; + time_accessor_t _time_accessor; + time_setter_t _time_setter; + uint32_t _base_offset; +}; + + +}} /* namespace uhd::rfnoc */ + +#endif /* INCLUDED_LIBUHD_RFNOC_REG2WBIF_ADAPTER_HPP */ |