Tidying RISC-V register structs

- Removed unnecessary bit fields
- Added default values to members
- Removed all user-defined constructors to make the structs aggregate, replacing the from-value constructor with a `fromValue()` status member function.
- Made use of designated initialisation
- Changed unscoped enums to scoped
- Other small bits of tidying
This commit is contained in:
Nav
2024-10-16 21:22:16 +01:00
parent 17b90e3c08
commit 348ec19c1b
16 changed files with 338 additions and 378 deletions

View File

@@ -62,7 +62,6 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
void DebugTranslator::init() {
// No pre-activation initialisation required.
return;
}
void DebugTranslator::activate() {
@@ -126,18 +125,19 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
}
void DebugTranslator::stop() {
auto controlRegister = ControlRegister{};
controlRegister.debugModuleActive = true;
controlRegister.selectedHartIndex = this->selectedHartIndex;
controlRegister.haltRequest = true;
auto controlRegister = ControlRegister{
.debugModuleActive = true,
.selectedHartIndex = this->selectedHartIndex,
.haltRequest = true,
};
this->writeDebugModuleControlRegister(controlRegister);
auto statusRegister = this->readDebugModuleStatusRegister();
for (
auto attempts = 1;
auto attempts = 0;
!statusRegister.allHalted
&& (DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY * attempts) < this->config.targetResponseTimeout;
&& (DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY * attempts) <= this->config.targetResponseTimeout;
++attempts
) {
std::this_thread::sleep_for(DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY);
@@ -153,18 +153,19 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
}
void DebugTranslator::run() {
auto controlRegister = ControlRegister{};
controlRegister.debugModuleActive = true;
controlRegister.selectedHartIndex = this->selectedHartIndex;
controlRegister.resumeRequest = true;
auto controlRegister = ControlRegister{
.debugModuleActive = true,
.selectedHartIndex = this->selectedHartIndex,
.resumeRequest = true,
};
this->writeDebugModuleControlRegister(controlRegister);
auto statusRegister = this->readDebugModuleStatusRegister();
for (
auto attempts = 1;
auto attempts = 0;
!statusRegister.allResumeAcknowledge
&& (DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY * attempts) < this->config.targetResponseTimeout;
&& (DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY * attempts) <= this->config.targetResponseTimeout;
++attempts
) {
std::this_thread::sleep_for(DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY);
@@ -175,6 +176,8 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
this->writeDebugModuleControlRegister(controlRegister);
if (!statusRegister.allResumeAcknowledge) {
Logger::debug("Failed to resume target execution - stopping target");
this->stop();
throw Exceptions::Exception{"Target took too long to acknowledge resume request"};
}
}
@@ -185,10 +188,11 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
this->writeDebugControlStatusRegister(debugControlStatusRegister);
auto controlRegister = ControlRegister{};
controlRegister.debugModuleActive = true;
controlRegister.selectedHartIndex = this->selectedHartIndex;
controlRegister.resumeRequest = true;
auto controlRegister = ControlRegister{
.debugModuleActive = true,
.selectedHartIndex = this->selectedHartIndex,
.resumeRequest = true,
};
this->writeDebugModuleControlRegister(controlRegister);
@@ -200,12 +204,13 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
}
void DebugTranslator::reset() {
auto controlRegister = ControlRegister{};
controlRegister.debugModuleActive = true;
controlRegister.selectedHartIndex = this->selectedHartIndex;
controlRegister.setResetHaltRequest = true;
controlRegister.haltRequest = true;
controlRegister.ndmReset = true;
auto controlRegister = ControlRegister{
.debugModuleActive = true,
.ndmReset = true,
.setResetHaltRequest = true,
.selectedHartIndex = this->selectedHartIndex,
.haltRequest = true,
};
this->writeDebugModuleControlRegister(controlRegister);
@@ -214,22 +219,21 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
auto statusRegister = this->readDebugModuleStatusRegister();
for (
auto attempts = 1;
auto attempts = 0;
!statusRegister.allHaveReset
&& (DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY * attempts) < this->config.targetResponseTimeout;
&& (DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY * attempts) <= this->config.targetResponseTimeout;
++attempts
) {
std::this_thread::sleep_for(DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY);
statusRegister = this->readDebugModuleStatusRegister();
}
controlRegister = ControlRegister{};
controlRegister.debugModuleActive = true;
controlRegister.selectedHartIndex = this->selectedHartIndex;
controlRegister.clearResetHaltRequest = true;
controlRegister.acknowledgeHaveReset = true;
this->writeDebugModuleControlRegister(controlRegister);
this->writeDebugModuleControlRegister(ControlRegister{
.debugModuleActive = true,
.clearResetHaltRequest = true,
.selectedHartIndex = this->selectedHartIndex,
.acknowledgeHaveReset = true,
});
if (!statusRegister.allHaveReset) {
throw Exceptions::Exception{"Target took too long to reset"};
@@ -258,7 +262,7 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
const auto& triggerDescriptor = triggerDescriptorOpt->get();
Logger::debug(
"Installing hardware BP at address " + Services::StringService::toHex(address) + " with trigger index "
"Installing hardware BP at address 0x" + Services::StringService::toHex(address) + " with trigger index "
+ std::to_string(triggerDescriptor.index)
);
@@ -270,16 +274,18 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
TriggerModule::Registers::TriggerSelect{triggerDescriptor.index}.value()
);
auto matchControlRegister = MatchControl{};
matchControlRegister.execute = true;
matchControlRegister.enabledInUserMode = true;
matchControlRegister.enabledInSupervisorMode = true;
matchControlRegister.enabledInMachineMode = true;
matchControlRegister.action = TriggerModule::TriggerAction::ENTER_DEBUG_MODE;
matchControlRegister.accessSize = MatchControl::AccessSize::ANY;
matchControlRegister.compareValueType = MatchControl::CompareValueType::ADDRESS;
this->writeCpuRegister(CpuRegisterNumber::TRIGGER_DATA_1, matchControlRegister.value());
this->writeCpuRegister(
CpuRegisterNumber::TRIGGER_DATA_1,
MatchControl{
.execute = true,
.enabledInUserMode = true,
.enabledInSupervisorMode = true,
.enabledInMachineMode = true,
.action = TriggerModule::TriggerAction::ENTER_DEBUG_MODE,
.accessSize = MatchControl::AccessSize::ANY,
.compareValueType = MatchControl::CompareValueType::ADDRESS,
}.value()
);
this->writeCpuRegister(CpuRegisterNumber::TRIGGER_DATA_2, address);
this->allocatedTriggerIndices.emplace(triggerDescriptor.index);
@@ -305,7 +311,7 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
void DebugTranslator::clearAllHardwareBreakpoints() {
// To ensure that any untracked breakpoints are cleared, we clear all triggers on the target.
for (const auto [triggerIndex, triggerDescriptor] : this->triggerDescriptorsByIndex) {
for (const auto& [triggerIndex, triggerDescriptor] : this->triggerDescriptorsByIndex) {
this->clearTrigger(triggerDescriptor);
}
@@ -386,13 +392,11 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
this->dtmInterface.writeDebugModuleRegister(RegisterAddress::ABSTRACT_DATA_1, startAddress);
constexpr auto command = AbstractCommandRegister{
MemoryAccessControlField{
false,
true,
MemoryAccessControlField::MemorySize::SIZE_32,
false
.control = MemoryAccessControlField{
.postIncrement = true,
.size = MemoryAccessControlField::MemorySize::SIZE_32,
}.value(),
AbstractCommandRegister::CommandType::MEMORY_ACCESS
.commandType = AbstractCommandRegister::CommandType::MEMORY_ACCESS
};
for (auto address = startAddress; address <= (startAddress + bytes - 1); address += 4) {
@@ -460,13 +464,12 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
this->dtmInterface.writeDebugModuleRegister(RegisterAddress::ABSTRACT_DATA_1, startAddress);
constexpr auto command = AbstractCommandRegister{
MemoryAccessControlField{
true,
true,
MemoryAccessControlField::MemorySize::SIZE_32,
false
.control = MemoryAccessControlField{
.write = true,
.postIncrement = true,
.size = MemoryAccessControlField::MemorySize::SIZE_32,
}.value(),
AbstractCommandRegister::CommandType::MEMORY_ACCESS
.commandType = AbstractCommandRegister::CommandType::MEMORY_ACCESS
};
for (TargetMemoryAddress offset = 0; offset < buffer.size(); offset += 4) {
@@ -491,11 +494,10 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
* We can obtain the maximum hart index by setting all of the hartsel bits in the control register and then
* read the value back.
*/
auto controlRegister = ControlRegister{};
controlRegister.debugModuleActive = true;
controlRegister.selectedHartIndex = 0xFFFFF;
this->writeDebugModuleControlRegister(
ControlRegister{.debugModuleActive = true, .selectedHartIndex = 0xFFFFF}
);
this->writeDebugModuleControlRegister(controlRegister);
const auto maxHartIndex = this->readDebugModuleControlRegister().selectedHartIndex;
for (auto hartIndex = DebugModule::HartIndex{0}; hartIndex <= maxHartIndex; ++hartIndex) {
@@ -503,11 +505,9 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
* We can't just assume that everything between 0 and the maximum hart index are valid hart indices. We
* have to test each index until we find one that is non-existent.
*/
auto controlRegister = ControlRegister{};
controlRegister.debugModuleActive = true;
controlRegister.selectedHartIndex = hartIndex;
this->writeDebugModuleControlRegister(controlRegister);
this->writeDebugModuleControlRegister(
ControlRegister{.debugModuleActive = true, .selectedHartIndex = hartIndex}
);
/*
* It's worth noting that some RISC-V targets **do not** set the non-existent flags. I'm not sure why.
@@ -544,7 +544,7 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
if (writeSelectError != DebugModule::AbstractCommandError::NONE) {
throw Exceptions::Exception{
"Failed to write to TRIGGER_SELECT register - abstract command error: 0x"
+ Services::StringService::toHex(writeSelectError)
+ Services::StringService::toHex(static_cast<std::uint8_t>(writeSelectError))
};
}
@@ -552,9 +552,9 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
break;
}
const auto infoReg = TriggerModule::Registers::TriggerInfo{
const auto infoReg = TriggerModule::Registers::TriggerInfo::fromValue(
this->readCpuRegister(CpuRegisterNumber::TRIGGER_INFO)
};
);
if (infoReg.info == 0x01) {
// Trigger doesn't exist
@@ -564,9 +564,9 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
auto supportedTypes = infoReg.getSupportedTriggerTypes();
if (supportedTypes.empty()) {
// The trigger info register has no trigger type info. Try the data1 register.
const auto data1Reg = TriggerModule::Registers::TriggerData1{
const auto data1Reg = TriggerModule::Registers::TriggerData1::fromValue(
this->readCpuRegister(CpuRegisterNumber::TRIGGER_DATA_1)
};
);
const auto triggerType = data1Reg.getType();
if (!triggerType.has_value()) {
@@ -584,37 +584,40 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
}
ControlRegister DebugTranslator::readDebugModuleControlRegister() {
return ControlRegister{this->dtmInterface.readDebugModuleRegister(RegisterAddress::CONTROL_REGISTER)};
return ControlRegister::fromValue(
this->dtmInterface.readDebugModuleRegister(RegisterAddress::CONTROL_REGISTER)
);
}
StatusRegister DebugTranslator::readDebugModuleStatusRegister() {
return StatusRegister{this->dtmInterface.readDebugModuleRegister(RegisterAddress::STATUS_REGISTER)};
return StatusRegister::fromValue(this->dtmInterface.readDebugModuleRegister(RegisterAddress::STATUS_REGISTER));
}
AbstractControlStatusRegister DebugTranslator::readDebugModuleAbstractControlStatusRegister() {
return AbstractControlStatusRegister{
return AbstractControlStatusRegister::fromValue(
this->dtmInterface.readDebugModuleRegister(RegisterAddress::ABSTRACT_CONTROL_STATUS_REGISTER)
};
);
}
DebugControlStatusRegister DebugTranslator::readDebugControlStatusRegister() {
return DebugControlStatusRegister{
return DebugControlStatusRegister::fromValue(
this->readCpuRegister(static_cast<RegisterNumber>(CpuRegisterNumber::DEBUG_CONTROL_STATUS_REGISTER))
};
);
}
void DebugTranslator::enableDebugModule() {
auto controlRegister = ControlRegister{};
controlRegister.debugModuleActive = true;
controlRegister.selectedHartIndex = this->selectedHartIndex;
auto controlRegister = ControlRegister{
.debugModuleActive = true,
.selectedHartIndex = this->selectedHartIndex
};
this->writeDebugModuleControlRegister(controlRegister);
controlRegister = this->readDebugModuleControlRegister();
for (
auto attempts = 1;
auto attempts = 0;
!controlRegister.debugModuleActive
&& (DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY * attempts) < this->config.targetResponseTimeout;
&& (DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY * attempts) <= this->config.targetResponseTimeout;
++attempts
) {
std::this_thread::sleep_for(DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY);
@@ -627,17 +630,16 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
}
void DebugTranslator::disableDebugModule() {
auto controlRegister = ControlRegister{};
controlRegister.debugModuleActive = false;
controlRegister.selectedHartIndex = this->selectedHartIndex;
this->writeDebugModuleControlRegister(
ControlRegister{.debugModuleActive = false, .selectedHartIndex = this->selectedHartIndex}
);
this->writeDebugModuleControlRegister(controlRegister);
controlRegister = this->readDebugModuleControlRegister();
auto controlRegister = this->readDebugModuleControlRegister();
for (
auto attempts = 1;
auto attempts = 0;
controlRegister.debugModuleActive
&& (DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY * attempts) < this->config.targetResponseTimeout;
&& (DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY * attempts) <= this->config.targetResponseTimeout;
++attempts
) {
std::this_thread::sleep_for(DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY);
@@ -655,15 +657,12 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
using DebugModule::Registers::RegisterAccessControlField;
const auto commandError = this->tryExecuteAbstractCommand(AbstractCommandRegister{
RegisterAccessControlField{
number,
false,
true,
false,
false,
RegisterAccessControlField::RegisterSize::SIZE_32
.control = RegisterAccessControlField{
.registerNumber = number,
.transfer = true,
.size= RegisterAccessControlField::RegisterSize::SIZE_32
}.value(),
AbstractCommandRegister::CommandType::REGISTER_ACCESS
.commandType = AbstractCommandRegister::CommandType::REGISTER_ACCESS
});
if (commandError != DebugModule::AbstractCommandError::NONE) {
@@ -685,7 +684,8 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
if (!result.hasValue()) {
throw Exceptions::Exception{
"Failed to read CPU register (number: 0x" + Services::StringService::toHex(number)
+ ") - abstract command error: 0x" + Services::StringService::toHex(result.error())
+ ") - abstract command error: 0x"
+ Services::StringService::toHex(static_cast<std::uint8_t>(result.error()))
};
}
@@ -704,15 +704,13 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
this->dtmInterface.writeDebugModuleRegister(RegisterAddress::ABSTRACT_DATA_0, value);
return this->tryExecuteAbstractCommand(AbstractCommandRegister{
RegisterAccessControlField{
number,
true,
true,
false,
false,
RegisterAccessControlField::RegisterSize::SIZE_32
.control = RegisterAccessControlField{
.registerNumber = number,
.write = true,
.transfer = true,
.size = RegisterAccessControlField::RegisterSize::SIZE_32
}.value(),
AbstractCommandRegister::CommandType::REGISTER_ACCESS
.commandType = AbstractCommandRegister::CommandType::REGISTER_ACCESS
});
}
@@ -728,7 +726,8 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
if (commandError != DebugModule::AbstractCommandError::NONE) {
throw Exceptions::Exception{
"Failed to write to CPU register (number: 0x" + Services::StringService::toHex(number)
+ ") - abstract command error: 0x" + Services::StringService::toHex(commandError)
+ ") - abstract command error: 0x"
+ Services::StringService::toHex(static_cast<std::uint8_t>(commandError))
};
}
}
@@ -762,9 +761,9 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
}
for (
auto attempts = 1;
auto attempts = 0;
abstractStatusRegister.busy
&& (DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY * attempts) < this->config.targetResponseTimeout;
&& (DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY * attempts) <= this->config.targetResponseTimeout;
++attempts
) {
std::this_thread::sleep_for(DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY);
@@ -784,7 +783,8 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
const auto commandError = this->tryExecuteAbstractCommand(abstractCommandRegister);
if (commandError != DebugModule::AbstractCommandError::NONE) {
throw Exceptions::Exception{
"Failed to execute abstract command - error: 0x" + Services::StringService::toHex(commandError)
"Failed to execute abstract command - error: 0x"
+ Services::StringService::toHex(static_cast<std::uint8_t>(commandError))
};
}
}