ChimeraTK-DeviceAccess 03.31.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 "ReadCoordinator.h"
7#include "TransferElement.h"
8
9namespace ChimeraTK {
10
11 template<typename UserType, bool isRaw>
12 class NumericAddressedBackendRegisterAccessor;
13
14 class NumericAddressedBackendASCIIAccessor;
15
16 /********************************************************************************************************************/
27 public:
29 const boost::shared_ptr<NumericAddressedBackend>& dev, size_t bar, size_t startAddress, size_t numberOfBytes)
30 : TransferElement("", {AccessMode::raw}), _dev(dev), _bar(bar),
31 _unalignedAccess(_dev->_unalignedAccess, std::defer_lock) {
32 if(!dev->barIndexValid(bar)) {
33 std::stringstream errorMessage;
34 errorMessage << "Invalid bar number: " << bar << std::endl;
35 throw ChimeraTK::logic_error(errorMessage.str());
36 }
37 setAddress(startAddress, numberOfBytes);
38 }
39
41
43 // There is nothing we can do about reinterpet_casting with the C-style interface
44 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
45 _dev->read(_bar, _startAddress, reinterpret_cast<int32_t*>(rawDataBuffer.data()), _numberOfBytes);
46 }
47
49 // There is nothing we can do about reinterpet_casting with the C-style interface
50 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
51 _dev->write(_bar, _startAddress, reinterpret_cast<int32_t*>(rawDataBuffer.data()), _numberOfBytes);
52 return false;
53 }
54
55 void doPostRead(TransferType, bool hasNewData) override {
56 if(hasNewData) {
57 // it is acceptable to create a new version number only in doPostRead because the LowLevelTransferElement never
58 // has wait_for_new_data.
59 _versionNumber = {};
60
61 // Run the read coordinator once for this read (the base class calls doPostRead at most once per read)
63 }
64 }
65
67 if(_isUnaligned) {
68 _unalignedAccess.lock();
69 // There is nothing we can do about reinterpet_casting with the C-style interface
70 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
71 _dev->read(_bar, _startAddress, reinterpret_cast<int32_t*>(rawDataBuffer.data()), _numberOfBytes);
72 }
73 }
74
76 if(_unalignedAccess.owns_lock()) {
77 _unalignedAccess.unlock();
78 }
79 }
80
86 bool isMergeable(const boost::shared_ptr<TransferElement const>& other) const {
87 if(!_dev->canMergeRequests()) return false;
88
89 // accessor type, device and bar must be the same
90 auto rhsCasted = boost::dynamic_pointer_cast<const NumericAddressedLowLevelTransferElement>(other);
91 if(!rhsCasted) return false;
92 if(_dev != rhsCasted->_dev) return false;
93 if(_bar != rhsCasted->_bar) return false;
94
95 // only allow adjacent and overlapping address areas to be merged
96 if(_startAddress + _numberOfBytes < rhsCasted->_startAddress) return false;
97 if(_startAddress > rhsCasted->_startAddress + rhsCasted->_numberOfBytes) return false;
98 return true;
99 }
100
101 bool mayReplaceOther(const boost::shared_ptr<TransferElement const>&) const override {
102 return false; // never used, since isMergeable() is used instead
103 }
104
105 const std::type_info& getValueType() const override {
106 // This implementation is for int32_t only (as all numerically addressed
107 // backends under the hood.
108 return typeid(int32_t);
109 }
110
111 bool isReadOnly() const override { return false; }
112
113 bool isReadable() const override { return true; }
114
115 bool isWriteable() const override { return true; }
116
124 uint8_t* begin(size_t addressInBar) { return rawDataBuffer.data() + (addressInBar - _startAddress); }
125
128 void changeAddress(size_t startAddress, size_t numberOfWords) {
129 setAddress(startAddress, numberOfWords);
130 isShared = true;
131 }
132
133 boost::shared_ptr<TransferElement> makeCopyRegisterDecorator() override { // LCOV_EXCL_LINE
134 throw ChimeraTK::logic_error("NumericAddressedLowLevelTransferElement::makeCopyRegisterDecorator() "
135 "is not implemented"); // LCOV_EXCL_LINE
136 } // LCOV_EXCL_LINE
137
138 protected:
141 void setAddress(size_t startAddress, size_t numberOfBytes) {
142 // change address
143 _startAddress = startAddress;
144 _numberOfBytes = numberOfBytes;
145
146 // make sure access is properly aligned
147 _isUnaligned = false;
148 auto alignment = _dev->minimumTransferAlignment(_bar);
149 auto start_padding = _startAddress % alignment;
150 assert(_startAddress >= start_padding);
151 if(start_padding > 0) _isUnaligned = true;
152 _startAddress -= start_padding;
153 _numberOfBytes += start_padding;
154 auto end_padding = alignment - _numberOfBytes % alignment;
155 if(end_padding != alignment) {
156 _isUnaligned = true;
157 _numberOfBytes += end_padding;
158 }
159
160 // Allocated the buffer
162
163 // update the name
165 }
166
168 boost::shared_ptr<NumericAddressedBackend> _dev;
169
171 uint64_t _bar;
172
174 uint64_t _startAddress{};
175
178
181 bool isShared{false};
182
184 bool _isUnaligned{false};
185
187 std::unique_lock<std::mutex> _unalignedAccess;
188
190 std::vector<uint8_t> rawDataBuffer;
191
196 detail::ReadCoordinator _readCoordinator;
197
198 std::vector<boost::shared_ptr<TransferElement>> getHardwareAccessingElements() override {
199 return {boost::enable_shared_from_this<TransferElement>::shared_from_this()};
200 }
201
202 std::list<boost::shared_ptr<TransferElement>> getInternalElements() override { return {}; }
203
204 void replaceTransferElement(boost::shared_ptr<TransferElement> /*newElement*/) override {} // LCOV_EXCL_LINE
205
206 template<typename UserType, bool isRaw>
208
210 };
211
212} // 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.
detail::ReadCoordinator _readCoordinator
Read coordinator serving every read consumer of this element (scalar registers, non-muxed 1D arrays a...
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
This header collects some conversion routines which should be useful both for ApplicationCore Python ...
@ 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)