ChimeraTK-DeviceAccess 03.25.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 <utility>
10
11namespace ChimeraTK::LNMBackend {
12
15 UndecoratedParams(const std::string& name, size_t numberOfWords, size_t wordOffsetInRegister, AccessModeFlags flags)
16 : _name(name), _numberOfWords(numberOfWords), _wordOffsetInRegister(wordOffsetInRegister),
17 _flags(std::move(flags)) {}
18 std::string _name;
22 };
23
27 public:
28 explicit AccessorPluginBase(const LNMBackendRegisterInfo& info);
29 virtual ~AccessorPluginBase() = default;
30
32 template<typename UserType>
33 boost::shared_ptr<NDRegisterAccessor<UserType>> getAccessor(boost::shared_ptr<LogicalNameMappingBackend> backend,
34 size_t numberOfWords, size_t wordOffsetInRegister, AccessModeFlags flags, size_t pluginIndex) {
36 getAccessor_impl, UserType, backend, numberOfWords, wordOffsetInRegister, flags, pluginIndex);
37 }
39 boost::shared_ptr<NDRegisterAccessor<T>>(
40 boost::shared_ptr<LogicalNameMappingBackend>, size_t, size_t, AccessModeFlags, size_t));
41
50
67 virtual void doRegisterInfoUpdate() = 0;
68
73 virtual void openHook(const boost::shared_ptr<LogicalNameMappingBackend>& backend) { std::ignore = backend; }
74
79 virtual void postParsingHook([[maybe_unused]] const boost::shared_ptr<const LogicalNameMappingBackend>& backend) {}
80
84 virtual void closeHook() {}
85
90 virtual void exceptionHook() {}
91
92 protected:
95 };
96
104 template<typename Derived>
106 public:
112 explicit AccessorPlugin(const LNMBackendRegisterInfo& info, size_t pluginIndex, bool shareTargetAccessors = false);
113
114 private:
115 // we make our destructor private and add Derived as a friend to enforce the correct CRTP
116 ~AccessorPlugin() override = default;
117 friend Derived;
118
119 protected:
125
126 public:
133 virtual DataType getTargetDataType(DataType userType) const { return userType; }
134
142 template<typename UserType, typename TargetType>
143 boost::shared_ptr<NDRegisterAccessor<UserType>> decorateAccessor(
144 boost::shared_ptr<LogicalNameMappingBackend>& backend,
145 boost::shared_ptr<NDRegisterAccessor<TargetType>>& target, const UndecoratedParams& accessorParams);
146
148 template<typename UserType>
149 boost::shared_ptr<NDRegisterAccessor<UserType>> getAccessor_impl(
150 boost::shared_ptr<LogicalNameMappingBackend>& backend, size_t numberOfWords, size_t wordOffsetInRegister,
151 AccessModeFlags flags, size_t pluginIndex);
152
157 };
158
159 /********************************************************************************************************************/
160
162 boost::shared_ptr<AccessorPluginBase> makePlugin(LNMBackendRegisterInfo info, size_t pluginIndex,
163 const std::string& name, const std::map<std::string, std::string>& parameters);
164
165 /********************************************************************************************************************/
166 /* Known plugins are defined below (implementations should go to a separate .cc file) */
167 /********************************************************************************************************************/
168
170 class MultiplierPlugin : public AccessorPlugin<MultiplierPlugin> {
171 public:
173 const LNMBackendRegisterInfo& info, size_t pluginIndex, const std::map<std::string, std::string>& parameters);
174
175 void doRegisterInfoUpdate() override;
177
178 template<typename UserType, typename TargetType>
179 boost::shared_ptr<NDRegisterAccessor<UserType>> decorateAccessor(
180 boost::shared_ptr<LogicalNameMappingBackend>& backend,
181 boost::shared_ptr<NDRegisterAccessor<TargetType>>& target, const UndecoratedParams& accessorParams);
182
183 double _factor;
184 };
185
186 /********************************************************************************************************************/
187
189 class MonostableTriggerPlugin : public AccessorPlugin<MonostableTriggerPlugin> {
190 public:
192 LNMBackendRegisterInfo info, size_t pluginIndex, const std::map<std::string, std::string>& parameters);
193
194 void doRegisterInfoUpdate() override;
196
197 template<typename UserType, typename TargetType>
198 boost::shared_ptr<NDRegisterAccessor<UserType>> decorateAccessor(
199 boost::shared_ptr<LogicalNameMappingBackend>& backend,
200 boost::shared_ptr<NDRegisterAccessor<TargetType>>& target, const UndecoratedParams& accessorParams);
201
203 uint32_t _active{1};
204 uint32_t _inactive{0};
205 };
206
208 class ForceReadOnlyPlugin : public AccessorPlugin<ForceReadOnlyPlugin> {
209 public:
211 const LNMBackendRegisterInfo& info, size_t pluginIndex, const std::map<std::string, std::string>& parameters);
212
213 void doRegisterInfoUpdate() override;
214
215 template<typename UserType, typename TargetType>
216 boost::shared_ptr<NDRegisterAccessor<UserType>> decorateAccessor(
217 boost::shared_ptr<LogicalNameMappingBackend>& backend,
218 boost::shared_ptr<NDRegisterAccessor<TargetType>>& target, const UndecoratedParams& accessorParams);
219 };
220
222 class ForcePollingReadPlugin : public AccessorPlugin<ForcePollingReadPlugin> {
223 public:
225 const LNMBackendRegisterInfo& info, size_t pluginIndex, const std::map<std::string, std::string>& parameters);
226
227 void doRegisterInfoUpdate() override;
228
229 template<typename UserType, typename TargetType>
230 boost::shared_ptr<NDRegisterAccessor<UserType>> decorateAccessor(
231 boost::shared_ptr<LogicalNameMappingBackend>& backend,
232 boost::shared_ptr<NDRegisterAccessor<TargetType>>& target, const UndecoratedParams& accessorParams);
233 };
234
236 class TypeHintModifierPlugin : public AccessorPlugin<TypeHintModifierPlugin> {
237 public:
239 const LNMBackendRegisterInfo& info, size_t pluginIndex, const std::map<std::string, std::string>& parameters);
240
241 void doRegisterInfoUpdate() override;
242
243 private:
244 DataType _dataType{DataType::none};
245 };
246
247 class BitRangeAccessPlugin : public AccessorPlugin<BitRangeAccessPlugin> {
248 public:
250 const LNMBackendRegisterInfo& info, size_t pluginIndex, const std::map<std::string, std::string>& parameters);
251
252 template<typename UserType, typename TargetType>
253 boost::shared_ptr<NDRegisterAccessor<UserType>> decorateAccessor(
254 boost::shared_ptr<LogicalNameMappingBackend>& backend,
255 boost::shared_ptr<NDRegisterAccessor<TargetType>>& target, const UndecoratedParams& accessorParams);
256
257 void doRegisterInfoUpdate() override;
258 DataType getTargetDataType(DataType /*userType*/) const override { return DataType::uint64; }
259 uint32_t _shift{0};
260 uint32_t _numberOfBits{0};
261 bool _writeable{true};
264 };
265
267 class TagModifierPlugin : public AccessorPlugin<TagModifierPlugin> {
268 public:
270 const LNMBackendRegisterInfo& info, size_t pluginIndex, const std::map<std::string, std::string>& parameters);
271
272 void doRegisterInfoUpdate() override;
273
274 private:
275 std::set<std::string> _tagsToAdd;
276 std::set<std::string> _tagsToRemove;
277 std::set<std::string> _tagsToSet;
278 };
279
280 template<auto Tag>
282 public:
283 FixedTagModifierPlugin(const LNMBackendRegisterInfo& info, size_t pluginIndex,
284 [[maybe_unused]] const std::map<std::string, std::string>& parameters)
285 : TagModifierPlugin(info, pluginIndex, {{"add", Tag}}) {}
286
288 };
289
290 class FanOutPlugin : public AccessorPlugin<FanOutPlugin> {
291 public:
293 const LNMBackendRegisterInfo& info, size_t pluginIndex, const std::map<std::string, std::string>& parameters);
294
295 template<typename UserType, typename TargetType>
296 boost::shared_ptr<NDRegisterAccessor<UserType>> decorateAccessor(
297 boost::shared_ptr<LogicalNameMappingBackend>& backend,
298 boost::shared_ptr<NDRegisterAccessor<TargetType>>& target, const UndecoratedParams& accessorParams);
299
300 void doRegisterInfoUpdate() override;
301
302 private:
303 std::list<std::string> _targets;
304 };
305
306 /********************************************************************************************************************/
307
308 /********************************************************************************************************************/
309 /* Implementations follow here */
310 /********************************************************************************************************************/
311
312 template<typename Derived>
314 const LNMBackendRegisterInfo& info, size_t pluginIndex, bool shareTargetAccessors)
315 : AccessorPluginBase(info), _needSharedTarget{shareTargetAccessors}, _pluginIndex(pluginIndex) {
317 }
318
319 /********************************************************************************************************************/
320
321 template<typename Derived>
322 template<typename UserType, typename TargetType>
323 boost::shared_ptr<NDRegisterAccessor<UserType>> AccessorPlugin<Derived>::decorateAccessor(
324 boost::shared_ptr<LogicalNameMappingBackend>&, boost::shared_ptr<NDRegisterAccessor<TargetType>>& target,
325 const UndecoratedParams&) {
326 if constexpr(std::is_same<UserType, TargetType>::value) {
327 return target;
328 }
329
330 assert(false); // When overriding getTargetDataType(), also decorateAccessor()
331 // must be overridden!
332
333 return {};
334 }
335
336 /********************************************************************************************************************/
337
338 template<typename Derived>
339 template<typename UserType>
340 boost::shared_ptr<NDRegisterAccessor<UserType>> AccessorPlugin<Derived>::getAccessor_impl(
341 boost::shared_ptr<LogicalNameMappingBackend>& backend, size_t numberOfWords, size_t wordOffsetInRegister,
342 AccessModeFlags flags, size_t pluginIndex) {
343 boost::shared_ptr<NDRegisterAccessor<UserType>> decorated;
344
345 assert(_pluginIndex == pluginIndex);
346
347 // obtain desired target type from plugin implementation
348 auto type = getTargetDataType(typeid(UserType));
349 if((_info._dataDescriptor.rawDataType() == DataType::none) && flags.has(AccessMode::raw)) {
351 "Access mode 'raw' is not supported for register '" + std::string(_info.getRegisterName()) + "'");
352 }
353
354 callForType(type, [&](auto T) {
355 boost::shared_ptr<ChimeraTK::NDRegisterAccessor<decltype(T)>> target;
356
357 if(_needSharedTarget) {
358 auto& map = boost::fusion::at_key<decltype(T)>(backend->sharedAccessorMap.table);
359 RegisterPath path{_info.registerName};
360 path.setAltSeparator(".");
361 LogicalNameMappingBackend::AccessorKey key{backend.get(), path};
362
363 auto it = map.find(key);
364 if(it == map.end() || (target = it->second.accessor.lock()) == nullptr) {
365 // obtain target accessor with desired type
366 target = backend->getRegisterAccessor_impl<decltype(T)>(
367 _info.getRegisterName(), numberOfWords, wordOffsetInRegister, flags, pluginIndex + 1);
368 map[key].accessor = target;
369 }
370 }
371 else {
372 target = backend->getRegisterAccessor_impl<decltype(T)>(
373 _info.getRegisterName(), numberOfWords, wordOffsetInRegister, flags, pluginIndex + 1);
374 }
375
376 // double buffering plugin needs numberOfWords, wordOffsetInRegister of already existing accessor
377 UndecoratedParams accessorParams(_info.registerName, numberOfWords, wordOffsetInRegister, flags);
378 decorated = static_cast<Derived*>(this)->template decorateAccessor<UserType>(backend, target, accessorParams);
379 });
380
381 decorated->setExceptionBackend(backend);
382 return decorated;
383 }
384
385} // 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.
const bool _needSharedTarget
Deriving plugins should set this to true if they want to use interlocked access to the same target ac...
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, bool shareTargetAccessors=false)
The constructor of the plugin should also accept a 3rd argument: const std::map<std::string,...
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.
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.
std::pair< DeviceBackend *, RegisterPath > AccessorKey
Map of target accessors which are potentially shared across our accessors.
N-dimensional register accessor.
Class to store a register path name.
void setAltSeparator(const std::string &altSeparator)
set alternative separator.
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)