Skip to content

Commit 76015bf

Browse files
feat(river_hdl): adding microcode execution
1 parent d857916 commit 76015bf

File tree

7 files changed

+2822
-1016
lines changed

7 files changed

+2822
-1016
lines changed

packages/riscv/lib/src/ops.dart

Lines changed: 78 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -127,9 +127,10 @@ class MicroOpEncoding<T extends MicroOp> {
127127
required this.constructor,
128128
});
129129

130-
int encode(T op, Mxlen mxlen) => struct(mxlen).encode(op.toMap());
130+
BigInt encode(T op, Mxlen mxlen) => struct(mxlen).bigEncode(op.toMap());
131131

132-
T decode(int value, Mxlen mxlen) => constructor(struct(mxlen).decode(value));
132+
T decode(BigInt value, Mxlen mxlen) =>
133+
constructor(struct(mxlen).bigDecode(value));
133134
}
134135

135136
/// {@category microcode}
@@ -270,6 +271,8 @@ enum MicroOpMemSize {
270271
final int bytes;
271272

272273
int get bits => bytes * 8;
274+
275+
static const int width = 2;
273276
}
274277

275278
/// {@category microcode}
@@ -300,9 +303,9 @@ class WriteCsrMicroOp extends MicroOp {
300303

301304
static BitStruct struct(Mxlen mxlen) => BitStruct({
302305
'funct': MicroOp.functRange,
303-
'field': const BitRange(5, 8),
304-
'source': const BitRange(9, 12),
305-
'offset': BitRange(13, 13 + mxlen.size),
306+
'field': const BitRange(5, 7),
307+
'source': const BitRange(8, 10),
308+
'offset': BitRange(11, 11 + mxlen.size),
306309
});
307310
}
308311

@@ -339,9 +342,9 @@ class ReadRegisterMicroOp extends MicroOp {
339342

340343
static BitStruct struct(Mxlen mxlen) => BitStruct({
341344
'funct': MicroOp.functRange,
342-
'source': const BitRange(5, 8),
343-
'offset': BitRange(9, 9 + mxlen.size),
344-
'valueOffset': BitRange(9 + mxlen.size, 9 + (mxlen.size * 2)),
345+
'source': const BitRange(5, 7),
346+
'offset': BitRange(8, 8 + mxlen.size - 1),
347+
'valueOffset': BitRange(8 + mxlen.size, 8 + (mxlen.size * 2) - 1),
345348
});
346349
}
347350

@@ -382,10 +385,10 @@ class WriteRegisterMicroOp extends MicroOp {
382385

383386
static BitStruct struct(Mxlen mxlen) => BitStruct({
384387
'funct': MicroOp.functRange,
385-
'field': const BitRange(5, 8),
386-
'source': const BitRange(9, 12),
387-
'offset': BitRange(13, 13 + mxlen.size),
388-
'valueOffset': BitRange(13 + mxlen.size, 13 + (mxlen.size * 2)),
388+
'field': const BitRange(5, 7),
389+
'source': const BitRange(8, 10),
390+
'offset': BitRange(11, 11 + mxlen.size - 1),
391+
'valueOffset': BitRange(11 + mxlen.size, 11 + (mxlen.size * 2) - 1),
389392
});
390393
}
391394

@@ -417,9 +420,9 @@ class ModifyLatchMicroOp extends MicroOp {
417420

418421
static BitStruct struct(Mxlen _) => BitStruct({
419422
'funct': MicroOp.functRange,
420-
'field': const BitRange(5, 8),
421-
'source': const BitRange(9, 12),
422-
'replace': BitRange.single(13),
423+
'field': const BitRange(5, 7),
424+
'source': const BitRange(8, 10),
425+
'replace': BitRange.single(11),
423426
});
424427
}
425428

@@ -451,9 +454,9 @@ class AluMicroOp extends MicroOp {
451454

452455
static BitStruct struct(Mxlen _) => BitStruct({
453456
'funct': MicroOp.functRange,
454-
'alu': const BitRange(5, 10),
455-
'a': const BitRange(11, 14),
456-
'b': const BitRange(15, 18),
457+
'alu': const BitRange(5, 9),
458+
'a': const BitRange(10, 12),
459+
'b': const BitRange(13, 15),
457460
});
458461
}
459462

