diff --git a/index.html b/index.html
index 1c4c54aa..497d2af2 100644
--- a/index.html
+++ b/index.html
@@ -68,6 +68,7 @@ body {
+
diff --git a/presets/verilog/ball_paddle.v b/presets/verilog/ball_paddle.v
index 672fa036..19651310 100644
--- a/presets/verilog/ball_paddle.v
+++ b/presets/verilog/ball_paddle.v
@@ -180,13 +180,12 @@ module ball_paddle_top(clk, reset, hpaddle, hsync, vsync, rgb);
if (paddle_gfx) begin
// did we collide w/ paddle?
ball_collide_bits[4] <= 1; // bit 4 == paddle collide
- end else begin
- // ball has 4 collision quadrants
- if (!ball_rel_x[2] & !ball_rel_y[2]) ball_collide_bits[0] <= 1;
- if (ball_rel_x[2] & !ball_rel_y[2]) ball_collide_bits[1] <= 1;
- if (!ball_rel_x[2] & ball_rel_y[2]) ball_collide_bits[2] <= 1;
- if (ball_rel_x[2] & ball_rel_y[2]) ball_collide_bits[3] <= 1;
end
+ // ball has 4 collision quadrants
+ if (!ball_rel_x[2] & !ball_rel_y[2]) ball_collide_bits[0] <= 1;
+ if (ball_rel_x[2] & !ball_rel_y[2]) ball_collide_bits[1] <= 1;
+ if (!ball_rel_x[2] & ball_rel_y[2]) ball_collide_bits[2] <= 1;
+ if (ball_rel_x[2] & ball_rel_y[2]) ball_collide_bits[3] <= 1;
end
// compute ball collisions with brick
@@ -213,7 +212,7 @@ module ball_paddle_top(clk, reset, hpaddle, hsync, vsync, rgb);
// which side of paddle, left/right?
ball_dir_x <= (ball_paddle_dx < 16) ? BALL_DIR_LEFT : BALL_DIR_RIGHT;
// hitting with edge of paddle makes it fast
- ball_speed_x <= !(ball_collide_bits[2] && ball_collide_bits[3]);
+ ball_speed_x <= ball_collide_bits[3:0] != 4'b1100;
end else begin
// collided with playfield
// TODO: can still slip through corners
diff --git a/src/platform/verilog.js b/src/platform/verilog.js
index 1a937883..55599ed9 100644
--- a/src/platform/verilog.js
+++ b/src/platform/verilog.js
@@ -83,14 +83,20 @@ function VerilatorBase() {
//
+ var totalTicks = 0;
+
function vl_fatal(msg) {
console.log(msg);
}
+ this.ticks = function() { return totalTicks; }
+ this.setTicks = function(T) { totalTicks = T|0; }
+
var RESET_TICKS = 1000;
this.reset2 = function() {
if (this.reset !== undefined) {
+ totalTicks = 0;
this.reset = 0;
this.tick2();
this.reset = 1;
@@ -130,6 +136,7 @@ function VerilatorBase() {
maxVclockLoop = __VclockLoop;
console.log("Graph took " + maxVclockLoop + " iterations to stabilize");
}
+ totalTicks++;
}
this._eval_initial_loop = function(vlSymsp) {
@@ -176,9 +183,12 @@ var VerilogPlatform = function(mainElement, options) {
0xffffffff,
];
+ var debugCond;
+
function vidtick() {
gen.tick2();
audio.addSingleSample(0+gen.spkr); // TODO: sync with audio freq
+ if (debugCond && debugCond()) debugCond = null;
}
function updateInspectionFrame() {
@@ -209,6 +219,7 @@ var VerilogPlatform = function(mainElement, options) {
}
function updateVideoFrame() {
+ debugCond = self.getDebugCallback();
var i=4; // TODO, start @ 0?
var trace=inspect_obj && inspect_sym;
for (var y=0; y 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+1000) {
+ 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;
+ });
+ }
+
};
function traceTiming() {
diff --git a/src/ui.js b/src/ui.js
index a8bfe7ec..d6372910 100644
--- a/src/ui.js
+++ b/src/ui.js
@@ -576,7 +576,7 @@ var lastDebugState;
function showMemory(state) {
var s = "";
- if (state) {
+ if (state && platform.cpuStateToLongString) {
s = platform.cpuStateToLongString(state.c);
if (platform.getRasterPosition) {
var pos = platform.getRasterPosition();
@@ -598,14 +598,16 @@ function setupBreakpoint() {
// TODO
platform.setupDebug(function(state) {
lastDebugState = state;
- var PC = state.c.PC;
- var line = sourcefile.findLineForOffset(PC);
- if (line >= 0) {
- console.log("BREAKPOINT", hex(PC), line);
- setCurrentLine(line);
- } else {
- console.log("BREAKPOINT", hex(PC));
- // TODO: switch to disasm
+ if (state.c) {
+ var PC = state.c.PC;
+ var line = sourcefile.findLineForOffset(PC);
+ if (line >= 0) {
+ console.log("BREAKPOINT", hex(PC), line);
+ setCurrentLine(line);
+ } else {
+ console.log("BREAKPOINT", hex(PC));
+ // TODO: switch to disasm
+ }
}
showMemory(state);
updateDisassembly();
@@ -635,7 +637,7 @@ function _resume() {
function resume() {
clearBreakpoint();
- if (! platform.isRunning())
+ if (! platform.isRunning() )
editor.setSelection(editor.getCursor()); // TODO??
_resume();
}
@@ -645,6 +647,11 @@ function singleStep() {
platform.step();
}
+function singleFrameStep() {
+ setupBreakpoint();
+ platform.runToVsync();
+}
+
function getCurrentLine() {
return editor.getCursor().line+1;
}
@@ -1213,31 +1220,40 @@ function _recordVideo() {
}
function setupDebugControls(){
- var hasDebug = platform.setupDebug;
$("#dbg_reset").click(resetAndDebug);
$("#dbg_pause").click(pause);
$("#dbg_go").click(resume);
- if (hasDebug) {
+
+ if (platform.step)
$("#dbg_step").click(singleStep).show();
- $("#dbg_toline").click(runToCursor).show();
- $("#dbg_stepout").click(runUntilReturn).show();
- $("#dbg_stepback").click(runStepBackwards).show();
- } else {
+ else
$("#dbg_step").hide();
+ if (platform.runToVsync)
+ $("#dbg_tovsync").click(singleFrameStep).show();
+ else
+ $("#dbg_tovsync").hide();
+ if (platform.runEval && platform_id != 'verilog')
+ $("#dbg_toline").click(runToCursor).show();
+ else
$("#dbg_toline").hide();
+ if (platform.runUntilReturn)
+ $("#dbg_stepout").click(runUntilReturn).show();
+ else
$("#dbg_stepout").hide();
+ if (platform.stepBack)
+ $("#dbg_stepback").click(runStepBackwards).show();
+ else
$("#dbg_stepback").hide();
- }
+
if (window.traceTiming) {
$("#dbg_timing").click(traceTiming).show();
- }
- else if (platform.readAddress) {
+ } else if (platform.readAddress) {
$("#dbg_memory").click(toggleMemoryWindow).show();
}
if (platform.getProbe) {
$("#dbg_profile").click(toggleProfileWindow).show();
}
- if (platform.saveState) { // TODO: only show if listing or disasm available
+ if (platform.saveState && platform_id != 'verilog') { // TODO: only show if listing or disasm available
$("#dbg_disasm").click(toggleDisassembly).show();
}
$("#disassembly").hide();
@@ -1246,7 +1262,10 @@ function setupDebugControls(){
$("#item_new_file").click(_createNewFile);
$("#item_share_file").click(_shareFile);
$("#item_reset_file").click(_resetPreset);
- $("#item_debug_expr").click(_breakExpression);
+ if (platform.runEval)
+ $("#item_debug_expr").click(_breakExpression).show();
+ else
+ $("#item_debug_expr").hide();
$("#item_download_rom").click(_downloadROMImage);
$("#item_record_video").click(_recordVideo);
updateDebugWindows();