mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2024-12-22 12:30:01 +00:00
start yosys profiling
This commit is contained in:
parent
27a9076cb5
commit
2525d6e585
@ -167,7 +167,7 @@ body {
|
||||
<script src="codemirror/addon/edit/matchbrackets.js"></script>
|
||||
<script src="codemirror/addon/search/search.js"></script>
|
||||
<script src="codemirror/addon/search/searchcursor.js"></script>
|
||||
<script src="codemirror/addon/search/jumpToLine.js"></script>
|
||||
<script src="codemirror/addon/search/jump-to-line.js"></script>
|
||||
<script src="codemirror/addon/dialog/dialog.js"></script>
|
||||
<script src="codemirror/addon/selection/active-line.js"></script>
|
||||
<link rel="stylesheet" href="codemirror/addon/dialog/dialog.css">
|
||||
|
@ -1,10 +1,11 @@
|
||||
`include "hvsync_generator.v"
|
||||
`include "digits10.v"
|
||||
|
||||
module player_stats(reset, score, lives, incscore, declives);
|
||||
module player_stats(reset, score0, score1, lives, incscore, declives);
|
||||
|
||||
input reset;
|
||||
output [3:0] score[2];
|
||||
output [3:0] score0;
|
||||
output [3:0] score1;
|
||||
input incscore;
|
||||
output [3:0] lives;
|
||||
input declives;
|
||||
@ -12,13 +13,13 @@ module player_stats(reset, score, lives, incscore, declives);
|
||||
always @(posedge incscore or posedge reset)
|
||||
begin
|
||||
if (reset) begin
|
||||
score[0] <= 0;
|
||||
score[1] <= 0;
|
||||
end else if (score[0] == 9) begin
|
||||
score[0] <= 0;
|
||||
score[1] <= score[1] + 1;
|
||||
score0 <= 0;
|
||||
score1 <= 0;
|
||||
end else if (score0 == 9) begin
|
||||
score0 <= 0;
|
||||
score1 <= score1 + 1;
|
||||
end else begin
|
||||
score[0] <= score[0] + 1;
|
||||
score0 <= score0 + 1;
|
||||
end
|
||||
end
|
||||
|
||||
@ -53,10 +54,11 @@ module ball_paddle_top(clk, reset, hpaddle, hsync, vsync, rgb);
|
||||
|
||||
reg brick_array [BRICKS_H * BRICKS_V];
|
||||
|
||||
wire [3:0] score[2];
|
||||
wire [3:0] score0;
|
||||
wire [3:0] score1;
|
||||
wire [3:0] lives;
|
||||
reg incscore;
|
||||
reg declives;
|
||||
reg declives = 0; // TODO
|
||||
|
||||
localparam BRICKS_H = 16;
|
||||
localparam BRICKS_V = 8;
|
||||
@ -81,8 +83,9 @@ module ball_paddle_top(clk, reset, hpaddle, hsync, vsync, rgb);
|
||||
|
||||
// scoreboard
|
||||
|
||||
player_stats stats(.reset(reset), .score(score), .lives(lives),
|
||||
.incscore(incscore), .declives(declives));
|
||||
player_stats stats(.reset(reset),
|
||||
.score0(score0), .score1(score1), .incscore(incscore),
|
||||
.lives(lives), .declives(declives));
|
||||
|
||||
wire [3:0] score_digit;
|
||||
wire [4:0] score_bits;
|
||||
@ -90,8 +93,8 @@ module ball_paddle_top(clk, reset, hpaddle, hsync, vsync, rgb);
|
||||
always @(*)
|
||||
begin
|
||||
case (hpos[7:5])
|
||||
1: score_digit = score[1];
|
||||
2: score_digit = score[0];
|
||||
1: score_digit = score1;
|
||||
2: score_digit = score0;
|
||||
6: score_digit = lives;
|
||||
default: score_digit = 15; // no digit
|
||||
endcase
|
||||
@ -105,11 +108,6 @@ module ball_paddle_top(clk, reset, hpaddle, hsync, vsync, rgb);
|
||||
|
||||
wire score_gfx = display_on && score_bits[hpos[4:2] ^ 3'b111];
|
||||
|
||||
// TODO: only works when paddle at bottom of screen!
|
||||
always @(posedge hsync)
|
||||
if (!hpaddle)
|
||||
paddle_pos <= vpos;
|
||||
|
||||
wire [5:0] hcell = hpos[8:3];
|
||||
wire [5:0] vcell = vpos[8:3];
|
||||
wire lr_border = hcell==0 || hcell==31;
|
||||
@ -127,10 +125,11 @@ module ball_paddle_top(clk, reset, hpaddle, hsync, vsync, rgb);
|
||||
reg main_gfx;
|
||||
reg brick_present;
|
||||
reg [6:0] brick_index;
|
||||
|
||||
wire visible_clk = clk & display_on;
|
||||
|
||||
// compute main_gfx and locate bricks
|
||||
always @(posedge clk)
|
||||
begin
|
||||
always @(posedge visible_clk)
|
||||
// see if we are scanning brick area
|
||||
if (vpos[8:6] == 1 && !lr_border)
|
||||
begin
|
||||
@ -162,16 +161,21 @@ module ball_paddle_top(clk, reset, hpaddle, hsync, vsync, rgb);
|
||||
default: main_gfx <= lr_border; // left/right borders
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
// only works when paddle at bottom of screen!
|
||||
// (we don't want to mess w/ paddle position during visible portion)
|
||||
always @(posedge hsync)
|
||||
if (!hpaddle)
|
||||
paddle_pos <= vpos;
|
||||
|
||||
wire ball_pixel_collide = main_gfx & ball_gfx;
|
||||
|
||||
/* verilator lint_off MULTIDRIVEN */
|
||||
reg [5:0] ball_collide_bits = 0;
|
||||
reg [4:0] ball_collide_bits = 0;
|
||||
/* verilator lint_on MULTIDRIVEN */
|
||||
|
||||
// compute ball collisions with paddle and playfield
|
||||
always @(posedge clk)
|
||||
always @(posedge visible_clk)
|
||||
if (ball_pixel_collide) begin
|
||||
if (paddle_gfx) begin
|
||||
// did we collide w/ paddle?
|
||||
@ -186,7 +190,7 @@ module ball_paddle_top(clk, reset, hpaddle, hsync, vsync, rgb);
|
||||
end
|
||||
|
||||
// compute ball collisions with brick
|
||||
always @(posedge clk)
|
||||
always @(posedge visible_clk)
|
||||
if (ball_pixel_collide && brick_present) begin
|
||||
brick_array[brick_index] <= 0;
|
||||
incscore <= 1; // increment score
|
||||
|
@ -12,17 +12,17 @@ module hvsync_generator(
|
||||
|
||||
// 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_L_BORDER = 16; // horizontal left border
|
||||
localparam H_R_BORDER = 16; // horizontal right border
|
||||
localparam H_RETRACE = 16; // 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_T_BORDER = 4; // vertical top border
|
||||
localparam V_B_BORDER = 14; // vertical bottom border
|
||||
localparam V_RETRACE = 4; // 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;
|
||||
@ -46,8 +46,8 @@ module hvsync_generator(
|
||||
reg vga_HS, vga_VS;
|
||||
always @(posedge clk)
|
||||
begin
|
||||
vga_HS <= (hpos>=280 && hpos<288); // change this value to move the display horizontally
|
||||
vga_VS <= (vpos==START_V_RETRACE); // change this value to move the display vertically
|
||||
vga_HS <= (hpos>=START_H_RETRACE && hpos<=END_H_RETRACE);
|
||||
vga_VS <= (vpos==START_V_RETRACE);
|
||||
end
|
||||
|
||||
always @(posedge clk)
|
||||
|
26
presets/verilog/skeleton.verilator
Normal file
26
presets/verilog/skeleton.verilator
Normal file
@ -0,0 +1,26 @@
|
||||
`include "hvsync_generator.v"
|
||||
|
||||
module top(clk, hsync, vsync, rgb);
|
||||
|
||||
input clk;
|
||||
output hsync, vsync;
|
||||
output [2:0] rgb;
|
||||
wire display_on;
|
||||
wire [8:0] hpos;
|
||||
wire [8:0] vpos;
|
||||
|
||||
hvsync_generator hvsync_gen(
|
||||
.clk(clk),
|
||||
.hsync(hsync),
|
||||
.vsync(vsync),
|
||||
.display_on(display_on),
|
||||
.hpos(hpos),
|
||||
.vpos(vpos)
|
||||
);
|
||||
|
||||
wire r = display_on && hpos[4];
|
||||
wire g = display_on && vpos[4];
|
||||
wire b = display_on && hpos[0];
|
||||
assign rgb = {b,g,r};
|
||||
|
||||
endmodule
|
@ -396,6 +396,7 @@ var SampleAudio = function(clockfreq) {
|
||||
}
|
||||
|
||||
this.addSingleSample = function(value) {
|
||||
if (!buffer) return;
|
||||
buffer[bufpos++] = value;
|
||||
if (bufpos >= buffer.length) {
|
||||
bufpos = 0;
|
||||
|
@ -242,8 +242,8 @@ var VerilogPlatform = function(mainElement, options) {
|
||||
video.create();
|
||||
setKeyboardFromMap(video, switches, VERILOG_KEYCODE_MAP);
|
||||
$(video.canvas).mousemove(function(e) {
|
||||
paddle_x = clamp(4,255,Math.floor(e.offsetX * video.canvas.width / $(video.canvas).width() - 20));
|
||||
paddle_y = clamp(4,255,Math.floor(e.offsetY * video.canvas.height / $(video.canvas).height() - 20));
|
||||
paddle_x = clamp(8,240,Math.floor(e.offsetX * video.canvas.width / $(video.canvas).width() - 20));
|
||||
paddle_y = clamp(8,240,Math.floor(e.offsetY * video.canvas.height / $(video.canvas).height() - 20));
|
||||
});
|
||||
audio = new SampleAudio(AUDIO_FREQ);
|
||||
idata = video.getFrameData();
|
||||
@ -294,11 +294,11 @@ var VerilogPlatform = function(mainElement, options) {
|
||||
}
|
||||
this.pause = function() {
|
||||
timer.stop();
|
||||
audio.stop();
|
||||
if (gen.spkr !== undefined) audio.stop();
|
||||
}
|
||||
this.resume = function() {
|
||||
timer.start();
|
||||
audio.start();
|
||||
if (gen.spkr !== undefined) audio.start();
|
||||
}
|
||||
|
||||
this.reset = function() {
|
||||
@ -311,6 +311,17 @@ var VerilogPlatform = function(mainElement, options) {
|
||||
this.getDefaultExtension = function() { return ".v"; };
|
||||
};
|
||||
|
||||
function traceTiming() {
|
||||
// TODO: merge with main setCode(text)
|
||||
var text = editor.getValue();
|
||||
worker.postMessage({
|
||||
code:text,
|
||||
dependencies:loadFileDependencies(text),
|
||||
platform:platform_id,
|
||||
tool:'yosys'
|
||||
});
|
||||
}
|
||||
|
||||
////////////////
|
||||
|
||||
PLATFORMS['verilog'] = VerilogPlatform;
|
||||
|
@ -1198,7 +1198,7 @@ function setupDebugControls(){
|
||||
$("#dbg_stepout").hide();
|
||||
$("#dbg_stepback").hide();
|
||||
}
|
||||
if (platform_id == 'vcs') {
|
||||
if (window.traceTiming) {
|
||||
$("#dbg_timing").click(traceTiming).show();
|
||||
}
|
||||
else if (platform.readAddress) {
|
||||
|
@ -1027,6 +1027,15 @@ function detectModuleName(code) {
|
||||
return m ? m[1] : null;
|
||||
}
|
||||
|
||||
function detectTopModuleName(code) {
|
||||
var topmod = detectModuleName(code) || "top";
|
||||
var m = /\bmodule\s+(\w+?_top)/.exec(code);
|
||||
if (m && m[1]) topmod = m[1];
|
||||
m = /\bmodule\s+(\w+?_top)/.exec(code);
|
||||
if (m && m[1]) topmod = m[1];
|
||||
return topmod;
|
||||
}
|
||||
|
||||
function writeDependencies(depends, FS, errors) {
|
||||
if (depends) {
|
||||
for (var i=0; i<depends.length; i++) {
|
||||
@ -1038,7 +1047,7 @@ function writeDependencies(depends, FS, errors) {
|
||||
}
|
||||
|
||||
function compileVerilator(code, platform, options) {
|
||||
loadWASM("verilator_bin");
|
||||
loadNative("verilator_bin");
|
||||
load("verilator2js");
|
||||
var errors = [];
|
||||
var match_fn = makeErrorMatcher(errors, /%(.+?): (.+?:)?(\d+)?[:]?\s*(.+)/i, 3, 4);
|
||||
@ -1048,13 +1057,8 @@ function compileVerilator(code, platform, options) {
|
||||
print:print_fn,
|
||||
printErr:match_fn,
|
||||
});
|
||||
var topmod = detectModuleName(code) || "top";
|
||||
var m = /\bmodule\s+(\w+?_top)/.exec(code);
|
||||
if (m && m[1]) topmod = m[1];
|
||||
m = /\bmodule\s+(\w+?_top)/.exec(code);
|
||||
if (m && m[1]) topmod = m[1];
|
||||
var topmod = detectTopModuleName(code);
|
||||
var FS = verilator_mod['FS'];
|
||||
//setupFS(FS);
|
||||
FS.writeFile(topmod+".v", code);
|
||||
writeDependencies(options.dependencies, FS, errors);
|
||||
starttime();
|
||||
@ -1078,6 +1082,37 @@ function compileVerilator(code, platform, options) {
|
||||
}
|
||||
}
|
||||
|
||||
function compileYosys(code, platform, options) {
|
||||
loadNative("yosys");
|
||||
var errors = [];
|
||||
var match_fn = makeErrorMatcher(errors, /ERROR: (.+?) in line (.+?[.]v):(\d+) (.+)/i, 3, 4);
|
||||
starttime();
|
||||
var yosys_mod = yosys({
|
||||
wasmBinary:wasmBlob['yosys'],
|
||||
noInitialRun:true,
|
||||
print:print_fn,
|
||||
printErr:match_fn,
|
||||
});
|
||||
endtime("create module");
|
||||
var topmod = detectTopModuleName(code);
|
||||
var FS = yosys_mod['FS'];
|
||||
FS.writeFile(topmod+".v", code);
|
||||
writeDependencies(options.dependencies, FS, errors);
|
||||
starttime();
|
||||
yosys_mod.callMain(["-q", "-o", topmod+".json", "-S", topmod+".v"]);
|
||||
endtime("compile");
|
||||
if (errors.length) return {errors:errors};
|
||||
try {
|
||||
var json_file = FS.readFile(topmod+".json", {encoding:'utf8'});
|
||||
var json = JSON.parse(json_file);
|
||||
console.log(json);
|
||||
return {yosys_json:json, errors:errors};
|
||||
} catch(e) {
|
||||
console.log(e);
|
||||
return {errors:errors};
|
||||
}
|
||||
}
|
||||
|
||||
var TOOLS = {
|
||||
'dasm': assembleDASM,
|
||||
'acme': assembleACME,
|
||||
@ -1090,6 +1125,7 @@ var TOOLS = {
|
||||
'xasm6809': assembleXASM6809,
|
||||
'naken': assembleNAKEN,
|
||||
'verilator': compileVerilator,
|
||||
'yosys': compileYosys,
|
||||
}
|
||||
|
||||
var TOOL_PRELOADFS = {
|
||||
|
@ -71,7 +71,7 @@ function compile(tool, code, platform, callback, outlen, nlines, nerrors) {
|
||||
assert.equal(nerrors, msg.errors.length, "errors");
|
||||
} else {
|
||||
assert.equal(nerrors||0, 0, "errors");
|
||||
assert.equal(msg.output.length, outlen, "output binary");
|
||||
assert.equal(msg.output.code?msg.output.code.length:msg.output.length, outlen, "output binary");
|
||||
assert.equal(msg.lines.length, nlines, "listing lines");
|
||||
}
|
||||
callback(null, msg);
|
||||
@ -159,6 +159,10 @@ describe('Worker', function() {
|
||||
var csource = ab2str(fs.readFileSync('presets/coleco/skeleton.sdcc'));
|
||||
compile('sdcc', csource, 'coleco', done, 32768, 31, 0);
|
||||
});
|
||||
it('should compile verilog example', function(done) {
|
||||
var csource = ab2str(fs.readFileSync('presets/verilog/lfsr.v'));
|
||||
compile('verilator', csource, 'verilog', done, 3731, 0, 0);
|
||||
});
|
||||
it('should NOT compile SDCC', function(done) {
|
||||
compile('sdcc', 'foobar', 'mw8080bw', done, 0, 0, 1);
|
||||
});
|
||||
|
Loading…
Reference in New Issue
Block a user