Skip to content

Commit 869c934

Browse files
feat: add mmu to hdl
1 parent d4b7e64 commit 869c934

8 files changed

Lines changed: 891 additions & 80 deletions

File tree

packages/riscv/lib/src/riscv_isa_base.dart

Lines changed: 47 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,32 +69,75 @@ enum PagingMode {
6969
0,
7070
levels: 0,
7171
vpnBits: 0,
72+
pteBytes: 0,
73+
ppnBits: const [],
7274
supportedMxlens: [Mxlen.mxlen_32, Mxlen.mxlen_64],
7375
),
7476
sv32(
7577
1,
7678
levels: 2,
7779
vpnBits: 10,
80+
pteBytes: 4,
81+
ppnBits: const [10, 12],
7882
supportedMxlens: [Mxlen.mxlen_32, Mxlen.mxlen_64],
7983
),
80-
sv39(8, levels: 3, vpnBits: 9, supportedMxlens: [Mxlen.mxlen_64]),
81-
sv48(9, levels: 4, vpnBits: 9, supportedMxlens: [Mxlen.mxlen_64]),
82-
sv57(10, levels: 5, vpnBits: 9, supportedMxlens: [Mxlen.mxlen_64]);
84+
sv39(
85+
8,
86+
levels: 3,
87+
vpnBits: 9,
88+
pteBytes: 8,
89+
ppnBits: const [9, 9, 26],
90+
supportedMxlens: [Mxlen.mxlen_64],
91+
),
92+
sv48(
93+
9,
94+
levels: 4,
95+
vpnBits: 9,
96+
pteBytes: 8,
97+
ppnBits: const [9, 9, 9, 17],
98+
supportedMxlens: [Mxlen.mxlen_64],
99+
),
100+
sv57(
101+
10,
102+
levels: 5,
103+
vpnBits: 9,
104+
pteBytes: 8,
105+
ppnBits: const [9, 9, 9, 9, 8],
106+
supportedMxlens: [Mxlen.mxlen_64],
107+
);
83108

84109
const PagingMode(
85110
this.id, {
86111
required this.levels,
87112
required this.vpnBits,
113+
required this.pteBytes,
114+
required this.ppnBits,
88115
required this.supportedMxlens,
89116
});
90117

91118
final int id;
92119
final int levels;
93120
final int vpnBits;
94-
final List supportedMxlens;
121+
final int pteBytes;
122+
final List<int> ppnBits;
123+
final List<Mxlen> supportedMxlens;
124+
125+
int get totalPpnBits => ppnBits.fold<int>(0, (a, b) => a + b);
95126

96127
bool isSupported(Mxlen mxlen) => supportedMxlens.contains(mxlen);
97128

