Refactored descriptor ID generation and added IDs to peripherals, register groups and registers

This commit is contained in:
Nav
2024-07-25 19:03:26 +01:00
parent 8f7c3bc1be
commit 3f88e2022c
14 changed files with 191 additions and 52 deletions

View File

@@ -6,6 +6,8 @@
#include <iomanip>
#include <ranges>
#include <functional>
#include <unordered_map>
#include <mutex>
namespace Services
{
@@ -100,9 +102,16 @@ namespace Services
return static_cast<std::uint8_t>(StringService::toUint64(str, base));
}
std::size_t StringService::hash(const std::string& str) {
static const auto hash = std::hash<std::string>{};
return hash(str);
std::size_t StringService::generateUniqueInteger(const std::string& str) {
static auto mutex = std::mutex{};
static auto lastValue = std::size_t{0};
static auto map = std::unordered_map<std::string, std::size_t>{};
const auto lock = std::unique_lock{mutex};
const auto valueIt = map.find(str);
return valueIt != map.end() ? valueIt->second : map.emplace(str, ++lastValue).first->second;
}
std::vector<std::string_view> StringService::split(std::string_view str, char delimiter) {

View File

@@ -29,7 +29,29 @@ namespace Services
static std::uint16_t toUint16(const std::string& str, int base = 0);
static std::uint8_t toUint8(const std::string& str, int base = 0);
static std::size_t hash(const std::string& str);
/**
* Generates a unique integer from a given string.
*
* This function will return the same value for matching strings.
* That is: If strA == strB, then generateUniqueInteger(strA) == generateUniqueInteger(strB).
*
* This function does *not* return a hash of the string. We can't use hashes because they're not unique due to
* collisions.
*
* The returned value will only be unique for the duration of the current execution cycle.
* That means generateUniqueInteger(strA) != generateUniqueInteger(strA) if the functions are called within
* different execution cycles.
*
* The generated value isn't actually derived from the string itself. It's just an integer that we produce and
* keep record of, in a key-value store. See the implementation for more.
*
* The purpose of this function is to generate internal integer IDs for entities within Bloom, such as address
* spaces and memory segments. These IDs have no meaning to the user or any other external entity.
*
* @param str
* @return
*/
static std::size_t generateUniqueInteger(const std::string& str);
static std::vector<std::string_view> split(std::string_view str, char delimiter);
};

View File

@@ -290,8 +290,10 @@ namespace Targets::Microchip::Avr8
auto& gpRegisterGroup = gpPeripheral.registerGroupDescriptorsByKey.emplace(
"gpr",
TargetRegisterGroupDescriptor{
"gpr",
"gpr",
"CPU General Purpose",
gpPeripheral.key,
registerFileAddressSpace.key,
std::nullopt,
{},
@@ -306,6 +308,8 @@ namespace Targets::Microchip::Avr8
TargetRegisterDescriptor{
key,
"R" + std::to_string(i),
gpRegisterGroup.absoluteKey,
gpPeripheral.key,
registerFileAddressSpace.key,
registerFileMemorySegment.startAddress + i,
1,

View File

@@ -462,8 +462,10 @@ namespace Targets::RiscV
auto& gprGroup = cpuPeripheralDescriptor.registerGroupDescriptorsByKey.emplace(
"gpr",
TargetRegisterGroupDescriptor{
"gpr",
"gpr",
"General Purpose Registers",
cpuPeripheralDescriptor.key,
addressSpaceDescriptor.key,
std::nullopt,
{},
@@ -478,6 +480,8 @@ namespace Targets::RiscV
TargetRegisterDescriptor{
key,
"X" + std::to_string(i),
gprGroup.absoluteKey,
cpuPeripheralDescriptor.key,
addressSpaceDescriptor.key,
gprMemorySegmentDescriptor.addressRange.startAddress + i,
4,
@@ -492,8 +496,10 @@ namespace Targets::RiscV
auto& csrGroup = cpuPeripheralDescriptor.registerGroupDescriptorsByKey.emplace(
"csr",
TargetRegisterGroupDescriptor{
"csr",
"csr",
"Control Status Registers",
cpuPeripheralDescriptor.key,
addressSpaceDescriptor.key,
std::nullopt,
{},
@@ -506,6 +512,8 @@ namespace Targets::RiscV
TargetRegisterDescriptor{
"marchid",
"MARCHID",
csrGroup.absoluteKey,
cpuPeripheralDescriptor.key,
addressSpaceDescriptor.key,
csrMemorySegmentDescriptor.addressRange.startAddress + 0xF12,
4,
@@ -521,6 +529,8 @@ namespace Targets::RiscV
TargetRegisterDescriptor{
"mimpid",
"MIMPID",
csrGroup.absoluteKey,
cpuPeripheralDescriptor.key,
addressSpaceDescriptor.key,
csrMemorySegmentDescriptor.addressRange.startAddress + 0xF13,
4,
@@ -536,6 +546,8 @@ namespace Targets::RiscV
TargetRegisterDescriptor{
"mstatus",
"MSTATUS",
csrGroup.absoluteKey,
cpuPeripheralDescriptor.key,
addressSpaceDescriptor.key,
csrMemorySegmentDescriptor.addressRange.startAddress + 0x300,
4,
@@ -551,6 +563,8 @@ namespace Targets::RiscV
TargetRegisterDescriptor{
"misa",
"MISA",
csrGroup.absoluteKey,
cpuPeripheralDescriptor.key,
addressSpaceDescriptor.key,
csrMemorySegmentDescriptor.addressRange.startAddress + 0x301,
4,
@@ -566,6 +580,8 @@ namespace Targets::RiscV
TargetRegisterDescriptor{
"mtvec",
"MTVEC",
csrGroup.absoluteKey,
cpuPeripheralDescriptor.key,
addressSpaceDescriptor.key,
csrMemorySegmentDescriptor.addressRange.startAddress + 0x305,
4,
@@ -581,6 +597,8 @@ namespace Targets::RiscV
TargetRegisterDescriptor{
"mcounteren",
"MCOUNTEREN",
csrGroup.absoluteKey,
cpuPeripheralDescriptor.key,
addressSpaceDescriptor.key,
csrMemorySegmentDescriptor.addressRange.startAddress + 0x306,
4,
@@ -596,6 +614,8 @@ namespace Targets::RiscV
TargetRegisterDescriptor{
"mscratch",
"MSCRATCH",
csrGroup.absoluteKey,
cpuPeripheralDescriptor.key,
addressSpaceDescriptor.key,
csrMemorySegmentDescriptor.addressRange.startAddress + 0x340,
4,
@@ -611,6 +631,8 @@ namespace Targets::RiscV
TargetRegisterDescriptor{
"mepc",
"MEPC",
csrGroup.absoluteKey,
cpuPeripheralDescriptor.key,
addressSpaceDescriptor.key,
csrMemorySegmentDescriptor.addressRange.startAddress + 0x341,
4,
@@ -626,6 +648,8 @@ namespace Targets::RiscV
TargetRegisterDescriptor{
"mcause",
"MCAUSE",
csrGroup.absoluteKey,
cpuPeripheralDescriptor.key,
addressSpaceDescriptor.key,
csrMemorySegmentDescriptor.addressRange.startAddress + 0x342,
4,
@@ -641,6 +665,8 @@ namespace Targets::RiscV
TargetRegisterDescriptor{
"mtval",
"MTVAL",
csrGroup.absoluteKey,
cpuPeripheralDescriptor.key,
addressSpaceDescriptor.key,
csrMemorySegmentDescriptor.addressRange.startAddress + 0x343,
4,
@@ -656,6 +682,8 @@ namespace Targets::RiscV
TargetRegisterDescriptor{
"mip",
"MIP",
csrGroup.absoluteKey,
cpuPeripheralDescriptor.key,
addressSpaceDescriptor.key,
csrMemorySegmentDescriptor.addressRange.startAddress + 0x344,
4,
@@ -671,6 +699,8 @@ namespace Targets::RiscV
TargetRegisterDescriptor{
"dcsr",
"DCSR",
csrGroup.absoluteKey,
cpuPeripheralDescriptor.key,
addressSpaceDescriptor.key,
csrMemorySegmentDescriptor.addressRange.startAddress + 0x7B0,
4,
@@ -686,6 +716,8 @@ namespace Targets::RiscV
TargetRegisterDescriptor{
"dpc",
"DPC",
csrGroup.absoluteKey,
cpuPeripheralDescriptor.key,
addressSpaceDescriptor.key,
csrMemorySegmentDescriptor.addressRange.startAddress + 0x7B1,
4,
@@ -701,6 +733,8 @@ namespace Targets::RiscV
TargetRegisterDescriptor{
"dscratch0",
"DSCRATCH0",
csrGroup.absoluteKey,
cpuPeripheralDescriptor.key,
addressSpaceDescriptor.key,
csrMemorySegmentDescriptor.addressRange.startAddress + 0x7B2,
4,
@@ -716,6 +750,8 @@ namespace Targets::RiscV
TargetRegisterDescriptor{
"dscratch1",
"DSCRATCH1",
csrGroup.absoluteKey,
cpuPeripheralDescriptor.key,
addressSpaceDescriptor.key,
csrMemorySegmentDescriptor.addressRange.startAddress + 0x7B3,
4,

View File

@@ -102,6 +102,6 @@ namespace Targets
}
TargetAddressSpaceId TargetAddressSpaceDescriptor::generateId(const std::string& addressSpaceKey) {
return static_cast<TargetAddressSpaceId>(Services::StringService::hash(addressSpaceKey));
return static_cast<TargetAddressSpaceId>(Services::StringService::generateUniqueInteger(addressSpaceKey));
}
}

View File

@@ -925,13 +925,15 @@ namespace Targets::TargetDescription
output.registerGroupDescriptorsByKey.emplace(
key,
TargetDescriptionFile::targetRegisterGroupDescriptorFromRegisterGroup(
registerGroupInstance.key,
registerGroupInstance.name,
registerGroupInstance.addressSpaceKey,
registerGroupInstance.description,
peripheralModule.getRegisterGroup(registerGroupInstance.registerGroupKey),
peripheralModule,
registerGroupInstance.offset
peripheral.key,
registerGroupInstance.addressSpaceKey,
registerGroupInstance.offset,
std::nullopt,
registerGroupInstance.description,
registerGroupInstance.key,
registerGroupInstance.name
)
);
}
@@ -955,17 +957,27 @@ namespace Targets::TargetDescription
}
TargetRegisterGroupDescriptor TargetDescriptionFile::targetRegisterGroupDescriptorFromRegisterGroup(
const std::string& key,
const std::string& name,
const std::string& addressSpaceKey,
const std::optional<std::string>& description,
const RegisterGroup& registerGroup,
const Module& peripheralModule,
TargetMemoryAddress baseAddress
const std::string& peripheralKey,
const std::string& addressSpaceKey,
TargetMemoryAddress baseAddress,
const std::optional<std::string>& parentGroupAbsoluteKey,
const std::optional<std::string>& description,
const std::optional<std::string>& keyOverride,
const std::optional<std::string>& nameOverride
) {
const auto& key = keyOverride.has_value() ? *keyOverride : registerGroup.key;
const auto& name = nameOverride.has_value() ? *nameOverride : registerGroup.name;
const auto absoluteKey = parentGroupAbsoluteKey.has_value()
? *parentGroupAbsoluteKey + "." + key
: key;
auto output = TargetRegisterGroupDescriptor{
key,
absoluteKey,
name,
peripheralKey,
addressSpaceKey,
description,
{},
@@ -976,29 +988,30 @@ namespace Targets::TargetDescription
output.subgroupDescriptorsByKey.emplace(
key,
TargetDescriptionFile::targetRegisterGroupDescriptorFromRegisterGroup(
subgroup.key,
subgroup.name,
addressSpaceKey,
std::nullopt,
registerGroup,
subgroup,
peripheralModule,
baseAddress + registerGroup.offset.value_or(0)
peripheralKey,
addressSpaceKey,
baseAddress + registerGroup.offset.value_or(0),
absoluteKey
)
);
}
for (const auto& [key, subgroupReference] : registerGroup.subgroupReferencesByKey) {
const auto& registerGroup = peripheralModule.getRegisterGroup(subgroupReference.registerGroupKey);
const auto& referencedGroup = peripheralModule.getRegisterGroup(subgroupReference.registerGroupKey);
output.subgroupDescriptorsByKey.emplace(
key,
TargetDescriptionFile::targetRegisterGroupDescriptorFromRegisterGroup(
subgroupReference.key,
subgroupReference.name,
addressSpaceKey,
subgroupReference.description,
registerGroup,
referencedGroup,
peripheralModule,
baseAddress + subgroupReference.offset + registerGroup.offset.value_or(0)
peripheralKey,
addressSpaceKey,
baseAddress + registerGroup.offset.value_or(0) + subgroupReference.offset,
absoluteKey,
subgroupReference.description,
subgroupReference.key,
subgroupReference.name
)
);
}
@@ -1008,6 +1021,8 @@ namespace Targets::TargetDescription
key,
TargetDescriptionFile::targetRegisterDescriptorFromRegister(
reg,
absoluteKey,
peripheralKey,
addressSpaceKey,
baseAddress + registerGroup.offset.value_or(0)
)
@@ -1019,12 +1034,16 @@ namespace Targets::TargetDescription
TargetRegisterDescriptor TargetDescriptionFile::targetRegisterDescriptorFromRegister(
const Register& reg,
const std::string& absoluteGroupKey,
const std::string& peripheralKey,
const std::string& addressSpaceKey,
TargetMemoryAddress baseAddress
) {
auto output = TargetRegisterDescriptor{
reg.key,
reg.name,
absoluteGroupKey,
peripheralKey,
addressSpaceKey,
baseAddress + reg.offset,
reg.size,

View File

@@ -215,17 +215,21 @@ namespace Targets::TargetDescription
static TargetPeripheralSignalDescriptor targetPeripheralSignalDescriptorFromSignal(const Signal& signal);
static TargetRegisterGroupDescriptor targetRegisterGroupDescriptorFromRegisterGroup(
const std::string& key,
const std::string& name,
const std::string& addressSpaceKey,
const std::optional<std::string>& description,
const RegisterGroup& registerGroup,
const Module& peripheralModule,
TargetMemoryAddress baseAddress
const std::string& peripheralKey,
const std::string& addressSpaceKey,
TargetMemoryAddress baseAddress,
const std::optional<std::string>& parentGroupAbsoluteKey,
const std::optional<std::string>& description = std::nullopt,
const std::optional<std::string>& keyOverride = std::nullopt,
const std::optional<std::string>& nameOverride = std::nullopt
);
static TargetRegisterDescriptor targetRegisterDescriptorFromRegister(
const Register& reg,
const std::string& absoluteGroupKey,
const std::string& peripheralKey,
const std::string& addressSpaceKey,
TargetMemoryAddress baseAddress
);

View File

@@ -16,7 +16,7 @@ namespace Targets
const TargetMemoryAccess& programmingModeAccess,
std::optional<TargetMemorySize> pageSize
)
: id(static_cast<TargetMemorySegmentId>(Services::StringService::hash(addressSpaceKey + key)))
: id(static_cast<TargetMemorySegmentId>(Services::StringService::generateUniqueInteger(addressSpaceKey + key)))
, key(key)
, name(name)
, type(type)

View File

@@ -15,12 +15,21 @@ namespace Targets
std::map<std::string, TargetRegisterGroupDescriptor, std::less<void>>&& registerGroupDescriptorsByKey,
std::vector<TargetPeripheralSignalDescriptor>&& signalDescriptors
)
: key(key)
: id(static_cast<TargetPeripheralId>(Services::StringService::generateUniqueInteger(key)))
, key(key)
, name(name)
, registerGroupDescriptorsByKey(std::move(registerGroupDescriptorsByKey))
, signalDescriptors(std::move(signalDescriptors))
{}
bool TargetPeripheralDescriptor::operator == (const TargetPeripheralDescriptor& other) const {
return this->id == other.id;
}
bool TargetPeripheralDescriptor::operator != (const TargetPeripheralDescriptor& other) const {
return !(*this == other);
}
std::optional<
std::reference_wrapper<const TargetRegisterGroupDescriptor>
> TargetPeripheralDescriptor::tryGetRegisterGroupDescriptor(std::string_view keyStr) const {

View File

@@ -1,5 +1,6 @@
#pragma once
#include <cstdint>
#include <string>
#include <map>
#include <vector>
@@ -13,10 +14,13 @@
namespace Targets
{
using TargetPeripheralId = std::size_t;
struct TargetPeripheralDescriptor
{
public:
std::string key;
const TargetPeripheralId id;
const std::string key;
std::string name;
std::map<std::string, TargetRegisterGroupDescriptor, std::less<void>> registerGroupDescriptorsByKey;
std::vector<TargetPeripheralSignalDescriptor> signalDescriptors;
@@ -32,7 +36,9 @@ namespace Targets
TargetPeripheralDescriptor& operator = (const TargetPeripheralDescriptor& other) = delete;
TargetPeripheralDescriptor(TargetPeripheralDescriptor&& other) noexcept = default;
TargetPeripheralDescriptor& operator = (TargetPeripheralDescriptor&& other) = default;
bool operator == (const TargetPeripheralDescriptor& other) const;
bool operator != (const TargetPeripheralDescriptor& other) const;
[[nodiscard]] std::optional<
std::reference_wrapper<const TargetRegisterGroupDescriptor>

View File

@@ -1,6 +1,8 @@
#include "TargetRegisterDescriptor.hpp"
#include "src/Services/StringService.hpp"
#include "TargetAddressSpaceDescriptor.hpp"
#include "src/Exceptions/InternalFatalErrorException.hpp"
namespace Targets
@@ -8,6 +10,8 @@ namespace Targets
TargetRegisterDescriptor::TargetRegisterDescriptor(
const std::string& key,
const std::string& name,
const std::string& absoluteGroupKey,
const std::string& peripheralKey,
const std::string& addressSpaceKey,
TargetMemoryAddress startAddress,
TargetMemorySize size,
@@ -16,8 +20,11 @@ namespace Targets
std::optional<std::string> description,
std::map<std::string, TargetBitFieldDescriptor>&& bitFieldDescriptorsByKey
)
: key(key)
: id(Services::StringService::generateUniqueInteger(peripheralKey + absoluteGroupKey + key))
, key(key)
, name(name)
, absoluteGroupKey(absoluteGroupKey)
, peripheralKey(peripheralKey)
, addressSpaceId(TargetAddressSpaceDescriptor::generateId(addressSpaceKey))
, addressSpaceKey(addressSpaceKey)
, startAddress(startAddress)
@@ -29,15 +36,7 @@ namespace Targets
{}
bool TargetRegisterDescriptor::operator == (const TargetRegisterDescriptor& other) const {
return this->key == other.key
&& this->name == other.name
&& this->addressSpaceKey == other.addressSpaceKey
&& this->startAddress == other.startAddress
&& this->size == other.size
&& this->type == other.type
&& this->access == other.access
&& this->description == other.description
;
return this->id == other.id;
}
bool TargetRegisterDescriptor::operator < (const TargetRegisterDescriptor& other) const {
@@ -81,6 +80,8 @@ namespace Targets
auto output = TargetRegisterDescriptor{
this->key,
this->name,
this->absoluteGroupKey,
this->peripheralKey,
this->addressSpaceKey,
this->startAddress,
this->size,

View File

@@ -15,6 +15,7 @@
namespace Targets
{
using TargetRegisterId = std::size_t;
using TargetRegisterDescriptorId = std::uint32_t;
using TargetRegisterDescriptorIds = std::set<Targets::TargetRegisterDescriptorId>;
@@ -47,8 +48,11 @@ namespace Targets
struct TargetRegisterDescriptor
{
public:
std::string key;
const TargetRegisterId id;
const std::string key;
std::string name;
std::string absoluteGroupKey;
std::string peripheralKey;
TargetAddressSpaceId addressSpaceId;
std::string addressSpaceKey;
TargetMemoryAddress startAddress;
@@ -61,6 +65,8 @@ namespace Targets
TargetRegisterDescriptor(
const std::string& key,
const std::string& name,
const std::string& absoluteGroupKey,
const std::string& peripheralKey,
const std::string& addressSpaceKey,
TargetMemoryAddress startAddress,
TargetMemorySize size,
@@ -74,7 +80,6 @@ namespace Targets
TargetRegisterDescriptor& operator = (const TargetRegisterDescriptor& other) = delete;
TargetRegisterDescriptor(TargetRegisterDescriptor&& other) noexcept = default;
TargetRegisterDescriptor& operator = (TargetRegisterDescriptor&& other) = default;
bool operator == (const TargetRegisterDescriptor& other) const;
bool operator < (const TargetRegisterDescriptor& other) const;

View File

@@ -10,20 +10,33 @@ namespace Targets
{
TargetRegisterGroupDescriptor::TargetRegisterGroupDescriptor(
const std::string& key,
const std::string& absoluteKey,
const std::string& name,
const std::string& peripheralKey,
const std::string& addressSpaceKey,
const std::optional<std::string>& description,
std::map<std::string, TargetRegisterDescriptor, std::less<void>>&& registerDescriptorsByKey,
std::map<std::string, TargetRegisterGroupDescriptor, std::less<void>>&& subgroupDescriptorsByKey
)
: key(key)
: id(Services::StringService::generateUniqueInteger(peripheralKey + absoluteKey))
, key(key)
, absoluteKey(absoluteKey)
, name(name)
, peripheralKey(peripheralKey)
, addressSpaceKey(addressSpaceKey)
, description(description)
, registerDescriptorsByKey(std::move(registerDescriptorsByKey))
, subgroupDescriptorsByKey(std::move(subgroupDescriptorsByKey))
{}
bool TargetRegisterGroupDescriptor::operator == (const TargetRegisterGroupDescriptor& other) const {
return this->id == other.id;
}
bool TargetRegisterGroupDescriptor::operator != (const TargetRegisterGroupDescriptor& other) const {
return !(*this == other);
}
TargetMemoryAddress TargetRegisterGroupDescriptor::startAddress() const {
assert(!this->registerDescriptorsByKey.empty() || !this->subgroupDescriptorsByKey.empty());
@@ -140,7 +153,9 @@ namespace Targets
TargetRegisterGroupDescriptor TargetRegisterGroupDescriptor::clone() const {
auto output = TargetRegisterGroupDescriptor{
this->key,
this->absoluteKey,
this->name,
this->peripheralKey,
this->addressSpaceKey,
this->description,
{},

View File

@@ -15,11 +15,16 @@
namespace Targets
{
using TargetRegisterGroupId = std::size_t;
struct TargetRegisterGroupDescriptor
{
public:
std::string key;
const TargetRegisterGroupId id;
const std::string key;
const std::string absoluteKey;
std::string name;
std::string peripheralKey;
std::string addressSpaceKey;
std::optional<std::string> description;
std::map<std::string, TargetRegisterDescriptor, std::less<void>> registerDescriptorsByKey;
@@ -27,7 +32,9 @@ namespace Targets
TargetRegisterGroupDescriptor(
const std::string& key,
const std::string& absoluteKey,
const std::string& name,
const std::string& peripheralKey,
const std::string& addressSpaceKey,
const std::optional<std::string>& description,
std::map<std::string, TargetRegisterDescriptor, std::less<void>>&& registerDescriptorsByKey,
@@ -38,7 +45,9 @@ namespace Targets
TargetRegisterGroupDescriptor& operator = (const TargetRegisterGroupDescriptor& other) = delete;
TargetRegisterGroupDescriptor(TargetRegisterGroupDescriptor&& other) noexcept = default;
TargetRegisterGroupDescriptor& operator = (TargetRegisterGroupDescriptor&& other) = default;
bool operator == (const TargetRegisterGroupDescriptor& other) const;
bool operator != (const TargetRegisterGroupDescriptor& other) const;
/**
* Calculates the start address of the register group.