started on .v files; framerate detect

This commit is contained in:
Steven Hugg 2017-11-11 14:45:32 -05:00
parent 07a0f97245
commit 014d659558
11 changed files with 445 additions and 11 deletions

View File

@ -0,0 +1,8 @@
emconfigure ./configure --includedir=/Library/Developer/CommandLineTools/usr/include
cd src
emmake make ../verilator_bin
cd ..
mkdir -p js
cp verilator_bin js/verilator_bin.bc
make -f Makefile.local

View File

@ -162,6 +162,7 @@ body {
<script src="codemirror/mode/clike/clike.js"></script>
<script src="codemirror/mode/6502/6502.js"></script>
<script src="codemirror/mode/z80/z80.js"></script>
<script src="codemirror/mode/verilog/verilog.js"></script>
<link rel="stylesheet" href="css/codemirror.css">
<script src="codemirror/addon/edit/matchbrackets.js"></script>
<script src="codemirror/addon/search/search.js"></script>

66
presets/verilog/hvsync.v Normal file
View File

@ -0,0 +1,66 @@
module hvsync(
clk, hsync, vsync, inDisplayArea, CounterX, CounterY, pixel);
input clk;
output hsync, vsync;
output inDisplayArea;
output [8:0] CounterX;
output [8:0] CounterY;
output pixel;
// constant declarations for VGA sync parameters
localparam H_DISPLAY = 256; // horizontal display area
localparam H_L_BORDER = 12; // horizontal left border
localparam H_R_BORDER = 8; // horizontal right border
localparam H_RETRACE = 24; // horizontal retrace
localparam H_MAX = H_DISPLAY + H_L_BORDER + H_R_BORDER + H_RETRACE - 1;
localparam START_H_RETRACE = H_DISPLAY + H_R_BORDER;
localparam END_H_RETRACE = H_DISPLAY + H_R_BORDER + H_RETRACE - 1;
localparam V_DISPLAY = 240; // vertical display area
localparam V_T_BORDER = 4; // vertical top border
localparam V_B_BORDER = 16; // vertical bottom border
localparam V_RETRACE = 2; // vertical retrace
localparam V_MAX = V_DISPLAY + V_T_BORDER + V_B_BORDER + V_RETRACE - 1;
localparam START_V_RETRACE = V_DISPLAY + V_B_BORDER;
localparam END_V_RETRACE = V_DISPLAY + V_B_BORDER + V_RETRACE - 1;
reg [8:0] CounterX;
reg [8:0] CounterY;
reg pixel;
wire CounterXmaxed = (CounterX==H_MAX);
wire CounterYmaxed = (CounterY==V_MAX);
always @(posedge clk)
if(CounterXmaxed)
CounterX <= 0;
else
CounterX <= CounterX + 1;
always @(posedge clk)
if(CounterXmaxed)
if (!CounterYmaxed)
CounterY <= CounterY + 1;
else
CounterY <= 0;
reg vga_HS, vga_VS;
always @(posedge clk)
begin
vga_HS <= (CounterX>=280 && CounterX<288); // change this value to move the display horizontally
vga_VS <= (CounterY==START_V_RETRACE); // change this value to move the display vertically
end
reg inDisplayArea;
always @(posedge clk)
begin
inDisplayArea <= (CounterX<H_DISPLAY) && (CounterY<V_DISPLAY);
pixel <= inDisplayArea &&
(((CounterX&7)==0) || ((CounterY&7)==0));
end
assign hsync = ~vga_HS;
assign vsync = ~vga_VS;
endmodule

View File

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

126
src/platform/verilog.js Normal file
View File

@ -0,0 +1,126 @@
"use strict";
var VERILOG_PRESETS = [
{id:'hvsync.v', name:'Hello Verilog'},
];
function VerilatorBase() {
this.VL_RAND_RESET_I = function(bits) { return Math.floor(Math.random() * (1<<bits)); }
this.tick = function() {
this.eval();
this.clk ^= 1;
}
var vlSymsp = {TOPp:this};
var maxVclockLoop = 1;
this.eval = function() {
vlSymsp.TOPp = this;
// Initialize
if (!vlSymsp.__Vm_didInit)
this._eval_initial_loop(vlSymsp);
// Evaluate till stable
//VL_DEBUG_IF(VL_PRINTF("\n----TOP Evaluate Vmain::eval\n"); );
var __VclockLoop = 0;
var __Vchange=1;
while (__Vchange) {
//VL_DEBUG_IF(VL_PRINTF(" Clock loop\n"););
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 > maxVclockLoop) {
maxVclockLoop = __VclockLoop;
console.log("Graph took " + maxVclockLoop + " iterations to stabilize");
}
}
this._eval_initial_loop = function(vlSymsp) {
vlSymsp.__Vm_didInit = true;
this._eval_initial(vlSymsp);
vlSymsp.__Vm_activity = true;
var __VclockLoop = 0;
var __Vchange=1;
while (__Vchange) {
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");
}
}
}
var VerilogPlatform = function(mainElement, options) {
var self = this;
var video;
var videoWidth=288;
var videoHeight=248;
var idata, timer;
var gen;
var frameRate = 60;
this.getPresets = function() { return VERILOG_PRESETS; }
this.start = function() {
// TODO
video = new RasterVideo(mainElement,videoWidth,videoHeight);
video.create();
idata = video.getFrameData();
// TODO: 15.7 kHz?
timer = new AnimationTimer(frameRate, function() {
if (!self.isRunning())
return;
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;
}
var z=0;
while (gen.hsync && z++<videoWidth*2) gen.tick();
while (!gen.hsync && z++<videoWidth*2) gen.tick();
}
var z=0;
while (gen.vsync && z++<videoWidth*160) gen.tick();
while (!gen.vsync && z++<videoWidth*160) gen.tick();
video.updateFrame();
});
}
this.loadROM = function(title, modtext) {
//console.log(modtext);
var mod = new Function('base', modtext);
var base = new VerilatorBase();
gen = new mod(base);
gen.__proto__ = base;
console.log(gen);
this.reset();
}
this.isRunning = function() {
return timer && timer.isRunning();
}
this.pause = function() {
timer.stop();
//audio.stop();
}
this.resume = function() {
timer.start();
//audio.start();
}
this.reset = function() {
gen._ctor_var_reset();
}
this.getToolForFilename = function(fn) {
return "verilator";
}
this.getDefaultExtension = function() { return ".v"; };
};
////////////////
PLATFORMS['verilog'] = VerilogPlatform;

