2024-07-23 21:14:22 +01:00
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
#include <cstdint>
|
|
|
|
|
#include <string>
|
2024-10-06 17:54:08 +01:00
|
|
|
#include <vector>
|
2024-10-06 23:32:36 +01:00
|
|
|
#include <chrono>
|
2024-11-23 20:14:47 +00:00
|
|
|
#include <memory>
|
2024-10-06 17:54:08 +01:00
|
|
|
#include <unordered_map>
|
|
|
|
|
#include <unordered_set>
|
|
|
|
|
#include <optional>
|
|
|
|
|
#include <functional>
|
2024-07-23 21:14:22 +01:00
|
|
|
|
|
|
|
|
#include "src/DebugToolDrivers/TargetInterfaces/RiscV/RiscVDebugInterface.hpp"
|
|
|
|
|
|
|
|
|
|
#include "DebugTransportModuleInterface.hpp"
|
2024-10-06 23:32:36 +01:00
|
|
|
#include "DebugTranslatorConfig.hpp"
|
2024-11-23 20:14:47 +00:00
|
|
|
#include "DebugModuleDescriptor.hpp"
|
2024-07-23 21:14:22 +01:00
|
|
|
|
|
|
|
|
#include "src/Targets/RiscV/TargetDescriptionFile.hpp"
|
|
|
|
|
#include "src/Targets/RiscV/RiscVTargetConfig.hpp"
|
2024-11-23 20:14:47 +00:00
|
|
|
#include "src/Targets/RiscV/Opcodes/Opcode.hpp"
|
|
|
|
|
#include "src/Targets/TargetMemory.hpp"
|
2024-07-23 21:14:22 +01:00
|
|
|
|
2024-11-18 21:11:54 +00:00
|
|
|
#include "Common.hpp"
|
2024-07-23 21:14:22 +01:00
|
|
|
#include "Registers/CpuRegisterNumbers.hpp"
|
|
|
|
|
#include "Registers/DebugControlStatusRegister.hpp"
|
|
|
|
|
|
|
|
|
|
#include "DebugModule/DebugModule.hpp"
|
|
|
|
|
#include "DebugModule/Registers/ControlRegister.hpp"
|
|
|
|
|
#include "DebugModule/Registers/StatusRegister.hpp"
|
|
|
|
|
#include "DebugModule/Registers/AbstractControlStatusRegister.hpp"
|
|
|
|
|
#include "DebugModule/Registers/AbstractCommandRegister.hpp"
|
2024-11-23 20:14:47 +00:00
|
|
|
#include "DebugModule/Registers/RegisterAccessControlField.hpp"
|
2024-07-23 21:14:22 +01:00
|
|
|
|
2024-10-06 17:54:08 +01:00
|
|
|
#include "TriggerModule/TriggerModule.hpp"
|
|
|
|
|
#include "TriggerModule/TriggerDescriptor.hpp"
|
2024-09-04 00:15:46 +01:00
|
|
|
|
|
|
|
|
#include "src/Helpers/Expected.hpp"
|
|
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
namespace DebugToolDrivers::Protocols::RiscVDebugSpec
|
|
|
|
|
{
|
|
|
|
|
/**
|
|
|
|
|
* Implementation of a RISC-V debug translator
|
|
|
|
|
*/
|
|
|
|
|
class DebugTranslator: public ::DebugToolDrivers::TargetInterfaces::RiscV::RiscVDebugInterface
|
|
|
|
|
{
|
|
|
|
|
public:
|
|
|
|
|
DebugTranslator(
|
|
|
|
|
DebugTransportModuleInterface& dtmInterface,
|
2024-10-06 23:32:36 +01:00
|
|
|
const DebugTranslatorConfig& config,
|
2024-07-23 21:14:22 +01:00
|
|
|
const ::Targets::RiscV::TargetDescriptionFile& targetDescriptionFile,
|
|
|
|
|
const ::Targets::RiscV::RiscVTargetConfig& targetConfig
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
virtual ~DebugTranslator() = default;
|
|
|
|
|
|
|
|
|
|
void init() override;
|
|
|
|
|
void activate() override;
|
|
|
|
|
void deactivate() override;
|
|
|
|
|
|
|
|
|
|
Targets::TargetExecutionState getExecutionState() override;
|
|
|
|
|
|
|
|
|
|
void stop() override;
|
|
|
|
|
void run() override;
|
|
|
|
|
void step() override;
|
|
|
|
|
void reset() override;
|
|
|
|
|
|
|
|
|
|
void setSoftwareBreakpoint(Targets::TargetMemoryAddress address) override;
|
|
|
|
|
void clearSoftwareBreakpoint(Targets::TargetMemoryAddress address) override;
|
|
|
|
|
|
2024-10-06 17:54:08 +01:00
|
|
|
std::uint16_t getHardwareBreakpointCount() override;
|
2024-07-23 21:14:22 +01:00
|
|
|
void setHardwareBreakpoint(Targets::TargetMemoryAddress address) override;
|
|
|
|
|
void clearHardwareBreakpoint(Targets::TargetMemoryAddress address) override;
|
2024-10-07 20:02:39 +01:00
|
|
|
void clearAllHardwareBreakpoints() override;
|
2024-07-23 21:14:22 +01:00
|
|
|
|
|
|
|
|
Targets::TargetRegisterDescriptorAndValuePairs readCpuRegisters(
|
|
|
|
|
const Targets::TargetRegisterDescriptors& descriptors
|
|
|
|
|
) override;
|
|
|
|
|
void writeCpuRegisters(const Targets::TargetRegisterDescriptorAndValuePairs& registers) override;
|
|
|
|
|
|
|
|
|
|
Targets::TargetMemoryBuffer readMemory(
|
|
|
|
|
const Targets::TargetAddressSpaceDescriptor& addressSpaceDescriptor,
|
|
|
|
|
const Targets::TargetMemorySegmentDescriptor& memorySegmentDescriptor,
|
|
|
|
|
Targets::TargetMemoryAddress startAddress,
|
|
|
|
|
Targets::TargetMemorySize bytes,
|
2024-11-16 20:06:55 +00:00
|
|
|
const std::set<Targets::TargetMemoryAddressRange>& excludedAddressRanges
|
2024-07-23 21:14:22 +01:00
|
|
|
) override;
|
|
|
|
|
void writeMemory(
|
|
|
|
|
const Targets::TargetAddressSpaceDescriptor& addressSpaceDescriptor,
|
|
|
|
|
const Targets::TargetMemorySegmentDescriptor& memorySegmentDescriptor,
|
|
|
|
|
Targets::TargetMemoryAddress startAddress,
|
2024-11-16 21:49:49 +00:00
|
|
|
Targets::TargetMemoryBufferSpan buffer
|
2024-07-23 21:14:22 +01:00
|
|
|
) override;
|
|
|
|
|
|
|
|
|
|
private:
|
2024-10-06 23:32:36 +01:00
|
|
|
static constexpr auto DEBUG_MODULE_RESPONSE_DELAY = std::chrono::microseconds{10};
|
2024-11-23 20:14:47 +00:00
|
|
|
static constexpr auto WORD_BYTE_SIZE = ::Targets::TargetMemorySize{4};
|
2024-10-06 23:32:36 +01:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
DebugTransportModuleInterface& dtmInterface;
|
2024-10-06 23:32:36 +01:00
|
|
|
const DebugTranslatorConfig& config;
|
2024-07-23 21:14:22 +01:00
|
|
|
|
|
|
|
|
const ::Targets::RiscV::TargetDescriptionFile& targetDescriptionFile;
|
|
|
|
|
const ::Targets::RiscV::RiscVTargetConfig& targetConfig;
|
|
|
|
|
|
2024-11-23 20:14:47 +00:00
|
|
|
DebugModuleDescriptor debugModuleDescriptor = {};
|
2024-07-23 21:14:22 +01:00
|
|
|
|
2024-11-23 20:14:47 +00:00
|
|
|
DebugModule::HartIndex selectedHartIndex = 0;
|
|
|
|
|
DebugModule::MemoryAccessStrategy memoryAccessStrategy = DebugModule::MemoryAccessStrategy::ABSTRACT_COMMAND;
|
2024-10-06 17:54:08 +01:00
|
|
|
std::unordered_set<TriggerModule::TriggerIndex> allocatedTriggerIndices;
|
|
|
|
|
std::unordered_map<Targets::TargetMemoryAddress, TriggerModule::TriggerIndex> triggerIndicesByBreakpointAddress;
|
|
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
std::vector<DebugModule::HartIndex> discoverHartIndices();
|
2024-10-06 17:54:08 +01:00
|
|
|
std::unordered_map<TriggerModule::TriggerIndex, TriggerModule::TriggerDescriptor> discoverTriggers();
|
2024-07-23 21:14:22 +01:00
|
|
|
|
|
|
|
|
DebugModule::Registers::ControlRegister readDebugModuleControlRegister();
|
|
|
|
|
DebugModule::Registers::StatusRegister readDebugModuleStatusRegister();
|
|
|
|
|
DebugModule::Registers::AbstractControlStatusRegister readDebugModuleAbstractControlStatusRegister();
|
|
|
|
|
Registers::DebugControlStatusRegister readDebugControlStatusRegister();
|
|
|
|
|
|
|
|
|
|
void enableDebugModule();
|
|
|
|
|
void disableDebugModule();
|
|
|
|
|
|
2024-11-23 20:14:47 +00:00
|
|
|
void initDebugControlStatusRegister();
|
|
|
|
|
|
2024-09-04 00:15:46 +01:00
|
|
|
Expected<RegisterValue, DebugModule::AbstractCommandError> tryReadCpuRegister(
|
2024-11-23 20:14:47 +00:00
|
|
|
RegisterNumber number,
|
|
|
|
|
const DebugModule::Registers::RegisterAccessControlField::Flags& flags = {}
|
|
|
|
|
);
|
|
|
|
|
Expected<RegisterValue, DebugModule::AbstractCommandError> tryReadCpuRegister(
|
|
|
|
|
Registers::CpuRegisterNumber number,
|
|
|
|
|
const DebugModule::Registers::RegisterAccessControlField::Flags& flags = {}
|
|
|
|
|
);
|
|
|
|
|
RegisterValue readCpuRegister(
|
|
|
|
|
RegisterNumber number,
|
|
|
|
|
const DebugModule::Registers::RegisterAccessControlField::Flags& flags = {}
|
|
|
|
|
);
|
|
|
|
|
RegisterValue readCpuRegister(
|
|
|
|
|
Registers::CpuRegisterNumber number,
|
|
|
|
|
const DebugModule::Registers::RegisterAccessControlField::Flags& flags = {}
|
2024-09-04 00:15:46 +01:00
|
|
|
);
|
|
|
|
|
|
2024-11-23 20:14:47 +00:00
|
|
|
DebugModule::AbstractCommandError tryWriteCpuRegister(
|
|
|
|
|
RegisterNumber number,
|
|
|
|
|
RegisterValue value,
|
|
|
|
|
const DebugModule::Registers::RegisterAccessControlField::Flags& flags = {}
|
|
|
|
|
);
|
|
|
|
|
DebugModule::AbstractCommandError tryWriteCpuRegister(
|
|
|
|
|
Registers::CpuRegisterNumber number,
|
|
|
|
|
RegisterValue value,
|
|
|
|
|
const DebugModule::Registers::RegisterAccessControlField::Flags& flags = {}
|
|
|
|
|
);
|
|
|
|
|
void writeCpuRegister(
|
|
|
|
|
RegisterNumber number,
|
|
|
|
|
RegisterValue value,
|
|
|
|
|
const DebugModule::Registers::RegisterAccessControlField::Flags& flags = {}
|
|
|
|
|
);
|
|
|
|
|
void writeCpuRegister(
|
|
|
|
|
Registers::CpuRegisterNumber number,
|
|
|
|
|
RegisterValue value,
|
|
|
|
|
const DebugModule::Registers::RegisterAccessControlField::Flags& flags = {}
|
|
|
|
|
);
|
2024-07-23 21:14:22 +01:00
|
|
|
|
|
|
|
|
void writeDebugModuleControlRegister(const DebugModule::Registers::ControlRegister& controlRegister);
|
|
|
|
|
void writeDebugControlStatusRegister(const Registers::DebugControlStatusRegister& controlRegister);
|
|
|
|
|
|
2024-11-23 20:14:47 +00:00
|
|
|
void clearAbstractCommandError();
|
2024-09-04 00:15:46 +01:00
|
|
|
DebugModule::AbstractCommandError tryExecuteAbstractCommand(
|
|
|
|
|
const DebugModule::Registers::AbstractCommandRegister& abstractCommandRegister
|
|
|
|
|
);
|
2024-07-23 21:14:22 +01:00
|
|
|
void executeAbstractCommand(const DebugModule::Registers::AbstractCommandRegister& abstractCommandRegister);
|
|
|
|
|
|
2024-11-23 20:14:47 +00:00
|
|
|
DebugModule::MemoryAccessStrategy determineMemoryAccessStrategy();
|
|
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
Targets::TargetMemoryAddress alignMemoryAddress(
|
|
|
|
|
Targets::TargetMemoryAddress address,
|
|
|
|
|
Targets::TargetMemoryAddress alignTo
|
|
|
|
|
);
|
|
|
|
|
Targets::TargetMemorySize alignMemorySize(Targets::TargetMemorySize size, Targets::TargetMemorySize alignTo);
|
2024-10-06 17:54:08 +01:00
|
|
|
|
2024-10-19 23:11:22 +01:00
|
|
|
Targets::TargetMemoryBuffer readMemoryViaAbstractCommand(
|
|
|
|
|
Targets::TargetMemoryAddress startAddress,
|
|
|
|
|
Targets::TargetMemorySize bytes
|
|
|
|
|
);
|
|
|
|
|
void writeMemoryViaAbstractCommand(
|
|
|
|
|
Targets::TargetMemoryAddress startAddress,
|
2024-11-16 21:49:49 +00:00
|
|
|
Targets::TargetMemoryBufferSpan buffer
|
2024-10-19 23:11:22 +01:00
|
|
|
);
|
|
|
|
|
|
2024-11-23 20:14:47 +00:00
|
|
|
Targets::TargetMemoryBuffer readMemoryViaProgramBuffer(
|
|
|
|
|
Targets::TargetMemoryAddress startAddress,
|
|
|
|
|
Targets::TargetMemorySize bytes
|
|
|
|
|
);
|
|
|
|
|
void writeMemoryViaProgramBuffer(
|
|
|
|
|
Targets::TargetMemoryAddress startAddress,
|
|
|
|
|
Targets::TargetMemoryBufferSpan buffer
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
void writeProgramBuffer(std::span<const Targets::RiscV::Opcodes::Opcode> opcodes);
|
|
|
|
|
|
2024-10-06 17:54:08 +01:00
|
|
|
std::optional<std::reference_wrapper<const TriggerModule::TriggerDescriptor>> getAvailableTrigger();
|
|
|
|
|
void clearTrigger(const TriggerModule::TriggerDescriptor& triggerDescriptor);
|
2024-11-23 20:14:47 +00:00
|
|
|
|
|
|
|
|
struct PreservedCpuRegister
|
|
|
|
|
{
|
|
|
|
|
const Registers::CpuRegisterNumber registerNumber;
|
|
|
|
|
const RegisterValue value;
|
|
|
|
|
|
|
|
|
|
PreservedCpuRegister(
|
|
|
|
|
Registers::CpuRegisterNumber registerNumber,
|
|
|
|
|
RegisterValue value,
|
|
|
|
|
DebugTranslator& debugTranslator
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
PreservedCpuRegister(
|
|
|
|
|
Registers::CpuRegisterNumber registerNumber,
|
|
|
|
|
DebugTranslator& debugTranslator
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
PreservedCpuRegister(const PreservedCpuRegister& other) = delete;
|
|
|
|
|
PreservedCpuRegister& operator = (const PreservedCpuRegister& other) = delete;
|
|
|
|
|
|
|
|
|
|
PreservedCpuRegister(const PreservedCpuRegister&& other) = delete;
|
|
|
|
|
PreservedCpuRegister& operator = (const PreservedCpuRegister&& other) = delete;
|
|
|
|
|
|
|
|
|
|
void restore();
|
|
|
|
|
void restoreOnce();
|
|
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
DebugTranslator& debugTranslator;
|
|
|
|
|
bool restored = false;
|
|
|
|
|
};
|
2024-07-23 21:14:22 +01:00
|
|
|
};
|
|
|
|
|
}
|