RISC-V hart selection

This commit is contained in:
Nav
2023-11-23 12:56:26 +00:00
parent c4dc3c89f5
commit c1c9a0ceeb
3 changed files with 63 additions and 3 deletions

View File

@@ -20,7 +20,7 @@ namespace Targets::RiscV::DebugModule::Registers
bool setResetHaltRequest:1 = false; bool setResetHaltRequest:1 = false;
bool clearKeepAlive:1 = false; bool clearKeepAlive:1 = false;
bool setKeepAlive:1 = false; bool setKeepAlive:1 = false;
HartIndex selectedHartIndex:20 = 0; HartIndex selectedHartIndex = 0;
HartSelectionMode hartSelectionMode:1 = HartSelectionMode::SINGLE; HartSelectionMode hartSelectionMode:1 = HartSelectionMode::SINGLE;
bool acknowledgeUnavailableHarts:1 = false; bool acknowledgeUnavailableHarts:1 = false;
bool acknowledgeHaveReset:1 = false; bool acknowledgeHaveReset:1 = false;
@@ -54,7 +54,7 @@ namespace Targets::RiscV::DebugModule::Registers
| static_cast<RegisterValue>(this->setResetHaltRequest) << 3 | static_cast<RegisterValue>(this->setResetHaltRequest) << 3
| static_cast<RegisterValue>(this->clearKeepAlive) << 4 | static_cast<RegisterValue>(this->clearKeepAlive) << 4
| static_cast<RegisterValue>(this->setKeepAlive) << 5 | static_cast<RegisterValue>(this->setKeepAlive) << 5
| static_cast<RegisterValue>(this->selectedHartIndex >> 10) << 6 | static_cast<RegisterValue>((this->selectedHartIndex & 0xFFFFF) >> 10) << 6
| static_cast<RegisterValue>(this->selectedHartIndex & 0x3FF) << 16 | static_cast<RegisterValue>(this->selectedHartIndex & 0x3FF) << 16
| static_cast<RegisterValue>(this->hartSelectionMode) << 26 | static_cast<RegisterValue>(this->hartSelectionMode) << 26
| static_cast<RegisterValue>(this->acknowledgeUnavailableHarts) << 27 | static_cast<RegisterValue>(this->acknowledgeUnavailableHarts) << 27

View File

@@ -30,7 +30,21 @@ namespace Targets::RiscV
void RiscV::activate() { void RiscV::activate() {
this->riscVDebugInterface->activate({}); this->riscVDebugInterface->activate({});
// TODO: Select a hart here. this->discoverHartIndices();
Logger::debug("Discovered RISC-V harts: " + std::to_string(this->hartIndices.size()));
/*
* We only support MCUs with a single hart, for now. So select the first index and ensure that this is
* explicitly communicated to the user.
*/
if (this->hartIndices.size() > 1) {
Logger::warning(
"Bloom only supports debugging a single RISC-V hart - selecting first available hart"
);
}
this->selectedHartIndex = *(this->hartIndices.begin());
Logger::info("Selected RISC-V hart index: " + std::to_string(this->selectedHartIndex));
this->stop(); this->stop();
} }
@@ -65,6 +79,7 @@ namespace Targets::RiscV
void RiscV::run(std::optional<TargetMemoryAddress> toAddress) { void RiscV::run(std::optional<TargetMemoryAddress> toAddress) {
auto controlRegister = ControlRegister(); auto controlRegister = ControlRegister();
controlRegister.debugModuleActive = true; controlRegister.debugModuleActive = true;
controlRegister.selectedHartIndex = this->selectedHartIndex;
controlRegister.resumeRequest = true; controlRegister.resumeRequest = true;
this->writeControlRegister(controlRegister); this->writeControlRegister(controlRegister);
@@ -88,6 +103,7 @@ namespace Targets::RiscV
void RiscV::stop() { void RiscV::stop() {
auto controlRegister = ControlRegister(); auto controlRegister = ControlRegister();
controlRegister.debugModuleActive = true; controlRegister.debugModuleActive = true;
controlRegister.selectedHartIndex = this->selectedHartIndex;
controlRegister.haltRequest = true; controlRegister.haltRequest = true;
this->writeControlRegister(controlRegister); this->writeControlRegister(controlRegister);
@@ -204,6 +220,44 @@ namespace Targets::RiscV
return false; return false;
} }
void RiscV::discoverHartIndices() {
/*
* We can obtain the maximum hart index by setting all of the hartsel bits in the control register and then
* reading the value back.
*/
auto controlRegister = ControlRegister();
controlRegister.debugModuleActive = true;
controlRegister.selectedHartIndex = 0xFFFFF;
this->writeControlRegister(controlRegister);
controlRegister = this->readControlRegister();
for (DebugModule::HartIndex hartIndex = 0; hartIndex <= controlRegister.selectedHartIndex; ++hartIndex) {
/*
* 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.
*/
controlRegister = ControlRegister();
controlRegister.debugModuleActive = true;
controlRegister.selectedHartIndex = hartIndex;
this->writeControlRegister(controlRegister);
/*
* It's worth noting that some RISC-V targets **do not** set the non-existent flags. I'm not sure why.
* Have they just hardwired hartsel to 0 because they only support a single hart, preventing the selection
* of non-existent harts?
*
* Relying on the maximum hart index seems to be all we can do in this case.
*/
if (this->readStatusRegister().anyNonExistent) {
break;
}
this->hartIndices.insert(hartIndex);
}
}
ControlRegister RiscV::readControlRegister() { ControlRegister RiscV::readControlRegister() {
return ControlRegister( return ControlRegister(
this->riscVDebugInterface->readDebugModuleRegister(RegisterAddresses::CONTROL_REGISTER) this->riscVDebugInterface->readDebugModuleRegister(RegisterAddresses::CONTROL_REGISTER)

View File

@@ -1,6 +1,7 @@
#pragma once #pragma once
#include <cstdint> #include <cstdint>
#include <set>
#include "src/Targets/Target.hpp" #include "src/Targets/Target.hpp"
#include "src/DebugToolDrivers/DebugTool.hpp" #include "src/DebugToolDrivers/DebugTool.hpp"
@@ -91,6 +92,11 @@ namespace Targets::RiscV
DebugToolDrivers::TargetInterfaces::RiscV::RiscVDebugInterface* riscVDebugInterface = nullptr; DebugToolDrivers::TargetInterfaces::RiscV::RiscVDebugInterface* riscVDebugInterface = nullptr;
std::string name; std::string name;
std::set<DebugModule::HartIndex> hartIndices;
DebugModule::HartIndex selectedHartIndex = 0;
void discoverHartIndices();
DebugModule::Registers::ControlRegister readControlRegister(); DebugModule::Registers::ControlRegister readControlRegister();
DebugModule::Registers::StatusRegister readStatusRegister(); DebugModule::Registers::StatusRegister readStatusRegister();