@@ -497,11 +500,11 @@ class BranchIfMicroOp extends MicroOp {
497500

498501
static BitStruct struct(Mxlen mxlen) => BitStruct({
499502
'funct': MicroOp.functRange,
500-
'condition': const BitRange(5, 10),
501-
'target': const BitRange(11, 14),
502-
'hasField': const BitRange.single(15),
503-
'offsetField': const BitRange(16, 19),
504-
'offset': BitRange(20, 20 + mxlen.size),
503+
'condition': const BitRange(5, 7),
504+
'target': const BitRange(8, 10),
505+
'hasField': const BitRange.single(11),
506+
'offsetField': const BitRange(12, 14),
507+
'offset': BitRange(15, 15 + mxlen.size - 1),
505508
});
506509
}
507510

@@ -559,11 +562,11 @@ class UpdatePCMicroOp extends MicroOp {
559562
'source': const BitRange(5, 8),
560563
'hasSource': const BitRange.single(9),
561564
'hasField': const BitRange.single(10),
562-
'offsetField': const BitRange(11, 14),
563-
'offsetSource': const BitRange(15, 17),
564-
'absolute': const BitRange.single(18),
565-
'align': const BitRange.single(19),
566-
'offset': BitRange(20, 20 + mxlen.size),
565+
'offsetField': const BitRange(11, 13),
566+
'offsetSource': const BitRange(14, 16),
567+
'absolute': const BitRange.single(17),
568+
'align': const BitRange.single(18),
569+
'offset': BitRange(19, 19 + mxlen.size - 1),
567570
});
568571
}
569572

@@ -604,10 +607,10 @@ class MemLoadMicroOp extends MicroOp {
604607

605608
static BitStruct struct(Mxlen _) => BitStruct({
606609
'funct': MicroOp.functRange,
607-
'base': const BitRange(5, 8),
608-
'dest': const BitRange(9, 12),
609-
'size': const BitRange(13, 14),
610-
'unsigned': BitRange.single(15),
610+
'base': const BitRange(5, 7),
611+
'dest': const BitRange(8, 10),
612+
'size': const BitRange(11, 12),
613+
'unsigned': BitRange.single(13),
611614
});
612615
}
613616

@@ -643,9 +646,9 @@ class MemStoreMicroOp extends MicroOp {
643646

644647
static BitStruct struct(Mxlen _) => BitStruct({
645648
'funct': MicroOp.functRange,
646-
'base': const BitRange(5, 8),
647-
'src': const BitRange(9, 12),
648-
'size': const BitRange(13, 14),
649+
'base': const BitRange(5, 7),
650+
'src': const BitRange(8, 10),
651+
'size': const BitRange(11, 12),
649652
});
650653
}
651654

