yosys2digitaljs 0.6.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  name: Node.js CI
2
2
 
3
- on: [push]
3
+ on: [push, pull_request]
4
4
 
5
5
  jobs:
6
6
  build:
@@ -9,7 +9,7 @@ jobs:
9
9
 
10
10
  strategy:
11
11
  matrix:
12
- node-version: [8.x, 10.x, 12.x]
12
+ node-version: [12.x, 14.x, 16.x]
13
13
 
14
14
  steps:
15
15
  - uses: actions/checkout@v2
package/ChangeLog.md CHANGED
@@ -1,6 +1,13 @@
1
1
  # Changelog
2
2
  All notable changes to this project will be documented in this file.
3
3
 
4
+ ## [0.7.0] -- 2023-03-2023
5
+
6
+ ### Added
7
+
8
+ - Support for `$lut` cells
9
+ - Support for generating 7-segment display outputs
10
+
4
11
  ## [0.6.0] -- 2022-02-02
5
12
 
6
13
  ### Added
package/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # yosys2digitaljs
2
- This program converts JSON netlist output generated by [Yosys](http://www.clifford.at/yosys/)
3
- circuit synthesis software for use with the
2
+ This program converts JSON netlist output generated by [Yosys](https://yosyshq.net/yosys/)
3
+ circuit synthesis software (Github repo [here](https://github.com/YosysHQ/yosys/)) for use with the
4
4
  [DigitalJS](http://github.com/tilk/digitaljs) graphical circuit simulator.
5
5
 
6
6
  # Usage
7
- You need to have [Yosys](http://www.clifford.at/yosys/) installed to run
7
+ You need to have [Yosys](https://yosyshq.net/yosys/) installed to run
8
8
  yosys2digitaljs. For example, in Debian/Ubuntu, run:
9
9
  ```bash
10
10
  apt install yosys
package/dist/index.js CHANGED
@@ -62,6 +62,7 @@ const gate_subst = new Map([
62
62
  ['$pmux', 'Mux1Hot'],
63
63
  ['$mem', 'Memory'],
64
64
  ['$mem_v2', 'Memory'],
65
+ ['$lut', 'Memory'],
65
66
  ['$fsm', 'FSM'],
66
67
  ['$clock', 'Clock'],
67
68
  ['$button', 'Button'],
@@ -865,6 +866,23 @@ function yosys_to_digitaljs_mod(name, mod, portmaps, options = {}) {
865
866
  }
866
867
  break;
867
868
  }
869
+ case '$lut':
870
+ assert(cell.connections.A.length == decode_json_number(cell.parameters.WIDTH));
871
+ assert(cell.connections.Y.length == 1);
872
+ assert(cell.port_directions.A == 'input');
873
+ assert(cell.port_directions.Y == 'output');
874
+ dev.abits = cell.connections.A.length;
875
+ dev.bits = cell.connections.Y.length;
876
+ dev.rdports = [{}];
877
+ dev.wrports = [];
878
+ dev.memdata = cell.parameters.LUT.split('').reverse();
879
+ assert(dev.memdata.length == Math.pow(2, dev.abits));
880
+ // Rewrite cell connections to be $mem compatible for port mapping
881
+ cell.connections.RD_ADDR = cell.connections.A;
882
+ cell.connections.RD_DATA = cell.connections.Y;
883
+ delete cell.connections.A;
884
+ delete cell.connections.Y;
885
+ break;
868
886
  default:
869
887
  }
870
888
  if (dev.type == 'Dff') {
@@ -887,6 +905,8 @@ function yosys_to_digitaljs_mod(name, mod, portmaps, options = {}) {
887
905
  connect_mem(dname, cell, dev);
888
906
  else if (cell.type == '$mem_v2')
889
907
  connect_mem(dname, cell, dev);
908
+ else if (cell.type == '$lut')
909
+ connect_mem(dname, cell, dev);
890
910
  else
891
911
  throw Error('Invalid cell type: ' + cell.type);
892
912
  }
@@ -1093,8 +1113,14 @@ function io_ui(output) {
1093
1113
  }
1094
1114
  if (dev.type == 'Input')
1095
1115
  dev.type = dev.bits == 1 ? 'Button' : 'NumEntry';
1096
- if (dev.type == 'Output')
1097
- dev.type = dev.bits == 1 ? 'Lamp' : 'NumDisplay';
1116
+ if (dev.type == 'Output') {
1117
+ if (dev.bits == 1)
1118
+ dev.type = 'Lamp';
1119
+ else if (dev.bits == 8 && (dev.label == 'display7' || dev.label.startsWith('display7_')))
1120
+ dev.type = 'Display7';
1121
+ else
1122
+ dev.type = 'NumDisplay';
1123
+ }
1098
1124
  }
1099
1125
  }
1100
1126
  exports.io_ui = io_ui;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yosys2digitaljs",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Export Yosys netlists to a logic simulator",
5
5
  "main": "dist/index",
6
6
  "types": "dist/index.d.ts",
@@ -13,7 +13,7 @@
13
13
  "author": "Marek Materzok",
14
14
  "license": "BSD-2-Clause",
15
15
  "dependencies": {
16
- "3vl": "^0.3.5",
16
+ "3vl": "^1.0.1",
17
17
  "big-integer": "^1.6.49",
18
18
  "hashmap": "^2.4.0",
19
19
  "minimist": "^1.2.5",
package/result.json ADDED
@@ -0,0 +1,420 @@
1
+ {
2
+ "creator": "Yosys 0.8 (git sha1 5706e90)",
3
+ "modules": {
4
+ "fsm": {
5
+ "attributes": {
6
+ "src": "tests/fsm.sv:1"
7
+ },
8
+ "ports": {
9
+ "clk": {
10
+ "direction": "input",
11
+ "bits": [ 2 ]
12
+ },
13
+ "rst": {
14
+ "direction": "input",
15
+ "bits": [ 3 ]
16
+ },
17
+ "a": {
18
+ "direction": "input",
19
+ "bits": [ 4 ]
20
+ },
21
+ "b": {
22
+ "direction": "output",
23
+ "bits": [ 5 ]
24
+ }
25
+ },
26
+ "cells": {
27
+ "$auto$simplemap.cc:136:simplemap_reduce$41": {
28
+ "hide_name": 1,
29
+ "type": "$_OR_",
30
+ "parameters": {
31
+ },
32
+ "attributes": {
33
+ },
34
+ "port_directions": {
35
+ "A": "input",
36
+ "B": "input",
37
+ "Y": "output"
38
+ },
39
+ "connections": {
40
+ "A": [ 6 ],
41
+ "B": [ 7 ],
42
+ "Y": [ 8 ]
43
+ }
44
+ },
45
+ "$auto$simplemap.cc:136:simplemap_reduce$61": {
46
+ "hide_name": 1,
47
+ "type": "$_OR_",
48
+ "parameters": {
49
+ },
50
+ "attributes": {
51
+ "src": "tests/fsm.sv:16"
52
+ },
53
+ "port_directions": {
54
+ "A": "input",
55
+ "B": "input",
56
+ "Y": "output"
57
+ },
58
+ "connections": {
59
+ "A": [ 7 ],
60
+ "B": [ 9 ],
61
+ "Y": [ 10 ]
62
+ }
63
+ },
64
+ "$auto$simplemap.cc:136:simplemap_reduce$63": {
65
+ "hide_name": 1,
66
+ "type": "$_OR_",
67
+ "parameters": {
68
+ },
69
+ "attributes": {
70
+ "src": "tests/fsm.sv:16"
71
+ },
72
+ "port_directions": {
73
+ "A": "input",
74
+ "B": "input",
75
+ "Y": "output"
76
+ },
77
+ "connections": {
78
+ "A": [ 6 ],
79
+ "B": [ 11 ],
80
+ "Y": [ 12 ]
81
+ }
82
+ },
83
+ "$auto$simplemap.cc:206:simplemap_lognot$52": {
84
+ "hide_name": 1,
85
+ "type": "$_NOT_",
86
+ "parameters": {
87
+ },
88
+ "attributes": {
89
+ },
90
+ "port_directions": {
91
+ "A": "input",
92
+ "Y": "output"
93
+ },
94
+ "connections": {
95
+ "A": [ 13 ],
96
+ "Y": [ 14 ]
97
+ }
98
+ },
99
+ "$auto$simplemap.cc:206:simplemap_lognot$59": {
100
+ "hide_name": 1,
101
+ "type": "$_NOT_",
102
+ "parameters": {
103
+ },
104
+ "attributes": {
105
+ },
106
+ "port_directions": {
107
+ "A": "input",
108
+ "Y": "output"
109
+ },
110
+ "connections": {
111
+ "A": [ 15 ],
112
+ "Y": [ 16 ]
113
+ }
114
+ },
115
+ "$auto$simplemap.cc:496:simplemap_adff$42": {
116
+ "hide_name": 1,
117
+ "type": "$_DFF_PP1_",
118
+ "parameters": {
119
+ },
120
+ "attributes": {
121
+ },
122
+ "port_directions": {
123
+ "C": "input",
124
+ "D": "input",
125
+ "Q": "output",
126
+ "R": "input"
127
+ },
128
+ "connections": {
129
+ "C": [ 2 ],
130
+ "D": [ 11 ],
131
+ "Q": [ 6 ],
132
+ "R": [ 3 ]
133
+ }
134
+ },
135
+ "$auto$simplemap.cc:496:simplemap_adff$43": {
136
+ "hide_name": 1,
137
+ "type": "$_DFF_PP0_",
138
+ "parameters": {
139
+ },
140
+ "attributes": {
141
+ },
142
+ "port_directions": {
143
+ "C": "input",
144
+ "D": "input",
145
+ "Q": "output",
146
+ "R": "input"
147
+ },
148
+ "connections": {
149
+ "C": [ 2 ],
150
+ "D": [ 8 ],
151
+ "Q": [ 9 ],
152
+ "R": [ 3 ]
153
+ }
154
+ },
155
+ "$auto$simplemap.cc:496:simplemap_adff$44": {
156
+ "hide_name": 1,
157
+ "type": "$_DFF_PP0_",
158
+ "parameters": {
159
+ },
160
+ "attributes": {
161
+ },
162
+ "port_directions": {
163
+ "C": "input",
164
+ "D": "input",
165
+ "Q": "output",
166
+ "R": "input"
167
+ },
168
+ "connections": {
169
+ "C": [ 2 ],
170
+ "D": [ 17 ],
171
+ "Q": [ 7 ],
172
+ "R": [ 3 ]
173
+ }
174
+ },
175
+ "$auto$simplemap.cc:496:simplemap_adff$45": {
176
+ "hide_name": 1,
177
+ "type": "$_DFF_PP0_",
178
+ "parameters": {
179
+ },
180
+ "attributes": {
181
+ },
182
+ "port_directions": {
183
+ "C": "input",
184
+ "D": "input",
185
+ "Q": "output",
186
+ "R": "input"
187
+ },
188
+ "connections": {
189
+ "C": [ 2 ],
190
+ "D": [ 18 ],
191
+ "Q": [ 11 ],
192
+ "R": [ 3 ]
193
+ }
194
+ },
195
+ "$auto$simplemap.cc:85:simplemap_bitop$38": {
196
+ "hide_name": 1,
197
+ "type": "$_AND_",
198
+ "parameters": {
199
+ },
200
+ "attributes": {
201
+ },
202
+ "port_directions": {
203
+ "A": "input",
204
+ "B": "input",
205
+ "Y": "output"
206
+ },
207
+ "connections": {
208
+ "A": [ 14 ],
209
+ "B": [ 9 ],
210
+ "Y": [ 17 ]
211
+ }
212
+ },
213
+ "$auto$simplemap.cc:85:simplemap_bitop$39": {
214
+ "hide_name": 1,
215
+ "type": "$_AND_",
216
+ "parameters": {
217
+ },
218
+ "attributes": {
219
+ },
220
+ "port_directions": {
221
+ "A": "input",
222
+ "B": "input",
223
+ "Y": "output"
224
+ },
225
+ "connections": {
226
+ "A": [ 16 ],
227
+ "B": [ 9 ],
228
+ "Y": [ 18 ]
229
+ }
230
+ },
231
+ "$auto$simplemap.cc:85:simplemap_bitop$48": {
232
+ "hide_name": 1,
233
+ "type": "$_XOR_",
234
+ "parameters": {
235
+ },
236
+ "attributes": {
237
+ },
238
+ "port_directions": {
239
+ "A": "input",
240
+ "B": "input",
241
+ "Y": "output"
242
+ },
243
+ "connections": {
244
+ "A": [ 4 ],
245
+ "B": [ "0" ],
246
+ "Y": [ 13 ]
247
+ }
248
+ },
249
+ "$auto$simplemap.cc:85:simplemap_bitop$55": {
250
+ "hide_name": 1,
251
+ "type": "$_XOR_",
252
+ "parameters": {
253
+ },
254
+ "attributes": {
255
+ },
256
+ "port_directions": {
257
+ "A": "input",
258
+ "B": "input",
259
+ "Y": "output"
260
+ },
261
+ "connections": {
262
+ "A": [ 4 ],
263
+ "B": [ "1" ],
264
+ "Y": [ 15 ]
265
+ }
266
+ },
267
+ "$procmux$3": {
268
+ "hide_name": 1,
269
+ "type": "$pmux",
270
+ "parameters": {
271
+ "S_WIDTH": 2,
272
+ "WIDTH": 1
273
+ },
274
+ "attributes": {
275
+ "src": "tests/fsm.sv:16"
276
+ },
277
+ "port_directions": {
278
+ "A": "input",
279
+ "B": "input",
280
+ "S": "input",
281
+ "Y": "output"
282
+ },
283
+ "connections": {
284
+ "A": [ "x" ],
285
+ "B": [ "1", "0" ],
286
+ "S": [ 10, 12 ],
287
+ "Y": [ 5 ]
288
+ }
289
+ }
290
+ },
291
+ "netnames": {
292
+ "$auto$fsm_map.cc:118:implement_pattern_cache$31": {
293
+ "hide_name": 1,
294
+ "bits": [ 17 ],
295
+ "attributes": {
296
+ }
297
+ },
298
+ "$auto$fsm_map.cc:118:implement_pattern_cache$35": {
299
+ "hide_name": 1,
300
+ "bits": [ 18 ],
301
+ "attributes": {
302
+ }
303
+ },
304
+ "$auto$fsm_map.cc:170:map_fsm$24": {
305
+ "hide_name": 1,
306
+ "bits": [ 19, 8 ],
307
+ "attributes": {
308
+ }
309
+ },
310
+ "$auto$fsm_map.cc:74:implement_pattern_cache$29": {
311
+ "hide_name": 1,
312
+ "bits": [ 14 ],
313
+ "attributes": {
314
+ }
315
+ },
316
+ "$auto$fsm_map.cc:74:implement_pattern_cache$33": {
317
+ "hide_name": 1,
318
+ "bits": [ 16 ],
319
+ "attributes": {
320
+ }
321
+ },
322
+ "$auto$simplemap.cc:127:simplemap_reduce$40": {
323
+ "hide_name": 1,
324
+ "bits": [ 20 ],
325
+ "attributes": {
326
+ }
327
+ },
328
+ "$auto$simplemap.cc:127:simplemap_reduce$60": {
329
+ "hide_name": 1,
330
+ "bits": [ 21 ],
331
+ "attributes": {
332
+ }
333
+ },
334
+ "$auto$simplemap.cc:127:simplemap_reduce$62": {
335
+ "hide_name": 1,
336
+ "bits": [ 22 ],
337
+ "attributes": {
338
+ }
339
+ },
340
+ "$auto$simplemap.cc:250:simplemap_eqne$46": {
341
+ "hide_name": 1,
342
+ "bits": [ 13 ],
343
+ "attributes": {
344
+ }
345
+ },
346
+ "$auto$simplemap.cc:250:simplemap_eqne$53": {
347
+ "hide_name": 1,
348
+ "bits": [ 15 ],
349
+ "attributes": {
350
+ }
351
+ },
352
+ "$auto$simplemap.cc:256:simplemap_eqne$49": {
353
+ "hide_name": 1,
354
+ "bits": [ 13 ],
355
+ "attributes": {
356
+ }
357
+ },
358
+ "$auto$simplemap.cc:256:simplemap_eqne$56": {
359
+ "hide_name": 1,
360
+ "bits": [ 15 ],
361
+ "attributes": {
362
+ }
363
+ },
364
+ "$auto$wreduce.cc:347:run$37": {
365
+ "hide_name": 1,
366
+ "bits": [ 19, 8, 23, 24 ],
367
+ "attributes": {
368
+ }
369
+ },
370
+ "$procmux$4_CTRL": {
371
+ "hide_name": 1,
372
+ "bits": [ 10 ],
373
+ "attributes": {
374
+ }
375
+ },
376
+ "$procmux$5_CTRL": {
377
+ "hide_name": 1,
378
+ "bits": [ 12 ],
379
+ "attributes": {
380
+ }
381
+ },
382
+ "a": {
383
+ "hide_name": 0,
384
+ "bits": [ 4 ],
385
+ "attributes": {
386
+ "src": "tests/fsm.sv:1"
387
+ }
388
+ },
389
+ "b": {
390
+ "hide_name": 0,
391
+ "bits": [ 5 ],
392
+ "attributes": {
393
+ "src": "tests/fsm.sv:1"
394
+ }
395
+ },
396
+ "clk": {
397
+ "hide_name": 0,
398
+ "bits": [ 2 ],
399
+ "attributes": {
400
+ "src": "tests/fsm.sv:1"
401
+ }
402
+ },
403
+ "rst": {
404
+ "hide_name": 0,
405
+ "bits": [ 3 ],
406
+ "attributes": {
407
+ "src": "tests/fsm.sv:1"
408
+ }
409
+ },
410
+ "state": {
411
+ "hide_name": 0,
412
+ "bits": [ 6, 9, 7, 11 ],
413
+ "attributes": {
414
+ "onehot": 1
415
+ }
416
+ }
417
+ }
418
+ }
419
+ }
420
+ }
package/src/index.ts CHANGED
@@ -61,6 +61,7 @@ const gate_subst = new Map([
61
61
  ['$pmux', 'Mux1Hot'],
62
62
  ['$mem', 'Memory'],
63
63
  ['$mem_v2', 'Memory'],
64
+ ['$lut', 'Memory'],
64
65
  ['$fsm', 'FSM'],
65
66
  ['$clock', 'Clock'],
66
67
  ['$button', 'Button'],
@@ -1030,6 +1031,24 @@ function yosys_to_digitaljs_mod(name: string, mod: Yosys.Module, portmaps: Portm
1030
1031
  }
1031
1032
  break;
1032
1033
  }
1034
+ case '$lut':
1035
+ assert(cell.connections.A.length == decode_json_number(cell.parameters.WIDTH));
1036
+ assert(cell.connections.Y.length == 1);
1037
+ assert(cell.port_directions.A == 'input');
1038
+ assert(cell.port_directions.Y == 'output');
1039
+ dev.abits = cell.connections.A.length;
1040
+ dev.bits = cell.connections.Y.length;
1041
+ dev.rdports = [{}];
1042
+ dev.wrports = [];
1043
+ dev.memdata = cell.parameters.LUT.split('').reverse();
1044
+ assert(dev.memdata.length == Math.pow(2, dev.abits));
1045
+
1046
+ // Rewrite cell connections to be $mem compatible for port mapping
1047
+ cell.connections.RD_ADDR = cell.connections.A;
1048
+ cell.connections.RD_DATA = cell.connections.Y;
1049
+ delete cell.connections.A;
1050
+ delete cell.connections.Y;
1051
+ break;
1033
1052
  default:
1034
1053
  }
1035
1054
  if (dev.type == 'Dff') {
@@ -1048,6 +1067,7 @@ function yosys_to_digitaljs_mod(name: string, mod: Yosys.Module, portmaps: Portm
1048
1067
  else if (cell.type == '$pmux') connect_pmux(dname, cell);
1049
1068
  else if (cell.type == '$mem') connect_mem(dname, cell, dev);
1050
1069
  else if (cell.type == '$mem_v2') connect_mem(dname, cell, dev);
1070
+ else if (cell.type == '$lut') connect_mem(dname, cell, dev);
1051
1071
  else throw Error('Invalid cell type: ' + cell.type);
1052
1072
  }
1053
1073
  // Group bits into nets for complex sources
@@ -1248,8 +1268,14 @@ export function io_ui(output: Digitaljs.Module) {
1248
1268
  }
1249
1269
  if (dev.type == 'Input')
1250
1270
  dev.type = dev.bits == 1 ? 'Button' : 'NumEntry';
1251
- if (dev.type == 'Output')
1252
- dev.type = dev.bits == 1 ? 'Lamp' : 'NumDisplay';
1271
+ if (dev.type == 'Output') {
1272
+ if (dev.bits == 1)
1273
+ dev.type = 'Lamp';
1274
+ else if (dev.bits == 8 && (dev.label == 'display7' || dev.label.startsWith('display7_')))
1275
+ dev.type = 'Display7';
1276
+ else
1277
+ dev.type = 'NumDisplay';
1278
+ }
1253
1279
  }
1254
1280
  }
1255
1281
 
package/tests/ram.sv CHANGED
@@ -1,5 +1,5 @@
1
1
  // Simple RAM
2
- module rom
2
+ module ram
3
3
  #(parameter AWIDTH = 4, DWIDTH = 4)(
4
4
  input clk,
5
5
  input [AWIDTH-1:0] addr,