ChimeraTK-DeviceAccess 03.29.00
Loading...
Searching...
No Matches
LNMAccessorPlugin.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
8
9#include <optional>
10#include <utility>
11
12namespace ChimeraTK::LNMBackend {
13
16 UndecoratedParams(const std::string& name, size_t numberOfWords, size_t wordOffsetInRegister, AccessModeFlags flags)
17 : _name(name), _numberOfWords(numberOfWords), _wordOffsetInRegister(wordOffsetInRegister),
18 _flags(std::move(flags)) {}
19 std::string _name;
23 };
24
28 public:
29 explicit AccessorPluginBase(const LNMBackendRegisterInfo& info);
30 virtual ~AccessorPluginBase() = default;
31
33 template<typename UserType>
34 boost::shared_ptr<NDRegisterAccessor<UserType>> getAccessor(boost::shared_ptr<LogicalNameMappingBackend> backend,
35 size_t numberOfWords, size_t wordOffsetInRegister, AccessModeFlags flags, size_t pluginIndex) {
37 getAccessor_impl, UserType, backend, numberOfWords, wordOffsetInRegister, flags, pluginIndex);
38 }
40 boost::shared_ptr<NDRegisterAccessor<T>>(
41 boost::shared_ptr<LogicalNameMappingBackend>, size_t, size_t, AccessModeFlags, size_t));
42
51
68 virtual void doRegisterInfoUpdate() = 0;
69
74 virtual void openHook(const boost::shared_ptr<LogicalNameMappingBackend>& backend) { std::ignore = backend; }
75
80 virtual void postParsingHook([[maybe_unused]] const boost::shared_ptr<const LogicalNameMappingBackend>& backend) {}
81
85 virtual void closeHook() {}
86
91 virtual void exceptionHook() {}
92
93 protected:
96 };
97
105 template<typename Derived>
107 public:
108 explicit AccessorPlugin(const LNMBackendRegisterInfo& info, size_t pluginIndex);
109
110 private:
111 // we make our destructor private and add Derived as a friend to enforce the correct CRTP
112 ~AccessorPlugin() override = default;
113 friend Derived;
114
115 public:
122 virtual DataType getTargetDataType(DataType userType) const { return userType; }
123
131 template<typename UserType, typename TargetType>
132 boost::shared_ptr<NDRegisterAccessor<UserType>> decorateAccessor(
133 boost::shared_ptr<LogicalNameMappingBackend>& backend,
134 boost::shared_ptr<NDRegisterAccessor<TargetType>>& target, const UndecoratedParams& accessorParams);
135
137 template<typename UserType>
138 boost::shared_ptr<NDRegisterAccessor<UserType>> getAccessor_impl(
139 boost::shared_ptr<LogicalNameMappingBackend>& backend, size_t numberOfWords, size_t wordOffsetInRegister,
140 AccessModeFlags flags, size_t pluginIndex);
141
146 };
147
148 /********************************************************************************************************************/
149
151 boost::shared_ptr<AccessorPluginBase> makePlugin(LNMBackendRegisterInfo info, size_t pluginIndex,
152 const std::string& name, const std::map<std::string, std::string>& parameters);
153
154 /********************************************************************************************************************/
155 /* Known plugins are defined below (implementations should go to a separate .cc file) */
156 /********************************************************************************************************************/
157
159 class MultiplierPlugin : public AccessorPlugin<MultiplierPlugin> {
160 public:
162 const LNMBackendRegisterInfo& info, size_t pluginIndex, const std::map<std::string, std::string>& parameters);
163
164 void doRegisterInfoUpdate() override;
166
167 template<typename UserType, typename TargetType>
168 boost::shared_ptr<NDRegisterAccessor<UserType>> decorateAccessor(
169 boost::shared_ptr<LogicalNameMappingBackend>& backend,
170 boost::shared_ptr<NDRegisterAccessor<TargetType>>& target, const UndecoratedParams& accessorParams);
171
172 double _factor;
173 };
174
175 /********************************************************************************************************************/
176
178 class MonostableTriggerPlugin : public AccessorPlugin<MonostableTriggerPlugin> {
179 public:
181 LNMBackendRegisterInfo info, size_t pluginIndex, const std::map<std::string, std::string>& parameters);
182
183 void doRegisterInfoUpdate() override;
185
186 template<typename UserType, typename TargetType>
187 boost::shared_ptr<NDRegisterAccessor<UserType>> decorateAccessor(
188 boost::shared_ptr<LogicalNameMappingBackend>& backend,
189 boost::shared_ptr<NDRegisterAccessor<TargetType>>& target, const UndecoratedParams& accessorParams);
190
192 uint32_t _active{1};
193 uint32_t _inactive{0};
194 };
195
197 class ForceReadOnlyPlugin : public AccessorPlugin<ForceReadOnlyPlugin> {
198 public:
200 const LNMBackendRegisterInfo& info, size_t pluginIndex, const std::map<std::string, std::string>& parameters);
201
202 void doRegisterInfoUpdate() override;
203
204 template<typename UserType, typename TargetType>
205 boost::shared_ptr<NDRegisterAccessor<UserType>> decorateAccessor(
206 boost::shared_ptr<LogicalNameMappingBackend>& backend,
207 boost::shared_ptr<NDRegisterAccessor<TargetType>>& target, const UndecoratedParams& accessorParams);
208 };
209
211 class ForcePollingReadPlugin : public AccessorPlugin<ForcePollingReadPlugin> {
212 public:
214 const LNMBackendRegisterInfo& info, size_t pluginIndex, const std::map<std::string, std::string>& parameters);
215
216 void doRegisterInfoUpdate() override;
217
218 template<typename UserType, typename TargetType>
219 boost::shared_ptr<NDRegisterAccessor<UserType>> decorateAccessor(
220 boost::shared_ptr<LogicalNameMappingBackend>& backend,
221 boost::shared_ptr<NDRegisterAccessor<TargetType>>& target, const UndecoratedParams& accessorParams);
222 };
223
227 class SetDescriptionPlugin : public AccessorPlugin<SetDescriptionPlugin> {
228 public:
230 const LNMBackendRegisterInfo& info, size_t pluginIndex, const std::map<std::string, std::string>& parameters);
231
232 void doRegisterInfoUpdate() override;
233
234 template<typename UserType, typename TargetType>
235 boost::shared_ptr<NDRegisterAccessor<UserType>> decorateAccessor(
236 boost::shared_ptr<LogicalNameMappingBackend>& backend,
237 boost::shared_ptr<NDRegisterAccessor<TargetType>>& target, const UndecoratedParams& accessorParams);
238
239 private:
240 std::optional<std::string> _engineeringUnit;
241 std::optional<std::string> _description;
242 };
243
245 class TypeHintModifierPlugin : public AccessorPlugin<TypeHintModifierPlugin> {
246 public:
248 const LNMBackendRegisterInfo& info, size_t pluginIndex, const std::map<std::string, std::string>& parameters);
249
250 void doRegisterInfoUpdate() override;
251
252 private:
253 DataType _dataType{DataType::none};
254 };
255
256 class BitRangeAccessPlugin : public AccessorPlugin<BitRangeAccessPlugin> {
257 public:
259 const LNMBackendRegisterInfo& info, size_t pluginIndex, const std::map<std::string, std::string>& parameters);
260
261 template<typename UserType, typename TargetType>
262 boost::shared_ptr<NDRegisterAccessor<UserType>> decorateAccessor(
263 boost::shared_ptr<LogicalNameMappingBackend>& backend,
264 boost::shared_ptr<NDRegisterAccessor<TargetType>>& target, const UndecoratedParams& accessorParams);
265
266 void doRegisterInfoUpdate() override;
267 DataType getTargetDataType(DataType /*userType*/) const override { return DataType::uint64; }
268 uint32_t _shift{0};
269 uint32_t _numberOfBits{0};
270 bool _writeable{true};
273 };
274
276 class TagModifierPlugin : public AccessorPlugin<TagModifierPlugin> {
277 public:
279 const LNMBackendRegisterInfo& info, size_t pluginIndex, const std::map<std::string, std::string>& parameters);
280
281 void doRegisterInfoUpdate() override;
282
283 private:
284 std::set<std::string> _tagsToAdd;
285 std::set<std::string> _tagsToRemove;
286 std::set<std::string> _tagsToSet;
287 };
288
289 template<auto Tag>
291 public:
292 FixedTagModifierPlugin(const LNMBackendRegisterInfo& info, size_t pluginIndex,
293 [[maybe_unused]] const std::map<std::string, std::string>& parameters)
294 : TagModifierPlugin(info, pluginIndex, {{"add", Tag}}) {}
295
297 };
298
299 class FanOutPlugin : public AccessorPlugin<FanOutPlugin> {
300 public:
302 const LNMBackendRegisterInfo& info, size_t pluginIndex, const std::map<std::string, std::string>& parameters);
303
304 template<typename UserType, typename TargetType>
305 boost::shared_ptr<NDRegisterAccessor<UserType>> decorateAccessor(
306 boost::shared_ptr<LogicalNameMappingBackend>& backend,
307 boost::shared_ptr<NDRegisterAccessor<TargetType>>& target, const UndecoratedParams& accessorParams);
308
309 void doRegisterInfoUpdate() override;
310
311 private:
312 std::list<std::string> _targets;
313 };
314
315 /********************************************************************************************************************/
316
317 /********************************************************************************************************************/
318 /* Implementations follow here */
319 /********************************************************************************************************************/
320
321 template<typename Derived>
323 : AccessorPluginBase(info), _pluginIndex(pluginIndex) {
325 }
326
327 /********************************************************************************************************************/
328
329 template<typename Derived>
330 template<typename UserType, typename TargetType>
331 boost::shared_ptr<NDRegisterAccessor<UserType>> AccessorPlugin<Derived>::decorateAccessor(
332 boost::shared_ptr<LogicalNameMappingBackend>&, boost::shared_ptr<NDRegisterAccessor<TargetType>>& target,
333 const UndecoratedParams&) {
334 if constexpr(std::is_same<UserType, TargetType>::value) {
335 return target;
336 }
337
338 assert(false); // When overriding getTargetDataType(), also decorateAccessor()
339 // must be overridden!
340
341 return {};
342 }
343
344 /********************************************************************************************************************/
345
346 template<typename Derived>
347 template<typename UserType>
348 boost::shared_ptr<NDRegisterAccessor<UserType>> AccessorPlugin<Derived>::getAccessor_impl(
349 boost::shared_ptr<LogicalNameMappingBackend>& backend, size_t numberOfWords, size_t wordOffsetInRegister,
350 AccessModeFlags flags, size_t pluginIndex) {
351 boost::shared_ptr<NDRegisterAccessor<UserType>> decorated;
352
353 assert(_pluginIndex == pluginIndex);
354
355 // obtain desired target type from plugin implementation
356 auto type = getTargetDataType(typeid(UserType));
357 if((_info._dataDescriptor.rawDataType() == DataType::none) && flags.has(AccessMode::raw)) {
359 "Access mode 'raw' is not supported for register '" + std::string(_info.getRegisterName()) + "'");
360 }
361
362 callForType(type, [&](auto T) {
363 boost::shared_ptr<ChimeraTK::NDRegisterAccessor<decltype(T)>> target;
364
365 target = backend->getRegisterAccessor_impl<decltype(T)>(
366 _info.getRegisterName(), numberOfWords, wordOffsetInRegister, flags, pluginIndex + 1);
367
368 // double buffering plugin needs numberOfWords, wordOffsetInRegister of already existing accessor
369 UndecoratedParams accessorParams(_info.registerName, numberOfWords, wordOffsetInRegister, flags);
370 decorated = static_cast<Derived*>(this)->template decorateAccessor<UserType>(backend, target, accessorParams);
371 });
372
373 decorated->setExceptionBackend(backend);
374 return decorated;
375 }
376
377} // namespace ChimeraTK::LNMBackend
#define CALL_VIRTUAL_FUNCTION_TEMPLATE(functionName, templateArgument,...)
Execute the virtual function template call using the vtable defined with the DEFINE_VIRTUAL_FUNCTION_...
#define FILL_VIRTUAL_FUNCTION_TEMPLATE_VTABLE(functionName)
Fill the vtable of a virtual function template defined with DEFINE_VIRTUAL_FUNCTION_TEMPLATE.
Set of AccessMode flags with additional functionality for an easier handling.
Definition AccessMode.h:48
bool has(AccessMode flag) const
Check if a certain flag is in the set.
Definition AccessMode.cc:20
Interface for backends to the register catalogue.
A class to describe which of the supported data types is used.
@ uint32
Unsigned 32 bit integer.
@ none
The data type/concept does not exist, e.g. there is no raw transfer (do not confuse with Void)
@ uint64
Unsigned 64 bit integer.
@ float64
Double precision float.
Base class for AccessorPlugins used by the LogicalNameMapping backend to store backends in lists.
virtual void exceptionHook()
Hook called when an exception is reported to the the backend via setException(), after the backend ha...
virtual void openHook(const boost::shared_ptr< LogicalNameMappingBackend > &backend)
Hook called when the backend is opened, at the end of the open() function after all backend work has ...
LNMBackendRegisterInfo _info
RegisterInfo describing the the target register for which this plugin instance should work.
boost::shared_ptr< NDRegisterAccessor< UserType > > getAccessor(boost::shared_ptr< LogicalNameMappingBackend > backend, size_t numberOfWords, size_t wordOffsetInRegister, AccessModeFlags flags, size_t pluginIndex)
Called by the backend when obtaining a register accessor.
virtual void postParsingHook(const boost::shared_ptr< const LogicalNameMappingBackend > &backend)
Hook called after the parsing of logical name map.
void updateRegisterInfo(BackendRegisterCatalogue< LNMBackendRegisterInfo > &)
Update the register info inside the catalogue if needed.
DEFINE_VIRTUAL_FUNCTION_TEMPLATE_VTABLE(getAccessor_impl, boost::shared_ptr< NDRegisterAccessor< T > >(boost::shared_ptr< LogicalNameMappingBackend >, size_t, size_t, AccessModeFlags, size_t))
virtual void doRegisterInfoUpdate()=0
Implementation of the plugin specific register information update.
virtual void closeHook()
Hook called when the backend is closed, at the beginning of the close() function when the device is s...
Base class for plugins that modify the behaviour of accessors in the logical name mapping backend.
size_t _pluginIndex
Index of the plugin instance within the stack of plugins on a particular register.
boost::shared_ptr< NDRegisterAccessor< UserType > > decorateAccessor(boost::shared_ptr< LogicalNameMappingBackend > &backend, boost::shared_ptr< NDRegisterAccessor< TargetType > > &target, const UndecoratedParams &accessorParams)
This function should be overridden by the plugin (yes, this is possible due to the CRTP).
boost::shared_ptr< NDRegisterAccessor< UserType > > getAccessor_impl(boost::shared_ptr< LogicalNameMappingBackend > &backend, size_t numberOfWords, size_t wordOffsetInRegister, AccessModeFlags flags, size_t pluginIndex)
This function is called by the backend.
AccessorPlugin(const LNMBackendRegisterInfo &info, size_t pluginIndex)
virtual DataType getTargetDataType(DataType userType) const
Return the data type for which the target accessor shall be obtained.
DataType getTargetDataType(DataType) const override
Return the data type for which the target accessor shall be obtained.
boost::shared_ptr< NDRegisterAccessor< UserType > > decorateAccessor(boost::shared_ptr< LogicalNameMappingBackend > &backend, boost::shared_ptr< NDRegisterAccessor< TargetType > > &target, const UndecoratedParams &accessorParams)
void doRegisterInfoUpdate() override
Implementation of the plugin specific register information update.
void doRegisterInfoUpdate() override
Implementation of the plugin specific register information update.
boost::shared_ptr< NDRegisterAccessor< UserType > > decorateAccessor(boost::shared_ptr< LogicalNameMappingBackend > &backend, boost::shared_ptr< NDRegisterAccessor< TargetType > > &target, const UndecoratedParams &accessorParams)
FixedTagModifierPlugin(const LNMBackendRegisterInfo &info, size_t pluginIndex, const std::map< std::string, std::string > &parameters)
ForcePollingRead Plugin: Forces a register to not allow setting the AccessMode::wait_for_new_data fla...
boost::shared_ptr< NDRegisterAccessor< UserType > > decorateAccessor(boost::shared_ptr< LogicalNameMappingBackend > &backend, boost::shared_ptr< NDRegisterAccessor< TargetType > > &target, const UndecoratedParams &accessorParams)
void doRegisterInfoUpdate() override
Implementation of the plugin specific register information update.
ForceReadOnly Plugin: Forces a register to be read only.
void doRegisterInfoUpdate() override
Implementation of the plugin specific register information update.
boost::shared_ptr< NDRegisterAccessor< UserType > > decorateAccessor(boost::shared_ptr< LogicalNameMappingBackend > &backend, boost::shared_ptr< NDRegisterAccessor< TargetType > > &target, const UndecoratedParams &accessorParams)
Monostable Trigger Plugin: Write value to target which falls back to another value after defined time...
DataType getTargetDataType(DataType) const override
Return the data type for which the target accessor shall be obtained.
void doRegisterInfoUpdate() override
Implementation of the plugin specific register information update.
boost::shared_ptr< NDRegisterAccessor< UserType > > decorateAccessor(boost::shared_ptr< LogicalNameMappingBackend > &backend, boost::shared_ptr< NDRegisterAccessor< TargetType > > &target, const UndecoratedParams &accessorParams)
Multiplier Plugin: Multiply register's data with a constant factor.
DataType getTargetDataType(DataType) const override
Return the data type for which the target accessor shall be obtained.
boost::shared_ptr< NDRegisterAccessor< UserType > > decorateAccessor(boost::shared_ptr< LogicalNameMappingBackend > &backend, boost::shared_ptr< NDRegisterAccessor< TargetType > > &target, const UndecoratedParams &accessorParams)
void doRegisterInfoUpdate() override
Implementation of the plugin specific register information update.
SetDescription Plugin: Overwrites the engineering unit and/or description of the accessor without cha...
void doRegisterInfoUpdate() override
Implementation of the plugin specific register information update.
boost::shared_ptr< NDRegisterAccessor< UserType > > decorateAccessor(boost::shared_ptr< LogicalNameMappingBackend > &backend, boost::shared_ptr< NDRegisterAccessor< TargetType > > &target, const UndecoratedParams &accessorParams)
TagModifier Plugin: Manipulate the tags in the register catalogue.
void doRegisterInfoUpdate() override
Implementation of the plugin specific register information update.
TypeHintModifier Plugin: Change the catalogue type of the mapped register.
void doRegisterInfoUpdate() override
Implementation of the plugin specific register information update.
RegisterInfo structure for the LogicalNameMappingBackend.
N-dimensional register accessor.
Exception thrown when a logic error has occured.
Definition Exception.h:51
boost::shared_ptr< AccessorPluginBase > makePlugin(LNMBackendRegisterInfo info, size_t pluginIndex, const std::string &name, const std::map< std::string, std::string > &parameters)
Factory function for accessor plugins.
void callForType(const std::type_info &type, LAMBDATYPE lambda)
Helper function for running code which uses some compile-time type that is specified at runtime as a ...
@ raw
Raw access: disable any possible conversion from the original hardware data type into the given UserT...
STL namespace.
Helper struct to hold extra parameters needed by some plugins, used in decorateAccessor()
UndecoratedParams(const std::string &name, size_t numberOfWords, size_t wordOffsetInRegister, AccessModeFlags flags)