verilog: multiple modules, sound, tables, reset, module_top detect

This commit is contained in:
Steven Hugg 2017-11-13 00:24:19 -05:00
parent 014d659558
commit 0ca9f43098
6 changed files with 90 additions and 37 deletions

View File

@ -395,19 +395,23 @@ var SampleAudio = function(clockfreq) {
}
}
this.addSingleSample = function(value) {
buffer[bufpos++] = value;
if (bufpos >= buffer.length) {
bufpos = 0;
bufferlist[0] = bufferlist[1];
bufferlist[1] = buffer;
}
}
this.feedSample = function(value, count) {
while (count-- > 0) {
accum += value;
sfrac += sinc;
if (sfrac >= 1) {
buffer[bufpos++] = accum / sfrac;
sfrac -= 1;
accum = 0;
if (bufpos >= buffer.length) {
bufpos = 0;
bufferlist[0] = bufferlist[1];
bufferlist[1] = buffer;
}
this.feedSingleSample(accum / sfrac);
}
}
}

View File

@ -207,8 +207,7 @@ var AnimationTimer = function(frequencyHz, callback) {
var running;
var lastts = 0;
var useReqAnimFrame = window.requestAnimationFrame ? true : false;
var nframes = 0;
var startts = 0;
var nframes, startts; // for FPS calc
function scheduleFrame() {
if (useReqAnimFrame)
@ -222,8 +221,8 @@ var AnimationTimer = function(frequencyHz, callback) {
lastts += intervalMsec;
} else {
lastts = ts;
startts = ts;
}
if (nframes == 0) startts = ts;
if (nframes++ == 300) {
console.log("Avg framerate: " + nframes*1000/(ts-startts) + " fps");
}
@ -240,6 +239,7 @@ var AnimationTimer = function(frequencyHz, callback) {
if (!running) {
running = true;
lastts = 0;
nframes = 0;
scheduleFrame();
}
}

View File

@ -2,14 +2,30 @@
var VERILOG_PRESETS = [
{id:'hvsync.v', name:'Hello Verilog'},
{id:'pong.v', name:'Pong'},
];
function VerilatorBase() {
this.VL_RAND_RESET_I = function(bits) { return Math.floor(Math.random() * (1<<bits)); }
this.tick = function() {
function vl_fatal(msg) {
console.log(msg);
}
this.reset2 = function() {
if (this.reset !== 'undefined') {
this.reset = 1;
for (var i=0; i<100; i++)
this.tick2();
this.reset = 0;
}
}
this.tick2 = function() {
this.clk = 0;
this.eval();
this.clk = 1;
this.eval();
this.clk ^= 1;
}
var vlSymsp = {TOPp:this};
@ -29,7 +45,7 @@ function VerilatorBase() {
vlSymsp.__Vm_activity = true;
this._eval(vlSymsp);
__Vchange = this._change_request(vlSymsp);
if (++__VclockLoop > 100) vl_fatal(__FILE__,__LINE__,__FILE__,"Verilated model didn't converge");
if (++__VclockLoop > 100) { vl_fatal("Verilated model didn't converge"); }
}
if (__VclockLoop > maxVclockLoop) {
maxVclockLoop = __VclockLoop;
@ -47,26 +63,44 @@ function VerilatorBase() {
this._eval_settle(vlSymsp);
this._eval(vlSymsp);
__Vchange = this._change_request(vlSymsp);
if (++__VclockLoop > 100) vl_fatal(__FILE__,__LINE__,__FILE__,"Verilated model didn't DC converge");
if (++__VclockLoop > 100) { vl_fatal("Verilated model didn't DC converge"); }
}
}
}
var VerilogPlatform = function(mainElement, options) {
var self = this;
var video;
var video, audio;
var videoWidth=288;
var videoHeight=248;
var idata, timer;
var gen;
var frameRate = 60;
var AUDIO_FREQ = 15700;
this.getPresets = function() { return VERILOG_PRESETS; }
function tick2() {
gen.tick2();
audio.addSingleSample(0+gen.audio); // TODO: sync with audio freq
}
var RGBLOOKUP = [
0xff111111,
0xff1111ff,
0xff11ff11,
0xff11ffff,
0xffff1111,
0xffff11ff,
0xffffff11,
0xffffffff,
];
this.start = function() {
// TODO
video = new RasterVideo(mainElement,videoWidth,videoHeight);
video.create();
audio = new SampleAudio(AUDIO_FREQ);
idata = video.getFrameData();
// TODO: 15.7 kHz?
timer = new AnimationTimer(frameRate, function() {
@ -75,17 +109,16 @@ var VerilogPlatform = function(mainElement, options) {
var i=0;
for (var y=0; y<videoHeight; y++) {
for (var x=0; x<videoWidth; x++) {
gen.tick();
gen.tick();
idata[i++] = gen.pixel ? 0xffffffff : 0xff111111;
tick2();
idata[i++] = RGBLOOKUP[gen.rgb];
}
var z=0;
while (gen.hsync && z++<videoWidth*2) gen.tick();
while (!gen.hsync && z++<videoWidth*2) gen.tick();
while (gen.hsync && z++<videoWidth) tick2();
while (!gen.hsync && z++<videoWidth) tick2();
}
var z=0;
while (gen.vsync && z++<videoWidth*160) gen.tick();
while (!gen.vsync && z++<videoWidth*160) gen.tick();
while (gen.vsync && z++<videoWidth*80) tick2();
while (!gen.vsync && z++<videoWidth*80) tick2();
video.updateFrame();
});
}
@ -105,15 +138,16 @@ var VerilogPlatform = function(mainElement, options) {
}
this.pause = function() {
timer.stop();
//audio.stop();
audio.stop();
}
this.resume = function() {
timer.start();
//audio.start();
audio.start();
}
this.reset = function() {
gen._ctor_var_reset();
gen.reset2();
}
this.getToolForFilename = function(fn) {
return "verilator";

View File

@ -429,6 +429,7 @@ function setCompileOutput(data) {
compparams = data.params;
updatePreset(current_preset_id, editor.getValue()); // update persisted entry
// errors?
var lines2errmsg = [];
function addErrorMarker(line, msg) {
var div = document.createElement("div");
div.setAttribute("class", "tooltipbox tooltiperror");
@ -436,7 +437,9 @@ function setCompileOutput(data) {
div.appendChild(document.createTextNode("\u24cd"));
var tooltip = document.createElement("span");
tooltip.setAttribute("class", "tooltiptext");
if (lines2errmsg[line]) msg = lines2errmsg[line] + "\n" + msg;
tooltip.appendChild(document.createTextNode(msg));
lines2errmsg[line] = msg;
div.appendChild(tooltip);
editor.setGutterMarker(line, "gutter-info", div);
}
@ -768,7 +771,6 @@ function resetAndDebug() {
setupBreakpoint();
platform.runEval(function(c) { return true; });
} else {
platform.pause();
platform.reset();
}
}

View File

@ -12,12 +12,10 @@ function parseDecls(text, arr, name, bin, bout) {
ofs:parseInt(m[4]),
});
}
//console.log(arr);
}
function buildModule(o) {
var m = '"use strict";\n';
//m += 'var ' + o.name + ' = function(base) {\n';
m += '\tvar self = this;\n';
m += '\tvar VL_RAND_RESET_I = base.VL_RAND_RESET_I;\n';
for (var i=0; i<o.ports.length; i++) {
@ -29,8 +27,6 @@ function buildModule(o) {
for (var i=0; i<o.funcs.length; i++) {
m += o.funcs[i];
}
//m += "\n}\n";
//m += "return " + o.name + ";\n";
return m;
}
@ -56,11 +52,20 @@ function translateFunction(text) {
return "function " + text + "\nself." + funcname + " = " + funcname + ";\n";
}
function translateStaticVars(text) {
var s = "";
var m;
var re = /VL_ST_SIG(\d+)[(](\w+?)::(\w+).(\d+).,(\d+),(\d+)[)]/g;
while (m = re.exec(text)) {
s += "var " + m[3] + " = this." + m[3] + " = new Uint" + m[1] + "Array(" + m[4] + ");\n";
}
return s;
}
function translateVerilatorOutputToJS(htext, cpptext) {
// parse header file
moduleName = /VL_MODULE.(\w+)./.exec(htext)[1];
symsName = moduleName + "__Syms";
//console.log(moduleName, symsName);
var ports = [];
parseDecls(htext, ports, 'VL_IN', true, false);
parseDecls(htext, ports, 'VL_OUT', false, true);
@ -72,9 +77,9 @@ function translateVerilatorOutputToJS(htext, cpptext) {
var re_fnsplit = new RegExp("(?:void|QData) " + moduleName + "::");
var functexts = cpptext.split(re_fnsplit);
var funcs = [];
funcs.push(translateStaticVars(functexts[0]));
for (var i=4; i<functexts.length; i++) {
var fntxt = translateFunction(functexts[i]);
//console.log(fntxt);
funcs.push(fntxt);
}
@ -93,6 +98,7 @@ function translateVerilatorOutputToJS(htext, cpptext) {
////
// TODO: unit test
/*
incpp = "obj_dir/Vhvsync_generator.cpp"
inh = "obj_dir/Vhvsync_generator.h"

View File

@ -266,9 +266,11 @@ function makeErrorMatcher(errors, regex, iline, imsg) {
var matches = regex.exec(s);
if (matches) {
errors.push({
line:parseInt(matches[iline]),
line:parseInt(matches[iline]) || 1,
msg:matches[imsg]
});
} else {
console.log(s);
}
}
}
@ -1033,29 +1035,34 @@ function compileVerilator(code, platform) {
loadWASM("verilator_bin");
load("verilator2js");
var errors = [];
var match_fn = makeErrorMatcher(errors, /%Error: main.v:(\d+): (.+)/, 1, 2);
var match_fn = makeErrorMatcher(errors, /%Error: (.+?:)?(\d+)?[:]?\s*(.+)/, 2, 3);
var verilator_mod = verilator_bin({
wasmBinary:wasmBlob['verilator_bin'],
noInitialRun:true,
print:print_fn,
printErr:match_fn,
});
// detect module_top name
var topmod = "top";
var m = /\bmodule\s+(\w+?_top)/.exec(code);
if (m && m[1]) topmod = m[1];
var FS = verilator_mod['FS'];
//setupFS(FS);
FS.writeFile("main.v", code);
FS.writeFile(topmod+".v", code);
starttime();
verilator_mod.callMain(["--cc", "-O2", "main.v"]);
verilator_mod.callMain(["--cc", "-O3", "--top-module", topmod, topmod+".v"]);
endtime("compile");
if (errors.length) return {errors:errors};
try {
var h_file = FS.readFile("obj_dir/Vmain.h", {encoding:'utf8'});
var cpp_file = FS.readFile("obj_dir/Vmain.cpp", {encoding:'utf8'});
//console.log(cpp_file)
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);
rtn.errors = errors;
rtn.lines = [];// TODO
rtn.intermediate = {listing:h_file + cpp_file};
return rtn;
} catch(e) {
console.log(e);
return {errors:errors};
}
}