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