Massive refactor to accommodate RISC-V targets

- Refactored entire codebase (excluding the Insight component) to accommodate multiple target architectures (no longer specific to AVR)
- Deleted 'generate SVD' GDB monitor command - I will eventually move this functionality to the Bloom website
- Added unit size property to address spaces
- Many other changes which I couldn't be bothered to describe here
This commit is contained in:
Nav
2024-07-23 21:14:22 +01:00
parent 2986934485
commit 6cdbfbe950
331 changed files with 8815 additions and 8565 deletions

View File

@@ -7,32 +7,19 @@
#include "src/Targets/Target.hpp"
#include "src/DebugToolDrivers/DebugTool.hpp"
#include "TargetDescription/TargetDescriptionFile.hpp"
#include "RiscVTargetConfig.hpp"
#include "TargetDescriptionFile.hpp"
#include "src/DebugToolDrivers/TargetInterfaces/RiscV/RiscVDebugInterface.hpp"
#include "src/DebugToolDrivers/TargetInterfaces/RiscV/RiscVProgramInterface.hpp"
#include "src/Targets/RiscV/RiscVGeneric.hpp"
#include "src/Targets/RiscV/Registers/RegisterNumbers.hpp"
#include "src/Targets/RiscV/Registers/DebugControlStatusRegister.hpp"
#include "src/Targets/RiscV/DebugModule/DebugModule.hpp"
#include "src/Targets/RiscV/DebugModule/Registers/ControlRegister.hpp"
#include "src/Targets/RiscV/DebugModule/Registers/StatusRegister.hpp"
#include "src/Targets/RiscV/DebugModule/Registers/AbstractControlStatusRegister.hpp"
#include "src/Targets/RiscV/DebugModule/Registers/AbstractCommandRegister.hpp"
#include "RiscVRegisterDescriptor.hpp"
#include "src/DebugToolDrivers/TargetInterfaces/RiscV/RiscVIdentificationInterface.hpp"
namespace Targets::RiscV
{
class RiscV: public Target
{
public:
explicit RiscV(
const TargetConfig& targetConfig,
TargetDescription::TargetDescriptionFile&& targetDescriptionFile
);
RiscV(const TargetConfig& targetConfig, TargetDescriptionFile&& targetDescriptionFile);
/*
* The functions below implement the Target interface for RISC-V targets.
@@ -41,20 +28,13 @@ namespace Targets::RiscV
* each function.
*/
/**
* All RISC-V compatible debug tools must provide a valid RiscVDebugInterface.
*
* @param debugTool
* @return
*/
bool supportsDebugTool(DebugTool* debugTool) override;
void setDebugTool(DebugTool* debugTool) override;
void activate() override;
void deactivate() override;
TargetDescriptor getDescriptor() override;
TargetDescriptor targetDescriptor() override;
void run(std::optional<TargetMemoryAddress> toAddress = std::nullopt) override;
void stop() override;
@@ -68,34 +48,45 @@ namespace Targets::RiscV
void removeHardwareBreakpoint(TargetMemoryAddress address) override;
void clearAllBreakpoints() override;
TargetRegisters readRegisters(const TargetRegisterDescriptorIds& descriptorIds) override;
void writeRegisters(const TargetRegisters& registers) override;
TargetRegisterDescriptorAndValuePairs readRegisters(const TargetRegisterDescriptors& descriptors) override;
void writeRegisters(const TargetRegisterDescriptorAndValuePairs& registers) override;
TargetMemoryBuffer readMemory(
TargetMemoryType memoryType,
const TargetAddressSpaceDescriptor& addressSpaceDescriptor,
const TargetMemorySegmentDescriptor& memorySegmentDescriptor,
TargetMemoryAddress startAddress,
TargetMemorySize bytes,
const std::set<TargetMemoryAddressRange>& excludedAddressRanges = {}
) override;
void writeMemory(
TargetMemoryType memoryType,
const TargetAddressSpaceDescriptor& addressSpaceDescriptor,
const TargetMemorySegmentDescriptor& memorySegmentDescriptor,
TargetMemoryAddress startAddress,
const TargetMemoryBuffer& buffer
) override;
void eraseMemory(TargetMemoryType memoryType) override;
bool isProgramMemory(
const TargetAddressSpaceDescriptor& addressSpaceDescriptor,
const TargetMemorySegmentDescriptor& memorySegmentDescriptor,
TargetMemoryAddress startAddress,
TargetMemorySize size
) override;
void eraseMemory(
const TargetAddressSpaceDescriptor& addressSpaceDescriptor,
const TargetMemorySegmentDescriptor& memorySegmentDescriptor
) override;
TargetState getState() override;
TargetExecutionState getExecutionState() override;
TargetMemoryAddress getProgramCounter() override;
void setProgramCounter(TargetMemoryAddress programCounter) override;
TargetStackPointer getStackPointer() override;
void setStackPointer(TargetStackPointer stackPointer) override;
std::map<int, TargetPinState> getPinStates(int variantId) override;
void setPinState(
const TargetPinDescriptor& pinDescriptor,
const TargetPinState& state
TargetGpioPinDescriptorAndStatePairs getGpioPinStates(
const TargetPinoutDescriptor& pinoutDescriptor
) override;
void setGpioPinState(const TargetPinDescriptor& pinDescriptor, const TargetGpioPinState& state) override;
void enableProgrammingMode() override;
@@ -104,43 +95,53 @@ namespace Targets::RiscV
bool programmingModeEnabled() override;
protected:
TargetDescription::TargetDescriptionFile targetDescriptionFile;
std::map<TargetRegisterDescriptorId, RiscVRegisterDescriptor> registerDescriptorsById;
RiscVRegisterDescriptor stackPointerRegisterDescriptor;
RiscVTargetConfig targetConfig;
TargetDescriptionFile targetDescriptionFile;
DebugToolDrivers::TargetInterfaces::RiscV::RiscVDebugInterface* riscVDebugInterface = nullptr;
DebugToolDrivers::TargetInterfaces::RiscV::RiscVProgramInterface* riscVProgramInterface = nullptr;
DebugToolDrivers::TargetInterfaces::RiscV::RiscVIdentificationInterface* riscVIdInterface = nullptr;
std::set<DebugModule::HartIndex> hartIndices;
DebugModule::HartIndex selectedHartIndex = 0;
/*
* On RISC-V targets, CPU registers are typically only accessible via the debug module (we can't access them
* via the system address space). So we use abstract commands to access these registers. This means we have to
* address these registers via their register numbers, as defined in the RISC-V debug spec.
*
* We effectively treat register numbers as a separate address space, with an addressable unit size of 4 bytes.
* The `cpuRegisterAddressSpaceDescriptor` member holds the descriptor for this address space.
*
* TODO: review this. This address space is specific to the RISC-V debug spec, but some debug tools may
* implement their own debug translator in firmware, and then provide a higher-level API to access the
* same registers. In that case, this address space may not be relevant. This may need to be moved.
* ATM all RISC-V debug tools supported by Bloom provide a DTM interface, so we use our own debug
* translator driver and this address space is, in fact, relevant. I will deal with this when it
* becomes a problem.
*/
TargetAddressSpaceDescriptor cpuRegisterAddressSpaceDescriptor;
const TargetMemorySegmentDescriptor& csrMemorySegmentDescriptor;
const TargetMemorySegmentDescriptor& gprMemorySegmentDescriptor;
void loadRegisterDescriptors();
TargetPeripheralDescriptor cpuPeripheralDescriptor;
const TargetRegisterGroupDescriptor& csrGroupDescriptor;
const TargetRegisterGroupDescriptor& gprGroupDescriptor;
const TargetRegisterDescriptor& pcRegisterDescriptor;
const TargetRegisterDescriptor& spRegisterDescriptor;
std::set<DebugModule::HartIndex> discoverHartIndices();
/*
* The "system" address space is the main address space on RISC-V targets.
*/
TargetAddressSpaceDescriptor sysAddressSpaceDescriptor;
DebugModule::Registers::ControlRegister readDebugModuleControlRegister();
DebugModule::Registers::StatusRegister readDebugModuleStatusRegister();
DebugModule::Registers::AbstractControlStatusRegister readDebugModuleAbstractControlStatusRegister();
const TargetMemorySegmentDescriptor& resolveRegisterMemorySegmentDescriptor(
const TargetRegisterDescriptor& regDescriptor,
const TargetAddressSpaceDescriptor& addressSpaceDescriptor
);
Registers::DebugControlStatusRegister readDebugControlStatusRegister();
void enableDebugModule();
void disableDebugModule();
RegisterValue readRegister(RegisterNumber number);
RegisterValue readRegister(Registers::RegisterNumber number);
void writeRegister(RegisterNumber number, RegisterValue value);
void writeRegister(Registers::RegisterNumber number, RegisterValue value);
void writeDebugModuleControlRegister(const DebugModule::Registers::ControlRegister& controlRegister);
void writeDebugControlStatusRegister(const Registers::DebugControlStatusRegister& controlRegister);
void executeAbstractCommand(const DebugModule::Registers::AbstractCommandRegister& abstractCommandRegister);
TargetMemoryAddress alignMemoryAddress(TargetMemoryAddress address, TargetMemoryAddress alignTo);
TargetMemorySize alignMemorySize(TargetMemorySize size, TargetMemorySize alignTo);
static TargetAddressSpaceDescriptor generateCpuRegisterAddressSpaceDescriptor();
static TargetPeripheralDescriptor generateCpuPeripheralDescriptor(
const TargetAddressSpaceDescriptor& addressSpaceDescriptor,
const TargetMemorySegmentDescriptor& csrMemorySegmentDescriptor,
const TargetMemorySegmentDescriptor& gprMemorySegmentDescriptor
);
};
}