View File

@ -134,6 +134,7 @@ var TOOL_TO_SOURCE_STYLE = {
'z80asm': 'z80',
'sdasz80': 'z80',
'sdcc': 'text/x-csrc',
'verilator': 'verilog',
}
var worker = new Worker("./src/worker/workermain.js");
@ -629,7 +630,7 @@ function runStepBackwards() {
function clearBreakpoint() {
lastDebugState = null;
platform.clearDebug();
if (platform.clearDebug) platform.clearDebug();
showMemory();
}
@ -670,7 +671,6 @@ function constraintEquals(a,b) {
return null;
}
/*
function showLoopTimingForCurrentLine() {
var line = getCurrentLine();
@ -761,11 +761,16 @@ function toggleDisassembly() {
}
function resetAndDebug() {
clearBreakpoint();
platform.resume();
platform.reset();
setupBreakpoint();
platform.runEval(function(c) { return true; });
if (platform.setupDebug) {
clearBreakpoint();
platform.resume();
platform.reset();
setupBreakpoint();
platform.runEval(function(c) { return true; });
} else {
platform.pause();
platform.reset();
}
}
function _breakExpression() {
@ -1141,13 +1146,21 @@ function _recordVideo() {
}
function setupDebugControls(){
var hasDebug = platform.setupDebug;
$("#dbg_reset").click(resetAndDebug);
$("#dbg_pause").click(pause);
$("#dbg_go").click(resume);
$("#dbg_step").click(singleStep);
$("#dbg_toline").click(runToCursor);
$("#dbg_stepout").click(runUntilReturn);
$("#dbg_stepback").click(runStepBackwards);
if (hasDebug) {
$("#dbg_step").click(singleStep).show();
$("#dbg_toline").click(runToCursor).show();
$("#dbg_stepout").click(runUntilReturn).show();
$("#dbg_stepback").click(runStepBackwards).show();
} else {
$("#dbg_step").hide();
$("#dbg_toline").hide();
$("#dbg_stepout").hide();
$("#dbg_stepback").hide();
}
if (platform_id == 'vcs') {
$("#dbg_timing").click(traceTiming).show();
}

116
src/worker/verilator2js.js Normal file
View File

@ -0,0 +1,116 @@
var moduleName, symsName;
function parseDecls(text, arr, name, bin, bout) {
var re = new RegExp(name + "(\\d+)[(](\\w+),(\\d+),(\\d+)[)]", 'gm');
var m;
while ((m = re.exec(text))) {
arr.push({
wordlen:parseInt(m[1]),
name:m[2],
len:parseInt(m[3]),
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++) {
m += "\tself." + o.ports[i].name + ";\n";
}
for (var i=0; i<o.signals.length; i++) {
m += "\tself." + o.signals[i].name + ";\n";
}
for (var i=0; i<o.funcs.length; i++) {
m += o.funcs[i];
}
//m += "\n}\n";
//m += "return " + o.name + ";\n";
return m;
}
function translateFunction(text) {
text = text.trim();
var funcname = text.match(/(\w+)/)[1];
text = text.replace(symsName + "* __restrict ", "");
text = text.replace(moduleName + "* __restrict vlTOPp VL_ATTR_UNUSED", "var vlTOPp");
text = text.replace(/VL_DEBUG_IF/g,"//VL_DEBUG_IF");
text = text.replace(/VL_SIG\d+[(](\w+),(\d+),(\d+)[)]/g, 'var $1');
text = text.replace(/\b->\b/g, ".");
text = text.replace('VL_INLINE_OPT', '');
text = text.replace(/[(]IData[)]/g, '');
text = text.replace(/\b(0x[0-9a-f]+)U/gi, '$1');
text = text.replace(/\b([0-9]+)U/gi, '$1');
text = text.replace(/\bQData /, 'var ');
text = text.replace(/\bbool /, '');
text = text.replace(/(\w+ = VL_RAND_RESET_I)/g, 'self.$1');
text = text.replace(/^#/gm, '//#');
text = text.replace(/VL_LIKELY/g, '!!');
text = text.replace(/VL_UNLIKELY/g, '!!');
text = text.replace(/Verilated::(\w+)Error/g, 'console.log');
return "function " + text + "\nself." + funcname + " = " + funcname + ";\n";
}
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);
var signals = [];
parseDecls(htext, signals, 'VL_SIG');
// parse cpp file
// split functions
var re_fnsplit = new RegExp("(?:void|QData) " + moduleName + "::");
var functexts = cpptext.split(re_fnsplit);
var funcs = [];
for (var i=4; i<functexts.length; i++) {
var fntxt = translateFunction(functexts[i]);
//console.log(fntxt);
funcs.push(fntxt);
}
return {
output:buildModule({
name:moduleName,
ports:ports,
signals:signals,
funcs:funcs,
}),
name:moduleName,
ports:ports,
signals:signals,
};
}
////
/*
incpp = "obj_dir/Vhvsync_generator.cpp"
inh = "obj_dir/Vhvsync_generator.h"
fs = require('fs')
fs.readFile(incpp, 'utf8', function (err,datacpp) {
fs.readFile(inh, 'utf8', function (err,datah) {
var modtext = translateVerilatorOutputToJS(datah, datacpp);
console.log(modtext);
var mod = new Function('base',modtext);
var gen = new mod(new VerilatorBase());
console.log(gen);
gen._ctor_var_reset();
var top = {TOPp:gen};
gen._eval_settle(top);
for (var i=0; i<1000000; i++)
gen._eval(top);
console.log(gen);
});
});
*/

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -80,6 +80,8 @@ var PLATFORM_PARAMS = {
cfgfile: 'neslib.cfg',
libargs: ['neslib.lib', 'nes.lib'],
},
'verilog': {
},
};
// shim out window and document objects for security
@ -1027,6 +1029,37 @@ function assembleNAKEN(code, platform) {
}
}
function compileVerilator(code, platform) {
loadWASM("verilator_bin");
load("verilator2js");
var errors = [];
var match_fn = makeErrorMatcher(errors, /%Error: main.v:(\d+): (.+)/, 1, 2);
var verilator_mod = verilator_bin({
wasmBinary:wasmBlob['verilator_bin'],
noInitialRun:true,
print:print_fn,
printErr:match_fn,
});
var FS = verilator_mod['FS'];
//setupFS(FS);
FS.writeFile("main.v", code);
starttime();
verilator_mod.callMain(["--cc", "-O2", "main.v"]);
endtime("compile");
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 rtn = translateVerilatorOutputToJS(h_file, cpp_file);
rtn.errors = errors;
rtn.lines = [];// TODO
rtn.intermediate = {listing:h_file + cpp_file};
return rtn;
} catch(e) {
return {errors:errors};
}
}
var TOOLS = {
'dasm': assembleDASM,
'acme': assembleACME,
@ -1038,6 +1071,7 @@ var TOOLS = {
'sdcc': compileSDCC,
'xasm6809': assembleXASM6809,
'naken': assembleNAKEN,
'verilator': compileVerilator,
}
var TOOL_PRELOADFS = {