ChimeraTK-DeviceAccess 03.27.00
Loading...
Searching...
No Matches
DummyRegisterAccessor.h
Go to the documentation of this file.
1// SPDX-FileCopyrightText: Deutsches Elektronen-Synchrotron DESY, MSK, ChimeraTK Project <chimeratk-support@desy.de>
2// SPDX-License-Identifier: LGPL-3.0-or-later
3#pragma once
4
5#include "DummyBackend.h"
6
7namespace ChimeraTK {
8
12 namespace proxies {
13
14 /******************************************************************************************************************/
15
20 template<typename UserType>
22 public:
23 virtual ~RawConverterCapsule() = default;
24 virtual UserType toCooked(std::byte* raw) = 0;
25 virtual void toRaw(UserType cooked, std::byte* raw) = 0;
26 static std::shared_ptr<RawConverterCapsule<UserType>> makeCapsule(
27 const ChimeraTK::NumericAddressedRegisterInfo& info, size_t channelIndex);
28 };
29
30 /******************************************************************************************************************/
35 template<typename T>
37 public:
38 DummyRegisterElement(std::shared_ptr<RawConverterCapsule<T>>& rc, int nbytes, std::byte* buffer)
39 : _rc(rc), _nbytes(nbytes), _buffer(buffer) {}
40
43 // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
44 operator T() const { return _rc->toCooked(_buffer); }
45
48 _rc->toRaw(rhs, _buffer);
49 return *this;
50 }
51
54 T cooked = _rc->toCooked(_buffer);
55 return operator=(cooked + 1);
56 }
57
60 T cooked = _rc->toCooked(_buffer);
61
62 return operator=(cooked - 1);
63 }
64
66 T operator++(int) {
67 T cooked = _rc->toCooked(_buffer);
68
69 operator=(cooked + 1);
70 return cooked;
71 }
72
74 T operator--(int) {
75 T cooked = _rc->toCooked(_buffer);
76
77 operator=(cooked - 1);
78 return cooked;
79 }
80
81 protected:
83 std::shared_ptr<RawConverterCapsule<T>>& _rc;
84
87
89 std::byte* _buffer;
90 };
91
92 /******************************************************************************************************************/
95 template<typename T>
97 public:
99 std::shared_ptr<proxies::RawConverterCapsule<T>>& rc, int nbytes, int pitch, int32_t* buffer)
100 : _rc(rc), _nbytes(nbytes), _pitch(pitch), _buffer(buffer) {}
101
103 DummyRegisterElement<T> operator[](unsigned int sample) {
104 // todo: Probably ranges are the correct tool in cpp22. In cpp17 this is not available yet. We turn off the
105 // warning not to use reinterpret_cast for the time being
106 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
107 auto* basePtr = reinterpret_cast<std::byte*>(_buffer);
108 auto* startPtr = basePtr + static_cast<size_t>(_pitch) * sample;
109 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
110 return DummyRegisterElement<T>(_rc, _nbytes, startPtr);
111 }
112
114 void operator=(const DummyRegisterSequence& rightHandSide) const = delete;
115
116 protected:
118 std::shared_ptr<proxies::RawConverterCapsule<T>>& _rc;
119
122
125
127 int32_t* _buffer;
128 };
129
130 /******************************************************************************************************************/
131
132 } // namespace proxies
133
134 /********************************************************************************************************************/
150 template<typename T>
152 public:
157 DummyRegisterAccessor(DummyBackend* dev, std::string const& module, std::string const& name)
158 : proxies::DummyRegisterElement<T>(_rc, 0, nullptr), _dev(dev), _path(module + "/" + name),
159 _registerInfo(_dev->_registerMap.getBackendRegister(_path)),
160 _rc(proxies::RawConverterCapsule<T>::makeCapsule(_registerInfo, 0)) {
161 // initialise the base DummyRegisterElement
164 }
165 // declare that we want the default copy constructor. Needed because we have a custom = operator
167
169 void operator=(const DummyRegisterAccessor& rightHandSide) const = delete;
170
172 proxies::DummyRegisterElement<T> operator[](unsigned int index) { return getProxy(index); }
173
175 unsigned int getNumberOfElements() { return _registerInfo.nElements; }
176
178 using proxies::DummyRegisterElement<T>::operator=;
179
181 [[nodiscard]] DummyBackend& getBackend() const { return *_dev; }
182
184 [[nodiscard]] const RegisterPath& getRegisterPath() const { return _path; }
185
187 void setWriteCallback(const std::function<void()>& writeCallback) {
188 assert(_registerInfo.elementPitchBits % 8 == 0);
190 {static_cast<uint8_t>(_registerInfo.bar), static_cast<uint32_t>(_registerInfo.address),
192 writeCallback);
193 }
194
196
200 std::unique_lock<std::mutex> getBufferLock() { return std::unique_lock<std::mutex>(_dev->mutex); }
201
202 protected:
205
208
211
213 std::shared_ptr<proxies::RawConverterCapsule<T>> _rc;
214
216 std::byte* getElement(unsigned int index) {
217 auto* ptr = &(_dev->_barContents[_registerInfo.bar][_registerInfo.address / sizeof(int32_t) + index]);
218 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
219 return reinterpret_cast<std::byte*>(ptr);
220 }
221
224 return proxies::DummyRegisterElement<T>(_rc, sizeof(int32_t), getElement(index));
225 }
226 };
227
228 /********************************************************************************************************************/
239 template<typename T>
241 public:
248 DummyMultiplexedRegisterAccessor(DummyBackend* dev, std::string const& module, std::string const& name)
249 : _dev(dev), _path(module + "/" + name) {
250 _registerInfo = _dev->_registerMap.getBackendRegister(module + "." + name);
251
252 // create fixed point converters for each channel
253 size_t ci = 0;
254 for(auto& c : _registerInfo.channels) {
255 // create fixed point converter for sequence
257 // store offsets and number of bytes per word
258 assert(c.bitOffset % 8 == 0);
259 _offsets.push_back(_registerInfo.address + c.bitOffset / 8);
260 _nbytes.push_back((c.width - 1) / 8 + 1); // width/8 rounded up
261 ++ci;
262 }
263
264 if(_rc.empty()) {
265 throw ChimeraTK::logic_error("No sequences found for name \"" + name + "\".");
266 }
267
268 // cache some information
270 assert(_registerInfo.elementPitchBits % 8 == 0);
272 }
273
275 void operator=(const DummyMultiplexedRegisterAccessor& rightHandSide) const = delete;
276
277 // declare that we want the default copy constructor. Needed because we have a custom = operator
279
281 unsigned int getNumberOfElements() { return _nElements; }
282
284 unsigned int getNumberOfSequences() { return _rc.size(); }
285
292 // todo: Probably ranges are the correct tool in cpp22. In cpp17 this is not available yet. We turn off the
293 // warning not to use reinterpret_cast for the time being
294 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
295 auto* basePtr = reinterpret_cast<std::byte*>(_dev->_barContents[_registerInfo.bar].data());
296 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
297 auto* seq = reinterpret_cast<int32_t*>(basePtr + _offsets[sequence]);
298 return proxies::DummyRegisterSequence<T>(_rc[sequence], _nbytes[sequence], _pitch, seq);
299 }
300
302 [[nodiscard]] DummyBackend& getBackend() const { return *_dev; }
303
305 [[nodiscard]] const RegisterPath& getRegisterPath() const { return _path; }
306
308
309 protected:
312
315
318
320 std::vector<std::shared_ptr<proxies::RawConverterCapsule<T>>> _rc;
321
323 std::vector<uint32_t> _offsets;
324
326 std::vector<uint32_t> _nbytes;
327
329 int _pitch = {0};
330
332 unsigned int _nElements;
333 };
334
346 public:
349 // NOLINTNEXTLINE(google-explicit-constructor, hicpp-explicit-conversions)
350 operator int32_t&() { return *_buffer; }
351
353 boost::shared_ptr<DeviceBackend> const& backend, std::string const& module, std::string const& name)
354 : _backend(boost::dynamic_pointer_cast<DummyBackend>(backend)) {
355 assert(_backend);
356 _registerInfo = _backend->_registerMap.getBackendRegister(module + "." + name);
357 _buffer = &(_backend->_barContents[_registerInfo.bar][_registerInfo.address / sizeof(int32_t)]);
358 }
359
360 // declare that we want the default copy constructor. Needed because we have a custom = operator
361 // The default copy/move constructor is fine. It will copy the raw pointer to the buffer,
362 // together with the shared pointer which holds the corresponding backend with the
363 // memory. So it is a consistent copy because the shared pointer is pointing to the
364 // same backend instance.
366
368 void operator=(const DummyRegisterRawAccessor& rightHandSide) const = delete;
369
371 _buffer[0] = rhs;
372 return *this;
373 }
374
376 int32_t& operator[](unsigned int index) { return _buffer[index]; }
377
379 [[nodiscard]] unsigned int getNumberOfElements() const { return _registerInfo.nElements; }
380
384 std::unique_lock<std::mutex> getBufferLock() { return std::unique_lock<std::mutex>(_backend->mutex); }
385
386 protected:
388 boost::shared_ptr<DummyBackend> _backend;
389
392
394 int32_t* _buffer;
395 };
396
397 /********************************************************************************************************************/
398
399} // namespace ChimeraTK
The dummy device opens a mapping file instead of a device, and implements all registers defined in th...
void setWriteCallbackFunction(AddressRange addressRange, boost::function< void(void)> const &writeCallbackFunction)
std::map< uint64_t, std::vector< int32_t > > _barContents
Register accessor for accessing multiplexed 2D array registers internally of a DummyBackend implement...
unsigned int _nElements
number of elements per sequence
DummyMultiplexedRegisterAccessor(DummyBackend *dev, std::string const &module, std::string const &name)
Constructor should normally be called in the constructor of the DummyBackend implementation.
std::vector< std::shared_ptr< proxies::RawConverterCapsule< T > > > _rc
pointer to fixed point converter
DummyBackend * _dev
pointer to VirtualDevice
DummyBackend & getBackend() const
Return the backend.
unsigned int getNumberOfSequences()
return number of sequences
const RegisterPath & getRegisterPath() const
Return the register path.
std::vector< uint32_t > _nbytes
number of bytes per word for sequences
const NumericAddressedRegisterInfo & getRegisterInfo()
DummyMultiplexedRegisterAccessor(const DummyMultiplexedRegisterAccessor &)=default
NumericAddressedRegisterInfo _registerInfo
register map information
int _pitch
pitch in bytes (distance between samples of the same sequence)
void operator=(const DummyMultiplexedRegisterAccessor &rightHandSide) const =delete
remove assignment operator since it will be confusing
unsigned int getNumberOfElements()
return number of elements per sequence
proxies::DummyRegisterSequence< T > operator[](unsigned int sequence)
Get or set register content by [] operators.
std::vector< uint32_t > _offsets
offsets in bytes for sequences
Register accessor for accessing single word or 1D array registers internally of a DummyBackend implem...
DummyBackend * _dev
pointer to VirtualDevice
DummyRegisterAccessor(const DummyRegisterAccessor &)=default
DummyBackend & getBackend() const
Return the backend.
void operator=(const DummyRegisterAccessor &rightHandSide) const =delete
remove assignment operator since it will be confusing *‍/
std::byte * getElement(unsigned int index)
return element
const RegisterPath & getRegisterPath() const
Return the register path.
std::shared_ptr< proxies::RawConverterCapsule< T > > _rc
fixed point converter
unsigned int getNumberOfElements()
return number of elements
RegisterPath _path
path of the register
proxies::DummyRegisterElement< T > operator[](unsigned int index)
Get or set register content by [] operator.
proxies::DummyRegisterElement< T > getProxy(int index)
return a proxy object
DummyRegisterAccessor(DummyBackend *dev, std::string const &module, std::string const &name)
Constructor should normally be called in the constructor of the DummyBackend implementation.
const NumericAddressedRegisterInfo & getRegisterInfo()
void setWriteCallback(const std::function< void()> &writeCallback)
Set callback function which is called when the register is written to (through the normal Device inte...
NumericAddressedRegisterInfo _registerInfo
register map information
std::unique_lock< std::mutex > getBufferLock()
Get a lock to safely modify the buffer in a multi-treaded environment.
Accessor for raw 32 bit integer access to the underlying memory space.
void operator=(const DummyRegisterRawAccessor &rightHandSide) const =delete
remove assignment operator since it will be confusing
DummyRegisterRawAccessor(boost::shared_ptr< DeviceBackend > const &backend, std::string const &module, std::string const &name)
unsigned int getNumberOfElements() const
return number of elements
boost::shared_ptr< DummyBackend > _backend
pointer to dummy backend
int32_t & operator[](unsigned int index)
Get or set register content by [] operator.
DummyRegisterRawAccessor(const DummyRegisterRawAccessor &)=default
NumericAddressedRegisterInfo _registerInfo
register map information
std::unique_lock< std::mutex > getBufferLock()
Get a lock to safely modify the buffer.
int32_t * _buffer
raw buffer of this accessor
DummyRegisterRawAccessor & operator=(int32_t rhs)
NumericAddressedRegisterCatalogue & _registerMap
NumericAddressedRegisterInfo getBackendRegister(const RegisterPath &registerPathName) const override
Note: Override this function if backend has "hidden" registers which are not added to the map and hen...
uint32_t nElements
Number of elements in register.
std::vector< ChannelInfo > channels
Define per-channel information (bit interpretation etc.), 1D/scalars have exactly one entry.
uint64_t bar
Upper part of the address (name originally from PCIe, meaning now generalised)
uint32_t elementPitchBits
Distance in bits (!) between two elements (of the same channel)
uint64_t address
Lower part of the address relative to BAR, in bytes.
Class to store a register path name.
Exception thrown when a logic error has occured.
Definition Exception.h:51
Temporary proxy class for use in the DummyRegister and DummyMultiplexedRegister classes.
std::byte * _buffer
raw buffer of this element
DummyRegisterElement< T > & operator=(T rhs)
assignment operator
DummyRegisterElement< T > operator++()
pre-increment operator
DummyRegisterElement(std::shared_ptr< RawConverterCapsule< T > > &rc, int nbytes, std::byte *buffer)
std::shared_ptr< RawConverterCapsule< T > > & _rc
fixed point converter to be used for this element
DummyRegisterElement< T > operator--()
pre-decrement operator
Temporary proxy class for sequences, used in the DummyMultiplexedRegister class.
int _pitch
pitch in bytes (distance between samples of the same sequence)
DummyRegisterElement< T > operator[](unsigned int sample)
Get or set register content by [] operator.
int32_t * _buffer
reference to the raw buffer (first word of the sequence)
DummyRegisterSequence(std::shared_ptr< proxies::RawConverterCapsule< T > > &rc, int nbytes, int pitch, int32_t *buffer)
std::shared_ptr< proxies::RawConverterCapsule< T > > & _rc
fixed point converter to be used for this sequence
void operator=(const DummyRegisterSequence &rightHandSide) const =delete
remove assignment operator since it will be confusing *‍/
This abstract class encapsulates a RawConverter to erase the exact RawConverter type (with all its te...
virtual UserType toCooked(std::byte *raw)=0
virtual void toRaw(UserType cooked, std::byte *raw)=0
static std::shared_ptr< RawConverterCapsule< UserType > > makeCapsule(const ChimeraTK::NumericAddressedRegisterInfo &info, size_t channelIndex)
@ raw
Raw access: disable any possible conversion from the original hardware data type into the given UserT...