15#include <nlohmann/json.hpp>
17using json = nlohmann::json;
24 std::unique_ptr<NumericAddressedRegisterCatalogue> registerMapPointer,
25 const std::string& dataConsistencyKeyDescriptor)
26 : _registerMapPointer(
std::move(registerMapPointer)), _registerMap(*_registerMapPointer) {
28 if(!mapFileName.empty()) {
32 if(!dataConsistencyKeyDescriptor.empty()) {
35 auto jdescr = nlohmann::json::parse(dataConsistencyKeyDescriptor);
36 for(
const auto& el : jdescr.items()) {
40 catch(json::parse_error& e) {
41 throw ChimeraTK::logic_error(std::format(
"Parsing DataConsistencyKeys parameter '{}' results in JSON error: {}",
42 dataConsistencyKeyDescriptor, e.what()));
56 if(components.size() != 3) {
59 auto bar = std::stoi(components[1]);
60 size_t pos = components[2].find_first_of(
'*');
61 auto address = std::stoi(components[2].substr(0, pos));
63 if(pos != std::string::npos) {
64 nBytes = std::stoi(components[2].substr(pos + 1));
67 nBytes =
sizeof(int32_t);
69 auto nElements = nBytes /
sizeof(int32_t);
70 if(nBytes == 0 || nBytes %
sizeof(int32_t) != 0) {
80 [[maybe_unused]] int32_t* data, [[maybe_unused]]
size_t sizeInBytes) {
81 throw ChimeraTK::logic_error(
"NumericAddressedBackend: internal error: interface read() called w/ 32bit address");
87 [[maybe_unused]] int32_t
const* data, [[maybe_unused]]
size_t sizeInBytes) {
88 throw ChimeraTK::logic_error(
"NumericAddressedBackend: internal error: interface write() called w/ 32bit address");
95#pragma GCC diagnostic push
96#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
97 read(
static_cast<uint8_t
>(bar),
static_cast<uint32_t
>(address), data, sizeInBytes);
98#pragma GCC diagnostic pop
104#pragma GCC diagnostic push
105#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
106 write(
static_cast<uint8_t
>(bar),
static_cast<uint32_t
>(address), data, sizeInBytes);
107#pragma GCC diagnostic pop
114 return bar <= 5 || bar == 13;
119 template<
typename UserType>
120 boost::shared_ptr<NDRegisterAccessor<UserType>> NumericAddressedBackend::getRegisterAccessor_impl(
127 "Register " + registerPathName +
" does not support AccessMode::wait_for_new_data.");
131 boost::static_pointer_cast<NumericAddressedBackend>(shared_from_this()),
132 registerInfo.getQualifiedAsyncId().front(), _asyncIsActive, registerPathName, numberOfWords,
133 wordOffsetInRegister, flags);
135 return getSyncRegisterAccessor<UserType>(registerPathName, numberOfWords, wordOffsetInRegister, flags);
140 template<
typename UserType>
141 boost::shared_ptr<NDRegisterAccessor<UserType>> NumericAddressedBackend::getSyncRegisterAccessor(
142 const RegisterPath& registerPathName,
size_t numberOfWords,
size_t wordOffsetInRegister, AccessModeFlags flags) {
143 boost::shared_ptr<NDRegisterAccessor<UserType>> accessor;
148 if(registerInfo.getNumberOfDimensions() <= 1) {
152 accessor = boost::shared_ptr<NDRegisterAccessor<UserType>>(
153 new NumericAddressedBackendRegisterAccessor<UserType, FixedPointConverter<DEPRECATED_FIXEDPOINT_DEFAULT>,
154 true>(shared_from_this(), registerPathName, numberOfWords, wordOffsetInRegister, flags));
157 accessor = boost::shared_ptr<NDRegisterAccessor<UserType>>(
158 new NumericAddressedBackendRegisterAccessor<UserType, FixedPointConverter<DEPRECATED_FIXEDPOINT_DEFAULT>,
159 false>(shared_from_this(), registerPathName, numberOfWords, wordOffsetInRegister, flags));
164 accessor = boost::shared_ptr<NDRegisterAccessor<UserType>>(
165 new NumericAddressedBackendRegisterAccessor<UserType, IEEE754_SingleConverter, true>(
166 shared_from_this(), registerPathName, numberOfWords, wordOffsetInRegister, flags));
169 accessor = boost::shared_ptr<NDRegisterAccessor<UserType>>(
170 new NumericAddressedBackendRegisterAccessor<UserType, IEEE754_SingleConverter, false>(
171 shared_from_this(), registerPathName, numberOfWords, wordOffsetInRegister, flags));
175 if constexpr(!std::is_same<UserType, std::string>::value) {
176 throw ChimeraTK::logic_error(
"NumericAddressedBackend: ASCII data must be read with std::string UserType.");
179 accessor = boost::shared_ptr<NDRegisterAccessor<UserType>>(
new NumericAddressedBackendASCIIAccessor(
180 shared_from_this(), registerPathName, numberOfWords, wordOffsetInRegister, flags));
184 throw ChimeraTK::logic_error(
"NumericAddressedBackend: trying to get accessor for unsupported data type");
189 flags.checkForUnknownFlags({});
191 accessor = boost::shared_ptr<NDRegisterAccessor<UserType>>(
192 new NumericAddressedBackendMuxedRegisterAccessor<UserType, IEEE754_SingleConverter>(
193 registerPathName, numberOfWords, wordOffsetInRegister, shared_from_this()));
198 FixedPointConverter<DEPRECATED_FIXEDPOINT_DEFAULT>>(
199 registerPathName, numberOfWords, wordOffsetInRegister, shared_from_this()));
203 accessor->setExceptionBackend(shared_from_this());
210 _asyncIsActive =
true;
213 auto activateDomain = [
this](
size_t key, boost::shared_ptr<async::Domain>& domain) {
214 auto domainImpl = boost::dynamic_pointer_cast<async::DomainImpl<std::nullptr_t>>(domain);
220 subscriptionDone.wait();
221 domainImpl->activate(
nullptr);
232 std::promise<void> subscriptionDonePromise;
233 subscriptionDonePromise.set_value();
234 return subscriptionDonePromise.get_future();
240 _asyncIsActive =
false;
262 _asyncIsActive =
false;
#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.
bool has(AccessMode flag) const
Check if a certain flag is in the set.
async::DomainsContainer _asyncDomainsContainer
Container for async::Domains to support wait_for_new_data.
static std::pair< NumericAddressedRegisterCatalogue, MetadataCatalogue > parse(const std::string &fileName)
Performs parsing of specified MAP file, resulting in catalogue objects describing all registers and m...
MetadataCatalogue _metadataCatalogue
metadata catalogue
RegisterCatalogue getRegisterCatalogue() const override
Return the register catalogue with detailed information on all registers.
virtual bool barIndexValid(uint64_t bar)
Function to be implemented by the backends.
NumericAddressedRegisterCatalogue & _registerMap
NumericAddressedRegisterInfo getRegisterInfo(const RegisterPath ®isterPathName)
getRegisterInfo returns a NumericAddressedRegisterInfo object for the given register.
friend class NumericAddressedBackendMuxedRegisterAccessor
NumericAddressedBackend(const std::string &mapFileName="", std::unique_ptr< NumericAddressedRegisterCatalogue > registerMapPointer=std::make_unique< NumericAddressedRegisterCatalogue >(), const std::string &dataConsistencyKeyDescriptor="")
void setExceptionImpl() noexcept override
Turn off the internal variable which remembers that async is active.
void close() final
Deactivates all asynchronous accessors and calls closeImpl().
MetadataCatalogue getMetadataCatalogue() const override
Return the device metadata catalogue.
void activateAsyncRead() noexcept override
Activate asyncronous read for all transfer elements where AccessMode::wait_for_new_data is set.
virtual void closeImpl()
All backends derrived from NumericAddressedBackend must implement closeImpl() instead of close.
virtual void write(uint64_t bar, uint64_t address, int32_t const *data, size_t sizeInBytes)
Write function to be implemented by backends.
virtual std::future< void > activateSubscription(uint32_t interruptNumber, boost::shared_ptr< async::DomainImpl< std::nullptr_t > > asyncDomain)
Activate/create the subscription for a given interrupt (for instance by starting the according interr...
virtual void read(uint64_t bar, uint64_t address, int32_t *data, size_t sizeInBytes)
Read function to be implemented by backends.
void addDataConsistencyRealm(const RegisterPath ®isterPath, const std::string &realmName)
NumericAddressedRegisterInfo getBackendRegister(const RegisterPath ®isterPathName) const override
Note: Override this function if backend has "hidden" registers which are not added to the map and hen...
std::unique_ptr< BackendRegisterCatalogueBase > clone() const override
Create deep copy of the catalogue.
Catalogue of register information.
Class to store a register path name.
std::vector< std::string > getComponents() const
split path into components
bool startsWith(const RegisterPath &compare) const
check if the register path starts with the given path
boost::shared_ptr< AsyncNDRegisterAccessor< UserDataType > > subscribe(boost::shared_ptr< BackendType > backend, size_t domainId, bool activate, RegisterPath name, size_t numberOfWords, size_t wordOffsetInRegister, AccessModeFlags flags)
Get an accessor from a particular domain.
void forEach(const std::function< void(size_t, boost::shared_ptr< Domain > &)> &executeMe)
Iterate all Domains under the container lock.
Exception thrown when a logic error has occured.
RegisterPath BAR()
The numeric_address::BAR() function can be used to directly access registers by numeric addresses,...
@ wait_for_new_data
Make any read blocking until new data has arrived since the last read.
@ raw
Raw access: disable any possible conversion from the original hardware data type into the given UserT...