Skip to content

Commit 968b793

Browse files
feat(river_hdl): adding microcode execution
1 parent d857916 commit 968b793

15 files changed

Lines changed: 3351 additions & 1079 deletions

File tree

flake.nix

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242

4343
gitHashes = {
4444
rohd_hcl = "sha256-YobXIH2PTUXxp6MfcAIJG8aXhkc1MZOLthOEaQUJxOM=";
45+
z3 = "sha256-B1gmCsFivLDKCJcBmdf2JOJqDvn6bEawqJ8QLix5Ils=";
4546
};
4647

4748
buildDartTest =
@@ -120,6 +121,10 @@
120121

121122
src = ./.;
122123

124+
buildInputs = [
125+
pkgs.z3
126+
];
127+
123128
dartEntryPoints = {
124129
"bin/river-emulator" = "packages/river_emulator/bin/river_emulator.dart";
125130
"bin/river-hdlgen" = "packages/river_hdl/bin/river_hdlgen.dart";
@@ -128,6 +133,10 @@
128133
preBuild = ''
129134
mkdir -p bin
130135
'';
136+
137+
postBuild = ''
138+
patchelf bin/river-hdlgen --add-needed libz3.so
139+
'';
131140
};
132141
emulator = buildDartApplication {
133142
pname = "river-emulator";
@@ -146,6 +155,10 @@
146155
pname = "river-hdl";
147156
inherit version pubspecLock gitHashes;
148157

158+
buildInputs = [
159+
pkgs.z3
160+
];
161+
149162
src = ./.;
150163
packageRoot = "packages/river_hdl";
151164

@@ -154,10 +167,16 @@
154167
preBuild = ''
155168
mkdir -p bin
156169
'';
170+
171+
postBuild = ''
172+
patchelf bin/river-hdlgen --add-needed libz3.so
173+
'';
157174
};
158175
};
159176

160177
devShells.default = pkgs.mkShell {
178+
LD_LIBRARY_PATH = "${pkgs.z3.lib}/lib";
179+
161180
packages =
162181
with pkgs;
163182
(
@@ -167,7 +186,9 @@
167186
yosys
168187
icestorm
169188
nextpnr
189+
z3
170190
gtkwave
191+
surfer
171192
pkgsCross.riscv32-embedded.stdenv.cc
172193
pkgsCross.riscv64-embedded.stdenv.cc
173194
]

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/bin/river_hdlgen.dart

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ Future<void> main(List<String> arguments) async {
123123

124124
Logger.root.finest('River SoC configured: $socConfig');
125125

126+
List<String> staticInstructions = [];
127+
126128
final ip = RiverSoCIP(
127129
socConfig,
128130
deviceOptions: Map.fromEntries(
@@ -162,6 +164,7 @@ Future<void> main(List<String> arguments) async {
162164
),
163165
),
164166
),
167+
staticInstructions: staticInstructions,
165168
);
166169

167170
Logger.root.finest('River SoC module created: $ip');

packages/river_hdl/lib/river_hdl.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,6 @@ export 'src/core/pipeline.dart';
1010
export 'src/core.dart';
1111
export 'src/dev.dart';
1212
export 'src/devices.dart';
13+
1314
export 'src/memory/port.dart';
1415
export 'src/soc.dart';

0 commit comments

Comments
 (0)