Renamed part description files to target description files.
Introduced a generic target description file class with an AVR8 derivation. Moved AVR8 target description files
This commit is contained in:
@@ -0,0 +1,148 @@
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonArray>
|
||||
|
||||
#include "TargetDescriptionFile.hpp"
|
||||
#include "src/Exceptions/Exception.hpp"
|
||||
#include "src/Targets/TargetDescription/Exceptions/TargetDescriptionParsingFailureException.hpp"
|
||||
#include "src/Logger/Logger.hpp"
|
||||
#include "src/Helpers/Paths.hpp"
|
||||
|
||||
using namespace Bloom::Targets::Microchip::Avr::Avr8Bit::TargetDescription;
|
||||
using namespace Bloom::Targets::Microchip::Avr::Avr8Bit;
|
||||
using namespace Bloom::Targets::Microchip::Avr;
|
||||
using namespace Bloom::Exceptions;
|
||||
|
||||
TargetDescriptionFile::TargetDescriptionFile(
|
||||
const std::string& targetSignatureHex,
|
||||
std::optional<std::string> targetName
|
||||
) {
|
||||
auto mapping = this->getTargetDescriptionMapping();
|
||||
auto qTargetSignatureHex = QString::fromStdString(targetSignatureHex);
|
||||
|
||||
if (mapping.contains(qTargetSignatureHex)) {
|
||||
// We have a match for the target signature.
|
||||
auto descriptionFilesJsonArray = mapping.find(qTargetSignatureHex).value().toArray();
|
||||
auto matchingDescriptionFiles = std::vector<QJsonValue>();
|
||||
std::copy_if(
|
||||
descriptionFilesJsonArray.begin(),
|
||||
descriptionFilesJsonArray.end(),
|
||||
std::back_inserter(matchingDescriptionFiles),
|
||||
[&targetName] (const QJsonValue& value) {
|
||||
auto pdTargetName = value.toObject().find("targetName")->toString().toLower().toStdString();
|
||||
return !targetName.has_value() || (targetName.has_value() && targetName.value() == pdTargetName);
|
||||
}
|
||||
);
|
||||
|
||||
if (targetName.has_value() && matchingDescriptionFiles.empty()) {
|
||||
throw Exception("Failed to resolve target description file for target \"" + targetName.value()
|
||||
+ "\" - target signature \"" + targetSignatureHex + "\" does not belong to target with name \"" +
|
||||
targetName.value() + "\". Please review your bloom.json configuration.");
|
||||
}
|
||||
|
||||
if (matchingDescriptionFiles.size() == 1) {
|
||||
// Attempt to load the XML target description file
|
||||
auto descriptionFilePath = QString::fromStdString(Paths::applicationDirPath()) + "/"
|
||||
+ matchingDescriptionFiles.front().toObject().find("targetDescriptionFilePath")->toString();
|
||||
|
||||
Logger::debug("Loading AVR8 target description file: " + descriptionFilePath.toStdString());
|
||||
this->init(descriptionFilePath);
|
||||
|
||||
} else if (matchingDescriptionFiles.size() > 1) {
|
||||
/*
|
||||
* There are numerous target description files mapped to this target signature. There's really not
|
||||
* much we can do at this point, so we'll just instruct the user to use a more specific target name.
|
||||
*/
|
||||
QStringList targetNames;
|
||||
std::transform(
|
||||
matchingDescriptionFiles.begin(),
|
||||
matchingDescriptionFiles.end(),
|
||||
std::back_inserter(targetNames),
|
||||
[](const QJsonValue& descriptionFile) {
|
||||
return QString("\"" + descriptionFile.toObject().find("targetName")->toString().toLower() + "\"");
|
||||
}
|
||||
);
|
||||
|
||||
throw Exception("Failed to resolve target description file for target \""
|
||||
+ targetSignatureHex + "\" - ambiguous signature.\nThe signature is mapped to numerous targets: "
|
||||
+ targetNames.join(", ").toStdString() + ".\n\nPlease update the target name in your Bloom " +
|
||||
"configuration to one of the above."
|
||||
);
|
||||
|
||||
} else {
|
||||
throw Exception("Failed to resolve target description file for target \""
|
||||
+ targetSignatureHex + "\" - invalid AVR8 target description mapping."
|
||||
);
|
||||
}
|
||||
|
||||
} else {
|
||||
throw Exception("Failed to resolve target description file for target \""
|
||||
+ targetSignatureHex + "\" - unknown target signature.");
|
||||
}
|
||||
}
|
||||
|
||||
QJsonObject TargetDescriptionFile::getTargetDescriptionMapping() {
|
||||
auto mappingFile = QFile(
|
||||
QString::fromStdString(Paths::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 {
|
||||
auto propertyGroups = this->getPropertyGroupsMappedByName();
|
||||
auto signaturePropertyGroupIt = propertyGroups.find("signatures");
|
||||
|
||||
if (signaturePropertyGroupIt == propertyGroups.end()) {
|
||||
throw TargetDescriptionParsingFailureException("Signature property group not found");
|
||||
}
|
||||
|
||||
auto signaturePropertyGroup = signaturePropertyGroupIt->second;
|
||||
auto& signatureProperties = signaturePropertyGroup.propertiesMappedByName;
|
||||
std::optional<unsigned char> signatureByteZero;
|
||||
std::optional<unsigned char> signatureByteOne;
|
||||
std::optional<unsigned char> signatureByteTwo;
|
||||
|
||||
if (signatureProperties.find("signature0") != signatureProperties.end()) {
|
||||
signatureByteZero = static_cast<unsigned char>(
|
||||
signatureProperties.find("signature0")->second.value.toShort(nullptr, 16)
|
||||
);
|
||||
}
|
||||
|
||||
if (signatureProperties.find("signature1") != signatureProperties.end()) {
|
||||
signatureByteOne = static_cast<unsigned char>(
|
||||
signatureProperties.find("signature1")->second.value.toShort(nullptr, 16)
|
||||
);
|
||||
}
|
||||
|
||||
if (signatureProperties.find("signature2") != signatureProperties.end()) {
|
||||
signatureByteTwo = static_cast<unsigned char>(
|
||||
signatureProperties.find("signature2")->second.value.toShort(nullptr, 16)
|
||||
);
|
||||
}
|
||||
|
||||
if (signatureByteZero.has_value() && signatureByteOne.has_value() && signatureByteTwo.has_value()) {
|
||||
return TargetSignature(signatureByteZero.value(), signatureByteOne.value(), signatureByteTwo.value());
|
||||
}
|
||||
|
||||
throw TargetDescriptionParsingFailureException("Failed to extract target signature from AVR8 target description.");
|
||||
}
|
||||
|
||||
Family TargetDescriptionFile::getFamily() const {
|
||||
static auto familyNameToEnums = this->getFamilyNameToEnumMapping();
|
||||
auto familyName = this->deviceElement.attributes().namedItem("family").nodeValue().toLower().toStdString();
|
||||
|
||||
if (familyName.empty()) {
|
||||
throw Exception("Could not find target family name in target description file.");
|
||||
}
|
||||
|
||||
if (familyNameToEnums.find(familyName) == familyNameToEnums.end()) {
|
||||
throw Exception("Unknown family name in target description file.");
|
||||
}
|
||||
|
||||
return familyNameToEnums.find(familyName)->second;
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
#pragma once
|
||||
|
||||
#include "src/Targets/TargetDescription/TargetDescriptionFile.hpp"
|
||||
|
||||
#include "src/Targets/Microchip/AVR/TargetSignature.hpp"
|
||||
#include "src/Targets/Microchip/AVR/AVR8/Family.hpp"
|
||||
|
||||
namespace Bloom::Targets::Microchip::Avr::Avr8Bit::TargetDescription
|
||||
{
|
||||
/**
|
||||
* Represents an AVR8 TDF. See the Targets::TargetDescription::TargetDescriptionFile close for more on TDFs.
|
||||
*
|
||||
* During the build process, we generate a JSON file containing a mapping of AVR8 target signatures to target
|
||||
* description file paths. Bloom uses this mapping to find a particular target description file, for AVR8 targets,
|
||||
* given a target signature. See directory "build/resources/TargetPartDescriptions".
|
||||
* The generation of the JSON mapping, is done by a PHP script:
|
||||
* "build/scripts/CopyAvrPartFilesAndCreateMapping.php". This script is invoked via a custom command, at build time.
|
||||
*/
|
||||
class TargetDescriptionFile: public Targets::TargetDescription::TargetDescriptionFile
|
||||
{
|
||||
private:
|
||||
/**`
|
||||
* AVR8 target description files include the target family name. This method returns a mapping of part
|
||||
* description family name strings to Family enum values.
|
||||
*
|
||||
* TODO: the difference in AVR8 family variations, like "tinyAVR" and "tinyAVR 2" may require attention.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
static inline auto getFamilyNameToEnumMapping() {
|
||||
// All keys should be lower case.
|
||||
return std::map<std::string, Family> {
|
||||
{"megaavr", Family::MEGA},
|
||||
{"avr mega", Family::MEGA},
|
||||
{"avr xmega", Family::XMEGA},
|
||||
{"avr tiny", Family::TINY},
|
||||
{"tinyavr", Family::TINY},
|
||||
{"tinyavr 2", Family::TINY},
|
||||
};
|
||||
};
|
||||
|
||||
public:
|
||||
/**
|
||||
* Will resolve the target description file using the target description JSON mapping and a given target signature.
|
||||
*
|
||||
* @param targetSignatureHex
|
||||
* @param targetName
|
||||
*/
|
||||
TargetDescriptionFile(const std::string& targetSignatureHex, std::optional<std::string> targetName);
|
||||
|
||||
/**
|
||||
* Loads the AVR8 target description JSON mapping file.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
static QJsonObject getTargetDescriptionMapping();
|
||||
|
||||
/**
|
||||
* Extracts the AVR8 target signature from the target description XML.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
TargetSignature getTargetSignature() const;
|
||||
|
||||
/**
|
||||
* Extracts the AVR8 target family from the target description XML.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Family getFamily() const;
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user