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:
@@ -22,7 +22,7 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec::DebugModule
|
|||||||
BUSY = 0x03,
|
BUSY = 0x03,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum AbstractCommandError: std::uint8_t
|
enum class AbstractCommandError: std::uint8_t
|
||||||
{
|
{
|
||||||
NONE = 0x00,
|
NONE = 0x00,
|
||||||
BUSY = 0x01,
|
BUSY = 0x01,
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec::DebugModule::Registers
|
|||||||
{
|
{
|
||||||
struct AbstractCommandRegister
|
struct AbstractCommandRegister
|
||||||
{
|
{
|
||||||
enum CommandType: std::uint8_t
|
enum class CommandType: std::uint8_t
|
||||||
{
|
{
|
||||||
REGISTER_ACCESS = 0x00,
|
REGISTER_ACCESS = 0x00,
|
||||||
QUICK_ACCESS = 0x01,
|
QUICK_ACCESS = 0x01,
|
||||||
@@ -19,15 +19,12 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec::DebugModule::Registers
|
|||||||
std::uint32_t control;
|
std::uint32_t control;
|
||||||
CommandType commandType;
|
CommandType commandType;
|
||||||
|
|
||||||
constexpr AbstractCommandRegister(std::uint32_t control, CommandType commandType)
|
static constexpr AbstractCommandRegister fromValue(RegisterValue value) {
|
||||||
: control(control)
|
return {
|
||||||
, commandType(commandType)
|
.control = static_cast<std::uint32_t>(value & 0x00FFFFFF),
|
||||||
{}
|
.commandType = static_cast<CommandType>((value >> 24) & 0xFF),
|
||||||
|
};
|
||||||
constexpr explicit AbstractCommandRegister(RegisterValue registerValue)
|
}
|
||||||
: control(static_cast<std::uint32_t>(registerValue & 0x00FFFFFF))
|
|
||||||
, commandType(static_cast<CommandType>((registerValue >> 24) & 0xFF))
|
|
||||||
{}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr RegisterValue value() const {
|
[[nodiscard]] constexpr RegisterValue value() const {
|
||||||
assert(this->control <= 0x00FFFFFF);
|
assert(this->control <= 0x00FFFFFF);
|
||||||
|
|||||||
@@ -8,27 +8,29 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec::DebugModule::Registers
|
|||||||
{
|
{
|
||||||
struct AbstractControlStatusRegister
|
struct AbstractControlStatusRegister
|
||||||
{
|
{
|
||||||
std::uint8_t dataCount:4;
|
std::uint8_t dataCount = 0;
|
||||||
AbstractCommandError commandError:3;
|
AbstractCommandError commandError = AbstractCommandError::NONE;
|
||||||
bool relaxedPrivilege:1;
|
bool relaxedPrivilege = false;
|
||||||
bool busy:1;
|
bool busy = false;
|
||||||
std::uint8_t programBufferSize:5;
|
std::uint8_t programBufferSize = 0;
|
||||||
|
|
||||||
constexpr explicit AbstractControlStatusRegister(RegisterValue registerValue)
|
static constexpr AbstractControlStatusRegister fromValue(RegisterValue value) {
|
||||||
: dataCount(static_cast<std::uint8_t>(registerValue & 0x0F))
|
return {
|
||||||
, commandError(static_cast<AbstractCommandError>((registerValue >> 8) & 0x07))
|
.dataCount = static_cast<std::uint8_t>(value & 0x0F),
|
||||||
, relaxedPrivilege(static_cast<bool>(registerValue & (0x01 << 11)))
|
.commandError = static_cast<AbstractCommandError>((value >> 8) & 0x07),
|
||||||
, busy(static_cast<bool>(registerValue & (0x01 << 12)))
|
.relaxedPrivilege = static_cast<bool>(value & (0x01 << 11)),
|
||||||
, programBufferSize(static_cast<std::uint8_t>((registerValue >> 24) & 0x1F))
|
.busy = static_cast<bool>(value & (0x01 << 12)),
|
||||||
{}
|
.programBufferSize = static_cast<std::uint8_t>((value >> 24) & 0x1F),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] constexpr RegisterValue value() const {
|
[[nodiscard]] constexpr RegisterValue value() const {
|
||||||
return RegisterValue{0}
|
return RegisterValue{0}
|
||||||
| static_cast<RegisterValue>(this->dataCount)
|
| static_cast<RegisterValue>(this->dataCount & 0x0F)
|
||||||
| static_cast<RegisterValue>(this->commandError) << 8
|
| static_cast<RegisterValue>(this->commandError) << 8
|
||||||
| static_cast<RegisterValue>(this->relaxedPrivilege) << 11
|
| static_cast<RegisterValue>(this->relaxedPrivilege) << 11
|
||||||
| static_cast<RegisterValue>(this->busy) << 12
|
| static_cast<RegisterValue>(this->busy) << 12
|
||||||
| static_cast<RegisterValue>(this->programBufferSize) << 24
|
| static_cast<RegisterValue>(this->programBufferSize & 0x1F) << 24
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,43 +9,50 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec::DebugModule::Registers
|
|||||||
{
|
{
|
||||||
struct ControlRegister
|
struct ControlRegister
|
||||||
{
|
{
|
||||||
enum HartSelectionMode: std::uint8_t
|
enum class HartSelectionMode: std::uint8_t
|
||||||
{
|
{
|
||||||
SINGLE = 0x00,
|
SINGLE = 0x00,
|
||||||
MULTI = 0x01,
|
MULTI = 0x01,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool debugModuleActive:1 = false;
|
bool debugModuleActive = false;
|
||||||
bool ndmReset:1 = false;
|
bool ndmReset = false;
|
||||||
bool clearResetHaltRequest:1 = false;
|
bool clearResetHaltRequest = false;
|
||||||
bool setResetHaltRequest:1 = false;
|
bool setResetHaltRequest = false;
|
||||||
bool clearKeepAlive:1 = false;
|
bool clearKeepAlive = false;
|
||||||
bool setKeepAlive:1 = false;
|
bool setKeepAlive = false;
|
||||||
HartIndex selectedHartIndex = 0;
|
HartIndex selectedHartIndex = 0;
|
||||||
HartSelectionMode hartSelectionMode:1 = HartSelectionMode::SINGLE;
|
HartSelectionMode hartSelectionMode = HartSelectionMode::SINGLE;
|
||||||
bool acknowledgeUnavailableHarts:1 = false;
|
bool acknowledgeUnavailableHarts = false;
|
||||||
bool acknowledgeHaveReset:1 = false;
|
bool acknowledgeHaveReset = false;
|
||||||
bool hartReset:1 = false;
|
bool hartReset = false;
|
||||||
bool resumeRequest:1 = false;
|
bool resumeRequest = false;
|
||||||
bool haltRequest:1 = false;
|
bool haltRequest = false;
|
||||||
|
|
||||||
ControlRegister() = default;
|
/**
|
||||||
|
* These `fromValue()` functions cannot be constructors because we'd lose designated initialisation (as the
|
||||||
constexpr explicit ControlRegister(RegisterValue registerValue)
|
* structs would no longer be aggregates - structs with user-defined constructors cannot be aggregates).
|
||||||
: debugModuleActive(static_cast<bool>(registerValue & 0x01))
|
*
|
||||||
, ndmReset(static_cast<bool>(registerValue & (0x01 << 1)))
|
* @param value
|
||||||
, clearResetHaltRequest(static_cast<bool>(registerValue & (0x01 << 2)))
|
* @return
|
||||||
, setResetHaltRequest(static_cast<bool>(registerValue & (0x01 << 3)))
|
*/
|
||||||
, clearKeepAlive(static_cast<bool>(registerValue & (0x01 << 4)))
|
static constexpr auto fromValue(RegisterValue value) {
|
||||||
, setKeepAlive(static_cast<bool>(registerValue & (0x01 << 5)))
|
return ControlRegister{
|
||||||
, selectedHartIndex((((registerValue >> 6) & 0x3FF) << 10) | ((registerValue >> 16) & 0x3FF))
|
.debugModuleActive = static_cast<bool>(value & 0x01),
|
||||||
, hartSelectionMode(static_cast<HartSelectionMode>(registerValue & (0x01 << 26)))
|
.ndmReset = static_cast<bool>(value & (0x01 << 1)),
|
||||||
, acknowledgeUnavailableHarts(static_cast<bool>(registerValue & (0x01 << 27)))
|
.clearResetHaltRequest = static_cast<bool>(value & (0x01 << 2)),
|
||||||
, acknowledgeHaveReset(static_cast<bool>(registerValue & (0x01 << 28)))
|
.setResetHaltRequest = static_cast<bool>(value & (0x01 << 3)),
|
||||||
, hartReset(static_cast<bool>(registerValue & (0x01 << 29)))
|
.clearKeepAlive = static_cast<bool>(value & (0x01 << 4)),
|
||||||
, resumeRequest(static_cast<bool>(registerValue & (0x01 << 30)))
|
.setKeepAlive = static_cast<bool>(value & (0x01 << 5)),
|
||||||
, haltRequest(static_cast<bool>(registerValue & static_cast<std::uint32_t>(0x01 << 31)))
|
.selectedHartIndex = (((value >> 6) & 0x3FF) << 10) | ((value >> 16) & 0x3FF),
|
||||||
{}
|
.hartSelectionMode = static_cast<HartSelectionMode>(value & (0x01 << 26)),
|
||||||
|
.acknowledgeUnavailableHarts = static_cast<bool>(value & (0x01 << 27)),
|
||||||
|
.acknowledgeHaveReset = static_cast<bool>(value & (0x01 << 28)),
|
||||||
|
.hartReset = static_cast<bool>(value & (0x01 << 29)),
|
||||||
|
.resumeRequest = static_cast<bool>(value & (0x01 << 30)),
|
||||||
|
.haltRequest = static_cast<bool>(value & static_cast<std::uint32_t>(0x01 << 31)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] constexpr RegisterValue value() const {
|
[[nodiscard]] constexpr RegisterValue value() const {
|
||||||
assert(this->selectedHartIndex <= 0xFFFFF);
|
assert(this->selectedHartIndex <= 0xFFFFF);
|
||||||
|
|||||||
@@ -17,29 +17,19 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec::DebugModule::Registers
|
|||||||
SIZE_128 = 0x04,
|
SIZE_128 = 0x04,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool write:1;
|
bool write = false;
|
||||||
bool postIncrement:1;
|
bool postIncrement = false;
|
||||||
MemorySize size:3;
|
MemorySize size = MemorySize::SIZE_8;
|
||||||
bool virtualAddress:1;
|
bool virtualAddress = false;
|
||||||
|
|
||||||
constexpr MemoryAccessControlField(
|
static constexpr auto fromValue(std::uint32_t value) {
|
||||||
bool write,
|
return MemoryAccessControlField{
|
||||||
bool postIncrement,
|
.write = static_cast<bool>(value & (0x01 << 16)),
|
||||||
MemorySize size,
|
.postIncrement = static_cast<bool>(value & (0x01 << 19)),
|
||||||
bool virtualAddress
|
.size = static_cast<MemorySize>((value >> 20) & 0x07),
|
||||||
)
|
.virtualAddress = static_cast<bool>(value & (0x01 << 23)),
|
||||||
: write(write)
|
};
|
||||||
, postIncrement(postIncrement)
|
}
|
||||||
, size(size)
|
|
||||||
, virtualAddress(virtualAddress)
|
|
||||||
{}
|
|
||||||
|
|
||||||
constexpr explicit MemoryAccessControlField(std::uint32_t controlValue)
|
|
||||||
: write(static_cast<bool>(controlValue & (0x01 << 16)))
|
|
||||||
, postIncrement(static_cast<bool>(controlValue & (0x01 << 19)))
|
|
||||||
, size(static_cast<MemorySize>((controlValue >> 20) & 0x07))
|
|
||||||
, virtualAddress(static_cast<bool>(controlValue & (0x01 << 23)))
|
|
||||||
{}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr std::uint32_t value() const {
|
[[nodiscard]] constexpr std::uint32_t value() const {
|
||||||
return std::uint32_t{0}
|
return std::uint32_t{0}
|
||||||
|
|||||||
@@ -15,37 +15,23 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec::DebugModule::Registers
|
|||||||
SIZE_128 = 0x04,
|
SIZE_128 = 0x04,
|
||||||
};
|
};
|
||||||
|
|
||||||
RegisterNumber registerNumber;
|
RegisterNumber registerNumber = 0;
|
||||||
bool write:1;
|
bool write = false;
|
||||||
bool transfer:1;
|
bool transfer = false;
|
||||||
bool postExecute:1;
|
bool postExecute = false;
|
||||||
bool postIncrement:1;
|
bool postIncrement = false;
|
||||||
RegisterSize size:3;
|
RegisterSize size = RegisterSize::SIZE_32;
|
||||||
|
|
||||||
RegisterAccessControlField(
|
static constexpr auto fromValue(std::uint32_t value) {
|
||||||
RegisterNumber registerNumber,
|
return RegisterAccessControlField{
|
||||||
bool write,
|
.registerNumber = static_cast<RegisterNumber>(value & 0xFFFF),
|
||||||
bool transfer,
|
.write = static_cast<bool>(value & (0x01 << 16)),
|
||||||
bool postExecute,
|
.transfer = static_cast<bool>(value & (0x01 << 17)),
|
||||||
bool postIncrement,
|
.postExecute = static_cast<bool>(value & (0x01 << 18)),
|
||||||
RegisterSize size
|
.postIncrement = static_cast<bool>(value & (0x01 << 19)),
|
||||||
)
|
.size = static_cast<RegisterSize>((value >> 20) & 0x07),
|
||||||
: registerNumber(registerNumber)
|
};
|
||||||
, write(write)
|
}
|
||||||
, transfer(transfer)
|
|
||||||
, postExecute(postExecute)
|
|
||||||
, postIncrement(postIncrement)
|
|
||||||
, size(size)
|
|
||||||
{}
|
|
||||||
|
|
||||||
constexpr explicit RegisterAccessControlField(std::uint32_t controlValue)
|
|
||||||
: registerNumber(static_cast<RegisterNumber>(controlValue & 0xFFFF))
|
|
||||||
, write(static_cast<bool>(controlValue & (0x01 << 16)))
|
|
||||||
, transfer(static_cast<bool>(controlValue & (0x01 << 17)))
|
|
||||||
, postExecute(static_cast<bool>(controlValue & (0x01 << 18)))
|
|
||||||
, postIncrement(static_cast<bool>(controlValue & (0x01 << 19)))
|
|
||||||
, size(static_cast<RegisterSize>((controlValue >> 20) & 0x07))
|
|
||||||
{}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr std::uint32_t value() const {
|
[[nodiscard]] constexpr std::uint32_t value() const {
|
||||||
return std::uint32_t{0}
|
return std::uint32_t{0}
|
||||||
|
|||||||
@@ -8,53 +8,55 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec::DebugModule::Registers
|
|||||||
{
|
{
|
||||||
struct StatusRegister
|
struct StatusRegister
|
||||||
{
|
{
|
||||||
std::uint8_t version:4;
|
std::uint8_t version = 0;
|
||||||
bool validConfigStructurePointer:1;
|
bool validConfigStructurePointer = false;
|
||||||
bool supportsResetHalt:1;
|
bool supportsResetHalt = false;
|
||||||
bool authBusy:1;
|
bool authBusy = false;
|
||||||
bool authenticated:1;
|
bool authenticated = false;
|
||||||
bool anyHalted:1;
|
bool anyHalted = false;
|
||||||
bool allHalted:1;
|
bool allHalted = false;
|
||||||
bool anyRunning:1;
|
bool anyRunning = false;
|
||||||
bool allRunning:1;
|
bool allRunning = false;
|
||||||
bool anyUnavailable:1;
|
bool anyUnavailable = false;
|
||||||
bool allUnavailable:1;
|
bool allUnavailable = false;
|
||||||
bool anyNonExistent:1;
|
bool anyNonExistent = false;
|
||||||
bool allNonExistent:1;
|
bool allNonExistent = false;
|
||||||
bool anyResumeAcknowledge:1;
|
bool anyResumeAcknowledge = false;
|
||||||
bool allResumeAcknowledge:1;
|
bool allResumeAcknowledge = false;
|
||||||
bool anyHaveReset:1;
|
bool anyHaveReset = false;
|
||||||
bool allHaveReset:1;
|
bool allHaveReset = false;
|
||||||
bool implicitBreak:1;
|
bool implicitBreak = false;
|
||||||
bool stickyUnavailableBits:1;
|
bool stickyUnavailableBits = false;
|
||||||
bool ndmResetPending:1;
|
bool ndmResetPending = false;
|
||||||
|
|
||||||
constexpr explicit StatusRegister(RegisterValue registerValue)
|
static constexpr StatusRegister fromValue(RegisterValue value) {
|
||||||
: version(static_cast<std::uint8_t>(registerValue & 0x0F))
|
return {
|
||||||
, validConfigStructurePointer(static_cast<bool>(registerValue & (0x01 << 4)))
|
.version = static_cast<std::uint8_t>(value & 0x0F),
|
||||||
, supportsResetHalt(static_cast<bool>(registerValue & (0x01 << 5)))
|
.validConfigStructurePointer = static_cast<bool>(value & (0x01 << 4)),
|
||||||
, authBusy(static_cast<bool>(registerValue & (0x01 << 6)))
|
.supportsResetHalt = static_cast<bool>(value & (0x01 << 5)),
|
||||||
, authenticated(static_cast<bool>(registerValue & (0x01 << 7)))
|
.authBusy = static_cast<bool>(value & (0x01 << 6)),
|
||||||
, anyHalted(static_cast<bool>(registerValue & (0x01 << 8)))
|
.authenticated = static_cast<bool>(value & (0x01 << 7)),
|
||||||
, allHalted(static_cast<bool>(registerValue & (0x01 << 9)))
|
.anyHalted = static_cast<bool>(value & (0x01 << 8)),
|
||||||
, anyRunning(static_cast<bool>(registerValue & (0x01 << 10)))
|
.allHalted = static_cast<bool>(value & (0x01 << 9)),
|
||||||
, allRunning(static_cast<bool>(registerValue & (0x01 << 11)))
|
.anyRunning = static_cast<bool>(value & (0x01 << 10)),
|
||||||
, anyUnavailable(static_cast<bool>(registerValue & (0x01 << 12)))
|
.allRunning = static_cast<bool>(value & (0x01 << 11)),
|
||||||
, allUnavailable(static_cast<bool>(registerValue & (0x01 << 13)))
|
.anyUnavailable = static_cast<bool>(value & (0x01 << 12)),
|
||||||
, anyNonExistent(static_cast<bool>(registerValue & (0x01 << 14)))
|
.allUnavailable = static_cast<bool>(value & (0x01 << 13)),
|
||||||
, allNonExistent(static_cast<bool>(registerValue & (0x01 << 15)))
|
.anyNonExistent = static_cast<bool>(value & (0x01 << 14)),
|
||||||
, anyResumeAcknowledge(static_cast<bool>(registerValue & (0x01 << 16)))
|
.allNonExistent = static_cast<bool>(value & (0x01 << 15)),
|
||||||
, allResumeAcknowledge(static_cast<bool>(registerValue & (0x01 << 17)))
|
.anyResumeAcknowledge = static_cast<bool>(value & (0x01 << 16)),
|
||||||
, anyHaveReset(static_cast<bool>(registerValue & (0x01 << 18)))
|
.allResumeAcknowledge = static_cast<bool>(value & (0x01 << 17)),
|
||||||
, allHaveReset(static_cast<bool>(registerValue & (0x01 << 19)))
|
.anyHaveReset = static_cast<bool>(value & (0x01 << 18)),
|
||||||
, implicitBreak(static_cast<bool>(registerValue & (0x01 << 22)))
|
.allHaveReset = static_cast<bool>(value & (0x01 << 19)),
|
||||||
, stickyUnavailableBits(static_cast<bool>(registerValue & (0x01 << 23)))
|
.implicitBreak = static_cast<bool>(value & (0x01 << 22)),
|
||||||
, ndmResetPending(static_cast<bool>(registerValue & (0x01 << 24)))
|
.stickyUnavailableBits = static_cast<bool>(value & (0x01 << 23)),
|
||||||
{}
|
.ndmResetPending = static_cast<bool>(value & (0x01 << 24)),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] constexpr RegisterValue value() const {
|
[[nodiscard]] constexpr RegisterValue value() const {
|
||||||
return RegisterValue{0}
|
return RegisterValue{0}
|
||||||
| static_cast<RegisterValue>(this->version)
|
| static_cast<RegisterValue>(this->version & 0x0F)
|
||||||
| static_cast<RegisterValue>(this->validConfigStructurePointer) << 4
|
| static_cast<RegisterValue>(this->validConfigStructurePointer) << 4
|
||||||
| static_cast<RegisterValue>(this->supportsResetHalt) << 5
|
| static_cast<RegisterValue>(this->supportsResetHalt) << 5
|
||||||
| static_cast<RegisterValue>(this->authBusy) << 6
|
| static_cast<RegisterValue>(this->authBusy) << 6
|
||||||
|
|||||||
@@ -62,7 +62,6 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
|
|||||||
|
|
||||||
void DebugTranslator::init() {
|
void DebugTranslator::init() {
|
||||||
// No pre-activation initialisation required.
|
// No pre-activation initialisation required.
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugTranslator::activate() {
|
void DebugTranslator::activate() {
|
||||||
@@ -126,18 +125,19 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DebugTranslator::stop() {
|
void DebugTranslator::stop() {
|
||||||
auto controlRegister = ControlRegister{};
|
auto controlRegister = ControlRegister{
|
||||||
controlRegister.debugModuleActive = true;
|
.debugModuleActive = true,
|
||||||
controlRegister.selectedHartIndex = this->selectedHartIndex;
|
.selectedHartIndex = this->selectedHartIndex,
|
||||||
controlRegister.haltRequest = true;
|
.haltRequest = true,
|
||||||
|
};
|
||||||
|
|
||||||
this->writeDebugModuleControlRegister(controlRegister);
|
this->writeDebugModuleControlRegister(controlRegister);
|
||||||
auto statusRegister = this->readDebugModuleStatusRegister();
|
auto statusRegister = this->readDebugModuleStatusRegister();
|
||||||
|
|
||||||
for (
|
for (
|
||||||
auto attempts = 1;
|
auto attempts = 0;
|
||||||
!statusRegister.allHalted
|
!statusRegister.allHalted
|
||||||
&& (DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY * attempts) < this->config.targetResponseTimeout;
|
&& (DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY * attempts) <= this->config.targetResponseTimeout;
|
||||||
++attempts
|
++attempts
|
||||||
) {
|
) {
|
||||||
std::this_thread::sleep_for(DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY);
|
std::this_thread::sleep_for(DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY);
|
||||||
@@ -153,18 +153,19 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DebugTranslator::run() {
|
void DebugTranslator::run() {
|
||||||
auto controlRegister = ControlRegister{};
|
auto controlRegister = ControlRegister{
|
||||||
controlRegister.debugModuleActive = true;
|
.debugModuleActive = true,
|
||||||
controlRegister.selectedHartIndex = this->selectedHartIndex;
|
.selectedHartIndex = this->selectedHartIndex,
|
||||||
controlRegister.resumeRequest = true;
|
.resumeRequest = true,
|
||||||
|
};
|
||||||
|
|
||||||
this->writeDebugModuleControlRegister(controlRegister);
|
this->writeDebugModuleControlRegister(controlRegister);
|
||||||
auto statusRegister = this->readDebugModuleStatusRegister();
|
auto statusRegister = this->readDebugModuleStatusRegister();
|
||||||
|
|
||||||
for (
|
for (
|
||||||
auto attempts = 1;
|
auto attempts = 0;
|
||||||
!statusRegister.allResumeAcknowledge
|
!statusRegister.allResumeAcknowledge
|
||||||
&& (DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY * attempts) < this->config.targetResponseTimeout;
|
&& (DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY * attempts) <= this->config.targetResponseTimeout;
|
||||||
++attempts
|
++attempts
|
||||||
) {
|
) {
|
||||||
std::this_thread::sleep_for(DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY);
|
std::this_thread::sleep_for(DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY);
|
||||||
@@ -175,6 +176,8 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
|
|||||||
this->writeDebugModuleControlRegister(controlRegister);
|
this->writeDebugModuleControlRegister(controlRegister);
|
||||||
|
|
||||||
if (!statusRegister.allResumeAcknowledge) {
|
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"};
|
throw Exceptions::Exception{"Target took too long to acknowledge resume request"};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -185,10 +188,11 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
|
|||||||
|
|
||||||
this->writeDebugControlStatusRegister(debugControlStatusRegister);
|
this->writeDebugControlStatusRegister(debugControlStatusRegister);
|
||||||
|
|
||||||
auto controlRegister = ControlRegister{};
|
auto controlRegister = ControlRegister{
|
||||||
controlRegister.debugModuleActive = true;
|
.debugModuleActive = true,
|
||||||
controlRegister.selectedHartIndex = this->selectedHartIndex;
|
.selectedHartIndex = this->selectedHartIndex,
|
||||||
controlRegister.resumeRequest = true;
|
.resumeRequest = true,
|
||||||
|
};
|
||||||
|
|
||||||
this->writeDebugModuleControlRegister(controlRegister);
|
this->writeDebugModuleControlRegister(controlRegister);
|
||||||
|
|
||||||
@@ -200,12 +204,13 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DebugTranslator::reset() {
|
void DebugTranslator::reset() {
|
||||||
auto controlRegister = ControlRegister{};
|
auto controlRegister = ControlRegister{
|
||||||
controlRegister.debugModuleActive = true;
|
.debugModuleActive = true,
|
||||||
controlRegister.selectedHartIndex = this->selectedHartIndex;
|
.ndmReset = true,
|
||||||
controlRegister.setResetHaltRequest = true;
|
.setResetHaltRequest = true,
|
||||||
controlRegister.haltRequest = true;
|
.selectedHartIndex = this->selectedHartIndex,
|
||||||
controlRegister.ndmReset = true;
|
.haltRequest = true,
|
||||||
|
};
|
||||||
|
|
||||||
this->writeDebugModuleControlRegister(controlRegister);
|
this->writeDebugModuleControlRegister(controlRegister);
|
||||||
|
|
||||||
@@ -214,22 +219,21 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
|
|||||||
auto statusRegister = this->readDebugModuleStatusRegister();
|
auto statusRegister = this->readDebugModuleStatusRegister();
|
||||||
|
|
||||||
for (
|
for (
|
||||||
auto attempts = 1;
|
auto attempts = 0;
|
||||||
!statusRegister.allHaveReset
|
!statusRegister.allHaveReset
|
||||||
&& (DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY * attempts) < this->config.targetResponseTimeout;
|
&& (DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY * attempts) <= this->config.targetResponseTimeout;
|
||||||
++attempts
|
++attempts
|
||||||
) {
|
) {
|
||||||
std::this_thread::sleep_for(DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY);
|
std::this_thread::sleep_for(DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY);
|
||||||
statusRegister = this->readDebugModuleStatusRegister();
|
statusRegister = this->readDebugModuleStatusRegister();
|
||||||
}
|
}
|
||||||
|
|
||||||
controlRegister = ControlRegister{};
|
this->writeDebugModuleControlRegister(ControlRegister{
|
||||||
controlRegister.debugModuleActive = true;
|
.debugModuleActive = true,
|
||||||
controlRegister.selectedHartIndex = this->selectedHartIndex;
|
.clearResetHaltRequest = true,
|
||||||
controlRegister.clearResetHaltRequest = true;
|
.selectedHartIndex = this->selectedHartIndex,
|
||||||
controlRegister.acknowledgeHaveReset = true;
|
.acknowledgeHaveReset = true,
|
||||||
|
});
|
||||||
this->writeDebugModuleControlRegister(controlRegister);
|
|
||||||
|
|
||||||
if (!statusRegister.allHaveReset) {
|
if (!statusRegister.allHaveReset) {
|
||||||
throw Exceptions::Exception{"Target took too long to reset"};
|
throw Exceptions::Exception{"Target took too long to reset"};
|
||||||
@@ -258,7 +262,7 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
|
|||||||
|
|
||||||
const auto& triggerDescriptor = triggerDescriptorOpt->get();
|
const auto& triggerDescriptor = triggerDescriptorOpt->get();
|
||||||
Logger::debug(
|
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)
|
+ std::to_string(triggerDescriptor.index)
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -270,16 +274,18 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
|
|||||||
TriggerModule::Registers::TriggerSelect{triggerDescriptor.index}.value()
|
TriggerModule::Registers::TriggerSelect{triggerDescriptor.index}.value()
|
||||||
);
|
);
|
||||||
|
|
||||||
auto matchControlRegister = MatchControl{};
|
this->writeCpuRegister(
|
||||||
matchControlRegister.execute = true;
|
CpuRegisterNumber::TRIGGER_DATA_1,
|
||||||
matchControlRegister.enabledInUserMode = true;
|
MatchControl{
|
||||||
matchControlRegister.enabledInSupervisorMode = true;
|
.execute = true,
|
||||||
matchControlRegister.enabledInMachineMode = true;
|
.enabledInUserMode = true,
|
||||||
matchControlRegister.action = TriggerModule::TriggerAction::ENTER_DEBUG_MODE;
|
.enabledInSupervisorMode = true,
|
||||||
matchControlRegister.accessSize = MatchControl::AccessSize::ANY;
|
.enabledInMachineMode = true,
|
||||||
matchControlRegister.compareValueType = MatchControl::CompareValueType::ADDRESS;
|
.action = TriggerModule::TriggerAction::ENTER_DEBUG_MODE,
|
||||||
|
.accessSize = MatchControl::AccessSize::ANY,
|
||||||
this->writeCpuRegister(CpuRegisterNumber::TRIGGER_DATA_1, matchControlRegister.value());
|
.compareValueType = MatchControl::CompareValueType::ADDRESS,
|
||||||
|
}.value()
|
||||||
|
);
|
||||||
this->writeCpuRegister(CpuRegisterNumber::TRIGGER_DATA_2, address);
|
this->writeCpuRegister(CpuRegisterNumber::TRIGGER_DATA_2, address);
|
||||||
|
|
||||||
this->allocatedTriggerIndices.emplace(triggerDescriptor.index);
|
this->allocatedTriggerIndices.emplace(triggerDescriptor.index);
|
||||||
@@ -305,7 +311,7 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
|
|||||||
|
|
||||||
void DebugTranslator::clearAllHardwareBreakpoints() {
|
void DebugTranslator::clearAllHardwareBreakpoints() {
|
||||||
// To ensure that any untracked breakpoints are cleared, we clear all triggers on the target.
|
// 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);
|
this->clearTrigger(triggerDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -386,13 +392,11 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
|
|||||||
this->dtmInterface.writeDebugModuleRegister(RegisterAddress::ABSTRACT_DATA_1, startAddress);
|
this->dtmInterface.writeDebugModuleRegister(RegisterAddress::ABSTRACT_DATA_1, startAddress);
|
||||||
|
|
||||||
constexpr auto command = AbstractCommandRegister{
|
constexpr auto command = AbstractCommandRegister{
|
||||||
MemoryAccessControlField{
|
.control = MemoryAccessControlField{
|
||||||
false,
|
.postIncrement = true,
|
||||||
true,
|
.size = MemoryAccessControlField::MemorySize::SIZE_32,
|
||||||
MemoryAccessControlField::MemorySize::SIZE_32,
|
|
||||||
false
|
|
||||||
}.value(),
|
}.value(),
|
||||||
AbstractCommandRegister::CommandType::MEMORY_ACCESS
|
.commandType = AbstractCommandRegister::CommandType::MEMORY_ACCESS
|
||||||
};
|
};
|
||||||
|
|
||||||
for (auto address = startAddress; address <= (startAddress + bytes - 1); address += 4) {
|
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);
|
this->dtmInterface.writeDebugModuleRegister(RegisterAddress::ABSTRACT_DATA_1, startAddress);
|
||||||
|
|
||||||
constexpr auto command = AbstractCommandRegister{
|
constexpr auto command = AbstractCommandRegister{
|
||||||
MemoryAccessControlField{
|
.control = MemoryAccessControlField{
|
||||||
true,
|
.write = true,
|
||||||
true,
|
.postIncrement = true,
|
||||||
MemoryAccessControlField::MemorySize::SIZE_32,
|
.size = MemoryAccessControlField::MemorySize::SIZE_32,
|
||||||
false
|
|
||||||
}.value(),
|
}.value(),
|
||||||
AbstractCommandRegister::CommandType::MEMORY_ACCESS
|
.commandType = AbstractCommandRegister::CommandType::MEMORY_ACCESS
|
||||||
};
|
};
|
||||||
|
|
||||||
for (TargetMemoryAddress offset = 0; offset < buffer.size(); offset += 4) {
|
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
|
* We can obtain the maximum hart index by setting all of the hartsel bits in the control register and then
|
||||||
* read the value back.
|
* read the value back.
|
||||||
*/
|
*/
|
||||||
auto controlRegister = ControlRegister{};
|
this->writeDebugModuleControlRegister(
|
||||||
controlRegister.debugModuleActive = true;
|
ControlRegister{.debugModuleActive = true, .selectedHartIndex = 0xFFFFF}
|
||||||
controlRegister.selectedHartIndex = 0xFFFFF;
|
);
|
||||||
|
|
||||||
this->writeDebugModuleControlRegister(controlRegister);
|
|
||||||
const auto maxHartIndex = this->readDebugModuleControlRegister().selectedHartIndex;
|
const auto maxHartIndex = this->readDebugModuleControlRegister().selectedHartIndex;
|
||||||
|
|
||||||
for (auto hartIndex = DebugModule::HartIndex{0}; hartIndex <= maxHartIndex; ++hartIndex) {
|
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
|
* 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.
|
* have to test each index until we find one that is non-existent.
|
||||||
*/
|
*/
|
||||||
auto controlRegister = ControlRegister{};
|
this->writeDebugModuleControlRegister(
|
||||||
controlRegister.debugModuleActive = true;
|
ControlRegister{.debugModuleActive = true, .selectedHartIndex = hartIndex}
|
||||||
controlRegister.selectedHartIndex = hartIndex;
|
);
|
||||||
|
|
||||||
this->writeDebugModuleControlRegister(controlRegister);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* It's worth noting that some RISC-V targets **do not** set the non-existent flags. I'm not sure why.
|
* 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) {
|
if (writeSelectError != DebugModule::AbstractCommandError::NONE) {
|
||||||
throw Exceptions::Exception{
|
throw Exceptions::Exception{
|
||||||
"Failed to write to TRIGGER_SELECT register - abstract command error: 0x"
|
"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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto infoReg = TriggerModule::Registers::TriggerInfo{
|
const auto infoReg = TriggerModule::Registers::TriggerInfo::fromValue(
|
||||||
this->readCpuRegister(CpuRegisterNumber::TRIGGER_INFO)
|
this->readCpuRegister(CpuRegisterNumber::TRIGGER_INFO)
|
||||||
};
|
);
|
||||||
|
|
||||||
if (infoReg.info == 0x01) {
|
if (infoReg.info == 0x01) {
|
||||||
// Trigger doesn't exist
|
// Trigger doesn't exist
|
||||||
@@ -564,9 +564,9 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
|
|||||||
auto supportedTypes = infoReg.getSupportedTriggerTypes();
|
auto supportedTypes = infoReg.getSupportedTriggerTypes();
|
||||||
if (supportedTypes.empty()) {
|
if (supportedTypes.empty()) {
|
||||||
// The trigger info register has no trigger type info. Try the data1 register.
|
// 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)
|
this->readCpuRegister(CpuRegisterNumber::TRIGGER_DATA_1)
|
||||||
};
|
);
|
||||||
|
|
||||||
const auto triggerType = data1Reg.getType();
|
const auto triggerType = data1Reg.getType();
|
||||||
if (!triggerType.has_value()) {
|
if (!triggerType.has_value()) {
|
||||||
@@ -584,37 +584,40 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
|
|||||||
}
|
}
|
||||||
|
|
||||||
ControlRegister DebugTranslator::readDebugModuleControlRegister() {
|
ControlRegister DebugTranslator::readDebugModuleControlRegister() {
|
||||||
return ControlRegister{this->dtmInterface.readDebugModuleRegister(RegisterAddress::CONTROL_REGISTER)};
|
return ControlRegister::fromValue(
|
||||||
|
this->dtmInterface.readDebugModuleRegister(RegisterAddress::CONTROL_REGISTER)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
StatusRegister DebugTranslator::readDebugModuleStatusRegister() {
|
StatusRegister DebugTranslator::readDebugModuleStatusRegister() {
|
||||||
return StatusRegister{this->dtmInterface.readDebugModuleRegister(RegisterAddress::STATUS_REGISTER)};
|
return StatusRegister::fromValue(this->dtmInterface.readDebugModuleRegister(RegisterAddress::STATUS_REGISTER));
|
||||||
}
|
}
|
||||||
|
|
||||||
AbstractControlStatusRegister DebugTranslator::readDebugModuleAbstractControlStatusRegister() {
|
AbstractControlStatusRegister DebugTranslator::readDebugModuleAbstractControlStatusRegister() {
|
||||||
return AbstractControlStatusRegister{
|
return AbstractControlStatusRegister::fromValue(
|
||||||
this->dtmInterface.readDebugModuleRegister(RegisterAddress::ABSTRACT_CONTROL_STATUS_REGISTER)
|
this->dtmInterface.readDebugModuleRegister(RegisterAddress::ABSTRACT_CONTROL_STATUS_REGISTER)
|
||||||
};
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
DebugControlStatusRegister DebugTranslator::readDebugControlStatusRegister() {
|
DebugControlStatusRegister DebugTranslator::readDebugControlStatusRegister() {
|
||||||
return DebugControlStatusRegister{
|
return DebugControlStatusRegister::fromValue(
|
||||||
this->readCpuRegister(static_cast<RegisterNumber>(CpuRegisterNumber::DEBUG_CONTROL_STATUS_REGISTER))
|
this->readCpuRegister(static_cast<RegisterNumber>(CpuRegisterNumber::DEBUG_CONTROL_STATUS_REGISTER))
|
||||||
};
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DebugTranslator::enableDebugModule() {
|
void DebugTranslator::enableDebugModule() {
|
||||||
auto controlRegister = ControlRegister{};
|
auto controlRegister = ControlRegister{
|
||||||
controlRegister.debugModuleActive = true;
|
.debugModuleActive = true,
|
||||||
controlRegister.selectedHartIndex = this->selectedHartIndex;
|
.selectedHartIndex = this->selectedHartIndex
|
||||||
|
};
|
||||||
|
|
||||||
this->writeDebugModuleControlRegister(controlRegister);
|
this->writeDebugModuleControlRegister(controlRegister);
|
||||||
controlRegister = this->readDebugModuleControlRegister();
|
controlRegister = this->readDebugModuleControlRegister();
|
||||||
|
|
||||||
for (
|
for (
|
||||||
auto attempts = 1;
|
auto attempts = 0;
|
||||||
!controlRegister.debugModuleActive
|
!controlRegister.debugModuleActive
|
||||||
&& (DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY * attempts) < this->config.targetResponseTimeout;
|
&& (DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY * attempts) <= this->config.targetResponseTimeout;
|
||||||
++attempts
|
++attempts
|
||||||
) {
|
) {
|
||||||
std::this_thread::sleep_for(DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY);
|
std::this_thread::sleep_for(DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY);
|
||||||
@@ -627,17 +630,16 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
|
|||||||
}
|
}
|
||||||
|
|
||||||
void DebugTranslator::disableDebugModule() {
|
void DebugTranslator::disableDebugModule() {
|
||||||
auto controlRegister = ControlRegister{};
|
this->writeDebugModuleControlRegister(
|
||||||
controlRegister.debugModuleActive = false;
|
ControlRegister{.debugModuleActive = false, .selectedHartIndex = this->selectedHartIndex}
|
||||||
controlRegister.selectedHartIndex = this->selectedHartIndex;
|
);
|
||||||
|
|
||||||
this->writeDebugModuleControlRegister(controlRegister);
|
auto controlRegister = this->readDebugModuleControlRegister();
|
||||||
controlRegister = this->readDebugModuleControlRegister();
|
|
||||||
|
|
||||||
for (
|
for (
|
||||||
auto attempts = 1;
|
auto attempts = 0;
|
||||||
controlRegister.debugModuleActive
|
controlRegister.debugModuleActive
|
||||||
&& (DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY * attempts) < this->config.targetResponseTimeout;
|
&& (DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY * attempts) <= this->config.targetResponseTimeout;
|
||||||
++attempts
|
++attempts
|
||||||
) {
|
) {
|
||||||
std::this_thread::sleep_for(DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY);
|
std::this_thread::sleep_for(DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY);
|
||||||
@@ -655,15 +657,12 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
|
|||||||
using DebugModule::Registers::RegisterAccessControlField;
|
using DebugModule::Registers::RegisterAccessControlField;
|
||||||
|
|
||||||
const auto commandError = this->tryExecuteAbstractCommand(AbstractCommandRegister{
|
const auto commandError = this->tryExecuteAbstractCommand(AbstractCommandRegister{
|
||||||
RegisterAccessControlField{
|
.control = RegisterAccessControlField{
|
||||||
number,
|
.registerNumber = number,
|
||||||
false,
|
.transfer = true,
|
||||||
true,
|
.size= RegisterAccessControlField::RegisterSize::SIZE_32
|
||||||
false,
|
|
||||||
false,
|
|
||||||
RegisterAccessControlField::RegisterSize::SIZE_32
|
|
||||||
}.value(),
|
}.value(),
|
||||||
AbstractCommandRegister::CommandType::REGISTER_ACCESS
|
.commandType = AbstractCommandRegister::CommandType::REGISTER_ACCESS
|
||||||
});
|
});
|
||||||
|
|
||||||
if (commandError != DebugModule::AbstractCommandError::NONE) {
|
if (commandError != DebugModule::AbstractCommandError::NONE) {
|
||||||
@@ -685,7 +684,8 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
|
|||||||
if (!result.hasValue()) {
|
if (!result.hasValue()) {
|
||||||
throw Exceptions::Exception{
|
throw Exceptions::Exception{
|
||||||
"Failed to read CPU register (number: 0x" + Services::StringService::toHex(number)
|
"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);
|
this->dtmInterface.writeDebugModuleRegister(RegisterAddress::ABSTRACT_DATA_0, value);
|
||||||
return this->tryExecuteAbstractCommand(AbstractCommandRegister{
|
return this->tryExecuteAbstractCommand(AbstractCommandRegister{
|
||||||
RegisterAccessControlField{
|
.control = RegisterAccessControlField{
|
||||||
number,
|
.registerNumber = number,
|
||||||
true,
|
.write = true,
|
||||||
true,
|
.transfer = true,
|
||||||
false,
|
.size = RegisterAccessControlField::RegisterSize::SIZE_32
|
||||||
false,
|
|
||||||
RegisterAccessControlField::RegisterSize::SIZE_32
|
|
||||||
}.value(),
|
}.value(),
|
||||||
AbstractCommandRegister::CommandType::REGISTER_ACCESS
|
.commandType = AbstractCommandRegister::CommandType::REGISTER_ACCESS
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -728,7 +726,8 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
|
|||||||
if (commandError != DebugModule::AbstractCommandError::NONE) {
|
if (commandError != DebugModule::AbstractCommandError::NONE) {
|
||||||
throw Exceptions::Exception{
|
throw Exceptions::Exception{
|
||||||
"Failed to write to CPU register (number: 0x" + Services::StringService::toHex(number)
|
"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 (
|
for (
|
||||||
auto attempts = 1;
|
auto attempts = 0;
|
||||||
abstractStatusRegister.busy
|
abstractStatusRegister.busy
|
||||||
&& (DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY * attempts) < this->config.targetResponseTimeout;
|
&& (DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY * attempts) <= this->config.targetResponseTimeout;
|
||||||
++attempts
|
++attempts
|
||||||
) {
|
) {
|
||||||
std::this_thread::sleep_for(DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY);
|
std::this_thread::sleep_for(DebugTranslator::DEBUG_MODULE_RESPONSE_DELAY);
|
||||||
@@ -784,7 +783,8 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
|
|||||||
const auto commandError = this->tryExecuteAbstractCommand(abstractCommandRegister);
|
const auto commandError = this->tryExecuteAbstractCommand(abstractCommandRegister);
|
||||||
if (commandError != DebugModule::AbstractCommandError::NONE) {
|
if (commandError != DebugModule::AbstractCommandError::NONE) {
|
||||||
throw Exceptions::Exception{
|
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))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
#include "DebugTranslatorConfig.hpp"
|
#include "DebugTranslatorConfig.hpp"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
namespace DebugToolDrivers::Protocols::RiscVDebugSpec
|
namespace DebugToolDrivers::Protocols::RiscVDebugSpec
|
||||||
{
|
{
|
||||||
DebugTranslatorConfig::DebugTranslatorConfig(const YAML::Node& configNode) {
|
DebugTranslatorConfig::DebugTranslatorConfig(const YAML::Node& configNode) {
|
||||||
if (configNode["targetResponseTimeout"]) {
|
if (configNode["targetResponseTimeout"]) {
|
||||||
this->targetResponseTimeout = std::chrono::microseconds{
|
this->targetResponseTimeout = std::chrono::microseconds{
|
||||||
configNode["targetResponseTimeout"].as<int>(this->targetResponseTimeout.count())
|
configNode["targetResponseTimeout"].as<std::int64_t>(this->targetResponseTimeout.count())
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,41 +18,41 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec::Registers
|
|||||||
GROUP = 0x06,
|
GROUP = 0x06,
|
||||||
};
|
};
|
||||||
|
|
||||||
PrivilegeMode privilegeMode:2;
|
PrivilegeMode privilegeMode = PrivilegeMode::USER;
|
||||||
bool step:1 = false;
|
bool step = false;
|
||||||
bool nmiPending:1 = false;
|
bool nmiPending = false;
|
||||||
bool mprvEnabled:1 = false;
|
bool mprvEnabled = false;
|
||||||
DebugModeCause debugModeCause:3;
|
DebugModeCause debugModeCause = DebugModeCause::BREAK;
|
||||||
bool stopTime:1 = false;
|
bool stopTime = false;
|
||||||
bool stopCount:1 = false;
|
bool stopCount = false;
|
||||||
bool stepInterruptsEnabled:1 = false;
|
bool stepInterruptsEnabled = false;
|
||||||
bool breakUMode:1 = false;
|
bool breakUMode = false;
|
||||||
bool breakSMode:1 = false;
|
bool breakSMode = false;
|
||||||
bool breakMMode:1 = false;
|
bool breakMMode = false;
|
||||||
bool breakVUMode:1 = false;
|
bool breakVUMode = false;
|
||||||
bool breakVSMode:1 = false;
|
bool breakVSMode = false;
|
||||||
std::uint8_t debugVersion:4 = 0;
|
std::uint8_t debugVersion = 0;
|
||||||
|
|
||||||
DebugControlStatusRegister() = default;
|
static constexpr auto fromValue(RegisterValue value) {
|
||||||
|
return DebugControlStatusRegister{
|
||||||
|
.privilegeMode = static_cast<PrivilegeMode>(value & 0x03),
|
||||||
|
.step = static_cast<bool>(value & (0x01 << 2)),
|
||||||
|
.nmiPending = static_cast<bool>(value & (0x01 << 3)),
|
||||||
|
.mprvEnabled = static_cast<bool>(value & (0x01 << 4)),
|
||||||
|
.debugModeCause = static_cast<DebugModeCause>((value >> 6) & 0x07),
|
||||||
|
.stopTime = static_cast<bool>(value & (0x01 << 9)),
|
||||||
|
.stopCount = static_cast<bool>(value & (0x01 << 10)),
|
||||||
|
.stepInterruptsEnabled = static_cast<bool>(value & (0x01 << 11)),
|
||||||
|
.breakUMode = static_cast<bool>(value & (0x01 << 12)),
|
||||||
|
.breakSMode = static_cast<bool>(value & (0x01 << 13)),
|
||||||
|
.breakMMode = static_cast<bool>(value & (0x01 << 15)),
|
||||||
|
.breakVUMode = static_cast<bool>(value & (0x01 << 16)),
|
||||||
|
.breakVSMode = static_cast<bool>(value & (0x01 << 17)),
|
||||||
|
.debugVersion = static_cast<std::uint8_t>((value >> 28) & 0x0F)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
constexpr explicit DebugControlStatusRegister(RegisterValue registerValue)
|
[[nodiscard]] constexpr RegisterValue value() const {
|
||||||
: privilegeMode(static_cast<PrivilegeMode>(registerValue & 0x03))
|
|
||||||
, step(static_cast<bool>(registerValue & (0x01 << 2)))
|
|
||||||
, nmiPending(static_cast<bool>(registerValue & (0x01 << 3)))
|
|
||||||
, mprvEnabled(static_cast<bool>(registerValue & (0x01 << 4)))
|
|
||||||
, debugModeCause(static_cast<DebugModeCause>((registerValue >> 6) & 0x07))
|
|
||||||
, stopTime(static_cast<bool>(registerValue & (0x01 << 9)))
|
|
||||||
, stopCount(static_cast<bool>(registerValue & (0x01 << 10)))
|
|
||||||
, stepInterruptsEnabled(static_cast<bool>(registerValue & (0x01 << 11)))
|
|
||||||
, breakUMode(static_cast<bool>(registerValue & (0x01 << 12)))
|
|
||||||
, breakSMode(static_cast<bool>(registerValue & (0x01 << 13)))
|
|
||||||
, breakMMode(static_cast<bool>(registerValue & (0x01 << 15)))
|
|
||||||
, breakVUMode(static_cast<bool>(registerValue & (0x01 << 16)))
|
|
||||||
, breakVSMode(static_cast<bool>(registerValue & (0x01 << 17)))
|
|
||||||
, debugVersion(static_cast<std::uint8_t>(registerValue >> 28) & 0x0F)
|
|
||||||
{}
|
|
||||||
|
|
||||||
constexpr RegisterValue value() const {
|
|
||||||
return RegisterValue{0}
|
return RegisterValue{0}
|
||||||
| static_cast<RegisterValue>(this->privilegeMode)
|
| static_cast<RegisterValue>(this->privilegeMode)
|
||||||
| static_cast<RegisterValue>(this->step) << 2
|
| static_cast<RegisterValue>(this->step) << 2
|
||||||
@@ -67,7 +67,7 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec::Registers
|
|||||||
| static_cast<RegisterValue>(this->breakMMode) << 15
|
| static_cast<RegisterValue>(this->breakMMode) << 15
|
||||||
| static_cast<RegisterValue>(this->breakVUMode) << 16
|
| static_cast<RegisterValue>(this->breakVUMode) << 16
|
||||||
| static_cast<RegisterValue>(this->breakVSMode) << 17
|
| static_cast<RegisterValue>(this->breakVSMode) << 17
|
||||||
| static_cast<RegisterValue>(this->debugVersion) << 28
|
| static_cast<RegisterValue>(this->debugVersion & 0x0F) << 28
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec
|
|||||||
|
|
||||||
enum class PrivilegeMode: std::uint8_t
|
enum class PrivilegeMode: std::uint8_t
|
||||||
{
|
{
|
||||||
U_MODE = 0x00,
|
USER = 0x00,
|
||||||
S_MODE = 0x01,
|
SUPERVISOR = 0x01,
|
||||||
M_MODE = 0x03,
|
MACHINE = 0x03,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,71 +37,39 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec::TriggerModule::Registers
|
|||||||
DATA = 0x01,
|
DATA = 0x01,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool load:1 = false;
|
bool load = false;
|
||||||
bool store:1 = false;
|
bool store = false;
|
||||||
bool execute:1 = false;
|
bool execute = false;
|
||||||
bool enabledInUserMode:1 = false;
|
bool enabledInUserMode = false;
|
||||||
bool enabledInSupervisorMode:1 = false;
|
bool enabledInSupervisorMode = false;
|
||||||
bool enabledInMachineMode:1 = false;
|
bool enabledInMachineMode = false;
|
||||||
MatchMode matchMode:4 = MatchMode::EQUAL;
|
MatchMode matchMode = MatchMode::EQUAL;
|
||||||
bool chain:1 = false; // TODO: Consider making this an enum
|
bool chain = false; // TODO: Consider making this an enum
|
||||||
TriggerAction action:4 = TriggerAction::ENTER_DEBUG_MODE;
|
TriggerAction action = TriggerAction::RAISE_BREAKPOINT_EXCEPTION;
|
||||||
AccessSize accessSize = AccessSize::ANY;
|
AccessSize accessSize = AccessSize::ANY;
|
||||||
bool timing:1 = false; // TODO: Consider making this an enum
|
bool timing = false; // TODO: Consider making this an enum
|
||||||
CompareValueType compareValueType:1 = CompareValueType::ADDRESS;
|
CompareValueType compareValueType = CompareValueType::ADDRESS;
|
||||||
bool hit:1 = false;
|
bool hit = false;
|
||||||
|
|
||||||
MatchControl() = default;
|
static constexpr auto fromValue(RegisterValue value) {
|
||||||
|
return MatchControl{
|
||||||
constexpr explicit MatchControl(
|
.load = static_cast<bool>(value & 0x01),
|
||||||
bool load,
|
.store = static_cast<bool>(value & (0x01 << 1)),
|
||||||
bool store,
|
.execute = static_cast<bool>(value & (0x01 << 2)),
|
||||||
bool execute,
|
.enabledInUserMode = static_cast<bool>(value & (0x01 << 3)),
|
||||||
bool enabledInUserMode,
|
.enabledInSupervisorMode = static_cast<bool>(value & (0x01 << 4)),
|
||||||
bool enabledInSupervisorMode,
|
.enabledInMachineMode = static_cast<bool>(value & (0x01 << 6)),
|
||||||
bool enabledInMachineMode,
|
.matchMode = static_cast<MatchMode>((value >> 7) & 0x0F),
|
||||||
MatchMode matchMode,
|
.chain = static_cast<bool>(value & (0x01 << 11)),
|
||||||
bool chain,
|
.action = static_cast<TriggerAction>((value >> 12) & 0x0F),
|
||||||
TriggerAction action,
|
.accessSize = static_cast<AccessSize>(
|
||||||
AccessSize accessSize,
|
(((value >> 21) & 0x03) << 2) | ((value >> 16) & 0x03)
|
||||||
bool timing,
|
),
|
||||||
CompareValueType compareValueType,
|
.timing = static_cast<bool>(value & (0x01 << 18)),
|
||||||
bool hit
|
.compareValueType = static_cast<CompareValueType>((value >> 19) & 0x01),
|
||||||
)
|
.hit = static_cast<bool>(value & (0x01 << 20)),
|
||||||
: load(load)
|
};
|
||||||
, store(store)
|
}
|
||||||
, execute(execute)
|
|
||||||
, enabledInUserMode(enabledInUserMode)
|
|
||||||
, enabledInSupervisorMode(enabledInSupervisorMode)
|
|
||||||
, enabledInMachineMode(enabledInMachineMode)
|
|
||||||
, matchMode(matchMode)
|
|
||||||
, chain(chain)
|
|
||||||
, action(action)
|
|
||||||
, accessSize(accessSize)
|
|
||||||
, timing(timing)
|
|
||||||
, compareValueType(compareValueType)
|
|
||||||
, hit(hit)
|
|
||||||
{}
|
|
||||||
|
|
||||||
constexpr explicit MatchControl(RegisterValue registerValue)
|
|
||||||
: load(static_cast<bool>(registerValue & 0x01))
|
|
||||||
, store(static_cast<bool>(registerValue & (0x01 << 1)))
|
|
||||||
, execute(static_cast<bool>(registerValue & (0x01 << 2)))
|
|
||||||
, enabledInUserMode(static_cast<bool>(registerValue & (0x01 << 3)))
|
|
||||||
, enabledInSupervisorMode(static_cast<bool>(registerValue & (0x01 << 4)))
|
|
||||||
, enabledInMachineMode(static_cast<bool>(registerValue & (0x01 << 6)))
|
|
||||||
, matchMode(static_cast<MatchMode>((registerValue >> 7) & 0x0F))
|
|
||||||
, chain(static_cast<bool>(registerValue & (0x01 << 11)))
|
|
||||||
, action(static_cast<TriggerAction>((registerValue >> 12) & 0x0F))
|
|
||||||
, accessSize(
|
|
||||||
static_cast<AccessSize>(
|
|
||||||
(((registerValue >> 21) & 0x03) << 2) | ((registerValue >> 16) & 0x03)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
, timing(static_cast<bool>(registerValue & (0x01 << 18)))
|
|
||||||
, compareValueType(static_cast<CompareValueType>((registerValue >> 19) & 0x01))
|
|
||||||
, hit(static_cast<bool>(registerValue & (0x01 << 20)))
|
|
||||||
{}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr RegisterValue value() const {
|
[[nodiscard]] constexpr RegisterValue value() const {
|
||||||
return RegisterValue{0}
|
return RegisterValue{0}
|
||||||
|
|||||||
@@ -9,27 +9,27 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec::TriggerModule::Registers
|
|||||||
{
|
{
|
||||||
struct TriggerData1
|
struct TriggerData1
|
||||||
{
|
{
|
||||||
std::uint32_t data:27;
|
std::uint32_t data;
|
||||||
bool debugModeOnly:1;
|
bool debugModeOnly;
|
||||||
std::uint8_t type:4;
|
std::uint8_t type;
|
||||||
|
|
||||||
TriggerData1() = default;
|
static constexpr auto fromValue(RegisterValue value) {
|
||||||
|
return TriggerData1{
|
||||||
constexpr explicit TriggerData1(RegisterValue registerValue)
|
.data = value & 0x07FFFFFF,
|
||||||
: data(registerValue & 0x07FFFFFF)
|
.debugModeOnly = static_cast<bool>(value & (0x01 << 27)),
|
||||||
, debugModeOnly(static_cast<bool>(registerValue & (0x01 << 27)))
|
.type = static_cast<std::uint8_t>((value >> 28) & 0x0F),
|
||||||
, type(static_cast<std::uint8_t>(registerValue >> 28) & 0x0F)
|
};
|
||||||
{}
|
}
|
||||||
|
|
||||||
[[nodiscard]] constexpr RegisterValue value() const {
|
[[nodiscard]] constexpr RegisterValue value() const {
|
||||||
return RegisterValue{0}
|
return RegisterValue{0}
|
||||||
| static_cast<RegisterValue>(this->data)
|
| static_cast<RegisterValue>(this->data & 0x07FFFFFF)
|
||||||
| static_cast<RegisterValue>(this->debugModeOnly) << 27
|
| static_cast<RegisterValue>(this->debugModeOnly) << 27
|
||||||
| static_cast<RegisterValue>(this->type) << 28
|
| static_cast<RegisterValue>(this->type & 0x0F) << 28
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<TriggerType> getType() const {
|
[[nodiscard]] std::optional<TriggerType> getType() const {
|
||||||
return (this->type >= 0x01 && this->type <= 0x07)
|
return (this->type >= 0x01 && this->type <= 0x07)
|
||||||
? std::optional{static_cast<TriggerType>(this->type)}
|
? std::optional{static_cast<TriggerType>(this->type)}
|
||||||
: std::nullopt;
|
: std::nullopt;
|
||||||
|
|||||||
@@ -13,10 +13,12 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec::TriggerModule::Registers
|
|||||||
std::uint16_t info;
|
std::uint16_t info;
|
||||||
std::uint8_t version;
|
std::uint8_t version;
|
||||||
|
|
||||||
constexpr explicit TriggerInfo(RegisterValue registerValue)
|
static constexpr auto fromValue(RegisterValue value) {
|
||||||
: info(registerValue & 0xFFFF)
|
return TriggerInfo{
|
||||||
, version(static_cast<std::uint8_t>(registerValue >> 24))
|
.info = static_cast<std::uint16_t>(value & 0xFFFF),
|
||||||
{}
|
.version = static_cast<std::uint8_t>(value >> 24),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
[[nodiscard]] constexpr RegisterValue value() const {
|
[[nodiscard]] constexpr RegisterValue value() const {
|
||||||
return RegisterValue{0}
|
return RegisterValue{0}
|
||||||
@@ -25,7 +27,7 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec::TriggerModule::Registers
|
|||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::set<TriggerType> getSupportedTriggerTypes() const {
|
[[nodiscard]] std::set<TriggerType> getSupportedTriggerTypes() const {
|
||||||
auto output = std::set<TriggerType>{};
|
auto output = std::set<TriggerType>{};
|
||||||
|
|
||||||
static constexpr auto types = std::to_array<TriggerType>({
|
static constexpr auto types = std::to_array<TriggerType>({
|
||||||
|
|||||||
@@ -6,6 +6,9 @@
|
|||||||
|
|
||||||
namespace DebugToolDrivers::Protocols::RiscVDebugSpec::TriggerModule::Registers
|
namespace DebugToolDrivers::Protocols::RiscVDebugSpec::TriggerModule::Registers
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* TODO: Given the single, full width bit field, is this struct really necessary? Review.
|
||||||
|
*/
|
||||||
struct TriggerSelect
|
struct TriggerSelect
|
||||||
{
|
{
|
||||||
TriggerIndex index;
|
TriggerIndex index;
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ namespace DebugToolDrivers::Protocols::RiscVDebugSpec::TriggerModule
|
|||||||
|
|
||||||
enum class TriggerAction: std::uint8_t
|
enum class TriggerAction: std::uint8_t
|
||||||
{
|
{
|
||||||
|
RAISE_BREAKPOINT_EXCEPTION = 0x00,
|
||||||
ENTER_DEBUG_MODE = 0x01,
|
ENTER_DEBUG_MODE = 0x01,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user