mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-11-15 14:07:16 +00:00
verilog -> typescript, but why does loadState() make it slow with racing_game_cpu?
This commit is contained in:
parent
132147b1a4
commit
05f5b96256
@ -60,8 +60,8 @@ TODO:
|
||||
- links to external tools in ide
|
||||
- error msg when #link doesn't work
|
||||
- figure out folders for projects for real
|
||||
|
||||
On the website the additional grey spacing next to the program line numbers is not dynamically resized when the web browser window size is changed. Intentional?
|
||||
- verilog download rom
|
||||
- why loadState() on verilog kill perf?
|
||||
|
||||
|
||||
|
||||
|
@ -22,8 +22,10 @@ export interface CpuState {
|
||||
N,V,D,Z,C:boolean*/
|
||||
};
|
||||
export interface EmuState {
|
||||
c:CpuState, // CPU state
|
||||
b?:number[] // RAM (TODO: not for vcs)
|
||||
c?:CpuState, // CPU state
|
||||
b?:number[], // RAM (TODO: not for vcs)
|
||||
o?:{}, // verilog
|
||||
T?:number, // verilog
|
||||
};
|
||||
export interface EmuControlsState {
|
||||
}
|
||||
@ -107,6 +109,7 @@ export abstract class BasePlatform {
|
||||
abstract saveState() : EmuState;
|
||||
abstract pause() : void;
|
||||
abstract resume() : void;
|
||||
abstract advance(novideo? : boolean) : void;
|
||||
|
||||
setRecorder(recorder : EmuRecorder) : void {
|
||||
this.recorder = recorder;
|
||||
@ -129,7 +132,6 @@ export abstract class BaseDebugPlatform extends BasePlatform {
|
||||
|
||||
abstract getCPUState() : CpuState;
|
||||
abstract readAddress(addr:number) : number;
|
||||
abstract advance(novideo? : boolean) : void;
|
||||
|
||||
getDebugCallback() : DebugCondition {
|
||||
return this.debugCondition;
|
||||
|
@ -1,8 +1,9 @@
|
||||
"use strict";
|
||||
|
||||
import { Platform } from "../baseplatform";
|
||||
import { Platform, BasePlatform } from "../baseplatform";
|
||||
import { PLATFORMS, setKeyboardFromMap, AnimationTimer, RasterVideo, Keys, makeKeycodeMap } from "../emu";
|
||||
import { SampleAudio } from "../audio";
|
||||
import { safe_extend } from "../util";
|
||||
|
||||
var VERILOG_PRESETS = [
|
||||
{id:'clock_divider.v', name:'Clock Divider'},
|
||||
@ -55,109 +56,113 @@ var VERILOG_KEYCODE_MAP = makeKeycodeMap([
|
||||
[Keys.VK_7, 2, 0x10],
|
||||
]);
|
||||
|
||||
var vl_finished = false;
|
||||
var vl_stopped = false;
|
||||
// SIMULATOR STUFF (should be global)
|
||||
|
||||
// TODO: these have to be global
|
||||
export var vl_finished = false;
|
||||
export var vl_stopped = false;
|
||||
|
||||
var VL_UL = this.VL_UL = function(x) { return x|0; }
|
||||
var VL_ULL = this.VL_ULL = function(x) { return x|0; }
|
||||
var VL_TIME_Q = this.VL_TIME_Q = function() { return (new Date().getTime())|0; }
|
||||
export function VL_UL(x) { return x|0; }
|
||||
export function VL_ULL(x) { return x|0; }
|
||||
export function VL_TIME_Q() { return (new Date().getTime())|0; }
|
||||
|
||||
/// Return true if data[bit] set
|
||||
var VL_BITISSET_I = this.VL_BITISSET_I = function(data,bit) { return (data & (VL_UL(1)<<VL_UL(bit))); }
|
||||
export function VL_BITISSET_I(data,bit) { return (data & (VL_UL(1)<<VL_UL(bit))); }
|
||||
|
||||
var VL_EXTENDSIGN_I = this.VL_EXTENDSIGN_I = function(lbits, lhs) { return (-((lhs)&(VL_UL(1)<<(lbits-1)))); }
|
||||
export function VL_EXTENDSIGN_I(lbits, lhs) { return (-((lhs)&(VL_UL(1)<<(lbits-1)))); }
|
||||
|
||||
var VL_EXTEND_II = this.VL_EXTEND_II = function(obits,lbits,lhs) { return lhs; }
|
||||
export function VL_EXTEND_II(obits,lbits,lhs) { return lhs; }
|
||||
|
||||
var VL_EXTENDS_II = this.VL_EXTENDS_II = function(x,lbits,lhs) {
|
||||
export function VL_EXTENDS_II(x,lbits,lhs) {
|
||||
return VL_EXTENDSIGN_I(lbits,lhs) | lhs;
|
||||
}
|
||||
|
||||
var VL_EXTEND_II = this.VL_EXTEND_II = function(obits,lbits,lhs) { return lhs; }
|
||||
export function VL_NEGATE_I(x) { return -x; }
|
||||
|
||||
var VL_NEGATE_I = this.VL_NEGATE_I = function(x) { return -x; }
|
||||
|
||||
var VL_LTS_III = this.VL_LTS_III = function(x,lbits,y,lhs,rhs) {
|
||||
export function VL_LTS_III(x,lbits,y,lhs,rhs) {
|
||||
return (VL_EXTENDS_II(x,lbits,lhs) < VL_EXTENDS_II(x,lbits,rhs)) ? 1 : 0; }
|
||||
|
||||
var VL_GTS_III = this.VL_GTS_III = function(x,lbits,y,lhs,rhs) {
|
||||
export function VL_GTS_III(x,lbits,y,lhs,rhs) {
|
||||
return (VL_EXTENDS_II(x,lbits,lhs) > VL_EXTENDS_II(x,lbits,rhs)) ? 1 : 0; }
|
||||
|
||||
var VL_LTES_III = this.VL_LTES_III = function(x,lbits,y,lhs,rhs) {
|
||||
export function VL_LTES_III(x,lbits,y,lhs,rhs) {
|
||||
return (VL_EXTENDS_II(x,lbits,lhs) <= VL_EXTENDS_II(x,lbits,rhs)) ? 1 : 0; }
|
||||
|
||||
var VL_GTES_III = this.VL_GTES_III = function(x,lbits,y,lhs,rhs) {
|
||||
export function VL_GTES_III(x,lbits,y,lhs,rhs) {
|
||||
return (VL_EXTENDS_II(x,lbits,lhs) >= VL_EXTENDS_II(x,lbits,rhs)) ? 1 : 0; }
|
||||
|
||||
var VL_MODDIV_III = this.VL_MODDIV_III = function(lbits,lhs,rhs) {
|
||||
export function VL_MODDIV_III(lbits,lhs,rhs) {
|
||||
return (((rhs)==0)?0:(lhs)%(rhs)); }
|
||||
|
||||
var VL_MODDIVS_III = this.VL_MODDIVS_III = function(lbits,lhs,rhs) {
|
||||
export function VL_MODDIVS_III(lbits,lhs,rhs) {
|
||||
return (((rhs)==0)?0:(lhs)%(rhs)); }
|
||||
|
||||
var VL_REDXOR_32 = this.VL_REDXOR_32 = function(r) {
|
||||
export function VL_REDXOR_32(r) {
|
||||
r=(r^(r>>1)); r=(r^(r>>2)); r=(r^(r>>4)); r=(r^(r>>8)); r=(r^(r>>16));
|
||||
return r;
|
||||
}
|
||||
|
||||
var VL_WRITEF = this.VL_WRITEF = console.log; // TODO: $write
|
||||
export var VL_WRITEF = console.log; // TODO: $write
|
||||
|
||||
var vl_finish = this.vl_finish = function(filename,lineno,hier) {
|
||||
export function vl_finish(filename,lineno,hier) {
|
||||
console.log("Finished at " + filename + ":" + lineno, hier);
|
||||
vl_finished = true;
|
||||
}
|
||||
var vl_stop = this.vl_stop = function(filename,lineno,hier) {
|
||||
export function vl_stop(filename,lineno,hier) {
|
||||
console.log("Stopped at " + filename + ":" + lineno, hier);
|
||||
vl_stopped = true;
|
||||
}
|
||||
|
||||
var VL_RAND_RESET_I = this.VL_RAND_RESET_I = function(bits) { return 0 | Math.floor(Math.random() * (1<<bits)); }
|
||||
export function VL_RAND_RESET_I(bits) { return 0 | Math.floor(Math.random() * (1<<bits)); }
|
||||
|
||||
var VL_RANDOM_I = this.VL_RANDOM_I = function(bits) { return 0 | Math.floor(Math.random() * (1<<bits)); }
|
||||
export function VL_RANDOM_I(bits) { return 0 | Math.floor(Math.random() * (1<<bits)); }
|
||||
|
||||
// SIMULATOR BASE
|
||||
|
||||
//
|
||||
abstract class VerilatorBase {
|
||||
|
||||
function VerilatorBase() {
|
||||
totalTicks = 0;
|
||||
maxVclockLoop = 1;
|
||||
clk = 0;
|
||||
reset = 0;
|
||||
|
||||
//
|
||||
|
||||
var totalTicks = 0;
|
||||
|
||||
function vl_fatal(msg) {
|
||||
vl_fatal(msg:string) {
|
||||
console.log(msg);
|
||||
}
|
||||
|
||||
this.ticks = function() { return totalTicks; }
|
||||
this.setTicks = function(T) { totalTicks = T|0; }
|
||||
ticks() : number { return this.totalTicks; }
|
||||
setTicks(T:number) { this.totalTicks = T|0; }
|
||||
|
||||
this.__reset = function() {
|
||||
__reset() {
|
||||
if (this.reset !== undefined) {
|
||||
totalTicks = 0;
|
||||
this.totalTicks = 0;
|
||||
this.reset = 0;
|
||||
this.tick2();
|
||||
this.reset = 1;
|
||||
}
|
||||
}
|
||||
|
||||
this.__unreset = function() {
|
||||
__unreset() {
|
||||
if (this.reset !== undefined) {
|
||||
this.reset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
this.tick2 = function() {
|
||||
tick2() {
|
||||
this.clk = 0;
|
||||
this.eval();
|
||||
this.clk = 1;
|
||||
this.eval();
|
||||
}
|
||||
|
||||
abstract _eval(vlSymsp);
|
||||
abstract __Vm_didInit : boolean;
|
||||
abstract __Vm_activity : boolean;
|
||||
abstract _change_request(vlSymsp);
|
||||
abstract _eval_initial(vlSymsp);
|
||||
abstract _eval_settle(vlSymsp);
|
||||
|
||||
var vlSymsp = this; //{TOPp:this};
|
||||
var maxVclockLoop = 1;
|
||||
|
||||
this.eval = function() {
|
||||
eval() {
|
||||
let vlSymsp = this; //{TOPp:this};
|
||||
// Initialize
|
||||
if (!vlSymsp.__Vm_didInit)
|
||||
this._eval_initial_loop(vlSymsp);
|
||||
@ -170,16 +175,16 @@ function VerilatorBase() {
|
||||
vlSymsp.__Vm_activity = true;
|
||||
this._eval(vlSymsp);
|
||||
__Vchange = this._change_request(vlSymsp);
|
||||
if (++__VclockLoop > 100) { vl_fatal("Verilated model didn't converge"); }
|
||||
if (++__VclockLoop > 100) { this.vl_fatal("Verilated model didn't converge"); }
|
||||
}
|
||||
if (__VclockLoop > maxVclockLoop) {
|
||||
maxVclockLoop = __VclockLoop;
|
||||
console.log("Graph took " + maxVclockLoop + " iterations to stabilize");
|
||||
if (__VclockLoop > this.maxVclockLoop) {
|
||||
this.maxVclockLoop = __VclockLoop;
|
||||
console.log("Graph took " + this.maxVclockLoop + " iterations to stabilize");
|
||||
}
|
||||
totalTicks++;
|
||||
this.totalTicks++;
|
||||
}
|
||||
|
||||
this._eval_initial_loop = function(vlSymsp) {
|
||||
_eval_initial_loop(vlSymsp) {
|
||||
vlSymsp.TOPp = this;
|
||||
vlSymsp.__Vm_didInit = true;
|
||||
this._eval_initial(vlSymsp);
|
||||
@ -190,13 +195,16 @@ function VerilatorBase() {
|
||||
this._eval_settle(vlSymsp);
|
||||
this._eval(vlSymsp);
|
||||
__Vchange = this._change_request(vlSymsp);
|
||||
if (++__VclockLoop > 100) { vl_fatal("Verilated model didn't DC converge"); }
|
||||
if (++__VclockLoop > 100) { this.vl_fatal("Verilated model didn't DC converge"); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PLATFORM
|
||||
|
||||
var VerilogPlatform = function(mainElement, options) {
|
||||
var self = this;
|
||||
this.__proto__ = new (BasePlatform as any)();
|
||||
|
||||
var video, audio;
|
||||
var useAudio = false;
|
||||
var videoWidth = 292;
|
||||
@ -206,11 +214,17 @@ var VerilogPlatform = function(mainElement, options) {
|
||||
var gen;
|
||||
var cyclesPerFrame = (256+23+7+23)*262; // 4857480/60 Hz
|
||||
var current_output;
|
||||
|
||||
// control inputs
|
||||
var paddle_x = 0;
|
||||
var paddle_y = 0;
|
||||
var switches = [0,0,0];
|
||||
|
||||
// inspect feature
|
||||
var inspect_obj, inspect_sym;
|
||||
var inspect_data = new Uint32Array(videoWidth * videoHeight);
|
||||
|
||||
// for scope
|
||||
var scope_time_x = 0; // scope cursor
|
||||
var scope_x_offset = 0;
|
||||
var scope_y_offset = 0;
|
||||
@ -223,7 +237,6 @@ var VerilogPlatform = function(mainElement, options) {
|
||||
var scopeImageData;
|
||||
var sdata; // scope data
|
||||
var module_name;
|
||||
|
||||
var yposlist = [];
|
||||
var lasty = [];
|
||||
var lastval = [];
|
||||
@ -234,7 +247,12 @@ var VerilogPlatform = function(mainElement, options) {
|
||||
var mouse_pressed;
|
||||
var dirty = false;
|
||||
|
||||
this.getPresets = function() { return VERILOG_PRESETS; }
|
||||
// for virtual CRT
|
||||
var framex=0;
|
||||
var framey=0;
|
||||
var frameidx=0;
|
||||
var framehsync=false;
|
||||
var framevsync=false;
|
||||
|
||||
var RGBLOOKUP = [
|
||||
0xff222222,
|
||||
@ -256,6 +274,7 @@ var VerilogPlatform = function(mainElement, options) {
|
||||
];
|
||||
|
||||
var debugCond;
|
||||
var frameRate = 0;
|
||||
|
||||
function vidtick() {
|
||||
gen.tick2();
|
||||
@ -265,7 +284,168 @@ var VerilogPlatform = function(mainElement, options) {
|
||||
debugCond = null;
|
||||
}
|
||||
|
||||
function updateInspectionFrame() {
|
||||
function clamp(minv,maxv,v) {
|
||||
return (v < minv) ? minv : (v > maxv) ? maxv : v;
|
||||
}
|
||||
|
||||
function shadowText(ctx, txt, x, y) {
|
||||
ctx.shadowColor = "black";
|
||||
ctx.shadowBlur = 0;
|
||||
ctx.shadowOffsetY = -1;
|
||||
ctx.shadowOffsetX = 0;
|
||||
ctx.fillText(txt, x, y);
|
||||
ctx.shadowOffsetY = 1;
|
||||
ctx.shadowOffsetX = 0;
|
||||
ctx.fillText(txt, x, y);
|
||||
ctx.shadowOffsetY = 0;
|
||||
ctx.shadowOffsetX = -1;
|
||||
ctx.fillText(txt, x, y);
|
||||
ctx.shadowOffsetY = 0;
|
||||
ctx.shadowOffsetX = 1;
|
||||
ctx.fillText(txt, x, y);
|
||||
ctx.shadowOffsetX = 0;
|
||||
}
|
||||
|
||||
// inner Platform class
|
||||
|
||||
class _VerilogPlatform extends BasePlatform {
|
||||
|
||||
getPresets() { return VERILOG_PRESETS; }
|
||||
|
||||
start() {
|
||||
video = new RasterVideo(mainElement,videoWidth,videoHeight);
|
||||
video.create();
|
||||
var ctx = video.getContext();
|
||||
ctx.font = "8px TinyFont";
|
||||
ctx.fillStyle = "white";
|
||||
ctx.textAlign = "left";
|
||||
setKeyboardFromMap(video, switches, VERILOG_KEYCODE_MAP);
|
||||
var vcanvas = $(video.canvas);
|
||||
vcanvas.mousemove( (e) => {
|
||||
var new_x = Math.floor(e.offsetX * video.canvas.width / vcanvas.width() - 20);
|
||||
var new_y = Math.floor(e.offsetY * video.canvas.height / vcanvas.height() - 20);
|
||||
if (mouse_pressed) {
|
||||
scope_y_offset = clamp(Math.min(0,-scope_max_y+videoHeight), 0, scope_y_offset + new_y - paddle_y);
|
||||
scope_time_x = Math.floor(e.offsetX * video.canvas.width / vcanvas.width() - 16);
|
||||
dirty = true;
|
||||
this.refreshFrame();
|
||||
}
|
||||
paddle_x = clamp(8, 240, new_x);
|
||||
paddle_y = clamp(8, 240, new_y);
|
||||
});
|
||||
vcanvas.mousedown( (e) => {
|
||||
scope_time_x = Math.floor(e.offsetX * video.canvas.width / vcanvas.width() - 16);
|
||||
mouse_pressed = true;
|
||||
//if (e.target.setCapture) e.target.setCapture(); // TODO: pointer capture
|
||||
dirty = true;
|
||||
this.refreshFrame();
|
||||
});
|
||||
vcanvas.mouseup( (e) => {
|
||||
mouse_pressed = false;
|
||||
//if (e.target.setCapture) e.target.releaseCapture(); // TODO: pointer capture
|
||||
dirty = true;
|
||||
this.refreshFrame();
|
||||
});
|
||||
vcanvas.keydown( (e) => {
|
||||
switch (e.keyCode) {
|
||||
case 37: scope_time_x--; dirty=true; this.refreshFrame(); break;
|
||||
case 39: scope_time_x++; dirty=true; this.refreshFrame(); break;
|
||||
}
|
||||
});
|
||||
idata = video.getFrameData();
|
||||
timerCallback = () => {
|
||||
if (!this.isRunning())
|
||||
return;
|
||||
gen.switches = switches[0];
|
||||
this.updateFrame();
|
||||
};
|
||||
trace_buffer = new Uint32Array(0x10000);
|
||||
this.setFrameRate(60);
|
||||
}
|
||||
|
||||
setGenInputs() {
|
||||
useAudio = (audio != null);
|
||||
//TODO debugCond = this.getDebugCallback();
|
||||
gen.switches_p1 = switches[0];
|
||||
gen.switches_p2 = switches[1];
|
||||
gen.switches_gen = switches[2];
|
||||
}
|
||||
|
||||
updateVideoFrame() {
|
||||
this.setGenInputs();
|
||||
var fps = this.getFrameRate();
|
||||
// darken the previous frame?
|
||||
if (fps < 45) {
|
||||
var mask = fps > 5 ? 0xe7ffffff : 0x7fdddddd;
|
||||
for (var i=0; i<idata.length; i++)
|
||||
idata[i] &= mask;
|
||||
}
|
||||
// paint into frame, synched with vsync if full speed
|
||||
var sync = fps > 45;
|
||||
var trace = fps < 0.02;
|
||||
this.updateVideoFrameCycles(cyclesPerFrame * fps/60 + 1, sync, trace);
|
||||
//if (trace) displayTraceBuffer();
|
||||
//this.restartDebugState();
|
||||
gen.__unreset();
|
||||
this.refreshVideoFrame();
|
||||
}
|
||||
|
||||
// TODO: merge with prev func
|
||||
advance(novideo : boolean) {
|
||||
this.setGenInputs();
|
||||
this.updateVideoFrameCycles(cyclesPerFrame, true, false);
|
||||
gen.__unreset();
|
||||
if (!novideo) {
|
||||
this.refreshVideoFrame();
|
||||
}
|
||||
}
|
||||
|
||||
refreshVideoFrame() {
|
||||
this.updateInspectionFrame();
|
||||
this.updateAnimateScope();
|
||||
this.updateInspectionPostFrame();
|
||||
}
|
||||
|
||||
updateFrame() {
|
||||
if (!gen) return;
|
||||
if (gen.vsync !== undefined && gen.hsync !== undefined && gen.rgb !== undefined)
|
||||
this.updateVideoFrame();
|
||||
else
|
||||
this.updateScopeFrame();
|
||||
}
|
||||
|
||||
refreshFrame() {
|
||||
if (!gen) return;
|
||||
if (gen.vsync !== undefined && gen.hsync !== undefined && gen.rgb !== undefined)
|
||||
this.refreshVideoFrame();
|
||||
else
|
||||
this.refreshScopeOverlay(trace_ports);
|
||||
}
|
||||
|
||||
updateAnimateScope() {
|
||||
var fps = this.getFrameRate();
|
||||
var trace = fps < 0.02;
|
||||
var ctx = video.getContext();
|
||||
if (scope_a > 0.01) {
|
||||
ctx.fillStyle = "black";
|
||||
ctx.fillRect(0, 0, videoWidth, videoHeight);
|
||||
var vidyoffset = Math.round(scope_a*(-framey+videoHeight/6));
|
||||
video.updateFrame(0, vidyoffset, 0, 0, videoWidth, videoHeight);
|
||||
ctx.fillStyle = "white";
|
||||
ctx.fillRect(framex, framey+vidyoffset, 1, 1);
|
||||
scope_index_offset = (trace_index - trace_signals.length*scopeWidth + trace_buffer.length) % trace_buffer.length;
|
||||
scope_x_offset = 0;
|
||||
this.refreshScopeOverlay(trace_signals);
|
||||
} else {
|
||||
video.updateFrame();
|
||||
scope_index_offset = 0;
|
||||
}
|
||||
// smooth transition
|
||||
scope_a = scope_a * 0.9 + (trace?1.0:0.0) * 0.1;
|
||||
scope_y_top = (1 - scope_a*0.7) * videoHeight - (1 - scope_a) * scope_y_offset;
|
||||
}
|
||||
|
||||
updateInspectionFrame() {
|
||||
useAudio = false;
|
||||
if (inspect_obj && inspect_sym) {
|
||||
var COLOR_BIT_OFF = 0xffff6666;
|
||||
@ -280,7 +460,7 @@ var VerilogPlatform = function(mainElement, options) {
|
||||
}
|
||||
}
|
||||
|
||||
function updateInspectionPostFrame() {
|
||||
updateInspectionPostFrame() {
|
||||
if (inspect_obj && inspect_sym) {
|
||||
var ctx = video.getContext();
|
||||
var val = inspect_data[inspect_data.length-1];
|
||||
@ -291,17 +471,12 @@ var VerilogPlatform = function(mainElement, options) {
|
||||
}
|
||||
}
|
||||
|
||||
var framex=0;
|
||||
var framey=0;
|
||||
var frameidx=0;
|
||||
var framehsync=false;
|
||||
var framevsync=false;
|
||||
|
||||
function updateVideoFrameCycles(ncycles, sync, trace) {
|
||||
updateVideoFrameCycles(ncycles, sync, trace) {
|
||||
ncycles |= 0;
|
||||
var inspect = inspect_obj && inspect_sym;
|
||||
while (ncycles--) {
|
||||
if (trace) snapshotTrace(true);
|
||||
if (trace)
|
||||
this.snapshotTrace(true);
|
||||
vidtick();
|
||||
if (framex++ < videoWidth) {
|
||||
if (framey < videoHeight) {
|
||||
@ -330,80 +505,15 @@ var VerilogPlatform = function(mainElement, options) {
|
||||
} else {
|
||||
var wasvsync = framevsync;
|
||||
framevsync = false;
|
||||
if (sync && wasvsync) return; // exit when vsync ends
|
||||
if (sync && wasvsync) {
|
||||
this.updateRecorder();
|
||||
return; // exit when vsync ends
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function updateVideoFrame() {
|
||||
useAudio = (audio != null);
|
||||
debugCond = self.getDebugCallback();
|
||||
gen.switches_p1 = switches[0];
|
||||
gen.switches_p2 = switches[1];
|
||||
gen.switches_gen = switches[2];
|
||||
var fps = self.getFrameRate();
|
||||
// darken the previous frame?
|
||||
if (fps < 45) {
|
||||
var mask = fps > 5 ? 0xe7ffffff : 0x7fdddddd;
|
||||
for (var i=0; i<idata.length; i++)
|
||||
idata[i] &= mask;
|
||||
}
|
||||
// paint into frame, synched with vsync if full speed
|
||||
var sync = fps > 45;
|
||||
var trace = fps < 0.02;
|
||||
updateVideoFrameCycles(cyclesPerFrame * fps/60 + 1, sync, trace);
|
||||
//if (trace) displayTraceBuffer();
|
||||
self.restartDebugState();
|
||||
gen.__unreset();
|
||||
refreshVideoFrame();
|
||||
}
|
||||
|
||||
function refreshVideoFrame() {
|
||||
updateInspectionFrame();
|
||||
updateAnimateScope();
|
||||
updateInspectionPostFrame();
|
||||
}
|
||||
|
||||
function updateFrame() {
|
||||
if (!gen) return;
|
||||
if (gen.vsync !== undefined && gen.hsync !== undefined && gen.rgb !== undefined)
|
||||
updateVideoFrame();
|
||||
else
|
||||
updateScopeFrame();
|
||||
}
|
||||
|
||||
function refreshFrame() {
|
||||
if (!gen) return;
|
||||
if (gen.vsync !== undefined && gen.hsync !== undefined && gen.rgb !== undefined)
|
||||
refreshVideoFrame();
|
||||
else
|
||||
refreshScopeOverlay(trace_ports);
|
||||
}
|
||||
|
||||
function updateAnimateScope() {
|
||||
var fps = self.getFrameRate();
|
||||
var trace = fps < 0.02;
|
||||
var ctx = video.getContext();
|
||||
if (scope_a > 0.01) {
|
||||
ctx.fillStyle = "black";
|
||||
ctx.fillRect(0, 0, videoWidth, videoHeight);
|
||||
var vidyoffset = Math.round(scope_a*(-framey+videoHeight/6));
|
||||
video.updateFrame(0, vidyoffset, 0, 0, videoWidth, videoHeight);
|
||||
ctx.fillStyle = "white";
|
||||
ctx.fillRect(framex, framey+vidyoffset, 1, 1);
|
||||
scope_index_offset = (trace_index - trace_signals.length*scopeWidth + trace_buffer.length) % trace_buffer.length;
|
||||
scope_x_offset = 0;
|
||||
refreshScopeOverlay(trace_signals);
|
||||
} else {
|
||||
video.updateFrame();
|
||||
scope_index_offset = 0;
|
||||
}
|
||||
// smooth transition
|
||||
scope_a = scope_a * 0.9 + (trace?1.0:0.0) * 0.1;
|
||||
scope_y_top = (1 - scope_a*0.7) * videoHeight - (1 - scope_a) * scope_y_offset;
|
||||
}
|
||||
|
||||
function displayTraceBuffer() {
|
||||
displayTraceBuffer() {
|
||||
var skip = trace_signals.length;
|
||||
var src = trace_index;
|
||||
for (var dest=0; dest<idata.length; dest+=videoWidth) {
|
||||
@ -415,7 +525,7 @@ var VerilogPlatform = function(mainElement, options) {
|
||||
}
|
||||
}
|
||||
|
||||
function snapshotTrace(signals) {
|
||||
snapshotTrace(signals) {
|
||||
var arr = signals ? trace_signals : trace_ports;
|
||||
for (var i=0; i<arr.length; i++) {
|
||||
var v = arr[i];
|
||||
@ -425,44 +535,26 @@ var VerilogPlatform = function(mainElement, options) {
|
||||
}
|
||||
}
|
||||
|
||||
function fillTraceBuffer(count) {
|
||||
fillTraceBuffer(count) {
|
||||
var max_index = Math.min(trace_buffer.length - trace_ports.length, trace_index + count);
|
||||
while (trace_index < max_index) {
|
||||
gen.clk ^= 1;
|
||||
gen.eval();
|
||||
snapshotTrace(false);
|
||||
this.snapshotTrace(false);
|
||||
dirty = true;
|
||||
}
|
||||
gen.__unreset();
|
||||
}
|
||||
|
||||
function shadowText(ctx, txt, x, y) {
|
||||
ctx.shadowColor = "black";
|
||||
ctx.shadowBlur = 0;
|
||||
ctx.shadowOffsetY = -1;
|
||||
ctx.shadowOffsetX = 0;
|
||||
ctx.fillText(txt, x, y);
|
||||
ctx.shadowOffsetY = 1;
|
||||
ctx.shadowOffsetX = 0;
|
||||
ctx.fillText(txt, x, y);
|
||||
ctx.shadowOffsetY = 0;
|
||||
ctx.shadowOffsetX = -1;
|
||||
ctx.fillText(txt, x, y);
|
||||
ctx.shadowOffsetY = 0;
|
||||
ctx.shadowOffsetX = 1;
|
||||
ctx.fillText(txt, x, y);
|
||||
ctx.shadowOffsetX = 0;
|
||||
}
|
||||
|
||||
function updateScopeFrame() {
|
||||
fillTraceBuffer(Math.floor(videoWidth/4) * trace_ports.length);
|
||||
updateScopeFrame() {
|
||||
this.fillTraceBuffer(Math.floor(videoWidth/4) * trace_ports.length);
|
||||
if (!dirty) return;
|
||||
dirty = false;
|
||||
scope_y_top = 0;
|
||||
refreshScopeOverlay(trace_ports);
|
||||
this.refreshScopeOverlay(trace_ports);
|
||||
}
|
||||
|
||||
function refreshScopeOverlay(arr) {
|
||||
refreshScopeOverlay(arr) {
|
||||
if (!sdata) {
|
||||
scopeImageData = video.getContext().createImageData(scopeWidth,scopeHeight);
|
||||
sdata = new Uint32Array(scopeImageData.data.buffer);
|
||||
@ -540,62 +632,7 @@ var VerilogPlatform = function(mainElement, options) {
|
||||
}
|
||||
}
|
||||
|
||||
function clamp(minv,maxv,v) {
|
||||
return (v < minv) ? minv : (v > maxv) ? maxv : v;
|
||||
}
|
||||
|
||||
this.start = function() {
|
||||
video = new RasterVideo(mainElement,videoWidth,videoHeight);
|
||||
video.create();
|
||||
var ctx = video.getContext();
|
||||
ctx.font = "8px TinyFont";
|
||||
ctx.fillStyle = "white";
|
||||
ctx.textAlign = "left";
|
||||
setKeyboardFromMap(video, switches, VERILOG_KEYCODE_MAP);
|
||||
var vcanvas = $(video.canvas);
|
||||
vcanvas.mousemove(function(e) {
|
||||
var new_x = Math.floor(e.offsetX * video.canvas.width / vcanvas.width() - 20);
|
||||
var new_y = Math.floor(e.offsetY * video.canvas.height / vcanvas.height() - 20);
|
||||
if (mouse_pressed) {
|
||||
scope_y_offset = clamp(Math.min(0,-scope_max_y+videoHeight), 0, scope_y_offset + new_y - paddle_y);
|
||||
scope_time_x = Math.floor(e.offsetX * video.canvas.width / vcanvas.width() - 16);
|
||||
dirty = true;
|
||||
refreshFrame();
|
||||
}
|
||||
paddle_x = clamp(8, 240, new_x);
|
||||
paddle_y = clamp(8, 240, new_y);
|
||||
});
|
||||
vcanvas.mousedown(function(e) {
|
||||
scope_time_x = Math.floor(e.offsetX * video.canvas.width / vcanvas.width() - 16);
|
||||
mouse_pressed = true;
|
||||
//if (e.target.setCapture) e.target.setCapture(); // TODO: pointer capture
|
||||
dirty = true;
|
||||
refreshFrame();
|
||||
});
|
||||
vcanvas.mouseup(function(e) {
|
||||
mouse_pressed = false;
|
||||
//if (e.target.setCapture) e.target.releaseCapture(); // TODO: pointer capture
|
||||
dirty = true;
|
||||
refreshFrame();
|
||||
});
|
||||
vcanvas.keydown(function(e) {
|
||||
switch (e.keyCode) {
|
||||
case 37: scope_time_x--; dirty=true; refreshFrame(); break;
|
||||
case 39: scope_time_x++; dirty=true; refreshFrame(); break;
|
||||
}
|
||||
});
|
||||
idata = video.getFrameData();
|
||||
timerCallback = function() {
|
||||
if (!self.isRunning())
|
||||
return;
|
||||
gen.switches = switches[0];
|
||||
updateFrame();
|
||||
};
|
||||
trace_buffer = new Uint32Array(0x10000);
|
||||
self.setFrameRate(60);
|
||||
}
|
||||
|
||||
this.printErrorCodeContext = function(e, code) {
|
||||
printErrorCodeContext(e, code) {
|
||||
if (e.lineNumber && e.message) {
|
||||
var lines = code.split('\n');
|
||||
var s = e.message + '\n';
|
||||
@ -608,7 +645,7 @@ var VerilogPlatform = function(mainElement, options) {
|
||||
}
|
||||
}
|
||||
|
||||
this.loadROM = function(title, output) {
|
||||
loadROM(title, output) {
|
||||
var mod;
|
||||
if (output.code) {
|
||||
// is code identical?
|
||||
@ -621,8 +658,8 @@ var VerilogPlatform = function(mainElement, options) {
|
||||
throw e;
|
||||
}
|
||||
// compile Verilog code
|
||||
var base = new VerilatorBase();
|
||||
gen = new mod(base);
|
||||
var base = new (VerilatorBase as any)();
|
||||
gen = new mod();
|
||||
//$.extend(gen, base);
|
||||
gen.__proto__ = base;
|
||||
current_output = output;
|
||||
@ -647,37 +684,35 @@ var VerilogPlatform = function(mainElement, options) {
|
||||
this.reset();
|
||||
}
|
||||
// restart audio
|
||||
restartAudio();
|
||||
this.restartAudio();
|
||||
}
|
||||
|
||||
function restartAudio() {
|
||||
restartAudio() {
|
||||
// stop/start audio
|
||||
var hasAudio = gen && gen.spkr !== undefined && frameRate > 1;
|
||||
if (audio && !hasAudio) {
|
||||
audio.stop();
|
||||
audio = null;
|
||||
} else if (!audio && hasAudio) {
|
||||
audio = new SampleAudio(cyclesPerFrame * self.getFrameRate());
|
||||
if (self.isRunning())
|
||||
audio = new SampleAudio(cyclesPerFrame * this.getFrameRate());
|
||||
if (this.isRunning())
|
||||
audio.start();
|
||||
}
|
||||
}
|
||||
|
||||
this.isRunning = function() {
|
||||
isRunning() {
|
||||
return timer && timer.isRunning();
|
||||
}
|
||||
this.pause = function() {
|
||||
pause() {
|
||||
timer.stop();
|
||||
if (audio) audio.stop();
|
||||
}
|
||||
this.resume = function() {
|
||||
resume() {
|
||||
timer.start();
|
||||
if (audio) audio.start();
|
||||
}
|
||||
|
||||
var frameRate = 0;
|
||||
|
||||
this.setFrameRate = function(rateHz) {
|
||||
setFrameRate(rateHz) {
|
||||
frameRate = rateHz;
|
||||
var fps = Math.min(60, rateHz*cyclesPerFrame);
|
||||
if (!timer || timer.frameRate != fps) {
|
||||
@ -690,33 +725,33 @@ var VerilogPlatform = function(mainElement, options) {
|
||||
audio.stop();
|
||||
audio = null;
|
||||
}
|
||||
restartAudio();
|
||||
}
|
||||
this.getFrameRate = function() { return frameRate; }
|
||||
this.restartAudio();
|
||||
}
|
||||
getFrameRate() { return frameRate; }
|
||||
|
||||
this.poweron = function() {
|
||||
poweron() {
|
||||
gen._ctor_var_reset();
|
||||
this.reset();
|
||||
}
|
||||
this.reset = function() {
|
||||
reset() {
|
||||
gen.__reset();
|
||||
trace_index = scope_x_offset = 0;
|
||||
if (trace_buffer) trace_buffer.fill(0);
|
||||
dirty = true;
|
||||
if (video) video.setRotate(gen.rotate ? -90 : 0);
|
||||
}
|
||||
this.tick = function() {
|
||||
tick() {
|
||||
gen.tick2();
|
||||
}
|
||||
this.getToolForFilename = function(fn) {
|
||||
getToolForFilename(fn) {
|
||||
if (fn.endsWith("asm"))
|
||||
return "jsasm";
|
||||
else
|
||||
return "verilator";
|
||||
}
|
||||
this.getDefaultExtension = function() { return ".v"; };
|
||||
getDefaultExtension() { return ".v"; };
|
||||
|
||||
this.inspect = function(name) {
|
||||
inspect(name) {
|
||||
if (!gen) return;
|
||||
if (name && !name.match(/^\w+$/)) return;
|
||||
var val = gen[name];
|
||||
@ -739,114 +774,40 @@ var VerilogPlatform = function(mainElement, options) {
|
||||
|
||||
// DEBUGGING
|
||||
|
||||
this.saveState = function() {
|
||||
return {T:gen.ticks(), o:$.extend(true, {}, gen)};
|
||||
// TODO: bind() a function to avoid depot?
|
||||
saveState() {
|
||||
var state = {
|
||||
T:gen.ticks(),
|
||||
o:safe_extend(true, {}, gen)
|
||||
};
|
||||
state.o.TOPp = null;
|
||||
return state;
|
||||
}
|
||||
this.loadState = function(state) {
|
||||
gen = $.extend(true, gen, state.o);
|
||||
loadState(state) {
|
||||
gen = safe_extend(true, gen, state.o);
|
||||
gen.setTicks(state.T);
|
||||
gen.TOPp = gen;
|
||||
//console.log(gen, state.o);
|
||||
}
|
||||
saveControlsState() {
|
||||
return {
|
||||
p1x: paddle_x,
|
||||
p1y: paddle_y,
|
||||
sw0: switches[0],
|
||||
sw1: switches[1],
|
||||
sw2: switches[2],
|
||||
};
|
||||
}
|
||||
loadControlsState(state) {
|
||||
paddle_x = state.p1x;
|
||||
paddle_y = state.p1y;
|
||||
switches[0] = state.sw0;
|
||||
switches[1] = state.sw1;
|
||||
switches[2] = state.sw2;
|
||||
}
|
||||
|
||||
var onBreakpointHit;
|
||||
var debugCondition;
|
||||
var debugSavedState = null;
|
||||
var debugBreakState = null;
|
||||
var debugTargetClock = 0;
|
||||
|
||||
this.setDebugCondition = function(debugCond) {
|
||||
if (debugSavedState) {
|
||||
this.loadState(debugSavedState);
|
||||
} else {
|
||||
debugSavedState = this.saveState();
|
||||
}
|
||||
debugCondition = debugCond;
|
||||
debugBreakState = null;
|
||||
this.resume();
|
||||
}
|
||||
this.restartDebugState = function() {
|
||||
if (debugCondition && !debugBreakState) {
|
||||
debugSavedState = this.saveState();
|
||||
if (debugTargetClock > 0)
|
||||
debugTargetClock -= debugSavedState.T;
|
||||
debugSavedState.T = 0;
|
||||
this.loadState(debugSavedState);
|
||||
}
|
||||
}
|
||||
this.getDebugCallback = function() {
|
||||
return debugCondition;
|
||||
}
|
||||
this.setupDebug = function(callback) {
|
||||
onBreakpointHit = callback;
|
||||
}
|
||||
this.clearDebug = function() {
|
||||
debugSavedState = null;
|
||||
debugBreakState = null;
|
||||
debugTargetClock = 0;
|
||||
onBreakpointHit = null;
|
||||
debugCondition = null;
|
||||
}
|
||||
this.breakpointHit = function(targetClock) {
|
||||
debugTargetClock = targetClock;
|
||||
debugBreakState = this.saveState();
|
||||
console.log("Breakpoint at clk", debugBreakState.T);
|
||||
this.pause();
|
||||
if (onBreakpointHit) {
|
||||
onBreakpointHit(debugBreakState);
|
||||
}
|
||||
}
|
||||
this.wasBreakpointHit = function() {
|
||||
return debugBreakState != null;
|
||||
}
|
||||
this.step = function() {
|
||||
var self = this;
|
||||
this.setDebugCondition(function() {
|
||||
if (gen.ticks() > debugTargetClock) {
|
||||
self.breakpointHit(gen.ticks());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
this.runToVsync = function() {
|
||||
var self = this;
|
||||
this.setDebugCondition(function() {
|
||||
if (gen.vsync && gen.ticks() > debugTargetClock+2000) {
|
||||
self.breakpointHit(gen.ticks());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
this.stepBack = function() {
|
||||
var self = this;
|
||||
var prevState;
|
||||
var prevClock;
|
||||
this.setDebugCondition(function() {
|
||||
var debugClock = gen.ticks();
|
||||
if (debugClock >= debugTargetClock && prevState) {
|
||||
self.loadState(prevState);
|
||||
self.breakpointHit(prevClock);
|
||||
return true;
|
||||
} else if (debugClock >= debugTargetClock-2 && debugClock < debugTargetClock) {
|
||||
prevState = self.saveState();
|
||||
prevClock = debugClock;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
this.runEval = function(evalfunc) {
|
||||
var self = this;
|
||||
this.setDebugCondition(function() {
|
||||
if (gen.ticks() > debugTargetClock) {
|
||||
if (evalfunc(gen)) {
|
||||
self.breakpointHit(gen.ticks());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
} // end of inner class
|
||||
return new _VerilogPlatform();
|
||||
};
|
||||
|
||||
////////////////
|
||||
|
13
src/ui.ts
13
src/ui.ts
@ -366,12 +366,17 @@ function _revertFile(e) {
|
||||
}
|
||||
|
||||
function _downloadROMImage(e) {
|
||||
if (current_output == null) { // TODO
|
||||
alert("Please fix errors before downloading ROM.");
|
||||
if (current_output == null) {
|
||||
alert("Please finish compiling with no errors before downloading ROM.");
|
||||
return true;
|
||||
}
|
||||
var blob = new Blob([current_output], {type: "application/octet-stream"});
|
||||
saveAs(blob, getCurrentMainFilename()+".rom");
|
||||
if (current_output.code) { // TODO
|
||||
var blob = new Blob([current_output.code], {type: "text/plain"});
|
||||
saveAs(blob, getCurrentMainFilename()+".js");
|
||||
} else {
|
||||
var blob = new Blob([current_output], {type: "application/octet-stream"});
|
||||
saveAs(blob, getCurrentMainFilename()+".rom");
|
||||
}
|
||||
}
|
||||
|
||||
function _downloadSourceFile(e) {
|
||||
|
24
src/util.ts
24
src/util.ts
@ -336,3 +336,27 @@ export function compressLZG(em_module, inBuffer:number[], levelArg?:boolean) : U
|
||||
em_module._free(outPtr);
|
||||
return outBuffer;
|
||||
}
|
||||
|
||||
// only does primitives, 1D arrays and no recursion
|
||||
export function safe_extend(deep, dest, src) {
|
||||
// TODO: deep ignored
|
||||
for (var key in src) {
|
||||
var val = src[key];
|
||||
var type = typeof(val);
|
||||
if (val === null || type == 'undefined') {
|
||||
dest[key] = val;
|
||||
} else if (type == 'function') {
|
||||
// ignore function
|
||||
} else if (type == 'object') {
|
||||
if (val['slice']) { // array?
|
||||
dest[key] = val.slice();
|
||||
} else {
|
||||
// ignore object
|
||||
}
|
||||
} else {
|
||||
dest[key] = val;
|
||||
}
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
@ -65,21 +65,20 @@ function parseDecls(text:string, arr:V2JS_Var[], name:string, bin?:boolean, bout
|
||||
|
||||
function buildModule(o : V2JS_Code) : string {
|
||||
var m = '"use strict";\n';
|
||||
m += '\tvar self = this;\n';
|
||||
for (var i=0; i<o.ports.length; i++) {
|
||||
m += "\tself." + o.ports[i].name + ";\n";
|
||||
m += "\tthis." + o.ports[i].name + ";\n";
|
||||
}
|
||||
for (var i=0; i<o.signals.length; i++) {
|
||||
var sig = o.signals[i];
|
||||
if (sig.arrdim) {
|
||||
if (sig.arrdim.length == 1) {
|
||||
m += "\tvar " + sig.name + " = self." + sig.name + " = [];\n";
|
||||
m += "\tvar " + sig.name + " = this." + sig.name + " = [];\n";
|
||||
} else if (sig.arrdim.length == 2) {
|
||||
m += "\tvar " + sig.name + " = self." + sig.name + " = [];\n";
|
||||
m += "\tvar " + sig.name + " = this." + sig.name + " = [];\n";
|
||||
m += "\tfor(var i=0; i<" + sig.arrdim[0] + "; i++) { " + sig.name + "[i] = []; }\n";
|
||||
}
|
||||
} else {
|
||||
m += "\tself." + sig.name + ";\n";
|
||||
m += "\tthis." + sig.name + ";\n";
|
||||
}
|
||||
}
|
||||
for (var i=0; i<o.funcs.length; i++) {
|
||||
@ -121,16 +120,16 @@ function translateFunction(text : string) : string {
|
||||
text = text.replace(/\bQData /g, 'var ');
|
||||
text = text.replace(/\bbool /g, '');
|
||||
text = text.replace(/\bint /g, 'var ');
|
||||
text = text.replace(/(\w+ = VL_RAND_RESET_)/g, 'self.$1'); // TODO?
|
||||
//text = text.replace(/^\s*(\w+ = \d+;)/gm, 'self.$1'); // TODO?
|
||||
//text = text.replace(/(\w+\[\w+\] = VL_RAND_RESET_I)/g, 'self.$1');
|
||||
text = text.replace(/(\w+ = VL_RAND_RESET_)/g, 'this.$1'); // TODO?
|
||||
//text = text.replace(/^\s*(\w+ = \d+;)/gm, 'this.$1'); // TODO?
|
||||
//text = text.replace(/(\w+\[\w+\] = VL_RAND_RESET_I)/g, 'this.$1');
|
||||
text = text.replace(/^#/gm, '//#');
|
||||
text = text.replace(/VL_LIKELY/g, '!!');
|
||||
text = text.replace(/VL_UNLIKELY/g, '!!');
|
||||
//[%0t] %Error: scoreboard.v:53: Assertion failed in %Nscoreboard_top.scoreboard_gen: reset 64 -935359306 Vscoreboard_top
|
||||
text = text.replace(/Verilated::(\w+)Error/g, 'console.log');
|
||||
text = text.replace(/vlSymsp.name[(][)]/g, '"'+moduleName+'"');
|
||||
return "function " + text + "\nself." + funcname + " = " + funcname + ";\n";
|
||||
return "function " + text + "\nthis." + funcname + " = " + funcname + ";\n";
|
||||
}
|
||||
|
||||
function translateStaticVars(text : string) : string {
|
||||
|
@ -456,7 +456,6 @@ var re_crlf = /\r?\n/;
|
||||
|
||||
function parseListing(code, lineMatch, iline, ioffset, iinsns) {
|
||||
var lines = [];
|
||||
origin |= 0;
|
||||
for (var line of code.split(re_crlf)) {
|
||||
var linem = lineMatch.exec(line);
|
||||
if (linem && linem[1]) {
|
||||
@ -466,7 +465,7 @@ function parseListing(code, lineMatch, iline, ioffset, iinsns) {
|
||||
if (insns) {
|
||||
lines.push({
|
||||
line:linenum,
|
||||
offset:offset + origin,
|
||||
offset:offset,
|
||||
insns:insns,
|
||||
});
|
||||
}
|
||||
@ -475,10 +474,9 @@ function parseListing(code, lineMatch, iline, ioffset, iinsns) {
|
||||
return lines;
|
||||
}
|
||||
|
||||
function parseSourceLines(code, lineMatch, offsetMatch, origin) {
|
||||
function parseSourceLines(code, lineMatch, offsetMatch) {
|
||||
var lines = [];
|
||||
var lastlinenum = 0;
|
||||
origin |= 0;
|
||||
for (var line of code.split(re_crlf)) {
|
||||
var linem = lineMatch.exec(line);
|
||||
if (linem && linem[1]) {
|
||||
@ -489,7 +487,7 @@ function parseSourceLines(code, lineMatch, offsetMatch, origin) {
|
||||
var offset = parseInt(linem[1], 16);
|
||||
lines.push({
|
||||
line:lastlinenum,
|
||||
offset:offset + origin,
|
||||
offset:offset,
|
||||
});
|
||||
lastlinenum = 0;
|
||||
}
|
||||
|
@ -15,10 +15,17 @@ function loadPlatform(msg) {
|
||||
//console.log(msg.output.ports);
|
||||
//console.log(msg.output.signals);
|
||||
platform.loadROM("ROM", msg.output);
|
||||
vl_finished = vl_stopped = false;
|
||||
for (var i=0; i<10000 && !(vl_finished||vl_stopped); i++)
|
||||
platform.loadROM("ROM", msg.output);
|
||||
platform.loadROM("ROM", msg.output);
|
||||
verilog.vl_finished = verilog.vl_stopped = false;
|
||||
for (var i=0; i<10000 && !(verilog.vl_finished||verilog.vl_stopped); i++) {
|
||||
platform.tick();
|
||||
assert.ok(!vl_stopped);
|
||||
}
|
||||
assert.ok(!verilog.vl_stopped);
|
||||
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);
|
||||
@ -29,7 +36,28 @@ function loadPlatform(msg) {
|
||||
return platform;
|
||||
}
|
||||
|
||||
function compileVerilator(code, callback, nerrors) {
|
||||
function testPerf(msg) {
|
||||
var platform = new VerilogPlatform();
|
||||
platform.loadROM("ROM", msg.output);
|
||||
var niters = 2000000;
|
||||
|
||||
console.time("before");
|
||||
for (var i=0; i<niters; i++)
|
||||
platform.tick();
|
||||
console.timeEnd("before");
|
||||
|
||||
var state = platform.saveState();
|
||||
platform.reset();
|
||||
platform.loadState(state);
|
||||
console.time("after");
|
||||
for (var i=0; i<niters; i++)
|
||||
platform.tick();
|
||||
console.timeEnd("after");
|
||||
|
||||
return platform;
|
||||
}
|
||||
|
||||
function compileVerilator(filename, code, callback, nerrors) {
|
||||
global.postMessage = function(msg) {
|
||||
if (msg.errors && msg.errors.length) {
|
||||
console.log(msg.errors);
|
||||
@ -37,6 +65,10 @@ function compileVerilator(code, callback, nerrors) {
|
||||
} else {
|
||||
assert.equal(nerrors||0, 0, "errors");
|
||||
loadPlatform(msg);
|
||||
//testPerf(msg);
|
||||
if (filename.indexOf('t_') >= 0) {
|
||||
//assert.ok(verilog.vl_finished);
|
||||
}
|
||||
}
|
||||
callback(null, msg);
|
||||
};
|
||||
@ -50,7 +82,7 @@ function testVerilator(filename, disables, nerrors) {
|
||||
var csource = ab2str(fs.readFileSync(filename));
|
||||
for (var i=0; i<(disables||[]).length; i++)
|
||||
csource = "/* verilator lint_off " + disables[i] + " */\n" + csource;
|
||||
compileVerilator(csource, done, nerrors||0);
|
||||
compileVerilator(filename, csource, done, nerrors||0);
|
||||
});
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user