Skip to content

Commit d4b7e64

Browse files
feat(river_hdl): adding interrupts
1 parent 20cfab6 commit d4b7e64

File tree

4 files changed

+425
-20
lines changed

4 files changed

+425
-20
lines changed

packages/river_hdl/lib/river_hdl.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ export 'src/core/decoder.dart';
55
export 'src/core/exec.dart';
66
export 'src/core/fetcher.dart';
77
export 'src/core/pipeline.dart';
8+
export 'src/core/int.dart';
89
export 'src/core.dart';
910
export 'src/memory/port.dart';

packages/river_hdl/lib/src/core.dart

Lines changed: 77 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
1+
import 'dart:math' show max;
2+
13
import 'package:rohd/rohd.dart';
24
import 'package:rohd_hcl/rohd_hcl.dart';
35
import 'package:riscv/riscv.dart';
46
import 'package:river/river.dart';
57

68
import 'core/csr.dart';
79
import 'core/pipeline.dart';
10+
import 'core/int.dart';
811

912
class RiverCoreHDL extends Module {
1013
final RiverCore config;
@@ -20,6 +23,7 @@ class RiverCoreHDL extends Module {
2023
DataPortInterface memFetchRead,
2124
DataPortInterface memExecRead,
2225
DataPortInterface memWrite, {
26+
Map<String, Logic> srcIrqs = const {},
2327
super.name = 'river_core',
2428
}) {
2529
clk = addInput('clk', clk);
@@ -34,6 +38,7 @@ class RiverCoreHDL extends Module {
3438
inputTags: {DataPortGroup.data, DataPortGroup.integrity},
3539
uniquify: (og) => 'memFetchRead_$og',
3640
);
41+
3742
memExecRead = memExecRead.clone()
3843
..connectIO(
3944
this,
@@ -42,6 +47,7 @@ class RiverCoreHDL extends Module {
4247
inputTags: {DataPortGroup.data, DataPortGroup.integrity},
4348
uniquify: (og) => 'memExecRead_$og',
4449
);
50+
4551
memWrite = memWrite.clone()
4652
..connectIO(
4753
this,
@@ -61,6 +67,70 @@ class RiverCoreHDL extends Module {
6167
final rs2Read = DataPortInterface(config.mxlen.size, 5);
6268
final rdWrite = DataPortInterface(config.mxlen.size, 5);
6369

70+
regs = RegisterFile(
71+
clk,
72+
reset,
73+
[rdWrite],
74+
[rs1Read, rs2Read],
75+
numEntries: 32,
76+
name: 'riscv_regfile',
77+
);
78+
79+
int computeNumIrqs(InterruptController ic) {
80+
final irqs = ic.lines.map((l) => l.irq).toList();
81+
if (irqs.isEmpty) return 1;
82+
final maxIrq = irqs.reduce((a, b) => a > b ? a : b);
83+
return max(1, maxIrq + 1);
84+
}
85+
86+
final interruptBundles =
87+
<
88+
({
89+
InterruptController cfg,
90+
Logic srcIrq,
91+
InterruptPortInterface ipi,
92+
RiscVInterruptController ctrl,
93+
})
94+
>[];
95+
96+
for (final ic in config.interrupts) {
97+
final numIrqs = computeNumIrqs(ic);
98+
99+
final isExternal = srcIrqs.containsKey(ic.name);
100+
final srcIrq = isExternal
101+
? addInput(
102+
'srcIrqLevel_${interruptBundles.length}',
103+
srcIrqs[ic.name]!,
104+
width: numIrqs,
105+
)
106+
: Logic(
107+
name: 'srcIrqLevel_${interruptBundles.length}',
108+
width: numIrqs,
109+
);
110+
111+
final ipi = InterruptPortInterface(config.mxlen.size, config.mxlen.size);
112+
113+
final ctrl = RiscVInterruptController(ic, clk, reset, srcIrq, ipi);
114+
115+
ipi.en <= Const(0);
116+
ipi.write <= Const(0);
117+
ipi.addr <= Const(0, width: ipi.addr.width);
118+
ipi.wdata <= Const(0, width: ipi.wdata.width);
119+
ipi.wstrb <= Const(0, width: ipi.wstrb.width);
120+
121+
interruptBundles.add((cfg: ic, srcIrq: srcIrq, ipi: ipi, ctrl: ctrl));
122+
}
123+
124+
Logic externalPending = Const(0);
125+
for (final b in interruptBundles) {
126+
final v = b.ctrl.irqToTargets;
127+
Logic anyFromThis = Const(0);
128+
for (var i = 0; i < v.width; i++) {
129+
anyFromThis = anyFromThis | v[i];
130+
}
131+
externalPending = externalPending | anyFromThis;
132+
}
133+
64134
final csrRead = DataPortInterface(config.mxlen.size, 12);
65135
final csrWrite = DataPortInterface(config.mxlen.size, 12);
66136

@@ -81,22 +151,14 @@ class RiverCoreHDL extends Module {
81151
marchid: config.archId,
82152
mimpid: config.impId,
83153
mhartid: config.hartId,
154+
externalPending: externalPending,
84155
hasSupervisor: config.hasSupervisor,
85156
hasUser: config.hasUser,
86157
csrRead: csrRead,
87158
csrWrite: csrWrite,
88159
)
89160
: null;
90161

91-
regs = RegisterFile(
92-
clk,
93-
reset,
94-
[rdWrite],
95-
[rs1Read, rs2Read],
96-
numEntries: 32,
97-
name: 'riscv_regfile',
98-
);
99-
100162
pipeline = RiverPipeline(
101163
clk,
102164
reset,
@@ -135,6 +197,11 @@ class RiverCoreHDL extends Module {
135197
interruptHold < 0,
136198
],
137199
orElse: [
200+
If(
201+
interruptHold & externalPending,
202+
then: [interruptHold < 0, pipelineEnable < 1],
203+
),
204+
138205
If(
139206
enable & ~interruptHold,
140207
then: [
@@ -150,12 +217,8 @@ class RiverCoreHDL extends Module {
150217
orElse: [pipelineEnable < 1],
151218
),
152219
],
153-
orElse: [
154-
pipelineEnable < 0,
155-
// TODO: if interrupt hold & interrupt is fired, re-enable pipeline.
156-
],
220+
orElse: [pipelineEnable < 0],
157221
),
158-
// TODO: trap handling circuitry
159222
],
160223
),
161224
]);

packages/river_hdl/lib/src/core/csr.dart

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ class RiscVCsrFile extends Module {
8585
int marchid = 0,
8686
int mimpid = 0,
8787
int mhartid = 0,
88+
Logic? externalPending,
8889
this.hasSupervisor = false,
8990
this.hasUser = false,
9091
required DataPortInterface csrRead,
@@ -99,6 +100,16 @@ class RiscVCsrFile extends Module {
99100
this.reset = addInput('reset', reset);
100101
this.mode = addInput('mode', mode, width: 3);
101102

103+
if (externalPending != null)
104+
externalPending = addInput(
105+
'externalPending',
106+
externalPending!,
107+
width: externalPending!.width,
108+
);
109+
110+
addOutput('mstatus', width: mxlen.size);
111+
addOutput('mie', width: mxlen.size);
112+
addOutput('mip', width: mxlen.size);
102113
addOutput('mideleg', width: mxlen.size);
103114
addOutput('medeleg', width: mxlen.size);
104115
addOutput('mtvec', width: mxlen.size);
@@ -170,6 +181,10 @@ class RiscVCsrFile extends Module {
170181
_bindBackdoorForCounters();
171182
_wireCounters();
172183

184+
mstatus <=
185+
_csrTop.getBackdoorPortsByAddr(0, CsrAddress.mstatus.address).rdData!;
186+
mie <= _csrTop.getBackdoorPortsByAddr(0, CsrAddress.mie.address).rdData!;
187+
mip <= _csrTop.getBackdoorPortsByAddr(0, CsrAddress.mip.address).rdData!;
173188
mideleg <=
174189
_csrTop.getBackdoorPortsByAddr(0, CsrAddress.mideleg.address).rdData!;
175190
medeleg <=
@@ -179,6 +194,12 @@ class RiscVCsrFile extends Module {
179194
if (hasSupervisor)
180195
stvec! <=
181196
_csrTop.getBackdoorPortsByAddr(0, CsrAddress.stvec.address).rdData!;
197+
198+
if (externalPending != null) {
199+
final mip = _csrTop.getBackdoorPortsByAddr(0, CsrAddress.mip.address);
200+
mip.wrEn! <= Const(1);
201+
mip.wrData! <= this.mip.withSet(11, externalPending);
202+
}
182203
}
183204

184205
CsrTopConfig _buildConfig(Mxlen mxlen) {
@@ -241,6 +262,7 @@ class RiscVCsrFile extends Module {
241262
addr: CsrAddress.mip.address,
242263
resetValue: 0,
243264
width: mxlen.size,
265+
isBackdoorWritable: true,
244266
),
245267
CsrInstanceConfig(
246268
arch: SimpleRwCsr('mtvec'),
@@ -618,12 +640,9 @@ class RiscVCsrFile extends Module {
618640
Logic get misa =>
619641
_csrTop.getBackdoorPortsByAddr(0, CsrAddress.misa.address).rdData!;
620642

621-
Logic get mstatus =>
622-
_csrTop.getBackdoorPortsByAddr(0, CsrAddress.mstatus.address).rdData!;
623-
Logic get mie =>
624-
_csrTop.getBackdoorPortsByAddr(0, CsrAddress.mie.address).rdData!;
625-
Logic get mip =>
626-
_csrTop.getBackdoorPortsByAddr(0, CsrAddress.mip.address).rdData!;
643+
Logic get mstatus => output('mstatus');
644+
Logic get mie => output('mie');
645+
Logic get mip => output('mip');
627646
Logic get mtvec => output('mtvec');
628647
Logic get mscratch =>
629648
_csrTop.getBackdoorPortsByAddr(0, CsrAddress.mscratch.address).rdData!;

0 commit comments

Comments
 (0)