Began refactoring target descriptor structs.
This is incomplete - a partial commit of a substantial peice of work
This commit is contained in:
@@ -1,11 +1,14 @@
|
||||
target_sources(
|
||||
Bloom
|
||||
PRIVATE
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TargetDescription/TargetDescriptionFile.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TargetDescriptor.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TargetAddressSpaceDescriptor.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TargetPeripheralDescriptor.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TargetRegisterGroupDescriptor.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TargetRegisterDescriptor.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TargetMemoryCache.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TargetPhysicalInterface.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/TargetDescription/TargetDescriptionFile.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Microchip/AVR/AVR8/Avr8.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Microchip/AVR/AVR8/Avr8TargetConfig.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Microchip/AVR/AVR8/TargetDescription/TargetDescriptionFile.cpp
|
||||
|
||||
@@ -39,9 +39,11 @@ namespace Targets
|
||||
|
||||
struct BreakpointResources
|
||||
{
|
||||
std::optional<std::uint16_t> maximumHardwareBreakpoints;
|
||||
std::optional<std::uint16_t> maximumSoftwareBreakpoints;
|
||||
std::uint16_t reservedHardwareBreakpoints;
|
||||
std::optional<std::uint16_t> maximumHardwareBreakpoints = std::nullopt;
|
||||
std::optional<std::uint16_t> maximumSoftwareBreakpoints = std::nullopt;
|
||||
std::uint16_t reservedHardwareBreakpoints = 0;
|
||||
|
||||
BreakpointResources() = default;
|
||||
|
||||
BreakpointResources(
|
||||
std::optional<std::uint16_t> maximumHardwareBreakpoints,
|
||||
|
||||
50
src/Targets/TargetDescriptor.cpp
Normal file
50
src/Targets/TargetDescriptor.cpp
Normal file
@@ -0,0 +1,50 @@
|
||||
#include "TargetDescriptor.hpp"
|
||||
|
||||
#include "src/Exceptions/InternalFatalErrorException.hpp"
|
||||
|
||||
namespace Targets
|
||||
{
|
||||
TargetDescriptor::TargetDescriptor(
|
||||
const std::string& name,
|
||||
TargetFamily family,
|
||||
const std::string& marketId,
|
||||
const std::string& vendorName,
|
||||
const std::map<std::string, TargetAddressSpaceDescriptor>& addressSpaceDescriptorsByKey,
|
||||
const std::map<std::string, TargetPeripheralDescriptor>& peripheralDescriptorsByKey,
|
||||
const std::vector<TargetVariant>& variants,
|
||||
const BreakpointResources& breakpointResources
|
||||
)
|
||||
: name(name)
|
||||
, family(family)
|
||||
, marketId(marketId)
|
||||
, vendorName(vendorName)
|
||||
, addressSpaceDescriptorsByKey(addressSpaceDescriptorsByKey)
|
||||
, peripheralDescriptorsByKey(peripheralDescriptorsByKey)
|
||||
, variants(variants)
|
||||
, breakpointResources(breakpointResources)
|
||||
{}
|
||||
|
||||
std::optional<
|
||||
std::reference_wrapper<const TargetAddressSpaceDescriptor>
|
||||
> TargetDescriptor::tryGetAddressSpaceDescriptor(const std::string& key) const {
|
||||
const auto descriptorIt = this->addressSpaceDescriptorsByKey.find(key);
|
||||
|
||||
if (descriptorIt == this->addressSpaceDescriptorsByKey.end()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return std::cref(descriptorIt->second);
|
||||
}
|
||||
|
||||
const TargetAddressSpaceDescriptor& TargetDescriptor::getAddressSpaceDescriptor(const std::string& key) const {
|
||||
const auto descriptor = this->tryGetAddressSpaceDescriptor(key);
|
||||
if (!descriptor.has_value()) {
|
||||
throw Exceptions::InternalFatalErrorException(
|
||||
"Failed to get address space descriptor \"" + std::string(key)
|
||||
+ "\" from target descriptor - descriptor not found"
|
||||
);
|
||||
}
|
||||
|
||||
return descriptor->get();
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,8 @@
|
||||
|
||||
#include "TargetFamily.hpp"
|
||||
#include "TargetMemory.hpp"
|
||||
#include "TargetRegisterDescriptor.hpp"
|
||||
#include "TargetAddressSpaceDescriptor.hpp"
|
||||
#include "TargetPeripheralDescriptor.hpp"
|
||||
#include "TargetVariant.hpp"
|
||||
#include "TargetBreakpoint.hpp"
|
||||
|
||||
@@ -17,50 +18,31 @@ namespace Targets
|
||||
{
|
||||
struct TargetDescriptor
|
||||
{
|
||||
std::string id;
|
||||
TargetFamily family;
|
||||
std::string name;
|
||||
TargetFamily family;
|
||||
std::string marketId;
|
||||
std::string vendorName;
|
||||
std::map<TargetMemoryType, TargetMemoryDescriptor> memoryDescriptorsByType;
|
||||
std::map<TargetRegisterDescriptorId, TargetRegisterDescriptor> registerDescriptorsById;
|
||||
BreakpointResources breakpointResources;
|
||||
std::map<std::string, TargetAddressSpaceDescriptor> addressSpaceDescriptorsByKey;
|
||||
std::map<std::string, TargetPeripheralDescriptor> peripheralDescriptorsByKey;
|
||||
std::vector<TargetVariant> variants;
|
||||
|
||||
TargetMemoryType programMemoryType;
|
||||
BreakpointResources breakpointResources;
|
||||
|
||||
TargetDescriptor(
|
||||
const std::string& id,
|
||||
TargetFamily family,
|
||||
const std::string& name,
|
||||
TargetFamily family,
|
||||
const std::string& vendorName,
|
||||
const std::map<TargetMemoryType, TargetMemoryDescriptor>& memoryDescriptorsByType,
|
||||
const std::map<TargetRegisterDescriptorId, TargetRegisterDescriptor>& registerDescriptorsById,
|
||||
const BreakpointResources& breakpointResources,
|
||||
const std::string& marketName,
|
||||
const std::map<std::string, TargetAddressSpaceDescriptor>& addressSpaceDescriptorsByKey,
|
||||
const std::map<std::string, TargetPeripheralDescriptor>& peripheralDescriptorsByKey,
|
||||
const std::vector<TargetVariant>& variants,
|
||||
TargetMemoryType programMemoryType
|
||||
)
|
||||
: id(id)
|
||||
, family(family)
|
||||
, name(name)
|
||||
, vendorName(vendorName)
|
||||
, memoryDescriptorsByType(memoryDescriptorsByType)
|
||||
, registerDescriptorsById(registerDescriptorsById)
|
||||
, breakpointResources(breakpointResources)
|
||||
, variants(variants)
|
||||
, programMemoryType(programMemoryType)
|
||||
{}
|
||||
const BreakpointResources& breakpointResources
|
||||
);
|
||||
|
||||
TargetRegisterDescriptorIds registerDescriptorIdsForType(TargetRegisterType type) {
|
||||
auto output = TargetRegisterDescriptorIds();
|
||||
std::optional<std::reference_wrapper<const TargetAddressSpaceDescriptor>> tryGetAddressSpaceDescriptor(
|
||||
const std::string& key
|
||||
) const;
|
||||
|
||||
for (const auto& [descriptorId, descriptor] : this->registerDescriptorsById) {
|
||||
if (descriptor.type == type) {
|
||||
output.insert(descriptorId);
|
||||
}
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
const TargetAddressSpaceDescriptor& getAddressSpaceDescriptor(const std::string& key) const;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
47
src/Targets/TargetPeripheralDescriptor.cpp
Normal file
47
src/Targets/TargetPeripheralDescriptor.cpp
Normal file
@@ -0,0 +1,47 @@
|
||||
#include "TargetPeripheralDescriptor.hpp"
|
||||
|
||||
#include <ranges>
|
||||
|
||||
#include "src/Services/StringService.hpp"
|
||||
|
||||
#include "src/Exceptions/InternalFatalErrorException.hpp"
|
||||
|
||||
namespace Targets
|
||||
{
|
||||
TargetPeripheralDescriptor::TargetPeripheralDescriptor(
|
||||
const std::string& key,
|
||||
const std::string& name,
|
||||
const std::map<std::string, TargetRegisterGroupDescriptor, std::less<void>>& registerGroupDescriptorsByKey
|
||||
)
|
||||
: key(key)
|
||||
, name(name)
|
||||
, registerGroupDescriptorsByKey(registerGroupDescriptorsByKey)
|
||||
{}
|
||||
|
||||
std::optional<
|
||||
std::reference_wrapper<const TargetRegisterGroupDescriptor>
|
||||
> TargetPeripheralDescriptor::tryGetRegisterGroupDescriptor(std::string_view keyStr) const {
|
||||
const auto keys = Services::StringService::split(keyStr, '.');
|
||||
|
||||
const auto firstGroupIt = this->registerGroupDescriptorsByKey.find(*keys.begin());
|
||||
return firstGroupIt != this->registerGroupDescriptorsByKey.end()
|
||||
? keys.size() > 1
|
||||
? firstGroupIt->second.tryGetSubgroupDescriptor(keys | std::ranges::views::drop(1))
|
||||
: std::optional(std::cref(firstGroupIt->second))
|
||||
: std::nullopt;
|
||||
}
|
||||
|
||||
const TargetRegisterGroupDescriptor& TargetPeripheralDescriptor::getRegisterGroupDescriptor(
|
||||
std::string_view key
|
||||
) const {
|
||||
const auto descriptor = this->tryGetRegisterGroupDescriptor(key);
|
||||
if (!descriptor.has_value()) {
|
||||
throw Exceptions::InternalFatalErrorException(
|
||||
"Failed to get register group descriptor \"" + std::string(key)
|
||||
+ "\" from peripheral \"" + this->key + "\" - register group descriptor not found"
|
||||
);
|
||||
}
|
||||
|
||||
return descriptor->get();
|
||||
}
|
||||
}
|
||||
32
src/Targets/TargetPeripheralDescriptor.hpp
Normal file
32
src/Targets/TargetPeripheralDescriptor.hpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <functional>
|
||||
#include <string_view>
|
||||
|
||||
#include "TargetRegisterGroupDescriptor.hpp"
|
||||
|
||||
namespace Targets
|
||||
{
|
||||
struct TargetPeripheralDescriptor
|
||||
{
|
||||
public:
|
||||
std::string key;
|
||||
std::string name;
|
||||
std::map<std::string, TargetRegisterGroupDescriptor, std::less<void>> registerGroupDescriptorsByKey;
|
||||
|
||||
TargetPeripheralDescriptor(
|
||||
const std::string& key,
|
||||
const std::string& name,
|
||||
const std::map<std::string, TargetRegisterGroupDescriptor, std::less<void>>& registerGroupDescriptorsByKey
|
||||
);
|
||||
|
||||
std::optional<std::reference_wrapper<const TargetRegisterGroupDescriptor>> tryGetRegisterGroupDescriptor(
|
||||
std::string_view keyStr
|
||||
) const;
|
||||
|
||||
const TargetRegisterGroupDescriptor& getRegisterGroupDescriptor(std::string_view key) const;
|
||||
};
|
||||
}
|
||||
@@ -2,14 +2,5 @@
|
||||
|
||||
namespace Targets
|
||||
{
|
||||
std::size_t TargetRegisterDescriptor::getHash() const {
|
||||
if (!this->cachedHash.has_value()) {
|
||||
auto stringHasher = std::hash<std::string>();
|
||||
|
||||
this->cachedHash = stringHasher(std::to_string(this->startAddress.value_or(0))
|
||||
+ "_" + std::to_string(static_cast<std::uint8_t>(this->type)));
|
||||
}
|
||||
|
||||
return this->cachedHash.value();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,22 +9,13 @@
|
||||
#include <set>
|
||||
|
||||
#include "TargetMemory.hpp"
|
||||
#include "TargetAddressSpaceDescriptor.hpp"
|
||||
|
||||
namespace Targets
|
||||
{
|
||||
using TargetRegisterDescriptorId = std::uint32_t;
|
||||
using TargetRegisterDescriptorIds = std::set<Targets::TargetRegisterDescriptorId>;
|
||||
|
||||
enum class TargetRegisterType: std::uint8_t
|
||||
{
|
||||
GENERAL_PURPOSE_REGISTER,
|
||||
PROGRAM_COUNTER,
|
||||
STACK_POINTER,
|
||||
STATUS_REGISTER,
|
||||
PORT_REGISTER,
|
||||
OTHER,
|
||||
};
|
||||
|
||||
struct TargetRegisterAccess
|
||||
{
|
||||
bool readable = false;
|
||||
@@ -37,89 +28,75 @@ namespace Targets
|
||||
: readable(readable)
|
||||
, writable(writable)
|
||||
{}
|
||||
|
||||
bool operator == (const TargetRegisterAccess& other) const {
|
||||
return this->readable == other.readable
|
||||
&& this->writable == other.writable
|
||||
;
|
||||
}
|
||||
};
|
||||
|
||||
struct TargetRegisterDescriptor
|
||||
{
|
||||
public:
|
||||
TargetRegisterDescriptorId id;
|
||||
TargetRegisterType type;
|
||||
std::optional<TargetMemoryAddress> startAddress;
|
||||
const TargetRegisterDescriptorId id;
|
||||
std::string key;
|
||||
std::string name;
|
||||
std::string addressSpaceKey;
|
||||
const TargetAddressSpaceDescriptorId addressSpaceDescriptorId;
|
||||
TargetMemoryAddress startAddress;
|
||||
TargetMemorySize size;
|
||||
TargetMemoryType memoryType;
|
||||
|
||||
std::optional<std::string> name;
|
||||
std::optional<std::string> groupName;
|
||||
TargetRegisterAccess access;
|
||||
std::optional<std::string> description;
|
||||
|
||||
TargetRegisterAccess access;
|
||||
|
||||
TargetRegisterDescriptor(
|
||||
TargetRegisterType type,
|
||||
std::optional<TargetMemoryAddress> startAddress,
|
||||
const std::string& key,
|
||||
const std::string& name,
|
||||
const std::string& addressSpaceKey,
|
||||
TargetAddressSpaceDescriptorId addressSpaceDescriptorId,
|
||||
TargetMemoryAddress startAddress,
|
||||
TargetMemorySize size,
|
||||
TargetMemoryType memoryType,
|
||||
std::optional<std::string> name,
|
||||
std::optional<std::string> groupName,
|
||||
std::optional<std::string> description,
|
||||
TargetRegisterAccess access
|
||||
TargetRegisterAccess access,
|
||||
std::optional<std::string> description
|
||||
)
|
||||
: id(++(TargetRegisterDescriptor::lastRegisterDescriptorId))
|
||||
, type(type)
|
||||
, key(key)
|
||||
, name(name)
|
||||
, addressSpaceKey(addressSpaceKey)
|
||||
, addressSpaceDescriptorId(addressSpaceDescriptorId)
|
||||
, startAddress(startAddress)
|
||||
, size(size)
|
||||
, memoryType(memoryType)
|
||||
, name(name)
|
||||
, groupName(groupName)
|
||||
, description(description)
|
||||
, access(access)
|
||||
, description(description)
|
||||
{};
|
||||
|
||||
bool operator == (const TargetRegisterDescriptor& other) const {
|
||||
return this->getHash() == other.getHash();
|
||||
return this->key == other.key
|
||||
&& this->name == other.name
|
||||
&& this->addressSpaceDescriptorId == other.addressSpaceDescriptorId
|
||||
&& this->startAddress == other.startAddress
|
||||
&& this->size == other.size
|
||||
&& this->access == other.access
|
||||
&& this->description == other.description
|
||||
;
|
||||
}
|
||||
|
||||
bool operator < (const TargetRegisterDescriptor& other) const {
|
||||
if (this->type == other.type) {
|
||||
return this->startAddress.has_value() && other.startAddress.has_value()
|
||||
? this->startAddress < other.startAddress
|
||||
: this->name < other.name
|
||||
;
|
||||
if (this->addressSpaceDescriptorId != other.addressSpaceDescriptorId) {
|
||||
/*
|
||||
* If the registers are within different address spaces, there is no meaningful way to sort them, so
|
||||
* we just sort by name.
|
||||
*/
|
||||
return this->name < other.name;
|
||||
}
|
||||
|
||||
/*
|
||||
* If the registers are of different type, there is no meaningful way to sort them, so we just use
|
||||
* the unique hash.
|
||||
*/
|
||||
return this->getHash() < other.getHash();
|
||||
return this->startAddress < other.startAddress;
|
||||
}
|
||||
|
||||
private:
|
||||
mutable std::optional<std::size_t> cachedHash;
|
||||
static inline std::atomic<TargetRegisterDescriptorId> lastRegisterDescriptorId = 0;
|
||||
std::size_t getHash() const;
|
||||
|
||||
friend std::hash<Targets::TargetRegisterDescriptor>;
|
||||
};
|
||||
|
||||
using TargetRegisterDescriptors = std::set<TargetRegisterDescriptor>;
|
||||
using TargetRegisterDescriptorMapping = std::map<TargetRegisterDescriptorId, TargetRegisterDescriptor>;
|
||||
}
|
||||
|
||||
namespace std
|
||||
{
|
||||
/**
|
||||
* Hashing function for TargetRegisterDescriptor type.
|
||||
*
|
||||
* This is required in order to use TargetRegisterDescriptor as a key in an std::unordered_map (see the BiMap
|
||||
* class)
|
||||
*/
|
||||
template<>
|
||||
class hash<Targets::TargetRegisterDescriptor>
|
||||
{
|
||||
public:
|
||||
std::size_t operator()(const Targets::TargetRegisterDescriptor& descriptor) const {
|
||||
return descriptor.getHash();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
86
src/Targets/TargetRegisterGroupDescriptor.cpp
Normal file
86
src/Targets/TargetRegisterGroupDescriptor.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
#include "TargetRegisterGroupDescriptor.hpp"
|
||||
|
||||
#include <cassert>
|
||||
#include <numeric>
|
||||
|
||||
#include "src/Services/StringService.hpp"
|
||||
#include "src/Exceptions/InternalFatalErrorException.hpp"
|
||||
|
||||
namespace Targets
|
||||
{
|
||||
TargetRegisterGroupDescriptor::TargetRegisterGroupDescriptor(
|
||||
const std::string& key,
|
||||
const std::string& name,
|
||||
const std::string& addressSpaceKey,
|
||||
TargetAddressSpaceDescriptorId addressSpaceDescriptorId,
|
||||
const std::optional<std::string>& description,
|
||||
const std::map<std::string, TargetRegisterDescriptor>& registerDescriptorsByKey,
|
||||
const std::map<std::string, TargetRegisterGroupDescriptor, std::less<void>>& subgroupDescriptorsByKey
|
||||
)
|
||||
: key(key)
|
||||
, name(name)
|
||||
, addressSpaceKey(addressSpaceKey)
|
||||
, addressSpaceDescriptorId(addressSpaceDescriptorId)
|
||||
, description(description)
|
||||
, registerDescriptorsByKey(registerDescriptorsByKey)
|
||||
, subgroupDescriptorsByKey(subgroupDescriptorsByKey)
|
||||
{}
|
||||
|
||||
TargetMemoryAddress TargetRegisterGroupDescriptor::startAddress() const {
|
||||
assert(!this->registerDescriptorsByKey.empty() || !this->subgroupDescriptorsByKey.empty());
|
||||
|
||||
auto startAddress = TargetMemoryAddress{0};
|
||||
|
||||
for (const auto& [key, registerDescriptor] : this->registerDescriptorsByKey) {
|
||||
if (registerDescriptor.startAddress < startAddress) {
|
||||
startAddress = registerDescriptor.startAddress;
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& [key, groupDescriptor] : this->subgroupDescriptorsByKey) {
|
||||
const auto groupStartAddress = groupDescriptor.startAddress();
|
||||
if (groupStartAddress < startAddress) {
|
||||
startAddress = groupStartAddress;
|
||||
}
|
||||
}
|
||||
|
||||
return startAddress;
|
||||
}
|
||||
|
||||
TargetMemorySize TargetRegisterGroupDescriptor::size() const {
|
||||
return std::accumulate(
|
||||
this->registerDescriptorsByKey.begin(),
|
||||
this->registerDescriptorsByKey.end(),
|
||||
TargetMemorySize{0},
|
||||
[] (TargetMemorySize size, const decltype(this->registerDescriptorsByKey)::value_type& pair) {
|
||||
return size + pair.second.size;
|
||||
}
|
||||
) + std::accumulate(
|
||||
this->subgroupDescriptorsByKey.begin(),
|
||||
this->subgroupDescriptorsByKey.end(),
|
||||
TargetMemorySize{0},
|
||||
[] (TargetMemorySize size, const decltype(this->subgroupDescriptorsByKey)::value_type& pair) {
|
||||
return size + pair.second.size();
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
std::optional<
|
||||
std::reference_wrapper<const TargetRegisterGroupDescriptor>
|
||||
> TargetRegisterGroupDescriptor::tryGetSubgroupDescriptor(std::string_view keyStr) const {
|
||||
return this->tryGetSubgroupDescriptor(Services::StringService::split(keyStr, '.'));
|
||||
}
|
||||
|
||||
const TargetRegisterGroupDescriptor& TargetRegisterGroupDescriptor::getSubgroupDescriptor(
|
||||
std::string_view keyStr
|
||||
) const {
|
||||
const auto subgroup = this->tryGetSubgroupDescriptor(keyStr);
|
||||
if (!subgroup.has_value()) {
|
||||
throw Exceptions::InternalFatalErrorException(
|
||||
"Failed to get subgroup \"" + std::string(keyStr) + "\" from register group - subgroup not found"
|
||||
);
|
||||
}
|
||||
|
||||
return subgroup->get();
|
||||
}
|
||||
}
|
||||
112
src/Targets/TargetRegisterGroupDescriptor.hpp
Normal file
112
src/Targets/TargetRegisterGroupDescriptor.hpp
Normal file
@@ -0,0 +1,112 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <string_view>
|
||||
#include <ranges>
|
||||
#include <concepts>
|
||||
|
||||
#include "TargetMemory.hpp"
|
||||
#include "TargetAddressSpaceDescriptor.hpp"
|
||||
#include "TargetRegisterDescriptor.hpp"
|
||||
|
||||
namespace Targets
|
||||
{
|
||||
struct TargetRegisterGroupDescriptor
|
||||
{
|
||||
public:
|
||||
std::string key;
|
||||
std::string name;
|
||||
std::string addressSpaceKey;
|
||||
const TargetAddressSpaceDescriptorId addressSpaceDescriptorId;
|
||||
std::optional<std::string> description;
|
||||
std::map<std::string, TargetRegisterDescriptor> registerDescriptorsByKey;
|
||||
std::map<std::string, TargetRegisterGroupDescriptor, std::less<void>> subgroupDescriptorsByKey;
|
||||
|
||||
TargetRegisterGroupDescriptor(
|
||||
const std::string& key,
|
||||
const std::string& name,
|
||||
const std::string& addressSpaceKey,
|
||||
TargetAddressSpaceDescriptorId addressSpaceDescriptorId,
|
||||
const std::optional<std::string>& description,
|
||||
const std::map<std::string, TargetRegisterDescriptor>& registerDescriptorsByKey,
|
||||
const std::map<std::string, TargetRegisterGroupDescriptor, std::less<void>>& subgroupDescriptorsByKey
|
||||
);
|
||||
|
||||
/**
|
||||
* Calculates the start address of the register group.
|
||||
*
|
||||
* Excessive calls to this function is discouraged, as the implementation is quite slow.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
TargetMemoryAddress startAddress() const;
|
||||
|
||||
/**
|
||||
* Calculates the size of this register group.
|
||||
*
|
||||
* Excessive calls to this function is discouraged, as the implementation is quite slow.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
TargetMemorySize size() const;
|
||||
|
||||
/**
|
||||
* Attempts to fetch a subgroup with a set of keys.
|
||||
*
|
||||
* @tparam KeysType
|
||||
* @param keys
|
||||
* @return
|
||||
*/
|
||||
template <typename KeysType>
|
||||
requires
|
||||
std::ranges::sized_range<KeysType>
|
||||
std::optional<std::reference_wrapper<const TargetRegisterGroupDescriptor>> tryGetSubgroupDescriptor(
|
||||
KeysType keys
|
||||
) const {
|
||||
auto firstSubgroupIt = this->subgroupDescriptorsByKey.find(*(keys.begin()));
|
||||
if (firstSubgroupIt == this->subgroupDescriptorsByKey.end()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto subgroup = std::optional(std::cref(firstSubgroupIt->second));
|
||||
for (const auto key : keys | std::ranges::views::drop(1)) {
|
||||
subgroup = subgroup->get().tryGetSubgroupDescriptor(key);
|
||||
|
||||
if (!subgroup.has_value()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return subgroup;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to fetch a subgroup with a set of keys in the form of a string in "dot notation".
|
||||
*
|
||||
* @param keyStr
|
||||
* A string in "dot notation", containing each key seperated with a period/dot character (e.g.
|
||||
* "parent.child.grandchild").
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
std::optional<std::reference_wrapper<const TargetRegisterGroupDescriptor>> tryGetSubgroupDescriptor(
|
||||
std::string_view keyStr
|
||||
) const;
|
||||
|
||||
/**
|
||||
* Fetches a subgroup with a set of keys in the form of a string in "dot notation". If the subgroup is not
|
||||
* found, an InternalFatalErrorException is thrown.
|
||||
*
|
||||
* @param keyStr
|
||||
* A string in "dot notation", containing each key seperated with a period/dot character (e.g.
|
||||
* "parent.child.grandchild").
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
const TargetRegisterGroupDescriptor& getSubgroupDescriptor(std::string_view keyStr) const;
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user