From a541b3c4e68f738bebbed7a97b3c93ed9b2d9b23 Mon Sep 17 00:00:00 2001 From: Steven Hugg Date: Fri, 24 Nov 2017 14:14:22 -0500 Subject: [PATCH] working on verilog debugger --- index.html | 1 + presets/verilog/ball_paddle.v | 13 ++-- src/platform/verilog.js | 123 ++++++++++++++++++++++++++++++++++ src/ui.js | 61 +++++++++++------ 4 files changed, 170 insertions(+), 28 deletions(-) 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();