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); }); */ });