yosys2digitaljs 0.7.0 → 0.9.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.
package/dist/index.js CHANGED
@@ -1,1030 +1,48 @@
1
1
  #!/usr/bin/env node
2
2
  "use strict";
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
- exports.process_sv = exports.process_files = exports.io_ui = exports.process = exports.yosys2digitaljs = exports.verilator_lint = void 0;
4
+ exports.verilator_lint = verilator_lint;
5
+ exports.process = process;
6
+ exports.process_files = process_files;
7
+ exports.process_sv = process_sv;
5
8
  const tmp = require("tmp-promise");
6
9
  const child_process = require("child_process");
7
- const assert = require("assert");
8
10
  const fs = require("fs");
9
11
  const path = require("path");
10
- const HashMap = require("hashmap");
11
- const bigInt = require("big-integer");
12
12
  const util_1 = require("util");
13
- const _3vl_1 = require("3vl");
14
- const topsort = require('topsort');
15
- const sanitize = require("sanitize-filename");
16
- const unary_gates = new Set([
17
- '$not', '$neg', '$pos', '$reduce_and', '$reduce_or', '$reduce_xor',
18
- '$reduce_xnor', '$reduce_bool', '$logic_not'
19
- ]);
20
- const binary_gates = new Set([
21
- '$and', '$or', '$xor', '$xnor',
22
- '$add', '$sub', '$mul', '$div', '$mod', '$pow',
23
- '$lt', '$le', '$eq', '$ne', '$ge', '$gt', '$eqx', '$nex',
24
- '$shl', '$shr', '$sshl', '$sshr', '$shift', '$shiftx',
25
- '$logic_and', '$logic_or'
26
- ]);
27
- const gate_subst = new Map([
28
- ['$not', 'Not'],
29
- ['$and', 'And'],
30
- ['$nand', 'Nand'],
31
- ['$or', 'Or'],
32
- ['$nor', 'Nor'],
33
- ['$xor', 'Xor'],
34
- ['$xnor', 'Xnor'],
35
- ['$reduce_and', 'AndReduce'],
36
- ['$reduce_nand', 'NandReduce'],
37
- ['$reduce_or', 'OrReduce'],
38
- ['$reduce_nor', 'NorReduce'],
39
- ['$reduce_xor', 'XorReduce'],
40
- ['$reduce_xnor', 'XnorReduce'],
41
- ['$reduce_bool', 'OrReduce'],
42
- ['$logic_not', 'NorReduce'],
43
- ['$repeater', 'Repeater'],
44
- ['$shl', 'ShiftLeft'],
45
- ['$shr', 'ShiftRight'],
46
- ['$lt', 'Lt'],
47
- ['$le', 'Le'],
48
- ['$eq', 'Eq'],
49
- ['$ne', 'Ne'],
50
- ['$gt', 'Gt'],
51
- ['$ge', 'Ge'],
52
- ['$constant', 'Constant'],
53
- ['$neg', 'Negation'],
54
- ['$pos', 'UnaryPlus'],
55
- ['$add', 'Addition'],
56
- ['$sub', 'Subtraction'],
57
- ['$mul', 'Multiplication'],
58
- ['$div', 'Division'],
59
- ['$mod', 'Modulo'],
60
- ['$pow', 'Power'],
61
- ['$mux', 'Mux'],
62
- ['$pmux', 'Mux1Hot'],
63
- ['$mem', 'Memory'],
64
- ['$mem_v2', 'Memory'],
65
- ['$lut', 'Memory'],
66
- ['$fsm', 'FSM'],
67
- ['$clock', 'Clock'],
68
- ['$button', 'Button'],
69
- ['$lamp', 'Lamp'],
70
- ['$numdisplay', 'NumDisplay'],
71
- ['$numentry', 'NumEntry'],
72
- ['$input', 'Input'],
73
- ['$output', 'Output'],
74
- ['$busgroup', 'BusGroup'],
75
- ['$busungroup', 'BusUngroup'],
76
- ['$busslice', 'BusSlice'],
77
- ['$zeroextend', 'ZeroExtend'],
78
- ['$signextend', 'SignExtend'],
79
- ['$reduce_bool', 'OrReduce'],
80
- ['$eqx', 'Eq'],
81
- ['$nex', 'Ne'],
82
- ['$sshl', 'ShiftLeft'],
83
- ['$sshr', 'ShiftRight'],
84
- ['$shift', 'ShiftRight'],
85
- ['$shiftx', 'ShiftRight'],
86
- ['$logic_and', 'And'],
87
- ['$logic_or', 'Or'],
88
- ['$dff', 'Dff'],
89
- ['$dffe', 'Dff'],
90
- ['$adff', 'Dff'],
91
- ['$adffe', 'Dff'],
92
- ['$sdff', 'Dff'],
93
- ['$sdffe', 'Dff'],
94
- ['$sdffce', 'Dff'],
95
- ['$dlatch', 'Dff'],
96
- ['$adlatch', 'Dff'],
97
- ['$sr', 'Dff'],
98
- ['$dffsr', 'Dff'],
99
- ['$dffsre', 'Dff'],
100
- ['$aldff', 'Dff'],
101
- ['$aldffe', 'Dff']
102
- ]);
103
- const gate_negations = new Map([
104
- ['And', 'Nand'],
105
- ['Nand', 'And'],
106
- ['Nor', 'Or'],
107
- ['Or', 'Nor'],
108
- ['Xor', 'Xnor'],
109
- ['Xnor', 'Xor'],
110
- ['AndReduce', 'NandReduce'],
111
- ['NandReduce', 'AndReduce'],
112
- ['NorReduce', 'OrReduce'],
113
- ['OrReduce', 'NorReduce'],
114
- ['XorReduce', 'XnorReduce'],
115
- ['XnorReduce', 'XorReduce']
116
- ]);
117
- ;
118
- ;
119
- function chunkArray(a, chunk_size) {
120
- let results = [];
121
- let ca = a.splice();
122
- while (ca.length) {
123
- results.push(ca.splice(0, chunk_size));
124
- }
125
- return results;
126
- }
127
- function module_deps(data) {
128
- const out = [];
129
- for (const [name, mod] of Object.entries(data.modules)) {
130
- out.push([name, 1 / 0]);
131
- for (const cname in mod.cells) {
132
- const cell = mod.cells[cname];
133
- if (cell.type in data.modules)
134
- out.push([cell.type, name]);
135
- }
136
- }
137
- return out;
138
- }
139
- function order_ports(data) {
140
- const unmap = { A: 'in', Y: 'out' };
141
- const binmap = { A: 'in1', B: 'in2', Y: 'out' };
142
- const out = {
143
- '$mux': { A: 'in0', B: 'in1', S: 'sel', Y: 'out' },
144
- '$dff': { CLK: 'clk', D: 'in', Q: 'out' },
145
- '$dffe': { CLK: 'clk', EN: 'en', D: 'in', Q: 'out' },
146
- '$adff': { CLK: 'clk', ARST: 'arst', D: 'in', Q: 'out' },
147
- '$adffe': { CLK: 'clk', EN: 'en', ARST: 'arst', D: 'in', Q: 'out' },
148
- '$sdff': { CLK: 'clk', SRST: 'srst', D: 'in', Q: 'out' },
149
- '$sdffe': { CLK: 'clk', EN: 'en', SRST: 'srst', D: 'in', Q: 'out' },
150
- '$sdffce': { CLK: 'clk', EN: 'en', SRST: 'srst', D: 'in', Q: 'out' },
151
- '$dlatch': { EN: 'en', D: 'in', Q: 'out' },
152
- '$adlatch': { EN: 'en', ARST: 'arst', D: 'in', Q: 'out' },
153
- '$dffsr': { CLK: 'clk', SET: 'set', CLR: 'clr', D: 'in', Q: 'out' },
154
- '$dffsre': { CLK: 'clk', EN: 'en', SET: 'set', CLR: 'clr', D: 'in', Q: 'out' },
155
- '$aldff': { CLK: 'clk', ALOAD: 'aload', AD: 'ain', D: 'in', Q: 'out' },
156
- '$aldffe': { CLK: 'clk', EN: 'en', ALOAD: 'aload', AD: 'ain', D: 'in', Q: 'out' },
157
- '$sr': { SET: 'set', CLR: 'clr', Q: 'out' },
158
- '$fsm': { ARST: 'arst', CLK: 'clk', CTRL_IN: 'in', CTRL_OUT: 'out' }
159
- };
160
- binary_gates.forEach((nm) => out[nm] = binmap);
161
- unary_gates.forEach((nm) => out[nm] = unmap);
162
- for (const [name, mod] of Object.entries(data.modules)) {
163
- const portmap = {};
164
- const ins = [], outs = [];
165
- for (const pname in mod.ports) {
166
- portmap[pname] = pname;
167
- }
168
- out[name] = portmap;
169
- }
170
- return out;
171
- }
172
- function decode_json_bigint(param) {
173
- if (typeof param == 'string')
174
- return bigInt(param, 2);
175
- else if (typeof param == 'number')
176
- return bigInt(param);
177
- else
178
- assert(false);
179
- }
180
- function decode_json_number(param) {
181
- if (typeof param == 'string')
182
- return Number.parseInt(param, 2);
183
- else if (typeof param == 'number')
184
- return param;
185
- else
186
- assert(false);
187
- }
188
- function decode_json_bigint_as_array(param) {
189
- return decode_json_bigint(param).toArray(2).value;
190
- }
191
- function decode_json_constant(param, bits, fill = '0') {
192
- if (typeof param == 'number')
193
- return bigInt(param).toArray(2).value.map(String).reverse()
194
- .concat(Array(bits).fill(fill)).slice(0, bits).reverse().join('');
195
- else
196
- return param;
197
- }
198
- function parse_source_positions(str) {
199
- const ret = [];
200
- for (const entry of str.split('|')) {
201
- const colonIdx = entry.lastIndexOf(':');
202
- const name = entry.slice(0, colonIdx);
203
- const pos = entry.slice(colonIdx + 1);
204
- const [from, to] = pos.split('-').map(s => s.split('.').map(v => Number(v))).map(([line, column]) => ({ line, column }));
205
- ret.push({ name, from, to });
206
- }
207
- return ret;
208
- }
209
- function yosys_to_digitaljs(data, portmaps, options = {}) {
210
- const out = {};
211
- for (const [name, mod] of Object.entries(data.modules)) {
212
- out[name] = yosys_to_digitaljs_mod(name, mod, portmaps, options);
213
- }
214
- return out;
215
- }
216
- function yosys_to_digitaljs_mod(name, mod, portmaps, options = {}) {
217
- function constbit(bit) {
218
- return bit == '0' || bit == '1' || bit == 'x';
219
- }
220
- const nets = new HashMap();
221
- const netnames = new HashMap();
222
- const netsrc = new HashMap();
223
- const bits = new Map();
224
- const devnets = new Map();
225
- let n = 0, pn = 0;
226
- function gen_name() {
227
- const nm = `dev${n++}`;
228
- devnets.set(nm, new Map());
229
- return nm;
230
- }
231
- function gen_bitname() {
232
- return `bit${pn++}`;
233
- }
234
- function get_net(k) {
235
- // create net if does not exist yet
236
- if (!nets.has(k)) {
237
- const nms = netnames.get(k);
238
- const src = netsrc.get(k);
239
- nets.set(k, { source: undefined, targets: [], name: nms ? nms[0] : undefined, source_positions: src || [] });
240
- }
241
- return nets.get(k);
242
- }
243
- function add_net_source(k, d, p, primary = false) {
244
- if (k.length == 0)
245
- return; // for unconnected ports
246
- const net = get_net(k);
247
- if (net.source !== undefined) {
248
- // multiple sources driving one net, disallowed in digitaljs
249
- console.log(k);
250
- console.log(net);
251
- throw Error('Multiple sources driving net: ' + net.name);
252
- }
253
- net.source = { id: d, port: p };
254
- if (primary)
255
- for (const [nbit, bit] of k.entries()) {
256
- bits.set(bit, { id: d, port: p, num: nbit });
257
- }
258
- devnets.get(d).set(p, k);
259
- }
260
- function add_net_target(k, d, p) {
261
- if (k.length == 0)
262
- return; // for unconnected ports
263
- const net = get_net(k);
264
- net.targets.push({ id: d, port: p });
265
- devnets.get(d).set(p, k);
266
- }
267
- const mout = {
268
- devices: {},
269
- connectors: []
270
- };
271
- function add_device(dev) {
272
- const dname = gen_name();
273
- if (options.propagation !== undefined)
274
- dev.propagation = options.propagation;
275
- mout.devices[dname] = dev;
276
- return dname;
277
- }
278
- function add_busgroup(nbits, groups) {
279
- if (get_net(nbits).source !== undefined)
280
- return; // the bits were already grouped
281
- const dname = add_device({
282
- type: 'BusGroup',
283
- groups: groups.map(g => g.length)
284
- });
285
- add_net_source(nbits, dname, 'out');
286
- for (const [gn, group] of groups.entries()) {
287
- add_net_target(group, dname, 'in' + gn);
288
- }
289
- }
290
- function connect_device(dname, cell, portmap) {
291
- for (const [pname, pdir] of Object.entries(cell.port_directions)) {
292
- const pconn = cell.connections[pname];
293
- switch (pdir) {
294
- case 'input':
295
- add_net_target(pconn, dname, portmap[pname]);
296
- break;
297
- case 'output':
298
- add_net_source(pconn, dname, portmap[pname], true);
299
- break;
300
- default:
301
- throw Error('Invalid port direction: ' + pdir);
302
- }
303
- }
304
- }
305
- function connect_pmux(dname, cell) {
306
- add_net_target(cell.connections.A, dname, 'in0');
307
- add_net_target(cell.connections.S.slice().reverse(), dname, 'sel');
308
- add_net_source(cell.connections.Y, dname, 'out', true);
309
- for (const i of Array(decode_json_number(cell.parameters.S_WIDTH)).keys()) {
310
- const p = (decode_json_number(cell.parameters.S_WIDTH) - i - 1) * decode_json_number(cell.parameters.WIDTH);
311
- add_net_target(cell.connections.B.slice(p, p + decode_json_number(cell.parameters.WIDTH)), dname, 'in' + (i + 1));
312
- }
313
- }
314
- function connect_mem(dname, cell, dev) {
315
- for (const [k, port] of dev.rdports.entries()) {
316
- const portname = "rd" + k;
317
- add_net_target(cell.connections.RD_ADDR.slice(dev.abits * k, dev.abits * (k + 1)), dname, portname + "addr");
318
- add_net_source(cell.connections.RD_DATA.slice(dev.bits * k, dev.bits * (k + 1)), dname, portname + "data", true);
319
- if ('clock_polarity' in port)
320
- add_net_target([cell.connections.RD_CLK[k]], dname, portname + "clk");
321
- if ('enable_polarity' in port)
322
- add_net_target([cell.connections.RD_EN[k]], dname, portname + "en");
323
- if ('arst_polarity' in port)
324
- add_net_target([cell.connections.RD_ARST[k]], dname, portname + "arst");
325
- if ('srst_polarity' in port)
326
- add_net_target([cell.connections.RD_SRST[k]], dname, portname + "srst");
327
- }
328
- for (const [k, port] of dev.wrports.entries()) {
329
- const portname = "wr" + k;
330
- add_net_target(cell.connections.WR_ADDR.slice(dev.abits * k, dev.abits * (k + 1)), dname, portname + "addr");
331
- add_net_target(cell.connections.WR_DATA.slice(dev.bits * k, dev.bits * (k + 1)), dname, portname + "data");
332
- if ('clock_polarity' in port)
333
- add_net_target([cell.connections.WR_CLK[k]], dname, portname + "clk");
334
- if ('enable_polarity' in port) {
335
- if (port.no_bit_enable)
336
- add_net_target([cell.connections.WR_EN[dev.bits * k]], dname, portname + "en");
337
- else
338
- add_net_target(cell.connections.WR_EN.slice(dev.bits * k, dev.bits * (k + 1)), dname, portname + "en");
339
- }
340
- }
341
- }
342
- // Find net names
343
- for (const [nname, data] of Object.entries(mod.netnames)) {
344
- if (data.hide_name)
345
- continue;
346
- let l = netnames.get(data.bits);
347
- if (l === undefined) {
348
- l = [];
349
- netnames.set(data.bits, l);
350
- }
351
- l.push(nname);
352
- if (typeof data.attributes == 'object' && data.attributes.src) {
353
- let l = netsrc.get(data.bits);
354
- if (l === undefined) {
355
- l = [];
356
- netsrc.set(data.bits, l);
357
- }
358
- const positions = parse_source_positions(data.attributes.src);
359
- l.push(...positions);
360
- }
361
- }
362
- // Add inputs/outputs
363
- for (const [pname, port] of Object.entries(mod.ports)) {
364
- const dir = port.direction == "input" ? "Input" :
365
- port.direction == "output" ? "Output" :
366
- undefined;
367
- const dname = add_device({
368
- type: dir,
369
- net: pname,
370
- order: n,
371
- bits: port.bits.length
372
- });
373
- switch (port.direction) {
374
- case 'input':
375
- add_net_source(port.bits, dname, 'out', true);
376
- break;
377
- case 'output':
378
- add_net_target(port.bits, dname, 'in');
379
- break;
380
- default: throw Error('Invalid port direction: ' + port.direction);
381
- }
382
- }
383
- // Add gates
384
- for (const [cname, cell] of Object.entries(mod.cells)) {
385
- const dev = {
386
- label: cname,
387
- type: gate_subst.get(cell.type)
388
- };
389
- if (dev.type == undefined) {
390
- dev.type = 'Subcircuit';
391
- dev.celltype = cell.type;
392
- }
393
- if (typeof cell.attributes == 'object' && cell.attributes.src) {
394
- dev.source_positions = parse_source_positions(cell.attributes.src);
395
- }
396
- const dname = add_device(dev);
397
- function match_port(con, nsig, sz) {
398
- const sig = decode_json_number(nsig);
399
- if (con.length > sz)
400
- con.splice(sz);
401
- else if (con.length < sz) {
402
- const ccon = con.slice();
403
- const pad = sig ? con.slice(-1)[0] : '0';
404
- con.splice(con.length, 0, ...Array(sz - con.length).fill(pad));
405
- if (!con.every(constbit) && get_net(con).source === undefined) {
406
- // WARNING: potentially troublesome hack for readability
407
- // handled generally in the grouping phase,
408
- // but it's hard to add sign extensions there
409
- const extname = add_device({
410
- type: sig ? 'SignExtend' : 'ZeroExtend',
411
- extend: { input: ccon.length, output: con.length }
412
- });
413
- add_net_target(ccon, extname, 'in');
414
- add_net_source(con, extname, 'out');
415
- }
416
- }
417
- }
418
- function zero_extend_output(con) {
419
- if (con.length > 1) {
420
- const ccon = con.slice();
421
- con.splice(1);
422
- const extname = add_device({
423
- type: 'ZeroExtend',
424
- extend: { input: con.length, output: ccon.length }
425
- });
426
- add_net_source(ccon, extname, 'out');
427
- add_net_target(con, extname, 'in');
428
- }
429
- }
430
- if (unary_gates.has(cell.type)) {
431
- assert(cell.connections.A.length == decode_json_number(cell.parameters.A_WIDTH));
432
- assert(cell.connections.Y.length == decode_json_number(cell.parameters.Y_WIDTH));
433
- assert(cell.port_directions.A == 'input');
434
- assert(cell.port_directions.Y == 'output');
435
- }
436
- if (binary_gates.has(cell.type)) {
437
- assert(cell.connections.A.length == decode_json_number(cell.parameters.A_WIDTH));
438
- assert(cell.connections.B.length == decode_json_number(cell.parameters.B_WIDTH));
439
- assert(cell.connections.Y.length == decode_json_number(cell.parameters.Y_WIDTH));
440
- assert(cell.port_directions.A == 'input');
441
- assert(cell.port_directions.B == 'input');
442
- assert(cell.port_directions.Y == 'output');
443
- }
444
- if (['$dff', '$dffe', '$adff', '$adffe', '$sdff', '$sdffe', '$sdffce', '$dlatch', '$adlatch', '$dffsr', '$dffsre', '$aldff', '$aldffe'].includes(cell.type)) {
445
- assert(cell.connections.D.length == decode_json_number(cell.parameters.WIDTH));
446
- assert(cell.connections.Q.length == decode_json_number(cell.parameters.WIDTH));
447
- assert(cell.port_directions.D == 'input');
448
- assert(cell.port_directions.Q == 'output');
449
- if (cell.type != '$dlatch' && cell.type != '$adlatch') {
450
- assert(cell.connections.CLK.length == 1);
451
- assert(cell.port_directions.CLK == 'input');
452
- }
453
- }
454
- if (['$dffe', '$adffe', '$sdffe', '$sdffce', '$dffsre', '$aldffe', '$dlatch', '$adlatch'].includes(cell.type)) {
455
- assert(cell.connections.EN.length == 1);
456
- assert(cell.port_directions.EN == 'input');
457
- }
458
- if (['$adff', '$adffe', '$adlatch'].includes(cell.type)) {
459
- assert(cell.connections.ARST.length == 1);
460
- assert(cell.port_directions.ARST == 'input');
461
- }
462
- if (['$sdff', '$sdffe', '$sdffce'].includes(cell.type)) {
463
- assert(cell.connections.SRST.length == 1);
464
- assert(cell.port_directions.SRST == 'input');
465
- }
466
- if (['$dffsr', '$dffsre'].includes(cell.type)) {
467
- assert(cell.connections.SET.length == decode_json_number(cell.parameters.WIDTH));
468
- assert(cell.connections.CLR.length == decode_json_number(cell.parameters.WIDTH));
469
- assert(cell.port_directions.SET == 'input');
470
- assert(cell.port_directions.CLR == 'input');
471
- }
472
- switch (cell.type) {
473
- case '$neg':
474
- case '$pos':
475
- dev.bits = {
476
- in: cell.connections.A.length,
477
- out: cell.connections.Y.length
478
- };
479
- dev.signed = Boolean(decode_json_number(cell.parameters.A_SIGNED));
480
- break;
481
- case '$not':
482
- match_port(cell.connections.A, cell.parameters.A_SIGNED, cell.connections.Y.length);
483
- dev.bits = cell.connections.Y.length;
484
- break;
485
- case '$add':
486
- case '$sub':
487
- case '$mul':
488
- case '$div':
489
- case '$mod':
490
- case '$pow':
491
- dev.bits = {
492
- in1: cell.connections.A.length,
493
- in2: cell.connections.B.length,
494
- out: cell.connections.Y.length
495
- };
496
- dev.signed = {
497
- in1: Boolean(decode_json_number(cell.parameters.A_SIGNED)),
498
- in2: Boolean(decode_json_number(cell.parameters.B_SIGNED))
499
- };
500
- break;
501
- case '$and':
502
- case '$or':
503
- case '$xor':
504
- case '$xnor':
505
- match_port(cell.connections.A, cell.parameters.A_SIGNED, cell.connections.Y.length);
506
- match_port(cell.connections.B, cell.parameters.B_SIGNED, cell.connections.Y.length);
507
- dev.bits = cell.connections.Y.length;
508
- break;
509
- case '$reduce_and':
510
- case '$reduce_or':
511
- case '$reduce_xor':
512
- case '$reduce_xnor':
513
- case '$reduce_bool':
514
- case '$logic_not':
515
- dev.bits = cell.connections.A.length;
516
- zero_extend_output(cell.connections.Y);
517
- if (dev.bits == 1) {
518
- if (['$reduce_xnor', '$logic_not'].includes(cell.type))
519
- dev.type = 'Not';
520
- else
521
- dev.type = 'Repeater';
522
- }
523
- break;
524
- case '$eq':
525
- case '$ne':
526
- case '$lt':
527
- case '$le':
528
- case '$gt':
529
- case '$ge':
530
- case '$eqx':
531
- case '$nex':
532
- dev.bits = {
533
- in1: cell.connections.A.length,
534
- in2: cell.connections.B.length
535
- };
536
- dev.signed = {
537
- in1: Boolean(decode_json_number(cell.parameters.A_SIGNED)),
538
- in2: Boolean(decode_json_number(cell.parameters.B_SIGNED))
539
- };
540
- zero_extend_output(cell.connections.Y);
541
- break;
542
- case '$shl':
543
- case '$shr':
544
- case '$sshl':
545
- case '$sshr':
546
- case '$shift':
547
- case '$shiftx':
548
- dev.bits = {
549
- in1: cell.connections.A.length,
550
- in2: cell.connections.B.length,
551
- out: cell.connections.Y.length
552
- };
553
- dev.signed = {
554
- in1: Boolean(decode_json_number(cell.parameters.A_SIGNED)),
555
- in2: Boolean(decode_json_number(cell.parameters.B_SIGNED) && ['$shift', '$shiftx'].includes(cell.type)),
556
- out: Boolean(decode_json_number(cell.parameters.A_SIGNED) && ['$sshl', '$sshr'].includes(cell.type))
557
- };
558
- dev.fillx = cell.type == '$shiftx';
559
- break;
560
- case '$logic_and':
561
- case '$logic_or': {
562
- function reduce_input(con) {
563
- const ccon = con.slice();
564
- con.splice(0, con.length, gen_bitname());
565
- const extname = add_device({
566
- type: 'OrReduce',
567
- bits: ccon.length
568
- });
569
- add_net_source(con, extname, 'out');
570
- add_net_target(ccon, extname, 'in');
571
- }
572
- if (cell.connections.A.length > 1)
573
- reduce_input(cell.connections.A);
574
- if (cell.connections.B.length > 1)
575
- reduce_input(cell.connections.B);
576
- zero_extend_output(cell.connections.Y);
577
- break;
578
- }
579
- case '$mux':
580
- assert(cell.connections.A.length == decode_json_number(cell.parameters.WIDTH));
581
- assert(cell.connections.B.length == decode_json_number(cell.parameters.WIDTH));
582
- assert(cell.connections.Y.length == decode_json_number(cell.parameters.WIDTH));
583
- assert(cell.port_directions.A == 'input');
584
- assert(cell.port_directions.B == 'input');
585
- assert(cell.port_directions.Y == 'output');
586
- dev.bits = {
587
- in: decode_json_number(cell.parameters.WIDTH),
588
- sel: 1
589
- };
590
- break;
591
- case '$pmux':
592
- assert(cell.connections.B.length == decode_json_number(cell.parameters.WIDTH) * decode_json_number(cell.parameters.S_WIDTH));
593
- assert(cell.connections.A.length == decode_json_number(cell.parameters.WIDTH));
594
- assert(cell.connections.S.length == decode_json_number(cell.parameters.S_WIDTH));
595
- assert(cell.connections.Y.length == decode_json_number(cell.parameters.WIDTH));
596
- assert(cell.port_directions.A == 'input');
597
- assert(cell.port_directions.B == 'input');
598
- assert(cell.port_directions.S == 'input');
599
- assert(cell.port_directions.Y == 'output');
600
- dev.bits = {
601
- in: decode_json_number(cell.parameters.WIDTH),
602
- sel: decode_json_number(cell.parameters.S_WIDTH)
603
- };
604
- break;
605
- case '$dff':
606
- dev.bits = decode_json_number(cell.parameters.WIDTH);
607
- dev.polarity = {
608
- clock: Boolean(decode_json_number(cell.parameters.CLK_POLARITY))
609
- };
610
- break;
611
- case '$dffe':
612
- dev.bits = decode_json_number(cell.parameters.WIDTH);
613
- dev.polarity = {
614
- clock: Boolean(decode_json_number(cell.parameters.CLK_POLARITY)),
615
- enable: Boolean(decode_json_number(cell.parameters.EN_POLARITY))
616
- };
617
- break;
618
- case '$aldff':
619
- dev.bits = decode_json_number(cell.parameters.WIDTH);
620
- dev.polarity = {
621
- clock: Boolean(decode_json_number(cell.parameters.CLK_POLARITY)),
622
- aload: Boolean(decode_json_number(cell.parameters.ALOAD_POLARITY))
623
- };
624
- break;
625
- case '$aldffe':
626
- dev.bits = decode_json_number(cell.parameters.WIDTH);
627
- dev.polarity = {
628
- clock: Boolean(decode_json_number(cell.parameters.CLK_POLARITY)),
629
- enable: Boolean(decode_json_number(cell.parameters.EN_POLARITY)),
630
- aload: Boolean(decode_json_number(cell.parameters.ALOAD_POLARITY))
631
- };
632
- break;
633
- case '$adff':
634
- dev.bits = decode_json_number(cell.parameters.WIDTH);
635
- dev.polarity = {
636
- clock: Boolean(decode_json_number(cell.parameters.CLK_POLARITY)),
637
- arst: Boolean(decode_json_number(cell.parameters.ARST_POLARITY))
638
- };
639
- dev.arst_value = decode_json_constant(cell.parameters.ARST_VALUE, dev.bits);
640
- break;
641
- case '$sdff':
642
- dev.bits = decode_json_number(cell.parameters.WIDTH);
643
- dev.polarity = {
644
- clock: Boolean(decode_json_number(cell.parameters.CLK_POLARITY)),
645
- srst: Boolean(decode_json_number(cell.parameters.SRST_POLARITY))
646
- };
647
- dev.srst_value = decode_json_constant(cell.parameters.SRST_VALUE, dev.bits);
648
- break;
649
- case '$adffe':
650
- dev.bits = decode_json_number(cell.parameters.WIDTH);
651
- dev.polarity = {
652
- clock: Boolean(decode_json_number(cell.parameters.CLK_POLARITY)),
653
- arst: Boolean(decode_json_number(cell.parameters.ARST_POLARITY)),
654
- enable: Boolean(decode_json_number(cell.parameters.EN_POLARITY))
655
- };
656
- dev.arst_value = decode_json_constant(cell.parameters.ARST_VALUE, dev.bits);
657
- break;
658
- case '$sdffe':
659
- dev.bits = decode_json_number(cell.parameters.WIDTH);
660
- dev.polarity = {
661
- clock: Boolean(decode_json_number(cell.parameters.CLK_POLARITY)),
662
- srst: Boolean(decode_json_number(cell.parameters.SRST_POLARITY)),
663
- enable: Boolean(decode_json_number(cell.parameters.EN_POLARITY))
664
- };
665
- dev.srst_value = decode_json_constant(cell.parameters.SRST_VALUE, dev.bits);
666
- break;
667
- case '$sdffce':
668
- dev.bits = decode_json_number(cell.parameters.WIDTH);
669
- dev.polarity = {
670
- clock: Boolean(decode_json_number(cell.parameters.CLK_POLARITY)),
671
- srst: Boolean(decode_json_number(cell.parameters.SRST_POLARITY)),
672
- enable: Boolean(decode_json_number(cell.parameters.EN_POLARITY))
673
- };
674
- dev.enable_srst = true;
675
- dev.srst_value = decode_json_constant(cell.parameters.SRST_VALUE, dev.bits);
676
- break;
677
- case '$dlatch':
678
- dev.bits = decode_json_number(cell.parameters.WIDTH);
679
- dev.polarity = {
680
- enable: Boolean(decode_json_number(cell.parameters.EN_POLARITY))
681
- };
682
- break;
683
- case '$adlatch':
684
- dev.bits = decode_json_number(cell.parameters.WIDTH);
685
- dev.polarity = {
686
- enable: Boolean(decode_json_number(cell.parameters.EN_POLARITY)),
687
- arst: Boolean(decode_json_number(cell.parameters.ARST_POLARITY))
688
- };
689
- dev.arst_value = decode_json_constant(cell.parameters.ARST_VALUE, dev.bits);
690
- break;
691
- case '$dffsr':
692
- dev.bits = decode_json_number(cell.parameters.WIDTH);
693
- dev.polarity = {
694
- clock: Boolean(decode_json_number(cell.parameters.CLK_POLARITY)),
695
- set: Boolean(decode_json_number(cell.parameters.SET_POLARITY)),
696
- clr: Boolean(decode_json_number(cell.parameters.CLR_POLARITY))
697
- };
698
- break;
699
- case '$dffsre':
700
- dev.bits = decode_json_number(cell.parameters.WIDTH);
701
- dev.polarity = {
702
- clock: Boolean(decode_json_number(cell.parameters.CLK_POLARITY)),
703
- enable: Boolean(decode_json_number(cell.parameters.EN_POLARITY)),
704
- set: Boolean(decode_json_number(cell.parameters.SET_POLARITY)),
705
- clr: Boolean(decode_json_number(cell.parameters.CLR_POLARITY))
706
- };
707
- break;
708
- case '$sr':
709
- assert(cell.connections.Q.length == decode_json_number(cell.parameters.WIDTH));
710
- assert(cell.port_directions.Q == 'output');
711
- dev.no_data = true;
712
- dev.bits = decode_json_number(cell.parameters.WIDTH);
713
- dev.polarity = {
714
- set: Boolean(decode_json_number(cell.parameters.SET_POLARITY)),
715
- clr: Boolean(decode_json_number(cell.parameters.CLR_POLARITY))
716
- };
717
- break;
718
- case '$fsm': {
719
- assert(cell.connections.ARST.length == 1);
720
- assert(cell.connections.CLK.length == 1);
721
- assert(cell.connections.CTRL_IN.length == decode_json_number(cell.parameters.CTRL_IN_WIDTH));
722
- assert(cell.connections.CTRL_OUT.length == decode_json_number(cell.parameters.CTRL_OUT_WIDTH));
723
- const TRANS_NUM = decode_json_number(cell.parameters.TRANS_NUM);
724
- const STATE_NUM_LOG2 = decode_json_number(cell.parameters.STATE_NUM_LOG2);
725
- const step = 2 * STATE_NUM_LOG2
726
- + decode_json_number(cell.parameters.CTRL_IN_WIDTH)
727
- + decode_json_number(cell.parameters.CTRL_OUT_WIDTH);
728
- const tt = typeof (cell.parameters.TRANS_TABLE) == "number"
729
- ? _3vl_1.Vector3vl.fromBin(bigInt(cell.parameters.TRANS_TABLE).toString(2), TRANS_NUM * step).toBin() // workaround for yosys silliness
730
- : cell.parameters.TRANS_TABLE;
731
- assert(tt.length == TRANS_NUM * step);
732
- dev.polarity = {
733
- clock: Boolean(decode_json_number(cell.parameters.CLK_POLARITY)),
734
- arst: Boolean(decode_json_number(cell.parameters.ARST_POLARITY))
735
- };
736
- dev.wirename = cell.parameters.NAME;
737
- dev.bits = {
738
- in: decode_json_number(cell.parameters.CTRL_IN_WIDTH),
739
- out: decode_json_number(cell.parameters.CTRL_OUT_WIDTH)
740
- };
741
- dev.states = decode_json_number(cell.parameters.STATE_NUM);
742
- dev.init_state = decode_json_number(cell.parameters.STATE_RST);
743
- dev.trans_table = [];
744
- for (let i = 0; i < TRANS_NUM; i++) {
745
- let base = i * step;
746
- const f = (sz) => {
747
- const ret = tt.slice(base, base + sz);
748
- base += sz;
749
- return ret;
750
- };
751
- const o = {
752
- state_in: parseInt(f(STATE_NUM_LOG2), 2),
753
- ctrl_in: f(decode_json_number(cell.parameters.CTRL_IN_WIDTH)).replace(/-/g, 'x'),
754
- state_out: parseInt(f(STATE_NUM_LOG2), 2),
755
- ctrl_out: f(decode_json_number(cell.parameters.CTRL_OUT_WIDTH))
756
- };
757
- dev.trans_table.push(o);
758
- }
759
- break;
760
- }
761
- case '$mem':
762
- case '$mem_v2': {
763
- const RD_PORTS = decode_json_number(cell.parameters.RD_PORTS);
764
- const WR_PORTS = decode_json_number(cell.parameters.WR_PORTS);
765
- assert(cell.connections.RD_EN.length == RD_PORTS);
766
- assert(cell.connections.RD_CLK.length == RD_PORTS);
767
- assert(cell.connections.RD_DATA.length == RD_PORTS * decode_json_number(cell.parameters.WIDTH));
768
- assert(cell.connections.RD_ADDR.length == RD_PORTS * decode_json_number(cell.parameters.ABITS));
769
- assert(cell.connections.WR_EN.length == WR_PORTS * decode_json_number(cell.parameters.WIDTH));
770
- assert(cell.connections.WR_CLK.length == WR_PORTS);
771
- assert(cell.connections.WR_DATA.length == WR_PORTS * decode_json_number(cell.parameters.WIDTH));
772
- assert(cell.connections.WR_ADDR.length == WR_PORTS * decode_json_number(cell.parameters.ABITS));
773
- if (cell.type == "$mem_v2") {
774
- assert(cell.connections.RD_ARST.length == RD_PORTS);
775
- assert(cell.connections.RD_SRST.length == RD_PORTS);
776
- }
777
- dev.bits = decode_json_number(cell.parameters.WIDTH);
778
- dev.abits = decode_json_number(cell.parameters.ABITS);
779
- dev.words = decode_json_number(cell.parameters.SIZE);
780
- dev.offset = decode_json_number(cell.parameters.OFFSET);
781
- dev.rdports = [];
782
- dev.wrports = [];
783
- const rdpol = decode_json_bigint_as_array(cell.parameters.RD_CLK_POLARITY).reverse();
784
- const rden = decode_json_bigint_as_array(cell.parameters.RD_CLK_ENABLE).reverse();
785
- const rdtr = cell.type == "$mem_v2"
786
- ? []
787
- : decode_json_bigint_as_array(cell.parameters.RD_TRANSPARENT).reverse();
788
- const wrpol = decode_json_bigint_as_array(cell.parameters.WR_CLK_POLARITY).reverse();
789
- const wren = decode_json_bigint_as_array(cell.parameters.WR_CLK_ENABLE).reverse();
790
- const init = typeof (cell.parameters.INIT) == 'number'
791
- ? bigInt(cell.parameters.INIT).toArray(2).value.map(String).reverse()
792
- : cell.parameters.INIT.split('').reverse();
793
- const v2_feature = (param) => cell.type == "$mem_v2" ? decode_json_bigint_as_array(param).reverse() : [];
794
- const v2_feature_const = (param, size) => cell.type == "$mem_v2" ? decode_json_constant(param, size) : "";
795
- const rdtrmask = v2_feature(cell.parameters.RD_TRANSPARENCY_MASK);
796
- const rdcolmask = v2_feature(cell.parameters.RD_COLLISION_X_MASK);
797
- const rdensrst = v2_feature(cell.parameters.RD_CE_OVER_SRST);
798
- const rdinit = v2_feature_const(cell.parameters.RD_INIT_VALUE, dev.bits * RD_PORTS);
799
- const rdarst = v2_feature_const(cell.parameters.RD_ARST_VALUE, dev.bits * RD_PORTS);
800
- const rdsrst = v2_feature_const(cell.parameters.RD_SRST_VALUE, dev.bits * RD_PORTS);
801
- if (cell.parameters.INIT) {
802
- const l = init.slice(-1)[0] == 'x' ? 'x' : '0';
803
- const memdata = new _3vl_1.Mem3vl(dev.bits, dev.words);
804
- for (const k of Array(dev.words).keys()) {
805
- const wrd = init.slice(dev.bits * k, dev.bits * (k + 1));
806
- while (wrd.length < dev.bits)
807
- wrd.push(l);
808
- memdata.set(k, _3vl_1.Vector3vl.fromBin(wrd.reverse().join('')));
809
- }
810
- dev.memdata = memdata.toJSON();
811
- }
812
- for (const k of Array(RD_PORTS).keys()) {
813
- const port = {};
814
- if (rden[k]) {
815
- port.clock_polarity = Boolean(rdpol[k]);
816
- if (cell.connections.RD_EN[k] != '1')
817
- port.enable_polarity = true;
818
- }
819
- ;
820
- if (rdtr[k])
821
- port.transparent = true;
822
- if (cell.type == "$mem_v2") {
823
- if (rdensrst[k])
824
- port.enable_srst = true;
825
- function mk_init(s, f) {
826
- const v = s.slice(dev.bits * k, dev.bits * (k + 1));
827
- if (!v.split('').every(c => c == 'x'))
828
- f(v);
829
- }
830
- ;
831
- mk_init(rdinit, v => port.init_value = v);
832
- if (cell.connections.RD_ARST[k] != '0') {
833
- port.arst_polarity = true;
834
- mk_init(rdarst, v => port.arst_value = v);
835
- }
836
- if (cell.connections.RD_SRST[k] != '0') {
837
- port.srst_polarity = true;
838
- mk_init(rdsrst, v => port.srst_value = v);
839
- }
840
- function mk_mask(s, f) {
841
- const v = Array(WR_PORTS).fill(0);
842
- s.slice(WR_PORTS * k, WR_PORTS * (k + 1)).map((c, i) => { v[i] = c; });
843
- if (v.every(c => c))
844
- f(true);
845
- else if (v.some(c => c))
846
- f(v.map(c => Boolean(c)));
847
- }
848
- mk_mask(rdtrmask, v => port.transparent = v);
849
- mk_mask(rdcolmask, v => port.collision = v);
850
- }
851
- dev.rdports.push(port);
852
- }
853
- for (const k of Array(WR_PORTS).keys()) {
854
- const port = {};
855
- if (wren[k]) {
856
- port.clock_polarity = Boolean(wrpol[k]);
857
- const wr_en_connections = cell.connections.WR_EN.slice(dev.bits * k, dev.bits * (k + 1));
858
- if (wr_en_connections.some(z => z != '1')) {
859
- port.enable_polarity = true;
860
- if (wr_en_connections.every(z => z == wr_en_connections[0]))
861
- port.no_bit_enable = true;
862
- }
863
- }
864
- ;
865
- dev.wrports.push(port);
866
- }
867
- break;
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;
886
- default:
887
- }
888
- if (dev.type == 'Dff') {
889
- // find register initial value, if exists
890
- // Yosys puts initial values in net attributes; there can be many for single actual net!
891
- const nms = netnames.get(cell.connections.Q);
892
- if (nms !== undefined) {
893
- for (const nm of nms) {
894
- if (mod.netnames[nm].attributes.init !== undefined)
895
- dev.initial = decode_json_constant(mod.netnames[nm].attributes.init, dev.bits);
896
- }
897
- }
898
- }
899
- const portmap = portmaps[cell.type];
900
- if (portmap)
901
- connect_device(dname, cell, portmap);
902
- else if (cell.type == '$pmux')
903
- connect_pmux(dname, cell);
904
- else if (cell.type == '$mem')
905
- connect_mem(dname, cell, dev);
906
- else if (cell.type == '$mem_v2')
907
- connect_mem(dname, cell, dev);
908
- else if (cell.type == '$lut')
909
- connect_mem(dname, cell, dev);
910
- else
911
- throw Error('Invalid cell type: ' + cell.type);
912
- }
913
- // Group bits into nets for complex sources
914
- for (const [nbits, net] of nets.entries()) {
915
- if (net.source !== undefined)
916
- continue;
917
- const groups = [[]];
918
- let pbitinfo = undefined;
919
- for (const bit of nbits) {
920
- let bitinfo = bits.get(bit);
921
- if (bitinfo == undefined && constbit(bit))
922
- bitinfo = 'const';
923
- if (groups.slice(-1)[0].length > 0 &&
924
- (typeof bitinfo != typeof pbitinfo ||
925
- typeof bitinfo == 'object' &&
926
- typeof pbitinfo == 'object' &&
927
- (bitinfo.id != pbitinfo.id ||
928
- bitinfo.port != pbitinfo.port ||
929
- bitinfo.num != pbitinfo.num + 1))) {
930
- groups.push([]);
931
- }
932
- groups.slice(-1)[0].push(bit);
933
- pbitinfo = bitinfo;
934
- }
935
- if (groups.length == 1)
936
- continue;
937
- if (groups.slice(-1)[0].every(x => x == '0')) {
938
- // infer zero-extend
939
- const ilen = nbits.length - groups.slice(-1)[0].length;
940
- const dname = add_device({
941
- type: 'ZeroExtend',
942
- extend: { output: nbits.length, input: ilen }
943
- });
944
- const zbits = nbits.slice(0, ilen);
945
- add_net_source(nbits, dname, 'out');
946
- add_net_target(zbits, dname, 'in');
947
- if (groups.length > 2)
948
- add_busgroup(zbits, groups.slice(0, groups.length - 1));
949
- }
950
- else
951
- add_busgroup(nbits, groups);
952
- }
953
- // Add constants
954
- for (const [nbits, net] of nets.entries()) {
955
- if (net.source !== undefined)
956
- continue;
957
- if (!nbits.every(constbit))
958
- continue;
959
- const dname = add_device({
960
- // label: String(val), // TODO
961
- type: 'Constant',
962
- constant: nbits.slice().reverse().join('')
963
- });
964
- add_net_source(nbits, dname, 'out');
965
- }
966
- // Select bits from complex targets
967
- for (const [nbits, net] of nets.entries()) {
968
- if (net.source !== undefined)
969
- continue;
970
- // constants should be already handled!
971
- assert(nbits.every(x => x > 1));
972
- const bitinfos = nbits.map(x => bits.get(x));
973
- if (!bitinfos.every(x => typeof x == 'object'))
974
- continue; // ignore not fully driven ports
975
- // complex sources should be already handled!
976
- assert(bitinfos.every(info => info.id == bitinfos[0].id &&
977
- info.port == bitinfos[0].port));
978
- const cconn = devnets.get(bitinfos[0].id).get(bitinfos[0].port);
979
- const dname = add_device({
980
- type: 'BusSlice',
981
- slice: {
982
- first: bitinfos[0].num,
983
- count: bitinfos.length,
984
- total: cconn.length
985
- }
986
- });
987
- add_net_source(nbits, dname, 'out');
988
- add_net_target(cconn, dname, 'in');
989
- }
990
- // Generate connections between devices
991
- for (const [nbits, net] of nets.entries()) {
992
- if (net.source === undefined) {
993
- console.warn('Undriven net in ' + name + ': ' + nbits);
994
- continue;
995
- }
996
- let first = true;
997
- for (const target in net.targets) {
998
- const conn = {
999
- to: net.targets[target],
1000
- from: net.source
1001
- };
1002
- if (net.name)
1003
- conn.name = net.name;
1004
- if (net.source_positions)
1005
- conn.source_positions = net.source_positions;
1006
- if (!first && mout.devices[conn.from.id].type == "Constant") {
1007
- // replicate constants for better clarity
1008
- const dname = add_device({
1009
- type: 'Constant',
1010
- constant: mout.devices[conn.from.id].constant
1011
- });
1012
- conn.from = { id: dname, port: 'out' };
1013
- }
1014
- mout.connectors.push(conn);
1015
- first = false;
1016
- }
1017
- }
1018
- return mout;
1019
- }
1020
- function escape_filename(cmd) {
1021
- return '"' + cmd.replace(/(["\s'$`\\])/g, '\\$1') + '"';
13
+ const core_1 = require("./core");
14
+ const sanitize = require('sanitize-filename');
15
+ function ansi_c_escape_contents(cmd) {
16
+ function func(ch) {
17
+ if (ch == '\t')
18
+ return '\\t';
19
+ if (ch == '\r')
20
+ return '\\r';
21
+ if (ch == '\n')
22
+ return '\\n';
23
+ return '\\x' + ch.charCodeAt(0).toString(16).padStart(2, '0');
24
+ }
25
+ return cmd.replace(/(["'\\])/g, '\\$1')
26
+ .replace(/[\x00-\x1F\x7F-\x9F]/g, func);
27
+ }
28
+ function ansi_c_escape(cmd) {
29
+ return '"' + ansi_c_escape_contents(cmd) + '"';
30
+ }
31
+ function shell_escape_contents(cmd) {
32
+ return cmd.replace(/(["\r\n$`\\])/g, '\\$1');
33
+ }
34
+ function shell_escape(cmd) {
35
+ return '"' + shell_escape_contents(cmd) + '"';
36
+ }
37
+ function process_filename(filename) {
38
+ const flags = /\.sv$/.test(filename) ? " -sv" : "";
39
+ return "read_verilog" + flags + " " + ansi_c_escape(filename);
1022
40
  }
1023
41
  const verilator_re = /^%(Warning|Error)[^:]*: ([^:]*):([0-9]+):([0-9]+): (.*)$/;
1024
42
  async function verilator_lint(filenames, dirname, options = {}) {
1025
43
  try {
1026
44
  const output = [];
1027
- const verilator_result = await (0, util_1.promisify)(child_process.exec)('verilator -lint-only -Wall -Wno-DECLFILENAME -Wno-UNOPT -Wno-UNOPTFLAT ' + filenames.map(escape_filename).join(' '), { maxBuffer: 1000000, cwd: dirname || null, timeout: options.timeout || 60000 })
45
+ const verilator_result = await (0, util_1.promisify)(child_process.exec)('timeout -k10s 40s verilator -lint-only -Wall -Wno-DECLFILENAME -Wno-UNOPT -Wno-UNOPTFLAT ' + filenames.map(shell_escape).join(' '), { maxBuffer: 1000000, cwd: dirname || null, timeout: options.timeout || 60000 })
1028
46
  .catch(exc => exc);
1029
47
  for (const line of verilator_result.stderr.split('\n')) {
1030
48
  const result = line.match(verilator_re);
@@ -1044,19 +62,6 @@ async function verilator_lint(filenames, dirname, options = {}) {
1044
62
  return null;
1045
63
  }
1046
64
  }
1047
- exports.verilator_lint = verilator_lint;
1048
- function yosys2digitaljs(obj, options = {}) {
1049
- const portmaps = order_ports(obj);
1050
- const out = yosys_to_digitaljs(obj, portmaps, options);
1051
- const toporder = topsort(module_deps(obj));
1052
- toporder.pop();
1053
- const toplevel = toporder.pop();
1054
- const output = Object.assign({ subcircuits: {} }, out[toplevel]);
1055
- for (const x of toporder)
1056
- output.subcircuits[x] = out[x];
1057
- return output;
1058
- }
1059
- exports.yosys2digitaljs = yosys2digitaljs;
1060
65
  async function process(filenames, dirname, options = {}) {
1061
66
  const optimize_simp = options.optimize ? "; opt" : "; opt_clean";
1062
67
  const optimize = options.optimize ? "; opt -full" : "; opt_clean";
@@ -1066,8 +71,9 @@ async function process(filenames, dirname, options = {}) {
1066
71
  : "";
1067
72
  const tmpjson = await tmp.tmpName({ postfix: '.json' });
1068
73
  let obj = undefined;
1069
- const yosys_result = await (0, util_1.promisify)(child_process.exec)('yosys -p "hierarchy -auto-top; proc' + optimize_simp + fsmpass + '; memory -nomap; wreduce -memx' +
1070
- optimize + '" -o "' + tmpjson + '" ' + filenames.map(escape_filename).join(' '), { maxBuffer: 1000000, cwd: dirname || null, timeout: options.timeout || 60000 })
74
+ const yosys_result = await (0, util_1.promisify)(child_process.exec)('timeout -k10s 40s yosys -p "' + shell_escape_contents(filenames.map(process_filename).join('; ')) +
75
+ '; hierarchy -auto-top; proc' + optimize_simp + fsmpass + '; memory -nomap; wreduce -memx' +
76
+ optimize + '" -o "' + tmpjson + '"', { maxBuffer: 1000000, cwd: dirname || null, timeout: options.timeout || 60000 })
1071
77
  .catch(exc => exc);
1072
78
  try {
1073
79
  if (yosys_result instanceof Error) {
@@ -1081,7 +87,7 @@ async function process(filenames, dirname, options = {}) {
1081
87
  }
1082
88
  obj = JSON.parse(fs.readFileSync(tmpjson, 'utf8'));
1083
89
  await (0, util_1.promisify)(fs.unlink)(tmpjson);
1084
- const output = yosys2digitaljs(obj, options);
90
+ const output = (0, core_1.yosys2digitaljs)(obj, options);
1085
91
  const ret = {
1086
92
  output: output,
1087
93
  yosys_output: obj,
@@ -1100,30 +106,6 @@ async function process(filenames, dirname, options = {}) {
1100
106
  throw exc;
1101
107
  }
1102
108
  }
1103
- exports.process = process;
1104
- function io_ui(output) {
1105
- for (const [name, dev] of Object.entries(output.devices)) {
1106
- if (dev.type == 'Input' || dev.type == 'Output') {
1107
- dev.label = dev.net;
1108
- }
1109
- // use clock for clocky named inputs
1110
- if (dev.type == 'Input' && dev.bits == 1 && (dev.label == 'clk' || dev.label == 'clock')) {
1111
- dev.type = 'Clock';
1112
- dev.propagation = 100;
1113
- }
1114
- if (dev.type == 'Input')
1115
- dev.type = dev.bits == 1 ? 'Button' : 'NumEntry';
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
- }
1124
- }
1125
- }
1126
- exports.io_ui = io_ui;
1127
109
  async function process_files(data, options = {}) {
1128
110
  const dir = await tmp.dir();
1129
111
  const names = [];
@@ -1143,7 +125,6 @@ async function process_files(data, options = {}) {
1143
125
  dir.cleanup();
1144
126
  }
1145
127
  }
1146
- exports.process_files = process_files;
1147
128
  async function process_sv(text, options = {}) {
1148
129
  const tmpsv = await tmp.file({ postfix: '.sv' });
1149
130
  try {
@@ -1155,4 +136,3 @@ async function process_sv(text, options = {}) {
1155
136
  tmpsv.cleanup();
1156
137
  }
1157
138
  }
1158
- exports.process_sv = process_sv;