WCH RISC-V software breakpoints, and a few other bits of refactoring/tidying

This commit is contained in:
Nav
2024-12-05 23:09:01 +00:00
parent 966244a01a
commit 33ed399337
55 changed files with 1530 additions and 686 deletions

View File

@@ -5,6 +5,7 @@
namespace Targets::RiscV::Opcodes
{
using Opcode = std::uint32_t;
using OpcodeCompressed = std::uint16_t;
enum class GprNumber: std::uint8_t
{
@@ -14,4 +15,8 @@ namespace Targets::RiscV::Opcodes
};
static constexpr auto Ebreak = Opcode{0x00100073};
static constexpr auto EbreakCompressed = OpcodeCompressed{0x9002};
static constexpr auto Fence = Opcode{0x0000000f};
static constexpr auto FenceI = Opcode{0x0000100f};
}

View File

@@ -0,0 +1,23 @@
#pragma once
#include <optional>
#include "src/Targets/TargetBreakpoint.hpp"
#include "Opcodes/Opcode.hpp"
namespace Targets::RiscV
{
struct ProgramBreakpoint: TargetProgramBreakpoint
{
std::optional<Opcodes::Opcode> originalInstruction = std::nullopt;
explicit ProgramBreakpoint(const TargetProgramBreakpoint& breakpoint)
: TargetProgramBreakpoint(breakpoint)
{}
explicit ProgramBreakpoint(const TargetProgramBreakpoint& breakpoint, Opcodes::Opcode originalInstruction)
: TargetProgramBreakpoint(breakpoint)
, originalInstruction(originalInstruction)
{}
};
}

View File

@@ -59,8 +59,6 @@ namespace Targets::RiscV
this->stop();
}
this->clearAllBreakpoints();
this->run();
this->riscVDebugInterface->deactivate();
}
@@ -80,26 +78,6 @@ namespace Targets::RiscV
this->riscVDebugInterface->reset();
}
void RiscV::setSoftwareBreakpoint(TargetMemoryAddress address) {
throw Exceptions::Exception{"TARGET - SW breakpoints not supported"};
}
void RiscV::removeSoftwareBreakpoint(TargetMemoryAddress address) {
throw Exceptions::Exception{"TARGET - SW breakpoints not supported"};
}
void RiscV::setHardwareBreakpoint(TargetMemoryAddress address) {
this->riscVDebugInterface->setHardwareBreakpoint(address);
}
void RiscV::removeHardwareBreakpoint(TargetMemoryAddress address) {
this->riscVDebugInterface->clearHardwareBreakpoint(address);
}
void RiscV::clearAllBreakpoints() {
this->riscVDebugInterface->clearAllHardwareBreakpoints();
}
TargetRegisterDescriptorAndValuePairs RiscV::readRegisters(const TargetRegisterDescriptors& descriptors) {
auto output = TargetRegisterDescriptorAndValuePairs{};
@@ -316,10 +294,12 @@ namespace Targets::RiscV
}
void RiscV::enableProgrammingMode() {
this->riscVDebugInterface->enableProgrammingMode();
this->programmingMode = true;
}
void RiscV::disableProgrammingMode() {
this->riscVDebugInterface->disableProgrammingMode();
this->programmingMode = false;
}

View File

@@ -38,13 +38,6 @@ namespace Targets::RiscV
void step() override;
void reset() override;
void setSoftwareBreakpoint(TargetMemoryAddress address) override;
void removeSoftwareBreakpoint(TargetMemoryAddress address) override;
void setHardwareBreakpoint(TargetMemoryAddress address) override;
void removeHardwareBreakpoint(TargetMemoryAddress address) override;
void clearAllBreakpoints() override;
TargetRegisterDescriptorAndValuePairs readRegisters(const TargetRegisterDescriptors& descriptors) override;
void writeRegisters(const TargetRegisterDescriptorAndValuePairs& registers) override;
@@ -84,9 +77,7 @@ namespace Targets::RiscV
void setGpioPadState(const TargetPadDescriptor& padDescriptor, const TargetGpioPadState& state) override;
void enableProgrammingMode() override;
void disableProgrammingMode() override;
bool programmingModeEnabled() override;
protected:

View File

