22 uint64_t address_, uint32_t nBytes_, uint64_t bar_, uint32_t width_, int32_t nFractionalBits_,
bool signedFlag_,
23 Access dataAccess_,
Type dataType_, std::vector<size_t> interruptId_,
24 std::optional<DoubleBufferInfo> doubleBufferInfo_,
bool isBitRange_)
25 : pathName(pathName_), nElements(nElements_), elementPitchBits(nElements_ > 0 ? nBytes_ / nElements_ * 8 : 0),
26 bar(bar_), address(address_), registerAccess(dataAccess_), interruptId(
std::move(interruptId_)),
27 doubleBuffer(
std::move(doubleBufferInfo_)), isBitRange(isBitRange_),
28 channels({{0, dataType_, width_, nFractionalBits_, signedFlag_,
32 assert(channels.size() == 1);
35 pathName.setAltSeparator(
".");
38 if(nBytes_ > 0 && nElements_ > 0) {
39 if(nBytes_ % nElements_ != 0) {
41 throw logic_error(
"Number of bytes is not a multiple of number of elements for register " + pathName +
42 ". Check your map file!");
46 computeDataDescriptor();
52 uint64_t address_, uint32_t nElements_, uint32_t elementPitchBits_, std::vector<ChannelInfo> channelInfo_,
53 Access dataAccess_, std::vector<size_t> interruptId_, std::optional<DoubleBufferInfo> doubleBufferInfo_)
54 : pathName(pathName_), nElements(nElements_), elementPitchBits(elementPitchBits_), bar(bar_), address(address_),
55 registerAccess(dataAccess_), interruptId(
std::move(interruptId_)), doubleBuffer(
std::move(doubleBufferInfo_)),
56 isBitRange(false), channels(
std::move(channelInfo_)) {
71 int32_t nFractionalBits = 0;
72 bool signedFlag =
false;
74 if(
int(c.dataType) > int(dataType)) dataType = c.dataType;
75 if(c.width + c.nFractionalBits + c.signedFlag > width + nFractionalBits + signedFlag) {
77 nFractionalBits = c.nFractionalBits;
78 signedFlag = c.signedFlag;
90 rawDataInfo =
channels.front().getRawType();
108 else if(width == 64) {
118 throw logic_error(
"Wrong data width for data type IEEE754 for register " +
pathName +
". Check your map file!");
124 if(nFractionalBits > 0) {
125 auto nDigits =
static_cast<size_t>(
126 std::ceil(std::log10(std::pow(2, width))) + (signedFlag ? 1 : 0) + (nFractionalBits != 0 ? 1 : 0));
127 size_t nFractionalDigits = std::ceil(std::log10(std::pow(2, nFractionalBits)));
132 nDigits, nFractionalDigits, rawDataInfo);
136 static_cast<size_t>(std::ceil(std::log10(std::pow(2, width + nFractionalBits))) + (signedFlag ? 1 : 0));
141 nDigits, 0, rawDataInfo);
144 else if(width == 1) {
207 auto path = registerPathName;
212 auto components = path.getComponents();
213 if(components.size() != 3) {
216 auto bar = std::stoi(components[1]);
220 bool signedFlag =
true;
221 size_t bitWidth = 32;
222 size_t pos = components[2].find_first_of(
"uU");
223 if(pos != std::string::npos) {
225 bitWidth = std::stoi(components[2].substr(pos + 1));
228 pos = components[2].find_first_of(
"sS");
229 if(pos != std::string::npos) {
231 bitWidth = std::stoi(components[2].substr(pos + 1));
234 if(bitWidth != 8 && bitWidth != 16 && bitWidth != 32 && bitWidth != 64) {
237 auto bytesPerElement = bitWidth / 8;
240 pos = components[2].find_first_of(
'*');
241 auto address = std::stoi(components[2].substr(0, pos));
243 if(pos != std::string::npos) {
244 nBytes = std::stoi(components[2].substr(pos + 1));
247 nBytes = bytesPerElement;
252 auto pitchPos = components[2].find_last_of(
"pP");
254 if(pitchPos != std::string::npos) {
255 auto pitchBits = std::stoi(components[2].substr(pitchPos + 1));
256 if(pitchBits == 0 || pitchBits % 8 != 0 || nBytes * 8 % pitchBits != 0 || nBytes * 8 / pitchBits == 0) {
263 if(nBytes == 0 || nBytes % bytesPerElement != 0) {
270 if(path.startsWith(
"!")) {
271 auto canonicalInterrupt = _canonicalInterrupts.find(path);
272 if(canonicalInterrupt == _canonicalInterrupts.end()) {
277 canonicalInterrupt->second);
289 if(_canonicalInterrupts.find(registerPathName) != _canonicalInterrupts.end()) {
298 return _listOfInterrupts;
305 _listOfInterrupts.insert(registerInfo.
interruptId);
307 std::vector<size_t> canonicalID = {registerInfo.
interruptId.front()};
308 _canonicalInterrupts[canonicalName] = canonicalID;
311 canonicalID.push_back(*subId);
312 _canonicalInterrupts[canonicalName] = canonicalID;
321 std::unique_ptr<BackendRegisterCatalogueBase> c = std::make_unique<NumericAddressedRegisterCatalogue>();
323 fillFromThis(casted_c);
339 const RegisterPath& registerPath,
const std::string& realmName) {
340 _dataConsistencyRealms[registerPath] = realmName;
346 const std::vector<size_t>& qualifiedAsyncDomainId)
const {
347 if(qualifiedAsyncDomainId.empty()) {
352 for(
auto const& [registerPath, realmName] : _dataConsistencyRealms) {
353 if(getBackendRegister(registerPath).getQualifiedAsyncId() == qualifiedAsyncDomainId) {
355 return store.getRealm(realmName);
364 const std::vector<size_t>& qualifiedAsyncDomainId)
const {
365 if(qualifiedAsyncDomainId.empty()) {
370 for(
auto const& [registerPath, realmName] : _dataConsistencyRealms) {
371 if(getBackendRegister(registerPath).getQualifiedAsyncId() == qualifiedAsyncDomainId) {
void addRegister(const BackendRegisterInfo ®isterInfo)
Add register information to the catalogue.
void fillFromThis(BackendRegisterCatalogue< BackendRegisterInfo > *target) const
Helper function for clone functions.
virtual BackendRegisterInfo getBackendRegister(const RegisterPath ®isterPathName) const
Note: Override this function if backend has "hidden" registers which are not added to the map and hen...
bool hasRegister(const RegisterPath ®isterPathName) const override
Check if register with the given path name exists.
unsigned int getNumberOfDimensions() const
Return number of dimensions of this register.
Class describing the actual payload data format of a register in an abstract manner.
A class to describe which of the supported data types is used.
@ none
The data type/concept does not exist, e.g. there is no raw transfer (do not confuse with Void)
void addDataConsistencyRealm(const RegisterPath ®isterPath, const std::string &realmName)
const std::set< std::vector< size_t > > & getListOfInterrupts() const
bool hasRegister(const RegisterPath ®isterPathName) const override
Check if register with the given path name exists.
void addRegister(const NumericAddressedRegisterInfo ®isterInfo)
void fillFromThis(NumericAddressedRegisterCatalogue *target) const
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::set< std::vector< size_t > > _listOfInterrupts
set of interrupt IDs.
std::map< RegisterPath, std::vector< size_t > > _canonicalInterrupts
A canonical interrupt path consists of an exclamation mark, followed by a numeric interrupt and a col...
std::unique_ptr< BackendRegisterCatalogueBase > clone() const override
Create deep copy of the catalogue.
std::shared_ptr< async::DataConsistencyRealm > getDataConsistencyRealm(const std::vector< size_t > &qualifiedAsyncDomainId) const override
Return DataConsistencyRealm for the given qualified AsyncDomainId.
RegisterPath getDataConsistencyKeyRegisterPath(const std::vector< size_t > &qualifiedAsyncDomainId) const override
Return RegisterPath for the register containing the DataConsistencyKey value for the given qualified ...
std::map< RegisterPath, std::string > _dataConsistencyRealms
Map of data consistency key register paths to realm names.
uint32_t nElements
Number of elements in register.
std::vector< ChannelInfo > channels
Define per-channel information (bit interpretation etc.), 1D/scalars have exactly one entry.
Access
Enum describing the access mode of the register:
uint64_t bar
Upper part of the address (name originally from PCIe, meaning now generalised)
uint32_t elementPitchBits
Distance in bits (!) between two elements (of the same channel)
bool operator==(const ChimeraTK::NumericAddressedRegisterInfo &rhs) const
bool operator!=(const ChimeraTK::NumericAddressedRegisterInfo &rhs) const
std::vector< size_t > getQualifiedAsyncId() const override
Return the fully qualified async::SubDomain ID.
DataDescriptor dataDescriptor
NumericAddressedRegisterInfo(RegisterPath const &pathName_={}, uint32_t nElements_=0, uint64_t address_=0, uint32_t nBytes_=0, uint64_t bar_=0, uint32_t width_=32, int32_t nFractionalBits_=0, bool signedFlag_=true, Access dataAccess_=Access::READ_WRITE, Type dataType_=Type::FIXED_POINT, std::vector< size_t > interruptId_={}, std::optional< DoubleBufferInfo > doubleBuffer_=std::nullopt, bool isBitRange_=false)
Constructor to set all data members for scalar/1D registers.
uint64_t address
Lower part of the address relative to BAR, in bytes.
Access registerAccess
Data access direction: Read, write, read and write or interrupt.
Type
Enum descibing the data interpretation:
std::vector< size_t > interruptId
void computeDataDescriptor()
Class to store a register path name.
bool startsWith(const RegisterPath &compare) const
check if the register path starts with the given path
void setAltSeparator(const std::string &altSeparator)
set alternative separator.
static DataConsistencyRealmStore & getInstance()
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,...
This header collects some conversion routines which should be useful both for ApplicationCore Python ...
std::string to_string(const std::string &v)
DataType getRawType() const
bool operator==(const ChannelInfo &rhs) const
int32_t nFractionalBits
Number of fractional bits.
bool signedFlag
Signed/Unsigned flag.
bool operator!=(const ChannelInfo &rhs) const
uint32_t bitOffset
Offset in bits w.r.t.
uint32_t width
Number of significant bits in the register.
Type dataType
Data type (fixpoint, floating point)
std::optional< SelectedBy > selectedBy