aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/include/uhdlib/rfnoc/reg_iface_adapter.hpp
blob: 55153c2290bc54fbc703aed7c9214d323291f468 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
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 */