@@ -47,8 +47,6 @@ namespace Targets::RiscV::Wch
}
TargetDescriptor WchRiscV::targetDescriptor() {
const auto hardwareBreakpointCount = this->riscVDebugInterface->getHardwareBreakpointCount();
auto descriptor = TargetDescriptor{
this->targetDescriptionFile.getName(),
this->targetDescriptionFile.getFamily(),
@@ -59,15 +57,16 @@ namespace Targets::RiscV::Wch
this->targetDescriptionFile.targetPadDescriptorsByKey(),
this->targetDescriptionFile.targetPinoutDescriptorsByKey(),
this->targetDescriptionFile.targetVariantDescriptorsByKey(),
BreakpointResources{
hardwareBreakpointCount,
std::nullopt,
static_cast<std::uint16_t>(
this->targetConfig.reserveSteppingBreakpoint.value_or(false) && hardwareBreakpointCount > 0 ? 1 : 0
)
}
this->riscVDebugInterface->getBreakpointResources()
};
if (
this->targetConfig.reserveSteppingBreakpoint.value_or(false)
&& descriptor.breakpointResources.hardwareBreakpoints > 0
) {
descriptor.breakpointResources.reservedHardwareBreakpoints = 1;
}
// Copy the RISC-V CPU register address space and peripheral descriptor
descriptor.addressSpaceDescriptorsByKey.emplace(
this->cpuRegisterAddressSpaceDescriptor.key,
@@ -100,6 +99,44 @@ namespace Targets::RiscV::Wch
return descriptor;
}
void WchRiscV::setProgramBreakpoint(const TargetProgramBreakpoint& breakpoint) {
if (
breakpoint.type == TargetProgramBreakpoint::Type::SOFTWARE
&& breakpoint.memorySegmentDescriptor == this->mappedProgramMemorySegmentDescriptor
) {
this->riscVDebugInterface->setProgramBreakpoint(TargetProgramBreakpoint{
.addressSpaceDescriptor = this->sysAddressSpaceDescriptor,
.memorySegmentDescriptor = this->getDestinationProgramMemorySegmentDescriptor(),
.address = this->transformAliasedProgramMemoryAddress(breakpoint.address),
.size = breakpoint.size,
.type = breakpoint.type
});
return;
}
this->riscVDebugInterface->setProgramBreakpoint(breakpoint);
}
void WchRiscV::removeProgramBreakpoint(const TargetProgramBreakpoint& breakpoint) {
if (
breakpoint.type == TargetProgramBreakpoint::Type::SOFTWARE
&& breakpoint.memorySegmentDescriptor == this->mappedProgramMemorySegmentDescriptor
) {
this->riscVDebugInterface->removeProgramBreakpoint(TargetProgramBreakpoint{
.addressSpaceDescriptor = this->sysAddressSpaceDescriptor,
.memorySegmentDescriptor = this->getDestinationProgramMemorySegmentDescriptor(),
.address = this->transformAliasedProgramMemoryAddress(breakpoint.address),
.size = breakpoint.size,
.type = breakpoint.type
});
return;
}
this->riscVDebugInterface->removeProgramBreakpoint(breakpoint);
}
void WchRiscV::writeMemory(
const TargetAddressSpaceDescriptor& addressSpaceDescriptor,
const TargetMemorySegmentDescriptor& memorySegmentDescriptor,
@@ -119,13 +156,35 @@ namespace Targets::RiscV::Wch
* before v2.0.0.
*/
if (memorySegmentDescriptor == this->mappedProgramMemorySegmentDescriptor) {
const auto newAddress = startAddress - this->mappedProgramMemorySegmentDescriptor.addressRange.startAddress
+ this->programMemorySegmentDescriptor.addressRange.startAddress;
assert(this->programMemorySegmentDescriptor.addressRange.contains(newAddress));
const auto transformedAddress = this->transformAliasedProgramMemoryAddress(startAddress);
assert(this->programMemorySegmentDescriptor.addressRange.contains(transformedAddress));
return RiscV::writeMemory(addressSpaceDescriptor, this->programMemorySegmentDescriptor, newAddress, buffer);
return RiscV::writeMemory(
addressSpaceDescriptor,
this->programMemorySegmentDescriptor,
transformedAddress,
buffer
);
}
return RiscV::writeMemory(addressSpaceDescriptor, memorySegmentDescriptor, startAddress, buffer);
}
const TargetMemorySegmentDescriptor& WchRiscV::getDestinationProgramMemorySegmentDescriptor() {
return this->programMemorySegmentDescriptor;
}
TargetMemoryAddress WchRiscV::transformAliasedProgramMemoryAddress(TargetMemoryAddress address) const {
using Services::StringService;
const auto transformedAddress = address - this->mappedProgramMemorySegmentDescriptor.addressRange.startAddress
+ this->programMemorySegmentDescriptor.addressRange.startAddress;
Logger::debug(
"Transformed mapped program memory address 0x" + StringService::toHex(address) + " to 0x"
+ StringService::toHex(transformedAddress)
);
return transformedAddress;
}
}

View File

@@ -19,6 +19,9 @@ namespace Targets::RiscV::Wch
void postActivate() override;
TargetDescriptor targetDescriptor() override;
void setProgramBreakpoint(const TargetProgramBreakpoint& breakpoint) override;
void removeProgramBreakpoint(const TargetProgramBreakpoint& breakpoint) override;
void writeMemory(
const TargetAddressSpaceDescriptor& addressSpaceDescriptor,
const TargetMemorySegmentDescriptor& memorySegmentDescriptor,
@@ -31,6 +34,10 @@ namespace Targets::RiscV::Wch
std::optional<std::reference_wrapper<const TargetDescription::Variant>> variant = std::nullopt;
const TargetMemorySegmentDescriptor& programMemorySegmentDescriptor;
const TargetMemorySegmentDescriptor& bootProgramMemorySegmentDescriptor;
const TargetMemorySegmentDescriptor& mappedProgramMemorySegmentDescriptor;
const TargetMemorySegmentDescriptor& getDestinationProgramMemorySegmentDescriptor();
TargetMemoryAddress transformAliasedProgramMemoryAddress(TargetMemoryAddress address) const;
};
}