(WIP) new hdl package, verilator 4 (emscripten 2.0.6), hdlwasm
This commit is contained in:
parent
7b492622c2
commit
9bb79c318f
|
@ -8,6 +8,7 @@
|
||||||
"version": "3.7.2",
|
"version": "3.7.2",
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"binaryen": "^101.0.0",
|
||||||
"chokidar": "^3.5.0",
|
"chokidar": "^3.5.0",
|
||||||
"electron-store": "^6.0.1",
|
"electron-store": "^6.0.1",
|
||||||
"jquery": "^3.5.1",
|
"jquery": "^3.5.1",
|
||||||
|
@ -789,6 +790,14 @@
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/binaryen": {
|
||||||
|
"version": "101.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/binaryen/-/binaryen-101.0.0.tgz",
|
||||||
|
"integrity": "sha512-FRmVxvrR8jtcf0qcukNAPZDM3dZ2sc9GmA/hKxBI7k3fFzREKh1cAs+ruQi+ITTKz7u/AuFMuVnbJwTh0ef/HQ==",
|
||||||
|
"bin": {
|
||||||
|
"wasm-opt": "bin/wasm-opt"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/bluebird": {
|
"node_modules/bluebird": {
|
||||||
"version": "3.7.2",
|
"version": "3.7.2",
|
||||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
|
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
|
||||||
|
@ -8245,6 +8254,11 @@
|
||||||
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
|
||||||
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA=="
|
"integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA=="
|
||||||
},
|
},
|
||||||
|
"binaryen": {
|
||||||
|
"version": "101.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/binaryen/-/binaryen-101.0.0.tgz",
|
||||||
|
"integrity": "sha512-FRmVxvrR8jtcf0qcukNAPZDM3dZ2sc9GmA/hKxBI7k3fFzREKh1cAs+ruQi+ITTKz7u/AuFMuVnbJwTh0ef/HQ=="
|
||||||
|
},
|
||||||
"bluebird": {
|
"bluebird": {
|
||||||
"version": "3.7.2",
|
"version": "3.7.2",
|
||||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
|
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
},
|
},
|
||||||
"license": "GPL-3.0",
|
"license": "GPL-3.0",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"binaryen": "^101.0.0",
|
||||||
"chokidar": "^3.5.0",
|
"chokidar": "^3.5.0",
|
||||||
"electron-store": "^6.0.1",
|
"electron-store": "^6.0.1",
|
||||||
"jquery": "^3.5.1",
|
"jquery": "^3.5.1",
|
||||||
|
|
|
@ -25,7 +25,7 @@ module ALU(A, B, carry, aluop, Y);
|
||||||
input [N-1:0] B; // B input
|
input [N-1:0] B; // B input
|
||||||
input carry; // carry input
|
input carry; // carry input
|
||||||
input [3:0] aluop; // alu operation
|
input [3:0] aluop; // alu operation
|
||||||
output [N:0] Y; // Y output + carry
|
output reg [N:0] Y; // Y output + carry
|
||||||
|
|
||||||
always @(*)
|
always @(*)
|
||||||
case (aluop)
|
case (aluop)
|
||||||
|
|
|
@ -42,8 +42,8 @@ module ball_absolute_top(clk, reset, hsync, vsync, rgb);
|
||||||
begin
|
begin
|
||||||
if (reset) begin
|
if (reset) begin
|
||||||
// reset ball position to center
|
// reset ball position to center
|
||||||
ball_hpos <= ball_horiz_initial;
|
|
||||||
ball_vpos <= ball_vert_initial;
|
ball_vpos <= ball_vert_initial;
|
||||||
|
ball_hpos <= ball_horiz_initial;
|
||||||
end else begin
|
end else begin
|
||||||
// add velocity vector to ball position
|
// add velocity vector to ball position
|
||||||
ball_hpos <= ball_hpos + ball_horiz_move;
|
ball_hpos <= ball_hpos + ball_horiz_move;
|
||||||
|
|
|
@ -16,7 +16,7 @@ module clock_divider(
|
||||||
// simple ripple clock divider
|
// simple ripple clock divider
|
||||||
|
|
||||||
always @(posedge clk)
|
always @(posedge clk)
|
||||||
clk_div2 <= ~clk_div2;
|
clk_div2 <= reset ? 0 : ~clk_div2;
|
||||||
|
|
||||||
always @(posedge clk_div2)
|
always @(posedge clk_div2)
|
||||||
clk_div4 <= ~clk_div4;
|
clk_div4 <= ~clk_div4;
|
||||||
|
|
|
@ -56,11 +56,14 @@ $$end
|
||||||
// -------------------------
|
// -------------------------
|
||||||
|
|
||||||
algorithm main(
|
algorithm main(
|
||||||
|
$$if NTSC then
|
||||||
|
// NTSC
|
||||||
output! uint$color_depth$ video_r,
|
output! uint$color_depth$ video_r,
|
||||||
output! uint$color_depth$ video_g,
|
output! uint$color_depth$ video_g,
|
||||||
output! uint$color_depth$ video_b,
|
output! uint$color_depth$ video_b,
|
||||||
output! uint1 video_hs,
|
output! uint1 video_hs,
|
||||||
output! uint1 video_vs
|
output! uint1 video_vs
|
||||||
|
$$end
|
||||||
)
|
)
|
||||||
<@clock,!reset>
|
<@clock,!reset>
|
||||||
{
|
{
|
||||||
|
|
|
@ -28,7 +28,7 @@ module ALU(A, B, carry, aluop, Y);
|
||||||
input [N-1:0] B; // B input
|
input [N-1:0] B; // B input
|
||||||
input carry; // carry input
|
input carry; // carry input
|
||||||
input [3:0] aluop; // alu operation
|
input [3:0] aluop; // alu operation
|
||||||
output [N:0] Y; // Y output + carry
|
output reg [N:0] Y; // Y output + carry
|
||||||
|
|
||||||
always @(*)
|
always @(*)
|
||||||
case (aluop)
|
case (aluop)
|
||||||
|
@ -72,14 +72,14 @@ endmodule
|
||||||
module CPU16(clk, reset, hold, busy,
|
module CPU16(clk, reset, hold, busy,
|
||||||
address, data_in, data_out, write);
|
address, data_in, data_out, write);
|
||||||
|
|
||||||
input clk;
|
input clk;
|
||||||
input reset;
|
input reset;
|
||||||
input hold;
|
input hold;
|
||||||
output busy;
|
output reg busy;
|
||||||
output [15:0] address;
|
output reg [15:0] address;
|
||||||
input [15:0] data_in;
|
input [15:0] data_in;
|
||||||
output [15:0] data_out;
|
output reg [15:0] data_out;
|
||||||
output write;
|
output reg write;
|
||||||
|
|
||||||
// wait state for RAM?
|
// wait state for RAM?
|
||||||
parameter RAM_WAIT = 1;
|
parameter RAM_WAIT = 1;
|
||||||
|
|
|
@ -1339,7 +1339,7 @@ endmodule
|
||||||
module cpu6502_test_top(clk, reset, AB, DI, DO, WE);
|
module cpu6502_test_top(clk, reset, AB, DI, DO, WE);
|
||||||
input clk,reset;
|
input clk,reset;
|
||||||
output reg [15:0] AB; // address bus
|
output reg [15:0] AB; // address bus
|
||||||
output wire [7:0] DI; // data in, read bus
|
output var [7:0] DI; // data in, read bus
|
||||||
output wire [7:0] DO; // data out, write bus
|
output wire [7:0] DO; // data out, write bus
|
||||||
output wire WE; // write enable
|
output wire WE; // write enable
|
||||||
wire IRQ=0; // interrupt request
|
wire IRQ=0; // interrupt request
|
||||||
|
|
|
@ -28,7 +28,7 @@ module ALU(A, B, carry, aluop, Y);
|
||||||
input [N-1:0] B; // B input
|
input [N-1:0] B; // B input
|
||||||
input carry; // carry input
|
input carry; // carry input
|
||||||
input [3:0] aluop; // alu operation
|
input [3:0] aluop; // alu operation
|
||||||
output [N:0] Y; // Y output + carry
|
output reg [N:0] Y; // Y output + carry
|
||||||
|
|
||||||
always @(*)
|
always @(*)
|
||||||
case (aluop)
|
case (aluop)
|
||||||
|
@ -99,12 +99,12 @@ tttt = flags test for conditional branch
|
||||||
|
|
||||||
module CPU(clk, reset, address, data_in, data_out, write);
|
module CPU(clk, reset, address, data_in, data_out, write);
|
||||||
|
|
||||||
input clk;
|
input clk;
|
||||||
input reset;
|
input reset;
|
||||||
output [7:0] address;
|
output reg [7:0] address;
|
||||||
input [7:0] data_in;
|
input [7:0] data_in;
|
||||||
output [7:0] data_out;
|
output reg [7:0] data_out;
|
||||||
output write;
|
output reg write;
|
||||||
|
|
||||||
reg [7:0] IP;
|
reg [7:0] IP;
|
||||||
reg [7:0] A, B;
|
reg [7:0] A, B;
|
||||||
|
|
|
@ -46,7 +46,7 @@ module cpu_platform(clk, reset, hsync, vsync,
|
||||||
reg [5:0] sprite_ram_addr;
|
reg [5:0] sprite_ram_addr;
|
||||||
wire tile_reading;
|
wire tile_reading;
|
||||||
wire sprite_reading;
|
wire sprite_reading;
|
||||||
wire [14:0] mux_ram_addr; // 15-bit RAM access
|
var [14:0] mux_ram_addr; // 15-bit RAM access
|
||||||
|
|
||||||
// multiplexor for sprite/tile/CPU RAM
|
// multiplexor for sprite/tile/CPU RAM
|
||||||
always @(*)
|
always @(*)
|
||||||
|
@ -138,11 +138,12 @@ module cpu_platform(clk, reset, hsync, vsync,
|
||||||
wire cpu_busy;
|
wire cpu_busy;
|
||||||
wire [15:0] cpu_ram_addr;
|
wire [15:0] cpu_ram_addr;
|
||||||
wire busy;
|
wire busy;
|
||||||
wire [15:0] cpu_bus;
|
var [15:0] cpu_bus;
|
||||||
wire [15:0] flags = {11'b0, vsync, hsync, vpaddle, hpaddle, display_on};
|
wire [15:0] flags = {11'b0, vsync, hsync, vpaddle, hpaddle, display_on};
|
||||||
wire [15:0] switches = {switches_p2, switches_p1};
|
wire [15:0] switches = {switches_p2, switches_p1};
|
||||||
|
|
||||||
// select ROM, RAM, switches ($FFFE) or flags ($FFFF)
|
// select ROM, RAM, switches ($FFFE) or flags ($FFFF)
|
||||||
|
/* verilator lint_off CASEOVERLAP */
|
||||||
always @(*)
|
always @(*)
|
||||||
casez (cpu_ram_addr)
|
casez (cpu_ram_addr)
|
||||||
16'hfffe: cpu_bus = switches;
|
16'hfffe: cpu_bus = switches;
|
||||||
|
|
|
@ -163,9 +163,11 @@ module digits10_array(digit, yofs, bits);
|
||||||
bitarray[9][4] = 5'b11111;
|
bitarray[9][4] = 5'b11111;
|
||||||
|
|
||||||
// clear unused array entries
|
// clear unused array entries
|
||||||
|
/* TODO
|
||||||
for (i = 10; i <= 15; i++)
|
for (i = 10; i <= 15; i++)
|
||||||
for (j = 0; j <= 4; j++)
|
for (j = 0; j <= 4; j++)
|
||||||
bitarray[i][j] = 0;
|
bitarray[i][j] = 0;
|
||||||
|
*/
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
|
|
||||||
{
|
{
|
||||||
"name":"femto8",
|
"name":"femto8",
|
||||||
|
"width":8,
|
||||||
"vars":{
|
"vars":{
|
||||||
"reg":{"bits":2, "toks":["a", "b", "ip", "none"]},
|
"reg":{"bits":2, "toks":["a", "b", "ip", "none"]},
|
||||||
"unop":{"bits":3, "toks":["zero","loada","inc","dec","asl","lsr","rol","ror"]},
|
"unop":{"bits":3, "toks":["zero","loada","inc","dec","asl","lsr","rol","ror"]},
|
||||||
|
|
|
@ -13,7 +13,7 @@ module frame_buffer_top(clk, reset, hsync, vsync, hpaddle, vpaddle,
|
||||||
wire display_on;
|
wire display_on;
|
||||||
wire [8:0] hpos;
|
wire [8:0] hpos;
|
||||||
wire [8:0] vpos;
|
wire [8:0] vpos;
|
||||||
output [3:0] rgb;
|
output reg [3:0] rgb;
|
||||||
|
|
||||||
reg [15:0] ram[0:32767]; // RAM (32768 x 16 bits)
|
reg [15:0] ram[0:32767]; // RAM (32768 x 16 bits)
|
||||||
reg [15:0] rom[0:1023]; // ROM (1024 x 16 bits)
|
reg [15:0] rom[0:1023]; // ROM (1024 x 16 bits)
|
||||||
|
|
|
@ -21,9 +21,10 @@ module RAM_sync(clk, addr, din, dout, we);
|
||||||
input clk; // clock
|
input clk; // clock
|
||||||
input [A-1:0] addr; // address
|
input [A-1:0] addr; // address
|
||||||
input [D-1:0] din; // data input
|
input [D-1:0] din; // data input
|
||||||
output [D-1:0] dout; // data output
|
|
||||||
input we; // write enable
|
input we; // write enable
|
||||||
|
|
||||||
|
output reg [D-1:0] dout; // data output
|
||||||
|
|
||||||
reg [D-1:0] mem [0:(1<<A)-1]; // (1<<A)xD bit memory
|
reg [D-1:0] mem [0:(1<<A)-1]; // (1<<A)xD bit memory
|
||||||
|
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) begin
|
||||||
|
|
|
@ -32,6 +32,7 @@ algorithm frame_display(
|
||||||
int20 deltau_y = 0;
|
int20 deltau_y = 0;
|
||||||
int20 deltav_x = 0;
|
int20 deltav_x = 0;
|
||||||
int20 deltav_y = 0;
|
int20 deltav_y = 0;
|
||||||
|
int8 scale = 128;
|
||||||
|
|
||||||
brom uint18 tbl[$32*32$] = {
|
brom uint18 tbl[$32*32$] = {
|
||||||
$$write_image_in_table('tile.tga',6)
|
$$write_image_in_table('tile.tga',6)
|
||||||
|
@ -84,8 +85,6 @@ $$end
|
||||||
// prepare scanline with mapping
|
// prepare scanline with mapping
|
||||||
corneru = - ((cornerx * cos) - (cornery * sin));
|
corneru = - ((cornerx * cos) - (cornery * sin));
|
||||||
cornerv = - ((cornerx * sin) + (cornery * cos));
|
cornerv = - ((cornerx * sin) + (cornery * cos));
|
||||||
//corneru = ((cornerx * cos) - (cornery * sin));
|
|
||||||
//cornerv = ((cornerx * sin) + (cornery * cos));
|
|
||||||
deltau_x = cos;
|
deltau_x = cos;
|
||||||
deltau_y = - sin;
|
deltau_y = - sin;
|
||||||
deltav_x = sin;
|
deltav_x = sin;
|
||||||
|
|
|
@ -16,9 +16,9 @@ module sprite_renderer(clk, vstart, load, hstart, rom_addr, rom_bits,
|
||||||
input vstart; // start drawing (top border)
|
input vstart; // start drawing (top border)
|
||||||
input load; // ok to load sprite data?
|
input load; // ok to load sprite data?
|
||||||
input hstart; // start drawing scanline (left border)
|
input hstart; // start drawing scanline (left border)
|
||||||
output [3:0] rom_addr; // select ROM address
|
output reg [3:0] rom_addr; // select ROM address
|
||||||
input [7:0] rom_bits; // input bits from ROM
|
input [7:0] rom_bits; // input bits from ROM
|
||||||
output gfx; // output pixel
|
output reg gfx; // output pixel
|
||||||
output in_progress; // 0 if waiting for vstart
|
output in_progress; // 0 if waiting for vstart
|
||||||
|
|
||||||
reg [2:0] state; // current state #
|
reg [2:0] state; // current state #
|
||||||
|
|
|
@ -114,9 +114,9 @@ module sprite_renderer2(clk, vstart, load, hstart, rom_addr, rom_bits,
|
||||||
|
|
||||||
input clk, vstart, load, hstart;
|
input clk, vstart, load, hstart;
|
||||||
input hmirror, vmirror;
|
input hmirror, vmirror;
|
||||||
output [4:0] rom_addr;
|
output reg [4:0] rom_addr;
|
||||||
input [7:0] rom_bits;
|
input [7:0] rom_bits;
|
||||||
output gfx;
|
output reg gfx;
|
||||||
output busy;
|
output busy;
|
||||||
|
|
||||||
assign busy = state != WAIT_FOR_VSTART;
|
assign busy = state != WAIT_FOR_VSTART;
|
||||||
|
@ -191,8 +191,8 @@ endmodule
|
||||||
module rotation_selector(rotation, bitmap_num, hmirror, vmirror);
|
module rotation_selector(rotation, bitmap_num, hmirror, vmirror);
|
||||||
|
|
||||||
input [3:0] rotation; // angle (0..15)
|
input [3:0] rotation; // angle (0..15)
|
||||||
output [2:0] bitmap_num; // bitmap index (0..4)
|
output reg [2:0] bitmap_num; // bitmap index (0..4)
|
||||||
output hmirror, vmirror; // horiz & vert mirror bits
|
output reg hmirror, vmirror; // horiz & vert mirror bits
|
||||||
|
|
||||||
always @(*)
|
always @(*)
|
||||||
case (rotation[3:2]) // 4 quadrants
|
case (rotation[3:2]) // 4 quadrants
|
||||||
|
|
|
@ -52,13 +52,13 @@ module sprite_scanline_renderer(clk, reset, hpos, vpos, rgb,
|
||||||
input clk, reset; // clock and reset inputs
|
input clk, reset; // clock and reset inputs
|
||||||
input [8:0] hpos; // horiz. sync pos
|
input [8:0] hpos; // horiz. sync pos
|
||||||
input [8:0] vpos; // vert. sync pos
|
input [8:0] vpos; // vert. sync pos
|
||||||
output [3:0] rgb; // rgb output
|
output reg [3:0] rgb; // rgb output
|
||||||
|
|
||||||
output [NB:0] ram_addr; // RAM for sprite data
|
output reg [NB:0] ram_addr; // RAM for sprite data
|
||||||
input [15:0] ram_data; // (2 words per sprite)
|
input [15:0] ram_data; // (2 words per sprite)
|
||||||
output ram_busy; // set when accessing RAM
|
output reg ram_busy; // set when accessing RAM
|
||||||
|
|
||||||
output [15:0] rom_addr; // sprite ROM address
|
output reg [15:0] rom_addr; // sprite ROM address
|
||||||
input [15:0] rom_data; // sprite ROM data
|
input [15:0] rom_data; // sprite ROM data
|
||||||
|
|
||||||
// copy of sprite data from RAM (N entries)
|
// copy of sprite data from RAM (N entries)
|
||||||
|
@ -208,11 +208,11 @@ module test_scanline_render_top(clk, reset, hsync, vsync, rgb);
|
||||||
.data(rom_data)
|
.data(rom_data)
|
||||||
);
|
);
|
||||||
|
|
||||||
wire [5:0] ram_addr;
|
reg [5:0] ram_addr;
|
||||||
wire [15:0] ram_read;
|
wire [15:0] ram_read;
|
||||||
reg [15:0] ram_write;
|
reg [15:0] ram_write;
|
||||||
reg ram_we;
|
reg ram_we;
|
||||||
wire ram_busy;
|
reg ram_busy;
|
||||||
|
|
||||||
// 64-word RAM
|
// 64-word RAM
|
||||||
RAM_sync #(6,16) ram(
|
RAM_sync #(6,16) ram(
|
||||||
|
|
|
@ -27,9 +27,9 @@ module test_hvsync_top(clk, reset, hsync, vsync, rgb);
|
||||||
);
|
);
|
||||||
|
|
||||||
// Assign each color bit to individual wires.
|
// Assign each color bit to individual wires.
|
||||||
wire r = display_on && (((hpos&7)==0) || ((vpos&7)==0));
|
wire r = display_on & (((hpos&7)==0) | ((vpos&7)==0));
|
||||||
wire g = display_on && vpos[4];
|
wire g = display_on & vpos[4];
|
||||||
wire b = display_on && hpos[4];
|
wire b = display_on & hpos[4];
|
||||||
|
|
||||||
// Concatenation operator merges the red, green, and blue signals
|
// Concatenation operator merges the red, green, and blue signals
|
||||||
// into a single 3-bit vector, which is assigned to the 'rgb'
|
// into a single 3-bit vector, which is assigned to the 'rgb'
|
||||||
|
|
Before Width: | Height: | Size: 3.0 KiB After Width: | Height: | Size: 3.0 KiB |
|
@ -138,6 +138,8 @@ export interface Platform {
|
||||||
|
|
||||||
readFile?(path: string) : FileData;
|
readFile?(path: string) : FileData;
|
||||||
writeFile?(path: string, data: FileData) : boolean;
|
writeFile?(path: string, data: FileData) : boolean;
|
||||||
|
|
||||||
|
getDownloadFile?() : {extension:string, blob:Blob};
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface Preset {
|
export interface Preset {
|
||||||
|
|
|
@ -0,0 +1,579 @@
|
||||||
|
|
||||||
|
import { byteArrayToString } from "../util";
|
||||||
|
import { HDLBinop, HDLBlock, HDLConstant, HDLDataType, HDLExpr, HDLExtendop, HDLFuncCall, HDLModuleDef, HDLTriop, HDLUnop, HDLValue, HDLVariableDef, HDLVarRef, isArrayItem, isArrayType, isBinop, isBlock, isConstExpr, isFuncCall, isLogicType, isTriop, isUnop, isVarDecl, isVarRef, isWhileop } from "./hdltypes";
|
||||||
|
|
||||||
|
interface VerilatorUnit {
|
||||||
|
_ctor_var_reset(state) : void;
|
||||||
|
_eval_initial(state) : void;
|
||||||
|
_eval_settle(state) : void;
|
||||||
|
_eval(state) : void;
|
||||||
|
_change_request(state) : boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class HDLModuleJS {
|
||||||
|
|
||||||
|
mod: HDLModuleDef;
|
||||||
|
constpool: HDLModuleDef;
|
||||||
|
locals: {[name: string] : HDLVariableDef};
|
||||||
|
state: {[name: string] : HDLValue};
|
||||||
|
basefuncs: VerilatorUnit;
|
||||||
|
curfuncs: VerilatorUnit;
|
||||||
|
finished: boolean = false;
|
||||||
|
stopped: boolean = false;
|
||||||
|
settleTime: number = 0;
|
||||||
|
curconsts: {};
|
||||||
|
specfuncs: VerilatorUnit[] = [];
|
||||||
|
|
||||||
|
constructor(mod: HDLModuleDef, constpool: HDLModuleDef) {
|
||||||
|
this.mod = mod;
|
||||||
|
this.constpool = constpool;
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
this.basefuncs = {} as any;
|
||||||
|
this.state = {}; //new Object(this.funcs) as any;
|
||||||
|
// set built-in functions
|
||||||
|
Object.getOwnPropertyNames(Object.getPrototypeOf(this)).filter((f) => f.startsWith('$')).forEach((f) => {
|
||||||
|
this.basefuncs[f] = this[f].bind(this);
|
||||||
|
})
|
||||||
|
// generate functions
|
||||||
|
this.basefuncs = this.genFuncs({});
|
||||||
|
this.curfuncs = this.basefuncs;
|
||||||
|
for (var i=0; i<2; i++) {
|
||||||
|
this.specfuncs[i] = this.genFuncs({
|
||||||
|
reset:(i&1),
|
||||||
|
//clk:(i&2),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// set initial state
|
||||||
|
if (this.constpool) {
|
||||||
|
var cp = new HDLModuleJS(this.constpool, null);
|
||||||
|
cp.init();
|
||||||
|
Object.assign(this.state, cp.state);
|
||||||
|
}
|
||||||
|
for (var varname in this.mod.vardefs) {
|
||||||
|
var vardef = this.mod.vardefs[varname];
|
||||||
|
this.state[varname] = this.defaultValue(vardef.dtype, vardef);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
genFuncs(constants: {}) : VerilatorUnit {
|
||||||
|
var funcs = Object.create(this.basefuncs);
|
||||||
|
this.curconsts = constants;
|
||||||
|
for (var block of this.mod.blocks) {
|
||||||
|
this.locals = {};
|
||||||
|
var s = this.block2js(block);
|
||||||
|
try {
|
||||||
|
var funcname = block.name||'__anon';
|
||||||
|
var funcbody = `'use strict'; function ${funcname}(o) { ${s} }; return ${funcname};`;
|
||||||
|
var func = new Function('', funcbody)();
|
||||||
|
funcs[block.name] = func;
|
||||||
|
//console.log(funcbody);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(funcbody);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return funcs;
|
||||||
|
}
|
||||||
|
|
||||||
|
getJSCode() : string {
|
||||||
|
var s = '';
|
||||||
|
for (var funcname in this.basefuncs) {
|
||||||
|
if (funcname && funcname.startsWith("_")) {
|
||||||
|
s += this.basefuncs[funcname].toString();
|
||||||
|
s += "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
reset() {
|
||||||
|
this.finished = false;
|
||||||
|
this.stopped = false;
|
||||||
|
this.basefuncs._ctor_var_reset(this.state);
|
||||||
|
this.basefuncs._eval_initial(this.state);
|
||||||
|
for (var i=0; i<100; i++) {
|
||||||
|
this.basefuncs._eval_settle(this.state);
|
||||||
|
this.eval();
|
||||||
|
var Vchange = this.basefuncs._change_request(this.state);
|
||||||
|
if (!Vchange) {
|
||||||
|
this.settleTime = i;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Error(`model did not converge on reset()`)
|
||||||
|
}
|
||||||
|
|
||||||
|
eval() {
|
||||||
|
//var clk = this.state.clk as number;
|
||||||
|
var reset = this.state.reset as number;
|
||||||
|
this.curfuncs = this.specfuncs[reset];
|
||||||
|
for (var i=0; i<100; i++) {
|
||||||
|
this.curfuncs._eval(this.state);
|
||||||
|
var Vchange = this.curfuncs._change_request(this.state);
|
||||||
|
/*
|
||||||
|
--- don't do it this way! it's like 4x slower...
|
||||||
|
this.call('_eval');
|
||||||
|
var Vchange = this.call('_change_request');
|
||||||
|
*/
|
||||||
|
if (!Vchange) {
|
||||||
|
this.settleTime = i;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Error(`model did not converge on eval()`)
|
||||||
|
}
|
||||||
|
|
||||||
|
tick2() {
|
||||||
|
//var k1 = Object.keys(this.state).length;
|
||||||
|
// TODO
|
||||||
|
this.state.clk = 0;
|
||||||
|
this.eval();
|
||||||
|
this.state.clk = 1;
|
||||||
|
this.eval();
|
||||||
|
//var k2 = Object.keys(this.state).length;
|
||||||
|
//if (k2 != k1) console.log(k1, k2);
|
||||||
|
}
|
||||||
|
|
||||||
|
defaultValue(dt: HDLDataType, vardef?: HDLVariableDef) : HDLValue {
|
||||||
|
if (isLogicType(dt)) {
|
||||||
|
return 0;
|
||||||
|
} else if (isArrayType(dt)) {
|
||||||
|
let arr;
|
||||||
|
let arrlen = dt.high.cvalue - dt.low.cvalue + 1;
|
||||||
|
if (arrlen < 0) arrlen = -arrlen; // TODO?
|
||||||
|
if (isLogicType(dt.subtype)) {
|
||||||
|
if (dt.subtype.left <= 7)
|
||||||
|
arr = new Uint8Array(arrlen);
|
||||||
|
else if (dt.subtype.left <= 15)
|
||||||
|
arr = new Uint16Array(arrlen);
|
||||||
|
else if (dt.subtype.left <= 31)
|
||||||
|
arr = new Uint32Array(arrlen);
|
||||||
|
else {
|
||||||
|
arr = []; // TODO?
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
arr = [];
|
||||||
|
for (let i=0; i<arrlen; i++) {
|
||||||
|
arr[i] = this.defaultValue(dt.subtype);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (vardef != null && vardef.initValue != null) {
|
||||||
|
for (let i=0; i<vardef.initValue.exprs.length; i++) {
|
||||||
|
let e = vardef.initValue.exprs[i];
|
||||||
|
if (isArrayItem(e) && isConstExpr(e.expr)) {
|
||||||
|
arr[e.index] = e.expr.cvalue;
|
||||||
|
} else {
|
||||||
|
throw new Error(`non-const expr in initarray`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
throw new Error(`no default value for var type: ${vardef.name}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
constValue(expr: HDLExpr) : number {
|
||||||
|
if (isConstExpr(expr)) {
|
||||||
|
return expr.cvalue;
|
||||||
|
} else {
|
||||||
|
throw new Error(`no const value for expr`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
block2js(block: HDLBlock) : string {
|
||||||
|
return this.expr2js(block);
|
||||||
|
}
|
||||||
|
|
||||||
|
expr2js(e: HDLExpr, options?:{cond?:boolean}) : string {
|
||||||
|
if (e == null) {
|
||||||
|
return "/*null*/"; // TODO
|
||||||
|
}
|
||||||
|
if (isVarRef(e)) {
|
||||||
|
if (this.curconsts[e.refname] != null)
|
||||||
|
return `${this.curconsts[e.refname]}`;
|
||||||
|
else if (this.locals[e.refname])
|
||||||
|
return `${e.refname}`;
|
||||||
|
else
|
||||||
|
return `o.${e.refname}`;
|
||||||
|
} else if (isVarDecl(e)) {
|
||||||
|
this.locals[e.name] = e;
|
||||||
|
let s = `var ${e.name}`;
|
||||||
|
if (e.constValue != null) {
|
||||||
|
s += ` = ${this.constValue(e)}`; // TODO?
|
||||||
|
} else if (e.initValue != null) {
|
||||||
|
// TODO?
|
||||||
|
throw new Error(`can't init array here`);
|
||||||
|
} else if (isLogicType(e.dtype) && e.dtype.left > 31) {
|
||||||
|
// TODO: hack for big ints ($readmem)
|
||||||
|
s += ` = []`;
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
} else if (isConstExpr(e)) {
|
||||||
|
return `0x${e.cvalue.toString(16)}`;
|
||||||
|
} else if (isTriop(e)) {
|
||||||
|
switch (e.op) {
|
||||||
|
case 'if':
|
||||||
|
if (e.right == null || (isBlock(e.right) && e.right.exprs.length == 0))
|
||||||
|
return `if (${this.expr2js(e.cond, {cond:true})}) { ${this.expr2js(e.left)} }`;
|
||||||
|
else
|
||||||
|
return `if (${this.expr2js(e.cond, {cond:true})}) { ${this.expr2js(e.left)} } else { ${this.expr2js(e.right)} }`;
|
||||||
|
case 'cond':
|
||||||
|
case 'condbound':
|
||||||
|
return `(${this.expr2js(e.cond, {cond:true})} ? ${this.expr2js(e.left)} : ${this.expr2js(e.right)})`;
|
||||||
|
default:
|
||||||
|
console.log(e);
|
||||||
|
throw Error(`unknown triop ${e.op}`);
|
||||||
|
}
|
||||||
|
} else if (isBinop(e)) {
|
||||||
|
switch (e.op) {
|
||||||
|
case 'contassign':
|
||||||
|
case 'assign':
|
||||||
|
case 'assignpre':
|
||||||
|
case 'assigndly':
|
||||||
|
case 'assignpost':
|
||||||
|
return `${this.expr2js(e.right)} = ${this.expr2js(e.left)}`;
|
||||||
|
case 'arraysel':
|
||||||
|
case 'wordsel':
|
||||||
|
return `${this.expr2js(e.left)}[${this.expr2js(e.right)}]`;
|
||||||
|
case 'changedet':
|
||||||
|
// __req |= ((vlTOPp->control_test_top__02Ehsync ^ vlTOPp->__Vchglast__TOP__control_test_top__02Ehsync)
|
||||||
|
// vlTOPp->__Vchglast__TOP__control_test_top__02Ehsync = vlTOPp->control_test_top__02Ehsync;
|
||||||
|
return `$$req |= (${this.expr2js(e.left)} ^ ${this.expr2js(e.right)}); ${this.expr2js(e.right)} = ${this.expr2js(e.left)}`;
|
||||||
|
default:
|
||||||
|
var jsop = OP2JS[e.op];
|
||||||
|
if (!jsop) {
|
||||||
|
console.log(e);
|
||||||
|
throw Error(`unknown binop ${e.op}`)
|
||||||
|
}
|
||||||
|
if (jsop.startsWith('?')) {
|
||||||
|
jsop = jsop.substr(1);
|
||||||
|
if (!options || !options.cond) {
|
||||||
|
return `((${this.expr2js(e.left)} ${jsop} ${this.expr2js(e.right)})?1:0)`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return `(${this.expr2js(e.left)} ${jsop} ${this.expr2js(e.right)})`;
|
||||||
|
}
|
||||||
|
} else if (isUnop(e)) {
|
||||||
|
switch (e.op) {
|
||||||
|
case 'ccast': // TODO: cast ints, cast bools?
|
||||||
|
return this.expr2js(e.left);
|
||||||
|
case 'creturn':
|
||||||
|
return `return ${this.expr2js(e.left)}`;
|
||||||
|
case 'creset':
|
||||||
|
return this.expr2reset(e.left);
|
||||||
|
case 'not':
|
||||||
|
return `(~${this.expr2js(e.left)})`;
|
||||||
|
//return `(${this.expr2js(e.left)}?0:1)`;
|
||||||
|
case 'negate':
|
||||||
|
return `(-${this.expr2js(e.left)})`;
|
||||||
|
case 'extends':
|
||||||
|
let shift = 32 - (e as HDLExtendop).widthminv;
|
||||||
|
return `((${this.expr2js(e.left)} << ${shift}) >> ${shift})`;
|
||||||
|
default:
|
||||||
|
console.log(e);
|
||||||
|
throw Error(`unknown unop ${e.op}`);
|
||||||
|
}
|
||||||
|
} else if (isBlock(e)) {
|
||||||
|
// TODO: { e } ?
|
||||||
|
var body = e.exprs.map((x) => this.expr2js(x)).join(';\n');
|
||||||
|
if (e.name) {
|
||||||
|
if (e.name.startsWith('_change_request')) {
|
||||||
|
return `var $$req = 0;\n${body}\n;return $$req;`
|
||||||
|
} else if (e.blocktype == 'sformatf') {
|
||||||
|
var args = e.exprs.map((x) => this.expr2js(x));
|
||||||
|
args = [JSON.stringify(e.name)].concat(args);
|
||||||
|
return args.join(', ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return body;
|
||||||
|
} else if (isWhileop(e)) {
|
||||||
|
return `for (${this.expr2js(e.precond)}; ${this.expr2js(e.loopcond)}; ${this.expr2js(e.inc)}) { ${this.expr2js(e.body)} }`
|
||||||
|
} else if (isFuncCall(e)) {
|
||||||
|
if (e.args == null || e.args.length == 0) {
|
||||||
|
return `this.${e.funcname}(o)`;
|
||||||
|
} else {
|
||||||
|
return `this.${e.funcname}(o, ${ e.args.map(arg => this.expr2js(arg)).join(', ') })`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(e);
|
||||||
|
throw new Error(`unrecognized expr: ${JSON.stringify(e)}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
expr2reset(e: HDLExpr) {
|
||||||
|
if (isVarRef(e)) {
|
||||||
|
// don't reset constant values
|
||||||
|
if (this.curconsts[e.refname] != null)
|
||||||
|
return `/* ${e.refname} */`;
|
||||||
|
// TODO: random values?
|
||||||
|
if (isLogicType(e.dtype)) {
|
||||||
|
return `${this.expr2js(e)} = 0`;
|
||||||
|
} else if (isArrayType(e.dtype)) {
|
||||||
|
if (isLogicType(e.dtype.subtype)) {
|
||||||
|
return `${this.expr2js(e)}.fill(0)`;
|
||||||
|
} else if (isArrayType(e.dtype.subtype) && isLogicType(e.dtype.subtype.subtype)) {
|
||||||
|
return `${this.expr2js(e)}.forEach((a) => a.fill(0))`
|
||||||
|
} else {
|
||||||
|
// TODO: 3d arrays?
|
||||||
|
throw Error(`unsupported data type for reset: ${JSON.stringify(e.dtype)}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw Error(`can only reset var refs`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// runtime methods
|
||||||
|
// TODO: $time, $display, etc
|
||||||
|
|
||||||
|
$finish(o) {
|
||||||
|
if (!this.finished) {
|
||||||
|
console.log("Simulation finished");
|
||||||
|
this.finished = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$stop(o) {
|
||||||
|
if (!this.stopped) {
|
||||||
|
console.log("Simulation stopped");
|
||||||
|
this.stopped = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$rand(o) : number {
|
||||||
|
return Math.random() | 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$display(o, fmt, ...args) {
|
||||||
|
// TODO: replace args, etc
|
||||||
|
console.log(fmt, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: implement arguments, XML
|
||||||
|
$readmem(o, filename, memp, lsbp, msbp, ishex) {
|
||||||
|
// parse filename from 32-bit values into characters
|
||||||
|
var barr = [];
|
||||||
|
for (var i=0; i<filename.length; i++) {
|
||||||
|
barr.push((filename[i] >> 0) & 0xff);
|
||||||
|
barr.push((filename[i] >> 8) & 0xff);
|
||||||
|
barr.push((filename[i] >> 16) & 0xff);
|
||||||
|
barr.push((filename[i] >> 24) & 0xff);
|
||||||
|
}
|
||||||
|
barr = barr.filter(x => x != 0); // ignore zeros
|
||||||
|
barr.reverse(); // reverse it
|
||||||
|
var strfn = byteArrayToString(barr); // convert to string
|
||||||
|
// parse hex/binary file
|
||||||
|
var strdata = this.getFile(strfn) as string;
|
||||||
|
if (strdata == null) throw Error("Could not $readmem '" + strfn + "'");
|
||||||
|
var data = strdata.split('\n').filter(s => s !== '').map(s => parseInt(s, ishex ? 16 : 2));
|
||||||
|
console.log('$readmem', ishex, strfn, data.length);
|
||||||
|
// copy into destination array
|
||||||
|
if (memp === null) throw Error("No destination array to $readmem " + strfn);
|
||||||
|
if (memp.length < data.length) throw Error("Destination array too small to $readmem " + strfn);
|
||||||
|
for (i=0; i<data.length; i++)
|
||||||
|
memp[i] = data[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
getFile(path: string) : string {
|
||||||
|
// TODO: override
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const OP2JS : {[key:string] : string} = {
|
||||||
|
'eq' : '?===',
|
||||||
|
'neq' : '?!==',
|
||||||
|
'gt' : '?>',
|
||||||
|
'lt' : '?<',
|
||||||
|
'gte' : '?>=',
|
||||||
|
'lte' : '?<=',
|
||||||
|
'and' : '&',
|
||||||
|
'or' : '|',
|
||||||
|
'xor' : '^',
|
||||||
|
'add' : '+',
|
||||||
|
'sub' : '-',
|
||||||
|
'shiftr': '>>>', // TODO?
|
||||||
|
'shiftl': '<<',
|
||||||
|
// TODO: correct?
|
||||||
|
'mul' : '*',
|
||||||
|
'moddiv': '%',
|
||||||
|
'div' : '/',
|
||||||
|
// TODO: signed versions? functions?
|
||||||
|
'muls' : '*',
|
||||||
|
'moddivs': '%',
|
||||||
|
'divs' : '/',
|
||||||
|
'gts' : '?>',
|
||||||
|
'gtes' : '?>=',
|
||||||
|
'lts' : '?<',
|
||||||
|
'ltes' : '?<=',
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
// SIMULATOR STUFF (should be global)
|
||||||
|
|
||||||
|
export var vl_finished = false;
|
||||||
|
export var vl_stopped = false;
|
||||||
|
|
||||||
|
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
|
||||||
|
export function VL_BITISSET_I(data,bit) { return (data & (VL_UL(1)<<VL_UL(bit))); }
|
||||||
|
|
||||||
|
export function VL_EXTENDSIGN_I(lbits, lhs) { return (-((lhs)&(VL_UL(1)<<(lbits-1)))); }
|
||||||
|
|
||||||
|
export function VL_EXTEND_II(obits,lbits,lhs) { return lhs; }
|
||||||
|
|
||||||
|
export function VL_EXTENDS_II(x,lbits,lhs) {
|
||||||
|
return VL_EXTENDSIGN_I(lbits,lhs) | lhs;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function VL_NEGATE_I(x) { return -x; }
|
||||||
|
|
||||||
|
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; }
|
||||||
|
|
||||||
|
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; }
|
||||||
|
|
||||||
|
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; }
|
||||||
|
|
||||||
|
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; }
|
||||||
|
|
||||||
|
export function VL_DIV_III(lbits,lhs,rhs) {
|
||||||
|
return (((rhs)==0)?0:(lhs)/(rhs)); }
|
||||||
|
|
||||||
|
export function VL_MULS_III(lbits,lhs,rhs) {
|
||||||
|
return (((rhs)==0)?0:(lhs)*(rhs)); }
|
||||||
|
|
||||||
|
export function VL_MODDIV_III(lbits,lhs,rhs) {
|
||||||
|
return (((rhs)==0)?0:(lhs)%(rhs)); }
|
||||||
|
|
||||||
|
export function VL_DIVS_III(lbits,lhs,rhs) {
|
||||||
|
var lhs_signed = VL_EXTENDS_II(32, lbits, lhs);
|
||||||
|
var rhs_signed = VL_EXTENDS_II(32, lbits, rhs);
|
||||||
|
return (((rhs_signed)==0)?0:(lhs_signed)/(rhs_signed));
|
||||||
|
}
|
||||||
|
|
||||||
|
export function VL_MODDIVS_III(lbits,lhs,rhs) {
|
||||||
|
var lhs_signed = VL_EXTENDS_II(32, lbits, lhs);
|
||||||
|
var rhs_signed = VL_EXTENDS_II(32, lbits, rhs);
|
||||||
|
return (((rhs_signed)==0)?0:(lhs_signed)%(rhs_signed));
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
export var VL_WRITEF = console.log; // TODO: $write
|
||||||
|
|
||||||
|
export function vl_finish(filename,lineno,hier) {
|
||||||
|
if (!vl_finished) console.log("Finished at " + filename + ":" + lineno, hier);
|
||||||
|
vl_finished = true;
|
||||||
|
}
|
||||||
|
export function vl_stop(filename,lineno,hier) {
|
||||||
|
if (!vl_stopped) console.log("Stopped at " + filename + ":" + lineno, hier);
|
||||||
|
vl_stopped = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function VL_RAND_RESET_I(bits) { return 0 | Math.floor(Math.random() * (1<<bits)); }
|
||||||
|
|
||||||
|
export function VL_RANDOM_I(bits) { return 0 | Math.floor(Math.random() * (1<<bits)); }
|
||||||
|
|
||||||
|
export function VL_READMEM_Q(ishex,width,depth,array_lsb,fnwords,filename,memp,start,end) {
|
||||||
|
VL_READMEM_W(ishex,width,depth,array_lsb,fnwords,filename,memp,start,end);
|
||||||
|
}
|
||||||
|
export function VL_READMEM_W(ishex,width,depth,array_lsb,fnwords,filename,memp,start,end) {
|
||||||
|
}
|
||||||
|
|
||||||
|
// SIMULATOR BASE
|
||||||
|
|
||||||
|
abstract class VerilatorBase {
|
||||||
|
|
||||||
|
totalTicks = 0;
|
||||||
|
maxVclockLoop = 0;
|
||||||
|
clk = 0;
|
||||||
|
reset = 0;
|
||||||
|
|
||||||
|
vl_fatal(msg:string) {
|
||||||
|
console.log(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
ticks() : number { return this.totalTicks; }
|
||||||
|
setTicks(T:number) { this.totalTicks = T|0; }
|
||||||
|
|
||||||
|
__reset() {
|
||||||
|
if (this.reset !== undefined) {
|
||||||
|
this.totalTicks = 0;
|
||||||
|
this.reset = 0;
|
||||||
|
this.tick2();
|
||||||
|
this.reset = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
eval() {
|
||||||
|
let vlSymsp = this; //{TOPp:this};
|
||||||
|
// Initialize
|
||||||
|
if (!vlSymsp.__Vm_didInit)
|
||||||
|
this._eval_initial_loop(vlSymsp);
|
||||||
|
// Evaluate till stable
|
||||||
|
//VL_DEBUG_IF(VL_PRINTF("\n----TOP Evaluate Vmain::eval\n"); );
|
||||||
|
var __VclockLoop = 0;
|
||||||
|
var __Vchange=1;
|
||||||
|
while (__Vchange) {
|
||||||
|
//VL_DEBUG_IF(VL_PRINTF(" Clock loop\n"););
|
||||||
|
vlSymsp.__Vm_activity = true;
|
||||||
|
this._eval(vlSymsp);
|
||||||
|
__Vchange = this._change_request(vlSymsp);
|
||||||
|
if (++__VclockLoop > 100) { this.vl_fatal("Verilated model didn't converge"); }
|
||||||
|
}
|
||||||
|
if (__VclockLoop > this.maxVclockLoop) {
|
||||||
|
this.maxVclockLoop = __VclockLoop;
|
||||||
|
if (this.maxVclockLoop > 1) {
|
||||||
|
console.log("Graph took " + this.maxVclockLoop + " iterations to stabilize");
|
||||||
|
$("#verilog_bar").show();
|
||||||
|
$("#settle_label").text(this.maxVclockLoop+"");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.totalTicks++;
|
||||||
|
}
|
||||||
|
|
||||||
|
_eval_initial_loop(vlSymsp) {
|
||||||
|
vlSymsp.TOPp = this;
|
||||||
|
vlSymsp.__Vm_didInit = true;
|
||||||
|
this._eval_initial(vlSymsp);
|
||||||
|
vlSymsp.__Vm_activity = true;
|
||||||
|
var __VclockLoop = 0;
|
||||||
|
var __Vchange=1;
|
||||||
|
while (__Vchange) {
|
||||||
|
this._eval_settle(vlSymsp);
|
||||||
|
this._eval(vlSymsp);
|
||||||
|
__Vchange = this._change_request(vlSymsp);
|
||||||
|
if (++__VclockLoop > 100) { this.vl_fatal("Verilated model didn't DC converge"); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
|
@ -0,0 +1,196 @@
|
||||||
|
|
||||||
|
export interface HDLLogicType extends HDLSourceObject {
|
||||||
|
left: number;
|
||||||
|
right: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HDLUnpackArray extends HDLSourceObject {
|
||||||
|
subtype: HDLDataType;
|
||||||
|
low: HDLConstant;
|
||||||
|
high: HDLConstant;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HDLNativeType extends HDLSourceObject {
|
||||||
|
jstype: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type HDLDataType = HDLLogicType | HDLUnpackArray | HDLNativeType;
|
||||||
|
|
||||||
|
export function isLogicType(arg:any): arg is HDLLogicType {
|
||||||
|
return typeof arg.left === 'number' && typeof arg.right === 'number';
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isArrayType(arg:any): arg is HDLUnpackArray {
|
||||||
|
return arg.subtype != null && arg.low != null && arg.high != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class HDLFile {
|
||||||
|
id: string;
|
||||||
|
filename: string;
|
||||||
|
isModule: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HDLSourceLocation {
|
||||||
|
file: HDLFile;
|
||||||
|
line: number;
|
||||||
|
col?: number;
|
||||||
|
end_line?: number;
|
||||||
|
end_col?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HDLSourceObject {
|
||||||
|
$loc?: HDLSourceLocation;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HDLDataTypeObject extends HDLSourceObject {
|
||||||
|
dtype: HDLDataType;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HDLModuleDef extends HDLSourceObject {
|
||||||
|
name: string;
|
||||||
|
origName: string;
|
||||||
|
blocks: HDLBlock[];
|
||||||
|
instances: HDLInstanceDef[];
|
||||||
|
vardefs: { [id:string] : HDLVariableDef };
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HDLVariableDef extends HDLDataTypeObject {
|
||||||
|
name: string;
|
||||||
|
origName: string;
|
||||||
|
isInput: boolean;
|
||||||
|
isOutput: boolean;
|
||||||
|
isParam: boolean;
|
||||||
|
constValue?: HDLConstant;
|
||||||
|
initValue?: HDLBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isVarDecl(arg:any): arg is HDLVariableDef {
|
||||||
|
return typeof arg.isParam !== 'undefined';
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HDLConstant extends HDLDataTypeObject {
|
||||||
|
cvalue: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isConstExpr(arg:any): arg is HDLConstant {
|
||||||
|
return typeof arg.cvalue === 'number';
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HDLHierarchyDef extends HDLSourceObject {
|
||||||
|
name: string;
|
||||||
|
module: HDLModuleDef;
|
||||||
|
parent: HDLHierarchyDef;
|
||||||
|
children: HDLHierarchyDef[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HDLInstanceDef extends HDLSourceObject {
|
||||||
|
name: string;
|
||||||
|
origName: string;
|
||||||
|
module: HDLModuleDef;
|
||||||
|
ports: HDLPort[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HDLVarRef extends HDLDataTypeObject {
|
||||||
|
refname: string;
|
||||||
|
//TODO? vardef: HDLVariableDef;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isVarRef(arg:any): arg is HDLVarRef {
|
||||||
|
return arg.refname != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HDLUnop extends HDLDataTypeObject {
|
||||||
|
op: string;
|
||||||
|
left: HDLExpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HDLExtendop extends HDLUnop {
|
||||||
|
width: number;
|
||||||
|
widthminv: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isUnop(arg:any): arg is HDLUnop {
|
||||||
|
return arg.op != null && arg.left != null && arg.right == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HDLBinop extends HDLUnop {
|
||||||
|
right: HDLExpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isBinop(arg:any): arg is HDLBinop {
|
||||||
|
return arg.op != null && arg.left != null && arg.right != null && arg.cond == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HDLTriop extends HDLBinop {
|
||||||
|
cond: HDLExpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isTriop(arg:any): arg is HDLTriop {
|
||||||
|
return arg.op != null && arg.cond != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HDLWhileOp extends HDLDataTypeObject {
|
||||||
|
op: 'while';
|
||||||
|
precond: HDLExpr;
|
||||||
|
loopcond: HDLExpr;
|
||||||
|
body: HDLExpr;
|
||||||
|
inc: HDLExpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isWhileop(arg:any): arg is HDLWhileOp {
|
||||||
|
return arg.op === 'while' && arg.loopcond != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HDLBlock extends HDLSourceObject {
|
||||||
|
blocktype: string;
|
||||||
|
name: string;
|
||||||
|
exprs: HDLExpr[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isBlock(arg:any): arg is HDLBlock {
|
||||||
|
return arg.blocktype != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HDLAlwaysBlock extends HDLBlock {
|
||||||
|
senlist: HDLSensItem[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HDLSensItem extends HDLSourceObject {
|
||||||
|
edgeType : "POS" | "NEG";
|
||||||
|
expr: HDLExpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HDLPort extends HDLSourceObject {
|
||||||
|
name: string;
|
||||||
|
expr: HDLExpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HDLFuncCall extends HDLSourceObject {
|
||||||
|
funcname: string;
|
||||||
|
args: HDLExpr[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isFuncCall(arg:any): arg is HDLFuncCall {
|
||||||
|
return typeof arg.funcname === 'string';
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface HDLArrayItem {
|
||||||
|
index: number;
|
||||||
|
expr: HDLExpr;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function isArrayItem(arg:any): arg is HDLArrayItem {
|
||||||
|
return typeof arg.index === 'number' && arg.expr != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type HDLExpr = HDLVarRef | HDLUnop | HDLBinop | HDLTriop | HDLBlock | HDLVariableDef | HDLFuncCall | HDLConstant;
|
||||||
|
|
||||||
|
export interface HDLUnit {
|
||||||
|
files: { [id: string]: HDLFile };
|
||||||
|
dtypes: { [id: string]: HDLDataType };
|
||||||
|
modules: { [id: string]: HDLModuleDef };
|
||||||
|
hierarchies: { [id: string]: HDLHierarchyDef };
|
||||||
|
}
|
||||||
|
|
||||||
|
export type HDLValue = number | Uint8Array | Uint16Array | Uint32Array | HDLValue[];
|
||||||
|
|
|
@ -0,0 +1,485 @@
|
||||||
|
|
||||||
|
import { HDLBinop, HDLBlock, HDLConstant, HDLDataType, HDLExpr, HDLExtendop, HDLFuncCall, HDLModuleDef, HDLTriop, HDLUnop, HDLValue, HDLVariableDef, HDLVarRef, isArrayItem, isArrayType, isBinop, isBlock, isConstExpr, isFuncCall, isLogicType, isTriop, isUnop, isVarDecl, isVarRef, isWhileop } from "./hdltypes";
|
||||||
|
import binaryen = require('binaryen');
|
||||||
|
|
||||||
|
interface VerilatorUnit {
|
||||||
|
_ctor_var_reset(state) : void;
|
||||||
|
_eval_initial(state) : void;
|
||||||
|
_eval_settle(state) : void;
|
||||||
|
_eval(state) : void;
|
||||||
|
_change_request(state) : boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
const VERILATOR_UNIT_FUNCTIONS = [
|
||||||
|
"_ctor_var_reset",
|
||||||
|
"_eval_initial",
|
||||||
|
"_eval_settle",
|
||||||
|
"_eval",
|
||||||
|
"_change_request"
|
||||||
|
];
|
||||||
|
|
||||||
|
interface Options {
|
||||||
|
store?: boolean;
|
||||||
|
funcblock?: HDLBlock;
|
||||||
|
}
|
||||||
|
|
||||||
|
const GLOBAL = "$$GLOBAL";
|
||||||
|
const CHANGEDET = "$$CHANGE";
|
||||||
|
const MEMORY = "0";
|
||||||
|
|
||||||
|
///
|
||||||
|
|
||||||
|
function getDataTypeSize(dt: HDLDataType) : number {
|
||||||
|
if (isLogicType(dt)) {
|
||||||
|
if (dt.left <= 7)
|
||||||
|
return 1;
|
||||||
|
else if (dt.left <= 15)
|
||||||
|
return 2;
|
||||||
|
else if (dt.left <= 31)
|
||||||
|
return 4;
|
||||||
|
else if (dt.left <= 63)
|
||||||
|
return 8;
|
||||||
|
else
|
||||||
|
return (dt.left >> 6) * 8 + 8; // 64-bit words
|
||||||
|
} else if (isArrayType(dt)) {
|
||||||
|
return (dt.high.cvalue - dt.low.cvalue + 1) * getDataTypeSize(dt.subtype);
|
||||||
|
//return (asValue(dt.high) - asValue(dt.low) + 1) * dt.
|
||||||
|
} else {
|
||||||
|
console.log(dt);
|
||||||
|
throw Error(`don't know data type`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getBinaryenType(size: number) {
|
||||||
|
return size <= 4 || size > 8 ? binaryen.i32 : binaryen.i64
|
||||||
|
}
|
||||||
|
|
||||||
|
interface StructRec {
|
||||||
|
name: string;
|
||||||
|
type: HDLDataType;
|
||||||
|
offset: number;
|
||||||
|
size: number;
|
||||||
|
itype: number;
|
||||||
|
index: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
class Struct {
|
||||||
|
parent : Struct;
|
||||||
|
len : number = 0;
|
||||||
|
vars : {[name: string] : StructRec} = {};
|
||||||
|
locals : StructRec[] = [];
|
||||||
|
params : StructRec[] = [];
|
||||||
|
|
||||||
|
addVar(vardef: HDLVariableDef) {
|
||||||
|
var size = getDataTypeSize(vardef.dtype);
|
||||||
|
return this.addEntry(vardef.name, getBinaryenType(size), size, vardef.dtype, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
addEntry(name: string, itype: number, size: number, hdltype: HDLDataType, isParam: boolean) : StructRec {
|
||||||
|
// pointers are 32 bits, so if size > 8 it's a pointer
|
||||||
|
var rec : StructRec = {
|
||||||
|
name: name,
|
||||||
|
type: hdltype,
|
||||||
|
size: size,
|
||||||
|
itype: itype,
|
||||||
|
index: this.params.length + this.locals.length,
|
||||||
|
offset: this.len,
|
||||||
|
}
|
||||||
|
this.len += 8; //TODO: rec.size, alignment
|
||||||
|
if (rec.name != null) this.vars[rec.name] = rec;
|
||||||
|
if (isParam) this.params.push(rec);
|
||||||
|
else this.locals.push(rec);
|
||||||
|
return rec;
|
||||||
|
}
|
||||||
|
|
||||||
|
getLocals() {
|
||||||
|
var vars = [];
|
||||||
|
for (const rec of this.locals) {
|
||||||
|
vars.push(rec.itype);
|
||||||
|
}
|
||||||
|
return vars;
|
||||||
|
}
|
||||||
|
|
||||||
|
lookup(name: string) : StructRec {
|
||||||
|
return this.vars[name];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class HDLModuleWASM {
|
||||||
|
|
||||||
|
bmod: binaryen.Module;
|
||||||
|
hdlmod: HDLModuleDef;
|
||||||
|
constpool: HDLModuleDef;
|
||||||
|
globals: Struct;
|
||||||
|
locals: Struct;
|
||||||
|
|
||||||
|
constructor(moddef: HDLModuleDef, constpool: HDLModuleDef) {
|
||||||
|
this.hdlmod = moddef;
|
||||||
|
this.constpool = constpool;
|
||||||
|
}
|
||||||
|
|
||||||
|
init() {
|
||||||
|
this.bmod = new binaryen.Module();
|
||||||
|
this.genTypes();
|
||||||
|
this.bmod.setMemory(this.globals.len, this.globals.len, MEMORY); // TODO?
|
||||||
|
this.genFuncs();
|
||||||
|
}
|
||||||
|
|
||||||
|
genTypes() {
|
||||||
|
var state = new Struct();
|
||||||
|
for (const [varname, vardef] of Object.entries(this.hdlmod.vardefs)) {
|
||||||
|
state.addVar(vardef);
|
||||||
|
}
|
||||||
|
this.globals = state;
|
||||||
|
}
|
||||||
|
|
||||||
|
genFuncs() {
|
||||||
|
// function type (dsegptr)
|
||||||
|
var fsig = binaryen.createType([binaryen.i32])
|
||||||
|
for (var block of this.hdlmod.blocks) {
|
||||||
|
// TODO: cfuncs only
|
||||||
|
var fnname = block.name;
|
||||||
|
// find locals of function
|
||||||
|
var fscope = new Struct();
|
||||||
|
fscope.addEntry(GLOBAL, binaryen.i32, 4, null, true); // 1st param to function
|
||||||
|
// add __req local if change_request function
|
||||||
|
if (this.funcResult(block) == binaryen.i32) {
|
||||||
|
fscope.addEntry(CHANGEDET, binaryen.i32, 1, null, false);
|
||||||
|
}
|
||||||
|
this.pushScope(fscope);
|
||||||
|
block.exprs.forEach((e) => {
|
||||||
|
if (e && isVarDecl(e)) {
|
||||||
|
fscope.addVar(e);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// create function body
|
||||||
|
var fbody = this.block2wasm(block, {funcblock:block});
|
||||||
|
//var fbody = this.bmod.return(this.bmod.i32.const(0));
|
||||||
|
var fret = this.funcResult(block);
|
||||||
|
var fref = this.bmod.addFunction(fnname, fsig, fret, fscope.getLocals(), fbody);
|
||||||
|
this.popScope();
|
||||||
|
}
|
||||||
|
// export functions
|
||||||
|
for (var fname of VERILATOR_UNIT_FUNCTIONS) {
|
||||||
|
this.bmod.addFunctionExport(fname, fname);
|
||||||
|
}
|
||||||
|
// create helper functions
|
||||||
|
this.addHelperFunctions();
|
||||||
|
// create wasm module
|
||||||
|
console.log(this.bmod.emitText());
|
||||||
|
//this.bmod.optimize();
|
||||||
|
if (!this.bmod.validate())
|
||||||
|
throw Error(`could not validate wasm module`);
|
||||||
|
//console.log(this.bmod.emitText());
|
||||||
|
this.test();
|
||||||
|
}
|
||||||
|
|
||||||
|
test() {
|
||||||
|
var wasmData = this.bmod.emitBinary();
|
||||||
|
var compiled = new WebAssembly.Module(wasmData);
|
||||||
|
var instance = new WebAssembly.Instance(compiled, {});
|
||||||
|
var mem = (instance.exports[MEMORY] as any).buffer;
|
||||||
|
(instance.exports as any)._ctor_var_reset(0);
|
||||||
|
(instance.exports as any)._eval_initial(0);
|
||||||
|
(instance.exports as any)._eval_settle(0);
|
||||||
|
var data = new Uint8Array(mem);
|
||||||
|
var o_clk = this.globals.lookup('clk').offset;
|
||||||
|
var o_reset = this.globals.lookup('reset').offset
|
||||||
|
data[o_reset] = 1;
|
||||||
|
//new Uint8Array(mem)[this.globals.lookup('reset').offset] = 0;
|
||||||
|
//new Uint8Array(mem)[this.globals.lookup('enable').offset] = 1;
|
||||||
|
for (var i=0; i<20; i++) {
|
||||||
|
data[o_clk] = 0;
|
||||||
|
(instance.exports as any).tick(0);
|
||||||
|
data[o_clk] = 1;
|
||||||
|
(instance.exports as any).tick(0);
|
||||||
|
if (i==5) new Uint8Array(mem)[this.globals.lookup('reset').offset] = 0;
|
||||||
|
}
|
||||||
|
console.log(mem);
|
||||||
|
var t1 = new Date().getTime();
|
||||||
|
var tickiters = 10000;
|
||||||
|
var looplen = Math.round(100000000/tickiters);
|
||||||
|
for (var i=0; i<looplen; i++) {
|
||||||
|
(instance.exports as any).tick2(0,tickiters);
|
||||||
|
}
|
||||||
|
var t2 = new Date().getTime();
|
||||||
|
console.log('wasm:',t2-t1,'msec',i*tickiters,'iterations');
|
||||||
|
console.log(mem);
|
||||||
|
}
|
||||||
|
|
||||||
|
addHelperFunctions() {
|
||||||
|
this.bmod.addFunction("tick",
|
||||||
|
binaryen.createType([binaryen.i32]), // (dataptr)
|
||||||
|
binaryen.i32, // return # of iterations
|
||||||
|
[], // no locals
|
||||||
|
this.makeTickFunction(0)
|
||||||
|
);
|
||||||
|
this.bmod.addFunctionExport("tick", "tick");
|
||||||
|
|
||||||
|
var l_dseg = this.bmod.local.get(0, binaryen.i32);
|
||||||
|
var l_count = this.bmod.local.get(1, binaryen.i32);
|
||||||
|
this.bmod.addFunction("tick2",
|
||||||
|
binaryen.createType([binaryen.i32, binaryen.i32]), // (dataptr, iters)
|
||||||
|
binaryen.none, // return nothing
|
||||||
|
[], // no locals
|
||||||
|
this.bmod.loop("@loop", this.bmod.block(null, [
|
||||||
|
this.makeSetVariableFunction("clk", 0),
|
||||||
|
this.bmod.drop(this.bmod.call("tick", [l_dseg], binaryen.i32)),
|
||||||
|
this.makeSetVariableFunction("clk", 1),
|
||||||
|
this.bmod.drop(this.bmod.call("tick", [l_dseg], binaryen.i32)),
|
||||||
|
// dec $1
|
||||||
|
this.bmod.local.set(1, this.bmod.i32.sub(l_count, this.bmod.i32.const(1))),
|
||||||
|
// goto @loop if $1
|
||||||
|
this.bmod.br_if("@loop", l_count)
|
||||||
|
]))
|
||||||
|
);
|
||||||
|
this.bmod.addFunctionExport("tick2", "tick2");
|
||||||
|
}
|
||||||
|
|
||||||
|
makeSetVariableFunction(name: string, value: number) {
|
||||||
|
var dtype = this.globals.lookup(name).type;
|
||||||
|
var dest : HDLVarRef = {refname:name, dtype:dtype};
|
||||||
|
var src : HDLConstant = {cvalue:value, dtype:dtype};
|
||||||
|
return this.assign2wasm(dest, src);
|
||||||
|
}
|
||||||
|
|
||||||
|
makeTickFunction(count: number) {
|
||||||
|
var dseg = this.bmod.local.get(0, binaryen.i32);
|
||||||
|
if (count > 4)
|
||||||
|
return this.bmod.i32.const(count);
|
||||||
|
return this.bmod.block(null, [
|
||||||
|
this.bmod.call("_eval", [dseg], binaryen.none),
|
||||||
|
this.bmod.if(
|
||||||
|
this.bmod.call("_change_request", [dseg], binaryen.i32),
|
||||||
|
this.makeTickFunction(count+1),
|
||||||
|
this.bmod.return(this.bmod.local.get(0, binaryen.i32))
|
||||||
|
)
|
||||||
|
], binaryen.i32)
|
||||||
|
}
|
||||||
|
|
||||||
|
funcResult(func: HDLBlock) {
|
||||||
|
// only _change functions return a result
|
||||||
|
return func.name.startsWith("_change_request") ? binaryen.i32 : binaryen.none;
|
||||||
|
}
|
||||||
|
|
||||||
|
pushScope(scope: Struct) {
|
||||||
|
scope.parent = this.locals;
|
||||||
|
this.locals = scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
popScope() {
|
||||||
|
this.locals = this.locals.parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
i3264(dt: HDLDataType) {
|
||||||
|
var size = getDataTypeSize(dt);
|
||||||
|
var type = getBinaryenType(size);
|
||||||
|
if (type == binaryen.i32) return this.bmod.i32;
|
||||||
|
else if (type == binaryen.i64) return this.bmod.i64;
|
||||||
|
else throw Error();
|
||||||
|
}
|
||||||
|
|
||||||
|
dataptr() : number {
|
||||||
|
return this.bmod.local.get(0, binaryen.i32); // 1st param of function == data ptr
|
||||||
|
}
|
||||||
|
|
||||||
|
e2w(e: HDLExpr, opts?:Options) : number {
|
||||||
|
if (e == null) {
|
||||||
|
return this.bmod.nop();
|
||||||
|
} else if (isBlock(e)) {
|
||||||
|
return this.block2wasm(e, opts);
|
||||||
|
} else if (isVarDecl(e)) {
|
||||||
|
return this.local2wasm(e, opts);
|
||||||
|
} else if (isVarRef(e)) {
|
||||||
|
return this.varref2wasm(e, opts);
|
||||||
|
} else if (isConstExpr(e)) {
|
||||||
|
return this.const2wasm(e, opts);
|
||||||
|
} else if (isFuncCall(e)) {
|
||||||
|
return this.funccall2wasm(e, opts);
|
||||||
|
} else if (isUnop(e) || isBinop(e) || isTriop(e) || isWhileop(e)) {
|
||||||
|
var n = `_${e.op}2wasm`;
|
||||||
|
var fn = this[n];
|
||||||
|
if (fn == null) { console.log(e); throw Error(`no such method ${n}`) }
|
||||||
|
return this[n](e, opts);
|
||||||
|
} else {
|
||||||
|
console.log('expr', e);
|
||||||
|
throw Error(`could not translate expr`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
block2wasm(e: HDLBlock, opts?:Options) : number {
|
||||||
|
var stmts = e.exprs.map((stmt) => this.e2w(stmt));
|
||||||
|
var ret = opts && opts.funcblock ? this.funcResult(opts.funcblock) : binaryen.none;
|
||||||
|
if (ret == binaryen.i32) { // must have return value
|
||||||
|
stmts.push(this.bmod.return(this.bmod.local.get(this.locals.lookup(CHANGEDET).index, ret)));
|
||||||
|
}
|
||||||
|
return this.bmod.block(e.name, stmts, ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
funccall2wasm(e: HDLFuncCall, opts?:Options) : number {
|
||||||
|
var args = [this.dataptr()];
|
||||||
|
var ret = e.funcname.startsWith("_change_request") ? binaryen.i32 : binaryen.none;
|
||||||
|
return this.bmod.call(e.funcname, args, ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
const2wasm(e: HDLConstant, opts: Options) : number {
|
||||||
|
var size = getDataTypeSize(e.dtype);
|
||||||
|
if (isLogicType(e.dtype)) {
|
||||||
|
if (size <= 4)
|
||||||
|
return this.bmod.i32.const(e.cvalue);
|
||||||
|
else
|
||||||
|
throw new Error(`constants > 32 bits not supported`)
|
||||||
|
} else {
|
||||||
|
console.log(e);
|
||||||
|
throw new Error(`non-logic constants not supported`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
varref2wasm(e: HDLVarRef, opts: Options) : number {
|
||||||
|
if (opts && opts.store) throw Error(`cannot store here`);
|
||||||
|
var local = this.locals && this.locals.lookup(e.refname);
|
||||||
|
var global = this.globals.lookup(e.refname);
|
||||||
|
if (local != null) {
|
||||||
|
return this.bmod.local.get(local.index, local.itype);
|
||||||
|
} else if (global != null) {
|
||||||
|
if (global.size == 1) {
|
||||||
|
return this.bmod.i32.load8_u(global.offset, 1, this.dataptr());
|
||||||
|
} else if (global.size == 2) {
|
||||||
|
return this.bmod.i32.load16_u(global.offset, 2, this.dataptr());
|
||||||
|
} else if (global.size == 4) {
|
||||||
|
return this.bmod.i32.load(global.offset, 4, this.dataptr());
|
||||||
|
} else if (global.size == 8) {
|
||||||
|
return this.bmod.i64.load(global.offset, 8, this.dataptr());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new Error(`cannot lookup variable ${e.refname}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
local2wasm(e: HDLVariableDef, opts:Options) : number {
|
||||||
|
var local = this.locals.lookup(e.name);
|
||||||
|
if (local == null) throw Error(`no local for ${e.name}`)
|
||||||
|
return this.bmod.nop(); // TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
assign2wasm(dest: HDLExpr, src: HDLExpr) {
|
||||||
|
var value = this.e2w(src);
|
||||||
|
if (isVarRef(dest)) {
|
||||||
|
var local = this.locals && this.locals.lookup(dest.refname);
|
||||||
|
var global = this.globals.lookup(dest.refname);
|
||||||
|
if (local != null) {
|
||||||
|
return this.bmod.local.set(local.index, value);
|
||||||
|
} else if (global != null) {
|
||||||
|
if (global.size == 1) {
|
||||||
|
return this.bmod.i32.store8(global.offset, 1, this.dataptr(), value);
|
||||||
|
} else if (global.size == 2) {
|
||||||
|
return this.bmod.i32.store16(global.offset, 2, this.dataptr(), value);
|
||||||
|
} else if (global.size == 4) {
|
||||||
|
return this.bmod.i32.store(global.offset, 4, this.dataptr(), value);
|
||||||
|
} else if (global.size == 8) {
|
||||||
|
return this.bmod.i64.store(global.offset, 8, this.dataptr(), value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(dest, src);
|
||||||
|
throw new Error(`cannot complete assignment`);
|
||||||
|
}
|
||||||
|
|
||||||
|
_assign2wasm(e: HDLBinop, opts:Options) {
|
||||||
|
return this.assign2wasm(e.right, e.left);
|
||||||
|
}
|
||||||
|
_assignpre2wasm(e: HDLBinop, opts:Options) {
|
||||||
|
return this._assign2wasm(e, opts);
|
||||||
|
}
|
||||||
|
_assigndly2wasm(e: HDLBinop, opts:Options) {
|
||||||
|
return this._assign2wasm(e, opts);
|
||||||
|
}
|
||||||
|
_assignpost2wasm(e: HDLBinop, opts:Options) {
|
||||||
|
return this._assign2wasm(e, opts);
|
||||||
|
}
|
||||||
|
_contassign2wasm(e: HDLBinop, opts:Options) {
|
||||||
|
return this._assign2wasm(e, opts);
|
||||||
|
}
|
||||||
|
|
||||||
|
_if2wasm(e: HDLTriop, opts:Options) {
|
||||||
|
return this.bmod.if(this.e2w(e.cond), this.e2w(e.left), this.e2w(e.right));
|
||||||
|
}
|
||||||
|
_cond2wasm(e: HDLTriop, opts:Options) {
|
||||||
|
return this.bmod.select(this.e2w(e.cond), this.e2w(e.left), this.e2w(e.right));
|
||||||
|
}
|
||||||
|
|
||||||
|
_ccast2wasm(e: HDLUnop, opts:Options) {
|
||||||
|
return this.e2w(e.left, opts);
|
||||||
|
}
|
||||||
|
_creset2wasm(e: HDLUnop, opts:Options) {
|
||||||
|
// TODO return this.e2w(e.left, opts);
|
||||||
|
return this.bmod.nop();
|
||||||
|
}
|
||||||
|
_creturn2wasm(e: HDLUnop, opts:Options) {
|
||||||
|
return this.bmod.return(this.e2w(e.left, opts));
|
||||||
|
}
|
||||||
|
|
||||||
|
_not2wasm(e: HDLUnop, opts:Options) {
|
||||||
|
var inst = this.i3264(e.dtype);
|
||||||
|
return inst.xor(inst.const(-1, -1), this.e2w(e.left, opts));
|
||||||
|
}
|
||||||
|
_changedet2wasm(e: HDLBinop, opts:Options) {
|
||||||
|
var req = this.locals.lookup(CHANGEDET);
|
||||||
|
if (!req) throw Error(`no changedet local`);
|
||||||
|
var left = this.e2w(e.left);
|
||||||
|
var right = this.e2w(e.right);
|
||||||
|
return this.bmod.block(null, [
|
||||||
|
// $$req |= (${this.expr2js(e.left)} ^ ${this.expr2js(e.right)})
|
||||||
|
this.bmod.local.set(req.index,
|
||||||
|
this.bmod.i32.or(
|
||||||
|
this.bmod.local.get(req.index, req.itype),
|
||||||
|
this.bmod.i32.xor(left, right) // TODO: i64?
|
||||||
|
)
|
||||||
|
),
|
||||||
|
// ${this.expr2js(e.right)} = ${this.expr2js(e.left)}`
|
||||||
|
this.assign2wasm(e.right, e.left)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
_or2wasm(e: HDLBinop, opts:Options) {
|
||||||
|
return this.i3264(e.dtype).or(this.e2w(e.left), this.e2w(e.right));
|
||||||
|
}
|
||||||
|
_and2wasm(e: HDLBinop, opts:Options) {
|
||||||
|
return this.i3264(e.dtype).and(this.e2w(e.left), this.e2w(e.right));
|
||||||
|
}
|
||||||
|
_xor2wasm(e: HDLBinop, opts:Options) {
|
||||||
|
return this.i3264(e.dtype).xor(this.e2w(e.left), this.e2w(e.right));
|
||||||
|
}
|
||||||
|
_shiftl2wasm(e: HDLBinop, opts:Options) {
|
||||||
|
return this.i3264(e.dtype).shl(this.e2w(e.left), this.e2w(e.right));
|
||||||
|
}
|
||||||
|
_shiftr2wasm(e: HDLBinop, opts:Options) {
|
||||||
|
// TODO: signed?
|
||||||
|
return this.i3264(e.dtype).shr_u(this.e2w(e.left), this.e2w(e.right));
|
||||||
|
}
|
||||||
|
_add2wasm(e: HDLBinop, opts:Options) {
|
||||||
|
return this.i3264(e.dtype).add(this.e2w(e.left), this.e2w(e.right));
|
||||||
|
}
|
||||||
|
_sub2wasm(e: HDLBinop, opts:Options) {
|
||||||
|
return this.i3264(e.dtype).sub(this.e2w(e.left), this.e2w(e.right));
|
||||||
|
}
|
||||||
|
|
||||||
|
_eq2wasm(e: HDLBinop, opts:Options) {
|
||||||
|
return this.i3264(e.dtype).eq(this.e2w(e.left), this.e2w(e.right));
|
||||||
|
}
|
||||||
|
_neq2wasm(e: HDLBinop, opts:Options) {
|
||||||
|
return this.i3264(e.dtype).ne(this.e2w(e.left), this.e2w(e.right));
|
||||||
|
}
|
||||||
|
_lt2wasm(e: HDLBinop, opts:Options) {
|
||||||
|
return this.i3264(e.dtype).lt_u(this.e2w(e.left), this.e2w(e.right));
|
||||||
|
}
|
||||||
|
_gt2wasm(e: HDLBinop, opts:Options) {
|
||||||
|
return this.i3264(e.dtype).gt_u(this.e2w(e.left), this.e2w(e.right));
|
||||||
|
}
|
||||||
|
_lte2wasm(e: HDLBinop, opts:Options) {
|
||||||
|
return this.i3264(e.dtype).le_u(this.e2w(e.left), this.e2w(e.right));
|
||||||
|
}
|
||||||
|
_gte2wasm(e: HDLBinop, opts:Options) {
|
||||||
|
return this.i3264(e.dtype).ge_u(this.e2w(e.left), this.e2w(e.right));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,669 @@
|
||||||
|
|
||||||
|
import { HDLAlwaysBlock, HDLArrayItem, HDLBinop, HDLBlock, HDLConstant, HDLDataType, HDLDataTypeObject, HDLExpr, HDLExtendop, HDLFile, HDLFuncCall, HDLHierarchyDef, HDLInstanceDef, HDLLogicType, HDLModuleDef, HDLNativeType, HDLPort, HDLSensItem, HDLSourceLocation, HDLTriop, HDLUnit, HDLUnop, HDLUnpackArray, HDLValue, HDLVariableDef, HDLVarRef, HDLWhileOp, isArrayType, isBinop, isBlock, isConstExpr, isFuncCall, isLogicType, isTriop, isUnop, isVarDecl, isVarRef } from "./hdltypes";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whaa?
|
||||||
|
*
|
||||||
|
* Each hierarchy takes (uint32[] -> uint32[])
|
||||||
|
* - convert to/from js object
|
||||||
|
* - JS or WASM
|
||||||
|
* - Fixed-size packets
|
||||||
|
* - state is another uint32[]
|
||||||
|
* Find optimal packing of bits
|
||||||
|
* Find clocks
|
||||||
|
* Find pivots (reset, state) concat them together
|
||||||
|
* Dependency cycles
|
||||||
|
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer
|
||||||
|
*/
|
||||||
|
|
||||||
|
interface XMLNode {
|
||||||
|
type: string;
|
||||||
|
text: string | null;
|
||||||
|
children: XMLNode[];
|
||||||
|
attrs: { [id: string]: string };
|
||||||
|
obj: any;
|
||||||
|
}
|
||||||
|
|
||||||
|
type XMLVisitFunction = (node: XMLNode) => any;
|
||||||
|
|
||||||
|
function escapeXML(s: string): string {
|
||||||
|
if (s.indexOf('&') >= 0) {
|
||||||
|
return s.replace(/'/g, "'")
|
||||||
|
.replace(/"/g, '"')
|
||||||
|
.replace(/>/g, '>')
|
||||||
|
.replace(/</g, '<')
|
||||||
|
.replace(/&/g, '&');
|
||||||
|
} else {
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseXMLPoorly(s: string, openfn?: XMLVisitFunction, closefn?: XMLVisitFunction): XMLNode {
|
||||||
|
const tag_re = /[<]([/]?)([?a-z_-]+)([^>]*)[>]+|(\s*[^<]+)/gi;
|
||||||
|
const attr_re = /\s*(\w+)="(.*?)"\s*/gi;
|
||||||
|
var fm: RegExpMatchArray;
|
||||||
|
var stack: XMLNode[] = [];
|
||||||
|
var top: XMLNode;
|
||||||
|
|
||||||
|
function closetop() {
|
||||||
|
top = stack.pop();
|
||||||
|
if (top.type != ident) throw Error("mismatch close tag: " + ident);
|
||||||
|
if (closefn) {
|
||||||
|
top.obj = closefn(top);
|
||||||
|
}
|
||||||
|
stack[stack.length - 1].children.push(top);
|
||||||
|
}
|
||||||
|
function parseattrs(as: string): { [id: string]: string } {
|
||||||
|
var am;
|
||||||
|
var attrs = {};
|
||||||
|
if (as != null) {
|
||||||
|
while (am = attr_re.exec(as)) {
|
||||||
|
attrs[am[1]] = escapeXML(am[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return attrs;
|
||||||
|
}
|
||||||
|
while (fm = tag_re.exec(s)) {
|
||||||
|
var [_m0, close, ident, attrs, content] = fm;
|
||||||
|
//console.log(stack.length, close, ident, attrs, content);
|
||||||
|
if (close) {
|
||||||
|
closetop();
|
||||||
|
} else if (ident) {
|
||||||
|
var node = { type: ident, text: null, children: [], attrs: parseattrs(attrs), obj: null };
|
||||||
|
stack.push(node);
|
||||||
|
if (attrs) {
|
||||||
|
parseattrs(attrs);
|
||||||
|
}
|
||||||
|
if (openfn) {
|
||||||
|
node.obj = openfn(node);
|
||||||
|
}
|
||||||
|
if (attrs && attrs.endsWith('/')) closetop();
|
||||||
|
} else if (content != null) {
|
||||||
|
var txt = escapeXML(content as string).trim();
|
||||||
|
if (txt.length) stack[stack.length - 1].text = txt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (stack.length != 1) throw Error("tag not closed");
|
||||||
|
if (stack[0].type != '?xml') throw Error("?xml needs to be first element");
|
||||||
|
return top;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class CompileError extends Error {
|
||||||
|
$loc : HDLSourceLocation;
|
||||||
|
constructor(msg: string, loc: HDLSourceLocation) {
|
||||||
|
super(msg);
|
||||||
|
Object.setPrototypeOf(this, CompileError.prototype);
|
||||||
|
this.$loc = loc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class VerilogXMLParser implements HDLUnit {
|
||||||
|
|
||||||
|
files: { [id: string]: HDLFile } = {};
|
||||||
|
dtypes: { [id: string]: HDLDataType } = {};
|
||||||
|
modules: { [id: string]: HDLModuleDef } = {};
|
||||||
|
hierarchies: { [id: string]: HDLHierarchyDef } = {};
|
||||||
|
|
||||||
|
cur_node : XMLNode;
|
||||||
|
cur_module : HDLModuleDef;
|
||||||
|
cur_deferred = [];
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
// TODO: other types
|
||||||
|
this.dtypes['IData'] = {left:31, right:0};
|
||||||
|
}
|
||||||
|
|
||||||
|
defer(fn: () => void) {
|
||||||
|
this.cur_deferred.unshift(fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
defer2(fn: () => void) {
|
||||||
|
this.cur_deferred.push(fn);
|
||||||
|
}
|
||||||
|
|
||||||
|
run_deferred() {
|
||||||
|
this.cur_deferred.forEach((fn) => fn());
|
||||||
|
this.cur_deferred = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
name2js(s: string) {
|
||||||
|
return s.replace(/[^a-z0-9_]/gi, '$');
|
||||||
|
}
|
||||||
|
|
||||||
|
findChildren(node: XMLNode, type: string, required: boolean) : XMLNode[] {
|
||||||
|
var arr = node.children.filter((n) => n.type == type);
|
||||||
|
if (arr.length == 0 && required) throw Error(`no child of type ${type}`);
|
||||||
|
return arr;
|
||||||
|
}
|
||||||
|
|
||||||
|
parseSourceLocation(node: XMLNode): HDLSourceLocation {
|
||||||
|
var loc = node.attrs['loc'];
|
||||||
|
if (loc) {
|
||||||
|
var [fileid, line, col, end_line, end_col] = loc.split(',');
|
||||||
|
return {
|
||||||
|
file: this.files[fileid],
|
||||||
|
line: parseInt(line),
|
||||||
|
col: parseInt(col),
|
||||||
|
end_line: parseInt(line),
|
||||||
|
end_col: parseInt(col),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open_module(node: XMLNode) {
|
||||||
|
var module: HDLModuleDef = {
|
||||||
|
$loc: this.parseSourceLocation(node),
|
||||||
|
name: node.attrs['name'],
|
||||||
|
origName: node.attrs['origName'],
|
||||||
|
blocks: [],
|
||||||
|
instances: [],
|
||||||
|
vardefs: {},
|
||||||
|
}
|
||||||
|
this.cur_module = module;
|
||||||
|
return module;
|
||||||
|
}
|
||||||
|
|
||||||
|
deferDataType(node: XMLNode, def: HDLDataTypeObject) {
|
||||||
|
var dtype_id = node.attrs['dtype_id'];
|
||||||
|
if (dtype_id != null) {
|
||||||
|
this.defer(() => {
|
||||||
|
def.dtype = this.dtypes[dtype_id];
|
||||||
|
if (!def.dtype) {
|
||||||
|
console.log(node);
|
||||||
|
throw Error(`Unknown data type ${dtype_id} for ${node.type}`);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parseConstValue(s: string) : number {
|
||||||
|
const re_const = /(\d+)'([s]?)h([0-9a-f]+)/i;
|
||||||
|
var m = re_const.exec(s);
|
||||||
|
if (m) {
|
||||||
|
return parseInt(m[3], 16);
|
||||||
|
} else {
|
||||||
|
throw Error(`could not parse constant "${s}"`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resolveVar(s: string, mod: HDLModuleDef) : HDLVariableDef {
|
||||||
|
var def = mod.vardefs[s];
|
||||||
|
if (def == null) throw Error(`could not resolve variable "${s}"`);
|
||||||
|
return def;
|
||||||
|
}
|
||||||
|
|
||||||
|
resolveModule(s: string) : HDLModuleDef {
|
||||||
|
var mod = this.modules[s];
|
||||||
|
if (mod == null) throw Error(`could not resolve module "${s}"`);
|
||||||
|
return mod;
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
visit_verilator_xml(node: XMLNode) {
|
||||||
|
}
|
||||||
|
|
||||||
|
visit_module(node: XMLNode) {
|
||||||
|
this.findChildren(node, 'var', false).forEach((n) => {
|
||||||
|
if (isVarDecl(n.obj)) {
|
||||||
|
this.cur_module.vardefs[n.obj.name] = n.obj;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.modules[this.cur_module.name] = this.cur_module;
|
||||||
|
this.cur_module = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
visit_var(node: XMLNode) : HDLVariableDef {
|
||||||
|
var name = node.attrs['name'];
|
||||||
|
name = this.name2js(name);
|
||||||
|
var vardef: HDLVariableDef = {
|
||||||
|
$loc: this.parseSourceLocation(node),
|
||||||
|
name: name,
|
||||||
|
origName: node.attrs['origName'],
|
||||||
|
isInput: node.attrs['dir'] == 'input',
|
||||||
|
isOutput: node.attrs['dir'] == 'output',
|
||||||
|
isParam: node.attrs['param'] == 'true',
|
||||||
|
dtype: null,
|
||||||
|
}
|
||||||
|
this.deferDataType(node, vardef);
|
||||||
|
var const_nodes = this.findChildren(node, 'const', false);
|
||||||
|
if (const_nodes.length) {
|
||||||
|
vardef.constValue = const_nodes[0].obj;
|
||||||
|
}
|
||||||
|
var init_nodes = this.findChildren(node, 'initarray', false);
|
||||||
|
if (init_nodes.length) {
|
||||||
|
vardef.initValue = init_nodes[0].obj;
|
||||||
|
}
|
||||||
|
return vardef;
|
||||||
|
}
|
||||||
|
|
||||||
|
visit_const(node: XMLNode) : HDLConstant {
|
||||||
|
var name = node.attrs['name'];
|
||||||
|
var constdef: HDLConstant = {
|
||||||
|
$loc: this.parseSourceLocation(node),
|
||||||
|
dtype: null,
|
||||||
|
cvalue: this.parseConstValue(name)
|
||||||
|
}
|
||||||
|
this.deferDataType(node, constdef);
|
||||||
|
return constdef;
|
||||||
|
}
|
||||||
|
|
||||||
|
visit_varref(node: XMLNode) : HDLVarRef {
|
||||||
|
var name = node.attrs['name'];
|
||||||
|
name = this.name2js(name);
|
||||||
|
var varref: HDLVarRef = {
|
||||||
|
$loc: this.parseSourceLocation(node),
|
||||||
|
dtype: null,
|
||||||
|
refname: name
|
||||||
|
}
|
||||||
|
this.deferDataType(node, varref);
|
||||||
|
var mod = this.cur_module;
|
||||||
|
/*
|
||||||
|
this.defer2(() => {
|
||||||
|
varref.vardef = this.resolveVar(name, mod);
|
||||||
|
});
|
||||||
|
*/
|
||||||
|
return varref;
|
||||||
|
}
|
||||||
|
|
||||||
|
visit_sentree(node: XMLNode) {
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
visit_always(node: XMLNode) : HDLAlwaysBlock {
|
||||||
|
// TODO
|
||||||
|
var sentree : HDLSensItem[];
|
||||||
|
var expr : HDLExpr;
|
||||||
|
if (node.children.length == 2) {
|
||||||
|
sentree = node.children[0].obj as HDLSensItem[];
|
||||||
|
expr = node.children[1].obj as HDLExpr;
|
||||||
|
// TODO: check sentree
|
||||||
|
} else {
|
||||||
|
sentree = null;
|
||||||
|
expr = node.children[0].obj as HDLExpr;
|
||||||
|
}
|
||||||
|
var always: HDLAlwaysBlock = {
|
||||||
|
$loc: this.parseSourceLocation(node),
|
||||||
|
blocktype: node.type,
|
||||||
|
name: null,
|
||||||
|
senlist: sentree,
|
||||||
|
exprs: [expr],
|
||||||
|
};
|
||||||
|
this.cur_module.blocks.push(always);
|
||||||
|
return always;
|
||||||
|
}
|
||||||
|
|
||||||
|
visit_begin(node: XMLNode) : HDLBlock {
|
||||||
|
var exprs = [];
|
||||||
|
node.children.forEach((n) => exprs.push(n.obj));
|
||||||
|
return {
|
||||||
|
$loc: this.parseSourceLocation(node),
|
||||||
|
blocktype: node.type,
|
||||||
|
name: node.attrs['name'],
|
||||||
|
exprs: exprs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
visit_initarray(node: XMLNode) : HDLBlock {
|
||||||
|
return this.visit_begin(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
visit_inititem(node: XMLNode) : HDLArrayItem {
|
||||||
|
if (node.children.length != 1) throw Error('expected 1 children');
|
||||||
|
return {
|
||||||
|
index: parseInt(node.attrs['index']),
|
||||||
|
expr: node.children[0].obj
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
visit_cfunc(node: XMLNode) : HDLBlock {
|
||||||
|
var block = this.visit_begin(node);
|
||||||
|
block.exprs = [];
|
||||||
|
node.children.forEach((n) => block.exprs.push(n.obj));
|
||||||
|
this.cur_module.blocks.push(block);
|
||||||
|
return block;
|
||||||
|
}
|
||||||
|
|
||||||
|
visit_instance(node: XMLNode) : HDLInstanceDef {
|
||||||
|
var instance : HDLInstanceDef = {
|
||||||
|
$loc: this.parseSourceLocation(node),
|
||||||
|
name: node.attrs['name'],
|
||||||
|
origName: node.attrs['origName'],
|
||||||
|
ports: [],
|
||||||
|
module: null,
|
||||||
|
}
|
||||||
|
node.children.forEach((child) => {
|
||||||
|
instance.ports.push(child.obj);
|
||||||
|
})
|
||||||
|
this.cur_module.instances.push(instance);
|
||||||
|
this.defer(() => {
|
||||||
|
instance.module = this.resolveModule(node.attrs['defName']);
|
||||||
|
})
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
visit_port(node: XMLNode) : HDLPort {
|
||||||
|
if (node.children.length != 1) throw Error('expected 1 children');
|
||||||
|
var varref: HDLPort = {
|
||||||
|
$loc: this.parseSourceLocation(node),
|
||||||
|
name: node.attrs['name'],
|
||||||
|
expr: node.children[0].obj
|
||||||
|
}
|
||||||
|
return varref;
|
||||||
|
}
|
||||||
|
|
||||||
|
visit_netlist(node: XMLNode) {
|
||||||
|
}
|
||||||
|
|
||||||
|
visit_files(node: XMLNode) {
|
||||||
|
}
|
||||||
|
|
||||||
|
visit_module_files(node: XMLNode) {
|
||||||
|
node.children.forEach((n) => this.files[(n.obj as HDLFile).id].isModule = true);
|
||||||
|
}
|
||||||
|
|
||||||
|
visit_file(node: XMLNode) {
|
||||||
|
return this.visit_file_or_module(node, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
visit_scope(node: XMLNode) {
|
||||||
|
}
|
||||||
|
|
||||||
|
visit_topscope(node: XMLNode) {
|
||||||
|
}
|
||||||
|
|
||||||
|
visit_file_or_module(node: XMLNode, isModule: boolean) : HDLFile {
|
||||||
|
var file : HDLFile = {
|
||||||
|
id: node.attrs['id'],
|
||||||
|
filename: node.attrs['filename'],
|
||||||
|
isModule: isModule,
|
||||||
|
}
|
||||||
|
this.files[file.id] = file;
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
|
||||||
|
visit_cells(node: XMLNode) {
|
||||||
|
var hier = node.children[0].obj as HDLHierarchyDef;
|
||||||
|
var hiername = hier.name;
|
||||||
|
this.hierarchies[hiername] = hier;
|
||||||
|
}
|
||||||
|
|
||||||
|
visit_cell(node: XMLNode) : HDLHierarchyDef {
|
||||||
|
var hier = {
|
||||||
|
$loc: this.parseSourceLocation(node),
|
||||||
|
name: node.attrs['name'],
|
||||||
|
module: null,
|
||||||
|
parent: null,
|
||||||
|
children: node.children.map((n) => n.obj),
|
||||||
|
}
|
||||||
|
node.children.forEach((n) => (n.obj as HDLHierarchyDef).parent = hier);
|
||||||
|
this.defer(() => {
|
||||||
|
hier.module = this.resolveModule(node.attrs['submodname']);
|
||||||
|
})
|
||||||
|
return hier;
|
||||||
|
}
|
||||||
|
|
||||||
|
visit_basicdtype(node: XMLNode): HDLDataType {
|
||||||
|
let id = node.attrs['id'];
|
||||||
|
var dtype: HDLDataType;
|
||||||
|
var dtypename = node.attrs['name'];
|
||||||
|
switch (dtypename) {
|
||||||
|
case 'logic':
|
||||||
|
case 'integer': // TODO?
|
||||||
|
case 'bit':
|
||||||
|
let dlogic: HDLLogicType = {
|
||||||
|
$loc: this.parseSourceLocation(node),
|
||||||
|
left: parseInt(node.attrs['left'] || "0"),
|
||||||
|
right: parseInt(node.attrs['right'] || "0"),
|
||||||
|
}
|
||||||
|
dtype = dlogic;
|
||||||
|
break;
|
||||||
|
case 'string':
|
||||||
|
let dstring: HDLNativeType = {
|
||||||
|
$loc: this.parseSourceLocation(node),
|
||||||
|
jstype: 'string'
|
||||||
|
}
|
||||||
|
dtype = dstring;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dtype = this.dtypes[dtypename];
|
||||||
|
if (dtype == null) {
|
||||||
|
console.log(node);
|
||||||
|
throw Error(`unknown data type ${dtypename}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.dtypes[id] = dtype;
|
||||||
|
return dtype;
|
||||||
|
}
|
||||||
|
|
||||||
|
visit_unpackarraydtype(node: XMLNode): HDLDataType {
|
||||||
|
let id = node.attrs['id'];
|
||||||
|
let sub_dtype_id = node.attrs['sub_dtype_id'];
|
||||||
|
let range = node.children[0].obj as HDLBinop;
|
||||||
|
if (isConstExpr(range.left) && isConstExpr(range.right)) {
|
||||||
|
var dtype: HDLUnpackArray = {
|
||||||
|
$loc: this.parseSourceLocation(node),
|
||||||
|
subtype: null,
|
||||||
|
low: range.left,
|
||||||
|
high: range.right,
|
||||||
|
}
|
||||||
|
this.dtypes[id] = dtype;
|
||||||
|
this.defer(() => {
|
||||||
|
dtype.subtype = this.dtypes[sub_dtype_id];
|
||||||
|
if (!dtype.subtype) throw Error(`Unknown data type ${sub_dtype_id} for array`);
|
||||||
|
})
|
||||||
|
return dtype;
|
||||||
|
} else {
|
||||||
|
throw Error(`could not parse constant exprs in array`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
visit_senitem(node: XMLNode) : HDLSensItem {
|
||||||
|
var edgeType = node.attrs['edgeType'];
|
||||||
|
if (edgeType != "POS" && edgeType != "NEG")
|
||||||
|
throw Error("POS/NEG required")
|
||||||
|
return {
|
||||||
|
$loc: this.parseSourceLocation(node),
|
||||||
|
edgeType: edgeType,
|
||||||
|
expr: node.obj
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
visit_text(node: XMLNode) {
|
||||||
|
}
|
||||||
|
|
||||||
|
visit_cstmt(node: XMLNode) {
|
||||||
|
}
|
||||||
|
|
||||||
|
visit_cfile(node: XMLNode) {
|
||||||
|
}
|
||||||
|
|
||||||
|
visit_typetable(node: XMLNode) {
|
||||||
|
}
|
||||||
|
|
||||||
|
visit_constpool(node: XMLNode) {
|
||||||
|
}
|
||||||
|
|
||||||
|
__visit_unop(node: XMLNode) : HDLUnop {
|
||||||
|
if (node.children.length != 1) throw Error('expected 1 children');
|
||||||
|
var expr: HDLUnop = {
|
||||||
|
$loc: this.parseSourceLocation(node),
|
||||||
|
op: node.type,
|
||||||
|
dtype: null,
|
||||||
|
left: node.children[0].obj as HDLExpr,
|
||||||
|
}
|
||||||
|
this.deferDataType(node, expr);
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
visit_extends(node: XMLNode) : HDLUnop {
|
||||||
|
var unop = this.__visit_unop(node) as HDLExtendop;
|
||||||
|
unop.width = parseInt(node.attrs['width']);
|
||||||
|
unop.widthminv = parseInt(node.attrs['widthminv']);
|
||||||
|
if (unop.width != 32) throw Error(`extends width ${unop.width} != 32`)
|
||||||
|
return unop;
|
||||||
|
}
|
||||||
|
|
||||||
|
__visit_binop(node: XMLNode) : HDLBinop {
|
||||||
|
if (node.children.length != 2) throw Error('expected 2 children');
|
||||||
|
var expr: HDLBinop = {
|
||||||
|
$loc: this.parseSourceLocation(node),
|
||||||
|
op: node.type,
|
||||||
|
dtype: null,
|
||||||
|
left: node.children[0].obj as HDLExpr,
|
||||||
|
right: node.children[1].obj as HDLExpr,
|
||||||
|
}
|
||||||
|
this.deferDataType(node, expr);
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
visit_if(node: XMLNode) : HDLTriop {
|
||||||
|
if (node.children.length < 2 || node.children.length > 3) throw Error('expected 2 or 3 children');
|
||||||
|
var expr: HDLTriop = {
|
||||||
|
$loc: this.parseSourceLocation(node),
|
||||||
|
op: 'if',
|
||||||
|
dtype: null,
|
||||||
|
cond: node.children[0].obj as HDLExpr,
|
||||||
|
left: node.children[1].obj as HDLExpr,
|
||||||
|
right: node.children[2] && node.children[2].obj as HDLExpr,
|
||||||
|
}
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// while and for loops
|
||||||
|
visit_while(node: XMLNode) : HDLWhileOp {
|
||||||
|
if (node.children.length < 2 || node.children.length > 4) throw Error('expected 2-4 children');
|
||||||
|
var expr: HDLWhileOp = {
|
||||||
|
$loc: this.parseSourceLocation(node),
|
||||||
|
op: 'while',
|
||||||
|
dtype: null,
|
||||||
|
precond: node.children[0].obj as HDLExpr,
|
||||||
|
loopcond: node.children[1].obj as HDLExpr,
|
||||||
|
body: node.children[2] && node.children[2].obj as HDLExpr,
|
||||||
|
inc: node.children[3] && node.children[3].obj as HDLExpr,
|
||||||
|
}
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
__visit_triop(node: XMLNode) : HDLBinop {
|
||||||
|
if (node.children.length != 3) throw Error('expected 2 children');
|
||||||
|
var expr: HDLTriop = {
|
||||||
|
$loc: this.parseSourceLocation(node),
|
||||||
|
op: node.type,
|
||||||
|
dtype: null,
|
||||||
|
cond: node.children[0].obj as HDLExpr,
|
||||||
|
left: node.children[1].obj as HDLExpr,
|
||||||
|
right: node.children[2].obj as HDLExpr,
|
||||||
|
}
|
||||||
|
this.deferDataType(node, expr);
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
|
||||||
|
__visit_func(node: XMLNode) : HDLFuncCall {
|
||||||
|
return {
|
||||||
|
$loc: this.parseSourceLocation(node),
|
||||||
|
funcname: node.attrs['func'] || ('$' + node.type),
|
||||||
|
args: node.children.map(n => n.obj as HDLExpr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
visit_not(node: XMLNode) { return this.__visit_unop(node); }
|
||||||
|
visit_negate(node: XMLNode) { return this.__visit_unop(node); }
|
||||||
|
visit_redand(node: XMLNode) { return this.__visit_unop(node); }
|
||||||
|
visit_redor(node: XMLNode) { return this.__visit_unop(node); }
|
||||||
|
visit_redxor(node: XMLNode) { return this.__visit_unop(node); }
|
||||||
|
visit_initial(node: XMLNode) { return this.__visit_unop(node); }
|
||||||
|
visit_ccast(node: XMLNode) { return this.__visit_unop(node); }
|
||||||
|
visit_creset(node: XMLNode) { return this.__visit_unop(node); }
|
||||||
|
visit_creturn(node: XMLNode) { return this.__visit_unop(node); }
|
||||||
|
|
||||||
|
visit_contassign(node: XMLNode) { return this.__visit_binop(node); }
|
||||||
|
visit_assigndly(node: XMLNode) { return this.__visit_binop(node); }
|
||||||
|
visit_assignpre(node: XMLNode) { return this.__visit_binop(node); }
|
||||||
|
visit_assignpost(node: XMLNode) { return this.__visit_binop(node); }
|
||||||
|
visit_assign(node: XMLNode) { return this.__visit_binop(node); }
|
||||||
|
visit_arraysel(node: XMLNode) { return this.__visit_binop(node); }
|
||||||
|
visit_wordsel(node: XMLNode) { return this.__visit_binop(node); }
|
||||||
|
|
||||||
|
visit_eq(node: XMLNode) { return this.__visit_binop(node); }
|
||||||
|
visit_neq(node: XMLNode) { return this.__visit_binop(node); }
|
||||||
|
visit_lte(node: XMLNode) { return this.__visit_binop(node); }
|
||||||
|
visit_gte(node: XMLNode) { return this.__visit_binop(node); }
|
||||||
|
visit_lt(node: XMLNode) { return this.__visit_binop(node); }
|
||||||
|
visit_gt(node: XMLNode) { return this.__visit_binop(node); }
|
||||||
|
visit_and(node: XMLNode) { return this.__visit_binop(node); }
|
||||||
|
visit_or(node: XMLNode) { return this.__visit_binop(node); }
|
||||||
|
visit_xor(node: XMLNode) { return this.__visit_binop(node); }
|
||||||
|
visit_add(node: XMLNode) { return this.__visit_binop(node); }
|
||||||
|
visit_sub(node: XMLNode) { return this.__visit_binop(node); }
|
||||||
|
visit_concat(node: XMLNode) { return this.__visit_binop(node); } // TODO?
|
||||||
|
visit_shiftl(node: XMLNode) { return this.__visit_binop(node); }
|
||||||
|
visit_shiftr(node: XMLNode) { return this.__visit_binop(node); }
|
||||||
|
|
||||||
|
visit_mul(node: XMLNode) { return this.__visit_binop(node); }
|
||||||
|
visit_div(node: XMLNode) { return this.__visit_binop(node); }
|
||||||
|
visit_moddiv(node: XMLNode) { return this.__visit_binop(node); }
|
||||||
|
visit_muls(node: XMLNode) { return this.__visit_binop(node); }
|
||||||
|
visit_divs(node: XMLNode) { return this.__visit_binop(node); }
|
||||||
|
visit_moddivs(node: XMLNode) { return this.__visit_binop(node); }
|
||||||
|
visit_gts(node: XMLNode) { return this.__visit_binop(node); }
|
||||||
|
visit_lts(node: XMLNode) { return this.__visit_binop(node); }
|
||||||
|
visit_gtes(node: XMLNode) { return this.__visit_binop(node); }
|
||||||
|
visit_ltes(node: XMLNode) { return this.__visit_binop(node); }
|
||||||
|
// TODO: more?
|
||||||
|
|
||||||
|
visit_range(node: XMLNode) { return this.__visit_binop(node); }
|
||||||
|
|
||||||
|
visit_cond(node: XMLNode) { return this.__visit_triop(node); }
|
||||||
|
visit_condbound(node: XMLNode) { return this.__visit_triop(node); }
|
||||||
|
visit_sel(node: XMLNode) { return this.__visit_triop(node); }
|
||||||
|
|
||||||
|
visit_changedet(node: XMLNode) : HDLBinop {
|
||||||
|
if (node.children.length == 0)
|
||||||
|
return null; //{ op: "changedet", dtype:null, left:null, right:null }
|
||||||
|
else
|
||||||
|
return this.__visit_binop(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
visit_ccall(node: XMLNode) { return this.__visit_func(node); }
|
||||||
|
visit_finish(node: XMLNode) { return this.__visit_func(node); }
|
||||||
|
visit_stop(node: XMLNode) { return this.__visit_func(node); }
|
||||||
|
visit_rand(node: XMLNode) { return this.__visit_func(node); }
|
||||||
|
visit_time(node: XMLNode) { return this.__visit_func(node); }
|
||||||
|
|
||||||
|
visit_display(node: XMLNode) { return this.__visit_func(node); }
|
||||||
|
visit_sformatf(node: XMLNode) { return this.visit_begin(node); }
|
||||||
|
|
||||||
|
visit_readmem(node: XMLNode) { return this.__visit_func(node); }
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
xml_open(node: XMLNode) {
|
||||||
|
this.cur_node = node;
|
||||||
|
var method = this[`open_${node.type}`];
|
||||||
|
if (method) {
|
||||||
|
return method.bind(this)(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
xml_close(node: XMLNode) {
|
||||||
|
this.cur_node = node;
|
||||||
|
var method = this[`visit_${node.type}`];
|
||||||
|
if (method) {
|
||||||
|
return method.bind(this)(node);
|
||||||
|
} else {
|
||||||
|
console.log(node);
|
||||||
|
throw Error(`no visitor for ${node.type}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
parse(xmls: string) {
|
||||||
|
parseXMLPoorly(xmls, this.xml_open.bind(this), this.xml_close.bind(this));
|
||||||
|
this.cur_node = null;
|
||||||
|
this.run_deferred();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
|
||||||
|
import { HDLModuleJS } from "./hdlruntime";
|
||||||
|
import { HDLModuleWASM } from "./hdlwasm";
|
||||||
|
import { VerilogXMLParser } from "./vxmlparser";
|
||||||
|
|
||||||
|
var fs = require('fs');
|
||||||
|
|
||||||
|
var xmltxt = fs.readFileSync(process.argv[2], 'utf8');
|
||||||
|
var parser = new VerilogXMLParser();
|
||||||
|
try {
|
||||||
|
parser.parse(xmltxt);
|
||||||
|
} catch (e) {
|
||||||
|
console.log(parser.cur_node);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
console.log(parser);
|
||||||
|
var modname = process.argv[3];
|
||||||
|
if (1 && modname) {
|
||||||
|
var bmod = new HDLModuleWASM(parser.modules[modname], parser.modules['@CONST-POOL@']);
|
||||||
|
bmod.init();
|
||||||
|
}
|
||||||
|
if (1 && modname) {
|
||||||
|
var mod = new HDLModuleJS(parser.modules[modname], parser.modules['@CONST-POOL@']);
|
||||||
|
mod.init();
|
||||||
|
console.log(mod.getJSCode());
|
||||||
|
mod.reset();
|
||||||
|
var t1 = new Date().getTime();
|
||||||
|
for (var i=0; i<100000000; i++) {
|
||||||
|
mod.tick2();
|
||||||
|
}
|
||||||
|
mod.state.reset = 1;
|
||||||
|
for (var j=0; j<10000000; j++) {
|
||||||
|
mod.tick2();
|
||||||
|
}
|
||||||
|
var t2 = new Date().getTime();
|
||||||
|
console.log(mod.state);
|
||||||
|
console.log('js:',t2-t1, 'msec', i, 'iterations', i/1000/(t2-t1), 'MHz')
|
||||||
|
//console.log(emitter);
|
||||||
|
}
|
|
@ -959,14 +959,15 @@ function _downloadROMImage(e) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
var prefix = getFilenamePrefix(getCurrentMainFilename());
|
var prefix = getFilenamePrefix(getCurrentMainFilename());
|
||||||
if (current_output instanceof Uint8Array) {
|
if (platform.getDownloadFile) {
|
||||||
|
var dl = platform.getDownloadFile();
|
||||||
|
var prefix = getFilenamePrefix(getCurrentMainFilename());
|
||||||
|
saveAs(dl.blob, prefix + dl.extension);
|
||||||
|
} else if (current_output instanceof Uint8Array) {
|
||||||
var blob = new Blob([current_output], {type: "application/octet-stream"});
|
var blob = new Blob([current_output], {type: "application/octet-stream"});
|
||||||
var suffix = (platform.getROMExtension && platform.getROMExtension(current_output))
|
var suffix = (platform.getROMExtension && platform.getROMExtension(current_output))
|
||||||
|| "-" + getBasePlatform(platform_id) + ".bin";
|
|| "-" + getBasePlatform(platform_id) + ".bin";
|
||||||
saveAs(blob, prefix + suffix);
|
saveAs(blob, prefix + suffix);
|
||||||
} else if (current_output.code != null) {
|
|
||||||
var blob = new Blob([(<VerilogOutput>current_output).code], {type: "text/plain"});
|
|
||||||
saveAs(blob, prefix + ".js");
|
|
||||||
} else {
|
} else {
|
||||||
alertError(`The "${platform_id}" platform doesn't have downloadable ROMs.`);
|
alertError(`The "${platform_id}" platform doesn't have downloadable ROMs.`);
|
||||||
}
|
}
|
||||||
|
@ -997,8 +998,11 @@ function _downloadAllFilesZipFile(e) {
|
||||||
loadScript('lib/jszip.min.js').then( () => {
|
loadScript('lib/jszip.min.js').then( () => {
|
||||||
var zip = new JSZip();
|
var zip = new JSZip();
|
||||||
store.keys( (err, keys : string[]) => {
|
store.keys( (err, keys : string[]) => {
|
||||||
|
setWaitDialog(true);
|
||||||
|
var i = 0;
|
||||||
return Promise.all(keys.map( (path) => {
|
return Promise.all(keys.map( (path) => {
|
||||||
return store.getItem(path).then( (text) => {
|
return store.getItem(path).then( (text) => {
|
||||||
|
setWaitProgress(i++/(keys.length+1));
|
||||||
if (text) {
|
if (text) {
|
||||||
zip.file(path, text);
|
zip.file(path, text);
|
||||||
}
|
}
|
||||||
|
@ -1007,9 +1011,9 @@ function _downloadAllFilesZipFile(e) {
|
||||||
return zip.generateAsync({type:"blob"});
|
return zip.generateAsync({type:"blob"});
|
||||||
}).then( (content) => {
|
}).then( (content) => {
|
||||||
return saveAs(content, getBasePlatform(platform_id) + "-all.zip");
|
return saveAs(content, getBasePlatform(platform_id) + "-all.zip");
|
||||||
});
|
}).finally(() => setWaitDialog(false));
|
||||||
});
|
});
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function populateExamples(sel) {
|
function populateExamples(sel) {
|
||||||
|
@ -1184,6 +1188,7 @@ function setCompileOutput(data: WorkerResult) {
|
||||||
toolbar.addClass("has-errors");
|
toolbar.addClass("has-errors");
|
||||||
showExceptionAsError(e, e+"");
|
showExceptionAsError(e, e+"");
|
||||||
current_output = null;
|
current_output = null;
|
||||||
|
refreshWindowList();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,12 +2,18 @@
|
||||||
import { Platform, BasePlatform } from "../common/baseplatform";
|
import { Platform, BasePlatform } from "../common/baseplatform";
|
||||||
import { PLATFORMS, setKeyboardFromMap, AnimationTimer, RasterVideo, Keys, makeKeycodeMap, getMousePos, KeyFlags } from "../common/emu";
|
import { PLATFORMS, setKeyboardFromMap, AnimationTimer, RasterVideo, Keys, makeKeycodeMap, getMousePos, KeyFlags } from "../common/emu";
|
||||||
import { SampleAudio } from "../common/audio";
|
import { SampleAudio } from "../common/audio";
|
||||||
import { safe_extend, clamp, byteArrayToString } from "../common/util";
|
import { safe_extend } from "../common/util";
|
||||||
import { WaveformView, WaveformProvider, WaveformMeta } from "../ide/waveform";
|
import { WaveformView, WaveformProvider, WaveformMeta } from "../ide/waveform";
|
||||||
import { setFrameRateUI, current_project } from "../ide/ui";
|
import { setFrameRateUI, loadScript } from "../ide/ui";
|
||||||
|
import { HDLUnit, isLogicType } from "../common/hdl/hdltypes";
|
||||||
|
import { HDLModuleJS } from "../common/hdl/hdlruntime";
|
||||||
|
|
||||||
declare var Split;
|
declare var Split;
|
||||||
|
|
||||||
|
interface WaveformSignal extends WaveformMeta {
|
||||||
|
name: string;
|
||||||
|
}
|
||||||
|
|
||||||
var VERILOG_PRESETS = [
|
var VERILOG_PRESETS = [
|
||||||
{id:'clock_divider.v', name:'Clock Divider'},
|
{id:'clock_divider.v', name:'Clock Divider'},
|
||||||
{id:'binary_counter.v', name:'Binary Counter'},
|
{id:'binary_counter.v', name:'Binary Counter'},
|
||||||
|
@ -64,198 +70,8 @@ var VERILOG_KEYCODE_MAP = makeKeycodeMap([
|
||||||
|
|
||||||
const TRACE_BUFFER_DWORDS = 0x40000;
|
const TRACE_BUFFER_DWORDS = 0x40000;
|
||||||
|
|
||||||
// SIMULATOR STUFF (should be global)
|
|
||||||
|
|
||||||
export var vl_finished = false;
|
|
||||||
export var vl_stopped = false;
|
|
||||||
|
|
||||||
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
|
|
||||||
export function VL_BITISSET_I(data,bit) { return (data & (VL_UL(1)<<VL_UL(bit))); }
|
|
||||||
|
|
||||||
export function VL_EXTENDSIGN_I(lbits, lhs) { return (-((lhs)&(VL_UL(1)<<(lbits-1)))); }
|
|
||||||
|
|
||||||
export function VL_EXTEND_II(obits,lbits,lhs) { return lhs; }
|
|
||||||
|
|
||||||
export function VL_EXTENDS_II(x,lbits,lhs) {
|
|
||||||
return VL_EXTENDSIGN_I(lbits,lhs) | lhs;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function VL_NEGATE_I(x) { return -x; }
|
|
||||||
|
|
||||||
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; }
|
|
||||||
|
|
||||||
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; }
|
|
||||||
|
|
||||||
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; }
|
|
||||||
|
|
||||||
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; }
|
|
||||||
|
|
||||||
export function VL_DIV_III(lbits,lhs,rhs) {
|
|
||||||
return (((rhs)==0)?0:(lhs)/(rhs)); }
|
|
||||||
|
|
||||||
export function VL_MULS_III(lbits,lhs,rhs) {
|
|
||||||
return (((rhs)==0)?0:(lhs)*(rhs)); }
|
|
||||||
|
|
||||||
export function VL_MODDIV_III(lbits,lhs,rhs) {
|
|
||||||
return (((rhs)==0)?0:(lhs)%(rhs)); }
|
|
||||||
|
|
||||||
export function VL_DIVS_III(lbits,lhs,rhs) {
|
|
||||||
var lhs_signed = VL_EXTENDS_II(32, lbits, lhs);
|
|
||||||
var rhs_signed = VL_EXTENDS_II(32, lbits, rhs);
|
|
||||||
return (((rhs_signed)==0)?0:(lhs_signed)/(rhs_signed));
|
|
||||||
}
|
|
||||||
|
|
||||||
export function VL_MODDIVS_III(lbits,lhs,rhs) {
|
|
||||||
var lhs_signed = VL_EXTENDS_II(32, lbits, lhs);
|
|
||||||
var rhs_signed = VL_EXTENDS_II(32, lbits, rhs);
|
|
||||||
return (((rhs_signed)==0)?0:(lhs_signed)%(rhs_signed));
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
export var VL_WRITEF = console.log; // TODO: $write
|
|
||||||
|
|
||||||
export function vl_finish(filename,lineno,hier) {
|
|
||||||
if (!vl_finished) console.log("Finished at " + filename + ":" + lineno, hier);
|
|
||||||
vl_finished = true;
|
|
||||||
}
|
|
||||||
export function vl_stop(filename,lineno,hier) {
|
|
||||||
if (!vl_stopped) console.log("Stopped at " + filename + ":" + lineno, hier);
|
|
||||||
vl_stopped = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
export function VL_RAND_RESET_I(bits) { return 0 | Math.floor(Math.random() * (1<<bits)); }
|
|
||||||
|
|
||||||
export function VL_RANDOM_I(bits) { return 0 | Math.floor(Math.random() * (1<<bits)); }
|
|
||||||
|
|
||||||
export function VL_READMEM_Q(ishex,width,depth,array_lsb,fnwords,filename,memp,start,end) {
|
|
||||||
VL_READMEM_W(ishex,width,depth,array_lsb,fnwords,filename,memp,start,end);
|
|
||||||
}
|
|
||||||
export function VL_READMEM_W(ishex,width,depth,array_lsb,fnwords,filename,memp,start,end) {
|
|
||||||
// parse filename from 32-bit values into characters
|
|
||||||
var barr = [];
|
|
||||||
for (var i=0; i<filename.length; i++) {
|
|
||||||
barr.push((filename[i] >> 0) & 0xff);
|
|
||||||
barr.push((filename[i] >> 8) & 0xff);
|
|
||||||
barr.push((filename[i] >> 16) & 0xff);
|
|
||||||
barr.push((filename[i] >> 24) & 0xff);
|
|
||||||
}
|
|
||||||
barr = barr.filter(x => x != 0); // ignore zeros
|
|
||||||
barr.reverse(); // reverse it
|
|
||||||
var strfn = byteArrayToString(barr); // convert to string
|
|
||||||
// parse hex/binary file
|
|
||||||
var strdata = current_project.getFile(strfn) as string;
|
|
||||||
if (strdata == null) throw Error("Could not $readmem '" + strfn + "'");
|
|
||||||
var data = strdata.split('\n').filter(s => s !== '').map(s => parseInt(s, ishex ? 16 : 2));
|
|
||||||
console.log('$readmem', ishex, strfn, data.length);
|
|
||||||
// copy into destination array
|
|
||||||
if (memp === null) throw Error("No destination array to $readmem " + strfn);
|
|
||||||
if (memp.length < data.length) throw Error("Destination array too small to $readmem " + strfn);
|
|
||||||
for (i=0; i<data.length; i++)
|
|
||||||
memp[i] = data[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
const CYCLES_PER_FILL = 20;
|
const CYCLES_PER_FILL = 20;
|
||||||
|
|
||||||
// SIMULATOR BASE
|
|
||||||
|
|
||||||
abstract class VerilatorBase {
|
|
||||||
|
|
||||||
totalTicks = 0;
|
|
||||||
maxVclockLoop = 0;
|
|
||||||
clk = 0;
|
|
||||||
reset = 0;
|
|
||||||
|
|
||||||
vl_fatal(msg:string) {
|
|
||||||
console.log(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
ticks() : number { return this.totalTicks; }
|
|
||||||
setTicks(T:number) { this.totalTicks = T|0; }
|
|
||||||
|
|
||||||
__reset() {
|
|
||||||
if (this.reset !== undefined) {
|
|
||||||
this.totalTicks = 0;
|
|
||||||
this.reset = 0;
|
|
||||||
this.tick2();
|
|
||||||
this.reset = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
__unreset() {
|
|
||||||
if (this.reset !== undefined) {
|
|
||||||
this.reset = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
eval() {
|
|
||||||
let vlSymsp = this; //{TOPp:this};
|
|
||||||
// Initialize
|
|
||||||
if (!vlSymsp.__Vm_didInit)
|
|
||||||
this._eval_initial_loop(vlSymsp);
|
|
||||||
// Evaluate till stable
|
|
||||||
//VL_DEBUG_IF(VL_PRINTF("\n----TOP Evaluate Vmain::eval\n"); );
|
|
||||||
var __VclockLoop = 0;
|
|
||||||
var __Vchange=1;
|
|
||||||
while (__Vchange) {
|
|
||||||
//VL_DEBUG_IF(VL_PRINTF(" Clock loop\n"););
|
|
||||||
vlSymsp.__Vm_activity = true;
|
|
||||||
this._eval(vlSymsp);
|
|
||||||
__Vchange = this._change_request(vlSymsp);
|
|
||||||
if (++__VclockLoop > 100) { this.vl_fatal("Verilated model didn't converge"); }
|
|
||||||
}
|
|
||||||
if (__VclockLoop > this.maxVclockLoop) {
|
|
||||||
this.maxVclockLoop = __VclockLoop;
|
|
||||||
if (this.maxVclockLoop > 1) {
|
|
||||||
console.log("Graph took " + this.maxVclockLoop + " iterations to stabilize");
|
|
||||||
$("#verilog_bar").show();
|
|
||||||
$("#settle_label").text(this.maxVclockLoop+"");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.totalTicks++;
|
|
||||||
}
|
|
||||||
|
|
||||||
_eval_initial_loop(vlSymsp) {
|
|
||||||
vlSymsp.TOPp = this;
|
|
||||||
vlSymsp.__Vm_didInit = true;
|
|
||||||
this._eval_initial(vlSymsp);
|
|
||||||
vlSymsp.__Vm_activity = true;
|
|
||||||
var __VclockLoop = 0;
|
|
||||||
var __Vchange=1;
|
|
||||||
while (__Vchange) {
|
|
||||||
this._eval_settle(vlSymsp);
|
|
||||||
this._eval(vlSymsp);
|
|
||||||
__Vchange = this._change_request(vlSymsp);
|
|
||||||
if (++__VclockLoop > 100) { this.vl_fatal("Verilated model didn't DC converge"); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// PLATFORM
|
// PLATFORM
|
||||||
|
|
||||||
var VerilogPlatform = function(mainElement, options) {
|
var VerilogPlatform = function(mainElement, options) {
|
||||||
|
@ -268,9 +84,9 @@ var VerilogPlatform = function(mainElement, options) {
|
||||||
var videoHeight = 256;
|
var videoHeight = 256;
|
||||||
var maxVideoLines = 262+40; // vertical hold
|
var maxVideoLines = 262+40; // vertical hold
|
||||||
var idata, timer, timerCallback;
|
var idata, timer, timerCallback;
|
||||||
|
var top : HDLModuleJS;
|
||||||
var gen;
|
var gen;
|
||||||
var cyclesPerFrame = (256+23+7+23)*262; // 4857480/60 Hz
|
var cyclesPerFrame = (256+23+7+23)*262; // 4857480/60 Hz
|
||||||
var current_output;
|
|
||||||
|
|
||||||
// control inputs
|
// control inputs
|
||||||
var switches = [0,0,0];
|
var switches = [0,0,0];
|
||||||
|
@ -317,7 +133,7 @@ var VerilogPlatform = function(mainElement, options) {
|
||||||
var frameRate = 0;
|
var frameRate = 0;
|
||||||
|
|
||||||
function vidtick() {
|
function vidtick() {
|
||||||
gen.tick2();
|
top.tick2();
|
||||||
if (useAudio)
|
if (useAudio)
|
||||||
audio.feedSample(gen.spkr*(1.0/255.0), 1);
|
audio.feedSample(gen.spkr*(1.0/255.0), 1);
|
||||||
if (keycode && keycode >= 128 && gen.keystrobe) // keystrobe = clear hi bit of key buffer
|
if (keycode && keycode >= 128 && gen.keystrobe) // keystrobe = clear hi bit of key buffer
|
||||||
|
@ -326,6 +142,16 @@ var VerilogPlatform = function(mainElement, options) {
|
||||||
debugCond = null;
|
debugCond = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function doreset() {
|
||||||
|
gen.reset = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
function unreset() {
|
||||||
|
if (gen.reset !== undefined) {
|
||||||
|
gen.reset = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// inner Platform class
|
// inner Platform class
|
||||||
|
|
||||||
class _VerilogPlatform extends BasePlatform implements WaveformProvider {
|
class _VerilogPlatform extends BasePlatform implements WaveformProvider {
|
||||||
|
@ -345,7 +171,9 @@ var VerilogPlatform = function(mainElement, options) {
|
||||||
maxVideoLines = height+40;
|
maxVideoLines = height+40;
|
||||||
}
|
}
|
||||||
|
|
||||||
start() {
|
async start() {
|
||||||
|
await loadScript('./gen/common/hdl/hdltypes.js');
|
||||||
|
await loadScript('./gen/common/hdl/hdlruntime.js');
|
||||||
video = new RasterVideo(mainElement,videoWidth,videoHeight,{overscan:true});
|
video = new RasterVideo(mainElement,videoWidth,videoHeight,{overscan:true});
|
||||||
video.create();
|
video.create();
|
||||||
poller = setKeyboardFromMap(video, switches, VERILOG_KEYCODE_MAP, (o,key,code,flags) => {
|
poller = setKeyboardFromMap(video, switches, VERILOG_KEYCODE_MAP, (o,key,code,flags) => {
|
||||||
|
@ -358,7 +186,7 @@ var VerilogPlatform = function(mainElement, options) {
|
||||||
timerCallback = () => {
|
timerCallback = () => {
|
||||||
if (!this.isRunning())
|
if (!this.isRunning())
|
||||||
return;
|
return;
|
||||||
if (gen) gen.switches = switches[0];
|
if (gen && gen.switches != null) gen.switches = switches[0];
|
||||||
this.updateFrame();
|
this.updateFrame();
|
||||||
};
|
};
|
||||||
this.setFrameRate(60);
|
this.setFrameRate(60);
|
||||||
|
@ -396,7 +224,7 @@ var VerilogPlatform = function(mainElement, options) {
|
||||||
while (framey != new_y || clock++ > 200000) {
|
while (framey != new_y || clock++ > 200000) {
|
||||||
this.setGenInputs();
|
this.setGenInputs();
|
||||||
this.updateVideoFrameCycles(1, true, false);
|
this.updateVideoFrameCycles(1, true, false);
|
||||||
gen.__unreset();
|
unreset();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -410,10 +238,10 @@ var VerilogPlatform = function(mainElement, options) {
|
||||||
setGenInputs() {
|
setGenInputs() {
|
||||||
useAudio = (audio != null);
|
useAudio = (audio != null);
|
||||||
//TODO debugCond = this.getDebugCallback();
|
//TODO debugCond = this.getDebugCallback();
|
||||||
gen.switches_p1 = switches[0];
|
if (gen.switches_p1 != null) gen.switches_p1 = switches[0];
|
||||||
gen.switches_p2 = switches[1];
|
if (gen.switches_p2 != null) gen.switches_p2 = switches[1];
|
||||||
gen.switches_gen = switches[2];
|
if (gen.switches_gen != null) gen.switches_gen = switches[2];
|
||||||
gen.keycode = keycode;
|
if (gen.keycode != null) gen.keycode = keycode;
|
||||||
}
|
}
|
||||||
|
|
||||||
updateVideoFrame() {
|
updateVideoFrame() {
|
||||||
|
@ -434,7 +262,7 @@ var VerilogPlatform = function(mainElement, options) {
|
||||||
idata[frameidx] = -1;
|
idata[frameidx] = -1;
|
||||||
}
|
}
|
||||||
//this.restartDebugState();
|
//this.restartDebugState();
|
||||||
gen.__unreset();
|
unreset();
|
||||||
this.refreshVideoFrame();
|
this.refreshVideoFrame();
|
||||||
// set scope offset
|
// set scope offset
|
||||||
if (trace && this.waveview) {
|
if (trace && this.waveview) {
|
||||||
|
@ -450,7 +278,7 @@ var VerilogPlatform = function(mainElement, options) {
|
||||||
advance(novideo : boolean) : number {
|
advance(novideo : boolean) : number {
|
||||||
this.setGenInputs();
|
this.setGenInputs();
|
||||||
this.updateVideoFrameCycles(cyclesPerFrame, true, false);
|
this.updateVideoFrameCycles(cyclesPerFrame, true, false);
|
||||||
gen.__unreset();
|
unreset();
|
||||||
if (!novideo) {
|
if (!novideo) {
|
||||||
this.refreshVideoFrame();
|
this.refreshVideoFrame();
|
||||||
}
|
}
|
||||||
|
@ -547,16 +375,16 @@ var VerilogPlatform = function(mainElement, options) {
|
||||||
framehsync = false;
|
framehsync = false;
|
||||||
framex = 0;
|
framex = 0;
|
||||||
framey++;
|
framey++;
|
||||||
gen.hpaddle = framey > video.paddle_x ? 1 : 0;
|
if (gen.hpaddle != null) gen.hpaddle = framey > video.paddle_x ? 1 : 0;
|
||||||
gen.vpaddle = framey > video.paddle_y ? 1 : 0;
|
if (gen.vpaddle != null) gen.vpaddle = framey > video.paddle_y ? 1 : 0;
|
||||||
}
|
}
|
||||||
if (framey > maxVideoLines || gen.vsync) {
|
if (framey > maxVideoLines || gen.vsync) {
|
||||||
framevsync = true;
|
framevsync = true;
|
||||||
framey = 0;
|
framey = 0;
|
||||||
framex = 0;
|
framex = 0;
|
||||||
frameidx = 0;
|
frameidx = 0;
|
||||||
gen.hpaddle = 0;
|
if (gen.hpaddle != null) gen.hpaddle = 0;
|
||||||
gen.vpaddle = 0;
|
if (gen.vpaddle != null) gen.vpaddle = 0;
|
||||||
} else {
|
} else {
|
||||||
var wasvsync = framevsync;
|
var wasvsync = framevsync;
|
||||||
framevsync = false;
|
framevsync = false;
|
||||||
|
@ -573,8 +401,7 @@ var VerilogPlatform = function(mainElement, options) {
|
||||||
for (var i=0; i<arr.length; i++) {
|
for (var i=0; i<arr.length; i++) {
|
||||||
var v = arr[i];
|
var v = arr[i];
|
||||||
var z = gen[v.name];
|
var z = gen[v.name];
|
||||||
if (typeof(z) === 'number')
|
trace_buffer[trace_index] = z+0;
|
||||||
trace_buffer[trace_index] = z;
|
|
||||||
trace_index++;
|
trace_index++;
|
||||||
}
|
}
|
||||||
if (trace_index >= trace_buffer.length - arr.length)
|
if (trace_index >= trace_buffer.length - arr.length)
|
||||||
|
@ -585,12 +412,12 @@ var VerilogPlatform = function(mainElement, options) {
|
||||||
var max_index = Math.min(trace_buffer.length - trace_signals.length, trace_index + count);
|
var max_index = Math.min(trace_buffer.length - trace_signals.length, trace_index + count);
|
||||||
while (trace_index < max_index) {
|
while (trace_index < max_index) {
|
||||||
gen.clk ^= 1;
|
gen.clk ^= 1;
|
||||||
gen.eval();
|
top.eval();
|
||||||
this.snapshotTrace();
|
this.snapshotTrace();
|
||||||
if (trace_index == 0)
|
if (trace_index == 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
gen.__unreset();
|
unreset();
|
||||||
return (trace_index == 0);
|
return (trace_index == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -633,35 +460,36 @@ var VerilogPlatform = function(mainElement, options) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
loadROM(title, output) {
|
loadROM(title:string, output:any) {
|
||||||
var mod;
|
var unit = output as HDLUnit;
|
||||||
if (output.code) {
|
var topmod = unit.modules['TOP'];
|
||||||
// is code identical?
|
if (unit.modules && topmod) {
|
||||||
if (current_output && current_output.code == output.code) {
|
{
|
||||||
} else {
|
// initialize top module and constant pool
|
||||||
try {
|
top = new HDLModuleJS(topmod, unit.modules['@CONST-POOL@']);
|
||||||
mod = new Function('base', output.code);
|
top.init();
|
||||||
} catch (e) {
|
top.reset();
|
||||||
this.printErrorCodeContext(e, output.code);
|
gen = top.state;
|
||||||
throw e;
|
// create signal array
|
||||||
}
|
var signals : WaveformSignal[] = [];
|
||||||
// compile Verilog code
|
for (var key in topmod.vardefs) {
|
||||||
var base = new (VerilatorBase as any)();
|
var vardef = topmod.vardefs[key];
|
||||||
gen = new mod();
|
if (isLogicType(vardef.dtype)) {
|
||||||
//$.extend(gen, base);
|
signals.push({
|
||||||
gen.__proto__ = base;
|
name: key,
|
||||||
current_output = output;
|
label: vardef.origName,
|
||||||
module_name = output.name ? output.name.substr(1) : "top";
|
input: vardef.isInput,
|
||||||
//trace_ports = current_output.ports;
|
output: vardef.isOutput,
|
||||||
trace_signals = current_output.ports.concat(current_output.signals); // combine ports + signals
|
len: vardef.dtype.left+1
|
||||||
trace_signals = trace_signals.filter((v) => { return !v.name.startsWith("__V"); }); // remove __Vclklast etc
|
});
|
||||||
for (var v of trace_signals) {
|
}
|
||||||
v.label = v.name.replace(/__DOT__/g, "."); // make nicer name
|
|
||||||
}
|
}
|
||||||
|
trace_signals = signals;
|
||||||
|
trace_signals = trace_signals.filter((v) => { return !v.label.startsWith("__V"); }); // remove __Vclklast etc
|
||||||
trace_index = 0;
|
trace_index = 0;
|
||||||
// power on module
|
// reset
|
||||||
this.poweron();
|
this.poweron();
|
||||||
// query output
|
// query output signals -- video or not?
|
||||||
this.hasvideo = gen.vsync !== undefined && gen.hsync !== undefined && gen.rgb !== undefined;
|
this.hasvideo = gen.vsync !== undefined && gen.hsync !== undefined && gen.rgb !== undefined;
|
||||||
if (this.hasvideo) {
|
if (this.hasvideo) {
|
||||||
const IGNORE_SIGNALS = ['clk','reset'];
|
const IGNORE_SIGNALS = ['clk','reset'];
|
||||||
|
@ -677,16 +505,16 @@ var VerilogPlatform = function(mainElement, options) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// replace program ROM, if using the assembler
|
// replace program ROM, if using the assembler
|
||||||
|
this.reset();
|
||||||
if (output.program_rom && output.program_rom_variable) {
|
if (output.program_rom && output.program_rom_variable) {
|
||||||
if (gen[output.program_rom_variable]) {
|
if (gen[output.program_rom_variable]) {
|
||||||
if (gen[output.program_rom_variable].length != output.program_rom.length)
|
if (gen[output.program_rom_variable].length != output.program_rom.length)
|
||||||
alert("ROM size mismatch -- expected " + gen[output.program_rom_variable].length + " got " + output.program_rom.length);
|
alert("ROM size mismatch -- expected " + gen[output.program_rom_variable].length + " got " + output.program_rom.length);
|
||||||
else
|
else
|
||||||
gen[output.program_rom_variable] = output.program_rom;
|
gen[output.program_rom_variable].set(output.program_rom);
|
||||||
} else {
|
} else {
|
||||||
alert("No program_rom variable found (" + output.program_rom_variable + ")");
|
alert("No program_rom variable found (" + output.program_rom_variable + ")");
|
||||||
}
|
}
|
||||||
this.reset();
|
|
||||||
}
|
}
|
||||||
// restart audio
|
// restart audio
|
||||||
this.restartAudio();
|
this.restartAudio();
|
||||||
|
@ -720,6 +548,13 @@ var VerilogPlatform = function(mainElement, options) {
|
||||||
if (audio) audio.start();
|
if (audio) audio.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isBlocked() {
|
||||||
|
return top && top.finished;
|
||||||
|
}
|
||||||
|
isStopped() {
|
||||||
|
return top && top.stopped;
|
||||||
|
}
|
||||||
|
|
||||||
setFrameRate(rateHz) {
|
setFrameRate(rateHz) {
|
||||||
frameRate = rateHz;
|
frameRate = rateHz;
|
||||||
var fps = Math.min(60, rateHz*cyclesPerFrame);
|
var fps = Math.min(60, rateHz*cyclesPerFrame);
|
||||||
|
@ -738,12 +573,13 @@ var VerilogPlatform = function(mainElement, options) {
|
||||||
getFrameRate() { return frameRate; }
|
getFrameRate() { return frameRate; }
|
||||||
|
|
||||||
poweron() {
|
poweron() {
|
||||||
gen._ctor_var_reset();
|
top.reset();
|
||||||
this.reset();
|
this.reset();
|
||||||
}
|
}
|
||||||
reset() {
|
reset() {
|
||||||
if (!gen) return;
|
if (!gen) return;
|
||||||
gen.__reset();
|
//top.reset(); // to avoid clobbering user inputs
|
||||||
|
doreset();
|
||||||
trace_index = 0;
|
trace_index = 0;
|
||||||
if (trace_buffer) trace_buffer.fill(0);
|
if (trace_buffer) trace_buffer.fill(0);
|
||||||
if (video) video.setRotate(gen.rotate ? -90 : 0);
|
if (video) video.setRotate(gen.rotate ? -90 : 0);
|
||||||
|
@ -751,7 +587,7 @@ var VerilogPlatform = function(mainElement, options) {
|
||||||
if (!this.hasvideo) this.resume(); // TODO?
|
if (!this.hasvideo) this.resume(); // TODO?
|
||||||
}
|
}
|
||||||
tick() {
|
tick() {
|
||||||
gen.tick2();
|
top.tick2();
|
||||||
}
|
}
|
||||||
getToolForFilename(fn) {
|
getToolForFilename(fn) {
|
||||||
if (fn.endsWith(".asm")) return "jsasm";
|
if (fn.endsWith(".asm")) return "jsasm";
|
||||||
|
@ -768,6 +604,7 @@ var VerilogPlatform = function(mainElement, options) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var val = gen[name];
|
var val = gen[name];
|
||||||
|
/* TODO
|
||||||
if (val === undefined && current_output.code) {
|
if (val === undefined && current_output.code) {
|
||||||
var re = new RegExp("(\\w+__DOT__(?:_[dcw]_)" + name + ")\\b", "gm");
|
var re = new RegExp("(\\w+__DOT__(?:_[dcw]_)" + name + ")\\b", "gm");
|
||||||
var m = re.exec(current_output.code);
|
var m = re.exec(current_output.code);
|
||||||
|
@ -776,6 +613,7 @@ var VerilogPlatform = function(mainElement, options) {
|
||||||
val = gen[name];
|
val = gen[name];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
if (typeof(val) === 'number') {
|
if (typeof(val) === 'number') {
|
||||||
inspect_obj = gen;
|
inspect_obj = gen;
|
||||||
inspect_sym = name;
|
inspect_sym = name;
|
||||||
|
@ -787,22 +625,24 @@ var VerilogPlatform = function(mainElement, options) {
|
||||||
// DEBUGGING
|
// DEBUGGING
|
||||||
|
|
||||||
getDebugTree() {
|
getDebugTree() {
|
||||||
return this.saveState().o;
|
return {
|
||||||
|
//ast: current_output,
|
||||||
|
runtime: top,
|
||||||
|
state: this.saveState().o
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: bind() a function to avoid depot?
|
// TODO: bind() a function to avoid depot?
|
||||||
saveState() {
|
saveState() {
|
||||||
var state = {
|
var state = {
|
||||||
T:gen.ticks(),
|
// TODO: T:gen.ticks(),
|
||||||
o:safe_extend(true, {}, gen)
|
o:safe_extend(true, {}, gen)
|
||||||
};
|
};
|
||||||
state.o.TOPp = null;
|
|
||||||
return state;
|
return state;
|
||||||
}
|
}
|
||||||
loadState(state) {
|
loadState(state) {
|
||||||
gen = safe_extend(true, gen, state.o);
|
gen = safe_extend(true, gen, state.o);
|
||||||
gen.setTicks(state.T);
|
// TODO: gen.setTicks(state.T);
|
||||||
gen.TOPp = gen;
|
|
||||||
//console.log(gen, state.o);
|
//console.log(gen, state.o);
|
||||||
}
|
}
|
||||||
saveControlsState() {
|
saveControlsState() {
|
||||||
|
@ -823,6 +663,12 @@ var VerilogPlatform = function(mainElement, options) {
|
||||||
switches[2] = state.sw2;
|
switches[2] = state.sw2;
|
||||||
keycode = state.keycode;
|
keycode = state.keycode;
|
||||||
}
|
}
|
||||||
|
getDownloadFile() {
|
||||||
|
return {
|
||||||
|
extension:".js",
|
||||||
|
blob: new Blob([top.getJSCode()], {type:"text/plain"})
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
} // end of inner class
|
} // end of inner class
|
||||||
return new _VerilogPlatform();
|
return new _VerilogPlatform();
|
||||||
|
|
File diff suppressed because one or more lines are too long
Binary file not shown.
|
@ -566,10 +566,26 @@ function load(modulename:string, debug?:boolean) {
|
||||||
}
|
}
|
||||||
function loadGen(modulename:string) {
|
function loadGen(modulename:string) {
|
||||||
if (!loaded[modulename]) {
|
if (!loaded[modulename]) {
|
||||||
|
console.log('loading', modulename);
|
||||||
importScripts('../../gen/'+modulename+".js");
|
importScripts('../../gen/'+modulename+".js");
|
||||||
loaded[modulename] = 1;
|
loaded[modulename] = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
function loadRequire(modulename:string, path:string) {
|
||||||
|
if (!loaded[path]) {
|
||||||
|
var thisModulesExports = {};
|
||||||
|
var oldRequire = emglobal['require'];
|
||||||
|
emglobal['require'] = (modname:string) => {
|
||||||
|
if (modname.startsWith('./')) modname = modname.substring(2);
|
||||||
|
console.log('require',modname,emglobal[modname]!=null);
|
||||||
|
return emglobal[modname];
|
||||||
|
}
|
||||||
|
emglobal['exports'] = thisModulesExports;
|
||||||
|
loadGen(path);
|
||||||
|
emglobal[modulename] = thisModulesExports;
|
||||||
|
emglobal['require'] = oldRequire;
|
||||||
|
}
|
||||||
|
}
|
||||||
function loadWASM(modulename:string, debug?:boolean) {
|
function loadWASM(modulename:string, debug?:boolean) {
|
||||||
if (!loaded[modulename]) {
|
if (!loaded[modulename]) {
|
||||||
importScripts(PWORKER+"wasm/" + modulename+(debug?"."+debug+".js":".js"));
|
importScripts(PWORKER+"wasm/" + modulename+(debug?"."+debug+".js":".js"));
|
||||||
|
@ -1651,8 +1667,8 @@ var jsasm_module_output;
|
||||||
var jsasm_module_key;
|
var jsasm_module_key;
|
||||||
|
|
||||||
function compileJSASM(asmcode:string, platform, options, is_inline) {
|
function compileJSASM(asmcode:string, platform, options, is_inline) {
|
||||||
loadGen("worker/assembler");
|
loadRequire("assembler", "worker/assembler");
|
||||||
var asm = new emglobal.exports.Assembler();
|
var asm = new emglobal['Assembler']();
|
||||||
var includes = [];
|
var includes = [];
|
||||||
asm.loadJSON = (filename:string) => {
|
asm.loadJSON = (filename:string) => {
|
||||||
var jsontext = getWorkFileAsString(filename);
|
var jsontext = getWorkFileAsString(filename);
|
||||||
|
@ -1691,8 +1707,8 @@ function compileJSASM(asmcode:string, platform, options, is_inline) {
|
||||||
// TODO: unify
|
// TODO: unify
|
||||||
result.output = jsasm_module_output.output;
|
result.output = jsasm_module_output.output;
|
||||||
result.output.program_rom = asmout;
|
result.output.program_rom = asmout;
|
||||||
// cpu_platform__DOT__program_rom
|
// TODO: not cpu_platform__DOT__program_rom anymore, make const
|
||||||
result.output.program_rom_variable = jsasm_module_top + "__DOT__program_rom";
|
result.output.program_rom_variable = jsasm_module_top + "$program_rom";
|
||||||
result.listings = {};
|
result.listings = {};
|
||||||
result.listings[options.path] = {lines:result.lines};
|
result.listings[options.path] = {lines:result.lines};
|
||||||
}
|
}
|
||||||
|
@ -1720,7 +1736,10 @@ function compileInlineASM(code:string, platform, options, errors, asmlines) {
|
||||||
let s = "";
|
let s = "";
|
||||||
var out = asmout.output;
|
var out = asmout.output;
|
||||||
for (var i=0; i<out.length; i++) {
|
for (var i=0; i<out.length; i++) {
|
||||||
if (i>0) s += ",";
|
if (i>0) {
|
||||||
|
s += ",";
|
||||||
|
if ((i & 0xff) == 0) s += "\n";
|
||||||
|
}
|
||||||
s += 0|out[i];
|
s += 0|out[i];
|
||||||
}
|
}
|
||||||
if (asmlines) {
|
if (asmlines) {
|
||||||
|
@ -1738,22 +1757,24 @@ function compileInlineASM(code:string, platform, options, errors, asmlines) {
|
||||||
|
|
||||||
function compileVerilator(step:BuildStep) {
|
function compileVerilator(step:BuildStep) {
|
||||||
loadNative("verilator_bin");
|
loadNative("verilator_bin");
|
||||||
loadGen("worker/verilator2js");
|
loadRequire("hdltypes", "common/hdl/hdltypes");
|
||||||
|
loadRequire("vxmlparser", "common/hdl/vxmlparser");
|
||||||
var platform = step.platform || 'verilog';
|
var platform = step.platform || 'verilog';
|
||||||
var errors = [];
|
var errors = [];
|
||||||
var asmlines = [];
|
var asmlines = [];
|
||||||
gatherFiles(step);
|
gatherFiles(step);
|
||||||
// compile verilog if files are stale
|
// compile verilog if files are stale
|
||||||
var outjs = "main.js";
|
var xmlPath = "main.xml";
|
||||||
if (staleFiles(step, [outjs])) {
|
if (staleFiles(step, [xmlPath])) {
|
||||||
// TODO: %Error: Specified --top-module 'ALU' isn't at the top level, it's under another cell 'cpu'
|
// TODO: %Error: Specified --top-module 'ALU' isn't at the top level, it's under another cell 'cpu'
|
||||||
var match_fn = makeErrorMatcher(errors, /%(.+?): (.+?):(\d+)?[:]?\s*(.+)/i, 3, 4, step.path, 2);
|
var match_fn = makeErrorMatcher(errors, /%(.+?): (.+?):(\d+)?[:]?\s*(.+)/i, 3, 4, step.path, 2);
|
||||||
var verilator_mod = emglobal.verilator_bin({
|
var verilator_mod = emglobal.verilator_bin({
|
||||||
instantiateWasm: moduleInstFn('verilator_bin'),
|
instantiateWasm: moduleInstFn('verilator_bin'),
|
||||||
noInitialRun:true,
|
noInitialRun:true,
|
||||||
|
noExitRuntime:true,
|
||||||
print:print_fn,
|
print:print_fn,
|
||||||
printErr:match_fn,
|
printErr:match_fn,
|
||||||
TOTAL_MEMORY:256*1024*1024,
|
//INITIAL_MEMORY:256*1024*1024,
|
||||||
});
|
});
|
||||||
var code = getWorkFileAsString(step.path);
|
var code = getWorkFileAsString(step.path);
|
||||||
var topmod = detectTopModuleName(code);
|
var topmod = detectTopModuleName(code);
|
||||||
|
@ -1770,6 +1791,7 @@ function compileVerilator(step:BuildStep) {
|
||||||
var args = ["--cc", "-O3"/*abcdefstzsuka*/, "-DEXT_INLINE_ASM", "-DTOPMOD__"+topmod,
|
var args = ["--cc", "-O3"/*abcdefstzsuka*/, "-DEXT_INLINE_ASM", "-DTOPMOD__"+topmod,
|
||||||
"-Wall", "-Wno-DECLFILENAME", "-Wno-UNUSED", '--report-unoptflat',
|
"-Wall", "-Wno-DECLFILENAME", "-Wno-UNUSED", '--report-unoptflat',
|
||||||
"--x-assign", "fast", "--noassert", "--pins-bv", "33",
|
"--x-assign", "fast", "--noassert", "--pins-bv", "33",
|
||||||
|
"--xml-output", xmlPath,
|
||||||
"--top-module", topmod, step.path]
|
"--top-module", topmod, step.path]
|
||||||
verilator_mod.callMain(args);
|
verilator_mod.callMain(args);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
@ -1783,13 +1805,13 @@ function compileVerilator(step:BuildStep) {
|
||||||
if (errors.length) {
|
if (errors.length) {
|
||||||
return {errors:errors};
|
return {errors:errors};
|
||||||
}
|
}
|
||||||
|
var xmlParser = new emglobal['VerilogXMLParser']();
|
||||||
try {
|
try {
|
||||||
var h_file = FS.readFile("obj_dir/V"+topmod+".h", {encoding:'utf8'});
|
var xmlContent = FS.readFile(xmlPath, {encoding:'utf8'});
|
||||||
var cpp_file = FS.readFile("obj_dir/V"+topmod+".cpp", {encoding:'utf8'});
|
putWorkFile(xmlPath, xmlContent);
|
||||||
var rtn = translateVerilatorOutputToJS(h_file, cpp_file);
|
if (!anyTargetChanged(step, [xmlPath]))
|
||||||
putWorkFile(outjs, rtn.output.code);
|
|
||||||
if (!anyTargetChanged(step, [outjs]))
|
|
||||||
return;
|
return;
|
||||||
|
xmlParser.parse(xmlContent);
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
errors.push({line:0,msg:""+e});
|
errors.push({line:0,msg:""+e});
|
||||||
|
@ -1797,11 +1819,12 @@ function compileVerilator(step:BuildStep) {
|
||||||
}
|
}
|
||||||
//rtn.intermediate = {listing:h_file + cpp_file}; // TODO
|
//rtn.intermediate = {listing:h_file + cpp_file}; // TODO
|
||||||
var listings : CodeListingMap = {};
|
var listings : CodeListingMap = {};
|
||||||
|
listings[step.prefix + '.lst'] = {lines:[],text:xmlContent};
|
||||||
// TODO: what if found in non-top-module?
|
// TODO: what if found in non-top-module?
|
||||||
if (asmlines.length)
|
if (asmlines.length)
|
||||||
listings[step.path] = {lines:asmlines};
|
listings[step.path] = {lines:asmlines};
|
||||||
return {
|
return {
|
||||||
output: rtn.output,
|
output: xmlParser,
|
||||||
errors: errors,
|
errors: errors,
|
||||||
listings: listings,
|
listings: listings,
|
||||||
};
|
};
|
||||||
|
@ -2015,7 +2038,7 @@ function setupRequireFunction() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
emglobal['require'] = (modname:string) => {
|
emglobal['require'] = (modname:string) => {
|
||||||
console.log('require',modname);
|
console.log('require',modname,exports[modname]!=null);
|
||||||
return exports[modname];
|
return exports[modname];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2755,10 +2778,8 @@ function compileBASIC(step:BuildStep) {
|
||||||
var jsonpath = step.path + ".json";
|
var jsonpath = step.path + ".json";
|
||||||
gatherFiles(step);
|
gatherFiles(step);
|
||||||
if (staleFiles(step, [jsonpath])) {
|
if (staleFiles(step, [jsonpath])) {
|
||||||
setupRequireFunction();
|
loadRequire("compiler", "common/basic/compiler");
|
||||||
loadGen("common/basic/compiler");
|
|
||||||
var parser = new emglobal['BASICParser']();
|
var parser = new emglobal['BASICParser']();
|
||||||
delete emglobal['require'];
|
|
||||||
var code = getWorkFileAsString(step.path);
|
var code = getWorkFileAsString(step.path);
|
||||||
try {
|
try {
|
||||||
var ast = parser.parseFile(code, step.path);
|
var ast = parser.parseFile(code, step.path);
|
||||||
|
|
|
@ -21,11 +21,12 @@ function loadPlatform(msg) {
|
||||||
platform.loadROM("ROM", msg.output);
|
platform.loadROM("ROM", msg.output);
|
||||||
platform.loadROM("ROM", msg.output);
|
platform.loadROM("ROM", msg.output);
|
||||||
platform.loadROM("ROM", msg.output);
|
platform.loadROM("ROM", msg.output);
|
||||||
verilog.vl_finished = verilog.vl_stopped = false;
|
for (var i=0; i<100000 && !platform.isBlocked(); i++) {
|
||||||
for (var i=0; i<100000 && !(verilog.vl_finished||verilog.vl_stopped); i++) {
|
|
||||||
platform.tick();
|
platform.tick();
|
||||||
}
|
}
|
||||||
assert.ok(!verilog.vl_stopped);
|
console.log(i, platform.isBlocked(), platform.isStopped());
|
||||||
|
//assert.ok(platform.isBlocked());
|
||||||
|
assert.ok(!platform.isStopped());
|
||||||
var state = platform.saveState();
|
var state = platform.saveState();
|
||||||
platform.reset();
|
platform.reset();
|
||||||
platform.loadState(state);
|
platform.loadState(state);
|
||||||
|
@ -33,7 +34,7 @@ function loadPlatform(msg) {
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
//platform.printErrorCodeContext(e, msg.output.code);
|
//platform.printErrorCodeContext(e, msg.output.code);
|
||||||
//console.log(msg.intermediate.listing);
|
//console.log(msg.intermediate.listing);
|
||||||
console.log(msg.output.code);
|
//console.log(msg.output.code);
|
||||||
console.log(e);
|
console.log(e);
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
@ -83,6 +84,7 @@ function compileVerilator(filename, code, callback, nerrors) {
|
||||||
|
|
||||||
function testVerilator(filename, disables, nerrors) {
|
function testVerilator(filename, disables, nerrors) {
|
||||||
it('should translate '+filename, function(done) {
|
it('should translate '+filename, function(done) {
|
||||||
|
console.log(filename);
|
||||||
var csource = ab2str(fs.readFileSync(filename));
|
var csource = ab2str(fs.readFileSync(filename));
|
||||||
for (var i=0; i<(disables||[]).length; i++)
|
for (var i=0; i<(disables||[]).length; i++)
|
||||||
csource = "/* verilator lint_off " + disables[i] + " */\n" + csource;
|
csource = "/* verilator lint_off " + disables[i] + " */\n" + csource;
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
// without warranty, 2004 by Wilson Snyder.
|
// any use, without warranty, 2004 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t (/*AUTOARG*/
|
module t (/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
// without warranty, 2003 by Wilson Snyder.
|
// any use, without warranty, 2003 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t (/*AUTOARG*/
|
module t (/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
// without warranty, 2003 by Wilson Snyder.
|
// any use, without warranty, 2003 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t (/*AUTOARG*/
|
module t (/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
|
@ -13,29 +14,15 @@ module t (/*AUTOARG*/
|
||||||
|
|
||||||
reg [15:0] m_din;
|
reg [15:0] m_din;
|
||||||
|
|
||||||
// OK
|
// We expect all these blocks should split;
|
||||||
|
// blocks that don't split should go in t_alw_nosplit.v
|
||||||
|
|
||||||
reg [15:0] a_split_1, a_split_2;
|
reg [15:0] a_split_1, a_split_2;
|
||||||
always @ (/*AS*/m_din) begin
|
always @ (/*AS*/m_din) begin
|
||||||
a_split_1 = m_din;
|
a_split_1 = m_din;
|
||||||
a_split_2 = m_din;
|
a_split_2 = m_din;
|
||||||
end
|
end
|
||||||
|
|
||||||
// OK
|
|
||||||
reg [15:0] b_split_1, b_split_2;
|
|
||||||
always @ (/*AS*/m_din) begin
|
|
||||||
b_split_1 = m_din;
|
|
||||||
b_split_2 = b_split_1;
|
|
||||||
end
|
|
||||||
|
|
||||||
// Not OK
|
|
||||||
reg [15:0] c_split_1, c_split_2;
|
|
||||||
always @ (/*AS*/m_din) begin
|
|
||||||
c_split_1 = m_din;
|
|
||||||
c_split_2 = c_split_1;
|
|
||||||
c_split_1 = ~m_din;
|
|
||||||
end
|
|
||||||
|
|
||||||
// OK
|
|
||||||
reg [15:0] d_split_1, d_split_2;
|
reg [15:0] d_split_1, d_split_2;
|
||||||
always @ (posedge clk) begin
|
always @ (posedge clk) begin
|
||||||
d_split_1 <= m_din;
|
d_split_1 <= m_din;
|
||||||
|
@ -43,44 +30,27 @@ module t (/*AUTOARG*/
|
||||||
d_split_1 <= ~m_din;
|
d_split_1 <= ~m_din;
|
||||||
end
|
end
|
||||||
|
|
||||||
// Not OK
|
reg [15:0] h_split_1;
|
||||||
|
reg [15:0] h_split_2;
|
||||||
always @ (posedge clk) begin
|
always @ (posedge clk) begin
|
||||||
$write(" foo %x", m_din);
|
// $write(" cyc = %x m_din = %x\n", cyc, m_din);
|
||||||
$write(" bar %x\n", m_din);
|
if (cyc > 2) begin
|
||||||
end
|
if (m_din == 16'h0) begin
|
||||||
|
h_split_1 <= 16'h0;
|
||||||
// Not OK
|
h_split_2 <= 16'h0;
|
||||||
reg [15:0] e_split_1, e_split_2;
|
end
|
||||||
always @ (posedge clk) begin
|
else begin
|
||||||
e_split_1 = m_din;
|
h_split_1 <= m_din;
|
||||||
e_split_2 = e_split_1;
|
h_split_2 <= ~m_din;
|
||||||
end
|
end
|
||||||
|
end
|
||||||
// Not OK
|
else begin
|
||||||
reg [15:0] f_split_1, f_split_2;
|
h_split_1 <= 16'h0;
|
||||||
always @ (posedge clk) begin
|
h_split_2 <= 16'h0;
|
||||||
f_split_2 = f_split_1;
|
end
|
||||||
f_split_1 = m_din;
|
|
||||||
end
|
|
||||||
|
|
||||||
// Not Ok
|
|
||||||
reg [15:0] l_split_1, l_split_2;
|
|
||||||
always @ (posedge clk) begin
|
|
||||||
l_split_2 <= l_split_1;
|
|
||||||
l_split_1 <= l_split_2 | m_din;
|
|
||||||
end
|
|
||||||
|
|
||||||
// OK
|
|
||||||
reg [15:0] z_split_1, z_split_2;
|
|
||||||
always @ (posedge clk) begin
|
|
||||||
z_split_1 <= 0;
|
|
||||||
z_split_1 <= ~m_din;
|
|
||||||
end
|
|
||||||
always @ (posedge clk) begin
|
|
||||||
z_split_2 <= 0;
|
|
||||||
z_split_2 <= z_split_1;
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
// (The checker block is an exception, it won't split.)
|
||||||
always @ (posedge clk) begin
|
always @ (posedge clk) begin
|
||||||
if (cyc!=0) begin
|
if (cyc!=0) begin
|
||||||
cyc<=cyc+1;
|
cyc<=cyc+1;
|
||||||
|
@ -93,39 +63,26 @@ module t (/*AUTOARG*/
|
||||||
m_din <= 16'he11e;
|
m_din <= 16'he11e;
|
||||||
//$write(" A %x %x\n", a_split_1, a_split_2);
|
//$write(" A %x %x\n", a_split_1, a_split_2);
|
||||||
if (!(a_split_1==16'hfeed && a_split_2==16'hfeed)) $stop;
|
if (!(a_split_1==16'hfeed && a_split_2==16'hfeed)) $stop;
|
||||||
if (!(b_split_1==16'hfeed && b_split_2==16'hfeed)) $stop;
|
|
||||||
if (!(c_split_1==16'h0112 && c_split_2==16'hfeed)) $stop;
|
|
||||||
if (!(d_split_1==16'h0112 && d_split_2==16'h0112)) $stop;
|
if (!(d_split_1==16'h0112 && d_split_2==16'h0112)) $stop;
|
||||||
if (!(e_split_1==16'hfeed && e_split_2==16'hfeed)) $stop;
|
if (!(h_split_1==16'hfeed && h_split_2==16'h0112)) $stop;
|
||||||
if (!(f_split_1==16'hfeed && f_split_2==16'hfeed)) $stop;
|
|
||||||
if (!(z_split_1==16'h0112 && z_split_2==16'h0112)) $stop;
|
|
||||||
end
|
end
|
||||||
if (cyc==5) begin
|
if (cyc==5) begin
|
||||||
m_din <= 16'he22e;
|
m_din <= 16'he22e;
|
||||||
if (!(a_split_1==16'he11e && a_split_2==16'he11e)) $stop;
|
if (!(a_split_1==16'he11e && a_split_2==16'he11e)) $stop;
|
||||||
if (!(b_split_1==16'he11e && b_split_2==16'he11e)) $stop;
|
|
||||||
if (!(c_split_1==16'h1ee1 && c_split_2==16'he11e)) $stop;
|
|
||||||
if (!(d_split_1==16'h0112 && d_split_2==16'h0112)) $stop;
|
if (!(d_split_1==16'h0112 && d_split_2==16'h0112)) $stop;
|
||||||
if (!(z_split_1==16'h0112 && z_split_2==16'h0112)) $stop;
|
if (!(h_split_1==16'hfeed && h_split_2==16'h0112)) $stop;
|
||||||
// Two valid orderings, as we don't know which posedge clk gets evaled first
|
|
||||||
if (!(e_split_1==16'hfeed && e_split_2==16'hfeed) && !(e_split_1==16'he11e && e_split_2==16'he11e)) $stop;
|
|
||||||
if (!(f_split_1==16'hfeed && f_split_2==16'hfeed) && !(f_split_1==16'he11e && f_split_2==16'hfeed)) $stop;
|
|
||||||
end
|
end
|
||||||
if (cyc==6) begin
|
if (cyc==6) begin
|
||||||
m_din <= 16'he33e;
|
m_din <= 16'he33e;
|
||||||
if (!(a_split_1==16'he22e && a_split_2==16'he22e)) $stop;
|
if (!(a_split_1==16'he22e && a_split_2==16'he22e)) $stop;
|
||||||
if (!(b_split_1==16'he22e && b_split_2==16'he22e)) $stop;
|
|
||||||
if (!(c_split_1==16'h1dd1 && c_split_2==16'he22e)) $stop;
|
|
||||||
if (!(d_split_1==16'h1ee1 && d_split_2==16'h0112)) $stop;
|
if (!(d_split_1==16'h1ee1 && d_split_2==16'h0112)) $stop;
|
||||||
if (!(z_split_1==16'h1ee1 && d_split_2==16'h0112)) $stop;
|
if (!(h_split_1==16'he11e && h_split_2==16'h1ee1)) $stop;
|
||||||
// Two valid orderings, as we don't know which posedge clk gets evaled first
|
|
||||||
if (!(e_split_1==16'he11e && e_split_2==16'he11e) && !(e_split_1==16'he22e && e_split_2==16'he22e)) $stop;
|
|
||||||
if (!(f_split_1==16'he11e && f_split_2==16'hfeed) && !(f_split_1==16'he22e && f_split_2==16'he11e)) $stop;
|
|
||||||
end
|
end
|
||||||
if (cyc==7) begin
|
if (cyc==7) begin
|
||||||
$write("*-* All Finished *-*\n");
|
$write("*-* All Finished *-*\n");
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end // always @ (posedge clk)
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
// without warranty, 2003-2007 by Wilson Snyder.
|
// any use, without warranty, 2003-2007 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t (/*AUTOARG*/
|
module t (/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
// without warranty, 2016 by Andrew Bardsley.
|
// without warranty, 2016 by Andrew Bardsley.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
// bug1071
|
// bug1071
|
||||||
|
|
||||||
|
@ -35,12 +36,16 @@ module t (/*AUTOARG*/
|
||||||
array_3[2] = 4'b0100;
|
array_3[2] = 4'b0100;
|
||||||
array_3[3] = 4'b0100;
|
array_3[3] = 4'b0100;
|
||||||
|
|
||||||
// Comparisons only compare elements 0
|
|
||||||
array_1_ne_array_2 = array_1 != array_2; // 0
|
array_1_ne_array_2 = array_1 != array_2; // 0
|
||||||
array_1_eq_array_2 = array_1 == array_2; // 0
|
array_1_eq_array_2 = array_1 == array_2; // 0
|
||||||
array_1_ne_array_3 = array_1 != array_3; // 1
|
array_1_ne_array_3 = array_1 != array_3; // 1
|
||||||
array_1_eq_array_3 = array_1 == array_3; // 1
|
array_1_eq_array_3 = array_1 == array_3; // 1
|
||||||
|
|
||||||
|
//Not legal: array_rxor = ^ array_1;
|
||||||
|
//Not legal: array_rxnor = ^~ array_1;
|
||||||
|
//Not legal: array_ror = | array_1;
|
||||||
|
//Not legal: array_rand = & array_1;
|
||||||
|
|
||||||
`ifdef TEST_VERBOSE
|
`ifdef TEST_VERBOSE
|
||||||
$write("array_1_ne_array2==%0d\n", array_1_ne_array_2);
|
$write("array_1_ne_array2==%0d\n", array_1_ne_array_2);
|
||||||
$write("array_1_ne_array3==%0d\n", array_1_ne_array_3);
|
$write("array_1_ne_array3==%0d\n", array_1_ne_array_3);
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
// without warranty, 2005 by Wilson Snyder.
|
// any use, without warranty, 2005 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t_case_huge_sub3 (/*AUTOARG*/
|
module t_case_huge_sub3 (/*AUTOARG*/
|
||||||
// Outputs
|
// Outputs
|
||||||
outr,
|
outr,
|
||||||
// Inputs
|
// Inputs
|
||||||
clk, index
|
clk, index
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
// without warranty, 2010 by Wilson Snyder.
|
// any use, without warranty, 2010 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
`ifndef VERILATOR
|
`ifndef VERILATOR
|
||||||
module t;
|
module t;
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
// without warranty, 2005 by Wilson Snyder.
|
// any use, without warranty, 2005 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t (clk);
|
module t (clk);
|
||||||
input clk;
|
input clk;
|
||||||
|
@ -111,6 +112,7 @@ module clockgate (clk, sen, ena, gatedclk);
|
||||||
wire gatedclk = clk & ena_b;
|
wire gatedclk = clk & ena_b;
|
||||||
|
|
||||||
// verilator lint_off COMBDLY
|
// verilator lint_off COMBDLY
|
||||||
|
// verilator lint_off LATCH
|
||||||
always @(clk or ena or sen) begin
|
always @(clk or ena or sen) begin
|
||||||
if (~clk) begin
|
if (~clk) begin
|
||||||
ena_b <= ena | sen;
|
ena_b <= ena | sen;
|
||||||
|
@ -119,6 +121,7 @@ module clockgate (clk, sen, ena, gatedclk);
|
||||||
if ((clk^sen)===1'bX) ena_b <= 1'bX;
|
if ((clk^sen)===1'bX) ena_b <= 1'bX;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
// verilator lint_on LATCH
|
||||||
// verilator lint_on COMBDLY
|
// verilator lint_on COMBDLY
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
// without warranty, 2005 by Wilson Snyder.
|
// any use, without warranty, 2005 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t (clk);
|
module t (clk);
|
||||||
input clk;
|
input clk;
|
||||||
|
@ -111,6 +112,7 @@ module clockgate (clk, sen, ena, gatedclk);
|
||||||
wire gatedclk = clk & ena_b;
|
wire gatedclk = clk & ena_b;
|
||||||
|
|
||||||
// verilator lint_off COMBDLY
|
// verilator lint_off COMBDLY
|
||||||
|
// verilator lint_off LATCH
|
||||||
always @(clk or ena or sen) begin
|
always @(clk or ena or sen) begin
|
||||||
if (~clk) begin
|
if (~clk) begin
|
||||||
ena_b <= ena | sen;
|
ena_b <= ena | sen;
|
||||||
|
@ -119,6 +121,7 @@ module clockgate (clk, sen, ena, gatedclk);
|
||||||
if ((clk^sen)===1'bX) ena_b <= 1'bX;
|
if ((clk^sen)===1'bX) ena_b <= 1'bX;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
// verilator lint_on LATCH
|
||||||
// verilator lint_on COMBDLY
|
// verilator lint_on COMBDLY
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
// without warranty, 2003 by Wilson Snyder.
|
// any use, without warranty, 2003 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t (/*AUTOARG*/
|
module t (/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
// without warranty, 2003 by Wilson Snyder.
|
// any use, without warranty, 2003 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t (/*AUTOARG*/
|
module t (/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
// without warranty, 2003 by Wilson Snyder.
|
// any use, without warranty, 2003 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t (/*AUTOARG*/
|
module t (/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
clk, fastclk
|
clk, fastclk
|
||||||
);
|
);
|
||||||
|
|
||||||
input clk /*verilator sc_clock*/;
|
input clk;
|
||||||
input fastclk /*verilator sc_clock*/;
|
input fastclk;
|
||||||
reg reset_l;
|
reg reset_l;
|
||||||
|
|
||||||
int cyc;
|
int cyc;
|
||||||
// TODO: initial cyc = 0;
|
|
||||||
initial reset_l = 0;
|
initial reset_l = 0;
|
||||||
always @ (posedge clk) begin
|
always @ (posedge clk) begin
|
||||||
if (cyc==0) reset_l <= 1'b1;
|
if (cyc==0) reset_l <= 1'b1;
|
||||||
|
@ -33,8 +33,8 @@ module t_clk (/*AUTOARG*/
|
||||||
clk, fastclk, reset_l
|
clk, fastclk, reset_l
|
||||||
);
|
);
|
||||||
|
|
||||||
input clk /*verilator sc_clock*/;
|
input clk;
|
||||||
input fastclk /*verilator sc_clock*/;
|
input fastclk;
|
||||||
input reset_l;
|
input reset_l;
|
||||||
|
|
||||||
// surefire lint_off STMINI
|
// surefire lint_off STMINI
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
// without warranty, 2008 by Wilson Snyder.
|
// any use, without warranty, 2008 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t (/*AUTOARG*/
|
module t (/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
// without warranty, 2003 by Wilson Snyder.
|
// any use, without warranty, 2003 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t (/*AUTOARG*/
|
module t (/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
// without warranty, 2005 by Wilson Snyder.
|
// any use, without warranty, 2005 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t (/*AUTOARG*/
|
module t (/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
|
@ -52,6 +53,7 @@ module t (/*AUTOARG*/
|
||||||
end
|
end
|
||||||
|
|
||||||
// verilator lint_off COMBDLY
|
// verilator lint_off COMBDLY
|
||||||
|
// verilator lint_off LATCH
|
||||||
always @ (`posstyle clk /*AS*/ or data) begin
|
always @ (`posstyle clk /*AS*/ or data) begin
|
||||||
if (clk) begin
|
if (clk) begin
|
||||||
data_a <= data + 8'd1;
|
data_a <= data + 8'd1;
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
// without warranty, 2010 by Wilson Snyder.
|
// any use, without warranty, 2010 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
//
|
//
|
||||||
// --------------------------------------------------------
|
// --------------------------------------------------------
|
||||||
// Bug Description:
|
// Bug Description:
|
||||||
|
@ -110,11 +111,13 @@ module llq (clk, d, q);
|
||||||
reg [WIDTH-1:0] qr;
|
reg [WIDTH-1:0] qr;
|
||||||
|
|
||||||
/* verilator lint_off COMBDLY */
|
/* verilator lint_off COMBDLY */
|
||||||
|
/* verilator lint_off LATCH */
|
||||||
|
|
||||||
always @(clk or d)
|
always @(clk or d)
|
||||||
if (clk == 1'b0)
|
if (clk == 1'b0)
|
||||||
qr <= d;
|
qr <= d;
|
||||||
|
|
||||||
|
/* verilator lint_on LATCH */
|
||||||
/* verilator lint_on COMBDLY */
|
/* verilator lint_on COMBDLY */
|
||||||
|
|
||||||
assign q = qr;
|
assign q = qr;
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
// without warranty, 2005 by Wilson Snyder.
|
// any use, without warranty, 2005 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t (/*AUTOARG*/
|
module t (/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
// without warranty, 2008 by Wilson Snyder.
|
// any use, without warranty, 2008 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t (/*AUTOARG*/
|
module t (/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
|
|
|
@ -1,4 +1,7 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2020 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t (/*AUTOARG*/
|
module t (/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
|
@ -53,7 +56,7 @@ module t (/*AUTOARG*/
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module test_top (/*AUTOARG*/
|
module Test (/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
clk, in
|
clk, in
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
// without warranty, 2003 by Wilson Snyder.
|
// any use, without warranty, 2003 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t (/*AUTOARG*/
|
module t (/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
clk
|
clk
|
||||||
);
|
);
|
||||||
input clk;
|
input clk;
|
||||||
reg _ranit;
|
reg _ranit;
|
||||||
|
|
||||||
reg [2:0] xor3;
|
reg [2:0] xor3;
|
||||||
reg [1:0] xor2;
|
reg [1:0] xor2;
|
||||||
|
@ -28,8 +29,8 @@ module t (/*AUTOARG*/
|
||||||
|
|
||||||
wire [4:0] cond_check = (( xor2 == 2'b11) ? 5'h1
|
wire [4:0] cond_check = (( xor2 == 2'b11) ? 5'h1
|
||||||
: (xor2 == 2'b00) ? 5'h2
|
: (xor2 == 2'b00) ? 5'h2
|
||||||
: (xor2 == 2'b01) ? 5'h3
|
: (xor2 == 2'b01) ? 5'h3
|
||||||
: 5'h4);
|
: 5'h4);
|
||||||
|
|
||||||
wire ctrue = 1'b1 ? cond_check[1] : cond_check[0];
|
wire ctrue = 1'b1 ? cond_check[1] : cond_check[0];
|
||||||
wire cfalse = 1'b0 ? cond_check[1] : cond_check[0];
|
wire cfalse = 1'b0 ? cond_check[1] : cond_check[0];
|
||||||
|
@ -48,94 +49,138 @@ module t (/*AUTOARG*/
|
||||||
|
|
||||||
always @ (posedge clk) begin
|
always @ (posedge clk) begin
|
||||||
if (!_ranit) begin
|
if (!_ranit) begin
|
||||||
_ranit <= 1;
|
_ranit <= 1;
|
||||||
|
|
||||||
if (rep6 != 6'b111111) $stop;
|
if (rep6 != 6'b111111) $stop;
|
||||||
if (!one) $stop;
|
if (!one) $stop;
|
||||||
if (~one) $stop;
|
if (~one) $stop;
|
||||||
|
|
||||||
if (( 1'b0 ? 3'h3 : 1'b0 ? 3'h2 : 1'b1 ? 3'h1 : 3'h0) !== 3'h1) $stop;
|
if (( 1'b0 ? 3'h3 : 1'b0 ? 3'h2 : 1'b1 ? 3'h1 : 3'h0) !== 3'h1) $stop;
|
||||||
// verilator lint_off WIDTH
|
// verilator lint_off WIDTH
|
||||||
if (( 8'h10 + 1'b0 ? 8'he : 8'hf) !== 8'he) $stop; // + is higher than ?
|
if (( 8'h10 + 1'b0 ? 8'he : 8'hf) !== 8'he) $stop; // + is higher than ?
|
||||||
// verilator lint_on WIDTH
|
// verilator lint_on WIDTH
|
||||||
|
|
||||||
// surefire lint_off SEQASS
|
// surefire lint_off SEQASS
|
||||||
xor1 = 1'b1;
|
xor1 = 1'b1;
|
||||||
xor2 = 2'b11;
|
xor2 = 2'b11;
|
||||||
xor3 = 3'b111;
|
xor3 = 3'b111;
|
||||||
// verilator lint_off WIDTH
|
// verilator lint_off WIDTH
|
||||||
if (1'b1 & | (!xor3)) $stop;
|
if (1'b1 & | (!xor3)) $stop;
|
||||||
// verilator lint_on WIDTH
|
// verilator lint_on WIDTH
|
||||||
if ({1{xor1}} != 1'b1) $stop;
|
if ({1{xor1}} != 1'b1) $stop;
|
||||||
if ({4{xor1}} != 4'b1111) $stop;
|
if ({4{xor1}} != 4'b1111) $stop;
|
||||||
if (!(~xor1) !== ~(!xor1)) $stop;
|
if (!(~xor1) !== ~(!xor1)) $stop;
|
||||||
if ((^xor1) !== 1'b1) $stop;
|
if ((^xor1) !== 1'b1) $stop;
|
||||||
if ((^xor2) !== 1'b0) $stop;
|
if ((^xor2) !== 1'b0) $stop;
|
||||||
if ((^xor3) !== 1'b1) $stop;
|
if ((^xor3) !== 1'b1) $stop;
|
||||||
if (~(^xor2) !== 1'b1) $stop;
|
if (~(^xor2) !== 1'b1) $stop;
|
||||||
if (~(^xor3) !== 1'b0) $stop;
|
if (~(^xor3) !== 1'b0) $stop;
|
||||||
if ((^~xor1) !== 1'b0) $stop;
|
if ((^~xor1) !== 1'b0) $stop;
|
||||||
if ((^~xor2) !== 1'b1) $stop;
|
if ((^~xor2) !== 1'b1) $stop;
|
||||||
if ((^~xor3) !== 1'b0) $stop;
|
if ((^~xor3) !== 1'b0) $stop;
|
||||||
if ((~^xor1) !== 1'b0) $stop;
|
if ((~^xor1) !== 1'b0) $stop;
|
||||||
if ((~^xor2) !== 1'b1) $stop;
|
if ((~^xor2) !== 1'b1) $stop;
|
||||||
if ((~^xor3) !== 1'b0) $stop;
|
if ((~^xor3) !== 1'b0) $stop;
|
||||||
xor1 = 1'b0;
|
xor1 = 1'b0;
|
||||||
xor2 = 2'b10;
|
xor2 = 2'b10;
|
||||||
xor3 = 3'b101;
|
xor3 = 3'b101;
|
||||||
if ((^xor1) !== 1'b0) $stop;
|
if ((^xor1) !== 1'b0) $stop;
|
||||||
if ((^xor2) !== 1'b1) $stop;
|
if ((^xor2) !== 1'b1) $stop;
|
||||||
if ((^xor3) !== 1'b0) $stop;
|
if ((^xor3) !== 1'b0) $stop;
|
||||||
if (~(^xor2) !== 1'b0) $stop;
|
if (~(^xor2) !== 1'b0) $stop;
|
||||||
if (~(^xor3) !== 1'b1) $stop;
|
if (~(^xor3) !== 1'b1) $stop;
|
||||||
if ((^~xor1) !== 1'b1) $stop;
|
if ((^~xor1) !== 1'b1) $stop;
|
||||||
if ((^~xor2) !== 1'b0) $stop;
|
if ((^~xor2) !== 1'b0) $stop;
|
||||||
if ((^~xor3) !== 1'b1) $stop;
|
if ((^~xor3) !== 1'b1) $stop;
|
||||||
if ((~^xor1) !== 1'b1) $stop;
|
if ((~^xor1) !== 1'b1) $stop;
|
||||||
if ((~^xor2) !== 1'b0) $stop;
|
if ((~^xor2) !== 1'b0) $stop;
|
||||||
if ((~^xor3) !== 1'b1) $stop;
|
if ((~^xor3) !== 1'b1) $stop;
|
||||||
|
|
||||||
ma = 3'h3;
|
// X propagation
|
||||||
|
if (!1'bx !== 1'bx) $stop;
|
||||||
|
if (~2'bx !== 2'bx) $stop;
|
||||||
|
if (-2'bx !== 2'bx) $stop;
|
||||||
|
if ((2'bxx + 2'b1) !== 2'bxx) $stop;
|
||||||
|
if ((2'bxx - 2'b1) !== 2'bxx) $stop;
|
||||||
|
if ((2'bxx * 2'b1) !== 2'bxx) $stop;
|
||||||
|
if ((2'bxx / 2'b1) !== 2'bxx) $stop;
|
||||||
|
if ((2'bxx % 2'b1) !== 2'bxx) $stop;
|
||||||
|
if ((2'sbxx * 2'sb1) !== 2'bxx) $stop;
|
||||||
|
if ((2'sbxx / 2'sb1) !== 2'bxx) $stop;
|
||||||
|
if ((2'sbxx % 2'sb1) !== 2'bxx) $stop;
|
||||||
|
if ((1'bx & 1'b1) !== 1'bx) $stop;
|
||||||
|
if ((1'bx & 1'b0) !== 1'b0) $stop;
|
||||||
|
if ((1'bx | 1'b0) !== 1'bx) $stop;
|
||||||
|
if ((1'bx | 1'b1) !== 1'b1) $stop;
|
||||||
|
if ((1'bx && 1'b1) !== 1'bx) $stop;
|
||||||
|
if ((1'bx && 1'b0) !== 1'b0) $stop;
|
||||||
|
if ((1'bx || 1'b0) !== 1'bx) $stop;
|
||||||
|
if ((1'bx || 1'b1) !== 1'b1) $stop;
|
||||||
|
if ((2'bxx ^ 2'b1) !== 2'bxx) $stop;
|
||||||
|
if ((2'bxx > 2'b1) !== 1'bx) $stop;
|
||||||
|
if ((2'bxx < 2'b1) !== 1'bx) $stop;
|
||||||
|
if ((2'bxx == 2'b1) !== 1'bx) $stop;
|
||||||
|
if ((2'bxx <= 2'b1) !== 1'bx) $stop;
|
||||||
|
if ((2'bxx >= 2'b1) !== 1'bx) $stop;
|
||||||
|
if ((2'sbxx <= 2'sb1) !== 1'bx) $stop;
|
||||||
|
if ((2'sbxx >= 2'sb1) !== 1'bx) $stop;
|
||||||
|
|
||||||
|
ma = 3'h3;
|
||||||
mb = 3'h4;
|
mb = 3'h4;
|
||||||
mc = 10'h5;
|
mc = 10'h5;
|
||||||
|
|
||||||
mr1 = ma * mb; // Lint ASWESB: Assignment width mismatch
|
mr1 = ma * mb; // Lint ASWESB: Assignment width mismatch
|
||||||
mr2 = 30'h5 * mc; // Lint ASWESB: Assignment width mismatch
|
mr2 = 30'h5 * mc; // Lint ASWESB: Assignment width mismatch
|
||||||
if (mr1 !== 5'd12) $stop;
|
if (mr1 !== 5'd12) $stop;
|
||||||
if (mr2 !== 31'd25) $stop; // Lint CWECBB: Comparison width mismatch
|
if (mr2 !== 31'd25) $stop; // Lint CWECBB: Comparison width mismatch
|
||||||
|
|
||||||
sh1 = 68'hf_def1_9abc_5678_1234;
|
sh1 = 68'hf_def1_9abc_5678_1234;
|
||||||
shq = sh1 >> 16;
|
shq = sh1 >> 16;
|
||||||
if (shq !== 68'hf_def1_9abc_5678) $stop;
|
if (shq !== 68'hf_def1_9abc_5678) $stop;
|
||||||
shq = sh1 << 16; // Lint ASWESB: Assignment width mismatch
|
shq = sh1 << 16; // Lint ASWESB: Assignment width mismatch
|
||||||
if (shq !== 68'h1_9abc_5678_1234_0000) $stop;
|
if (shq !== 68'h1_9abc_5678_1234_0000) $stop;
|
||||||
|
|
||||||
// surefire lint_on SEQASS
|
// surefire lint_on SEQASS
|
||||||
|
|
||||||
// Test display extraction widthing
|
// Test display extraction widthing
|
||||||
$display("[%0t] %x %x %x(%d)", $time, shq[2:0], shq[2:0]<<2, xor3[2:0], xor3[2:0]);
|
$display("[%0t] %x %x %x(%d)", $time, shq[2:0], shq[2:0]<<2, xor3[2:0], xor3[2:0]);
|
||||||
|
|
||||||
// bug736
|
// bug736
|
||||||
//verilator lint_off WIDTH
|
//verilator lint_off WIDTH
|
||||||
if ((~| 4'b0000) != 4'b0001) $stop;
|
if ((~| 4'b0000) != 4'b0001) $stop;
|
||||||
if ((~| 4'b0010) != 4'b0000) $stop;
|
if ((~| 4'b0010) != 4'b0000) $stop;
|
||||||
if ((~& 4'b1111) != 4'b0000) $stop;
|
if ((~& 4'b1111) != 4'b0000) $stop;
|
||||||
if ((~& 4'b1101) != 4'b0001) $stop;
|
if ((~& 4'b1101) != 4'b0001) $stop;
|
||||||
//verilator lint_on WIDTH
|
//verilator lint_on WIDTH
|
||||||
|
|
||||||
// bug764
|
// bug764
|
||||||
//verilator lint_off WIDTH
|
//verilator lint_off WIDTH
|
||||||
// X does not sign extend
|
// X does not sign extend
|
||||||
if (bug764_p11 !== 4'b000x) $stop;
|
if (bug764_p11 !== 4'b000x) $stop;
|
||||||
if (~& bug764_p11 !== 1'b1) $stop;
|
if (~& bug764_p11 !== 1'b1) $stop;
|
||||||
//verilator lint_on WIDTH
|
//verilator lint_on WIDTH
|
||||||
// However IEEE says for constants in 2012 5.7.1 that smaller-sizes do extend
|
// However IEEE 2017 5.7.1 says for constants that smaller-sizes do extend
|
||||||
if (4'bx !== 4'bxxxx) $stop;
|
if (4'bx !== 4'bxxxx) $stop;
|
||||||
if (4'bz !== 4'bzzzz) $stop;
|
if (4'bz !== 4'bzzzz) $stop;
|
||||||
if (4'b1 !== 4'b0001) $stop;
|
if (4'b1 !== 4'b0001) $stop;
|
||||||
|
|
||||||
$write("*-* All Finished *-*\n");
|
if ((0 -> 0) != 1'b1) $stop;
|
||||||
$finish;
|
if ((0 -> 1) != 1'b1) $stop;
|
||||||
|
if ((1 -> 0) != 1'b0) $stop;
|
||||||
|
if ((1 -> 1) != 1'b1) $stop;
|
||||||
|
|
||||||
|
if ((0 <-> 0) != 1'b1) $stop;
|
||||||
|
if ((0 <-> 1) != 1'b0) $stop;
|
||||||
|
if ((1 <-> 0) != 1'b0) $stop;
|
||||||
|
if ((1 <-> 1) != 1'b1) $stop;
|
||||||
|
|
||||||
|
// bug2912
|
||||||
|
// verilator lint_off WIDTH
|
||||||
|
if (2'(~1'b1) != 2'b10) $stop;
|
||||||
|
// verilator lint_on WIDTH
|
||||||
|
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -145,13 +190,13 @@ module t (/*AUTOARG*/
|
||||||
reg [7:0] m_corr_data_b8;
|
reg [7:0] m_corr_data_b8;
|
||||||
initial begin
|
initial begin
|
||||||
m_data_pipe2_r = 64'h1234_5678_9abc_def0;
|
m_data_pipe2_r = 64'h1234_5678_9abc_def0;
|
||||||
{m_corr_data_b8, m_corr_data_w1, m_corr_data_w0} = { m_data_pipe2_r[63:57], 1'b0, //m_corr_data_b8 [7:0]
|
{m_corr_data_b8, m_corr_data_w1, m_corr_data_w0} = { m_data_pipe2_r[63:57], 1'b0, //m_corr_data_b8 [7:0]
|
||||||
m_data_pipe2_r[56:26], 1'b0, //m_corr_data_w1 [31:0]
|
m_data_pipe2_r[56:26], 1'b0, //m_corr_data_w1 [31:0]
|
||||||
m_data_pipe2_r[25:11], 1'b0, //m_corr_data_w0 [31:16]
|
m_data_pipe2_r[25:11], 1'b0, //m_corr_data_w0 [31:16]
|
||||||
m_data_pipe2_r[10:04], 1'b0, //m_corr_data_w0 [15:8]
|
m_data_pipe2_r[10:04], 1'b0, //m_corr_data_w0 [15:8]
|
||||||
m_data_pipe2_r[03:01], 1'b0, //m_corr_data_w0 [7:4]
|
m_data_pipe2_r[03:01], 1'b0, //m_corr_data_w0 [7:4]
|
||||||
m_data_pipe2_r[0], 3'b000 //m_corr_data_w0 [3:0]
|
m_data_pipe2_r[0], 3'b000 //m_corr_data_w0 [3:0]
|
||||||
};
|
};
|
||||||
if (m_corr_data_w0 != 32'haf36de00) $stop;
|
if (m_corr_data_w0 != 32'haf36de00) $stop;
|
||||||
if (m_corr_data_w1 != 32'h1a2b3c4c) $stop;
|
if (m_corr_data_w1 != 32'h1a2b3c4c) $stop;
|
||||||
if (m_corr_data_b8 != 8'h12) $stop;
|
if (m_corr_data_b8 != 8'h12) $stop;
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
// without warranty, 2003 by Wilson Snyder.
|
// any use, without warranty, 2003 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t (/*AUTOARG*/
|
module t (/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
// without warranty, 2004 by Wilson Snyder.
|
// any use, without warranty, 2004 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t (/*AUTOARG*/
|
module t (/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
|
@ -14,12 +15,20 @@ module t (/*AUTOARG*/
|
||||||
reg [60:0] divisor;
|
reg [60:0] divisor;
|
||||||
reg [60:0] qq;
|
reg [60:0] qq;
|
||||||
reg [60:0] rq;
|
reg [60:0] rq;
|
||||||
|
reg [60:0] qq4;
|
||||||
|
reg [60:0] rq4;
|
||||||
|
reg [60:0] qq5;
|
||||||
|
reg [60:0] rq5;
|
||||||
reg signed [60:0] qqs;
|
reg signed [60:0] qqs;
|
||||||
reg signed [60:0] rqs;
|
reg signed [60:0] rqs;
|
||||||
|
|
||||||
always @* begin
|
always @* begin
|
||||||
qq = a[60:0] / divisor;
|
qq = a[60:0] / divisor;
|
||||||
rq = a[60:0] % divisor;
|
rq = a[60:0] % divisor;
|
||||||
|
qq4 = a[60:0] / 4; // Check power-of-two constification
|
||||||
|
rq4 = a[60:0] % 4;
|
||||||
|
qq5 = a[60:0] / 5; // Non power-of-two
|
||||||
|
rq5 = a[60:0] % 5;
|
||||||
qqs = $signed(a[60:0]) / $signed(divisor);
|
qqs = $signed(a[60:0]) / $signed(divisor);
|
||||||
rqs = $signed(a[60:0]) % $signed(divisor);
|
rqs = $signed(a[60:0]) % $signed(divisor);
|
||||||
end
|
end
|
||||||
|
@ -34,6 +43,10 @@ module t (/*AUTOARG*/
|
||||||
divisor <= 61'h12371;
|
divisor <= 61'h12371;
|
||||||
a[60] <= 1'b0; divisor[60] <= 1'b0; // Unsigned
|
a[60] <= 1'b0; divisor[60] <= 1'b0; // Unsigned
|
||||||
end
|
end
|
||||||
|
if (cyc > 1) begin
|
||||||
|
if (qq4 != {2'b0, a[60:2]}) $stop;
|
||||||
|
if (rq4 != {59'h0, a[1:0]}) $stop;
|
||||||
|
end
|
||||||
if (cyc==2) begin
|
if (cyc==2) begin
|
||||||
a <= 256'h0e17c88f3d5fe51a982646c8e2bd68c3e236ddfddddbdad20a48e039c9f395b8;
|
a <= 256'h0e17c88f3d5fe51a982646c8e2bd68c3e236ddfddddbdad20a48e039c9f395b8;
|
||||||
divisor <= 61'h1238123771;
|
divisor <= 61'h1238123771;
|
||||||
|
@ -42,6 +55,8 @@ module t (/*AUTOARG*/
|
||||||
if (rq!==61'h00000000000090ec) $stop;
|
if (rq!==61'h00000000000090ec) $stop;
|
||||||
if (qqs!==61'h00000403ad81c0da) $stop;
|
if (qqs!==61'h00000403ad81c0da) $stop;
|
||||||
if (rqs!==61'h00000000000090ec) $stop;
|
if (rqs!==61'h00000000000090ec) $stop;
|
||||||
|
if (qq4 != 61'h01247cf6851f9fc9) $stop;
|
||||||
|
if (rq4 != 61'h0000000000000002) $stop;
|
||||||
end
|
end
|
||||||
if (cyc==3) begin
|
if (cyc==3) begin
|
||||||
a <= 256'h0e17c88f00d5fe51a982646c8002bd68c3e236ddfd00ddbdad20a48e00f395b8;
|
a <= 256'h0e17c88f00d5fe51a982646c8002bd68c3e236ddfd00ddbdad20a48e00f395b8;
|
||||||
|
@ -51,6 +66,8 @@ module t (/*AUTOARG*/
|
||||||
if (rq!==61'h0000000334becc6a) $stop;
|
if (rq!==61'h0000000334becc6a) $stop;
|
||||||
if (qqs!==61'h000000000090832e) $stop;
|
if (qqs!==61'h000000000090832e) $stop;
|
||||||
if (rqs!==61'h0000000334becc6a) $stop;
|
if (rqs!==61'h0000000334becc6a) $stop;
|
||||||
|
if (qq4 != 61'h0292380e727ce56e) $stop;
|
||||||
|
if (rq4 != 61'h0000000000000000) $stop;
|
||||||
end
|
end
|
||||||
if (cyc==4) begin
|
if (cyc==4) begin
|
||||||
a[60] <= 1'b0; divisor[60] <= 1'b1; // Signed
|
a[60] <= 1'b0; divisor[60] <= 1'b1; // Signed
|
||||||
|
@ -58,6 +75,8 @@ module t (/*AUTOARG*/
|
||||||
if (rq!==61'h0000000000000c40) $stop;
|
if (rq!==61'h0000000000000c40) $stop;
|
||||||
if (qqs!==61'h1fffcf5187c76510) $stop;
|
if (qqs!==61'h1fffcf5187c76510) $stop;
|
||||||
if (rqs!==61'h1ffffffffffffd08) $stop;
|
if (rqs!==61'h1ffffffffffffd08) $stop;
|
||||||
|
if (qq4 != 61'h07482923803ce56e) $stop;
|
||||||
|
if (rq4 != 61'h0000000000000000) $stop;
|
||||||
end
|
end
|
||||||
if (cyc==5) begin
|
if (cyc==5) begin
|
||||||
a[60] <= 1'b1; divisor[60] <= 1'b1; // Signed
|
a[60] <= 1'b1; divisor[60] <= 1'b1; // Signed
|
||||||
|
|
|
@ -1,10 +1,32 @@
|
||||||
module t(y);
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2020 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
|
module t(/*AUTOARG*/
|
||||||
|
// Outputs
|
||||||
|
y, d2, m2, d3, m3
|
||||||
|
);
|
||||||
output [3:0] y;
|
output [3:0] y;
|
||||||
|
output [31:0] d2;
|
||||||
|
output [31:0] m2;
|
||||||
|
output [63:0] d3;
|
||||||
|
output [63:0] m3;
|
||||||
// bug775
|
// bug775
|
||||||
// verilator lint_off WIDTH
|
// verilator lint_off WIDTH
|
||||||
assign y = ((0/0) ? 1 : 2) % 0;
|
assign y = ((0/0) ? 1 : 2) % 0;
|
||||||
|
|
||||||
|
// bug2460
|
||||||
|
reg [31:0] b;
|
||||||
|
assign d2 = $signed(32'h80000000) / $signed(b);
|
||||||
|
assign m2 = $signed(32'h80000000) % $signed(b);
|
||||||
|
reg [63:0] b3;
|
||||||
|
assign d3 = $signed(64'h80000000_00000000) / $signed(b3);
|
||||||
|
assign m3 = $signed(64'h80000000_00000000) % $signed(b3);
|
||||||
|
|
||||||
initial begin
|
initial begin
|
||||||
|
b = 32'hffffffff;
|
||||||
|
b3 = 64'hffffffff_ffffffff;
|
||||||
$write("*-* All Finished *-*\n");
|
$write("*-* All Finished *-*\n");
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
// without warranty, 2004 by Wilson Snyder.
|
// any use, without warranty, 2004 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t (/*AUTOARG*/
|
module t (/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
// without warranty, 2003 by Wilson Snyder.
|
// any use, without warranty, 2003 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t (/*AUTOARG*/
|
module t (/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
// without warranty, 2003 by Wilson Snyder.
|
// any use, without warranty, 2003 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t (/*AUTOARG*/
|
module t (/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
// without warranty, 2015 by Wilson Snyder.
|
// any use, without warranty, 2015 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t (/*AUTOARG*/
|
module t (/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
// without warranty, 2003 by Wilson Snyder.
|
// any use, without warranty, 2003 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t_order_a (/*AUTOARG*/
|
module t_order_a (/*AUTOARG*/
|
||||||
// Outputs
|
// Outputs
|
||||||
m_from_clk_lev1_r, n_from_clk_lev2, o_from_com_levs11, o_from_comandclk_levs12,
|
m_from_clk_lev1_r, n_from_clk_lev2, o_from_com_levs11,
|
||||||
|
o_from_comandclk_levs12,
|
||||||
// Inputs
|
// Inputs
|
||||||
clk, a_to_clk_levm3, b_to_clk_levm1, c_com_levs10, d_to_clk_levm2, one
|
clk, a_to_clk_levm3, b_to_clk_levm1, c_com_levs10, d_to_clk_levm2, one
|
||||||
);
|
);
|
||||||
|
@ -23,7 +25,7 @@ module t_order_a (/*AUTOARG*/
|
||||||
|
|
||||||
/*AUTOREG*/
|
/*AUTOREG*/
|
||||||
// Beginning of automatic regs (for this module's undeclared outputs)
|
// Beginning of automatic regs (for this module's undeclared outputs)
|
||||||
reg [7:0] m_from_clk_lev1_r;
|
reg [7:0] m_from_clk_lev1_r;
|
||||||
// End of automatics
|
// End of automatics
|
||||||
|
|
||||||
// surefire lint_off ASWEBB
|
// surefire lint_off ASWEBB
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
// without warranty, 2003 by Wilson Snyder.
|
// any use, without warranty, 2003 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t_order_b (/*AUTOARG*/
|
module t_order_b (/*AUTOARG*/
|
||||||
// Outputs
|
// Outputs
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
// without warranty, 2003 by Wilson Snyder.
|
// any use, without warranty, 2003 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t (/*AUTOARG*/
|
module t (/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
|
@ -10,14 +11,16 @@ module t (/*AUTOARG*/
|
||||||
input clk;
|
input clk;
|
||||||
|
|
||||||
// verilator lint_off COMBDLY
|
// verilator lint_off COMBDLY
|
||||||
|
// verilator lint_off LATCH
|
||||||
// verilator lint_off UNOPT
|
// verilator lint_off UNOPT
|
||||||
// verilator lint_off UNOPTFLAT
|
// verilator lint_off UNOPTFLAT
|
||||||
|
// verilator lint_off BLKANDNBLK
|
||||||
|
|
||||||
reg c1_start; initial c1_start = 0;
|
reg c1_start; initial c1_start = 0;
|
||||||
wire [31:0] c1_count;
|
wire [31:0] c1_count;
|
||||||
comb_loop c1 (.count(c1_count), .start(c1_start));
|
comb_loop c1 (.count(c1_count), .start(c1_start));
|
||||||
|
|
||||||
wire s2_start = (c1_count==0 && c1_start);
|
wire s2_start = c1_start;
|
||||||
wire [31:0] s2_count;
|
wire [31:0] s2_count;
|
||||||
seq_loop s2 (.count(s2_count), .start(s2_start));
|
seq_loop s2 (.count(s2_count), .start(s2_start));
|
||||||
|
|
||||||
|
@ -30,25 +33,29 @@ module t (/*AUTOARG*/
|
||||||
//$write("[%0t] %x counts %x %x %x\n",$time,cyc,c1_count,s2_count,c3_count);
|
//$write("[%0t] %x counts %x %x %x\n",$time,cyc,c1_count,s2_count,c3_count);
|
||||||
cyc <= cyc + 8'd1;
|
cyc <= cyc + 8'd1;
|
||||||
case (cyc)
|
case (cyc)
|
||||||
8'd00: begin
|
8'd00: begin
|
||||||
c1_start <= 1'b0;
|
c1_start <= 1'b0;
|
||||||
end
|
end
|
||||||
8'd01: begin
|
8'd01: begin
|
||||||
c1_start <= 1'b1;
|
c1_start <= 1'b1;
|
||||||
end
|
end
|
||||||
default: ;
|
default: ;
|
||||||
endcase
|
endcase
|
||||||
case (cyc)
|
case (cyc)
|
||||||
8'd02: begin
|
8'd02: begin
|
||||||
if (c1_count!=32'h3) $stop;
|
// On Verilator, we expect these comparisons to match exactly,
|
||||||
if (s2_count!=32'h3) $stop;
|
// confirming that our settle loop repeated the exact number of
|
||||||
if (c3_count!=32'h6) $stop;
|
// iterations we expect. No '$stop' should be called here, and we
|
||||||
end
|
// should reach the normal '$finish' below on the next cycle.
|
||||||
8'd03: begin
|
if (c1_count!=32'h3) $stop;
|
||||||
$write("*-* All Finished *-*\n");
|
if (s2_count!=32'h3) $stop;
|
||||||
$finish;
|
if (c3_count!=32'h5) $stop;
|
||||||
end
|
end
|
||||||
default: ;
|
8'd03: begin
|
||||||
|
$write("*-* All Finished *-*\n");
|
||||||
|
$finish;
|
||||||
|
end
|
||||||
|
default: ;
|
||||||
endcase
|
endcase
|
||||||
end
|
end
|
||||||
endmodule
|
endmodule
|
||||||
|
@ -62,12 +69,10 @@ module comb_loop (/*AUTOARG*/
|
||||||
input start;
|
input start;
|
||||||
output reg [31:0] count; initial count = 0;
|
output reg [31:0] count; initial count = 0;
|
||||||
|
|
||||||
reg [31:0] runnerm1, runner; initial runner = 0;
|
reg [31:0] runnerm1, runner; initial runner = 0;
|
||||||
|
|
||||||
always @ (start) begin
|
always @ (posedge start) begin
|
||||||
if (start) begin
|
runner = 3;
|
||||||
runner = 3;
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
always @ (/*AS*/runner) begin
|
always @ (/*AS*/runner) begin
|
||||||
|
@ -76,9 +81,9 @@ module comb_loop (/*AUTOARG*/
|
||||||
|
|
||||||
always @ (/*AS*/runnerm1) begin
|
always @ (/*AS*/runnerm1) begin
|
||||||
if (runner > 0) begin
|
if (runner > 0) begin
|
||||||
count = count + 1;
|
count = count + 1;
|
||||||
runner = runnerm1;
|
runner = runnerm1;
|
||||||
$write ("%m count=%d runner =%x\n",count, runnerm1);
|
$write ("%m count=%d runner =%x\n",count, runnerm1);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -93,12 +98,10 @@ module seq_loop (/*AUTOARG*/
|
||||||
input start;
|
input start;
|
||||||
output reg [31:0] count; initial count = 0;
|
output reg [31:0] count; initial count = 0;
|
||||||
|
|
||||||
reg [31:0] runnerm1, runner; initial runner = 0;
|
reg [31:0] runnerm1, runner; initial runner = 0;
|
||||||
|
|
||||||
always @ (start) begin
|
always @ (posedge start) begin
|
||||||
if (start) begin
|
runner <= 3;
|
||||||
runner <= 3;
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
always @ (/*AS*/runner) begin
|
always @ (/*AS*/runner) begin
|
||||||
|
@ -107,9 +110,9 @@ module seq_loop (/*AUTOARG*/
|
||||||
|
|
||||||
always @ (/*AS*/runnerm1) begin
|
always @ (/*AS*/runnerm1) begin
|
||||||
if (runner > 0) begin
|
if (runner > 0) begin
|
||||||
count = count + 1;
|
count = count + 1;
|
||||||
runner <= runnerm1;
|
runner <= runnerm1;
|
||||||
$write ("%m count=%d runner<=%x\n",count, runnerm1);
|
$write ("%m count=%d runner<=%x\n",count, runnerm1);
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
// without warranty, 2003 by Wilson Snyder.
|
// any use, without warranty, 2003 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t (/*AUTOARG*/
|
module t (/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
|
@ -11,6 +12,7 @@ module t (/*AUTOARG*/
|
||||||
|
|
||||||
// verilator lint_off BLKANDNBLK
|
// verilator lint_off BLKANDNBLK
|
||||||
// verilator lint_off COMBDLY
|
// verilator lint_off COMBDLY
|
||||||
|
// verilator lint_off LATCH
|
||||||
// verilator lint_off UNOPT
|
// verilator lint_off UNOPT
|
||||||
// verilator lint_off UNOPTFLAT
|
// verilator lint_off UNOPTFLAT
|
||||||
// verilator lint_off MULTIDRIVEN
|
// verilator lint_off MULTIDRIVEN
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
// without warranty, 2003 by Wilson Snyder.
|
// any use, without warranty, 2003 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t (/*AUTOARG*/
|
module t (/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
|
@ -10,6 +11,7 @@ module t (/*AUTOARG*/
|
||||||
input clk;
|
input clk;
|
||||||
integer cyc; initial cyc=1;
|
integer cyc; initial cyc=1;
|
||||||
|
|
||||||
|
// verilator lint_off LATCH
|
||||||
// verilator lint_off UNOPT
|
// verilator lint_off UNOPT
|
||||||
// verilator lint_off UNOPTFLAT
|
// verilator lint_off UNOPTFLAT
|
||||||
reg [31:0] runner; initial runner = 5;
|
reg [31:0] runner; initial runner = 5;
|
||||||
|
@ -38,7 +40,7 @@ module t (/*AUTOARG*/
|
||||||
end
|
end
|
||||||
|
|
||||||
// This forms a "loop" where we keep going through the always till runner=0
|
// This forms a "loop" where we keep going through the always till runner=0
|
||||||
// This isn't "regular" beh code, but insures our change detection is working properly
|
// This isn't "regular" beh code, but ensures our change detection is working properly
|
||||||
always @ (/*AS*/runner) begin
|
always @ (/*AS*/runner) begin
|
||||||
runnerm1 = runner - 32'd1;
|
runnerm1 = runner - 32'd1;
|
||||||
end
|
end
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
// without warranty, 2005 by Wilson Snyder.
|
// any use, without warranty, 2005 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t (/*AUTOARG*/
|
module t (/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
|
@ -10,6 +11,7 @@ module t (/*AUTOARG*/
|
||||||
input clk;
|
input clk;
|
||||||
integer cyc; initial cyc=1;
|
integer cyc; initial cyc=1;
|
||||||
|
|
||||||
|
// verilator lint_off LATCH
|
||||||
// verilator lint_off UNOPT
|
// verilator lint_off UNOPT
|
||||||
// verilator lint_off UNOPTFLAT
|
// verilator lint_off UNOPTFLAT
|
||||||
// verilator lint_off MULTIDRIVEN
|
// verilator lint_off MULTIDRIVEN
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
// without warranty, 2003 by Wilson Snyder.
|
// any use, without warranty, 2003 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t (/*AUTOARG*/
|
module t (/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
// without warranty, 2012 by Jeremy Bennett.
|
// without warranty, 2012 by Jeremy Bennett.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t (/*AUTOARG*/
|
module t (/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
|
@ -15,7 +16,7 @@ module t (/*AUTOARG*/
|
||||||
);
|
);
|
||||||
input clk;
|
input clk;
|
||||||
|
|
||||||
reg ready;
|
reg ready;
|
||||||
|
|
||||||
initial begin
|
initial begin
|
||||||
ready = 1'b0;
|
ready = 1'b0;
|
||||||
|
@ -23,8 +24,8 @@ module t (/*AUTOARG*/
|
||||||
|
|
||||||
always @(posedge ready) begin
|
always @(posedge ready) begin
|
||||||
if ((ready === 1'b1)) begin
|
if ((ready === 1'b1)) begin
|
||||||
$write("*-* All Finished *-*\n");
|
$write("*-* All Finished *-*\n");
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
// without warranty, 2005 by Wilson Snyder.
|
// any use, without warranty, 2005 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t (/*AUTOARG*/
|
module t (/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
|
|
|
@ -2,11 +2,12 @@
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
// without warranty, 2013 by Ted Campbell.
|
// without warranty, 2013 by Ted Campbell.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
//With MULTI_CLK defined shows bug, without it is hidden
|
//With MULTI_CLK defined shows bug, without it is hidden
|
||||||
`define MULTI_CLK
|
`define MULTI_CLK
|
||||||
|
|
||||||
//bug634
|
//bug634
|
||||||
|
|
||||||
module t (
|
module t (
|
||||||
input i_clk_wr,
|
input i_clk_wr,
|
||||||
|
@ -162,13 +163,13 @@ module FooMemImpl(
|
||||||
input a_wen,
|
input a_wen,
|
||||||
input [7:0] a_addr,
|
input [7:0] a_addr,
|
||||||
input [7:0] a_wdata,
|
input [7:0] a_wdata,
|
||||||
output [7:0] a_rdata,
|
output reg [7:0] a_rdata,
|
||||||
|
|
||||||
input b_clk,
|
input b_clk,
|
||||||
input b_wen,
|
input b_wen,
|
||||||
input [7:0] b_addr,
|
input [7:0] b_addr,
|
||||||
input [7:0] b_wdata,
|
input [7:0] b_wdata,
|
||||||
output [7:0] b_rdata
|
output reg [7:0] b_rdata
|
||||||
);
|
);
|
||||||
|
|
||||||
/* verilator lint_off MULTIDRIVEN */
|
/* verilator lint_off MULTIDRIVEN */
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
// without warranty, 2014 by Wilson Snyder.
|
// any use, without warranty, 2014 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
//bug 762
|
//bug 762
|
||||||
module t(a0, y);
|
module t(a0, y);
|
||||||
|
@ -12,5 +13,5 @@ module t(a0, y);
|
||||||
assign y[30] = 0;
|
assign y[30] = 0;
|
||||||
// verilator lint_off UNOPTFLAT
|
// verilator lint_off UNOPTFLAT
|
||||||
assign { y[44:41], y[39:31], y[29:0] } = { 6'b000000, a0, 7'b0000000, y[40], y[30], y[30], y[30], y[30], 21'b000000000000000000000 };
|
assign { y[44:41], y[39:31], y[29:0] } = { 6'b000000, a0, 7'b0000000, y[40], y[30], y[30], y[30], y[30], 21'b000000000000000000000 };
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
// without warranty, 2005 by Wilson Snyder.
|
// any use, without warranty, 2005 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t (/*AUTOARG*/
|
module t (/*AUTOARG*/
|
||||||
// Outputs
|
// Outputs
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
// without warranty, 2012 by Wilson Snyder.
|
// any use, without warranty, 2012 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t (/*AUTOARG*/
|
module t (/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
|
@ -36,8 +37,8 @@ module updown #(parameter UP=0)
|
||||||
endgenerate
|
endgenerate
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module t_up (inout tri1 z);
|
module t_up (inout tri1 z);
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
module t_down (inout tri0 z);
|
module t_down (inout tri0 z);
|
||||||
endmodule
|
endmodule
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
// DESCRIPTION: Verilator: Unsupported tristate constructur error
|
// DESCRIPTION: Verilator: Unsupported tristate construct error
|
||||||
//
|
//
|
||||||
// This is a compile only regression test of tristate handling for bug514
|
// This is a compile only regression test of tristate handling for bug514
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
// without warranty, 2012 by Jeremy Bennett.
|
// without warranty, 2012 by Jeremy Bennett.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t (/*AUTOARG*/
|
module t (/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
|
// any use, without warranty, 2020 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module top (/*AUTOARG*/
|
module t (/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
clk
|
clk
|
||||||
);
|
);
|
||||||
input clk;
|
input clk;
|
||||||
|
|
||||||
tri pad_io_h;
|
tri pad_io_h;
|
||||||
tri pad_io_l;
|
tri pad_io_l;
|
||||||
|
|
||||||
sub sub (.*);
|
sub sub (.*);
|
||||||
|
|
||||||
|
@ -45,8 +48,7 @@ module sub (/*AUTOARG*/
|
||||||
if (DIFFERENTIAL)
|
if (DIFFERENTIAL)
|
||||||
assign pad_io_l = sig_l_r;
|
assign pad_io_l = sig_l_r;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
endgenerate
|
endgenerate
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
// without warranty, 2008 by Lane Brooks
|
// without warranty, 2008 by Lane Brooks.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module top (input A, input B, input SEL, output Y1, output Y2, output Z);
|
module top (input A, input B, input SEL, output Y1, output Y2, output Z);
|
||||||
io io1(.A(A), .OE( SEL), .Z(Z), .Y(Y1));
|
io io1(.A(A), .OE( SEL), .Z(Z), .Y(Y1));
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
// without warranty, 2008 by Wilson Snyder.
|
// any use, without warranty, 2008 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t (/*AUTOARG*/
|
module t (/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
|
@ -22,7 +23,6 @@ module t (/*AUTOARG*/
|
||||||
ChildA childa ( .A(a), .B(b), .en(en), .Y(y),.Yfix(y_fixed) );
|
ChildA childa ( .A(a), .B(b), .en(en), .Y(y),.Yfix(y_fixed) );
|
||||||
|
|
||||||
initial in=0;
|
initial in=0;
|
||||||
initial en=0;
|
|
||||||
|
|
||||||
// Test loop
|
// Test loop
|
||||||
always @ (posedge clk) begin
|
always @ (posedge clk) begin
|
||||||
|
@ -51,7 +51,7 @@ module t (/*AUTOARG*/
|
||||||
end
|
end
|
||||||
|
|
||||||
if (in==3) begin
|
if (in==3) begin
|
||||||
$write("*-* All Finished *-*\n");
|
$write("*-* All Finished *-*\n");
|
||||||
$finish;
|
$finish;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
@ -74,4 +74,3 @@ endmodule
|
||||||
module ChildB(input A, output Y);
|
module ChildB(input A, output Y);
|
||||||
assign Y = A;
|
assign Y = A;
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
// without warranty, 2008 by Lane Brooks
|
// without warranty, 2008 by Lane Brooks.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module top (input A, input OE, output X, output Y, output Z);
|
module top (input A, input OE, output X, output Y, output Z);
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
// without warranty, 2012 by Jeremy Bennett.
|
// without warranty, 2012 by Jeremy Bennett.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t (/*AUTOARG*/
|
module t (/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
|
@ -13,7 +14,7 @@ module t (/*AUTOARG*/
|
||||||
|
|
||||||
wire [1:0] b;
|
wire [1:0] b;
|
||||||
wire [1:0] c;
|
wire [1:0] c;
|
||||||
wire [0:0] d; // Explicit width due to issue 508
|
wire [0:0] d; // Explicit width due to issue 508
|
||||||
wire [0:0] e;
|
wire [0:0] e;
|
||||||
|
|
||||||
// This works if we use 1'bz, or 1'bx, but not with just 'bz or 'bx. It
|
// This works if we use 1'bz, or 1'bx, but not with just 'bz or 'bx. It
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
// DESCRIPTION: Verilator: Verilog Test module
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
//
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||||
// without warranty, 2012 by Wilson Snyder.
|
// any use, without warranty, 2012 by Wilson Snyder.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t (/*AUTOARG*/
|
module t (/*AUTOARG*/
|
||||||
// Inputs
|
// Inputs
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
|
// DESCRIPTION: Verilator: Verilog Test module
|
||||||
|
//
|
||||||
// This file ONLY is placed into the Public Domain, for any use,
|
// This file ONLY is placed into the Public Domain, for any use,
|
||||||
// without warranty, 2008 by Lane Brooks
|
// without warranty, 2008 by Lane Brooks.
|
||||||
|
// SPDX-License-Identifier: CC0-1.0
|
||||||
|
|
||||||
module t (clk);
|
module t (clk);
|
||||||
input clk;
|
input clk;
|
||||||
|
@ -208,4 +211,3 @@ endmodule
|
||||||
// end
|
// end
|
||||||
// end
|
// end
|
||||||
//endmodule
|
//endmodule
|
||||||
|
|
||||||
|
|
|
@ -1,18 +1,21 @@
|
||||||
|
|
||||||
|
var _require = require;
|
||||||
var assert = require('assert');
|
var assert = require('assert');
|
||||||
var fs = require('fs');
|
var fs = require('fs');
|
||||||
var vm = require('vm');
|
var vm = require('vm');
|
||||||
|
|
||||||
var worker = {};
|
var worker = {};
|
||||||
|
|
||||||
|
process.exit = function() { console.log("arggh you can't exit when i pass noExitRuntime! lol process.exit() go brrr") }
|
||||||
|
|
||||||
global.window = global;
|
global.window = global;
|
||||||
global.exports = {};
|
global.exports = {};
|
||||||
global.self = global;
|
global.self = global;
|
||||||
global.location = {href:'.'};
|
global.location = {href:'.'};
|
||||||
global.require = (modname) => {
|
global.require = (modname) => {
|
||||||
console.log("REQUIRE",modname);
|
//console.log("REQUIRE",modname);
|
||||||
if (modname == 'path')
|
if (modname == 'path')
|
||||||
return require(modname);
|
return _require(modname);
|
||||||
};
|
};
|
||||||
|
|
||||||
global.btoa = require('btoa');
|
global.btoa = require('btoa');
|
||||||
|
|
Loading…
Reference in New Issue