Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 50 additions & 4 deletions packages/river_hdl/lib/src/core.dart
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,14 @@ class RiverCore extends BridgeModule {
int? resetPrivilege,
super.name = 'river_core',
}) : super('RiverCore') {
// Lockstep scalar debug entry drains the current instruction rather than
// cancelling externally visible memory operations. H/OoO and speculative
// execution retain their existing debug path.
final boundaryDebug =
withDebug &&
!config.speculativeFetch &&
config.executionMode == ExecutionMode.inOrder &&
!config.hasHypervisor;
final wbConfig =
busConfig ??
WishboneConfig(
Expand Down Expand Up @@ -112,6 +120,7 @@ class RiverCore extends BridgeModule {
// the one stepped instruction commits (which re-enters Debug Mode, cause 4).
Logic? stepping;
Logic? haltReqIn;
Logic? boundaryHaltRequest;
Logic? resumeReqIn;
// Abstract-command register access (driven by the Debug Module while halted).
Logic? dbgGprRead; // read a GPR onto the regfile read port
Expand Down Expand Up @@ -165,6 +174,21 @@ class RiverCore extends BridgeModule {
haltReqIn = input('debug_halt_req');
resumeReqIn = input('debug_resume_req');
debugHalted = Logic(name: 'debugHalted');
if (boundaryDebug) {
final pending = Logic(name: 'boundaryHaltPending');
// Keep accepting one-cycle halt pulses while the current instruction
// drains. Clear on entry so an old request cannot halt a later resume.
Sequential(clk, [
If(
reset | debugHalted,
then: [pending < 0],
orElse: [
If(haltReqIn, then: [pending < 1]),
],
),
]);
boundaryHaltRequest = haltReqIn | pending;
}
debugDpc = Logic(name: 'debugDpc', width: config.mxlen.size);
debugDcsr = Logic(name: 'debugDcsr', width: 32);
if (userProbe) {
Expand Down Expand Up @@ -1848,15 +1872,31 @@ class RiverCore extends BridgeModule {
// Debug Mode at the next PC (cause 4) and freeze the pipeline.
if (withDebug)
If(
stepping!,
boundaryDebug
? (stepping! | boundaryHaltRequest!)
: stepping!,
then: [
debugHalted! < 1,
pipelineEnable < 0,
debugDpc! < committedNextPc,
debugDcsr! <
(debugDcsr! & Const(0xFFFFFE3C, width: 32)) |
(Const(4 << 6, width: 32) | dcsrPrv),
((boundaryDebug
? mux(
boundaryHaltRequest!,
Const(3 << 6, width: 32),
Const(4 << 6, width: 32),
)
: Const(4 << 6, width: 32)) |
(boundaryDebug
? mux(
pipeline.isReturn,
retMode,
pipeline.nextMode,
).getRange(0, 2).zeroExtend(32)
: dcsrPrv)),
stepping! < Const(0),
if (boundaryDebug) interruptHold < 0,
],
),
],
Expand Down Expand Up @@ -1957,7 +1997,9 @@ class RiverCore extends BridgeModule {
),
],
If(
resumeReqIn!,
boundaryDebug
? (resumeReqIn! & ~haltReqIn!)
: resumeReqIn!,
then: [
debugHalted < 0,
pc < debugDpc,
Expand All @@ -1968,9 +2010,13 @@ class RiverCore extends BridgeModule {
],
orElse: [
If(
haltReqIn!,
boundaryDebug
? (boundaryHaltRequest! &
(~pipelineEnable | interruptHold))
: haltReqIn!,
then: [
debugHalted < 1,
if (boundaryDebug) interruptHold < 0,
pipelineEnable < 0,
debugDpc < pc,
// Halt cause = 3 (haltreq); keep the other dcsr bits.
Expand Down
Loading
Loading