diff --git a/doc/notes.txt b/doc/notes.txt index 2ea2398e..38f5e9ef 100644 --- a/doc/notes.txt +++ b/doc/notes.txt @@ -84,7 +84,7 @@ TODO: - wasm dynamic linking of emulators (https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md) - use alternate confirm/prompt dialogs - https://github.com/jvilk/BrowserFS -- verilog: in .asm file editing .v files doesnt update +- what if error in include file you can't edit b/c it never appears? WEB WORKER FORMAT diff --git a/src/project.ts b/src/project.ts index e53a99a1..23ba0f8c 100644 --- a/src/project.ts +++ b/src/project.ts @@ -264,19 +264,8 @@ export class CodeProject { console.log(err); // TODO? } if (!depends) depends = []; - if (this.platform_id.startsWith('verilog')) { - // TODO: should get rid of this msg format - this.worker.postMessage({ - code:text, - path:getFilenameForPath(this.mainpath), - dependencies:depends, - platform:this.platform_id, - tool:this.platform.getToolForFilename(this.mainpath) - }); - } else { - var workermsg = this.buildWorkerMessage(depends); - this.worker.postMessage(workermsg); - } + var workermsg = this.buildWorkerMessage(depends); + this.worker.postMessage(workermsg); this.isCompiling = true; }); } diff --git a/src/worker/workermain.ts b/src/worker/workermain.ts index 3cd9881b..5a464cd6 100644 --- a/src/worker/workermain.ts +++ b/src/worker/workermain.ts @@ -215,7 +215,8 @@ type FileEntry = { }; type BuildOptions = { - mainFilePath : string + mainFilePath : string, + processFn?: (FileData) => FileData }; // TODO @@ -230,7 +231,6 @@ interface BuildStep extends WorkerBuildStep { generated? prefix? maxts? - dependencies? }; var buildsteps : BuildStep[] = []; @@ -270,8 +270,11 @@ function getWorkFileAsString(path:string) : string { return workfs[path] && workfs[path].data as string; // TODO } -function populateEntry(fs, path:string, entry:FileEntry) { - fs.writeFile(path, entry.data, {encoding:entry.encoding}); +function populateEntry(fs, path:string, entry:FileEntry, options:BuildOptions) { + var data = entry.data; + if (options && options.processFn) + data = options.processFn(data); + fs.writeFile(path, data, {encoding:entry.encoding}); fs.utime(path, entry.ts, entry.ts); console.log("<<<", path, entry.data.length); } @@ -283,7 +286,11 @@ function gatherFiles(step:BuildStep, options?:BuildOptions) { for (var i=0; i { - var jsontext : string; - for (var dep of options.dependencies) { - if (dep.filename == filename) - jsontext = dep.data as string; - } - // TODO: var jsontext = getWorkFileAsString(filename) || getWorkFileAsString("local/"+filename); + var jsontext = getWorkFileAsString(filename); if (!jsontext) throw "could not load " + filename; return JSON.parse(jsontext); }; @@ -1307,24 +1297,26 @@ function compileJSASM(asmcode:string, platform, options, is_inline) { }; var loaded_module = false; asm.loadModule = function(top_module) { - // TODO: cache module // compile last file in list loaded_module = true; var key = top_module + '/' + includes; - if (key != jsasm_module_key) { + if (jsasm_module_key != key) { jsasm_module_key = key; - jsasm_module_top = top_module; - var main_filename = includes[includes.length-1]; - var code = '`include "' + main_filename + '"\n'; - code += "/*\nmodule " + top_module + "\n*/\n"; - var voutput = compileVerilator({code:code, platform:platform, dependencies:options.dependencies, path:options.path, tool:'verilator'}); // TODO - if (voutput.errors.length) - return voutput.errors[0].msg; - jsasm_module_output = voutput; + jsasm_module_output = null; } + jsasm_module_top = top_module; + var main_filename = includes[includes.length-1]; + // TODO: take out .asm dependency + var voutput = compileVerilator({platform:platform, files:includes, path:main_filename, tool:'verilator'}); + if (voutput) + jsasm_module_output = voutput; } var result = asm.assembleFile(asmcode); if (loaded_module && jsasm_module_output) { + // errors? return them + if (jsasm_module_output.errors && jsasm_module_output.errors.length) + return jsasm_module_output; + // return program ROM array var asmout = result.output; // TODO: unify result.output = jsasm_module_output.output; @@ -1338,10 +1330,10 @@ function compileJSASM(asmcode:string, platform, options, is_inline) { } function compileJSASMStep(step:BuildStep) { - // TODO - var code = step.code; + gatherFiles(step); + var code = getWorkFileAsString(step.path); var platform = step.platform || 'verilog'; - return compileJSASM(code, platform, step, false); // TODO + return compileJSASM(code, platform, step, false); } function compileInlineASM(code:string, platform, options, errors, asmlines) { @@ -1374,58 +1366,62 @@ function compileInlineASM(code:string, platform, options, errors, asmlines) { return code; } -// TODO: make compliant with standard msg format function compileVerilator(step:BuildStep) { loadNative("verilator_bin"); loadGen("worker/verilator2js"); var platform = step.platform || 'verilog'; var errors = []; var asmlines = []; - // TODO? gatherFiles(step); - step.code = compileInlineASM(step.code, platform, step, errors, asmlines); - if (errors.length) { - return {errors:errors}; - } - var code = step.code; - var match_fn = makeErrorMatcher(errors, /%(.+?): (.+?:)?(\d+)?[:]?\s*(.+)/i, 3, 4, step.path); - var verilator_mod = emglobal.verilator_bin({ - instantiateWasm: moduleInstFn('verilator_bin'), - noInitialRun:true, - print:print_fn, - printErr:match_fn, - TOTAL_MEMORY:256*1024*1024, - }); - var topmod = detectTopModuleName(code); - var FS = verilator_mod['FS']; - populateFiles(step, FS, {mainFilePath:step.path}); - writeDependencies(step.dependencies, FS, errors, function(d, code) { - return compileInlineASM(code, platform, step, errors, null); - }); - starttime(); - try { - var args = ["--cc", "-O3", "-DEXT_INLINE_ASM", "-DTOPMOD__"+topmod, - "-Wall", "-Wno-DECLFILENAME", "-Wno-UNUSED", '--report-unoptflat', - "--x-assign", "fast", "--noassert", "--pins-bv", "33", - "--top-module", topmod, step.path] - verilator_mod.callMain(args); - } catch (e) { - console.log(e); - errors.push({line:0,msg:"Compiler internal error: " + e}); - } - endtime("compile"); - // remove boring errors - errors = errors.filter(function(e) { return !/Exiting due to \d+/.exec(e.msg); }, errors); - errors = errors.filter(function(e) { return !/Use ["][/][*]/.exec(e.msg); }, errors); - if (errors.length) { - return {errors:errors}; - } - try { - var h_file = FS.readFile("obj_dir/V"+topmod+".h", {encoding:'utf8'}); - var cpp_file = FS.readFile("obj_dir/V"+topmod+".cpp", {encoding:'utf8'}); - var rtn = translateVerilatorOutputToJS(h_file, cpp_file); - putWorkFile("main.js", rtn.output.code); - if (!anyTargetChanged(step, ["main.js"])) - return; + gatherFiles(step); + // compile verilog if files are stale + var outjs = "main.js"; + if (staleFiles(step, [outjs])) { + var match_fn = makeErrorMatcher(errors, /%(.+?): (.+?):(\d+)?[:]?\s*(.+)/i, 3, 4, step.path, 2); + var verilator_mod = emglobal.verilator_bin({ + instantiateWasm: moduleInstFn('verilator_bin'), + noInitialRun:true, + print:print_fn, + printErr:match_fn, + TOTAL_MEMORY:256*1024*1024, + }); + var code = getWorkFileAsString(step.path); + var topmod = detectTopModuleName(code); + var FS = verilator_mod['FS']; + populateFiles(step, FS, { + mainFilePath:step.path, + processFn:(code) => { + return compileInlineASM(code, platform, step, errors, asmlines); + } + }); + starttime(); + try { + var args = ["--cc", "-O3", "-DEXT_INLINE_ASM", "-DTOPMOD__"+topmod, + "-Wall", "-Wno-DECLFILENAME", "-Wno-UNUSED", '--report-unoptflat', + "--x-assign", "fast", "--noassert", "--pins-bv", "33", + "--top-module", topmod, step.path] + verilator_mod.callMain(args); + } catch (e) { + console.log(e); + errors.push({line:0,msg:"Compiler internal error: " + e}); + } + endtime("compile"); + // remove boring errors + errors = errors.filter(function(e) { return !/Exiting due to \d+/.exec(e.msg); }, errors); + errors = errors.filter(function(e) { return !/Use ["][/][*]/.exec(e.msg); }, errors); + if (errors.length) { + return {errors:errors}; + } + try { + var h_file = FS.readFile("obj_dir/V"+topmod+".h", {encoding:'utf8'}); + var cpp_file = FS.readFile("obj_dir/V"+topmod+".cpp", {encoding:'utf8'}); + var rtn = translateVerilatorOutputToJS(h_file, cpp_file); + putWorkFile(outjs, rtn.output.code); + if (!anyTargetChanged(step, [outjs])) + return; + } catch(e) { + console.log(e); + return {errors:errors}; + } //rtn.intermediate = {listing:h_file + cpp_file}; // TODO var listings = {}; // TODO: what if found in non-top-module? @@ -1436,9 +1432,6 @@ function compileVerilator(step:BuildStep) { errors: errors, listings: listings, }; - } catch(e) { - console.log(e); - return {errors:errors}; } } @@ -1459,7 +1452,6 @@ function compileYosys(step:BuildStep) { var topmod = detectTopModuleName(code); var FS = yosys_mod['FS']; FS.writeFile(topmod+".v", code); - writeDependencies(step.dependencies, FS, errors); starttime(); try { yosys_mod.callMain(["-q", "-o", topmod+".json", "-S", topmod+".v"]); @@ -1726,7 +1718,6 @@ function executeBuildSteps() { buildstartseq = workerseq; while (buildsteps.length) { var step = buildsteps.shift(); // get top of array - var code = step.code; var platform = step.platform; var toolfn = TOOLS[step.tool]; if (!toolfn) throw "no tool named " + step.tool; @@ -1797,7 +1788,6 @@ function handleMessage(data : WorkerMessage) : WorkerResult { workfs = {}; return; } - // (code,platform,tool,dependencies) buildsteps = []; // file updates if (data.updates) { diff --git a/test/cli/testworker.js b/test/cli/testworker.js index 50be6c9a..af4335a2 100644 --- a/test/cli/testworker.js +++ b/test/cli/testworker.js @@ -173,7 +173,7 @@ describe('Worker', function() { */ it('should compile verilog example', function(done) { var csource = ab2str(fs.readFileSync('presets/verilog/lfsr.v')); - var msgs = [{code:csource, platform:"verilog", tool:"verilator", dependencies:[], path:'main.v'}]; + var msgs = [{code:csource, platform:"verilog", tool:"verilator", path:'main.v'}]; var done2 = function(err, msg) { var jscode = msg.output.code; var fn = new Function(jscode); @@ -184,18 +184,20 @@ describe('Worker', function() { }); it('should NOT compile verilog example', function(done) { var csource = "foobar"; - var msgs = [{code:csource, platform:"verilog", tool:"verilator", dependencies:[], path:'foomain.v'}]; + var msgs = [{code:csource, platform:"verilog", tool:"verilator", path:'foomain.v'}]; doBuild(msgs, done, 0, 0, 1); }); it('should compile verilog inline assembler (JSASM)', function(done) { - var csource = ab2str(fs.readFileSync('presets/verilog/racing_game_cpu.v')); - var dependfiles = ["hvsync_generator.v", "sprite_bitmap.v", "sprite_renderer.v", "cpu8.v", "femto8.json"]; + var dependfiles = ["racing_game_cpu.v", "hvsync_generator.v", "sprite_bitmap.v", "sprite_renderer.v", "cpu8.v", "femto8.json"]; var depends = []; for (var dfile of dependfiles) { var code = ab2str(fs.readFileSync('presets/verilog/' + dfile)); - depends.push({filename:dfile, data:code, prefix:"verilog"}); + depends.push({path:dfile, data:code}); } - var msgs = [{code:csource, platform:"verilog", tool:"verilator", dependencies:depends, path:'racing_game_cpu.v'}]; + var msgs = [{ + updates:depends, + buildsteps:[{platform:"verilog", tool:"verilator", path:'racing_game_cpu.v', files:dependfiles}] + }]; var done2 = function(err, msg) { var jscode = msg.output.code; var fn = new Function(jscode); @@ -205,14 +207,16 @@ describe('Worker', function() { doBuild(msgs, done2, 51459, 0, 0); }); it('should compile verilog assembler file (JSASM)', function(done) { - var csource = ab2str(fs.readFileSync('presets/verilog/test2.asm')); - var dependfiles = ["hvsync_generator.v", "font_cp437_8x8.v", "ram.v", "tile_renderer.v", "sprite_scanline_renderer.v", "lfsr.v", "sound_generator.v", "cpu16.v", "cpu_platform.v", "femto16.json"]; + var dependfiles = ["test2.asm", "hvsync_generator.v", "font_cp437_8x8.v", "ram.v", "tile_renderer.v", "sprite_scanline_renderer.v", "lfsr.v", "sound_generator.v", "cpu16.v", "cpu_platform.v", "femto16.json"]; var depends = []; for (var dfile of dependfiles) { var code = ab2str(fs.readFileSync('presets/verilog/' + dfile)); - depends.push({filename:dfile, data:code, prefix:"verilog"}); + depends.push({path:dfile, data:code}); } - var msgs = [{code:csource, platform:"verilog", tool:"jsasm", dependencies:depends, path:'main.asm'}]; + var msgs = [{ + updates:depends, + buildsteps:[{platform:"verilog", tool:"jsasm", path:'test2.asm', files:dependfiles}] + }]; var done2 = function(err, msg) { var jscode = msg.output.code; var fn = new Function(jscode);