@@ -672,10 +675,8 @@ class TrapMicroOp extends MicroOp {
672675
Map<String, int> toMap() => {
673676
'funct': funct,
674677
'machine': kindMachine.index,
675-
'hasSupervisor': kindSupervisor != null ? 1 : 0,
676-
'supervisor': kindSupervisor?.index ?? 0,
677-
'hasUser': kindUser != null ? 1 : 0,
678-
'user': kindUser?.index ?? 0,
678+
'supervisor': kindSupervisor?.index ?? kindMachine.index,
679+
'user': kindSupervisor?.index ?? kindMachine.index,
679680
};
680681

681682
@override
@@ -685,12 +686,9 @@ class TrapMicroOp extends MicroOp {
685686

686687
static BitStruct struct(Mxlen _) => BitStruct({
687688
'funct': MicroOp.functRange,
688-
// 8 bits per trap kind
689-
'machine': const BitRange(5, 12),
690-
'supervisor': const BitRange(13, 20),
691-
'user': const BitRange(21, 28),
692-
'hasSupervisor': BitRange.single(29),
693-
'hasUser': BitRange.single(30),
689+
'machine': const BitRange(5, 9),
690+
'supervisor': const BitRange(10, 14),
691+
'user': const BitRange(15, 19),
694692
});
695693
}
696694

@@ -808,8 +806,8 @@ class WriteLinkRegisterMicroOp extends MicroOp {
808806

809807
static BitStruct struct(Mxlen mxlen) => BitStruct({
810808
'funct': MicroOp.functRange,
811-
'link': const BitRange(5, 7),
812-
'pcOffset': BitRange(8, 8 + mxlen.size),
809+
'link': const BitRange.single(5),
810+
'pcOffset': BitRange(6, 6 + mxlen.size - 1),
813811
});
814812
}
815813

@@ -984,9 +982,9 @@ class ValidateFieldMicroOp extends MicroOp {
984982

985983
static BitStruct struct(Mxlen mxlen) => BitStruct({
986984
'funct': MicroOp.functRange,
987-
'condition': const BitRange(5, 8),
988-
'field': const BitRange(9, 12),
989-
'value': BitRange(12, 12 + mxlen.size),
985+
'condition': const BitRange(5, 7),
986+
'field': const BitRange(8, 10),
987+
'value': BitRange(10, 10 + mxlen.size - 1),
990988
});
991989
}
992990

@@ -1015,8 +1013,8 @@ class SetFieldMicroOp extends MicroOp {
10151013

10161014
static BitStruct struct(Mxlen mxlen) => BitStruct({
10171015
'funct': MicroOp.functRange,
1018-
'field': const BitRange(5, 8),
1019-
'value': BitRange(9, 9 + mxlen.size),
1016+
'field': const BitRange(5, 7),
1017+
'value': BitRange(8, 8 + mxlen.size - 1),
10201018
});
10211019
}
10221020

@@ -1035,11 +1033,10 @@ class ReadCsrMicroOp extends MicroOp {
10351033
@override
10361034
String toString() => 'ReadCsrMicroOp($source)';
10371035

1038-
// NOTE: must be unique, SetField uses 21
10391036
static const int funct = 22;
10401037

10411038
static BitStruct struct(Mxlen _) =>
1042-
BitStruct({'funct': MicroOp.functRange, 'source': const BitRange(5, 8)});
1039+
BitStruct({'funct': MicroOp.functRange, 'source': const BitRange(5, 7)});
10431040
}
10441041

10451042
class OperationDecodePattern {
@@ -1268,21 +1265,25 @@ class Operation<T extends InstructionType> {
12681265

12691266
bool matches(InstructionType instr) => _mapMatch(instr.toMap());
12701267

1271-
int microcodeWidth(Mxlen mxlen) => microcode
1268+
int mopWidth(Mxlen mxlen) => microcode
12721269
.map((mop) {
12731270
final m = mop.toMap();
12741271
final funct = m['funct']!;
12751272
final e = kMicroOpTable.firstWhere((e) => e.funct == funct);
1276-
final s = e.struct(mxlen);
1277-
1278-
for (final field in s.mapping.entries) {
1279-
m[field.key] = field.value.mask;
1280-
}
1281-
1282-
return s.encode(m).bitLength;
1273+
return e.struct(mxlen).width;
12831274
})
12841275
.fold(0, (a, b) => a > b ? a : b);
12851276

1277+
List<BigInt> mopEncode(Mxlen mxlen) => [
1278+
BigInt.from(microcode.length),
1279+
...microcode.map((mop) {
1280+
final m = mop.toMap();
1281+
final funct = m['funct']!;
1282+
final e = kMicroOpTable.firstWhere((e) => e.funct == funct);
1283+
return e.struct(mxlen).bigEncode(m);
1284+
}),
1285+
];
1286+
12861287
@override
12871288
String toString() =>
12881289
'Operation(mnemonic: $mnemonic, opcode: $opcode, funct2: $funct2,'
@@ -1385,12 +1386,19 @@ class Microcode {
13851386
fieldIndices,
13861387
).width;
13871388

1388-
int get opIndexWidth => decodeLookup.keys.fold(0, (a, b) => a > b ? a : b);
1389+
int get opIndexWidth =>
1390+
decodeLookup.keys.fold(0, (a, b) => a > b ? a : b).bitLength;
13891391

1390-
int opWidth(Mxlen mxlen) => map.values
1391-
.map((op) => op.microcodeWidth(mxlen))
1392+
int mopWidth(Mxlen mxlen) => map.values
1393+
.map((op) => op.mopWidth(mxlen))
13921394
.fold(0, (a, b) => a > b ? a : b);
13931395

1396+
int mopIndexWidth(Mxlen mxlen) => encodedMops(mxlen).length.bitLength;
1397+
1398+
List<BigInt> encodedMops(Mxlen mxlen) => map.values
1399+
.map((m) => m.mopEncode(mxlen))
1400+
.fold([], (a, b) => [...a, ...b]);
1401+
13941402
Map<int, OperationDecodePattern> get decodeLookup {
13951403
Map<int, OperationDecodePattern> result = {};
13961404
var i = 0;
@@ -1621,4 +1629,9 @@ class Microcode {
16211629
final name = i.runtimeType.toString();
16221630
return name.substring(10, name.length - 1);
16231631
}
1632+
1633+
static String mopType<T extends MicroOp>(MicroOpEncoding<T> i) {
1634+
final name = i.runtimeType.toString();
1635+
return name.substring(16, name.length - 8);
1636+
}
16241637
}

packages/river_hdl/lib/src/core.dart

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -239,13 +239,27 @@ class RiverCoreIP extends BridgeModule {
239239
)
240240
: null;
241241

242-
if (csrs != null) {
242+
if (csrs != null && csrs.satp != null) {
243+
pagingMode <=
244+
((csrs.satp! >>
245+
Const(config.mxlen.satpModeShift, width: config.mxlen.size)) &
246+
Const(config.mxlen.satpModeMask, width: config.mxlen.size));
247+
pageTableAddress <=
248+
(csrs.satp! &
249+
Const(config.mxlen.satpPpnMask, width: config.mxlen.size));
250+
} else {
243251
pagingMode <= Const(0, width: pagingMode.width);
244252
pageTableAddress <= Const(0, width: config.mxlen.size);
245-
// TODO: drive pagingMode, pageTableAddress, mxr, and sum from CSRs
246253
}
247254

248-
final microcodeRead = DataPortInterface(
255+
if (csrs != null) {
256+
enableMxr <=
257+
((csrs.mstatus >> 19) & Const(1, width: config.mxlen.size)).neq(0);
258+
enableSum <=
259+
((csrs.mstatus >> 18) & Const(1, width: config.mxlen.size)).neq(0);
260+
}
261+
262+
final microcodeDecodeRead = DataPortInterface(
249263
config.microcode.patternWidth,
250264
config.microcode.map.length.bitLength,
251265
);
@@ -255,13 +269,32 @@ class RiverCoreIP extends BridgeModule {
255269
clk,
256270
reset,
257271
[],
258-
[microcodeRead],
272+
[microcodeDecodeRead],
259273
numEntries: config.microcode.map.length,
260274
resetValue: config.microcode.encodedPatterns,
261275
definitionName: 'RiverMicrocodeLookup',
262276
);
263277
}
264278

279+
final microcodeExecRead = DataPortInterface(
280+
config.microcode.mopWidth(config.mxlen),
281+
config.microcode.mopIndexWidth(config.mxlen),
282+
);
283+
284+
if (config.microcodeMode.onExec != MicrocodePipelineMode.none) {
285+
final mops = config.microcode.encodedMops(config.mxlen);
286+
287+
RegisterFile(
288+
clk,
289+
reset,
290+
[],
291+
[microcodeExecRead],
292+
numEntries: mops.length,
293+
resetValue: mops,
294+
definitionName: 'RiverMicrocodeOperations',
295+
);
296+
}
297+
265298
pipeline = RiverPipeline(
266299
clk,
267300
reset,
@@ -279,10 +312,15 @@ class RiverCoreIP extends BridgeModule {
279312
rs2Read,
280313
rdWrite,
281314
config.microcodeMode.onDecoder != MicrocodePipelineMode.none
282-
? microcodeRead
315+
? microcodeDecodeRead
316+
: null,
317+
config.microcodeMode.onExec != MicrocodePipelineMode.none
318+
? microcodeExecRead
283319
: null,
284320
useMixedDecoders:
285321
config.microcodeMode.onDecoder == MicrocodePipelineMode.in_parallel,
322+
useMixedExecution:
323+
config.microcodeMode.onExec == MicrocodePipelineMode.in_parallel,
286324
microcode: config.microcode,
287325
mxlen: config.mxlen,
288326
hasSupervisor: config.hasSupervisor,

0 commit comments

Comments
 (0)