mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2025-01-18 09:30:11 +00:00
started on .v files; framerate detect
This commit is contained in:
parent
07a0f97245
commit
014d659558
8
emsrc/verilator/verilator.txt
Normal file
8
emsrc/verilator/verilator.txt
Normal 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
|
@ -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
66
presets/verilog/hvsync.v
Normal 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
|
@ -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
126
src/platform/verilog.js
Normal 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;
|
35
src/ui.js
35
src/ui.js
@ -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
116
src/worker/verilator2js.js
Normal 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);
|
||||
});
|
||||
});
|
||||
*/
|
50
src/worker/verilator_bin.js
Normal file
50
src/worker/verilator_bin.js
Normal file
File diff suppressed because one or more lines are too long
14
src/worker/wasm/verilator_bin.js
Normal file
14
src/worker/wasm/verilator_bin.js
Normal file
File diff suppressed because one or more lines are too long
BIN
src/worker/wasm/verilator_bin.wasm
Normal file
BIN
src/worker/wasm/verilator_bin.wasm
Normal file
Binary file not shown.
@ -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 = {
|
||||
|
Loading…
x
Reference in New Issue
Block a user