- Refactored AVR8 constructor, moving TDF construction to the TargetControllerComponent
- The `TargetControllerComponent` now resolves the target via the new generated mapping approach - Added `TargetDescriptionFile` derived class - Removed obsolete JSON map processing code - Other bits of refactoring and tidying
This commit is contained in:
@@ -51,6 +51,15 @@ namespace Services
|
||||
return PathService::projectDirPath() + "/.bloom";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path to the directory containing Bloom's target description files.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
static std::string targetDescriptionDirPath() {
|
||||
return PathService::resourcesDirPath() + "/TargetDescriptionFiles";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the path to the current project's settings file.
|
||||
*
|
||||
|
||||
@@ -4,8 +4,12 @@
|
||||
#include <typeindex>
|
||||
#include <algorithm>
|
||||
|
||||
#include "src/Targets/Microchip/AVR/AVR8/TargetDescription/TargetDescriptionFile.hpp"
|
||||
#include "src/Targets/RiscV/TargetDescription/TargetDescriptionFile.hpp"
|
||||
|
||||
#include "Responses/Error.hpp"
|
||||
|
||||
#include "src/Services/PathService.hpp"
|
||||
#include "src/Services/ProcessService.hpp"
|
||||
#include "src/Services/StringService.hpp"
|
||||
#include "src/Logger/Logger.hpp"
|
||||
@@ -371,32 +375,30 @@ namespace TargetController
|
||||
};
|
||||
}
|
||||
|
||||
std::map<
|
||||
std::string,
|
||||
std::function<std::unique_ptr<Targets::Target>(const TargetConfig&)>
|
||||
> TargetControllerComponent::getSupportedTargets() {
|
||||
using Avr8TargetDescriptionFile = Targets::Microchip::Avr::Avr8Bit::TargetDescription::TargetDescriptionFile;
|
||||
std::unique_ptr<Targets::Target> TargetControllerComponent::constructTargetFromBrief(
|
||||
const TargetDescription::GeneratedMapping::BriefTargetDescriptor &targetBrief
|
||||
) {
|
||||
using Services::PathService;
|
||||
|
||||
auto mapping = std::map<std::string, std::function<std::unique_ptr<Targets::Target>(const TargetConfig&)>>();
|
||||
|
||||
// Include all targets from AVR8 target description files
|
||||
const auto avr8PdMapping = Avr8TargetDescriptionFile::getTargetDescriptionMapping();
|
||||
|
||||
for (auto mapIt = avr8PdMapping.begin(); mapIt != avr8PdMapping.end(); ++mapIt) {
|
||||
const auto mappingObject = mapIt.value().toObject();
|
||||
const auto targetName = mappingObject.find("name").value().toString().toLower().toStdString();
|
||||
|
||||
if (!mapping.contains(targetName)) {
|
||||
mapping.insert({
|
||||
targetName,
|
||||
[targetName] (const TargetConfig& targetConfig) {
|
||||
return std::make_unique<Targets::Microchip::Avr::Avr8Bit::Avr8>(targetConfig);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (targetBrief.targetFamily == TargetFamily::AVR_8) {
|
||||
return std::make_unique<Microchip::Avr::Avr8Bit::Avr8>(
|
||||
this->environmentConfig.targetConfig,
|
||||
Microchip::Avr::Avr8Bit::TargetDescription::TargetDescriptionFile(
|
||||
PathService::targetDescriptionDirPath() + "/" + targetBrief.relativeTdfPath
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
return mapping;
|
||||
if (targetBrief.targetFamily == TargetFamily::RISC_V) {
|
||||
return std::make_unique<RiscV::RiscV>(
|
||||
this->environmentConfig.targetConfig,
|
||||
RiscV::TargetDescription::TargetDescriptionFile(
|
||||
PathService::targetDescriptionDirPath() + "/" + targetBrief.relativeTdfPath
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
throw Exception("Cannot construct target instance - invalid target family in BriefTargetDescriptor");
|
||||
}
|
||||
|
||||
void TargetControllerComponent::processQueuedCommands() {
|
||||
@@ -468,10 +470,10 @@ namespace TargetController
|
||||
const auto& targetName = this->environmentConfig.targetConfig.name;
|
||||
|
||||
static const auto supportedDebugTools = this->getSupportedDebugTools();
|
||||
static const auto supportedTargets = this->getSupportedTargets();
|
||||
static const auto targetsByConfigValue = TargetDescription::TargetDescriptionFile::mapping();
|
||||
|
||||
const auto debugToolIt = supportedDebugTools.find(debugToolName);
|
||||
const auto targetIt = supportedTargets.find(targetName);
|
||||
const auto targetBriefIt = targetsByConfigValue.find(targetName);
|
||||
|
||||
if (debugToolIt == supportedDebugTools.end()) {
|
||||
throw Exceptions::InvalidConfig(
|
||||
@@ -479,7 +481,7 @@ namespace TargetController
|
||||
);
|
||||
}
|
||||
|
||||
if (targetIt == supportedTargets.end()) {
|
||||
if (targetBriefIt == targetsByConfigValue.end()) {
|
||||
throw Exceptions::InvalidConfig(
|
||||
"Target name (\"" + targetName + "\") not recognised. Please check your configuration!"
|
||||
);
|
||||
@@ -495,7 +497,7 @@ namespace TargetController
|
||||
Logger::info("Debug tool serial: " + this->debugTool->getSerialNumber());
|
||||
Logger::info("Debug tool firmware version: " + this->debugTool->getFirmwareVersionString());
|
||||
|
||||
this->target = targetIt->second(this->environmentConfig.targetConfig);
|
||||
this->target = this->constructTargetFromBrief(targetBriefIt->second);
|
||||
const auto& targetDescriptor = this->getTargetDescriptor();
|
||||
|
||||
if (!this->target->supportsDebugTool(this->debugTool.get())) {
|
||||
|
||||
@@ -246,12 +246,14 @@ namespace TargetController
|
||||
std::map<std::string, std::function<std::unique_ptr<DebugTool>()>> getSupportedDebugTools();
|
||||
|
||||
/**
|
||||
* Constructs a mapping of supported target names to lambdas. The lambdas should instantiate and return an
|
||||
* instance to the appropriate Target class.
|
||||
* Constructs a Target instance from a BriefTargetDescriptor object.
|
||||
*
|
||||
* @param targetBrief
|
||||
* @return
|
||||
*/
|
||||
std::map<std::string, std::function<std::unique_ptr<Targets::Target>(const TargetConfig&)>> getSupportedTargets();
|
||||
std::unique_ptr<Targets::Target> constructTargetFromBrief(
|
||||
const Targets::TargetDescription::GeneratedMapping::BriefTargetDescriptor& targetBrief
|
||||
);
|
||||
|
||||
/**
|
||||
* Processes any pending commands in the queue.
|
||||
|
||||
@@ -10,4 +10,5 @@ target_sources(
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Microchip/AVR/AVR8/TargetDescription/TargetDescriptionFile.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/Microchip/AVR/AVR8/OpcodeDecoder/Decoder.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/RiscV/RiscV.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/RiscV/TargetDescription/TargetDescriptionFile.cpp
|
||||
)
|
||||
|
||||
@@ -18,9 +18,9 @@ namespace Targets::Microchip::Avr::Avr8Bit
|
||||
{
|
||||
using namespace Exceptions;
|
||||
|
||||
Avr8::Avr8(const TargetConfig& targetConfig)
|
||||
Avr8::Avr8(const TargetConfig& targetConfig, TargetDescription::TargetDescriptionFile&& targetDescriptionFile)
|
||||
: targetConfig(Avr8TargetConfig(targetConfig))
|
||||
, targetDescriptionFile(TargetDescription::TargetDescriptionFile(this->targetConfig.name))
|
||||
, targetDescriptionFile(std::move(targetDescriptionFile))
|
||||
, signature(this->targetDescriptionFile.getTargetSignature())
|
||||
, name(this->targetDescriptionFile.getTargetName())
|
||||
, family(this->targetDescriptionFile.getAvrFamily())
|
||||
|
||||
@@ -30,7 +30,10 @@ namespace Targets::Microchip::Avr::Avr8Bit
|
||||
class Avr8: public Target
|
||||
{
|
||||
public:
|
||||
explicit Avr8(const TargetConfig& targetConfig);
|
||||
explicit Avr8(
|
||||
const TargetConfig& targetConfig,
|
||||
TargetDescription::TargetDescriptionFile&& targetDescriptionFile
|
||||
);
|
||||
|
||||
/*
|
||||
* The functions below implement the Target interface for AVR8 targets.
|
||||
|
||||
@@ -1,9 +1,5 @@
|
||||
#include "TargetDescriptionFile.hpp"
|
||||
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonArray>
|
||||
#include <QJsonObject>
|
||||
|
||||
#include "src/Services/PathService.hpp"
|
||||
#include "src/Logger/Logger.hpp"
|
||||
|
||||
@@ -22,54 +18,15 @@ namespace Targets::Microchip::Avr::Avr8Bit::TargetDescription
|
||||
using Targets::TargetVariant;
|
||||
using Targets::TargetRegisterDescriptor;
|
||||
|
||||
TargetDescriptionFile::TargetDescriptionFile(const std::string& targetName) {
|
||||
const auto mapping = TargetDescriptionFile::getTargetDescriptionMapping();
|
||||
const auto descriptionFileObjectIt = mapping.find(QString::fromStdString(targetName).toLower());
|
||||
|
||||
if (descriptionFileObjectIt == mapping.end()) {
|
||||
throw Exception(
|
||||
"Failed to resolve target description file for target \"" + targetName + "\" - unknown target name."
|
||||
);
|
||||
}
|
||||
|
||||
const auto descriptionFileObject = descriptionFileObjectIt.value().toObject();
|
||||
const auto descriptionFilePath = QString::fromStdString(
|
||||
Services::PathService::resourcesDirPath()) + "/" + descriptionFileObject.find("tdfPath")->toString();
|
||||
|
||||
Logger::debug("Loading AVR8 target description file: " + descriptionFilePath.toStdString());
|
||||
|
||||
Targets::TargetDescription::TargetDescriptionFile::init(descriptionFilePath);
|
||||
}
|
||||
|
||||
void TargetDescriptionFile::init(const QDomDocument& document) {
|
||||
Targets::TargetDescription::TargetDescriptionFile::init(document);
|
||||
|
||||
const auto device = document.elementsByTagName("device").item(0).toElement();
|
||||
if (!device.isElement()) {
|
||||
throw TargetDescriptionParsingFailureException("Device element not found.");
|
||||
}
|
||||
|
||||
this->avrFamilyName = device.attributes().namedItem("avr-family").nodeValue().toLower().toStdString();
|
||||
|
||||
TargetDescriptionFile::TargetDescriptionFile(const std::string& xmlFilePath)
|
||||
: Targets::TargetDescription::TargetDescriptionFile(xmlFilePath)
|
||||
{
|
||||
this->loadSupportedPhysicalInterfaces();
|
||||
this->loadPadDescriptors();
|
||||
this->loadTargetVariants();
|
||||
this->loadTargetRegisterDescriptors();
|
||||
}
|
||||
|
||||
QJsonObject TargetDescriptionFile::getTargetDescriptionMapping() {
|
||||
auto mappingFile = QFile(
|
||||
QString::fromStdString(Services::PathService::resourcesDirPath() + "/TargetDescriptionFiles/AVR/Mapping.json")
|
||||
);
|
||||
|
||||
if (!mappingFile.exists()) {
|
||||
throw Exception("Failed to load AVR target description mapping - mapping file not found");
|
||||
}
|
||||
|
||||
mappingFile.open(QIODevice::ReadOnly);
|
||||
return QJsonDocument::fromJson(mappingFile.readAll()).object();
|
||||
}
|
||||
|
||||
TargetSignature TargetDescriptionFile::getTargetSignature() const {
|
||||
const auto& propertyGroups = this->propertyGroupsMappedByName;
|
||||
|
||||
@@ -110,11 +67,9 @@ namespace Targets::Microchip::Avr::Avr8Bit::TargetDescription
|
||||
Family TargetDescriptionFile::getAvrFamily() const {
|
||||
static const auto targetFamiliesByName = TargetDescriptionFile::getFamilyNameToEnumMapping();
|
||||
|
||||
if (this->avrFamilyName.empty()) {
|
||||
throw Exception("Could not find target family name in target description file.");
|
||||
}
|
||||
|
||||
const auto familyIt = targetFamiliesByName.find(this->avrFamilyName);
|
||||
const auto familyIt = targetFamiliesByName.find(
|
||||
QString::fromStdString(this->deviceAttribute("avr-family")).toLower().toStdString()
|
||||
);
|
||||
|
||||
if (familyIt == targetFamiliesByName.end()) {
|
||||
throw Exception("Unknown family name in target description file.");
|
||||
|
||||
@@ -33,27 +33,13 @@ namespace Targets::Microchip::Avr::Avr8Bit::TargetDescription
|
||||
class TargetDescriptionFile: public Targets::TargetDescription::TargetDescriptionFile
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Will resolve the target description file using the target description JSON mapping and a given target name.
|
||||
*
|
||||
* @param targetName
|
||||
*/
|
||||
TargetDescriptionFile(const std::string& targetName);
|
||||
|
||||
/**
|
||||
* Extends TDF initialisation to include the loading of physical interfaces for debugging AVR8 targets, among
|
||||
* other things.
|
||||
*
|
||||
* @param xml
|
||||
*/
|
||||
void init(const QDomDocument& document) override;
|
||||
|
||||
/**
|
||||
* Loads the AVR8 target description JSON mapping file.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
static QJsonObject getTargetDescriptionMapping();
|
||||
explicit TargetDescriptionFile(const std::string& xmlFilePath);
|
||||
|
||||
/**
|
||||
* Extracts the AVR8 target signature from the TDF.
|
||||
|
||||
@@ -27,8 +27,11 @@ namespace Targets::RiscV
|
||||
using DebugModule::Registers::AbstractControlStatusRegister;
|
||||
using DebugModule::Registers::AbstractCommandRegister;
|
||||
|
||||
RiscV::RiscV(const TargetConfig& targetConfig)
|
||||
: name("CH32X035C8T6") // TODO: TDF
|
||||
RiscV::RiscV(
|
||||
const TargetConfig& targetConfig,
|
||||
TargetDescription::TargetDescriptionFile&& targetDescriptionFile
|
||||
)
|
||||
: targetDescriptionFile(targetDescriptionFile)
|
||||
, stackPointerRegisterDescriptor(
|
||||
RiscVRegisterDescriptor(
|
||||
TargetRegisterType::STACK_POINTER,
|
||||
@@ -107,10 +110,10 @@ namespace Targets::RiscV
|
||||
|
||||
TargetDescriptor RiscV::getDescriptor() {
|
||||
return TargetDescriptor(
|
||||
"TDF ID",
|
||||
this->targetDescriptionFile.getTargetId(),
|
||||
TargetFamily::RISC_V,
|
||||
this->name,
|
||||
"TDF VENDOR NAME",
|
||||
this->targetDescriptionFile.getTargetName(),
|
||||
this->targetDescriptionFile.getVendorName(),
|
||||
{
|
||||
{
|
||||
Targets::TargetMemoryType::FLASH,
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
#include "src/Targets/Target.hpp"
|
||||
#include "src/DebugToolDrivers/DebugTool.hpp"
|
||||
|
||||
#include "TargetDescription/TargetDescriptionFile.hpp"
|
||||
|
||||
#include "src/DebugToolDrivers/TargetInterfaces/RiscV/RiscVDebugInterface.hpp"
|
||||
#include "src/DebugToolDrivers/TargetInterfaces/RiscV/RiscVProgramInterface.hpp"
|
||||
|
||||
@@ -27,7 +29,10 @@ namespace Targets::RiscV
|
||||
class RiscV: public Target
|
||||
{
|
||||
public:
|
||||
explicit RiscV(const TargetConfig& targetConfig);
|
||||
explicit RiscV(
|
||||
const TargetConfig& targetConfig,
|
||||
TargetDescription::TargetDescriptionFile&& targetDescriptionFile
|
||||
);
|
||||
|
||||
/*
|
||||
* The functions below implement the Target interface for RISC-V targets.
|
||||
@@ -99,7 +104,8 @@ namespace Targets::RiscV
|
||||
bool programmingModeEnabled() override;
|
||||
|
||||
protected:
|
||||
std::string name;
|
||||
TargetDescription::TargetDescriptionFile targetDescriptionFile;
|
||||
|
||||
std::map<TargetRegisterDescriptorId, RiscVRegisterDescriptor> registerDescriptorsById;
|
||||
|
||||
RiscVRegisterDescriptor stackPointerRegisterDescriptor;
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
#include "TargetDescriptionFile.hpp"
|
||||
|
||||
#include <QString>
|
||||
|
||||
namespace Targets::RiscV::TargetDescription
|
||||
{
|
||||
TargetDescriptionFile::TargetDescriptionFile(const std::string& xmlFilePath)
|
||||
: Targets::TargetDescription::TargetDescriptionFile(xmlFilePath)
|
||||
{}
|
||||
|
||||
std::string TargetDescriptionFile::getTargetId() const {
|
||||
return this->deviceAttribute("id");
|
||||
}
|
||||
|
||||
std::string TargetDescriptionFile::getVendorName() const {
|
||||
return this->deviceAttribute("vendor");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
#pragma once
|
||||
|
||||
#include "src/Targets/TargetDescription/TargetDescriptionFile.hpp"
|
||||
|
||||
#include "src/Targets/RiscV/RiscVGeneric.hpp"
|
||||
|
||||
namespace Targets::RiscV::TargetDescription
|
||||
{
|
||||
/**
|
||||
* Represents an RISC-V TDF.
|
||||
*
|
||||
* For more information of TDFs, see src/Targets/TargetDescription/README.md
|
||||
*/
|
||||
class TargetDescriptionFile: public Targets::TargetDescription::TargetDescriptionFile
|
||||
{
|
||||
public:
|
||||
explicit TargetDescriptionFile(const std::string& xmlFilePath);
|
||||
|
||||
/**
|
||||
* Returns the RISC-V target ID from the TDF.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
[[nodiscard]] std::string getTargetId() const;
|
||||
|
||||
/**
|
||||
* Returns the RISC-V vendor name from the TDF.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
[[nodiscard]] std::string getVendorName() const;
|
||||
};
|
||||
}
|
||||
@@ -15,7 +15,7 @@ namespace Targets::TargetDescription
|
||||
return GeneratedMapping::map;
|
||||
}
|
||||
|
||||
TargetDescriptionFile::TargetDescriptionFile(const QString& xmlFilePath) {
|
||||
TargetDescriptionFile::TargetDescriptionFile(const std::string& xmlFilePath) {
|
||||
this->init(xmlFilePath);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Targets::TargetDescription
|
||||
}
|
||||
|
||||
const std::string& TargetDescriptionFile::getTargetName() const {
|
||||
return this->targetName;
|
||||
return this->deviceAttribute("name");
|
||||
}
|
||||
|
||||
TargetFamily TargetDescriptionFile::getFamily() const {
|
||||
@@ -33,7 +33,7 @@ namespace Targets::TargetDescription
|
||||
{"RISCV", TargetFamily::RISC_V},
|
||||
};
|
||||
|
||||
const auto familyIt = familiesByName.find(this->familyName);
|
||||
const auto familyIt = familiesByName.find(this->deviceAttribute("family"));
|
||||
|
||||
if (familyIt == familiesByName.end()) {
|
||||
throw Exception("Failed to resolve target family - invalid family name");
|
||||
@@ -42,8 +42,8 @@ namespace Targets::TargetDescription
|
||||
return familyIt->second;
|
||||
}
|
||||
|
||||
void TargetDescriptionFile::init(const QString& xmlFilePath) {
|
||||
auto file = QFile(xmlFilePath);
|
||||
void TargetDescriptionFile::init(const std::string& xmlFilePath) {
|
||||
auto file = QFile(QString::fromStdString(xmlFilePath));
|
||||
if (!file.exists()) {
|
||||
// This can happen if someone has been messing with the Resources directory.
|
||||
throw Exception("Failed to load target description file - file not found");
|
||||
@@ -65,8 +65,16 @@ namespace Targets::TargetDescription
|
||||
throw TargetDescriptionParsingFailureException("Device element not found.");
|
||||
}
|
||||
|
||||
this->targetName = device.attributes().namedItem("name").nodeValue().toStdString();
|
||||
this->familyName = device.attributes().namedItem("family").nodeValue().toLower().toStdString();
|
||||
const auto deviceAttributes = device.attributes();
|
||||
for (auto i = 0; i < deviceAttributes.length(); ++i) {
|
||||
const auto deviceAttribute = deviceAttributes.item(i);
|
||||
this->deviceAttributesByName.insert(
|
||||
std::pair(
|
||||
deviceAttribute.nodeName().toStdString(),
|
||||
deviceAttribute.nodeValue().toStdString()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
this->loadAddressSpaces(document);
|
||||
this->loadPropertyGroups(document);
|
||||
@@ -306,6 +314,16 @@ namespace Targets::TargetDescription
|
||||
return bitField;
|
||||
}
|
||||
|
||||
const std::string& TargetDescriptionFile::deviceAttribute(const std::string& attributeName) const {
|
||||
const auto attributeIt = this->deviceAttributesByName.find(attributeName);
|
||||
|
||||
if (attributeIt == this->deviceAttributesByName.end()) {
|
||||
throw Exception("Missing target device attribute (\"" + attributeName + "\")");
|
||||
}
|
||||
|
||||
return attributeIt->second;
|
||||
}
|
||||
|
||||
void TargetDescriptionFile::loadAddressSpaces(const QDomDocument& document) {
|
||||
const auto deviceElement = document.elementsByTagName("device").item(0).toElement();
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ namespace Targets::TargetDescription
|
||||
*
|
||||
* @param xmlFilePath
|
||||
*/
|
||||
explicit TargetDescriptionFile(const QString& xmlFilePath);
|
||||
explicit TargetDescriptionFile(const std::string& xmlFilePath);
|
||||
|
||||
/**
|
||||
* Will construct a TargetDescriptionFile instance from pre-loaded XML.
|
||||
@@ -83,9 +83,7 @@ namespace Targets::TargetDescription
|
||||
[[nodiscard]] TargetFamily getFamily() const;
|
||||
|
||||
protected:
|
||||
std::string targetName;
|
||||
std::string familyName;
|
||||
|
||||
std::map<std::string, std::string> deviceAttributesByName;
|
||||
std::map<std::string, AddressSpace> addressSpacesMappedById;
|
||||
std::map<std::string, PropertyGroup> propertyGroupsMappedByName;
|
||||
std::map<std::string, Module> modulesMappedByName;
|
||||
@@ -104,8 +102,8 @@ namespace Targets::TargetDescription
|
||||
TargetDescriptionFile& operator = (const TargetDescriptionFile& other) = default;
|
||||
TargetDescriptionFile& operator = (TargetDescriptionFile&& other) = default;
|
||||
|
||||
virtual void init(const QDomDocument& document);
|
||||
void init(const QString& xmlFilePath);
|
||||
void init(const std::string& xmlFilePath);
|
||||
void init(const QDomDocument& document);
|
||||
|
||||
/**
|
||||
* Constructs an AddressSpace object from an XML element.
|
||||
@@ -147,6 +145,14 @@ namespace Targets::TargetDescription
|
||||
*/
|
||||
static BitField bitFieldFromXml(const QDomElement& xmlElement);
|
||||
|
||||
/**
|
||||
* Fetches a device attribute value by name. Throws an exception if the attribute is not found.
|
||||
*
|
||||
* @param attributeName
|
||||
* @return
|
||||
*/
|
||||
const std::string& deviceAttribute(const std::string& attributeName) const;
|
||||
|
||||
/**
|
||||
* Extracts all address spaces and loads them into this->addressSpacesMappedById.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user