Triggering a registers written event when a memory range that contains a register is written to.

This commit is contained in:
Nav
2021-09-11 20:39:31 +01:00
parent b8bf590be7
commit 12a7d58b59
4 changed files with 161 additions and 5 deletions

View File

@@ -3,6 +3,7 @@
#include <string>
#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;
}

View File

@@ -3,6 +3,7 @@
#include <thread>
#include <filesystem>
#include <typeindex>
#include <algorithm>
#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<Events::DebugSessionFinished>(
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>();
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<Events::RegistersWrittenToTarget>();
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<std::uint32_t>(event.startAddress + (event.buffer.size() - 1)),
event.memoryType
);
if (!registerDescriptors.empty()) {
auto registersWrittenEvent = std::make_shared<Events::RegistersWrittenToTarget>();
registersWrittenEvent->correlationId = event.id;
registersWrittenEvent->descriptors = registerDescriptors;
this->eventManager.triggerEvent(registersWrittenEvent);
}
}
// TODO: REMOVE THIS
if (this->target->memoryAddressRangeClashesWithIoPortRegisters(
event.memoryType,
event.startAddress,

View File

@@ -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<Targets::TargetDescriptor> cachedTargetDescriptor;
/**
* Target register descriptors mapped by the memory type on which the register is stored.
*/
std::map<Targets::TargetMemoryType, Targets::TargetRegisterDescriptors> registerDescriptorsByMemoryType;
/**
* Memory address ranges for target registers, mapped by the register memory type.
*/
std::map<Targets::TargetMemoryType, Targets::TargetMemoryAddressRange> 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) {};

View File

@@ -13,5 +13,11 @@ namespace Bloom::Targets
OTHER,
};
struct TargetMemoryAddressRange
{
std::uint32_t startAddress = 0;
std::uint32_t endAddress = 0;
};
using TargetMemoryBuffer = std::vector<unsigned char>;
}