2017-11-22 14:42:07 +00:00
|
|
|
|
|
|
|
var assert = require('assert');
|
2021-07-06 20:45:27 +00:00
|
|
|
var _fs = require('fs');
|
2021-07-04 17:00:25 +00:00
|
|
|
var _path = require('path')
|
|
|
|
var _cproc = require('child_process');
|
2017-11-22 14:42:07 +00:00
|
|
|
var fs = require('fs');
|
|
|
|
var wtu = require('./workertestutils.js');
|
2021-07-07 04:18:46 +00:00
|
|
|
var heapdump = require("heapdump");
|
2021-07-07 16:06:22 +00:00
|
|
|
var commandExists = require('command-exists');
|
|
|
|
|
|
|
|
var has_yosys = commandExists('yosys');
|
|
|
|
var has_iverilog = commandExists('iverilog');
|
2021-07-04 17:00:25 +00:00
|
|
|
|
2020-07-27 13:04:48 +00:00
|
|
|
createTestDOM();
|
2017-11-22 14:42:07 +00:00
|
|
|
|
2019-10-26 01:55:50 +00:00
|
|
|
var emu = require('gen/common/emu.js');
|
2018-08-16 23:19:20 +00:00
|
|
|
var verilog = require('gen/platform/verilog.js');
|
|
|
|
var VerilogPlatform = emu.PLATFORMS['verilog'];
|
|
|
|
|
|
|
|
Object.assign(global, verilog); // copy global VL_* properties
|
2017-11-22 14:42:07 +00:00
|
|
|
|
2018-10-11 15:08:15 +00:00
|
|
|
// TODO: must define $
|
|
|
|
|
2021-07-03 14:49:03 +00:00
|
|
|
async function loadPlatform(msg) {
|
2017-11-22 14:42:07 +00:00
|
|
|
var platform = new VerilogPlatform();
|
2018-10-11 15:08:15 +00:00
|
|
|
platform.resume = function() { }; // prevent resume after reset
|
2017-11-22 14:42:07 +00:00
|
|
|
try {
|
2018-07-24 15:38:56 +00:00
|
|
|
//console.log(msg.output.ports);
|
|
|
|
//console.log(msg.output.signals);
|
2021-07-03 14:49:03 +00:00
|
|
|
await platform.loadROM("ROM", msg.output);
|
|
|
|
await platform.loadROM("ROM", msg.output);
|
2021-06-28 20:36:47 +00:00
|
|
|
for (var i=0; i<100000 && !platform.isBlocked(); i++) {
|
2017-11-22 14:42:07 +00:00
|
|
|
platform.tick();
|
2018-08-29 12:24:13 +00:00
|
|
|
}
|
2021-06-28 20:36:47 +00:00
|
|
|
console.log(i, platform.isBlocked(), platform.isStopped());
|
|
|
|
//assert.ok(platform.isBlocked());
|
|
|
|
assert.ok(!platform.isStopped());
|
2018-08-29 12:24:13 +00:00
|
|
|
var state = platform.saveState();
|
|
|
|
platform.reset();
|
|
|
|
platform.loadState(state);
|
|
|
|
assert.deepEqual(state, platform.saveState());
|
2017-11-22 14:42:07 +00:00
|
|
|
} catch (e) {
|
|
|
|
//platform.printErrorCodeContext(e, msg.output.code);
|
2018-10-11 15:08:15 +00:00
|
|
|
//console.log(msg.intermediate.listing);
|
2021-06-28 20:36:47 +00:00
|
|
|
//console.log(msg.output.code);
|
2017-11-22 14:42:07 +00:00
|
|
|
console.log(e);
|
|
|
|
throw e;
|
|
|
|
}
|
|
|
|
return platform;
|
|
|
|
}
|
|
|
|
|
2018-08-29 12:24:13 +00:00
|
|
|
function testPerf(msg) {
|
|
|
|
var platform = new VerilogPlatform();
|
|
|
|
platform.loadROM("ROM", msg.output);
|
2020-07-27 13:04:48 +00:00
|
|
|
var niters = 5000000;
|
2018-08-29 12:24:13 +00:00
|
|
|
|
|
|
|
console.time("before");
|
2021-07-03 14:49:03 +00:00
|
|
|
for (var i=0; i<niters && !platform.isBlocked(); i++)
|
2018-08-29 12:24:13 +00:00
|
|
|
platform.tick();
|
|
|
|
console.timeEnd("before");
|
|
|
|
|
|
|
|
var state = platform.saveState();
|
|
|
|
platform.reset();
|
|
|
|
platform.loadState(state);
|
|
|
|
console.time("after");
|
2021-07-03 14:49:03 +00:00
|
|
|
for (var i=0; i<niters && !platform.isBlocked(); i++)
|
2018-08-29 12:24:13 +00:00
|
|
|
platform.tick();
|
|
|
|
console.timeEnd("after");
|
|
|
|
|
|
|
|
return platform;
|
|
|
|
}
|
|
|
|
|
2021-07-04 17:00:25 +00:00
|
|
|
function compileVerilator(filename, code, callback, nerrors, depends) {
|
2021-07-07 04:18:46 +00:00
|
|
|
// files come back from worker
|
2021-07-03 14:49:03 +00:00
|
|
|
global.postMessage = async function(msg) {
|
2021-07-06 20:45:27 +00:00
|
|
|
try {
|
2017-11-22 14:42:07 +00:00
|
|
|
if (msg.errors && msg.errors.length) {
|
2021-07-07 16:06:22 +00:00
|
|
|
if (msg.errors.length > 0 && nerrors == 0) throw new Error(JSON.stringify(msg.errors));
|
2017-11-22 14:42:07 +00:00
|
|
|
assert.equal(nerrors||0, msg.errors.length, "errors");
|
|
|
|
} else {
|
|
|
|
assert.equal(nerrors||0, 0, "errors");
|
2021-07-06 20:45:27 +00:00
|
|
|
var platform = await loadPlatform(msg);
|
2018-08-29 12:24:13 +00:00
|
|
|
//testPerf(msg);
|
|
|
|
if (filename.indexOf('t_') >= 0) {
|
2021-07-06 20:45:27 +00:00
|
|
|
//assert.ok(platform.isBlocked() && !platform.isStopped());
|
2018-08-29 12:24:13 +00:00
|
|
|
}
|
2021-07-06 20:45:27 +00:00
|
|
|
platform.dispose();
|
2017-11-22 14:42:07 +00:00
|
|
|
}
|
|
|
|
callback(null, msg);
|
2021-07-06 20:45:27 +00:00
|
|
|
} catch (e) {
|
2021-07-07 16:06:22 +00:00
|
|
|
console.log('rm', filename); //fs.unlinkSync(filename);
|
|
|
|
callback(e, null);
|
2021-07-06 20:45:27 +00:00
|
|
|
}
|
|
|
|
};
|
2021-07-07 04:18:46 +00:00
|
|
|
// send files to worker for build
|
2021-07-06 20:45:27 +00:00
|
|
|
try {
|
|
|
|
global.onmessage({
|
|
|
|
data:{
|
|
|
|
updates:[{path:_path.basename(filename), data:code}],
|
|
|
|
buildsteps:[{path:_path.basename(filename), platform:'verilog', tool:'verilator', files:depends}]
|
|
|
|
}
|
|
|
|
});
|
|
|
|
} catch (e) {
|
2021-07-07 16:06:22 +00:00
|
|
|
console.log('rm', filename); //fs.unlinkSync(filename);
|
|
|
|
callback(e, null);
|
2021-07-06 20:45:27 +00:00
|
|
|
}
|
2017-11-22 14:42:07 +00:00
|
|
|
}
|
|
|
|
|
2021-07-04 17:00:25 +00:00
|
|
|
function testIcarus(filename) {
|
2021-07-07 16:06:22 +00:00
|
|
|
if (has_iverilog) it('should icarus '+filename, function(done) {
|
|
|
|
_cproc.exec('iverilog -g2012 -I./presets/verilog -I./tests/cli/verilog ./' + filename, function(err,stdout,stderr) {
|
|
|
|
if (err) {
|
|
|
|
console.log(stdout);
|
|
|
|
console.log(stderr);
|
|
|
|
}
|
|
|
|
done(err);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
function testYosys(filename) {
|
|
|
|
if (has_yosys) it('should yosys '+filename, function(done) {
|
|
|
|
_cproc.exec(`yosys -q -p "read_verilog -sv ./${filename}"`, function(err,stdout,stderr) {
|
|
|
|
if (err) {
|
|
|
|
console.log(stdout);
|
|
|
|
console.log(stderr);
|
|
|
|
}
|
|
|
|
done(err);
|
|
|
|
});
|
|
|
|
});
|
2021-07-04 17:00:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function testVerilator(filename, disables, nerrors, depends) {
|
2021-07-07 16:06:22 +00:00
|
|
|
it('should verilate '+filename, function(done) {
|
2021-06-28 20:36:47 +00:00
|
|
|
console.log(filename);
|
2017-11-22 14:42:07 +00:00
|
|
|
var csource = ab2str(fs.readFileSync(filename));
|
2021-07-07 04:18:46 +00:00
|
|
|
var header = '';
|
2017-11-22 14:42:07 +00:00
|
|
|
for (var i=0; i<(disables||[]).length; i++)
|
2021-07-07 04:18:46 +00:00
|
|
|
header += "/* verilator lint_off " + disables[i] + " */ ";
|
|
|
|
compileVerilator(filename, header + "\n" + csource, done, nerrors||0, depends);
|
2017-11-22 14:42:07 +00:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2021-07-07 16:06:22 +00:00
|
|
|
function testModule(filename, disables, nerrors, depends) {
|
|
|
|
testVerilator(filename, disables, nerrors, depends);
|
|
|
|
//testIcarus(filename);
|
|
|
|
//testYosys(filename);
|
|
|
|
}
|
|
|
|
|
2017-11-22 14:42:07 +00:00
|
|
|
describe('Verilog Worker', function() {
|
2021-07-06 20:45:27 +00:00
|
|
|
|
|
|
|
var files = _fs.readdirSync('test/cli/verilog').filter(fn => fn.endsWith('.v'));
|
2021-07-07 04:18:46 +00:00
|
|
|
//files = files.slice(0,75);
|
2021-07-06 20:45:27 +00:00
|
|
|
for (var fn of files) {
|
2021-07-07 16:06:22 +00:00
|
|
|
testModule('test/cli/verilog/' + fn,
|
2021-07-07 04:18:46 +00:00
|
|
|
['UNDRIVEN','BLKSEQ','WIDTH','PINCONNECTEMPTY','SYNCASYNCNET','UNOPT','UNOPTFLAT','VARHIDDEN','EOFNEWLINE','ASSIGNDLY','CASEX','SYMRSVDWORD','STMTDLY','PROCASSWIRE']
|
2021-07-06 20:45:27 +00:00
|
|
|
);
|
|
|
|
global.onmessage({data:{reset:true}});
|
|
|
|
}
|
|
|
|
|
2021-07-07 16:06:22 +00:00
|
|
|
testModule('presets/verilog/hvsync_generator.v');
|
|
|
|
testModule('presets/verilog/test_hvsync.v', null, null, ['test_hvsync.v', 'hvsync_generator.v']);
|
|
|
|
testModule('presets/verilog/digits10.v', null, null, ['digits10.v', 'hvsync_generator.v']);
|
|
|
|
testModule('presets/verilog/scoreboard.v', null, null, ['scoreboard.v', 'digits10.v', 'hvsync_generator.v']);
|
|
|
|
testModule('presets/verilog/ball_paddle.v', null, null, ['ball_paddle.v', 'scoreboard.v', 'digits10.v', 'hvsync_generator.v']);
|
|
|
|
testModule('presets/verilog/sprite_rotation.v', null, null, ['sprite_rotation.v', 'hvsync_generator.v']);
|
|
|
|
testModule('presets/verilog/lfsr.v');
|
|
|
|
testModule('presets/verilog/starfield.v', null, null, ['starfield.v', 'lfsr.v', 'hvsync_generator.v']);
|
|
|
|
testModule('presets/verilog/ram.v');
|
|
|
|
testModule('presets/verilog/font_cp437_8x8.v');
|
|
|
|
testModule('presets/verilog/sprite_scanline_renderer.v', null, null, ['sprite_scanline_renderer.v', 'ram.v', 'hvsync_generator.v']);
|
|
|
|
testModule('presets/verilog/tile_renderer.v', null, null, ['tile_renderer.v', 'font_cp437_8x8.v', 'ram.v', 'hvsync_generator.v']);
|
|
|
|
testModule('presets/verilog/cpu6502.v');
|
|
|
|
|
|
|
|
testYosys('presets/verilog/ball_paddle.v');
|
|
|
|
testYosys('presets/verilog/starfield.v');
|
|
|
|
testYosys('presets/verilog/racing_game.v');
|
|
|
|
testYosys('presets/verilog/racing_game_cpu.v');
|
|
|
|
// TODO: fix testYosys('presets/verilog/cpu_platform.v');
|
|
|
|
testYosys('presets/verilog/cpu6502.v');
|
2017-11-28 02:08:19 +00:00
|
|
|
|
2021-07-07 04:18:46 +00:00
|
|
|
}).afterAll(() => {
|
|
|
|
/*
|
|
|
|
heapdump.writeSnapshot((err, filename) => {
|
|
|
|
console.log("Heap dump written to", filename);
|
|
|
|
});
|
|
|
|
*/
|
2017-11-22 14:42:07 +00:00
|
|
|
});
|