diff --git a/src/Targets/RiscV/Registers/DebugControlStatusRegister.hpp b/src/Targets/RiscV/Registers/DebugControlStatusRegister.hpp new file mode 100644 index 00000000..4c1d8625 --- /dev/null +++ b/src/Targets/RiscV/Registers/DebugControlStatusRegister.hpp @@ -0,0 +1,74 @@ +#pragma once + +#include + +#include "src/Targets/RiscV/RiscVGeneric.hpp" + +namespace Targets::RiscV::Registers +{ + struct DebugControlStatusRegister + { + enum class DebugModeCause: std::uint8_t + { + BREAK = 0x01, + TRIGGER = 0x02, + HALT_REQUEST = 0x03, + STEP = 0x04, + RESET_HALT_REQUEST = 0x05, + GROUP = 0x06, + }; + + PrivilegeMode privilegeMode:2; + bool step:1 = false; + bool nmiPending:1 = false; + bool mprvEnabled:1 = false; + DebugModeCause debugModeCause:3; + bool stopTime:1 = false; + bool stopCount:1 = false; + bool stepInterruptsEnabled:1 = false; + bool breakUMode:1 = false; + bool breakSMode:1 = false; + bool breakMMode:1 = false; + bool breakVUMode:1 = false; + bool breakVSMode:1 = false; + std::uint8_t debugVersion:4 = 0; + + DebugControlStatusRegister() = default; + + constexpr explicit DebugControlStatusRegister(RegisterValue registerValue) + : privilegeMode(static_cast(registerValue & 0x03)) + , step(static_cast(registerValue & (0x01 << 2))) + , nmiPending(static_cast(registerValue & (0x01 << 3))) + , mprvEnabled(static_cast(registerValue & (0x01 << 4))) + , debugModeCause(static_cast((registerValue >> 6) & 0x07)) + , stopTime(static_cast(registerValue & (0x01 << 9))) + , stopCount(static_cast(registerValue & (0x01 << 10))) + , stepInterruptsEnabled(static_cast(registerValue & (0x01 << 11))) + , breakUMode(static_cast(registerValue & (0x01 << 12))) + , breakSMode(static_cast(registerValue & (0x01 << 13))) + , breakMMode(static_cast(registerValue & (0x01 << 15))) + , breakVUMode(static_cast(registerValue & (0x01 << 16))) + , breakVSMode(static_cast(registerValue & (0x01 << 17))) + , debugVersion(static_cast(registerValue >> 28) & 0x0F) + {} + + constexpr RegisterValue value() const { + return RegisterValue{0} + | static_cast(this->privilegeMode) + | static_cast(this->step) << 2 + | static_cast(this->nmiPending) << 3 + | static_cast(this->mprvEnabled) << 4 + | static_cast(this->debugModeCause) << 6 + | static_cast(this->stopTime) << 9 + | static_cast(this->stopCount) << 10 + | static_cast(this->stepInterruptsEnabled) << 11 + | static_cast(this->breakUMode) << 12 + | static_cast(this->breakSMode) << 13 + | static_cast(this->breakMMode) << 15 + | static_cast(this->breakVUMode) << 16 + | static_cast(this->breakVSMode) << 17 + | static_cast(this->debugVersion) << 28 + ; + } + }; +} diff --git a/src/Targets/RiscV/RiscV.cpp b/src/Targets/RiscV/RiscV.cpp index 40eb2e73..a9dc7bb2 100644 --- a/src/Targets/RiscV/RiscV.cpp +++ b/src/Targets/RiscV/RiscV.cpp @@ -14,6 +14,8 @@ namespace Targets::RiscV { using Registers::RegisterNumber; + using Registers::DebugControlStatusRegister; + using DebugModule::Registers::RegisterAddresses; using DebugModule::Registers::ControlRegister; using DebugModule::Registers::StatusRegister; @@ -142,7 +144,23 @@ namespace Targets::RiscV } void RiscV::step() { + auto debugControlStatusRegister = this->readDebugControlStatusRegister(); + debugControlStatusRegister.step = true; + this->writeDebugControlStatusRegister(debugControlStatusRegister); + + auto controlRegister = ControlRegister(); + controlRegister.debugModuleActive = true; + controlRegister.selectedHartIndex = this->selectedHartIndex; + controlRegister.resumeRequest = true; + + this->writeDebugModuleControlRegister(controlRegister); + + controlRegister.resumeRequest = false; + this->writeDebugModuleControlRegister(controlRegister); + + debugControlStatusRegister.step = false; + this->writeDebugControlStatusRegister(debugControlStatusRegister); } void RiscV::reset() { @@ -295,6 +313,10 @@ namespace Targets::RiscV ); } + DebugControlStatusRegister RiscV::readDebugControlStatusRegister() { + return DebugControlStatusRegister(this->readRegister(RegisterNumber::DEBUG_CONTROL_STATUS_REGISTER)); + } + RegisterValue RiscV::readRegister(RegisterNumber number) { using DebugModule::Registers::RegisterAccessControlField; @@ -339,6 +361,10 @@ namespace Targets::RiscV ); } + void RiscV::writeDebugControlStatusRegister(const DebugControlStatusRegister& controlRegister) { + this->writeRegister(RegisterNumber::DEBUG_CONTROL_STATUS_REGISTER, controlRegister.value()); + } + void RiscV::executeAbstractCommand( const DebugModule::Registers::AbstractCommandRegister& abstractCommandRegister ) { diff --git a/src/Targets/RiscV/RiscV.hpp b/src/Targets/RiscV/RiscV.hpp index 0affbdbd..5c87c160 100644 --- a/src/Targets/RiscV/RiscV.hpp +++ b/src/Targets/RiscV/RiscV.hpp @@ -9,6 +9,8 @@ #include "src/DebugToolDrivers/TargetInterfaces/RiscV/RiscVDebugInterface.hpp" #include "src/Targets/RiscV/RiscVGeneric.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" @@ -104,10 +106,12 @@ namespace Targets::RiscV DebugModule::Registers::StatusRegister readDebugModuleStatusRegister(); DebugModule::Registers::AbstractControlStatusRegister readDebugModuleAbstractControlStatusRegister(); + Registers::DebugControlStatusRegister readDebugControlStatusRegister(); RegisterValue readRegister(Registers::RegisterNumber number); void writeRegister(Registers::RegisterNumber number, RegisterValue value); + void writeDebugControlStatusRegister(const Registers::DebugControlStatusRegister& controlRegister); void writeDebugModuleControlRegister(const DebugModule::Registers::ControlRegister &controlRegister); void executeAbstractCommand(const DebugModule::Registers::AbstractCommandRegister& abstractCommandRegister);