8bitworkshop/test/verilog/testverilog.js

174 lines
6.1 KiB
JavaScript

var assert = require('assert');
var _fs = require('fs');
var _path = require('path')
var _cproc = require('child_process');
var fs = require('fs');
var wtu = require('../cli/workertestutils.js');
//var heapdump = require("heapdump");
var commandExists = require('command-exists');
var has_yosys = commandExists('yosys');
var has_iverilog = commandExists('iverilog');
createTestDOM();
var emu = require('gen/common/emu.js');
var verilog = require('gen/platform/verilog.js');
var VerilogPlatform = emu.PLATFORMS['verilog'];
Object.assign(global, verilog); // copy global VL_* properties
// TODO: must define $
async function loadPlatform(msg) {
var platform = new VerilogPlatform();
platform.resume = function() { }; // prevent resume after reset
try {
//console.log(msg.output.ports);
//console.log(msg.output.signals);
await platform.loadROM("ROM", msg.output);
platform.getHDLModuleRunner().randomizeOnReset = false;
platform.getHDLModuleRunner().powercycle();
//await platform.loadROM("ROM", msg.output);
for (var i=0; i<100000 && !platform.isBlocked(); i++) {
platform.tick();
}
console.log(i, platform.isBlocked(), platform.isStopped());
//assert.ok(platform.isBlocked());
assert.ok(!platform.isStopped());
var state = platform.saveState();
platform.reset();
platform.loadState(state);
assert.deepEqual(state, platform.saveState());
} catch (e) {
//platform.printErrorCodeContext(e, msg.output.code);
//console.log(msg.intermediate.listing);
//console.log(msg.output.code);
console.log(e);
throw e;
}
return platform;
}
function compileVerilator(filename, code, callback, nerrors, depends) {
var loadfail = false;
if (filename.indexOf('t_unopt_converge') >= 0) loadfail = true;
// files come back from worker
global.postMessage = async function(msg) {
try {
if (msg.errors && msg.errors.length) {
if (msg.errors.length > 0 && nerrors == 0) throw new Error(JSON.stringify(msg.errors));
assert.equal(nerrors||0, msg.errors.length, "errors");
} else {
assert.equal(nerrors||0, 0, "errors");
var platform = await loadPlatform(msg);
//testPerf(msg);
if (filename.indexOf('t_') >= 0) {
//assert.ok(platform.isBlocked() && !platform.isStopped());
}
platform.dispose();
}
if (loadfail) e = new Error('should have failed');
callback(null, msg);
} catch (e) {
if (loadfail) e = null;
//console.log('rm', filename);
callback(e, null);
}
};
// send files to worker for build
try {
global.onmessage({
data:{
updates:[{path:_path.basename(filename), data:code}],
buildsteps:[{path:_path.basename(filename), platform:'verilog', tool:'verilator', files:depends}]
}
});
} catch (e) {
//console.log('rm', filename);
callback(e, null);
}
}
function testIcarus(filename) {
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);
});
});
}
function testVerilator(filename, disables, nerrors, depends) {
it('should verilate '+filename, function(done) {
console.log(filename);
var csource = ab2str(fs.readFileSync(filename));
var header = '';
for (var i=0; i<(disables||[]).length; i++)
header += "/* verilator lint_off " + disables[i] + " */ ";
compileVerilator(filename, header + "\n" + csource, done, nerrors||0, depends);
});
}
function testModule(filename, disables, nerrors, depends) {
testVerilator(filename, disables, nerrors, depends);
//testIcarus(filename);
//testYosys(filename);
}
describe('Verilog Worker', function() {
var files = _fs.readdirSync('test/cli/verilog').filter(fn => fn.endsWith('.v'));
//files = files.slice(0,75);
for (var fn of files) {
testModule('test/cli/verilog/' + fn,
['UNDRIVEN','BLKSEQ','WIDTH','PINCONNECTEMPTY','SYNCASYNCNET','UNOPT','UNOPTFLAT','VARHIDDEN','EOFNEWLINE','ASSIGNDLY','CASEX','SYMRSVDWORD','STMTDLY','PROCASSWIRE']
);
global.onmessage({data:{reset:true}});
}
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');
}).afterAll(() => {
/*
heapdump.writeSnapshot((err, filename) => {
console.log("Heap dump written to", filename);
});
*/
});