ChimeraTK-DeviceAccess  03.18.00
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 
8 namespace ChimeraTK {
9 
10  template<typename UserType, typename DataConverterType, bool isRaw>
11  class NumericAddressedBackendRegisterAccessor;
12 
13  class NumericAddressedBackendASCIIAccessor;
14 
15  namespace detail {
16  template<typename UserType, typename DataConverterType, bool isRaw>
17  struct NumericAddressedPrePostActionsImplementor;
18  } // namespace detail
19 
20  /********************************************************************************************************************/
31  public:
33  const boost::shared_ptr<NumericAddressedBackend>& dev, size_t bar, size_t startAddress, size_t numberOfBytes)
34  : TransferElement("", {AccessMode::raw}), _dev(dev), _bar(bar),
35  _unalignedAccess(_dev->_unalignedAccess, std::defer_lock) {
36  if(!dev->barIndexValid(bar)) {
37  std::stringstream errorMessage;
38  errorMessage << "Invalid bar number: " << bar << std::endl;
39  throw ChimeraTK::logic_error(errorMessage.str());
40  }
41  setAddress(startAddress, numberOfBytes);
42  }
43 
44  ~NumericAddressedLowLevelTransferElement() override = default;
45 
46  void doReadTransferSynchronously() override {
47  // There is nothing we can do about reinterpet_casting with the C-style interface
48  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
49  _dev->read(_bar, _startAddress, reinterpret_cast<int32_t*>(rawDataBuffer.data()), _numberOfBytes);
50  }
51 
53  // There is nothing we can do about reinterpet_casting with the C-style interface
54  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
55  _dev->write(_bar, _startAddress, reinterpret_cast<int32_t*>(rawDataBuffer.data()), _numberOfBytes);
56  return false;
57  }
58 
59  void doPostRead(TransferType, bool hasNewData) override {
60  if(hasNewData) {
61  // it is acceptable to create a new version number only in doPostRead because the LowLevelTransferElement never
62  // has wait_for_new_data.
63  _versionNumber = {};
64  }
65  }
66 
68  if(_isUnaligned) {
69  _unalignedAccess.lock();
70  // There is nothing we can do about reinterpet_casting with the C-style interface
71  // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
72  _dev->read(_bar, _startAddress, reinterpret_cast<int32_t*>(rawDataBuffer.data()), _numberOfBytes);
73  }
74  }
75 
77  if(_unalignedAccess.owns_lock()) {
78  _unalignedAccess.unlock();
79  }
80  }
81 
87  bool isMergeable(const boost::shared_ptr<TransferElement const>& other) const {
88  if(!_dev->canMergeRequests()) return false;
89 
90  // accessor type, device and bar must be the same
91  auto rhsCasted = boost::dynamic_pointer_cast<const NumericAddressedLowLevelTransferElement>(other);
92  if(!rhsCasted) return false;
93  if(_dev != rhsCasted->_dev) return false;
94  if(_bar != rhsCasted->_bar) return false;
95 
96  // only allow adjacent and overlapping address areas to be merged
97  if(_startAddress + _numberOfBytes < rhsCasted->_startAddress) return false;
98  if(_startAddress > rhsCasted->_startAddress + rhsCasted->_numberOfBytes) return false;
99  return true;
100  }
101 
102  bool mayReplaceOther(const boost::shared_ptr<TransferElement const>&) const override {
103  return false; // never used, since isMergeable() is used instead
104  }
105 
106  const std::type_info& getValueType() const override {
107  // This implementation is for int32_t only (as all numerically addressed
108  // backends under the hood.
109  return typeid(int32_t);
110  }
111 
112  bool isReadOnly() const override { return false; }
113 
114  bool isReadable() const override { return true; }
115 
116  bool isWriteable() const override { return true; }
117 
125  uint8_t* begin(size_t addressInBar) { return rawDataBuffer.data() + (addressInBar - _startAddress); }
126 
129  void changeAddress(size_t startAddress, size_t numberOfWords) {
130  setAddress(startAddress, numberOfWords);
131  isShared = true;
132  }
133 
134  boost::shared_ptr<TransferElement> makeCopyRegisterDecorator() override { // LCOV_EXCL_LINE
135  throw ChimeraTK::logic_error("NumericAddressedLowLevelTransferElement::makeCopyRegisterDecorator() "
136  "is not implemented"); // LCOV_EXCL_LINE
137  } // LCOV_EXCL_LINE
138 
139  protected:
142  void setAddress(size_t startAddress, size_t numberOfBytes) {
143  // change address
144  _startAddress = startAddress;
145  _numberOfBytes = numberOfBytes;
146 
147  // make sure access is properly aligned
148  _isUnaligned = false;
149  auto alignment = _dev->minimumTransferAlignment(_bar);
150  auto start_padding = _startAddress % alignment;
151  assert(_startAddress >= start_padding);
152  if(start_padding > 0) _isUnaligned = true;
153  _startAddress -= start_padding;
154  _numberOfBytes += start_padding;
155  auto end_padding = alignment - _numberOfBytes % alignment;
156  if(end_padding != alignment) {
157  _isUnaligned = true;
158  _numberOfBytes += end_padding;
159  }
160 
161  // Allocated the buffer
163 
164  // update the name
166  }
167 
169  boost::shared_ptr<NumericAddressedBackend> _dev;
170 
172  uint64_t _bar;
173 
175  uint64_t _startAddress{};
176 
178  size_t _numberOfBytes{};
179 
182  bool isShared{false};
183 
185  bool _isUnaligned{false};
186 
188  std::unique_lock<std::mutex> _unalignedAccess;
189 
191  std::vector<uint8_t> rawDataBuffer;
192 
193  std::vector<boost::shared_ptr<TransferElement>> getHardwareAccessingElements() override {
194  return {boost::enable_shared_from_this<TransferElement>::shared_from_this()};
195  }
196 
197  std::list<boost::shared_ptr<TransferElement>> getInternalElements() override { return {}; }
198 
199  void replaceTransferElement(boost::shared_ptr<TransferElement> /*newElement*/) override {} // LCOV_EXCL_LINE
200 
201  template<typename UserType, typename DataConverterType, bool isRaw>
203 
204  template<typename UserType, typename DataConverterType, bool isRaw>
206 
208  };
209 
210 } // namespace ChimeraTK
ChimeraTK::NumericAddressedLowLevelTransferElement::NumericAddressedPrePostActionsImplementor
friend struct detail::NumericAddressedPrePostActionsImplementor
Definition: NumericAddressedLowLevelTransferElement.h:205
ChimeraTK::AccessMode::raw
@ raw
Raw access: disable any possible conversion from the original hardware data type into the given UserT...
ChimeraTK::NumericAddressedLowLevelTransferElement::~NumericAddressedLowLevelTransferElement
~NumericAddressedLowLevelTransferElement() override=default
ChimeraTK::NumericAddressedLowLevelTransferElement::_dev
boost::shared_ptr< NumericAddressedBackend > _dev
the backend to use for the actual hardware access
Definition: NumericAddressedLowLevelTransferElement.h:169
TransferElement.h
ChimeraTK::NumericAddressedBackendRegisterAccessor
Implementation of the NDRegisterAccessor for NumericAddressedBackends for scalar and 1D registers.
Definition: NumericAddressedBackendRegisterAccessor.h:17
ChimeraTK::NumericAddressedLowLevelTransferElement::getInternalElements
std::list< boost::shared_ptr< TransferElement > > getInternalElements() override
Obtain the full list of TransferElements internally used by this TransferElement.
Definition: NumericAddressedLowLevelTransferElement.h:197
ChimeraTK::NumericAddressedLowLevelTransferElement::doPostWrite
void doPostWrite(TransferType, VersionNumber) override
Backend specific implementation of postWrite().
Definition: NumericAddressedLowLevelTransferElement.h:76
ChimeraTK::NumericAddressedLowLevelTransferElement::_isUnaligned
bool _isUnaligned
flag whether access is unaligned
Definition: NumericAddressedLowLevelTransferElement.h:185
ChimeraTK::NumericAddressedLowLevelTransferElement::getHardwareAccessingElements
std::vector< boost::shared_ptr< TransferElement > > getHardwareAccessingElements() override
Obtain the underlying TransferElements with actual hardware access.
Definition: NumericAddressedLowLevelTransferElement.h:193
ChimeraTK::NumericAddressedLowLevelTransferElement::doWriteTransfer
bool doWriteTransfer(ChimeraTK::VersionNumber) override
Implementation version of writeTransfer().
Definition: NumericAddressedLowLevelTransferElement.h:52
ChimeraTK::NumericAddressedLowLevelTransferElement::isReadable
bool isReadable() const override
Check if transfer element is readable.
Definition: NumericAddressedLowLevelTransferElement.h:114
ChimeraTK::NumericAddressedLowLevelTransferElement::_startAddress
uint64_t _startAddress
start address w.r.t.
Definition: NumericAddressedLowLevelTransferElement.h:175
NumericAddressedBackend.h
ChimeraTK::NumericAddressedLowLevelTransferElement::_numberOfBytes
size_t _numberOfBytes
number of bytes to access
Definition: NumericAddressedLowLevelTransferElement.h:178
ChimeraTK::TransferElement::_name
std::string _name
Identifier uniquely identifying the TransferElement.
Definition: TransferElement.h:804
ChimeraTK::NumericAddressedLowLevelTransferElement::getValueType
const std::type_info & getValueType() const override
Returns the std::type_info for the value type of this transfer element.
Definition: NumericAddressedLowLevelTransferElement.h:106
ChimeraTK::NumericAddressedLowLevelTransferElement::setAddress
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.
Definition: NumericAddressedLowLevelTransferElement.h:142
ChimeraTK::NumericAddressedLowLevelTransferElement::begin
uint8_t * begin(size_t addressInBar)
Return pointer to the begin of the raw buffer matching the given address.
Definition: NumericAddressedLowLevelTransferElement.h:125
ChimeraTK::NumericAddressedLowLevelTransferElement::doPreWrite
void doPreWrite(TransferType, VersionNumber) override
Backend specific implementation of preWrite().
Definition: NumericAddressedLowLevelTransferElement.h:67
ChimeraTK::TransferType
TransferType
Used to indicate the applicable operation on a Transferelement.
Definition: TransferElement.h:51
ChimeraTK::NumericAddressedLowLevelTransferElement::isWriteable
bool isWriteable() const override
Check if transfer element is writeable.
Definition: NumericAddressedLowLevelTransferElement.h:116
ChimeraTK::NumericAddressedLowLevelTransferElement::_unalignedAccess
std::unique_lock< std::mutex > _unalignedAccess
Lock to protect unaligned access (with mutex from backend)
Definition: NumericAddressedLowLevelTransferElement.h:188
ChimeraTK::NumericAddressedLowLevelTransferElement::rawDataBuffer
std::vector< uint8_t > rawDataBuffer
raw buffer
Definition: NumericAddressedLowLevelTransferElement.h:191
ChimeraTK::NumericAddressedLowLevelTransferElement
Implementation of the NDRegisterAccessor for NumericAddressedBackends, responsible for the underlying...
Definition: NumericAddressedLowLevelTransferElement.h:30
ChimeraTK::TransferElement
Base class for register accessors which can be part of a TransferGroup.
Definition: TransferElement.h:67
ChimeraTK::NumericAddressedLowLevelTransferElement::mayReplaceOther
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...
Definition: NumericAddressedLowLevelTransferElement.h:102
ChimeraTK::NumericAddressedLowLevelTransferElement::doPostRead
void doPostRead(TransferType, bool hasNewData) override
Backend specific implementation of postRead().
Definition: NumericAddressedLowLevelTransferElement.h:59
ChimeraTK::NumericAddressedLowLevelTransferElement::doReadTransferSynchronously
void doReadTransferSynchronously() override
Implementation version of readTransfer() for synchronous reads.
Definition: NumericAddressedLowLevelTransferElement.h:46
ChimeraTK::VersionNumber
Class for generating and holding version numbers without exposing a numeric representation.
Definition: VersionNumber.h:23
ChimeraTK::NumericAddressedLowLevelTransferElement::replaceTransferElement
void replaceTransferElement(boost::shared_ptr< TransferElement >) override
Definition: NumericAddressedLowLevelTransferElement.h:199
ChimeraTK::NumericAddressedLowLevelTransferElement::NumericAddressedLowLevelTransferElement
NumericAddressedLowLevelTransferElement(const boost::shared_ptr< NumericAddressedBackend > &dev, size_t bar, size_t startAddress, size_t numberOfBytes)
Definition: NumericAddressedLowLevelTransferElement.h:32
ChimeraTK::NumericAddressedLowLevelTransferElement::makeCopyRegisterDecorator
boost::shared_ptr< TransferElement > makeCopyRegisterDecorator() override
Create a CopyRegisterDecorator of the right type decorating this TransferElement.
Definition: NumericAddressedLowLevelTransferElement.h:134
ChimeraTK::NumericAddressedLowLevelTransferElement::changeAddress
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...
Definition: NumericAddressedLowLevelTransferElement.h:129
ChimeraTK
Definition: DummyBackend.h:16
ChimeraTK::to_string
std::string to_string(Boolean &value)
Definition: SupportedUserTypes.h:59
ChimeraTK::NumericAddressedLowLevelTransferElement::isShared
bool isShared
flag if changeAddress() has been called, which is this low-level transfer element is shared between m...
Definition: NumericAddressedLowLevelTransferElement.h:182
ChimeraTK::NumericAddressedBackendASCIIAccessor
Implementation of the NDRegisterAccessor for NumericAddressedBackends for ASCII data.
Definition: NumericAddressedBackendASCIIAccessor.h:18
ChimeraTK::NumericAddressedLowLevelTransferElement::_bar
uint64_t _bar
start address w.r.t.
Definition: NumericAddressedLowLevelTransferElement.h:172
ChimeraTK::NumericAddressedLowLevelTransferElement::isMergeable
bool isMergeable(const boost::shared_ptr< TransferElement const > &other) const
Check if the address areas are adjacent and/or overlapping.
Definition: NumericAddressedLowLevelTransferElement.h:87
ChimeraTK::NumericAddressedLowLevelTransferElement::isReadOnly
bool isReadOnly() const override
Check if transfer element is read only, i.e.
Definition: NumericAddressedLowLevelTransferElement.h:112
ChimeraTK::logic_error
Exception thrown when a logic error has occured.
Definition: Exception.h:51
ChimeraTK::TransferElement::_versionNumber
VersionNumber _versionNumber
The version number of the last successful transfer.
Definition: TransferElement.h:851