ChimeraTK-DeviceAccess 03.26.00
Loading...
Searching...
No Matches
NumericAddressedLowLevelTransferElement.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
6#include "TransferElement.h"
7
8namespace ChimeraTK {
9
10 template<typename UserType, bool isRaw>
11 class NumericAddressedBackendRegisterAccessor;
12
13 class NumericAddressedBackendASCIIAccessor;
14
15 /********************************************************************************************************************/
26 public:
28 const boost::shared_ptr<NumericAddressedBackend>& dev, size_t bar, size_t startAddress, size_t numberOfBytes)
29 : TransferElement("", {AccessMode::raw}), _dev(dev), _bar(bar),
30 _unalignedAccess(_dev->_unalignedAccess, std::defer_lock) {
31 if(!dev->barIndexValid(bar)) {
32 std::stringstream errorMessage;
33 errorMessage << "Invalid bar number: " << bar << std::endl;
34 throw ChimeraTK::logic_error(errorMessage.str());
35 }
36 setAddress(startAddress, numberOfBytes);
37 }
38
40
42 // There is nothing we can do about reinterpet_casting with the C-style interface
43 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
44 _dev->read(_bar, _startAddress, reinterpret_cast<int32_t*>(rawDataBuffer.data()), _numberOfBytes);
45 }
46
48 // There is nothing we can do about reinterpet_casting with the C-style interface
49 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
50 _dev->write(_bar, _startAddress, reinterpret_cast<int32_t*>(rawDataBuffer.data()), _numberOfBytes);
51 return false;
52 }
53
54 void doPostRead(TransferType, bool hasNewData) override {
55 if(hasNewData) {
56 // it is acceptable to create a new version number only in doPostRead because the LowLevelTransferElement never
57 // has wait_for_new_data.
58 _versionNumber = {};
59 }
60 }
61
63 if(_isUnaligned) {
64 _unalignedAccess.lock();
65 // There is nothing we can do about reinterpet_casting with the C-style interface
66 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
67 _dev->read(_bar, _startAddress, reinterpret_cast<int32_t*>(rawDataBuffer.data()), _numberOfBytes);
68 }
69 }
70
72 if(_unalignedAccess.owns_lock()) {
73 _unalignedAccess.unlock();
74 }
75 }
76
82 bool isMergeable(const boost::shared_ptr<TransferElement const>& other) const {
83 if(!_dev->canMergeRequests()) return false;
84
85 // accessor type, device and bar must be the same
86 auto rhsCasted = boost::dynamic_pointer_cast<const NumericAddressedLowLevelTransferElement>(other);
87 if(!rhsCasted) return false;
88 if(_dev != rhsCasted->_dev) return false;
89 if(_bar != rhsCasted->_bar) return false;
90
91 // only allow adjacent and overlapping address areas to be merged
92 if(_startAddress + _numberOfBytes < rhsCasted->_startAddress) return false;
93 if(_startAddress > rhsCasted->_startAddress + rhsCasted->_numberOfBytes) return false;
94 return true;
95 }
96
97 bool mayReplaceOther(const boost::shared_ptr<TransferElement const>&) const override {
98 return false; // never used, since isMergeable() is used instead
99 }
100
101 const std::type_info& getValueType() const override {
102 // This implementation is for int32_t only (as all numerically addressed
103 // backends under the hood.
104 return typeid(int32_t);
105 }
106
107 bool isReadOnly() const override { return false; }
108
109 bool isReadable() const override { return true; }
110
111 bool isWriteable() const override { return true; }
112
120 uint8_t* begin(size_t addressInBar) { return rawDataBuffer.data() + (addressInBar - _startAddress); }
121
124 void changeAddress(size_t startAddress, size_t numberOfWords) {
125 setAddress(startAddress, numberOfWords);
126 isShared = true;
127 }
128
129 boost::shared_ptr<TransferElement> makeCopyRegisterDecorator() override { // LCOV_EXCL_LINE
130 throw ChimeraTK::logic_error("NumericAddressedLowLevelTransferElement::makeCopyRegisterDecorator() "
131 "is not implemented"); // LCOV_EXCL_LINE
132 } // LCOV_EXCL_LINE
133
134 protected:
137 void setAddress(size_t startAddress, size_t numberOfBytes) {
138 // change address
139 _startAddress = startAddress;
140 _numberOfBytes = numberOfBytes;
141
142 // make sure access is properly aligned
143 _isUnaligned = false;
144 auto alignment = _dev->minimumTransferAlignment(_bar);
145 auto start_padding = _startAddress % alignment;
146 assert(_startAddress >= start_padding);
147 if(start_padding > 0) _isUnaligned = true;
148 _startAddress -= start_padding;
149 _numberOfBytes += start_padding;
150 auto end_padding = alignment - _numberOfBytes % alignment;
151 if(end_padding != alignment) {
152 _isUnaligned = true;
153 _numberOfBytes += end_padding;
154 }
155
156 // Allocated the buffer
158
159 // update the name
161 }
162
164 boost::shared_ptr<NumericAddressedBackend> _dev;
165
167 uint64_t _bar;
168
170 uint64_t _startAddress{};
171
174
177 bool isShared{false};
178
180 bool _isUnaligned{false};
181
183 std::unique_lock<std::mutex> _unalignedAccess;
184
186 std::vector<uint8_t> rawDataBuffer;
187
188 std::vector<boost::shared_ptr<TransferElement>> getHardwareAccessingElements() override {
189 return {boost::enable_shared_from_this<TransferElement>::shared_from_this()};
190 }
191
192 std::list<boost::shared_ptr<TransferElement>> getInternalElements() override { return {}; }
193
194 void replaceTransferElement(boost::shared_ptr<TransferElement> /*newElement*/) override {} // LCOV_EXCL_LINE
195
196 template<typename UserType, bool isRaw>
198
200 };
201
202} // namespace ChimeraTK
Implementation of the NDRegisterAccessor for NumericAddressedBackends for ASCII data.
Implementation of the NDRegisterAccessor for NumericAddressedBackends for scalar and 1D registers.
Implementation of the NDRegisterAccessor for NumericAddressedBackends, responsible for the underlying...
void doPostRead(TransferType, bool hasNewData) override
Backend specific implementation of postRead().
boost::shared_ptr< TransferElement > makeCopyRegisterDecorator() override
Create a CopyRegisterDecorator of the right type decorating this TransferElement.
bool isReadOnly() const override
Check if transfer element is read only, i.e.
void doReadTransferSynchronously() override
Implementation version of readTransfer() for synchronous reads.
void replaceTransferElement(boost::shared_ptr< TransferElement >) override
Search for all underlying TransferElements which are considered identical (see sameRegister()) with t...
const std::type_info & getValueType() const override
Returns the std::type_info for the value type of this transfer element.
bool doWriteTransfer(ChimeraTK::VersionNumber) override
Implementation version of writeTransfer().
std::vector< boost::shared_ptr< TransferElement > > getHardwareAccessingElements() override
Obtain the underlying TransferElements with actual hardware access.
std::unique_lock< std::mutex > _unalignedAccess
Lock to protect unaligned access (with mutex from backend)
void changeAddress(size_t startAddress, size_t numberOfWords)
Change the start address (inside the bar given in the constructor) and number of words of this access...
bool isWriteable() const override
Check if transfer element is writeable.
bool isShared
flag if changeAddress() has been called, which is this low-level transfer element is shared between m...
NumericAddressedLowLevelTransferElement(const boost::shared_ptr< NumericAddressedBackend > &dev, size_t bar, size_t startAddress, size_t numberOfBytes)
bool isReadable() const override
Check if transfer element is readable.
uint8_t * begin(size_t addressInBar)
Return pointer to the begin of the raw buffer matching the given address.
void doPostWrite(TransferType, VersionNumber) override
Backend specific implementation of postWrite().
void doPreWrite(TransferType, VersionNumber) override
Backend specific implementation of preWrite().
std::list< boost::shared_ptr< TransferElement > > getInternalElements() override
Obtain the full list of TransferElements internally used by this TransferElement.
boost::shared_ptr< NumericAddressedBackend > _dev
the backend to use for the actual hardware access
void setAddress(size_t startAddress, size_t numberOfBytes)
Set the start address (inside the bar given in the constructor) and number of words of this accessor.
bool mayReplaceOther(const boost::shared_ptr< TransferElement const > &) const override
Check whether the TransferElement can be used in places where the TransferElement "other" is currentl...
bool isMergeable(const boost::shared_ptr< TransferElement const > &other) const
Check if the address areas are adjacent and/or overlapping.
Base class for register accessors which can be part of a TransferGroup.
std::string _name
Identifier uniquely identifying the TransferElement.
VersionNumber _versionNumber
The version number of the last successful transfer.
Class for generating and holding version numbers without exposing a numeric representation.
Exception thrown when a logic error has occured.
Definition Exception.h:51
@ raw
Raw access: disable any possible conversion from the original hardware data type into the given UserT...
TransferType
Used to indicate the applicable operation on a Transferelement.
std::string to_string(const std::string &v)