From 12a7d58b59112c95b7c8532f24f2b9eae0b61efe Mon Sep 17 00:00:00 2001 From: Nav Date: Sat, 11 Sep 2021 20:39:31 +0100 Subject: [PATCH] Triggering a registers written event when a memory range that contains a register is written to. --- .../Events/RegistersWrittenToTarget.hpp | 3 + src/TargetController/TargetController.cpp | 124 +++++++++++++++++- src/TargetController/TargetController.hpp | 33 +++++ src/Targets/TargetMemory.hpp | 6 + 4 files changed, 161 insertions(+), 5 deletions(-) diff --git a/src/EventManager/Events/RegistersWrittenToTarget.hpp b/src/EventManager/Events/RegistersWrittenToTarget.hpp index cb57896b..b6bbae9a 100644 --- a/src/EventManager/Events/RegistersWrittenToTarget.hpp +++ b/src/EventManager/Events/RegistersWrittenToTarget.hpp @@ -3,6 +3,7 @@ #include #include "Event.hpp" +#include "src/Targets/TargetRegister.hpp" namespace Bloom::Events { @@ -12,6 +13,8 @@ namespace Bloom::Events static inline EventType type = EventType::REGISTERS_WRITTEN_TO_TARGET; static inline const std::string name = "RegistersWrittenToTarget"; + Targets::TargetRegisterDescriptors descriptors; + [[nodiscard]] EventType getType() const override { return RegistersWrittenToTarget::type; } diff --git a/src/TargetController/TargetController.cpp b/src/TargetController/TargetController.cpp index 1c8639f7..bed67445 100644 --- a/src/TargetController/TargetController.cpp +++ b/src/TargetController/TargetController.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include "src/Application.hpp" #include "src/Helpers/Paths.hpp" @@ -17,6 +18,9 @@ using namespace Bloom::Targets; using namespace Bloom::Events; using namespace Bloom::Exceptions; +using Bloom::Targets::TargetRegisterDescriptor; +using Bloom::Targets::TargetRegisterDescriptors; + void TargetController::run() { try { this->startup(); @@ -170,6 +174,8 @@ void TargetController::suspend() { this->lastTargetState = TargetState::UNKNOWN; this->cachedTargetDescriptor = std::nullopt; + this->registerDescriptorsByMemoryType.clear(); + this->registerAddressRangeByMemoryType.clear(); this->state = TargetControllerState::SUSPENDED; this->eventManager.triggerEvent( @@ -181,6 +187,7 @@ void TargetController::suspend() { void TargetController::resume() { this->acquireHardware(); + this->loadRegisterDescriptors(); this->eventListener->registerCallbackForEventType( std::bind(&TargetController::onDebugSessionFinishedEvent, this, std::placeholders::_1) @@ -252,6 +259,78 @@ void TargetController::resume() { } } +void TargetController::loadRegisterDescriptors() { + auto& targetDescriptor = this->getTargetDescriptor(); + + for (const auto& [registerType, registerDescriptors] : targetDescriptor.registerDescriptorsByType) { + for (const auto& registerDescriptor : registerDescriptors) { + auto startAddress = registerDescriptor.startAddress.value_or(0); + auto endAddress = startAddress + (registerDescriptor.size - 1); + + if (!this->registerAddressRangeByMemoryType.contains(registerDescriptor.memoryType)) { + auto addressRange = TargetMemoryAddressRange(); + addressRange.startAddress = startAddress; + addressRange.endAddress = endAddress; + this->registerAddressRangeByMemoryType.insert( + std::pair(registerDescriptor.memoryType, addressRange) + ); + + } else { + auto& addressRange = this->registerAddressRangeByMemoryType.at(registerDescriptor.memoryType); + + if (startAddress < addressRange.startAddress) { + addressRange.startAddress = startAddress; + } + + if (endAddress > addressRange.endAddress) { + addressRange.endAddress = endAddress; + } + } + + this->registerDescriptorsByMemoryType[registerDescriptor.memoryType].insert(registerDescriptor); + } + } +} + +TargetRegisterDescriptors TargetController::getRegisterDescriptorsWithinAddressRange( + std::uint32_t startAddress, + std::uint32_t endAddress, + Targets::TargetMemoryType memoryType +) { + auto output = TargetRegisterDescriptors(); + + if (this->registerAddressRangeByMemoryType.contains(memoryType) + && this->registerDescriptorsByMemoryType.contains(memoryType) + ) { + auto& registersAddressRange = this->registerAddressRangeByMemoryType.at(memoryType); + + if ( + (startAddress <= registersAddressRange.startAddress && endAddress >= registersAddressRange.startAddress) + || (startAddress <= registersAddressRange.endAddress && endAddress >= registersAddressRange.startAddress) + ) { + auto& registerDescriptors = this->registerDescriptorsByMemoryType.at(memoryType); + + for (const auto& registerDescriptor : registerDescriptors) { + if (!registerDescriptor.startAddress.has_value() || registerDescriptor.size < 1) { + continue; + } + + auto registerStartAddress = registerDescriptor.startAddress.value(); + auto registerEndAddress = registerStartAddress + registerDescriptor.size; + + if ( + (startAddress <= registerStartAddress && endAddress >= registerStartAddress) + || (startAddress <= registerEndAddress && endAddress >= registerStartAddress) + ) { + output.insert(registerDescriptor); + } + } + } + } + + return output; +} + void TargetController::acquireHardware() { auto debugToolName = this->environmentConfig.debugToolConfig.name; auto targetName = this->environmentConfig.targetConfig.name; @@ -364,6 +443,14 @@ void TargetController::emitErrorEvent(int correlationId) { this->eventManager.triggerEvent(errorEvent); } +Targets::TargetDescriptor& TargetController::getTargetDescriptor() { + if (!this->cachedTargetDescriptor.has_value()) { + this->cachedTargetDescriptor = this->target->getDescriptor(); + } + + return this->cachedTargetDescriptor.value(); +} + void TargetController::onShutdownTargetControllerEvent(const Events::ShutdownTargetController&) { this->shutdown(); } @@ -401,12 +488,8 @@ void TargetController::onDebugSessionFinishedEvent(const DebugSessionFinished&) } void TargetController::onExtractTargetDescriptor(const Events::ExtractTargetDescriptor& event) { - if (!this->cachedTargetDescriptor.has_value()) { - this->cachedTargetDescriptor = this->target->getDescriptor(); - } - auto targetDescriptorExtracted = std::make_shared(); - targetDescriptorExtracted->targetDescriptor = this->cachedTargetDescriptor.value(); + targetDescriptorExtracted->targetDescriptor = this->getTargetDescriptor(); targetDescriptorExtracted->correlationId = event.id; this->eventManager.triggerEvent(targetDescriptorExtracted); @@ -495,6 +578,16 @@ void TargetController::onWriteRegistersEvent(const Events::WriteRegistersToTarge auto registersWrittenEvent = std::make_shared(); registersWrittenEvent->correlationId = event.id; + + std::transform( + event.registers.begin(), + event.registers.end(), + std::inserter(registersWrittenEvent->descriptors, registersWrittenEvent->descriptors.begin()), + [] (const TargetRegister& targetRegister) { + return targetRegister.descriptor; + } + ); + this->eventManager.triggerEvent(registersWrittenEvent); } catch (const TargetOperationFailure& exception) { @@ -525,6 +618,27 @@ void TargetController::onWriteMemoryEvent(const Events::WriteMemoryToTarget& eve memoryWrittenEvent->correlationId = event.id; this->eventManager.triggerEvent(memoryWrittenEvent); + if (this->registerDescriptorsByMemoryType.contains(event.memoryType)) { + /* + * The memory type we just wrote to contains some number of registers - if we've written to any address + * that is known to store the value of a register, trigger a RegistersWrittenToTarget event + */ + auto registerDescriptors = this->getRegisterDescriptorsWithinAddressRange( + event.startAddress, + static_cast(event.startAddress + (event.buffer.size() - 1)), + event.memoryType + ); + + if (!registerDescriptors.empty()) { + auto registersWrittenEvent = std::make_shared(); + registersWrittenEvent->correlationId = event.id; + registersWrittenEvent->descriptors = registerDescriptors; + + this->eventManager.triggerEvent(registersWrittenEvent); + } + } + + // TODO: REMOVE THIS if (this->target->memoryAddressRangeClashesWithIoPortRegisters( event.memoryType, event.startAddress, diff --git a/src/TargetController/TargetController.hpp b/src/TargetController/TargetController.hpp index 6f4edd78..e8fbdbe9 100644 --- a/src/TargetController/TargetController.hpp +++ b/src/TargetController/TargetController.hpp @@ -13,6 +13,8 @@ #include "src/DebugToolDrivers/DebugTools.hpp" #include "src/Targets/Target.hpp" #include "src/Targets/Targets.hpp" +#include "src/Targets/TargetRegister.hpp" +#include "src/Targets/TargetMemory.hpp" #include "src/EventManager/EventManager.hpp" #include "src/EventManager/EventListener.hpp" @@ -65,6 +67,16 @@ namespace Bloom */ std::optional cachedTargetDescriptor; + /** + * Target register descriptors mapped by the memory type on which the register is stored. + */ + std::map registerDescriptorsByMemoryType; + + /** + * Memory address ranges for target registers, mapped by the register memory type. + */ + std::map registerAddressRangeByMemoryType; + /** * Constructs a mapping of supported debug tool names to lambdas. The lambdas should *only* instantiate * and return an instance to the derived DebugTool class. They should not attempt to establish @@ -210,6 +222,25 @@ namespace Bloom */ void resume(); + /** + * Extracts address ranges and groups target register descriptors. + */ + void loadRegisterDescriptors(); + + /** + * Resolves the descriptors of all target registers found within the given address range and memory type. + * + * @param startAddress + * @param endAddress + * @param memoryType + * @return + */ + Targets::TargetRegisterDescriptors getRegisterDescriptorsWithinAddressRange( + std::uint32_t startAddress, + std::uint32_t endAddress, + Targets::TargetMemoryType memoryType + ); + /** * Should fire any events queued on the target. */ @@ -223,6 +254,8 @@ namespace Bloom */ void emitErrorEvent(int correlationId); + Targets::TargetDescriptor& getTargetDescriptor(); + public: explicit TargetController(EventManager& eventManager): eventManager(eventManager) {}; diff --git a/src/Targets/TargetMemory.hpp b/src/Targets/TargetMemory.hpp index cbf050f8..e46c1d48 100644 --- a/src/Targets/TargetMemory.hpp +++ b/src/Targets/TargetMemory.hpp @@ -13,5 +13,11 @@ namespace Bloom::Targets OTHER, }; + struct TargetMemoryAddressRange + { + std::uint32_t startAddress = 0; + std::uint32_t endAddress = 0; + }; + using TargetMemoryBuffer = std::vector; }