2023-11-22 00:38:40 +00:00
|
|
|
#include "RiscV.hpp"
|
|
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
#include <cassert>
|
2023-11-25 19:09:14 +00:00
|
|
|
#include <cmath>
|
2024-07-23 21:14:22 +01:00
|
|
|
#include <iterator>
|
2023-11-22 00:38:40 +00:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
#include "src/Helpers/Pair.hpp"
|
|
|
|
|
#include "src/Services/StringService.hpp"
|
|
|
|
|
#include "src/Logger/Logger.hpp"
|
2023-11-22 00:38:40 +00:00
|
|
|
|
|
|
|
|
#include "src/Exceptions/Exception.hpp"
|
2023-12-17 18:41:38 +00:00
|
|
|
#include "src/Exceptions/InvalidConfig.hpp"
|
2023-11-23 12:59:36 +00:00
|
|
|
#include "src/TargetController/Exceptions/TargetOperationFailure.hpp"
|
2023-11-22 00:38:40 +00:00
|
|
|
|
|
|
|
|
namespace Targets::RiscV
|
|
|
|
|
{
|
2023-12-17 18:12:53 +00:00
|
|
|
RiscV::RiscV(
|
|
|
|
|
const TargetConfig& targetConfig,
|
2024-07-23 21:14:22 +01:00
|
|
|
TargetDescriptionFile&& targetDescriptionFile
|
2023-12-17 18:12:53 +00:00
|
|
|
)
|
2024-07-23 21:14:22 +01:00
|
|
|
: targetConfig(RiscVTargetConfig(targetConfig))
|
|
|
|
|
, targetDescriptionFile(std::move(targetDescriptionFile))
|
|
|
|
|
, cpuRegisterAddressSpaceDescriptor(RiscV::generateCpuRegisterAddressSpaceDescriptor())
|
|
|
|
|
, csrMemorySegmentDescriptor(this->cpuRegisterAddressSpaceDescriptor.getMemorySegmentDescriptor("cs_registers"))
|
|
|
|
|
, gprMemorySegmentDescriptor(this->cpuRegisterAddressSpaceDescriptor.getMemorySegmentDescriptor("gp_registers"))
|
|
|
|
|
, cpuPeripheralDescriptor(
|
|
|
|
|
RiscV::generateCpuPeripheralDescriptor(
|
|
|
|
|
this->cpuRegisterAddressSpaceDescriptor,
|
|
|
|
|
this->csrMemorySegmentDescriptor,
|
|
|
|
|
this->gprMemorySegmentDescriptor
|
2023-11-24 15:19:52 +00:00
|
|
|
)
|
|
|
|
|
)
|
2024-07-23 21:14:22 +01:00
|
|
|
, csrGroupDescriptor(this->cpuPeripheralDescriptor.getRegisterGroupDescriptor("csr"))
|
|
|
|
|
, gprGroupDescriptor(this->cpuPeripheralDescriptor.getRegisterGroupDescriptor("gpr"))
|
|
|
|
|
, pcRegisterDescriptor(this->csrGroupDescriptor.getRegisterDescriptor("dpc"))
|
|
|
|
|
, spRegisterDescriptor(this->gprGroupDescriptor.getRegisterDescriptor("x2"))
|
|
|
|
|
, sysAddressSpaceDescriptor(this->targetDescriptionFile.getSystemAddressSpaceDescriptor())
|
|
|
|
|
{}
|
2023-11-22 00:38:40 +00:00
|
|
|
|
|
|
|
|
bool RiscV::supportsDebugTool(DebugTool* debugTool) {
|
2024-07-23 21:14:22 +01:00
|
|
|
return
|
|
|
|
|
debugTool->getRiscVDebugInterface(this->targetDescriptionFile, this->targetConfig) != nullptr
|
|
|
|
|
&& debugTool->getRiscVIdentificationInterface(this->targetDescriptionFile, this->targetConfig) != nullptr
|
|
|
|
|
;
|
2023-11-22 00:38:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RiscV::setDebugTool(DebugTool* debugTool) {
|
2024-07-23 21:14:22 +01:00
|
|
|
this->riscVDebugInterface = debugTool->getRiscVDebugInterface(this->targetDescriptionFile, this->targetConfig);
|
|
|
|
|
this->riscVProgramInterface = debugTool->getRiscVProgramInterface(
|
|
|
|
|
this->targetDescriptionFile,
|
|
|
|
|
this->targetConfig
|
|
|
|
|
);
|
|
|
|
|
this->riscVIdInterface = debugTool->getRiscVIdentificationInterface(
|
|
|
|
|
this->targetDescriptionFile,
|
|
|
|
|
this->targetConfig
|
|
|
|
|
);
|
2023-11-22 00:38:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RiscV::activate() {
|
2024-07-23 21:14:22 +01:00
|
|
|
this->riscVDebugInterface->activate();
|
2023-11-22 00:38:40 +00:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
const auto deviceId = this->riscVIdInterface->getDeviceId();
|
2023-12-17 18:41:38 +00:00
|
|
|
const auto tdfDeviceId = this->targetDescriptionFile.getTargetId();
|
|
|
|
|
if (deviceId != tdfDeviceId) {
|
|
|
|
|
throw Exceptions::InvalidConfig(
|
|
|
|
|
"RISC-V target ID mismatch - expected " + tdfDeviceId + " but got " + deviceId +
|
|
|
|
|
". Please check target configuration."
|
|
|
|
|
);
|
|
|
|
|
}
|
2023-11-22 00:38:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RiscV::deactivate() {
|
2024-07-23 21:14:22 +01:00
|
|
|
if (this->getExecutionState() != TargetExecutionState::RUNNING) {
|
2023-11-25 19:06:23 +00:00
|
|
|
this->run();
|
|
|
|
|
}
|
|
|
|
|
|
2023-11-22 00:38:40 +00:00
|
|
|
this->riscVDebugInterface->deactivate();
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
TargetDescriptor RiscV::targetDescriptor() {
|
|
|
|
|
auto descriptor = TargetDescriptor{
|
|
|
|
|
this->targetDescriptionFile.getName(),
|
|
|
|
|
this->targetDescriptionFile.getFamily(),
|
2023-12-17 18:12:53 +00:00
|
|
|
this->targetDescriptionFile.getTargetId(),
|
|
|
|
|
this->targetDescriptionFile.getVendorName(),
|
2024-07-23 21:14:22 +01:00
|
|
|
this->targetDescriptionFile.targetAddressSpaceDescriptorsByKey(),
|
|
|
|
|
this->targetDescriptionFile.targetPeripheralDescriptorsByKey(),
|
|
|
|
|
this->targetDescriptionFile.targetPinoutDescriptorsByKey(),
|
|
|
|
|
this->targetDescriptionFile.targetVariantDescriptors(),
|
|
|
|
|
{} // TODO: populate this
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
// Copy the RISC-V CPU register address space and peripheral descriptor
|
|
|
|
|
descriptor.addressSpaceDescriptorsByKey.emplace(
|
|
|
|
|
this->cpuRegisterAddressSpaceDescriptor.key,
|
|
|
|
|
this->cpuRegisterAddressSpaceDescriptor.clone()
|
2023-11-22 00:38:40 +00:00
|
|
|
);
|
|
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
descriptor.peripheralDescriptorsByKey.emplace(
|
|
|
|
|
this->cpuPeripheralDescriptor.key,
|
|
|
|
|
this->cpuPeripheralDescriptor.clone()
|
|
|
|
|
);
|
2023-11-22 00:38:40 +00:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
return descriptor;
|
|
|
|
|
}
|
2023-11-22 00:38:40 +00:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
void RiscV::run(std::optional<TargetMemoryAddress> toAddress) {
|
|
|
|
|
this->riscVDebugInterface->run();
|
2023-11-22 00:38:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RiscV::stop() {
|
2024-07-23 21:14:22 +01:00
|
|
|
this->riscVDebugInterface->stop();
|
2023-11-22 00:38:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RiscV::step() {
|
2024-07-23 21:14:22 +01:00
|
|
|
this->riscVDebugInterface->step();
|
2023-11-22 00:38:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RiscV::reset() {
|
2024-07-23 21:14:22 +01:00
|
|
|
this->riscVDebugInterface->reset();
|
2023-11-22 00:38:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RiscV::setSoftwareBreakpoint(TargetMemoryAddress address) {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RiscV::removeSoftwareBreakpoint(TargetMemoryAddress address) {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RiscV::setHardwareBreakpoint(TargetMemoryAddress address) {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RiscV::removeHardwareBreakpoint(TargetMemoryAddress address) {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RiscV::clearAllBreakpoints() {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
TargetRegisterDescriptorAndValuePairs RiscV::readRegisters(const TargetRegisterDescriptors& descriptors) {
|
|
|
|
|
auto output = TargetRegisterDescriptorAndValuePairs{};
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* A "system register" is simply a register that we can access via the system address space.
|
|
|
|
|
*
|
|
|
|
|
* CPU registers (GPRs, CSRs, etc) cannot be accessed via the system address space, so we separate them from
|
|
|
|
|
* system registers, in order to access them separately.
|
|
|
|
|
*/
|
|
|
|
|
auto cpuRegisterDescriptors = TargetRegisterDescriptors{};
|
|
|
|
|
|
|
|
|
|
for (const auto& descriptor : descriptors) {
|
|
|
|
|
if (descriptor->addressSpaceId == this->cpuRegisterAddressSpaceDescriptor.id) {
|
|
|
|
|
if (
|
|
|
|
|
!this->csrMemorySegmentDescriptor.addressRange.contains(descriptor->startAddress)
|
|
|
|
|
&& !this->gprMemorySegmentDescriptor.addressRange.contains(descriptor->startAddress)
|
|
|
|
|
) {
|
|
|
|
|
throw Exceptions::Exception(
|
|
|
|
|
"Cannot access CPU register \"" + descriptor->key + "\" - unknown memory segment"
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cpuRegisterDescriptors.emplace_back(descriptor);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (descriptor->addressSpaceId != this->sysAddressSpaceDescriptor.id) {
|
|
|
|
|
throw Exceptions::Exception(
|
|
|
|
|
"Cannot access register \"" + descriptor->key + "\" - unknown address space"
|
|
|
|
|
);
|
|
|
|
|
}
|
2023-11-25 07:45:31 +00:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
auto value = this->riscVDebugInterface->readMemory(
|
|
|
|
|
this->sysAddressSpaceDescriptor,
|
|
|
|
|
this->resolveRegisterMemorySegmentDescriptor(*descriptor, this->sysAddressSpaceDescriptor),
|
|
|
|
|
descriptor->startAddress,
|
|
|
|
|
descriptor->size
|
2023-11-25 07:45:31 +00:00
|
|
|
);
|
2024-07-23 21:14:22 +01:00
|
|
|
|
|
|
|
|
if (value.size() > 1 && this->sysAddressSpaceDescriptor.endianness == TargetMemoryEndianness::LITTLE) {
|
|
|
|
|
// LSB to MSB
|
|
|
|
|
std::reverse(value.begin(), value.end());
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
output.emplace_back(*descriptor, std::move(value));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!cpuRegisterDescriptors.empty()) {
|
|
|
|
|
auto cpuRegisterValues = this->riscVDebugInterface->readCpuRegisters(cpuRegisterDescriptors);
|
|
|
|
|
std::move(cpuRegisterValues.begin(), cpuRegisterValues.end(), std::back_inserter(output));
|
2023-11-25 07:45:31 +00:00
|
|
|
}
|
2023-11-22 00:38:40 +00:00
|
|
|
|
2023-11-25 07:45:31 +00:00
|
|
|
return output;
|
2023-11-22 00:38:40 +00:00
|
|
|
}
|
|
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
void RiscV::writeRegisters(const TargetRegisterDescriptorAndValuePairs& registers) {
|
|
|
|
|
for (const auto& pair : registers) {
|
|
|
|
|
const auto& descriptor = pair.first;
|
|
|
|
|
|
|
|
|
|
if (descriptor.addressSpaceId == this->cpuRegisterAddressSpaceDescriptor.id) {
|
|
|
|
|
if (
|
|
|
|
|
!this->csrMemorySegmentDescriptor.addressRange.contains(descriptor.startAddress)
|
|
|
|
|
&& !this->gprMemorySegmentDescriptor.addressRange.contains(descriptor.startAddress)
|
|
|
|
|
) {
|
|
|
|
|
throw Exceptions::Exception("Cannot access CPU register - unknown memory segment");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
this->riscVDebugInterface->writeCpuRegisters({pair});
|
|
|
|
|
continue;
|
2023-11-25 07:45:31 +00:00
|
|
|
}
|
|
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
if (descriptor.addressSpaceId != this->sysAddressSpaceDescriptor.id) {
|
|
|
|
|
throw Exceptions::Exception(
|
|
|
|
|
"Cannot access register \"" + descriptor.key + "\" - unknown address space"
|
|
|
|
|
);
|
|
|
|
|
}
|
2023-11-25 07:45:31 +00:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
auto value = pair.second;
|
|
|
|
|
|
|
|
|
|
if (value.size() > 1 && this->sysAddressSpaceDescriptor.endianness == TargetMemoryEndianness::LITTLE) {
|
|
|
|
|
// MSB to LSB
|
|
|
|
|
std::reverse(value.begin(), value.end());
|
2023-11-25 07:45:31 +00:00
|
|
|
}
|
|
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
this->riscVDebugInterface->writeMemory(
|
|
|
|
|
this->sysAddressSpaceDescriptor,
|
|
|
|
|
this->resolveRegisterMemorySegmentDescriptor(descriptor, this->sysAddressSpaceDescriptor),
|
|
|
|
|
descriptor.startAddress,
|
|
|
|
|
value
|
2023-11-25 07:45:31 +00:00
|
|
|
);
|
|
|
|
|
}
|
2023-11-22 00:38:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TargetMemoryBuffer RiscV::readMemory(
|
2024-07-23 21:14:22 +01:00
|
|
|
const TargetAddressSpaceDescriptor& addressSpaceDescriptor,
|
|
|
|
|
const TargetMemorySegmentDescriptor& memorySegmentDescriptor,
|
2023-11-22 00:38:40 +00:00
|
|
|
TargetMemoryAddress startAddress,
|
|
|
|
|
TargetMemorySize bytes,
|
2023-11-25 23:18:50 +00:00
|
|
|
const std::set<TargetMemoryAddressRange>& excludedAddressRanges
|
2023-11-22 00:38:40 +00:00
|
|
|
) {
|
2024-07-23 21:14:22 +01:00
|
|
|
assert(bytes > 0);
|
2023-11-25 19:09:14 +00:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
assert(addressSpaceDescriptor.addressRange.contains(startAddress));
|
|
|
|
|
assert(addressSpaceDescriptor.addressRange.contains(startAddress + bytes - 1));
|
2023-11-25 19:09:14 +00:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
assert(memorySegmentDescriptor.addressRange.contains(startAddress));
|
|
|
|
|
assert(memorySegmentDescriptor.addressRange.contains(startAddress + bytes - 1));
|
2023-11-25 19:09:14 +00:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
return this->riscVDebugInterface->readMemory(
|
|
|
|
|
addressSpaceDescriptor,
|
|
|
|
|
memorySegmentDescriptor,
|
|
|
|
|
startAddress,
|
|
|
|
|
bytes,
|
|
|
|
|
excludedAddressRanges
|
|
|
|
|
);
|
2023-11-22 00:38:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RiscV::writeMemory(
|
2024-07-23 21:14:22 +01:00
|
|
|
const TargetAddressSpaceDescriptor& addressSpaceDescriptor,
|
|
|
|
|
const TargetMemorySegmentDescriptor& memorySegmentDescriptor,
|
2023-11-22 00:38:40 +00:00
|
|
|
TargetMemoryAddress startAddress,
|
|
|
|
|
const TargetMemoryBuffer& buffer
|
|
|
|
|
) {
|
2024-07-23 21:14:22 +01:00
|
|
|
assert(!buffer.empty());
|
2023-11-22 00:38:40 +00:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
assert(addressSpaceDescriptor.addressRange.contains(startAddress));
|
|
|
|
|
assert(addressSpaceDescriptor.addressRange.contains(
|
|
|
|
|
static_cast<TargetMemoryAddress>(startAddress + buffer.size()) - 1)
|
|
|
|
|
);
|
2023-11-26 15:58:18 +00:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
assert(memorySegmentDescriptor.addressRange.contains(startAddress));
|
|
|
|
|
assert(memorySegmentDescriptor.addressRange.contains(
|
|
|
|
|
static_cast<TargetMemoryAddress>(startAddress + buffer.size()) - 1)
|
|
|
|
|
);
|
2023-11-26 15:58:18 +00:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
if (memorySegmentDescriptor.type == TargetMemorySegmentType::FLASH && this->riscVProgramInterface) {
|
2023-12-08 23:04:04 +00:00
|
|
|
return this->riscVProgramInterface->writeFlashMemory(startAddress, buffer);
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
return this->riscVDebugInterface->writeMemory(
|
|
|
|
|
addressSpaceDescriptor,
|
|
|
|
|
memorySegmentDescriptor,
|
|
|
|
|
startAddress,
|
|
|
|
|
buffer
|
|
|
|
|
);
|
|
|
|
|
}
|
2023-11-26 15:58:18 +00:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
bool RiscV::isProgramMemory(
|
|
|
|
|
const TargetAddressSpaceDescriptor& addressSpaceDescriptor,
|
|
|
|
|
const TargetMemorySegmentDescriptor& memorySegmentDescriptor,
|
|
|
|
|
TargetMemoryAddress startAddress,
|
|
|
|
|
TargetMemorySize size
|
|
|
|
|
) {
|
|
|
|
|
return memorySegmentDescriptor.executable;
|
2023-11-22 00:38:40 +00:00
|
|
|
}
|
|
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
void RiscV::eraseMemory(
|
|
|
|
|
const TargetAddressSpaceDescriptor& addressSpaceDescriptor,
|
|
|
|
|
const TargetMemorySegmentDescriptor& memorySegmentDescriptor
|
|
|
|
|
) {
|
2023-11-22 00:38:40 +00:00
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
TargetExecutionState RiscV::getExecutionState() {
|
|
|
|
|
return this->riscVDebugInterface->getExecutionState();
|
2023-11-22 00:38:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TargetMemoryAddress RiscV::getProgramCounter() {
|
2024-07-23 21:14:22 +01:00
|
|
|
const auto value = this->riscVDebugInterface->readCpuRegisters({&(this->pcRegisterDescriptor)}).at(0).second;
|
|
|
|
|
assert(value.size() == 4);
|
|
|
|
|
return static_cast<TargetMemoryAddress>(
|
|
|
|
|
(value[0] << 24) | (value[1] << 16) | (value[2] << 8) | (value[3])
|
|
|
|
|
);
|
2023-11-22 00:38:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RiscV::setProgramCounter(TargetMemoryAddress programCounter) {
|
2023-11-23 19:43:37 +00:00
|
|
|
// TODO: test this
|
2024-07-23 21:14:22 +01:00
|
|
|
this->riscVDebugInterface->writeCpuRegisters({
|
|
|
|
|
{
|
|
|
|
|
this->pcRegisterDescriptor,
|
|
|
|
|
TargetMemoryBuffer{
|
|
|
|
|
static_cast<unsigned char>(programCounter >> 24),
|
|
|
|
|
static_cast<unsigned char>(programCounter >> 16),
|
|
|
|
|
static_cast<unsigned char>(programCounter >> 8),
|
|
|
|
|
static_cast<unsigned char>(programCounter)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
2023-11-22 00:38:40 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
TargetStackPointer RiscV::getStackPointer() {
|
2024-07-23 21:14:22 +01:00
|
|
|
const auto value = this->riscVDebugInterface->readCpuRegisters({&(this->spRegisterDescriptor)}).at(0).second;
|
|
|
|
|
assert(value.size() == 4);
|
|
|
|
|
return static_cast<TargetStackPointer>(
|
|
|
|
|
(value[0] << 24) | (value[1] << 16) | (value[2] << 8) | (value[3])
|
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RiscV::setStackPointer(TargetStackPointer stackPointer) {
|
|
|
|
|
this->riscVDebugInterface->writeCpuRegisters({
|
|
|
|
|
{
|
|
|
|
|
this->spRegisterDescriptor,
|
|
|
|
|
TargetMemoryBuffer{
|
|
|
|
|
static_cast<unsigned char>(stackPointer >> 24),
|
|
|
|
|
static_cast<unsigned char>(stackPointer >> 16),
|
|
|
|
|
static_cast<unsigned char>(stackPointer >> 8),
|
|
|
|
|
static_cast<unsigned char>(stackPointer)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
});
|
2023-11-22 00:38:40 +00:00
|
|
|
}
|
|
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
TargetGpioPinDescriptorAndStatePairs RiscV::getGpioPinStates(const TargetPinoutDescriptor& pinoutDescriptor) {
|
2023-11-22 00:38:40 +00:00
|
|
|
return {};
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
void RiscV::setGpioPinState(const TargetPinDescriptor& pinDescriptor, const TargetGpioPinState& state) {
|
2023-11-22 00:38:40 +00:00
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RiscV::enableProgrammingMode() {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void RiscV::disableProgrammingMode() {
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool RiscV::programmingModeEnabled() {
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
const TargetMemorySegmentDescriptor& RiscV::resolveRegisterMemorySegmentDescriptor(
|
|
|
|
|
const TargetRegisterDescriptor& regDescriptor,
|
|
|
|
|
const TargetAddressSpaceDescriptor& addressSpaceDescriptor
|
|
|
|
|
) {
|
|
|
|
|
const auto segmentDescriptors = addressSpaceDescriptor.getIntersectingMemorySegmentDescriptors(
|
|
|
|
|
TargetMemoryAddressRange{
|
|
|
|
|
regDescriptor.startAddress,
|
|
|
|
|
(regDescriptor.startAddress + (regDescriptor.size / addressSpaceDescriptor.unitSize) - 1)
|
|
|
|
|
}
|
|
|
|
|
);
|
2023-11-24 15:19:52 +00:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
if (segmentDescriptors.empty()) {
|
|
|
|
|
throw Exceptions::Exception(
|
|
|
|
|
"Cannot access system register \"" + regDescriptor.key + "\" - unknown memory segment"
|
2023-11-24 15:19:52 +00:00
|
|
|
);
|
|
|
|
|
}
|
2023-11-23 12:56:26 +00:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
if (segmentDescriptors.size() != 1) {
|
|
|
|
|
throw Exceptions::Exception(
|
|
|
|
|
"Cannot access system register \"" + regDescriptor.key
|
|
|
|
|
+ "\" - register spans multiple memory segments"
|
|
|
|
|
);
|
2023-11-23 12:56:26 +00:00
|
|
|
}
|
2023-11-23 12:59:36 +00:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
return *(segmentDescriptors.front());
|
2023-11-23 12:56:26 +00:00
|
|
|
}
|
|
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
TargetAddressSpaceDescriptor RiscV::generateCpuRegisterAddressSpaceDescriptor() {
|
|
|
|
|
auto addressSpace = TargetAddressSpaceDescriptor{
|
|
|
|
|
"debug_module",
|
|
|
|
|
{0x0000, 0xFFFF},
|
|
|
|
|
TargetMemoryEndianness::LITTLE,
|
|
|
|
|
{},
|
|
|
|
|
4
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
addressSpace.segmentDescriptorsByKey.emplace(
|
|
|
|
|
"cs_registers",
|
|
|
|
|
TargetMemorySegmentDescriptor{
|
|
|
|
|
addressSpace.key,
|
|
|
|
|
"cs_registers",
|
|
|
|
|
"Control Status Registers",
|
|
|
|
|
TargetMemorySegmentType::REGISTERS,
|
|
|
|
|
{0x0000, 0x0FFF},
|
|
|
|
|
addressSpace.unitSize,
|
|
|
|
|
false,
|
|
|
|
|
{true, true},
|
|
|
|
|
{false, false},
|
|
|
|
|
std::nullopt
|
|
|
|
|
}
|
2023-11-23 17:46:32 +00:00
|
|
|
);
|
2023-11-22 00:38:40 +00:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
addressSpace.segmentDescriptorsByKey.emplace(
|
|
|
|
|
"gp_registers",
|
|
|
|
|
TargetMemorySegmentDescriptor{
|
|
|
|
|
addressSpace.key,
|
|
|
|
|
"gp_registers",
|
|
|
|
|
"General Purpose Registers",
|
|
|
|
|
TargetMemorySegmentType::GENERAL_PURPOSE_REGISTERS,
|
|
|
|
|
{0x1000, 0x101F},
|
|
|
|
|
addressSpace.unitSize,
|
|
|
|
|
false,
|
|
|
|
|
{true, true},
|
|
|
|
|
{false, false},
|
|
|
|
|
std::nullopt
|
|
|
|
|
}
|
2023-11-23 15:21:46 +00:00
|
|
|
);
|
2023-11-25 19:06:23 +00:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
return addressSpace;
|
2023-11-25 19:06:23 +00:00
|
|
|
}
|
|
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
TargetPeripheralDescriptor RiscV::generateCpuPeripheralDescriptor(
|
|
|
|
|
const TargetAddressSpaceDescriptor& addressSpaceDescriptor,
|
|
|
|
|
const TargetMemorySegmentDescriptor& csrMemorySegmentDescriptor,
|
|
|
|
|
const TargetMemorySegmentDescriptor& gprMemorySegmentDescriptor
|
|
|
|
|
) {
|
|
|
|
|
auto cpuPeripheralDescriptor = TargetPeripheralDescriptor{
|
|
|
|
|
"cpu",
|
|
|
|
|
"RISC-V CPU",
|
|
|
|
|
{},
|
|
|
|
|
{}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
auto& gprGroup = cpuPeripheralDescriptor.registerGroupDescriptorsByKey.emplace(
|
|
|
|
|
"gpr",
|
|
|
|
|
TargetRegisterGroupDescriptor{
|
|
|
|
|
"gpr",
|
|
|
|
|
"General Purpose Registers",
|
|
|
|
|
addressSpaceDescriptor.key,
|
|
|
|
|
std::nullopt,
|
|
|
|
|
{},
|
|
|
|
|
{}
|
|
|
|
|
}
|
|
|
|
|
).first->second;
|
|
|
|
|
|
|
|
|
|
for (auto i = std::uint8_t{0}; i <= 31; ++i) {
|
|
|
|
|
const auto key = "x" + std::to_string(i);
|
|
|
|
|
gprGroup.registerDescriptorsByKey.emplace(
|
|
|
|
|
key,
|
|
|
|
|
TargetRegisterDescriptor{
|
|
|
|
|
key,
|
|
|
|
|
"X" + std::to_string(i),
|
|
|
|
|
addressSpaceDescriptor.key,
|
|
|
|
|
gprMemorySegmentDescriptor.addressRange.startAddress + i,
|
|
|
|
|
4,
|
|
|
|
|
TargetRegisterType::GENERAL_PURPOSE_REGISTER,
|
|
|
|
|
TargetRegisterAccess(true, true),
|
|
|
|
|
std::nullopt,
|
|
|
|
|
{}
|
|
|
|
|
}
|
|
|
|
|
);
|
2023-11-25 19:06:23 +00:00
|
|
|
}
|
2023-11-23 16:32:53 +00:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
auto& csrGroup = cpuPeripheralDescriptor.registerGroupDescriptorsByKey.emplace(
|
|
|
|
|
"csr",
|
|
|
|
|
TargetRegisterGroupDescriptor{
|
|
|
|
|
"csr",
|
|
|
|
|
"Control Status Registers",
|
|
|
|
|
addressSpaceDescriptor.key,
|
|
|
|
|
std::nullopt,
|
|
|
|
|
{},
|
|
|
|
|
{}
|
|
|
|
|
}
|
|
|
|
|
).first->second;
|
|
|
|
|
|
|
|
|
|
csrGroup.registerDescriptorsByKey.emplace(
|
|
|
|
|
"marchid",
|
|
|
|
|
TargetRegisterDescriptor{
|
|
|
|
|
"marchid",
|
|
|
|
|
"MARCHID",
|
|
|
|
|
addressSpaceDescriptor.key,
|
|
|
|
|
csrMemorySegmentDescriptor.addressRange.startAddress + 0xF12,
|
|
|
|
|
4,
|
|
|
|
|
TargetRegisterType::OTHER,
|
|
|
|
|
TargetRegisterAccess(true, false),
|
|
|
|
|
"Architecture ID",
|
|
|
|
|
{}
|
|
|
|
|
}
|
|
|
|
|
);
|
2023-11-23 16:32:53 +00:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
csrGroup.registerDescriptorsByKey.emplace(
|
|
|
|
|
"mimpid",
|
|
|
|
|
TargetRegisterDescriptor{
|
|
|
|
|
"mimpid",
|
|
|
|
|
"MIMPID",
|
|
|
|
|
addressSpaceDescriptor.key,
|
|
|
|
|
csrMemorySegmentDescriptor.addressRange.startAddress + 0xF13,
|
|
|
|
|
4,
|
|
|
|
|
TargetRegisterType::OTHER,
|
|
|
|
|
TargetRegisterAccess(true, false),
|
|
|
|
|
"Implementation ID",
|
|
|
|
|
{}
|
|
|
|
|
}
|
|
|
|
|
);
|
2023-11-23 16:32:53 +00:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
csrGroup.registerDescriptorsByKey.emplace(
|
|
|
|
|
"mstatus",
|
|
|
|
|
TargetRegisterDescriptor{
|
|
|
|
|
"mstatus",
|
|
|
|
|
"MSTATUS",
|
|
|
|
|
addressSpaceDescriptor.key,
|
|
|
|
|
csrMemorySegmentDescriptor.addressRange.startAddress + 0x300,
|
|
|
|
|
4,
|
|
|
|
|
TargetRegisterType::OTHER,
|
|
|
|
|
TargetRegisterAccess(true, true),
|
|
|
|
|
"Machine status",
|
|
|
|
|
{}
|
|
|
|
|
}
|
|
|
|
|
);
|
2023-11-23 16:32:53 +00:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
csrGroup.registerDescriptorsByKey.emplace(
|
|
|
|
|
"misa",
|
|
|
|
|
TargetRegisterDescriptor{
|
|
|
|
|
"misa",
|
|
|
|
|
"MISA",
|
|
|
|
|
addressSpaceDescriptor.key,
|
|
|
|
|
csrMemorySegmentDescriptor.addressRange.startAddress + 0x301,
|
|
|
|
|
4,
|
|
|
|
|
TargetRegisterType::OTHER,
|
|
|
|
|
TargetRegisterAccess(true, true),
|
|
|
|
|
"ISA and extensions",
|
|
|
|
|
{}
|
|
|
|
|
}
|
|
|
|
|
);
|
2023-11-23 23:31:13 +00:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
csrGroup.registerDescriptorsByKey.emplace(
|
|
|
|
|
"mtvec",
|
|
|
|
|
TargetRegisterDescriptor{
|
|
|
|
|
"mtvec",
|
|
|
|
|
"MTVEC",
|
|
|
|
|
addressSpaceDescriptor.key,
|
|
|
|
|
csrMemorySegmentDescriptor.addressRange.startAddress + 0x305,
|
|
|
|
|
4,
|
|
|
|
|
TargetRegisterType::OTHER,
|
|
|
|
|
TargetRegisterAccess(true, true),
|
|
|
|
|
"Machine trap-handler base address",
|
|
|
|
|
{}
|
|
|
|
|
}
|
|
|
|
|
);
|
2023-11-23 16:32:53 +00:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
csrGroup.registerDescriptorsByKey.emplace(
|
|
|
|
|
"mcounteren",
|
|
|
|
|
TargetRegisterDescriptor{
|
|
|
|
|
"mcounteren",
|
|
|
|
|
"MCOUNTEREN",
|
|
|
|
|
addressSpaceDescriptor.key,
|
|
|
|
|
csrMemorySegmentDescriptor.addressRange.startAddress + 0x306,
|
|
|
|
|
4,
|
|
|
|
|
TargetRegisterType::OTHER,
|
|
|
|
|
TargetRegisterAccess(true, true),
|
|
|
|
|
"Machine counter enable",
|
|
|
|
|
{}
|
|
|
|
|
}
|
|
|
|
|
);
|
2023-11-23 16:32:53 +00:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
csrGroup.registerDescriptorsByKey.emplace(
|
|
|
|
|
"mscratch",
|
|
|
|
|
TargetRegisterDescriptor{
|
|
|
|
|
"mscratch",
|
|
|
|
|
"MSCRATCH",
|
|
|
|
|
addressSpaceDescriptor.key,
|
|
|
|
|
csrMemorySegmentDescriptor.addressRange.startAddress + 0x340,
|
|
|
|
|
4,
|
|
|
|
|
TargetRegisterType::OTHER,
|
|
|
|
|
TargetRegisterAccess(true, true),
|
|
|
|
|
"Scratch register for machine trap handlers",
|
|
|
|
|
{}
|
|
|
|
|
}
|
|
|
|
|
);
|
2023-11-23 16:32:53 +00:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
csrGroup.registerDescriptorsByKey.emplace(
|
|
|
|
|
"mepc",
|
|
|
|
|
TargetRegisterDescriptor{
|
|
|
|
|
"mepc",
|
|
|
|
|
"MEPC",
|
|
|
|
|
addressSpaceDescriptor.key,
|
|
|
|
|
csrMemorySegmentDescriptor.addressRange.startAddress + 0x341,
|
|
|
|
|
4,
|
|
|
|
|
TargetRegisterType::OTHER,
|
|
|
|
|
TargetRegisterAccess(true, true),
|
|
|
|
|
"Machine exception program counter",
|
|
|
|
|
{}
|
|
|
|
|
}
|
2023-11-23 23:31:13 +00:00
|
|
|
);
|
|
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
csrGroup.registerDescriptorsByKey.emplace(
|
|
|
|
|
"mcause",
|
|
|
|
|
TargetRegisterDescriptor{
|
|
|
|
|
"mcause",
|
|
|
|
|
"MCAUSE",
|
|
|
|
|
addressSpaceDescriptor.key,
|
|
|
|
|
csrMemorySegmentDescriptor.addressRange.startAddress + 0x342,
|
|
|
|
|
4,
|
|
|
|
|
TargetRegisterType::OTHER,
|
|
|
|
|
TargetRegisterAccess(true, true),
|
|
|
|
|
"Machine trap cause",
|
|
|
|
|
{}
|
|
|
|
|
}
|
2023-11-22 00:38:40 +00:00
|
|
|
);
|
2023-11-23 15:21:46 +00:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
csrGroup.registerDescriptorsByKey.emplace(
|
|
|
|
|
"mtval",
|
|
|
|
|
TargetRegisterDescriptor{
|
|
|
|
|
"mtval",
|
|
|
|
|
"MTVAL",
|
|
|
|
|
addressSpaceDescriptor.key,
|
|
|
|
|
csrMemorySegmentDescriptor.addressRange.startAddress + 0x343,
|
|
|
|
|
4,
|
|
|
|
|
TargetRegisterType::OTHER,
|
|
|
|
|
TargetRegisterAccess(true, true),
|
|
|
|
|
"Machine bad address or instruction",
|
|
|
|
|
{}
|
|
|
|
|
}
|
|
|
|
|
);
|
2023-11-23 16:34:35 +00:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
csrGroup.registerDescriptorsByKey.emplace(
|
|
|
|
|
"mip",
|
|
|
|
|
TargetRegisterDescriptor{
|
|
|
|
|
"mip",
|
|
|
|
|
"MIP",
|
|
|
|
|
addressSpaceDescriptor.key,
|
|
|
|
|
csrMemorySegmentDescriptor.addressRange.startAddress + 0x344,
|
|
|
|
|
4,
|
|
|
|
|
TargetRegisterType::OTHER,
|
|
|
|
|
TargetRegisterAccess(true, true),
|
|
|
|
|
"Machine interrupt pending",
|
|
|
|
|
{}
|
|
|
|
|
}
|
2023-11-23 15:21:46 +00:00
|
|
|
);
|
|
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
csrGroup.registerDescriptorsByKey.emplace(
|
|
|
|
|
"dcsr",
|
|
|
|
|
TargetRegisterDescriptor{
|
|
|
|
|
"dcsr",
|
|
|
|
|
"DCSR",
|
|
|
|
|
addressSpaceDescriptor.key,
|
|
|
|
|
csrMemorySegmentDescriptor.addressRange.startAddress + 0x7B0,
|
|
|
|
|
4,
|
|
|
|
|
TargetRegisterType::OTHER,
|
|
|
|
|
TargetRegisterAccess(true, true),
|
|
|
|
|
"Debug control and status",
|
|
|
|
|
{}
|
|
|
|
|
}
|
|
|
|
|
);
|
2023-11-23 15:21:46 +00:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
csrGroup.registerDescriptorsByKey.emplace(
|
|
|
|
|
"dpc",
|
|
|
|
|
TargetRegisterDescriptor{
|
|
|
|
|
"dpc",
|
|
|
|
|
"DPC",
|
|
|
|
|
addressSpaceDescriptor.key,
|
|
|
|
|
csrMemorySegmentDescriptor.addressRange.startAddress + 0x7B1,
|
|
|
|
|
4,
|
|
|
|
|
TargetRegisterType::OTHER,
|
|
|
|
|
TargetRegisterAccess(true, true),
|
|
|
|
|
"Debug program counter",
|
|
|
|
|
{}
|
|
|
|
|
}
|
|
|
|
|
);
|
2023-11-23 15:21:46 +00:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
csrGroup.registerDescriptorsByKey.emplace(
|
|
|
|
|
"dscratch0",
|
|
|
|
|
TargetRegisterDescriptor{
|
|
|
|
|
"dscratch0",
|
|
|
|
|
"DSCRATCH0",
|
|
|
|
|
addressSpaceDescriptor.key,
|
|
|
|
|
csrMemorySegmentDescriptor.addressRange.startAddress + 0x7B2,
|
|
|
|
|
4,
|
|
|
|
|
TargetRegisterType::OTHER,
|
|
|
|
|
TargetRegisterAccess(true, true),
|
|
|
|
|
"Debug scratch 0",
|
|
|
|
|
{}
|
|
|
|
|
}
|
|
|
|
|
);
|
2023-11-26 15:58:18 +00:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
csrGroup.registerDescriptorsByKey.emplace(
|
|
|
|
|
"dscratch1",
|
|
|
|
|
TargetRegisterDescriptor{
|
|
|
|
|
"dscratch1",
|
|
|
|
|
"DSCRATCH1",
|
|
|
|
|
addressSpaceDescriptor.key,
|
|
|
|
|
csrMemorySegmentDescriptor.addressRange.startAddress + 0x7B3,
|
|
|
|
|
4,
|
|
|
|
|
TargetRegisterType::OTHER,
|
|
|
|
|
TargetRegisterAccess(true, true),
|
|
|
|
|
"Debug scratch 1",
|
|
|
|
|
{}
|
|
|
|
|
}
|
|
|
|
|
);
|
2023-11-26 15:58:18 +00:00
|
|
|
|
2024-07-23 21:14:22 +01:00
|
|
|
return cpuPeripheralDescriptor;
|
2023-11-26 15:58:18 +00:00
|
|
|
}
|
2023-11-22 00:38:40 +00:00
|
|
|
}
|