Skip to content

Commit ae10edf

Browse files
feat(river_hdl): adding devices
1 parent e69a580 commit ae10edf

13 files changed

Lines changed: 1013 additions & 98 deletions

File tree

packages/river/lib/src/dev.dart

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,10 @@ class Device {
113113
final BusClientPort? clientPort;
114114
final ClockConfig? clock;
115115

116+
String get module => (runtimeType.toString() == 'Device')
117+
? compatible.replaceAll(',', '_')
118+
: runtimeType.toString();
119+
116120
const Device({
117121
required this.name,
118122
required this.compatible,
@@ -133,6 +137,7 @@ class Device {
133137
Map<int, DeviceField>? fields,
134138
DeviceAccessorType type = DeviceAccessorType.memory,
135139
ClockConfig? clock,
140+
List<DevicePort> ports = const [],
136141
}) {
137142
path ??= '/$name';
138143
final accessor = fields != null
@@ -154,6 +159,7 @@ class Device {
154159
accessor: accessor,
155160
clientPort: clientPort,
156161
clock: clock,
162+
ports: ports,
157163
);
158164
}
159165

packages/river/lib/src/impl/devices/uart.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ class RiverUart extends Device {
2727
6: DeviceField('msr', 1),
2828
7: DeviceField('scr', 1),
2929
}, type: DeviceAccessorType.io),
30+
ports: [DevicePort('rx', 1), DevicePort('tx', 1, isOutput: true)],
3031
);
3132

3233
static const lcr = BitStruct({

packages/river/lib/src/impl/soc/stream/v1.dart

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,10 @@ class StreamV1SoC extends RiverSoC {
126126
];
127127

128128
@override
129-
List<RiverPortMap> get ports => [];
129+
List<RiverPortMap> get ports => [
130+
const RiverPortMap('uart_rx', [4], {'uart0': 'rx'}),
131+
const RiverPortMap('uart_tx', [6], {'uart0': 'tx'}, isOutput: true),
132+
];
130133

131134
List<MemoryBlock> get mmap =>
132135
devices.map((dev) => dev.mmap).nonNulls.toList();

packages/river/lib/src/river_base.dart

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -192,15 +192,15 @@ class RiverCore {
192192
class RiverPortMap {
193193
final String name;
194194
final List<int> pins;
195-
final List<String> devices;
195+
final Map<String, String> devices;
196196
final bool isOutput;
197197

198198
int get width => pins.length.bitLength;
199199

200200
const RiverPortMap(
201-
this.name, {
202-
this.pins = const [],
203-
this.devices = const [],
201+
this.name,
202+
this.pins,
203+
this.devices, {
204204
this.isOutput = false,
205205
});
206206

packages/river_hdl/bin/river_hdlgen.dart

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'dart:io' show Platform, File;
22

33
import 'package:args/args.dart';
4+
import 'package:logging/logging.dart';
45
import 'package:path/path.dart' as path;
56
import 'package:river/river.dart';
67
import 'package:river_hdl/river_hdl.dart';
@@ -25,11 +26,23 @@ Future<void> main(List<String> arguments) async {
2526
allowed: RiverPlatformChoice.values.map((v) => v.name).toList(),
2627
);
2728

29+
parser.addMultiOption(
30+
'device-option',
31+
help: 'Adds an option when configuring a device',
32+
splitCommas: false,
33+
);
34+
2835
parser.addOption(
2936
'output',
3037
help: 'Sets the output path to generate the SystemVerilog to',
3138
);
3239

40+
parser.addOption(
41+
'log',
42+
help: 'Sets the log level',
43+
allowed: Level.LEVELS.map((v) => v.name.toLowerCase()).toList(),
44+
);
45+
3346
parser.addFlag('help', help: 'Prints the usage');
3447

3548
final args = parser.parse(arguments);
@@ -42,6 +55,17 @@ Future<void> main(List<String> arguments) async {
4255
return;
4356
}
4457

58+
Logger.root.onRecord.listen((record) {
59+
print('${record.level.name}: ${record.time}: ${record.message}');
60+
});
61+
62+
if (args.option('log') != null) {
63+
Logger.root.level = Level.LEVELS.firstWhere(
64+
(v) => v.name.toLowerCase() == args.option('log'),
65+
);
66+
Logger.root.finest('Logging set to ${Logger.root.level}');
67+
}
68+
4569
RiverPlatformChoice? platformChoice;
4670
RiverSoCChoice? socChoice;
4771

@@ -97,7 +121,53 @@ Future<void> main(List<String> arguments) async {
97121
}) ??
98122
(throw 'Invalid platform configuration');
99123

100-
final ip = RiverSoCIP(socConfig);
124+
Logger.root.finest('River SoC configured: $socConfig');
101125

102-
await ip.buildAndGenerateRTL(outputPath: args.option('output') ?? 'output');
126+
final ip = RiverSoCIP(
127+
socConfig,
128+
deviceOptions: Map.fromEntries(
129+
args
130+
.multiOption('device-option')
131+
.map((option) {
132+
final i = option.indexOf('.');
133+
assert(i > 0);
134+
return option.substring(0, i);
135+
})
136+
.map(
137+
(key) => MapEntry(
138+
key,
139+
Map.fromEntries(
140+
args
141+
.multiOption('device-option')
142+
.where((option) {
143+
final i = option.indexOf('.');
144+
assert(i > 0);
145+
return option.substring(0, i) == key;
146+
})
147+
.map((option) {
148+
final i = option.indexOf('.');
149+
assert(i > 0);
150+
151+
final entry = option.substring(i + 1);
152+
153+
final x = entry.indexOf('=');
154+
assert(x > 0);
155+
156+
return MapEntry(
157+
entry.substring(0, x),
158+
entry.substring(x + 1),
159+
);
160+
}),
161+
),
162+
),
163+
),
164+
),
165+
);
166+
167+
Logger.root.finest('River SoC module created: $ip');
168+
169+
await ip.buildAndGenerateRTL(
170+
logger: Logger.root,
171+
outputPath: args.option('output') ?? 'output',
172+
);
103173
}

packages/river_hdl/lib/river_hdl.dart

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

0 commit comments

Comments
 (0)