From d732f320b0135da1a20b0cec1258f8f214c55c65 Mon Sep 17 00:00:00 2001 From: Steven Hugg Date: Tue, 28 Nov 2017 20:48:27 -0500 Subject: [PATCH] work on simple CPU, paddle game, `include local files too, scope scrolling, hvsync reset --- presets/verilog/ball_paddle.v | 62 +++++---- presets/verilog/ball_slip_counter.v | 66 +++++++--- presets/verilog/digits10.v | 3 +- presets/verilog/hvsync_generator.v | 22 ++-- presets/verilog/simple_cpu.v | 196 ---------------------------- presets/verilog/sprite_bitmap.v | 3 +- presets/verilog/sprite_multiple.v | 1 + presets/verilog/sprite_renderer.v | 3 +- presets/verilog/test_hvsync.v | 1 + src/platform/verilog.js | 33 ++++- src/ui.js | 6 +- src/worker/workermain.js | 10 +- 12 files changed, 143 insertions(+), 263 deletions(-) delete mode 100644 presets/verilog/simple_cpu.v diff --git a/presets/verilog/ball_paddle.v b/presets/verilog/ball_paddle.v index 19651310..2afd5f12 100644 --- a/presets/verilog/ball_paddle.v +++ b/presets/verilog/ball_paddle.v @@ -74,6 +74,7 @@ module ball_paddle_top(clk, reset, hpaddle, hsync, vsync, rgb); hvsync_generator hvsync_gen( .clk(clk), + .reset(reset), .hsync(hsync), .vsync(vsync), .display_on(display_on), @@ -125,10 +126,11 @@ module ball_paddle_top(clk, reset, hpaddle, hsync, vsync, rgb); reg main_gfx; reg brick_present; reg [6:0] brick_index; + wire brick_gfx = lr_border || (brick_present && vpos[2:0] != 0 && hpos[3:1] != 4); wire visible_clk = clk & display_on; - // compute main_gfx and locate bricks + // scan bricks: compute brick_index and brick_present flag always @(posedge visible_clk) // see if we are scanning brick area if (vpos[8:6] == 1 && !lr_border) @@ -137,31 +139,19 @@ module ball_paddle_top(clk, reset, hpaddle, hsync, vsync, rgb); if (hpos[3:0] == 8) begin // compute brick index brick_index <= {vpos[5:3], hpos[7:4]}; - main_gfx <= 0; // 2 pixel horiz spacing between bricks + //main_gfx <= 0; // 2 pixel horiz spacing between bricks end // every 17th pixel else if (hpos[3:0] == 9) begin // load brick bit from array brick_present <= brick_array[brick_index]; end else begin - main_gfx <= brick_present && vpos[2:0] != 0; // 1 pixel vert. spacing + //main_gfx <= brick_present && vpos[2:0] != 0; // 1 pixel vert. spacing end end else begin brick_present <= 0; - case (vpos[8:3]) - 0: main_gfx <= score_gfx; // scoreboard - 1: main_gfx <= score_gfx; - 2: main_gfx <= score_gfx; - 3: main_gfx <= 0; - 4: main_gfx <= 1; // top border - //14: main_gfx <= hpos[4]; - //21: main_gfx <= hpos[5]; - 28: main_gfx <= paddle_gfx | lr_border; // paddle - 29: main_gfx <= hpos[0] ^ vpos[0]; // bottom border - default: main_gfx <= lr_border; // left/right borders - endcase end - + // only works when paddle at bottom of screen! // (we don't want to mess w/ paddle position during visible portion) always @(posedge hsync) @@ -171,15 +161,16 @@ module ball_paddle_top(clk, reset, hpaddle, hsync, vsync, rgb); wire ball_pixel_collide = main_gfx & ball_gfx; /* verilator lint_off MULTIDRIVEN */ - reg [4:0] ball_collide_bits = 0; + reg ball_collide_paddle = 0; + reg [3:0] ball_collide_bits = 0; /* verilator lint_on MULTIDRIVEN */ // compute ball collisions with paddle and playfield always @(posedge visible_clk) if (ball_pixel_collide) begin + // did we collide w/ paddle? if (paddle_gfx) begin - // did we collide w/ paddle? - ball_collide_bits[4] <= 1; // bit 4 == paddle collide + ball_collide_paddle <= 1; end // ball has 4 collision quadrants if (!ball_rel_x[2] & !ball_rel_y[2]) ball_collide_bits[0] <= 1; @@ -188,7 +179,7 @@ module ball_paddle_top(clk, reset, hpaddle, hsync, vsync, rgb); if (ball_rel_x[2] & ball_rel_y[2]) ball_collide_bits[3] <= 1; end - // compute ball collisions with brick + // compute ball collisions with brick and increment score always @(posedge visible_clk) if (ball_pixel_collide && brick_present) begin brick_array[brick_index] <= 0; @@ -199,18 +190,18 @@ module ball_paddle_top(clk, reset, hpaddle, hsync, vsync, rgb); wire signed [8:0] ball_paddle_dx = ball_x - paddle_pos + 8; - // compute ball new position and velocity + // ball bounce: determine new velocity/direction always @(posedge vsync or posedge reset) begin if (reset) begin ball_dir_y <= BALL_DIR_DOWN; end else // ball collided with paddle? - if (ball_collide_bits[4]) begin + if (ball_collide_paddle) begin // bounces upward off of paddle ball_dir_y <= BALL_DIR_UP; // which side of paddle, left/right? - ball_dir_x <= (ball_paddle_dx < 16) ? BALL_DIR_LEFT : BALL_DIR_RIGHT; + ball_dir_x <= (ball_paddle_dx < 20) ? BALL_DIR_LEFT : BALL_DIR_RIGHT; // hitting with edge of paddle makes it fast ball_speed_x <= ball_collide_bits[3:0] != 4'b1100; end else begin @@ -238,8 +229,10 @@ module ball_paddle_top(clk, reset, hpaddle, hsync, vsync, rgb); endcase end ball_collide_bits <= 0; // clear all collide bits for frame + ball_collide_paddle <= 0; end + // ball motion: update ball position always @(negedge vsync or posedge reset) begin if (reset) begin @@ -254,6 +247,29 @@ module ball_paddle_top(clk, reset, hpaddle, hsync, vsync, rgb); end end + // compute main_gfx + always @(*) + begin + case (vpos[8:3]) + 0: main_gfx = score_gfx; // scoreboard + 1: main_gfx = score_gfx; + 2: main_gfx = score_gfx; + 3: main_gfx = 0; + 4: main_gfx = 1; // top border + 8: main_gfx = brick_gfx; // 1st brick row + 9: main_gfx = brick_gfx; // ... + 10: main_gfx = brick_gfx; + 11: main_gfx = brick_gfx; + 12: main_gfx = brick_gfx; + 13: main_gfx = brick_gfx; + 14: main_gfx = brick_gfx; + 15: main_gfx = brick_gfx; // 8th brick row + 28: main_gfx = paddle_gfx | lr_border; // paddle + 29: main_gfx = hpos[0] ^ vpos[0]; // bottom border + default: main_gfx = lr_border; // left/right borders + endcase + end + wire grid_gfx = (((hpos&7)==0) || ((vpos&7)==0)); wire r = display_on && (ball_gfx | paddle_gfx); diff --git a/presets/verilog/ball_slip_counter.v b/presets/verilog/ball_slip_counter.v index 132bfa2d..a9a845fc 100644 --- a/presets/verilog/ball_slip_counter.v +++ b/presets/verilog/ball_slip_counter.v @@ -10,14 +10,17 @@ module ball_paddle_top(clk, reset, hsync, vsync, rgb); wire [8:0] hpos; wire [8:0] vpos; - reg [7:0] ball_htimer; - reg [7:0] ball_vtimer; + reg [8:0] ball_htimer; + reg [8:0] ball_vtimer; - reg [3:0] ball_horiz_vel; - reg [3:0] ball_vert_vel; + reg [8:0] ball_horiz_stop = 209; + reg [8:0] ball_horiz_move = -2; + reg [8:0] ball_vert_stop = 251; + reg [8:0] ball_vert_move = 2; hvsync_generator hvsync_gen( .clk(clk), + .reset(reset), .hsync(hsync), .vsync(vsync), .display_on(display_on), @@ -25,29 +28,56 @@ module ball_paddle_top(clk, reset, hsync, vsync, rgb); .vpos(vpos) ); - always @(posedge clk) + // update horizontal timer + always @(posedge clk or posedge reset) begin - if (hpos == 0 && vpos == 0) - ball_htimer <= ball_htimer + 8'(ball_horiz_vel) - 4; - else if (display_on) + if (reset) + ball_htimer <= ball_horiz_stop - 128; + else if (ball_htimer == 0) begin + if (ball_vtimer == 0) + ball_htimer <= ball_horiz_stop + ball_horiz_move; + else + ball_htimer <= ball_horiz_stop; + end else ball_htimer <= ball_htimer + 1; end; - always @(posedge hsync) + // update vertical timer + always @(posedge hsync or posedge reset) begin - if (vpos > 9'(ball_vert_vel)) + if (reset) + ball_vtimer <= ball_vert_stop - 128; + else if (ball_vtimer == 0) + ball_vtimer <= ball_vert_stop + ball_vert_move; + else ball_vtimer <= ball_vtimer + 1; end; - - wire ball_hgfx = ball_htimer < 8; - wire ball_vgfx = ball_vtimer < 8; - wire ball_gfx = ball_hgfx & ball_vgfx; - wire grid_gfx = (((hpos&7)==0) || ((vpos&7)==0)); + // vertical bounce + always @(posedge ball_vert_collide) + begin + ball_vert_move <= -ball_vert_move; + end; - wire r = display_on && (grid_gfx | ball_gfx); - wire g = display_on && ball_gfx; - wire b = display_on && ball_gfx; + // horizontal bounce + always @(posedge ball_horiz_collide) + begin + ball_horiz_move <= -ball_horiz_move; + end; + + wire ball_hgfx = ball_htimer >= 508; + wire ball_vgfx = ball_vtimer >= 508; + wire ball_gfx = ball_hgfx && ball_vgfx; + + // collide with vertical and horizontal boundaries + wire ball_vert_collide = ball_vgfx && vpos >= 240; + wire ball_horiz_collide = ball_hgfx && hpos >= 256 && vpos == 255; + + wire grid_gfx = (((hpos&7)==0) && ((vpos&7)==0)); + + wire r = display_on && (ball_hgfx | ball_gfx); + wire g = display_on && (grid_gfx | ball_gfx); + wire b = display_on && (ball_vgfx | ball_gfx); assign rgb = {b,g,r}; endmodule diff --git a/presets/verilog/digits10.v b/presets/verilog/digits10.v index 13013e0f..9820afcf 100644 --- a/presets/verilog/digits10.v +++ b/presets/verilog/digits10.v @@ -82,7 +82,7 @@ module digits10_array(digit, yofs, bits); reg [4:0] bitarray[10][5]; assign bits = bitarray[digit][yofs]; - + initial begin/*{w:5,h:5,count:10}*/ bitarray[0][0] = 5'b11111; bitarray[0][1] = 5'b10001; @@ -157,6 +157,7 @@ module test_numbers_top(clk, hsync, vsync, rgb); hvsync_generator hvsync_gen( .clk(clk), + .reset(0), .hsync(hsync), .vsync(vsync), .display_on(display_on), diff --git a/presets/verilog/hvsync_generator.v b/presets/verilog/hvsync_generator.v index 817961cb..e41b75c3 100644 --- a/presets/verilog/hvsync_generator.v +++ b/presets/verilog/hvsync_generator.v @@ -2,15 +2,16 @@ `define HVSYNC_GENERATOR_H module hvsync_generator( - clk, hsync, vsync, display_on, hpos, vpos); + clk, reset, hsync, vsync, display_on, hpos, vpos); input clk; - output hsync, vsync; + input reset; + output reg hsync, vsync; output reg display_on; output reg [8:0] hpos; output reg [8:0] vpos; - // constant declarations for VGA sync parameters + // constant declarations for TV-simulator sync parameters localparam H_DISPLAY = 256; // horizontal display area localparam H_L_BORDER = 16; // horizontal left border localparam H_R_BORDER = 16; // horizontal right border @@ -27,15 +28,17 @@ module hvsync_generator( localparam START_V_RETRACE = V_DISPLAY + V_B_BORDER; localparam END_V_RETRACE = V_DISPLAY + V_B_BORDER + V_RETRACE - 1; - wire hmaxxed = (hpos==H_MAX); - wire vmaxxed = (vpos==V_MAX); - - always @(posedge clk) + wire hmaxxed = (hpos == H_MAX) || reset; + wire vmaxxed = (vpos == V_MAX) || reset; + + // increment horizontal position counter + always @(posedge clk) if(hmaxxed) hpos <= 0; else hpos <= hpos + 1; + // increment vertical position counter always @(posedge clk) if(hmaxxed) if (!vmaxxed) @@ -43,14 +46,11 @@ module hvsync_generator( else vpos <= 0; + // compute hsync + vsync + display_on signals always @(posedge clk) begin hsync <= (hpos>=START_H_RETRACE && hpos<=END_H_RETRACE); vsync <= (vpos==START_V_RETRACE); - end - - always @(posedge clk) - begin display_on <= (hpos> 1}; - `OP_OR: Y = {1'b0, A | B}; - `OP_AND: Y = {1'b0, A & B}; - `OP_XOR: Y = {1'b0, A ^ B}; - default: Y = 9'bx; - endcase - -endmodule - -`define REG_A 1'b0 -`define REG_B 1'b1 -`define I_CONST(r,x) { 2'b00, r, x } -`define I_LOAD_ADDR(r,addr) { 3'b010, r, addr } -`define I_STORE_ADDR(r,addr) { 3'b011, r, addr } -`define I_COMPUTE(r,op) { 3'b100, r, op } -`define I_RESET 8'hff - -module CPU(clk, reset, address, data_in, data_out, write); - - input clk, reset; - output [7:0] address; - input [7:0] data_in; - output [7:0] data_out; - output write; - - reg [7:0] ip; - reg [7:0] opcode; - reg [3:0] aluop; - reg [7:0] A, B; - reg [8:0] Y; - reg [1:0] state; - reg [2:0] action; - - reg carry; - reg zero; - - localparam NOOP = 0; - localparam MAKE_CONST = 1; - localparam LOAD_ADDR = 2; - localparam STORE_ADDR = 3; - localparam COMPUTE = 4; - - wire load_const = opcode[3:1] == 3'b111; - - ALU alu(.A(A), .B(B), .Y(Y), .aluop(aluop)); - - always @(posedge clk) - if (reset) begin - state <= 0; - write <= 0; - end else begin - case (state) - // state 0: reset - 0: begin - ip <= 8'h80; - write <= 0; - state <= 1; - end - // state 1: select opcode address - 1: begin - address <= ip; - ip <= ip + 1; - write <= 0; - state <= 2; - end - // state 2: read/decode opcode - 2: begin - casez (data_in) - 8'b00??????: begin - action <= MAKE_CONST; - if (data_in[5]) - B <= {3'b0, data_in[4:0]}; - else - A <= {3'b0, data_in[4:0]}; - state <= 1; - end - 8'b010?????: begin - action <= LOAD_ADDR; - address <= {4'b0, data_in[3:0]}; - state <= 3; - end - 8'b011?????: begin - action <= STORE_ADDR; - address <= {4'b0, data_in[3:0]}; - state <= 3; - end - 8'b100?????: begin - action <= COMPUTE; - aluop <= data_in[3:0]; - state <= 3; - end - default: begin - action <= NOOP; - state <= 0; // reset - end - endcase - opcode <= data_in; - end - // state 3: perform action - 3: begin - if (action == LOAD_ADDR) begin - if (opcode[4]) - B <= data_in; - else - A <= data_in; - end else if (action == STORE_ADDR) begin - if (opcode[4]) - data_out <= B; - else - data_out <= A; - write <= 1; - end else if (action == COMPUTE) begin - if (opcode[4]) - B <= Y[7:0]; - else - A <= Y[7:0]; - carry <= Y[8]; - zero <= ~|Y; - end - state <= 1; // repeat loop at state 1 - end - endcase - end - -endmodule - -module test_CPU_top(clk, reset, address_bus, to_cpu, from_cpu, write_enable); - - input clk, reset; - output [7:0] address_bus; - output reg [7:0] to_cpu; - output [7:0] from_cpu; - output write_enable; - - reg [7:0] ram[128]; - reg [7:0] rom[128]; - - CPU cpu(.clk(clk), - .reset(reset), - .address(address_bus), - .data_in(to_cpu), - .data_out(from_cpu), - .write(write_enable)); - - // does not work as (posedge clk) - always @(*) - if (write_enable) - ram[address_bus[6:0]] = from_cpu; - else if (address_bus[7] == 0) - to_cpu = ram[address_bus[6:0]]; - else - to_cpu = rom[address_bus[6:0]]; - - initial begin - // address 0x80 - rom['h00] = `I_CONST(`REG_A, 5'h1f); - rom['h01] = `I_COMPUTE(`REG_A, `OP_ASL); - rom['h02] = `I_COMPUTE(`REG_A, `OP_ASL); - rom['h03] = `I_COMPUTE(`REG_A, `OP_ASL); - rom['h04] = `I_COMPUTE(`REG_A, `OP_ASL); - rom['h05] = `I_COMPUTE(`REG_B, `OP_LOAD_A); - rom['h06] = `I_STORE_ADDR(`REG_B, 4'd1); - rom['h07] = `I_LOAD_ADDR(`REG_B, 4'd1); - rom['h08] = `I_RESET; - end - -endmodule diff --git a/presets/verilog/sprite_bitmap.v b/presets/verilog/sprite_bitmap.v index 4022bcc6..bda742a6 100644 --- a/presets/verilog/sprite_bitmap.v +++ b/presets/verilog/sprite_bitmap.v @@ -29,7 +29,7 @@ module car_bitmap(yofs, bits); end endmodule -module test_top(clk, hsync, vsync, rgb, hpaddle, vpaddle); +module sprite_bitmap_top(clk, hsync, vsync, rgb, hpaddle, vpaddle); input clk; input hpaddle, vpaddle; @@ -49,6 +49,7 @@ module test_top(clk, hsync, vsync, rgb, hpaddle, vpaddle); hvsync_generator hvsync_gen( .clk(clk), + .reset(0), .hsync(hsync), .vsync(vsync), .display_on(display_on), diff --git a/presets/verilog/sprite_multiple.v b/presets/verilog/sprite_multiple.v index c3e6f696..dc108608 100644 --- a/presets/verilog/sprite_multiple.v +++ b/presets/verilog/sprite_multiple.v @@ -24,6 +24,7 @@ module sprite_multiple_top(clk, hsync, vsync, rgb, hpaddle, vpaddle); hvsync_generator hvsync_gen( .clk(clk), + .reset(0), .hsync(hsync), .vsync(vsync), .display_on(display_on), diff --git a/presets/verilog/sprite_renderer.v b/presets/verilog/sprite_renderer.v index b8bef0f8..3c20bd97 100644 --- a/presets/verilog/sprite_renderer.v +++ b/presets/verilog/sprite_renderer.v @@ -6,7 +6,7 @@ module car_bitmap(yofs, bits); output [7:0] bits; reg [7:0] bitarray[16]; - + assign bits = bitarray[yofs]; initial begin/*{w:8,h:16}*/ @@ -102,6 +102,7 @@ module test_top(clk, hsync, vsync, rgb, hpaddle, vpaddle); hvsync_generator hvsync_gen( .clk(clk), + .reset(0), .hsync(hsync), .vsync(vsync), .display_on(display_on), diff --git a/presets/verilog/test_hvsync.v b/presets/verilog/test_hvsync.v index a17b3152..55c6b8b9 100644 --- a/presets/verilog/test_hvsync.v +++ b/presets/verilog/test_hvsync.v @@ -11,6 +11,7 @@ module test_hvsync_top(clk, hsync, vsync, rgb); hvsync_generator hvsync_gen( .clk(clk), + .reset(0), .hsync(hsync), .vsync(vsync), .display_on(display_on), diff --git a/src/platform/verilog.js b/src/platform/verilog.js index de1f8308..29e04ec1 100644 --- a/src/platform/verilog.js +++ b/src/platform/verilog.js @@ -11,6 +11,7 @@ var VERILOG_PRESETS = [ {id:'sprite_bitmap.v', name:'Sprite Bitmaps'}, {id:'sprite_renderer.v', name:'Sprite Rendering'}, {id:'sprite_multiple.v', name:'Multiple Sprites'}, + {id:'cpu8.v', name:'Simple 8-Bit CPU'}, ]; var VERILOG_KEYCODE_MAP = makeKeycodeMap([ @@ -170,7 +171,8 @@ var VerilogPlatform = function(mainElement, options) { var switches = [0]; var inspect_obj, inspect_sym; var inspect_data = new Uint32Array(videoWidth * videoHeight); - var scope_time_x = 0; + var scope_time_x = 0; // scope cursor + var scope_x_offset = 0; var scope_y_offset = 0; var scope_max_y = 0; @@ -289,7 +291,8 @@ var VerilogPlatform = function(mainElement, options) { var COLOR_BORDER = 0xff662222; var COLOR_TRANS_SIGNAL = 0xff226622; var COLOR_BLIP_SIGNAL = 0xff226622; - var j = 0; + var jstart = scope_x_offset * arr.length; + var j = jstart; for (var x=0; x 0) { - ctx.fillRect(scope_time_x, 0, 1, 4000); ctx.textAlign = 'right'; - var value = arr.length * scope_time_x + i; + var value = arr.length * scope_time_x + i + jstart; ctx.fillText(""+trace_buffer[value], videoWidth-1, yposlist[i]); } } + // draw scope line & label + if (scope_time_x > 0) { + ctx.fillStyle = "cyan"; + ctx.fillText(""+(scope_time_x+scope_x_offset), + (scope_time_x>10)?(scope_time_x-2):(scope_time_x+20), videoHeight-2); + ctx.fillRect(scope_time_x, 0, 1, 4000); + } + // scroll left/right + if (scope_time_x >= videoWidth && scope_x_offset < (trace_buffer.length / arr.length) - videoWidth) { + scope_x_offset += 1 + (scope_time_x - videoWidth); + dirty = true; + } + else if (scope_time_x < 0 && scope_x_offset > 0) { + scope_x_offset = Math.max(0, scope_x_offset + scope_time_x); + dirty = true; + } } function clamp(minv,maxv,v) { @@ -352,7 +370,7 @@ var VerilogPlatform = function(mainElement, options) { var new_x = Math.floor(e.offsetX * video.canvas.width / $(video.canvas).width() - 20); var new_y = Math.floor(e.offsetY * video.canvas.height / $(video.canvas).height() - 20); if (mouse_pressed) { - scope_y_offset = clamp(-scope_max_y, 0, scope_y_offset + new_y - paddle_y); + 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 / $(video.canvas).width() - 16); dirty = true; } @@ -432,7 +450,7 @@ var VerilogPlatform = function(mainElement, options) { } this.reset = function() { gen.__reset(); - trace_index = 0; + trace_index = scope_x_offset = 0; trace_buffer.fill(0); dirty = true; } @@ -462,6 +480,7 @@ var VerilogPlatform = function(mainElement, options) { } else { inspect_obj = inspect_sym = null; } + dirty = true; } // DEBUGGING diff --git a/src/ui.js b/src/ui.js index afacc424..fcb7c3b4 100644 --- a/src/ui.js +++ b/src/ui.js @@ -419,12 +419,12 @@ function updateSelector() { function loadFileDependencies(text) { var arr = []; if (platform_id == 'verilog') { - var re = /`include\s+"(.+)"/g; + var re = /`include\s+"(.+?)"/g; var m; while (m = re.exec(text)) { arr.push({ filename:m[1], - text:store.loadFile(m[1]) // TODO: if missing? + text:store.loadFile(m[1]) || store.loadFile('local/'+m[1]) // TODO?? }); } } @@ -836,7 +836,7 @@ function toggleDisassembly() { } function resetAndDebug() { - if (platform.setupDebug) { + if (platform.setupDebug && platform.readAddress) { // TODO?? clearBreakpoint(); _resume(); platform.reset(); diff --git a/src/worker/workermain.js b/src/worker/workermain.js index 9d0a3bce..9e79d4fb 100644 --- a/src/worker/workermain.js +++ b/src/worker/workermain.js @@ -1087,7 +1087,7 @@ 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); + var match_fn = makeErrorMatcher(errors, /ERROR: (.+?) in line (.+?[.]v):(\d+)[: ]+(.+)/i, 3, 4); starttime(); var yosys_mod = yosys({ wasmBinary:wasmBlob['yosys'], @@ -1101,7 +1101,13 @@ function compileYosys(code, platform, options) { FS.writeFile(topmod+".v", code); writeDependencies(options.dependencies, FS, errors); starttime(); - yosys_mod.callMain(["-q", "-o", topmod+".json", "-S", topmod+".v"]); + try { + yosys_mod.callMain(["-q", "-o", topmod+".json", "-S", topmod+".v"]); + } catch (e) { + console.log(e); + endtime("compile"); + return {errors:errors}; + } endtime("compile"); if (errors.length) return {errors:errors}; try {