129+
int ppnPhysShift(int i) => 12 + (vpnBits * i);
130+
131+
int ppnShift(int index) {
132+
int shift = 12;
133+
for (int i = 0; i < index; i++) {
134+
shift += ppnBits[i];
135+
}
136+
return shift;
137+
}
138+
139+
bool isSuperpageLevel(int level) => level < levels - 1;
140+
98141
static PagingMode? fromId(int id) {
99142
for (final mode in PagingMode.values) {
100143
if (mode.id == id) return mode;

packages/river_emulator/lib/src/mmu.dart

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,26 @@ class MmuEmulator {
8080
var a = pageTable;
8181
var i = levels - 1;
8282

83+
int buildPhys(int pte, int level) {
84+
int phys = addr & 0xfff;
85+
86+
for (int i = 0; i < mode.ppnBits.length; i++) {
87+
final bits = mode.ppnBits[i];
88+
final mask = (1 << bits) - 1;
89+
90+
int value;
91+
if (i < level) {
92+
value = (addr >> (12 + mode.vpnBits * i)) & mask;
93+
} else {
94+
value = (pte >> mode.ppnShift(i)) & mask;
95+
}
96+
97+
phys |= value << mode.ppnPhysShift(i);
98+
}
99+
100+
return phys;
101+
}
102+
83103
while (true) {
84104
final pte = await read(
85105
a + vpn[i] * config.mxlen.width,
@@ -143,13 +163,7 @@ class MmuEmulator {
143163
);
144164
}
145165

146-
final ppn0 = (pte >> 10) & 0x1ff;
147-
final ppn1 = (pte >> 19) & 0x1ff;
148-
final ppn2 = (pte >> 28) & 0x3ff_ffff;
149-
150-
final offset = addr & 0xfff;
151-
final phys = (ppn2 << 30) | (ppn1 << 21) | (ppn0 << 12) | offset;
152-
return phys;
166+
return buildPhys(pte, i);
153167
}
154168

155169
i -= 1;

packages/river_hdl/lib/river_hdl.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ export 'src/core/csr.dart';
44
export 'src/core/decoder.dart';
55
export 'src/core/exec.dart';
66
export 'src/core/fetcher.dart';
7-
export 'src/core/pipeline.dart';
87
export 'src/core/int.dart';
8+
export 'src/core/mmu.dart';
9+
export 'src/core/pipeline.dart';
910
export 'src/core.dart';
1011
export 'src/memory/port.dart';

packages/river_hdl/lib/src/core.dart

Lines changed: 108 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@ import 'package:riscv/riscv.dart';
66
import 'package:river/river.dart';
77

88
import 'core/csr.dart';
9-
import 'core/pipeline.dart';
109
import 'core/int.dart';
10+
import 'core/mmu.dart';
11+
import 'core/pipeline.dart';
12+
13+
import 'memory/port.dart';
1114

1215
class RiverCoreHDL extends Module {
1316
final RiverCore config;
@@ -19,49 +22,106 @@ class RiverCoreHDL extends Module {
1922
this.config,
2023
Logic clk,
2124
Logic reset,
22-
Logic enable,
23-
DataPortInterface memFetchRead,
24-
DataPortInterface memExecRead,
25-
DataPortInterface memWrite, {
25+
Logic enable, {
26+
Map<MemoryBlock, (DataPortInterface, DataPortInterface)> devices = const {},
2627
Map<String, Logic> srcIrqs = const {},
2728
super.name = 'river_core',
2829
}) {
2930
clk = addInput('clk', clk);
3031
reset = addInput('reset', reset);
3132
enable = addInput('enable', enable);
3233

33-
memFetchRead = memFetchRead.clone()
34-
..connectIO(
35-
this,
36-
memFetchRead,
37-
outputTags: {DataPortGroup.control},
38-
inputTags: {DataPortGroup.data, DataPortGroup.integrity},
39-
uniquify: (og) => 'memFetchRead_$og',
40-
);
41-
42-
memExecRead = memExecRead.clone()
43-
..connectIO(
44-
this,
45-
memExecRead,
46-
outputTags: {DataPortGroup.control},
47-
inputTags: {DataPortGroup.data, DataPortGroup.integrity},
48-
uniquify: (og) => 'memExecRead_$og',
49-
);
50-
51-
memWrite = memWrite.clone()
52-
..connectIO(
53-
this,
54-
memWrite,
55-
outputTags: {DataPortGroup.control, DataPortGroup.data},
56-
inputTags: {DataPortGroup.integrity},
57-
uniquify: (og) => 'memWrite_$og',
58-
);
34+
devices = Map.fromEntries(
35+
devices.entries.indexed.map((e) {
36+
final index = e.$1;
37+
final mmap = e.$2.key;
38+
final devReadPort = e.$2.value.$1;
39+
final devWritePort = e.$2.value.$2;
40+
return MapEntry(mmap, (
41+
devReadPort.clone()..connectIO(
42+
this,
43+
devReadPort,
44+
outputTags: {DataPortGroup.control},
45+
inputTags: {DataPortGroup.data, DataPortGroup.integrity},
46+
uniquify: (og) => 'devRead${index}_$og',
47+
),
48+
devWritePort.clone()..connectIO(
49+
this,
50+
devWritePort,
51+
outputTags: {DataPortGroup.control, DataPortGroup.data},
52+
inputTags: {DataPortGroup.integrity},
53+
uniquify: (og) => 'devWrite${index}_$og',
54+
),
55+
));
56+
}),
57+
);
5958

6059
final pipelineEnable = Logic(name: 'pipelineEnable');
6160
final pc = Logic(name: 'pc', width: config.mxlen.size);
6261
final sp = Logic(name: 'sp', width: config.mxlen.size);
6362
final mode = Logic(name: 'mode', width: 3);
6463
final interruptHold = Logic(name: 'interruptHold');
64+
final fence = Logic(name: 'fence');
65+
66+
final pagingMode = Logic(
67+
name: 'pagingMode',
68+
width: PagingMode.values
69+
.where((m) => m.isSupported(config.mxlen))
70+
.map((m) => m.id)
71+
.fold((0), (a, b) => a > b ? a : b)
72+
.bitLength,
73+
);
74+
75+
final pageTableAddress = Logic(
76+
name: 'pageTableAddress',
77+
width: config.mxlen.size,
78+
);
79+
80+
final enableMxr = Logic(name: 'enableMxr');
81+
final enableSum = Logic(name: 'enableSum');
82+
83+
final mmuFetchRead = DataPortInterface(
84+
config.mxlen.size,
85+
config.mxlen.size,
86+
);
87+
final mmuExecRead = DataPortInterface(config.mxlen.size, config.mxlen.size);
88+
final mmuWritebackRead = DataPortInterface(
89+
config.mxlen.size,
90+
config.mxlen.size,
91+
);
92+
93+
final mmuWrite = DataPortInterface(config.mxlen.size, config.mxlen.size);
94+
final sizedMmuWrite = DataPortInterface(
95+
config.mxlen.size + 7,
96+
config.mxlen.size,
97+
);
98+
99+
SizedWriteSingleDataPort(
100+
clk,
101+
reset,
102+
backingRead: mmuWritebackRead,
103+
backingWrite: mmuWrite,
104+
source: sizedMmuWrite,
105+
);
106+
107+
MmuHDL(
108+
clk,
109+
reset,
110+
[(MemoryAccess.write, mmuWrite)],
111+
[
112+
(MemoryAccess.instr, mmuFetchRead),
113+
(MemoryAccess.read, mmuExecRead),
114+
(MemoryAccess.read, mmuWritebackRead),
115+
],
116+
config: config.mmu,
117+
privilegeMode: mode,
118+
pagingMode: config.mmu.hasPaging ? pagingMode : null,
119+
pageTableAddress: config.mmu.hasPaging ? pageTableAddress : null,
120+
devices: devices,
121+
enableSum: config.mmu.hasSum ? enableSum : null,
122+
enableMxr: config.mmu.hasMxr ? enableMxr : null,
123+
fence: fence,
124+
);
65125

66126
final rs1Read = DataPortInterface(config.mxlen.size, 5);
67127
final rs2Read = DataPortInterface(config.mxlen.size, 5);
@@ -154,11 +214,20 @@ class RiverCoreHDL extends Module {
154214
externalPending: externalPending,
155215
hasSupervisor: config.hasSupervisor,
156216
hasUser: config.hasUser,
217+
hasPaging: config.mmu.hasPaging,
218+
hasMxr: config.mmu.hasMxr,
219+
hasSum: config.mmu.hasSum,
157220
csrRead: csrRead,
158221
csrWrite: csrWrite,
159222
)
160223
: null;
161224

225+
if (csrs != null) {
226+
pagingMode <= Const(0, width: pagingMode.width);
227+
pageTableAddress <= Const(0, width: config.mxlen.size);
228+
// TODO: drive pagingMode, pageTableAddress, mxr, and sum from CSRs
229+
}
230+
162231
pipeline = RiverPipeline(
163232
clk,
164233
reset,
@@ -169,9 +238,9 @@ class RiverCoreHDL extends Module {
169238
config.type.hasCsrs ? csrRead : null,
170239
config.type.hasCsrs ? csrWrite : null,
171240
// TODO: have a cache backed memory interface
172-
memFetchRead,
173-
memExecRead,
174-
memWrite,
241+
mmuFetchRead,
242+
mmuExecRead,
243+
sizedMmuWrite,
175244
rs1Read,
176245
rs2Read,
177246
rdWrite,
@@ -194,12 +263,13 @@ class RiverCoreHDL extends Module {
194263
pc < config.resetVector,
195264
sp < 0,
196265
mode < 0,
266+
fence < 0,
197267
interruptHold < 0,
198268
],
199269
orElse: [
200270
If(
201271
interruptHold & externalPending,
202-
then: [interruptHold < 0, pipelineEnable < 1],
272+
then: [interruptHold < 0, pipelineEnable < 1, fence < 0],
203273
),
204274

205275
If(
@@ -212,12 +282,13 @@ class RiverCoreHDL extends Module {
212282
sp < pipeline.nextSp,
213283
mode < pipeline.nextMode,
214284
interruptHold < pipeline.interruptHold,
285+
fence < pipeline.fence,
215286
pipelineEnable < 0,
216287
],
217-
orElse: [pipelineEnable < 1],
288+
orElse: [pipelineEnable < 1, fence < 0],
218289
),
219290
],
220-
orElse: [pipelineEnable < 0],
291+
orElse: [pipelineEnable < 0, fence < 0],
221292
),
222293
],
223294
),

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ class RiscVCsrFile extends Module {
5656

5757
final bool hasSupervisor;
5858
final bool hasUser;
59+
final bool hasPaging;
60+
final bool hasMxr;
61+
final bool hasSum;
5962

6063
late final Logic clk;
6164
late final Logic reset;
@@ -88,6 +91,9 @@ class RiscVCsrFile extends Module {
8891
Logic? externalPending,
8992
this.hasSupervisor = false,
9093
this.hasUser = false,
94+
this.hasPaging = false,
95+
this.hasMxr = false,
96+
this.hasSum = false,
9197
required DataPortInterface csrRead,
9298
required DataPortInterface csrWrite,
9399
super.name = 'riscv_csr_file',

0 commit comments

Comments
 (0)