diff --git a/src/TargetController/TargetControllerComponent.cpp b/src/TargetController/TargetControllerComponent.cpp index c411c2ea..04d6fe4e 100644 --- a/src/TargetController/TargetControllerComponent.cpp +++ b/src/TargetController/TargetControllerComponent.cpp @@ -5,7 +5,7 @@ #include #include "src/Targets/Microchip/AVR8/TargetDescriptionFile.hpp" -#include "src/Targets/RiscV/TargetDescriptionFile.hpp" +#include "src/Targets/RiscV/Wch/TargetDescriptionFile.hpp" #include "Responses/Error.hpp" @@ -393,9 +393,15 @@ namespace TargetController } if (briefDescriptor.family == TargetFamily::RISC_V) { - return std::make_unique( + /* + * Given that WCH targets are the only RISC-V targets we support ATM, we can just assume that + * construction of a WchRiscV object is necessary. + * + * TODO: Review later + */ + return std::make_unique( this->environmentConfig.targetConfig, - RiscV::TargetDescriptionFile{ + RiscV::Wch::TargetDescriptionFile{ PathService::targetDescriptionFilesDirPath() + "/" + briefDescriptor.relativeTdfPath } ); diff --git a/src/Targets/CMakeLists.txt b/src/Targets/CMakeLists.txt index d2ce60dc..d5335f33 100755 --- a/src/Targets/CMakeLists.txt +++ b/src/Targets/CMakeLists.txt @@ -24,4 +24,6 @@ target_sources( ${CMAKE_CURRENT_SOURCE_DIR}/RiscV/RiscV.cpp ${CMAKE_CURRENT_SOURCE_DIR}/RiscV/RiscVTargetConfig.cpp ${CMAKE_CURRENT_SOURCE_DIR}/RiscV/TargetDescriptionFile.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/RiscV/Wch/WchRiscV.cpp + ${CMAKE_CURRENT_SOURCE_DIR}/RiscV/Wch/TargetDescriptionFile.cpp ) diff --git a/src/Targets/RiscV/RiscV.cpp b/src/Targets/RiscV/RiscV.cpp index 3a3b1db3..db5a4e1a 100644 --- a/src/Targets/RiscV/RiscV.cpp +++ b/src/Targets/RiscV/RiscV.cpp @@ -16,10 +16,10 @@ namespace Targets::RiscV { RiscV::RiscV( const TargetConfig& targetConfig, - TargetDescriptionFile&& targetDescriptionFile + const TargetDescriptionFile& targetDescriptionFile ) : targetConfig(RiscVTargetConfig{targetConfig}) - , targetDescriptionFile(std::move(targetDescriptionFile)) + , targetDescriptionFile(targetDescriptionFile) , cpuRegisterAddressSpaceDescriptor(RiscV::generateCpuRegisterAddressSpaceDescriptor()) , csrMemorySegmentDescriptor(this->cpuRegisterAddressSpaceDescriptor.getMemorySegmentDescriptor("cs_registers")) , gprMemorySegmentDescriptor(this->cpuRegisterAddressSpaceDescriptor.getMemorySegmentDescriptor("gp_registers")) @@ -58,15 +58,6 @@ namespace Targets::RiscV void RiscV::activate() { this->riscVDebugInterface->activate(); - - const auto deviceId = this->riscVIdInterface->getDeviceId(); - const auto tdfDeviceId = this->targetDescriptionFile.getTargetId(); - if (deviceId != tdfDeviceId) { - throw Exceptions::InvalidConfig{ - "RISC-V target ID mismatch - expected " + tdfDeviceId + " but got " + deviceId + - ". Please check target configuration." - }; - } } void RiscV::deactivate() { @@ -82,39 +73,7 @@ namespace Targets::RiscV } void RiscV::postActivate() { - Logger::info("WCH target ID: " + this->riscVIdInterface->getDeviceId()); - } - - TargetDescriptor RiscV::targetDescriptor() { - auto descriptor = TargetDescriptor{ - this->targetDescriptionFile.getName(), - this->targetDescriptionFile.getFamily(), - this->targetDescriptionFile.getTargetId(), - this->targetDescriptionFile.getVendorName(), - this->targetDescriptionFile.targetAddressSpaceDescriptorsByKey(), - this->targetDescriptionFile.targetPeripheralDescriptorsByKey(), - this->targetDescriptionFile.targetPadDescriptorsByKey(), - this->targetDescriptionFile.targetPinoutDescriptorsByKey(), - this->targetDescriptionFile.targetVariantDescriptorsByKey(), - BreakpointResources{ - this->riscVDebugInterface->getHardwareBreakpointCount(), - std::nullopt, - static_cast(this->targetConfig.reserveSteppingBreakpoint ? 1 : 0) - } - }; - - // Copy the RISC-V CPU register address space and peripheral descriptor - descriptor.addressSpaceDescriptorsByKey.emplace( - this->cpuRegisterAddressSpaceDescriptor.key, - this->cpuRegisterAddressSpaceDescriptor.clone() - ); - - descriptor.peripheralDescriptorsByKey.emplace( - this->cpuPeripheralDescriptor.key, - this->cpuPeripheralDescriptor.clone() - ); - - return descriptor; + // Nothing to do here, for now. } void RiscV::run(std::optional toAddress) { diff --git a/src/Targets/RiscV/RiscV.hpp b/src/Targets/RiscV/RiscV.hpp index 56644e22..b42f6130 100644 --- a/src/Targets/RiscV/RiscV.hpp +++ b/src/Targets/RiscV/RiscV.hpp @@ -19,7 +19,7 @@ namespace Targets::RiscV class RiscV: public Target { public: - RiscV(const TargetConfig& targetConfig, TargetDescriptionFile&& targetDescriptionFile); + RiscV(const TargetConfig& targetConfig, const TargetDescriptionFile& targetDescriptionFile); /* * The functions below implement the Target interface for RISC-V targets. @@ -36,8 +36,6 @@ namespace Targets::RiscV void postActivate() override; - TargetDescriptor targetDescriptor() override; - void run(std::optional toAddress = std::nullopt) override; void stop() override; void step() override; diff --git a/src/Targets/RiscV/TargetDescriptionFile.cpp b/src/Targets/RiscV/TargetDescriptionFile.cpp index 97dfc9e2..fc75ff1a 100644 --- a/src/Targets/RiscV/TargetDescriptionFile.cpp +++ b/src/Targets/RiscV/TargetDescriptionFile.cpp @@ -6,10 +6,6 @@ namespace Targets::RiscV : Targets::TargetDescription::TargetDescriptionFile(xmlFilePath) {} - std::string TargetDescriptionFile::getTargetId() const { - return this->getProperty("vendor", "target_id").value; - } - TargetAddressSpaceDescriptor TargetDescriptionFile::getSystemAddressSpaceDescriptor() const { return this->targetAddressSpaceDescriptorFromAddressSpace(this->getAddressSpace("system")); } diff --git a/src/Targets/RiscV/TargetDescriptionFile.hpp b/src/Targets/RiscV/TargetDescriptionFile.hpp index e1b02dee..34ee26b6 100644 --- a/src/Targets/RiscV/TargetDescriptionFile.hpp +++ b/src/Targets/RiscV/TargetDescriptionFile.hpp @@ -14,13 +14,6 @@ namespace Targets::RiscV public: explicit TargetDescriptionFile(const std::string& xmlFilePath); - /** - * Returns the RISC-V target ID from the TDF. - * - * @return - */ - [[nodiscard]] std::string getTargetId() const; - [[nodiscard]] TargetAddressSpaceDescriptor getSystemAddressSpaceDescriptor() const; }; } diff --git a/src/Targets/RiscV/Wch/TargetDescriptionFile.cpp b/src/Targets/RiscV/Wch/TargetDescriptionFile.cpp new file mode 100644 index 00000000..1b225d0b --- /dev/null +++ b/src/Targets/RiscV/Wch/TargetDescriptionFile.cpp @@ -0,0 +1,21 @@ +#include "TargetDescriptionFile.hpp" + +namespace Targets::RiscV::Wch +{ + TargetDescriptionFile::TargetDescriptionFile(const std::string& xmlFilePath) + : Targets::RiscV::TargetDescriptionFile(xmlFilePath) + {} + + std::map< + std::string, + const Targets::TargetDescription::Variant* + > TargetDescriptionFile::getVariantsByWchVariantId() { + auto output = std::map{}; + + for (const auto& [variantKey, variant] : this->variantsByKey) { + output.emplace(variant.getProperty("vendor", "variant_id").value, &variant); + } + + return output; + } +} diff --git a/src/Targets/RiscV/Wch/TargetDescriptionFile.hpp b/src/Targets/RiscV/Wch/TargetDescriptionFile.hpp new file mode 100644 index 00000000..d2d53016 --- /dev/null +++ b/src/Targets/RiscV/Wch/TargetDescriptionFile.hpp @@ -0,0 +1,17 @@ +#pragma once + +#include + +#include "src/Targets/RiscV/TargetDescriptionFile.hpp" +#include "src/Targets/TargetDescription/Variant.hpp" + +namespace Targets::RiscV::Wch +{ + class TargetDescriptionFile: public Targets::RiscV::TargetDescriptionFile + { + public: + explicit TargetDescriptionFile(const std::string& xmlFilePath); + + std::map getVariantsByWchVariantId(); + }; +} diff --git a/src/Targets/RiscV/Wch/WchRiscV.cpp b/src/Targets/RiscV/Wch/WchRiscV.cpp new file mode 100644 index 00000000..102120d5 --- /dev/null +++ b/src/Targets/RiscV/Wch/WchRiscV.cpp @@ -0,0 +1,84 @@ +#include "WchRiscV.hpp" + +#include +#include + +#include "src/Logger/Logger.hpp" +#include "src/Exceptions/InvalidConfig.hpp" + +namespace Targets::RiscV::Wch +{ + WchRiscV::WchRiscV( + const TargetConfig& targetConfig, + TargetDescriptionFile&& targetDescriptionFile + ) + : RiscV(targetConfig, targetDescriptionFile) + , targetDescriptionFile(std::move(targetDescriptionFile)) + {} + + void WchRiscV::activate() { + RiscV::activate(); + + /* + * WCH target IDs are specific to the variant. Each variant in the TDF should have a property group that holds + * the variant ID. + */ + const auto variantsById = this->targetDescriptionFile.getVariantsByWchVariantId(); + const auto deviceId = this->riscVIdInterface->getDeviceId(); + + const auto variantIt = variantsById.find(deviceId); + if (variantIt == variantsById.end()) { + throw Exceptions::InvalidConfig{ + "Unknown WCH variant ID \"" + deviceId + "\". Please check your configuration." + }; + } + + this->variant = *(variantIt->second); + } + + void WchRiscV::postActivate() { + assert(this->variant.has_value()); + + const auto& variant = this->variant->get(); + Logger::info("WCH variant ID: " + variant.getProperty("vendor", "variant_id").value); + Logger::info("WCH variant name: " + variant.name); + + RiscV::postActivate(); + } + + TargetDescriptor WchRiscV::targetDescriptor() { + auto descriptor = TargetDescriptor{ + this->targetDescriptionFile.getName(), + this->targetDescriptionFile.getFamily(), + this->variant->get().getProperty("vendor", "variant_id").value, + this->targetDescriptionFile.getVendorName(), + this->targetDescriptionFile.targetAddressSpaceDescriptorsByKey(), + this->targetDescriptionFile.targetPeripheralDescriptorsByKey(), + this->targetDescriptionFile.targetPadDescriptorsByKey(), + this->targetDescriptionFile.targetPinoutDescriptorsByKey(), + this->targetDescriptionFile.targetVariantDescriptorsByKey(), + BreakpointResources{ + this->riscVDebugInterface->getHardwareBreakpointCount(), + std::nullopt, + static_cast(this->targetConfig.reserveSteppingBreakpoint ? 1 : 0) + } + }; + + // Copy the RISC-V CPU register address space and peripheral descriptor + descriptor.addressSpaceDescriptorsByKey.emplace( + this->cpuRegisterAddressSpaceDescriptor.key, + this->cpuRegisterAddressSpaceDescriptor.clone() + ); + + descriptor.peripheralDescriptorsByKey.emplace( + this->cpuPeripheralDescriptor.key, + this->cpuPeripheralDescriptor.clone() + ); + + auto& sysAddressSpaceDescriptor = descriptor.getAddressSpaceDescriptor("system"); + sysAddressSpaceDescriptor.getMemorySegmentDescriptor("internal_program_memory").inspectionEnabled = true; + sysAddressSpaceDescriptor.getMemorySegmentDescriptor("internal_ram").inspectionEnabled = true; + + return descriptor; + } +} diff --git a/src/Targets/RiscV/Wch/WchRiscV.hpp b/src/Targets/RiscV/Wch/WchRiscV.hpp new file mode 100644 index 00000000..753fce5d --- /dev/null +++ b/src/Targets/RiscV/Wch/WchRiscV.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include +#include +#include + +#include "src/Targets/RiscV/RiscV.hpp" + +#include "TargetDescriptionFile.hpp" + +namespace Targets::RiscV::Wch +{ +class WchRiscV: public ::Targets::RiscV::RiscV + { + public: + WchRiscV(const TargetConfig& targetConfig, TargetDescriptionFile&& targetDescriptionFile); + + void activate() override; + void postActivate() override; + TargetDescriptor targetDescriptor() override; + + protected: + TargetDescriptionFile targetDescriptionFile; + std::optional> variant = std::nullopt; + }; +} diff --git a/src/Targets/Targets.hpp b/src/Targets/Targets.hpp index 22d2e792..75778076 100644 --- a/src/Targets/Targets.hpp +++ b/src/Targets/Targets.hpp @@ -2,4 +2,4 @@ #include "src/Targets/Target.hpp" #include "src/Targets/Microchip/AVR8/Avr8.hpp" -#include "src/Targets/RiscV/RiscV.hpp" +#include "src/Targets/RiscV/Wch/WchRiscV.hpp"