Updated TDF module, register group, register group reference, register and bit field extraction to align with new TDF format
This commit is contained in:
@@ -2,12 +2,30 @@
|
|||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
namespace Targets::TargetDescription
|
namespace Targets::TargetDescription
|
||||||
{
|
{
|
||||||
struct BitField
|
struct BitField
|
||||||
{
|
{
|
||||||
|
std::string key;
|
||||||
std::string name;
|
std::string name;
|
||||||
std::uint8_t mask;
|
std::optional<std::string> description;
|
||||||
|
std::uint64_t mask;
|
||||||
|
std::optional<std::string> access;
|
||||||
|
|
||||||
|
BitField(
|
||||||
|
const std::string& key,
|
||||||
|
const std::string& name,
|
||||||
|
const std::optional<std::string>& description,
|
||||||
|
std::uint64_t mask,
|
||||||
|
const std::optional<std::string>& access
|
||||||
|
)
|
||||||
|
: key(key)
|
||||||
|
, name(name)
|
||||||
|
, description(description)
|
||||||
|
, mask(mask)
|
||||||
|
, access(access)
|
||||||
|
{}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,14 +1,59 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
#include <map>
|
||||||
|
#include <string_view>
|
||||||
|
#include <optional>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
#include "ModuleInstance.hpp"
|
#include "ModuleInstance.hpp"
|
||||||
#include "RegisterGroup.hpp"
|
#include "RegisterGroup.hpp"
|
||||||
|
|
||||||
|
#include "src/Services/StringService.hpp"
|
||||||
|
|
||||||
namespace Targets::TargetDescription
|
namespace Targets::TargetDescription
|
||||||
{
|
{
|
||||||
struct Module
|
struct Module
|
||||||
{
|
{
|
||||||
|
std::string key;
|
||||||
std::string name;
|
std::string name;
|
||||||
std::map<std::string, ModuleInstance> instancesMappedByName;
|
std::string description;
|
||||||
std::map<std::string, RegisterGroup> registerGroupsMappedByName;
|
std::map<std::string, RegisterGroup, std::less<void>> registerGroupsByKey;
|
||||||
|
|
||||||
|
Module(
|
||||||
|
const std::string& key,
|
||||||
|
const std::string& name,
|
||||||
|
const std::string& description,
|
||||||
|
const std::map<std::string, RegisterGroup, std::less<void>>& registerGroupsByKey
|
||||||
|
)
|
||||||
|
: key(key)
|
||||||
|
, name(name)
|
||||||
|
, description(description)
|
||||||
|
, registerGroupsByKey(registerGroupsByKey)
|
||||||
|
{}
|
||||||
|
|
||||||
|
std::optional<std::reference_wrapper<const RegisterGroup>> tryGetRegisterGroup(std::string_view keyStr) const {
|
||||||
|
const auto keys = Services::StringService::split(keyStr, '.');
|
||||||
|
|
||||||
|
const auto firstGroupIt = this->registerGroupsByKey.find(*keys.begin());
|
||||||
|
return firstGroupIt != this->registerGroupsByKey.end()
|
||||||
|
? keys.size() > 1
|
||||||
|
? firstGroupIt->second.tryGetSubgroup(keys | std::ranges::views::drop(1))
|
||||||
|
: std::optional(std::cref(firstGroupIt->second))
|
||||||
|
: std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::reference_wrapper<const RegisterGroup>> getRegisterGroup(std::string_view keyStr) const {
|
||||||
|
const auto group = this->tryGetRegisterGroup(keyStr);
|
||||||
|
if (!group.has_value()) {
|
||||||
|
throw Exceptions::InvalidTargetDescriptionDataException(
|
||||||
|
"Failed to get register group \"" + std::string(keyStr)
|
||||||
|
+ "\" from module in TDF - register group not found"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return group->get();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
70
src/Targets/TargetDescription/Register.hpp
Normal file
70
src/Targets/TargetDescription/Register.hpp
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
#include <optional>
|
||||||
|
#include <map>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
#include "BitField.hpp"
|
||||||
|
|
||||||
|
#include "Exceptions/InvalidTargetDescriptionDataException.hpp"
|
||||||
|
|
||||||
|
namespace Targets::TargetDescription
|
||||||
|
{
|
||||||
|
struct Register
|
||||||
|
{
|
||||||
|
std::string key;
|
||||||
|
std::string name;
|
||||||
|
std::optional<std::string> description;
|
||||||
|
std::uint32_t offset;
|
||||||
|
std::uint16_t size;
|
||||||
|
std::optional<std::uint64_t> initialValue;
|
||||||
|
std::optional<std::string> access;
|
||||||
|
std::optional<bool> alternative;
|
||||||
|
std::map<std::string, BitField, std::less<void>> bitFieldsByKey;
|
||||||
|
|
||||||
|
Register(
|
||||||
|
const std::string& key,
|
||||||
|
const std::string& name,
|
||||||
|
const std::optional<std::string>& description,
|
||||||
|
std::uint32_t offset,
|
||||||
|
std::uint16_t size,
|
||||||
|
const std::optional<std::uint64_t>& initialValue,
|
||||||
|
const std::optional<std::string>& access,
|
||||||
|
const std::optional<bool>& alternative,
|
||||||
|
const std::map<std::string, BitField, std::less<void>>& bitFieldsByKey
|
||||||
|
)
|
||||||
|
: key(key)
|
||||||
|
, name(name)
|
||||||
|
, description(description)
|
||||||
|
, offset(offset)
|
||||||
|
, size(size)
|
||||||
|
, initialValue(initialValue)
|
||||||
|
, access(access)
|
||||||
|
, alternative(alternative)
|
||||||
|
, bitFieldsByKey(bitFieldsByKey)
|
||||||
|
{}
|
||||||
|
|
||||||
|
std::optional<std::reference_wrapper<const BitField>> tryGetBitField(std::string_view key) const {
|
||||||
|
const auto bitFieldIt = this->bitFieldsByKey.find(key);
|
||||||
|
|
||||||
|
if (bitFieldIt == this->bitFieldsByKey.end()) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::cref(bitFieldIt->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
const BitField& getBitField(std::string_view key) const {
|
||||||
|
const auto bitField = this->tryGetBitField(key);
|
||||||
|
if (!bitField.has_value()) {
|
||||||
|
throw Exceptions::InvalidTargetDescriptionDataException(
|
||||||
|
"Failed to get bit field \"" + std::string(key) + "\" from register in TDF - bit field not found"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bitField->get();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -2,29 +2,100 @@
|
|||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include <map>
|
||||||
|
#include <string_view>
|
||||||
|
#include <ranges>
|
||||||
|
#include <concepts>
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
#include "BitField.hpp"
|
#include "Register.hpp"
|
||||||
|
#include "RegisterGroupReference.hpp"
|
||||||
|
|
||||||
namespace Targets::TargetDescription
|
namespace Targets::TargetDescription
|
||||||
{
|
{
|
||||||
struct Register
|
|
||||||
{
|
|
||||||
std::string name;
|
|
||||||
std::optional<std::string> caption;
|
|
||||||
std::uint16_t offset;
|
|
||||||
std::uint16_t size;
|
|
||||||
std::optional<std::string> readWriteAccess;
|
|
||||||
std::map<std::string, BitField> bitFieldsMappedByName;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct RegisterGroup
|
struct RegisterGroup
|
||||||
{
|
{
|
||||||
|
std::string key;
|
||||||
std::string name;
|
std::string name;
|
||||||
std::optional<std::string> moduleName;
|
std::optional<std::uint32_t> offset;
|
||||||
std::optional<std::uint16_t> offset;
|
std::map<std::string, Register, std::less<void>> registersByKey;
|
||||||
std::optional<std::string> addressSpaceId;
|
std::map<std::string, RegisterGroup, std::less<void>> subgroupsByKey;
|
||||||
std::map<std::string, Register> registersMappedByName;
|
std::map<std::string, RegisterGroupReference, std::less<void>> subgroupReferencesByKey;
|
||||||
|
|
||||||
|
RegisterGroup(
|
||||||
|
const std::string& key,
|
||||||
|
const std::string& name,
|
||||||
|
const std::optional<std::uint32_t>& offset,
|
||||||
|
const std::map<std::string, Register, std::less<void>>& registersByKey,
|
||||||
|
const std::map<std::string, RegisterGroup, std::less<void>>& subgroupsByKey,
|
||||||
|
const std::map<std::string, RegisterGroupReference, std::less<void>>& subgroupReferencesByKey
|
||||||
|
)
|
||||||
|
: key(key)
|
||||||
|
, name(name)
|
||||||
|
, offset(offset)
|
||||||
|
, registersByKey(registersByKey)
|
||||||
|
, subgroupsByKey(subgroupsByKey)
|
||||||
|
, subgroupReferencesByKey(subgroupReferencesByKey)
|
||||||
|
{}
|
||||||
|
|
||||||
|
template <typename KeysType>
|
||||||
|
requires
|
||||||
|
std::ranges::sized_range<KeysType>
|
||||||
|
std::optional<std::reference_wrapper<const RegisterGroup>> tryGetSubgroup(KeysType keys) const {
|
||||||
|
auto firstSubgroupIt = this->subgroupsByKey.find(*(keys.begin()));
|
||||||
|
if (firstSubgroupIt == this->subgroupsByKey.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().tryGetSubgroup(key);
|
||||||
|
|
||||||
|
if (!subgroup.has_value()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return subgroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::reference_wrapper<const RegisterGroup>> tryGetSubgroup(std::string_view keyStr) const {
|
||||||
|
return this->tryGetSubgroup(Services::StringService::split(keyStr, '.'));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::reference_wrapper<const RegisterGroup>> getSubgroup(std::string_view keyStr) const {
|
||||||
|
const auto subgroup = this->tryGetSubgroup(keyStr);
|
||||||
|
if (!subgroup.has_value()) {
|
||||||
|
throw Exceptions::InvalidTargetDescriptionDataException(
|
||||||
|
"Failed to get subgroup \"" + std::string(keyStr)
|
||||||
|
+ "\" from register group in TDF - subgroup not found"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return subgroup->get();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<std::reference_wrapper<const Register>> tryGetRegister(std::string_view key) const {
|
||||||
|
const auto registerIt = this->registersByKey.find(key);
|
||||||
|
|
||||||
|
if (registerIt == this->registersByKey.end()) {
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
return std::cref(registerIt->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Register& getRegister(std::string_view key) const {
|
||||||
|
const auto reg = this->tryGetRegister(key);
|
||||||
|
if (!reg.has_value()) {
|
||||||
|
throw Exceptions::InvalidTargetDescriptionDataException(
|
||||||
|
"Failed to get register \"" + std::string(key) + "\" from register group in TDF - register "
|
||||||
|
"not found"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return reg->get();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
31
src/Targets/TargetDescription/RegisterGroupReference.hpp
Normal file
31
src/Targets/TargetDescription/RegisterGroupReference.hpp
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <string>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
namespace Targets::TargetDescription
|
||||||
|
{
|
||||||
|
struct RegisterGroupReference
|
||||||
|
{
|
||||||
|
std::string key;
|
||||||
|
std::string name;
|
||||||
|
std::string registerGroupKey;
|
||||||
|
std::uint32_t offset;
|
||||||
|
std::optional<std::string> description;
|
||||||
|
|
||||||
|
RegisterGroupReference(
|
||||||
|
const std::string& key,
|
||||||
|
const std::string& name,
|
||||||
|
const std::string& registerGroupKey,
|
||||||
|
std::uint32_t offset,
|
||||||
|
const std::optional<std::string>& description
|
||||||
|
)
|
||||||
|
: key(key)
|
||||||
|
, name(name)
|
||||||
|
, registerGroupKey(registerGroupKey)
|
||||||
|
, offset(offset)
|
||||||
|
, description(description)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -121,6 +121,27 @@ namespace Targets::TargetDescription
|
|||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::optional<std::reference_wrapper<const Module>> TargetDescriptionFile::tryGetModule(
|
||||||
|
std::string_view key
|
||||||
|
) const {
|
||||||
|
const auto moduleIt = this->modulesByKey.find(key);
|
||||||
|
return moduleIt != this->modulesByKey.end()
|
||||||
|
? std::optional(std::cref(moduleIt->second))
|
||||||
|
: std::nullopt;
|
||||||
|
}
|
||||||
|
|
||||||
|
const Module& TargetDescriptionFile::getModule(std::string_view key) const {
|
||||||
|
const auto module = this->tryGetModule(key);
|
||||||
|
|
||||||
|
if (!module.has_value()) {
|
||||||
|
throw InvalidTargetDescriptionDataException(
|
||||||
|
"Failed to get module \"" + std::string(key) + "\" from TDF - module not found"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return module->get();
|
||||||
|
}
|
||||||
|
|
||||||
void TargetDescriptionFile::init(const std::string& xmlFilePath) {
|
void TargetDescriptionFile::init(const std::string& xmlFilePath) {
|
||||||
auto file = QFile(QString::fromStdString(xmlFilePath));
|
auto file = QFile(QString::fromStdString(xmlFilePath));
|
||||||
if (!file.exists()) {
|
if (!file.exists()) {
|
||||||
@@ -188,7 +209,17 @@ namespace Targets::TargetDescription
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->loadModules(document);
|
for (
|
||||||
|
auto element = deviceElement.firstChildElement("modules").firstChildElement("module");
|
||||||
|
!element.isNull();
|
||||||
|
element = element.nextSiblingElement("module")
|
||||||
|
) {
|
||||||
|
auto module = TargetDescriptionFile::moduleFromXml(element);
|
||||||
|
this->modulesByKey.insert(
|
||||||
|
std::pair(module.key, std::move(module))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
this->loadPeripheralModules(document);
|
this->loadPeripheralModules(document);
|
||||||
this->loadVariants(document);
|
this->loadVariants(document);
|
||||||
this->loadPinouts(document);
|
this->loadPinouts(document);
|
||||||
@@ -365,124 +396,116 @@ namespace Targets::TargetDescription
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Module TargetDescriptionFile::moduleFromXml(const QDomElement& xmlElement) {
|
||||||
|
auto output = Module(
|
||||||
|
TargetDescriptionFile::getAttribute(xmlElement, "key"),
|
||||||
|
TargetDescriptionFile::getAttribute(xmlElement, "name"),
|
||||||
|
TargetDescriptionFile::getAttribute(xmlElement, "description"),
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
|
||||||
|
for (
|
||||||
|
auto element = xmlElement.firstChildElement("register-group");
|
||||||
|
!element.isNull();
|
||||||
|
element = element.nextSiblingElement("register-group")
|
||||||
|
) {
|
||||||
|
auto registerGroup = TargetDescriptionFile::registerGroupFromXml(element);
|
||||||
|
output.registerGroupsByKey.insert(std::pair(registerGroup.key, std::move(registerGroup)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
RegisterGroup TargetDescriptionFile::registerGroupFromXml(const QDomElement& xmlElement) {
|
RegisterGroup TargetDescriptionFile::registerGroupFromXml(const QDomElement& xmlElement) {
|
||||||
if (!xmlElement.hasAttribute("name")) {
|
const auto offset = TargetDescriptionFile::tryGetAttribute(xmlElement, "offset");
|
||||||
throw Exception("Missing register group name attribute");
|
|
||||||
|
auto output = RegisterGroup(
|
||||||
|
TargetDescriptionFile::getAttribute(xmlElement, "key"),
|
||||||
|
TargetDescriptionFile::getAttribute(xmlElement, "name"),
|
||||||
|
offset.has_value() ? std::optional(StringService::toUint32(*offset)) : std::nullopt,
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
|
||||||
|
for (
|
||||||
|
auto element = xmlElement.firstChildElement("register");
|
||||||
|
!element.isNull();
|
||||||
|
element = element.nextSiblingElement("register")
|
||||||
|
) {
|
||||||
|
auto reg = TargetDescriptionFile::registerFromXml(element);
|
||||||
|
output.registersByKey.insert(std::pair(reg.key, std::move(reg)));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto registerGroup = RegisterGroup();
|
for (
|
||||||
registerGroup.name = xmlElement.attribute("name").toLower().toStdString();
|
auto element = xmlElement.firstChildElement("register-group");
|
||||||
|
!element.isNull();
|
||||||
if (registerGroup.name.empty()) {
|
element = element.nextSiblingElement("register-group")
|
||||||
throw Exception("Empty register group name");
|
) {
|
||||||
|
auto registerGroup = TargetDescriptionFile::registerGroupFromXml(element);
|
||||||
|
output.subgroupsByKey.insert(std::pair(registerGroup.key, std::move(registerGroup)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xmlElement.hasAttribute("name-in-module")) {
|
for (
|
||||||
registerGroup.moduleName = xmlElement.attribute("name-in-module").toLower().toStdString();
|
auto element = xmlElement.firstChildElement("register-group-reference");
|
||||||
|
!element.isNull();
|
||||||
|
element = element.nextSiblingElement("register-group-reference")
|
||||||
|
) {
|
||||||
|
auto registerGroupReference = TargetDescriptionFile::registerGroupReferenceFromXml(element);
|
||||||
|
output.subgroupReferencesByKey.insert(
|
||||||
|
std::pair(registerGroupReference.key, std::move(registerGroupReference))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (xmlElement.hasAttribute("address-space")) {
|
return output;
|
||||||
registerGroup.addressSpaceId = xmlElement.attribute("address-space").toLower().toStdString();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (xmlElement.hasAttribute("offset")) {
|
RegisterGroupReference TargetDescriptionFile::registerGroupReferenceFromXml(const QDomElement& xmlElement) {
|
||||||
registerGroup.offset = xmlElement.attribute("offset").toInt(nullptr, 16);
|
return RegisterGroupReference(
|
||||||
}
|
TargetDescriptionFile::getAttribute(xmlElement, "key"),
|
||||||
|
TargetDescriptionFile::getAttribute(xmlElement, "name"),
|
||||||
auto& registers = registerGroup.registersMappedByName;
|
TargetDescriptionFile::getAttribute(xmlElement, "register-group-key"),
|
||||||
auto registerNodes = xmlElement.elementsByTagName("register");
|
StringService::toUint32(TargetDescriptionFile::getAttribute(xmlElement, "offset")),
|
||||||
for (int registerIndex = 0; registerIndex < registerNodes.count(); registerIndex++) {
|
TargetDescriptionFile::tryGetAttribute(xmlElement, "description")
|
||||||
try {
|
);
|
||||||
auto reg = TargetDescriptionFile::registerFromXml(
|
|
||||||
registerNodes.item(registerIndex).toElement()
|
|
||||||
);
|
|
||||||
registers.insert(std::pair(reg.name, reg));
|
|
||||||
|
|
||||||
} catch (const Exception& exception) {
|
|
||||||
Logger::debug("Failed to extract register from register group target description element - "
|
|
||||||
+ exception.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return registerGroup;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Register TargetDescriptionFile::registerFromXml(const QDomElement& xmlElement) {
|
Register TargetDescriptionFile::registerFromXml(const QDomElement& xmlElement) {
|
||||||
if (
|
const auto initialValue = TargetDescriptionFile::tryGetAttribute(xmlElement, "initial-value");
|
||||||
!xmlElement.hasAttribute("name")
|
const auto alternative = TargetDescriptionFile::tryGetAttribute(xmlElement, "alternative");
|
||||||
|| !xmlElement.hasAttribute("offset")
|
|
||||||
|| !xmlElement.hasAttribute("size")
|
auto output = Register(
|
||||||
|
TargetDescriptionFile::getAttribute(xmlElement, "key"),
|
||||||
|
TargetDescriptionFile::getAttribute(xmlElement, "name"),
|
||||||
|
TargetDescriptionFile::tryGetAttribute(xmlElement, "description"),
|
||||||
|
StringService::toUint32(TargetDescriptionFile::getAttribute(xmlElement, "offset")),
|
||||||
|
StringService::toUint16(TargetDescriptionFile::getAttribute(xmlElement, "size")),
|
||||||
|
initialValue.has_value() ? std::optional(StringService::toUint64(*initialValue)) : std::nullopt,
|
||||||
|
TargetDescriptionFile::tryGetAttribute(xmlElement, "access"),
|
||||||
|
alternative.has_value() ? std::optional(*alternative == "true") : std::nullopt,
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
|
||||||
|
for (
|
||||||
|
auto element = xmlElement.firstChildElement("bit-field");
|
||||||
|
!element.isNull();
|
||||||
|
element = element.nextSiblingElement("bit-field")
|
||||||
) {
|
) {
|
||||||
throw Exception("Missing register name/offset/size attribute");
|
auto bitField = TargetDescriptionFile::bitFieldFromXml(element);
|
||||||
|
output.bitFieldsByKey.insert(std::pair(bitField.key, std::move(bitField)));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto reg = Register();
|
return output;
|
||||||
reg.name = xmlElement.attribute("name").toLower().toStdString();
|
|
||||||
|
|
||||||
if (reg.name.empty()) {
|
|
||||||
throw Exception("Empty register name");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xmlElement.hasAttribute("caption")) {
|
|
||||||
reg.caption = xmlElement.attribute("caption").toStdString();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (xmlElement.hasAttribute("ocd-rw")) {
|
|
||||||
reg.readWriteAccess = xmlElement.attribute("ocd-rw").toLower().toStdString();
|
|
||||||
|
|
||||||
} else if (xmlElement.hasAttribute("rw")) {
|
|
||||||
reg.readWriteAccess = xmlElement.attribute("rw").toLower().toStdString();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool conversionStatus = false;
|
|
||||||
reg.size = xmlElement.attribute("size").toUShort(nullptr, 10);
|
|
||||||
reg.offset = xmlElement.attribute("offset").toUShort(&conversionStatus, 16);
|
|
||||||
|
|
||||||
if (!conversionStatus) {
|
|
||||||
// Failed to convert offset hex value as string to uint16_t
|
|
||||||
throw Exception("Invalid register offset");
|
|
||||||
}
|
|
||||||
|
|
||||||
auto& bitFields = reg.bitFieldsMappedByName;
|
|
||||||
auto bitFieldNodes = xmlElement.elementsByTagName("bitfield");
|
|
||||||
for (int bitFieldIndex = 0; bitFieldIndex < bitFieldNodes.count(); bitFieldIndex++) {
|
|
||||||
try {
|
|
||||||
auto bitField = TargetDescriptionFile::bitFieldFromXml(
|
|
||||||
bitFieldNodes.item(bitFieldIndex).toElement()
|
|
||||||
);
|
|
||||||
bitFields.insert(std::pair(bitField.name, bitField));
|
|
||||||
|
|
||||||
} catch (const Exception& exception) {
|
|
||||||
Logger::debug("Failed to extract bit field from register target description element - "
|
|
||||||
+ exception.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return reg;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BitField TargetDescriptionFile::bitFieldFromXml(const QDomElement& xmlElement) {
|
BitField TargetDescriptionFile::bitFieldFromXml(const QDomElement& xmlElement) {
|
||||||
if (!xmlElement.hasAttribute("name") || !xmlElement.hasAttribute("mask")) {
|
return BitField(
|
||||||
throw Exception("Missing bit field name/mask attribute");
|
TargetDescriptionFile::getAttribute(xmlElement, "key"),
|
||||||
}
|
TargetDescriptionFile::getAttribute(xmlElement, "name"),
|
||||||
|
TargetDescriptionFile::tryGetAttribute(xmlElement, "description"),
|
||||||
auto bitField = BitField();
|
StringService::toUint64(TargetDescriptionFile::getAttribute(xmlElement, "mask")),
|
||||||
bitField.name = xmlElement.attribute("name").toLower().toStdString();
|
TargetDescriptionFile::tryGetAttribute(xmlElement, "access")
|
||||||
|
|
||||||
auto maskConversion = false;
|
|
||||||
bitField.mask = static_cast<std::uint8_t>(
|
|
||||||
xmlElement.attribute("mask").toUShort(&maskConversion, 16)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!maskConversion) {
|
|
||||||
throw Exception("Failed to convert bit field mask to integer (from hex string)");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bitField.name.empty()) {
|
|
||||||
throw Exception("Empty bit field name");
|
|
||||||
}
|
|
||||||
|
|
||||||
return bitField;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string& TargetDescriptionFile::deviceAttribute(const std::string& attributeName) const {
|
const std::string& TargetDescriptionFile::deviceAttribute(const std::string& attributeName) const {
|
||||||
@@ -495,105 +518,11 @@ namespace Targets::TargetDescription
|
|||||||
return attributeIt->second;
|
return attributeIt->second;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TargetDescriptionFile::loadModules(const QDomDocument& document) {
|
|
||||||
const auto deviceElement = document.elementsByTagName("device").item(0).toElement();
|
|
||||||
|
|
||||||
auto moduleNodes = document.elementsByTagName("modules").item(0).toElement()
|
|
||||||
.elementsByTagName("module");
|
|
||||||
|
|
||||||
for (int moduleIndex = 0; moduleIndex < moduleNodes.count(); moduleIndex++) {
|
|
||||||
auto moduleElement = moduleNodes.item(moduleIndex).toElement();
|
|
||||||
auto moduleName = moduleElement.attributes().namedItem("name").nodeValue().toLower().toStdString();
|
|
||||||
Module module;
|
|
||||||
module.name = moduleName;
|
|
||||||
|
|
||||||
auto registerGroupNodes = moduleElement.elementsByTagName("register-group");
|
|
||||||
for (int registerGroupIndex = 0; registerGroupIndex < registerGroupNodes.count(); registerGroupIndex++) {
|
|
||||||
auto registerGroup = TargetDescriptionFile::registerGroupFromXml(
|
|
||||||
registerGroupNodes.item(registerGroupIndex).toElement()
|
|
||||||
);
|
|
||||||
|
|
||||||
module.registerGroupsMappedByName.insert(std::pair(registerGroup.name, registerGroup));
|
|
||||||
}
|
|
||||||
|
|
||||||
this->modulesMappedByName.insert(std::pair(module.name, module));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void TargetDescriptionFile::loadPeripheralModules(const QDomDocument& document) {
|
void TargetDescriptionFile::loadPeripheralModules(const QDomDocument& document) {
|
||||||
const auto deviceElement = document.elementsByTagName("device").item(0).toElement();
|
const auto deviceElement = document.elementsByTagName("device").item(0).toElement();
|
||||||
|
|
||||||
auto moduleNodes = deviceElement.elementsByTagName("peripherals").item(0).toElement()
|
auto moduleNodes = deviceElement.elementsByTagName("peripherals").item(0).toElement()
|
||||||
.elementsByTagName("module");
|
.elementsByTagName("module");
|
||||||
|
|
||||||
for (int moduleIndex = 0; moduleIndex < moduleNodes.count(); moduleIndex++) {
|
|
||||||
auto moduleElement = moduleNodes.item(moduleIndex).toElement();
|
|
||||||
auto moduleName = moduleElement.attributes().namedItem("name").nodeValue().toLower().toStdString();
|
|
||||||
Module module;
|
|
||||||
module.name = moduleName;
|
|
||||||
|
|
||||||
auto registerGroupNodes = moduleElement.elementsByTagName("register-group");
|
|
||||||
for (int registerGroupIndex = 0; registerGroupIndex < registerGroupNodes.count(); registerGroupIndex++) {
|
|
||||||
auto registerGroup = TargetDescriptionFile::registerGroupFromXml(
|
|
||||||
registerGroupNodes.item(registerGroupIndex).toElement()
|
|
||||||
);
|
|
||||||
|
|
||||||
module.registerGroupsMappedByName.insert(std::pair(registerGroup.name, registerGroup));
|
|
||||||
|
|
||||||
if (registerGroup.moduleName.has_value()) {
|
|
||||||
this->peripheralRegisterGroupsMappedByModuleRegisterGroupName[registerGroup.moduleName.value()]
|
|
||||||
.emplace_back(registerGroup);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
auto instanceNodes = moduleElement.elementsByTagName("instance");
|
|
||||||
for (int instanceIndex = 0; instanceIndex < instanceNodes.count(); instanceIndex++) {
|
|
||||||
auto instanceXml = instanceNodes.item(instanceIndex).toElement();
|
|
||||||
auto instance = ModuleInstance();
|
|
||||||
instance.name = instanceXml.attribute("name").toLower().toStdString();
|
|
||||||
|
|
||||||
auto registerGroupNodes = instanceXml.elementsByTagName("register-group");
|
|
||||||
for (
|
|
||||||
int registerGroupIndex = 0;
|
|
||||||
registerGroupIndex < registerGroupNodes.count();
|
|
||||||
registerGroupIndex++
|
|
||||||
) {
|
|
||||||
auto registerGroup = TargetDescriptionFile::registerGroupFromXml(
|
|
||||||
registerGroupNodes.item(registerGroupIndex).toElement()
|
|
||||||
);
|
|
||||||
|
|
||||||
instance.registerGroupsMappedByName.insert(std::pair(registerGroup.name, registerGroup));
|
|
||||||
}
|
|
||||||
|
|
||||||
auto signalNodes = instanceXml.elementsByTagName("signals").item(0).toElement()
|
|
||||||
.elementsByTagName("signal");
|
|
||||||
for (int signalIndex = 0; signalIndex < signalNodes.count(); signalIndex++) {
|
|
||||||
auto signalXml = signalNodes.item(signalIndex).toElement();
|
|
||||||
auto signal = Signal();
|
|
||||||
|
|
||||||
if (!signalXml.hasAttribute("pad")) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
signal.padName = signalXml.attribute("pad").toLower().toStdString();
|
|
||||||
signal.function = signalXml.attribute("function").toStdString();
|
|
||||||
signal.group = signalXml.attribute("group").toStdString();
|
|
||||||
auto indexAttribute = signalXml.attribute("index");
|
|
||||||
bool indexValid = false;
|
|
||||||
auto indexValue = indexAttribute.toInt(&indexValid, 10);
|
|
||||||
|
|
||||||
if (!indexAttribute.isEmpty() && indexValid) {
|
|
||||||
signal.index = indexValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
instance.instanceSignals.emplace_back(signal);
|
|
||||||
}
|
|
||||||
|
|
||||||
module.instancesMappedByName.insert(std::pair(instance.name, instance));
|
|
||||||
}
|
|
||||||
|
|
||||||
this->peripheralModulesMappedByName.insert(std::pair(module.name, module));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TargetDescriptionFile::loadVariants(const QDomDocument& document) {
|
void TargetDescriptionFile::loadVariants(const QDomDocument& document) {
|
||||||
|
|||||||
@@ -102,12 +102,17 @@ namespace Targets::TargetDescription
|
|||||||
|
|
||||||
[[nodiscard]] std::set<Targets::TargetPhysicalInterface> getPhysicalInterfaces() const;
|
[[nodiscard]] std::set<Targets::TargetPhysicalInterface> getPhysicalInterfaces() const;
|
||||||
|
|
||||||
|
[[nodiscard]] std::optional<std::reference_wrapper<const Module>> tryGetModule(
|
||||||
|
std::string_view key
|
||||||
|
) const;
|
||||||
|
[[nodiscard]] const Module& getModule(std::string_view key) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::map<std::string, std::string> deviceAttributesByName;
|
std::map<std::string, std::string> deviceAttributesByName;
|
||||||
std::map<std::string, PropertyGroup, std::less<void>> propertyGroupsByKey;
|
std::map<std::string, PropertyGroup, std::less<void>> propertyGroupsByKey;
|
||||||
std::map<std::string, AddressSpace, std::less<void>> addressSpacesByKey;
|
std::map<std::string, AddressSpace, std::less<void>> addressSpacesByKey;
|
||||||
std::vector<PhysicalInterface> physicalInterfaces;
|
std::vector<PhysicalInterface> physicalInterfaces;
|
||||||
std::map<std::string, Module> modulesMappedByName;
|
std::map<std::string, Module, std::less<void>> modulesByKey;
|
||||||
std::map<std::string, Module> peripheralModulesMappedByName;
|
std::map<std::string, Module> peripheralModulesMappedByName;
|
||||||
std::map<std::string, std::vector<RegisterGroup>> peripheralRegisterGroupsMappedByModuleRegisterGroupName;
|
std::map<std::string, std::vector<RegisterGroup>> peripheralRegisterGroupsMappedByModuleRegisterGroupName;
|
||||||
std::vector<Variant> variants;
|
std::vector<Variant> variants;
|
||||||
@@ -163,6 +168,14 @@ namespace Targets::TargetDescription
|
|||||||
*/
|
*/
|
||||||
static PhysicalInterface physicalInterfaceFromXml(const QDomElement& xmlElement);
|
static PhysicalInterface physicalInterfaceFromXml(const QDomElement& xmlElement);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a Module object from an XML element.
|
||||||
|
*
|
||||||
|
* @param xmlElement
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
static Module moduleFromXml(const QDomElement& xmlElement);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a RegisterGroup object from an XML element.
|
* Constructs a RegisterGroup object from an XML element.
|
||||||
*
|
*
|
||||||
@@ -171,6 +184,14 @@ namespace Targets::TargetDescription
|
|||||||
*/
|
*/
|
||||||
static RegisterGroup registerGroupFromXml(const QDomElement& xmlElement);
|
static RegisterGroup registerGroupFromXml(const QDomElement& xmlElement);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a RegisterGroupReference object from an XML element.
|
||||||
|
*
|
||||||
|
* @param xmlElement
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
static RegisterGroupReference registerGroupReferenceFromXml(const QDomElement& xmlElement);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a Register object from an XML element.
|
* Constructs a Register object from an XML element.
|
||||||
*
|
*
|
||||||
@@ -180,7 +201,7 @@ namespace Targets::TargetDescription
|
|||||||
static Register registerFromXml(const QDomElement& xmlElement);
|
static Register registerFromXml(const QDomElement& xmlElement);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Consturcts a BitField object from an XML element.
|
* Constructs a BitField object from an XML element.
|
||||||
*
|
*
|
||||||
* @param xmlElement
|
* @param xmlElement
|
||||||
* @return
|
* @return
|
||||||
@@ -195,11 +216,6 @@ namespace Targets::TargetDescription
|
|||||||
*/
|
*/
|
||||||
const std::string& deviceAttribute(const std::string& attributeName) const;
|
const std::string& deviceAttribute(const std::string& attributeName) const;
|
||||||
|
|
||||||
/**
|
|
||||||
* Extracts all modules and loads them into this->modulesMappedByName.
|
|
||||||
*/
|
|
||||||
void loadModules(const QDomDocument& document);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extracts all peripheral modules and loads them into this->peripheralModulesMappedByName.
|
* Extracts all peripheral modules and loads them into this->peripheralModulesMappedByName.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user