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 | |
| 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')
| -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 */  | 
