(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",
|
||||
"license": "GPL-3.0",
|
||||
"dependencies": {
|
||||
"binaryen": "^101.0.0",
|
||||
"chokidar": "^3.5.0",
|
||||
"electron-store": "^6.0.1",
|
||||
"jquery": "^3.5.1",
|
||||
|
@ -789,6 +790,14 @@
|
|||
"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": {
|
||||
"version": "3.7.2",
|
||||
"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",
|
||||
"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": {
|
||||
"version": "3.7.2",
|
||||
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
},
|
||||
"license": "GPL-3.0",
|
||||
"dependencies": {
|
||||
"binaryen": "^101.0.0",
|
||||
"chokidar": "^3.5.0",
|
||||
"electron-store": "^6.0.1",
|
||||
"jquery": "^3.5.1",
|
||||
|
|
|
@ -25,7 +25,7 @@ module ALU(A, B, carry, aluop, Y);
|
|||
input [N-1:0] B; // B input
|
||||
input carry; // carry input
|
||||
input [3:0] aluop; // alu operation
|
||||
output [N:0] Y; // Y output + carry
|
||||
output reg [N:0] Y; // Y output + carry
|
||||
|
||||
always @(*)
|
||||
case (aluop)
|
||||
|
|
|
@ -42,8 +42,8 @@ module ball_absolute_top(clk, reset, hsync, vsync, rgb);
|
|||
begin
|
||||
if (reset) begin
|
||||
// reset ball position to center
|
||||
ball_hpos <= ball_horiz_initial;
|
||||
ball_vpos <= ball_vert_initial;
|
||||
ball_hpos <= ball_horiz_initial;
|
||||
end else begin
|
||||
// add velocity vector to ball position
|
||||
ball_hpos <= ball_hpos + ball_horiz_move;
|
||||
|
|
|
@ -16,7 +16,7 @@ module clock_divider(
|
|||
// simple ripple clock divider
|
||||
|
||||
always @(posedge clk)
|
||||
clk_div2 <= ~clk_div2;
|
||||
clk_div2 <= reset ? 0 : ~clk_div2;
|
||||
|
||||
always @(posedge clk_div2)
|
||||
clk_div4 <= ~clk_div4;
|
||||
|
|
|
@ -56,11 +56,14 @@ $$end
|
|||
// -------------------------
|
||||
|
||||
algorithm main(
|
||||
$$if NTSC then
|
||||
// NTSC
|
||||
output! uint$color_depth$ video_r,
|
||||
output! uint$color_depth$ video_g,
|
||||
output! uint$color_depth$ video_b,
|
||||
output! uint1 video_hs,
|
||||
output! uint1 video_vs
|
||||
$$end
|
||||
)
|
||||
<@clock,!reset>
|
||||
{
|
||||
|
|
|
@ -28,7 +28,7 @@ module ALU(A, B, carry, aluop, Y);
|
|||
input [N-1:0] B; // B input
|
||||
input carry; // carry input
|
||||
input [3:0] aluop; // alu operation
|
||||
output [N:0] Y; // Y output + carry
|
||||
output reg [N:0] Y; // Y output + carry
|
||||
|
||||
always @(*)
|
||||
case (aluop)
|
||||
|
@ -72,14 +72,14 @@ endmodule
|
|||
module CPU16(clk, reset, hold, busy,
|
||||
address, data_in, data_out, write);
|
||||
|
||||
input clk;
|
||||
input reset;
|
||||
input hold;
|
||||
output busy;
|
||||
output [15:0] address;
|
||||
input [15:0] data_in;
|
||||
output [15:0] data_out;
|
||||
output write;
|
||||
input clk;
|
||||
input reset;
|
||||
input hold;
|
||||
output reg busy;
|
||||
output reg [15:0] address;
|
||||
input [15:0] data_in;
|
||||
output reg [15:0] data_out;
|
||||
output reg write;
|
||||
|
||||
// wait state for RAM?
|
||||
parameter RAM_WAIT = 1;
|
||||
|
|
|
@ -1339,7 +1339,7 @@ endmodule
|
|||
module cpu6502_test_top(clk, reset, AB, DI, DO, WE);
|
||||
input clk,reset;
|
||||
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 WE; // write enable
|
||||
wire IRQ=0; // interrupt request
|
||||
|
|
|
@ -28,7 +28,7 @@ module ALU(A, B, carry, aluop, Y);
|
|||
input [N-1:0] B; // B input
|
||||
input carry; // carry input
|
||||
input [3:0] aluop; // alu operation
|
||||
output [N:0] Y; // Y output + carry
|
||||
output reg [N:0] Y; // Y output + carry
|
||||
|
||||
always @(*)
|
||||
case (aluop)
|
||||
|
@ -99,12 +99,12 @@ tttt = flags test for conditional branch
|
|||
|
||||
module CPU(clk, reset, address, data_in, data_out, write);
|
||||
|
||||
input clk;
|
||||
input reset;
|
||||
output [7:0] address;
|
||||
input [7:0] data_in;
|
||||
output [7:0] data_out;
|
||||
output write;
|
||||
input clk;
|
||||
input reset;
|
||||
output reg [7:0] address;
|
||||
input [7:0] data_in;
|
||||
output reg [7:0] data_out;
|
||||
output reg write;
|
||||
|
||||
reg [7:0] IP;
|
||||
reg [7:0] A, B;
|
||||
|
|
|
@ -46,7 +46,7 @@ module cpu_platform(clk, reset, hsync, vsync,
|
|||
reg [5:0] sprite_ram_addr;
|
||||
wire tile_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
|
||||
always @(*)
|
||||
|
@ -138,11 +138,12 @@ module cpu_platform(clk, reset, hsync, vsync,
|
|||
wire cpu_busy;
|
||||
wire [15:0] cpu_ram_addr;
|
||||
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] switches = {switches_p2, switches_p1};
|
||||
|
||||
// select ROM, RAM, switches ($FFFE) or flags ($FFFF)
|
||||
/* verilator lint_off CASEOVERLAP */
|
||||
always @(*)
|
||||
casez (cpu_ram_addr)
|
||||
16'hfffe: cpu_bus = switches;
|
||||
|
|
|
@ -163,9 +163,11 @@ module digits10_array(digit, yofs, bits);
|
|||
bitarray[9][4] = 5'b11111;
|
||||
|
||||
// clear unused array entries
|
||||
/* TODO
|
||||
for (i = 10; i <= 15; i++)
|
||||
for (j = 0; j <= 4; j++)
|
||||
bitarray[i][j] = 0;
|
||||
*/
|
||||
end
|
||||
endmodule
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
|
||||
{
|
||||
"name":"femto8",
|
||||
"width":8,
|
||||
"vars":{
|
||||
"reg":{"bits":2, "toks":["a", "b", "ip", "none"]},
|
||||
"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 [8:0] hpos;
|
||||
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] rom[0:1023]; // ROM (1024 x 16 bits)
|
||||
|
|
|
@ -21,9 +21,10 @@ module RAM_sync(clk, addr, din, dout, we);
|
|||
input clk; // clock
|
||||
input [A-1:0] addr; // address
|
||||
input [D-1:0] din; // data input
|
||||
output [D-1:0] dout; // data output
|
||||
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
|
||||
|
||||
always @(posedge clk) begin
|
||||
|
|
|
@ -32,6 +32,7 @@ algorithm frame_display(
|
|||
int20 deltau_y = 0;
|
||||
int20 deltav_x = 0;
|
||||
int20 deltav_y = 0;
|
||||
int8 scale = 128;
|
||||
|
||||
brom uint18 tbl[$32*32$] = {
|
||||
$$write_image_in_table('tile.tga',6)
|
||||
|
@ -84,8 +85,6 @@ $$end
|
|||
// prepare scanline with mapping
|
||||
corneru = - ((cornerx * cos) - (cornery * sin));
|
||||
cornerv = - ((cornerx * sin) + (cornery * cos));
|
||||
//corneru = ((cornerx * cos) - (cornery * sin));
|
||||
//cornerv = ((cornerx * sin) + (cornery * cos));
|
||||
deltau_x = cos;
|
||||
deltau_y = - 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 load; // ok to load sprite data?
|
||||
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
|
||||
output gfx; // output pixel
|
||||
output reg gfx; // output pixel
|
||||
output in_progress; // 0 if waiting for vstart
|
||||
|
||||
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 hmirror, vmirror;
|
||||
output [4:0] rom_addr;
|
||||
output reg [4:0] rom_addr;
|
||||
input [7:0] rom_bits;
|
||||
output gfx;
|
||||
output reg gfx;
|
||||
output busy;
|
||||
|
||||
assign busy = state != WAIT_FOR_VSTART;
|
||||
|
@ -191,8 +191,8 @@ endmodule
|
|||
module rotation_selector(rotation, bitmap_num, hmirror, vmirror);
|
||||
|
||||
input [3:0] rotation; // angle (0..15)
|
||||
output [2:0] bitmap_num; // bitmap index (0..4)
|
||||
output hmirror, vmirror; // horiz & vert mirror bits
|
||||
output reg [2:0] bitmap_num; // bitmap index (0..4)
|
||||
output reg hmirror, vmirror; // horiz & vert mirror bits
|
||||
|
||||
always @(*)
|
||||
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 [8:0] hpos; // horiz. 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)
|
||||
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
|
||||
|
||||
// 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)
|
||||
);
|
||||
|
||||
wire [5:0] ram_addr;
|
||||
reg [5:0] ram_addr;
|
||||
wire [15:0] ram_read;
|
||||
reg [15:0] ram_write;
|
||||
reg ram_we;
|
||||
wire ram_busy;
|
||||
reg ram_busy;
|
||||
|
||||
// 64-word 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.
|
||||
wire r = display_on && (((hpos&7)==0) || ((vpos&7)==0));
|
||||
wire g = display_on && vpos[4];
|
||||
wire b = display_on && hpos[4];
|
||||
wire r = display_on & (((hpos&7)==0) | ((vpos&7)==0));
|
||||
wire g = display_on & vpos[4];
|
||||
wire b = display_on & hpos[4];
|
||||
|
||||
// Concatenation operator merges the red, green, and blue signals
|
||||
// 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;
|
||||
writeFile?(path: string, data: FileData) : boolean;
|
||||
|
||||
getDownloadFile?() : {extension:string, blob:Blob};
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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 suffix = (platform.getROMExtension && platform.getROMExtension(current_output))
|
||||
|| "-" + getBasePlatform(platform_id) + ".bin";
|
||||
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 {
|
||||
alertError(`The "${platform_id}" platform doesn't have downloadable ROMs.`);
|
||||
}
|
||||
|
@ -997,8 +998,11 @@ function _downloadAllFilesZipFile(e) {
|
|||
loadScript('lib/jszip.min.js').then( () => {
|
||||
var zip = new JSZip();
|
||||
store.keys( (err, keys : string[]) => {
|
||||
setWaitDialog(true);
|
||||
var i = 0;
|
||||
return Promise.all(keys.map( (path) => {
|
||||
return store.getItem(path).then( (text) => {
|
||||
setWaitProgress(i++/(keys.length+1));
|
||||
if (text) {
|
||||
zip.file(path, text);
|
||||
}
|
||||
|
@ -1007,9 +1011,9 @@ function _downloadAllFilesZipFile(e) {
|
|||
return zip.generateAsync({type:"blob"});
|
||||
}).then( (content) => {
|
||||
return saveAs(content, getBasePlatform(platform_id) + "-all.zip");
|
||||
});
|
||||
}).finally(() => setWaitDialog(false));
|
||||
});
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
function populateExamples(sel) {
|
||||
|
@ -1184,6 +1188,7 @@ function setCompileOutput(data: WorkerResult) {
|
|||
toolbar.addClass("has-errors");
|
||||
showExceptionAsError(e, e+"");
|
||||
current_output = null;
|
||||
refreshWindowList();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,12 +2,18 @@
|
|||
import { Platform, BasePlatform } from "../common/baseplatform";
|
||||
import { PLATFORMS, setKeyboardFromMap, AnimationTimer, RasterVideo, Keys, makeKeycodeMap, getMousePos, KeyFlags } from "../common/emu";
|
||||
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 { 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;
|
||||
|
||||
interface WaveformSignal extends WaveformMeta {
|
||||
name: string;
|
||||
}
|
||||
|
||||
var VERILOG_PRESETS = [
|
||||
{id:'clock_divider.v', name:'Clock Divider'},
|
||||
{id:'binary_counter.v', name:'Binary Counter'},
|
||||
|
@ -64,198 +70,8 @@ var VERILOG_KEYCODE_MAP = makeKeycodeMap([
|
|||
|
||||
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;
|
||||
|
||||
// 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
|
||||
|
||||
var VerilogPlatform = function(mainElement, options) {
|
||||
|
@ -268,9 +84,9 @@ var VerilogPlatform = function(mainElement, options) {
|
|||
var videoHeight = 256;
|
||||
var maxVideoLines = 262+40; // vertical hold
|
||||
var idata, timer, timerCallback;
|
||||
var top : HDLModuleJS;
|
||||
var gen;
|
||||
var cyclesPerFrame = (256+23+7+23)*262; // 4857480/60 Hz
|
||||
var current_output;
|
||||
|
||||
// control inputs
|
||||
var switches = [0,0,0];
|
||||
|
@ -317,7 +133,7 @@ var VerilogPlatform = function(mainElement, options) {
|
|||
var frameRate = 0;
|
||||
|
||||
function vidtick() {
|
||||
gen.tick2();
|
||||
top.tick2();
|
||||
if (useAudio)
|
||||
audio.feedSample(gen.spkr*(1.0/255.0), 1);
|
||||
if (keycode && keycode >= 128 && gen.keystrobe) // keystrobe = clear hi bit of key buffer
|
||||
|
@ -326,6 +142,16 @@ var VerilogPlatform = function(mainElement, options) {
|
|||
debugCond = null;
|
||||
}
|
||||
|
||||
function doreset() {
|
||||
gen.reset = 1;
|
||||
}
|
||||
|
||||
function unreset() {
|
||||
if (gen.reset !== undefined) {
|
||||
gen.reset = 0;
|
||||
}
|
||||
}
|
||||
|
||||
// inner Platform class
|
||||
|
||||
class _VerilogPlatform extends BasePlatform implements WaveformProvider {
|
||||
|
@ -345,7 +171,9 @@ var VerilogPlatform = function(mainElement, options) {
|
|||
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.create();
|
||||
poller = setKeyboardFromMap(video, switches, VERILOG_KEYCODE_MAP, (o,key,code,flags) => {
|
||||
|
@ -358,7 +186,7 @@ var VerilogPlatform = function(mainElement, options) {
|
|||
timerCallback = () => {
|
||||
if (!this.isRunning())
|
||||
return;
|
||||
if (gen) gen.switches = switches[0];
|
||||
if (gen && gen.switches != null) gen.switches = switches[0];
|
||||
this.updateFrame();
|
||||
};
|
||||
this.setFrameRate(60);
|
||||
|
@ -396,7 +224,7 @@ var VerilogPlatform = function(mainElement, options) {
|
|||
while (framey != new_y || clock++ > 200000) {
|
||||
this.setGenInputs();
|
||||
this.updateVideoFrameCycles(1, true, false);
|
||||
gen.__unreset();
|
||||
unreset();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -410,10 +238,10 @@ var VerilogPlatform = function(mainElement, options) {
|
|||
setGenInputs() {
|
||||
useAudio = (audio != null);
|
||||
//TODO debugCond = this.getDebugCallback();
|
||||
gen.switches_p1 = switches[0];
|
||||
gen.switches_p2 = switches[1];
|
||||
gen.switches_gen = switches[2];
|
||||
gen.keycode = keycode;
|
||||
if (gen.switches_p1 != null) gen.switches_p1 = switches[0];
|
||||
if (gen.switches_p2 != null) gen.switches_p2 = switches[1];
|
||||
if (gen.switches_gen != null) gen.switches_gen = switches[2];
|
||||
if (gen.keycode != null) gen.keycode = keycode;
|
||||
}
|
||||
|
||||
updateVideoFrame() {
|
||||
|
@ -434,7 +262,7 @@ var VerilogPlatform = function(mainElement, options) {
|
|||
idata[frameidx] = -1;
|
||||
}
|
||||
//this.restartDebugState();
|
||||
gen.__unreset();
|
||||
unreset();
|
||||
this.refreshVideoFrame();
|
||||
// set scope offset
|
||||
if (trace && this.waveview) {
|
||||
|
@ -450,7 +278,7 @@ var VerilogPlatform = function(mainElement, options) {
|
|||
advance(novideo : boolean) : number {
|
||||
this.setGenInputs();
|
||||
this.updateVideoFrameCycles(cyclesPerFrame, true, false);
|
||||
gen.__unreset();
|
||||
unreset();
|
||||
if (!novideo) {
|
||||
this.refreshVideoFrame();
|
||||
}
|
||||
|
@ -547,16 +375,16 @@ var VerilogPlatform = function(mainElement, options) {
|
|||
framehsync = false;
|
||||
framex = 0;
|
||||
framey++;
|
||||
gen.hpaddle = framey > video.paddle_x ? 1 : 0;
|
||||
gen.vpaddle = framey > video.paddle_y ? 1 : 0;
|
||||
if (gen.hpaddle != null) gen.hpaddle = framey > video.paddle_x ? 1 : 0;
|
||||
if (gen.vpaddle != null) gen.vpaddle = framey > video.paddle_y ? 1 : 0;
|
||||
}
|
||||
if (framey > maxVideoLines || gen.vsync) {
|
||||
framevsync = true;
|
||||
framey = 0;
|
||||
framex = 0;
|
||||
frameidx = 0;
|
||||
gen.hpaddle = 0;
|
||||
gen.vpaddle = 0;
|
||||
if (gen.hpaddle != null) gen.hpaddle = 0;
|
||||
if (gen.vpaddle != null) gen.vpaddle = 0;
|
||||
} else {
|
||||
var wasvsync = framevsync;
|
||||
framevsync = false;
|
||||
|
@ -573,8 +401,7 @@ var VerilogPlatform = function(mainElement, options) {
|
|||
for (var i=0; i<arr.length; i++) {
|
||||
var v = arr[i];
|
||||
var z = gen[v.name];
|
||||
if (typeof(z) === 'number')
|
||||
trace_buffer[trace_index] = z;
|
||||
trace_buffer[trace_index] = z+0;
|
||||
trace_index++;
|
||||
}
|
||||
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);
|
||||
while (trace_index < max_index) {
|
||||
gen.clk ^= 1;
|
||||
gen.eval();
|
||||
top.eval();
|
||||
this.snapshotTrace();
|
||||
if (trace_index == 0)
|
||||
break;
|
||||
}
|
||||
gen.__unreset();
|
||||
unreset();
|
||||
return (trace_index == 0);
|
||||
}
|
||||
|
||||
|
@ -633,35 +460,36 @@ var VerilogPlatform = function(mainElement, options) {
|
|||
}
|
||||
}
|
||||
|
||||
loadROM(title, output) {
|
||||
var mod;
|
||||
if (output.code) {
|
||||
// is code identical?
|
||||
if (current_output && current_output.code == output.code) {
|
||||
} else {
|
||||
try {
|
||||
mod = new Function('base', output.code);
|
||||
} catch (e) {
|
||||
this.printErrorCodeContext(e, output.code);
|
||||
throw e;
|
||||
}
|
||||
// compile Verilog code
|
||||
var base = new (VerilatorBase as any)();
|
||||
gen = new mod();
|
||||
//$.extend(gen, base);
|
||||
gen.__proto__ = base;
|
||||
current_output = output;
|
||||
module_name = output.name ? output.name.substr(1) : "top";
|
||||
//trace_ports = current_output.ports;
|
||||
trace_signals = current_output.ports.concat(current_output.signals); // combine ports + signals
|
||||
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
|
||||
loadROM(title:string, output:any) {
|
||||
var unit = output as HDLUnit;
|
||||
var topmod = unit.modules['TOP'];
|
||||
if (unit.modules && topmod) {
|
||||
{
|
||||
// initialize top module and constant pool
|
||||
top = new HDLModuleJS(topmod, unit.modules['@CONST-POOL@']);
|
||||
top.init();
|
||||
top.reset();
|
||||
gen = top.state;
|
||||
// create signal array
|
||||
var signals : WaveformSignal[] = [];
|
||||
for (var key in topmod.vardefs) {
|
||||
var vardef = topmod.vardefs[key];
|
||||
if (isLogicType(vardef.dtype)) {
|
||||
signals.push({
|
||||
name: key,
|
||||
label: vardef.origName,
|
||||
input: vardef.isInput,
|
||||
output: vardef.isOutput,
|
||||
len: vardef.dtype.left+1
|
||||
});
|
||||
}
|
||||
}
|
||||
trace_signals = signals;
|
||||
trace_signals = trace_signals.filter((v) => { return !v.label.startsWith("__V"); }); // remove __Vclklast etc
|
||||
trace_index = 0;
|
||||
// power on module
|
||||
// reset
|
||||
this.poweron();
|
||||
// query output
|
||||
// query output signals -- video or not?
|
||||
this.hasvideo = gen.vsync !== undefined && gen.hsync !== undefined && gen.rgb !== undefined;
|
||||
if (this.hasvideo) {
|
||||
const IGNORE_SIGNALS = ['clk','reset'];
|
||||
|
@ -677,16 +505,16 @@ var VerilogPlatform = function(mainElement, options) {
|
|||
}
|
||||
}
|
||||
// replace program ROM, if using the assembler
|
||||
this.reset();
|
||||
if (output.program_rom && output.program_rom_variable) {
|
||||
if (gen[output.program_rom_variable]) {
|
||||
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);
|
||||
else
|
||||
gen[output.program_rom_variable] = output.program_rom;
|
||||
gen[output.program_rom_variable].set(output.program_rom);
|
||||
} else {
|
||||
alert("No program_rom variable found (" + output.program_rom_variable + ")");
|
||||
}
|
||||
this.reset();
|
||||
}
|
||||
// restart audio
|
||||
this.restartAudio();
|
||||
|
@ -720,6 +548,13 @@ var VerilogPlatform = function(mainElement, options) {
|
|||
if (audio) audio.start();
|
||||
}
|
||||
|
||||
isBlocked() {
|
||||
return top && top.finished;
|
||||
}
|
||||
isStopped() {
|
||||
return top && top.stopped;
|
||||
}
|
||||
|
||||
setFrameRate(rateHz) {
|
||||
frameRate = rateHz;
|
||||
var fps = Math.min(60, rateHz*cyclesPerFrame);
|
||||
|
@ -738,12 +573,13 @@ var VerilogPlatform = function(mainElement, options) {
|
|||
getFrameRate() { return frameRate; }
|
||||
|
||||
poweron() {
|
||||
gen._ctor_var_reset();
|
||||
top.reset();
|
||||
this.reset();
|
||||
}
|
||||
reset() {
|
||||
if (!gen) return;
|
||||
gen.__reset();
|
||||
//top.reset(); // to avoid clobbering user inputs
|
||||
doreset();
|
||||
trace_index = 0;
|
||||
if (trace_buffer) trace_buffer.fill(0);
|
||||
if (video) video.setRotate(gen.rotate ? -90 : 0);
|
||||
|
@ -751,7 +587,7 @@ var VerilogPlatform = function(mainElement, options) {
|
|||
if (!this.hasvideo) this.resume(); // TODO?
|
||||
}
|
||||
tick() {
|
||||
gen.tick2();
|
||||
top.tick2();
|
||||
}
|
||||
getToolForFilename(fn) {
|
||||
if (fn.endsWith(".asm")) return "jsasm";
|
||||
|
@ -768,6 +604,7 @@ var VerilogPlatform = function(mainElement, options) {
|
|||
return;
|
||||
}
|
||||
var val = gen[name];
|
||||
/* TODO
|
||||
if (val === undefined && current_output.code) {
|
||||
var re = new RegExp("(\\w+__DOT__(?:_[dcw]_)" + name + ")\\b", "gm");
|
||||
var m = re.exec(current_output.code);
|
||||
|
@ -776,6 +613,7 @@ var VerilogPlatform = function(mainElement, options) {
|
|||
val = gen[name];
|
||||
}
|
||||
}
|
||||
*/
|
||||
if (typeof(val) === 'number') {
|
||||
inspect_obj = gen;
|
||||
inspect_sym = name;
|
||||
|
@ -787,22 +625,24 @@ var VerilogPlatform = function(mainElement, options) {
|
|||
// DEBUGGING
|
||||
|
||||
getDebugTree() {
|
||||
return this.saveState().o;
|
||||
return {
|
||||
//ast: current_output,
|
||||
runtime: top,
|
||||
state: this.saveState().o
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: bind() a function to avoid depot?
|
||||
saveState() {
|
||||
var state = {
|
||||
T:gen.ticks(),
|
||||
// TODO: T:gen.ticks(),
|
||||
o:safe_extend(true, {}, gen)
|
||||
};
|
||||
state.o.TOPp = null;
|
||||
return state;
|
||||
}
|
||||
loadState(state) {
|
||||
gen = safe_extend(true, gen, state.o);
|
||||
gen.setTicks(state.T);
|
||||
gen.TOPp = gen;
|
||||
// TODO: gen.setTicks(state.T);
|
||||
//console.log(gen, state.o);
|
||||
}
|
||||
saveControlsState() {
|
||||
|
@ -823,6 +663,12 @@ var VerilogPlatform = function(mainElement, options) {
|
|||
switches[2] = state.sw2;
|
||||
keycode = state.keycode;
|
||||
}
|
||||
getDownloadFile() {
|
||||
return {
|
||||
extension:".js",
|
||||
blob: new Blob([top.getJSCode()], {type:"text/plain"})
|
||||
};
|
||||
}
|
||||
|
||||
} // end of inner class
|
||||
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) {
|
||||
if (!loaded[modulename]) {
|
||||
console.log('loading', modulename);
|
||||
importScripts('../../gen/'+modulename+".js");
|
||||
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) {
|
||||
if (!loaded[modulename]) {
|
||||
importScripts(PWORKER+"wasm/" + modulename+(debug?"."+debug+".js":".js"));
|
||||
|
@ -1651,8 +1667,8 @@ var jsasm_module_output;
|
|||
var jsasm_module_key;
|
||||
|
||||
function compileJSASM(asmcode:string, platform, options, is_inline) {
|
||||
loadGen("worker/assembler");
|
||||
var asm = new emglobal.exports.Assembler();
|
||||
loadRequire("assembler", "worker/assembler");
|
||||
var asm = new emglobal['Assembler']();
|
||||
var includes = [];
|
||||
asm.loadJSON = (filename:string) => {
|
||||
var jsontext = getWorkFileAsString(filename);
|
||||
|
@ -1691,8 +1707,8 @@ function compileJSASM(asmcode:string, platform, options, is_inline) {
|
|||
// TODO: unify
|
||||
result.output = jsasm_module_output.output;
|
||||
result.output.program_rom = asmout;
|
||||
// cpu_platform__DOT__program_rom
|
||||
result.output.program_rom_variable = jsasm_module_top + "__DOT__program_rom";
|
||||
// TODO: not cpu_platform__DOT__program_rom anymore, make const
|
||||
result.output.program_rom_variable = jsasm_module_top + "$program_rom";
|
||||
result.listings = {};
|
||||
result.listings[options.path] = {lines:result.lines};
|
||||
}
|
||||
|
@ -1720,7 +1736,10 @@ function compileInlineASM(code:string, platform, options, errors, asmlines) {
|
|||
let s = "";
|
||||
var out = asmout.output;
|
||||
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];
|
||||
}
|
||||
if (asmlines) {
|
||||
|
@ -1738,22 +1757,24 @@ function compileInlineASM(code:string, platform, options, errors, asmlines) {
|
|||
|
||||
function compileVerilator(step:BuildStep) {
|
||||
loadNative("verilator_bin");
|
||||
loadGen("worker/verilator2js");
|
||||
loadRequire("hdltypes", "common/hdl/hdltypes");
|
||||
loadRequire("vxmlparser", "common/hdl/vxmlparser");
|
||||
var platform = step.platform || 'verilog';
|
||||
var errors = [];
|
||||
var asmlines = [];
|
||||
gatherFiles(step);
|
||||
// compile verilog if files are stale
|
||||
var outjs = "main.js";
|
||||
if (staleFiles(step, [outjs])) {
|
||||
var xmlPath = "main.xml";
|
||||
if (staleFiles(step, [xmlPath])) {
|
||||
// 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 verilator_mod = emglobal.verilator_bin({
|
||||
instantiateWasm: moduleInstFn('verilator_bin'),
|
||||
noInitialRun:true,
|
||||
noExitRuntime:true,
|
||||
print:print_fn,
|
||||
printErr:match_fn,
|
||||
TOTAL_MEMORY:256*1024*1024,
|
||||
//INITIAL_MEMORY:256*1024*1024,
|
||||
});
|
||||
var code = getWorkFileAsString(step.path);
|
||||
var topmod = detectTopModuleName(code);
|
||||
|
@ -1770,6 +1791,7 @@ function compileVerilator(step:BuildStep) {
|
|||
var args = ["--cc", "-O3"/*abcdefstzsuka*/, "-DEXT_INLINE_ASM", "-DTOPMOD__"+topmod,
|
||||
"-Wall", "-Wno-DECLFILENAME", "-Wno-UNUSED", '--report-unoptflat',
|
||||
"--x-assign", "fast", "--noassert", "--pins-bv", "33",
|
||||
"--xml-output", xmlPath,
|
||||
"--top-module", topmod, step.path]
|
||||
verilator_mod.callMain(args);
|
||||
} catch (e) {
|
||||
|
@ -1783,13 +1805,13 @@ function compileVerilator(step:BuildStep) {
|
|||
if (errors.length) {
|
||||
return {errors:errors};
|
||||
}
|
||||
var xmlParser = new emglobal['VerilogXMLParser']();
|
||||
try {
|
||||
var h_file = FS.readFile("obj_dir/V"+topmod+".h", {encoding:'utf8'});
|
||||
var cpp_file = FS.readFile("obj_dir/V"+topmod+".cpp", {encoding:'utf8'});
|
||||
var rtn = translateVerilatorOutputToJS(h_file, cpp_file);
|
||||
putWorkFile(outjs, rtn.output.code);
|
||||
if (!anyTargetChanged(step, [outjs]))
|
||||
var xmlContent = FS.readFile(xmlPath, {encoding:'utf8'});
|
||||
putWorkFile(xmlPath, xmlContent);
|
||||
if (!anyTargetChanged(step, [xmlPath]))
|
||||
return;
|
||||
xmlParser.parse(xmlContent);
|
||||
} catch(e) {
|
||||
console.log(e);
|
||||
errors.push({line:0,msg:""+e});
|
||||
|
@ -1797,11 +1819,12 @@ function compileVerilator(step:BuildStep) {
|
|||
}
|
||||
//rtn.intermediate = {listing:h_file + cpp_file}; // TODO
|
||||
var listings : CodeListingMap = {};
|
||||
listings[step.prefix + '.lst'] = {lines:[],text:xmlContent};
|
||||
// TODO: what if found in non-top-module?
|
||||
if (asmlines.length)
|
||||
listings[step.path] = {lines:asmlines};
|
||||
return {
|
||||
output: rtn.output,
|
||||
output: xmlParser,
|
||||
errors: errors,
|
||||
listings: listings,
|
||||
};
|
||||
|
@ -2015,7 +2038,7 @@ function setupRequireFunction() {
|
|||
}
|
||||
};
|
||||
emglobal['require'] = (modname:string) => {
|
||||
console.log('require',modname);
|
||||
console.log('require',modname,exports[modname]!=null);
|
||||
return exports[modname];
|
||||
}
|
||||
}
|
||||
|
@ -2755,10 +2778,8 @@ function compileBASIC(step:BuildStep) {
|
|||
var jsonpath = step.path + ".json";
|
||||
gatherFiles(step);
|
||||
if (staleFiles(step, [jsonpath])) {
|
||||
setupRequireFunction();
|
||||
loadGen("common/basic/compiler");
|
||||
loadRequire("compiler", "common/basic/compiler");
|
||||
var parser = new emglobal['BASICParser']();
|
||||
delete emglobal['require'];
|
||||
var code = getWorkFileAsString(step.path);
|
||||
try {
|
||||
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);
|
||||
verilog.vl_finished = verilog.vl_stopped = false;
|
||||
for (var i=0; i<100000 && !(verilog.vl_finished||verilog.vl_stopped); i++) {
|
||||
for (var i=0; i<100000 && !platform.isBlocked(); i++) {
|
||||
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();
|
||||
platform.reset();
|
||||
platform.loadState(state);
|
||||
|
@ -33,7 +34,7 @@ function loadPlatform(msg) {
|
|||
} catch (e) {
|
||||
//platform.printErrorCodeContext(e, msg.output.code);
|
||||
//console.log(msg.intermediate.listing);
|
||||
console.log(msg.output.code);
|
||||
//console.log(msg.output.code);
|
||||
console.log(e);
|
||||
throw e;
|
||||
}
|
||||
|
@ -83,6 +84,7 @@ function compileVerilator(filename, code, callback, nerrors) {
|
|||
|
||||
function testVerilator(filename, disables, nerrors) {
|
||||
it('should translate '+filename, function(done) {
|
||||
console.log(filename);
|
||||
var csource = ab2str(fs.readFileSync(filename));
|
||||
for (var i=0; i<(disables||[]).length; i++)
|
||||
csource = "/* verilator lint_off " + disables[i] + " */\n" + csource;
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2004 by Wilson Snyder.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2004 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2003 by Wilson Snyder.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2003 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2003 by Wilson Snyder.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2003 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
|
@ -13,29 +14,15 @@ module t (/*AUTOARG*/
|
|||
|
||||
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;
|
||||
always @ (/*AS*/m_din) begin
|
||||
a_split_1 = m_din;
|
||||
a_split_2 = m_din;
|
||||
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;
|
||||
always @ (posedge clk) begin
|
||||
d_split_1 <= m_din;
|
||||
|
@ -43,44 +30,27 @@ module t (/*AUTOARG*/
|
|||
d_split_1 <= ~m_din;
|
||||
end
|
||||
|
||||
// Not OK
|
||||
reg [15:0] h_split_1;
|
||||
reg [15:0] h_split_2;
|
||||
always @ (posedge clk) begin
|
||||
$write(" foo %x", m_din);
|
||||
$write(" bar %x\n", m_din);
|
||||
end
|
||||
|
||||
// Not OK
|
||||
reg [15:0] e_split_1, e_split_2;
|
||||
always @ (posedge clk) begin
|
||||
e_split_1 = m_din;
|
||||
e_split_2 = e_split_1;
|
||||
end
|
||||
|
||||
// Not OK
|
||||
reg [15:0] f_split_1, f_split_2;
|
||||
always @ (posedge clk) begin
|
||||
f_split_2 = f_split_1;
|
||||
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;
|
||||
// $write(" cyc = %x m_din = %x\n", cyc, m_din);
|
||||
if (cyc > 2) begin
|
||||
if (m_din == 16'h0) begin
|
||||
h_split_1 <= 16'h0;
|
||||
h_split_2 <= 16'h0;
|
||||
end
|
||||
else begin
|
||||
h_split_1 <= m_din;
|
||||
h_split_2 <= ~m_din;
|
||||
end
|
||||
end
|
||||
else begin
|
||||
h_split_1 <= 16'h0;
|
||||
h_split_2 <= 16'h0;
|
||||
end
|
||||
end
|
||||
|
||||
// (The checker block is an exception, it won't split.)
|
||||
always @ (posedge clk) begin
|
||||
if (cyc!=0) begin
|
||||
cyc<=cyc+1;
|
||||
|
@ -93,39 +63,26 @@ module t (/*AUTOARG*/
|
|||
m_din <= 16'he11e;
|
||||
//$write(" A %x %x\n", a_split_1, a_split_2);
|
||||
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 (!(e_split_1==16'hfeed && e_split_2==16'hfeed)) $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;
|
||||
if (!(h_split_1==16'hfeed && h_split_2==16'h0112)) $stop;
|
||||
end
|
||||
if (cyc==5) begin
|
||||
m_din <= 16'he22e;
|
||||
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 (!(z_split_1==16'h0112 && z_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;
|
||||
if (!(h_split_1==16'hfeed && h_split_2==16'h0112)) $stop;
|
||||
end
|
||||
if (cyc==6) begin
|
||||
m_din <= 16'he33e;
|
||||
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 (!(z_split_1==16'h1ee1 && d_split_2==16'h0112)) $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;
|
||||
if (!(h_split_1==16'he11e && h_split_2==16'h1ee1)) $stop;
|
||||
end
|
||||
if (cyc==7) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
end
|
||||
end // always @ (posedge clk)
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2003-2007 by Wilson Snyder.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2003-2007 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2016 by Andrew Bardsley.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
// bug1071
|
||||
|
||||
|
@ -35,12 +36,16 @@ module t (/*AUTOARG*/
|
|||
array_3[2] = 4'b0100;
|
||||
array_3[3] = 4'b0100;
|
||||
|
||||
// Comparisons only compare elements 0
|
||||
array_1_ne_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_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
|
||||
$write("array_1_ne_array2==%0d\n", array_1_ne_array_2);
|
||||
$write("array_1_ne_array3==%0d\n", array_1_ne_array_3);
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2005 by Wilson Snyder.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2005 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t_case_huge_sub3 (/*AUTOARG*/
|
||||
// Outputs
|
||||
outr,
|
||||
outr,
|
||||
// Inputs
|
||||
clk, index
|
||||
);
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2010 by Wilson Snyder.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2010 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
`ifndef VERILATOR
|
||||
module t;
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2005 by Wilson Snyder.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2005 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t (clk);
|
||||
input clk;
|
||||
|
@ -111,6 +112,7 @@ module clockgate (clk, sen, ena, gatedclk);
|
|||
wire gatedclk = clk & ena_b;
|
||||
|
||||
// verilator lint_off COMBDLY
|
||||
// verilator lint_off LATCH
|
||||
always @(clk or ena or sen) begin
|
||||
if (~clk) begin
|
||||
ena_b <= ena | sen;
|
||||
|
@ -119,6 +121,7 @@ module clockgate (clk, sen, ena, gatedclk);
|
|||
if ((clk^sen)===1'bX) ena_b <= 1'bX;
|
||||
end
|
||||
end
|
||||
// verilator lint_on LATCH
|
||||
// verilator lint_on COMBDLY
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2005 by Wilson Snyder.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2005 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t (clk);
|
||||
input clk;
|
||||
|
@ -111,6 +112,7 @@ module clockgate (clk, sen, ena, gatedclk);
|
|||
wire gatedclk = clk & ena_b;
|
||||
|
||||
// verilator lint_off COMBDLY
|
||||
// verilator lint_off LATCH
|
||||
always @(clk or ena or sen) begin
|
||||
if (~clk) begin
|
||||
ena_b <= ena | sen;
|
||||
|
@ -119,6 +121,7 @@ module clockgate (clk, sen, ena, gatedclk);
|
|||
if ((clk^sen)===1'bX) ena_b <= 1'bX;
|
||||
end
|
||||
end
|
||||
// verilator lint_on LATCH
|
||||
// verilator lint_on COMBDLY
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2003 by Wilson Snyder.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2003 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2003 by Wilson Snyder.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2003 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2003 by Wilson Snyder.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2003 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk, fastclk
|
||||
);
|
||||
|
||||
input clk /*verilator sc_clock*/;
|
||||
input fastclk /*verilator sc_clock*/;
|
||||
input clk;
|
||||
input fastclk;
|
||||
reg reset_l;
|
||||
|
||||
int cyc;
|
||||
// TODO: initial cyc = 0;
|
||||
initial reset_l = 0;
|
||||
always @ (posedge clk) begin
|
||||
if (cyc==0) reset_l <= 1'b1;
|
||||
|
@ -33,8 +33,8 @@ module t_clk (/*AUTOARG*/
|
|||
clk, fastclk, reset_l
|
||||
);
|
||||
|
||||
input clk /*verilator sc_clock*/;
|
||||
input fastclk /*verilator sc_clock*/;
|
||||
input clk;
|
||||
input fastclk;
|
||||
input reset_l;
|
||||
|
||||
// surefire lint_off STMINI
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2008 by Wilson Snyder.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2008 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2003 by Wilson Snyder.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2003 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2005 by Wilson Snyder.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2005 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
|
@ -52,6 +53,7 @@ module t (/*AUTOARG*/
|
|||
end
|
||||
|
||||
// verilator lint_off COMBDLY
|
||||
// verilator lint_off LATCH
|
||||
always @ (`posstyle clk /*AS*/ or data) begin
|
||||
if (clk) begin
|
||||
data_a <= data + 8'd1;
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2010 by Wilson Snyder.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2010 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
//
|
||||
// --------------------------------------------------------
|
||||
// Bug Description:
|
||||
|
@ -110,11 +111,13 @@ module llq (clk, d, q);
|
|||
reg [WIDTH-1:0] qr;
|
||||
|
||||
/* verilator lint_off COMBDLY */
|
||||
/* verilator lint_off LATCH */
|
||||
|
||||
always @(clk or d)
|
||||
if (clk == 1'b0)
|
||||
qr <= d;
|
||||
|
||||
/* verilator lint_on LATCH */
|
||||
/* verilator lint_on COMBDLY */
|
||||
|
||||
assign q = qr;
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2005 by Wilson Snyder.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2005 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2008 by Wilson Snyder.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2008 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
// 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*/
|
||||
// Inputs
|
||||
|
@ -53,7 +56,7 @@ module t (/*AUTOARG*/
|
|||
|
||||
endmodule
|
||||
|
||||
module test_top (/*AUTOARG*/
|
||||
module Test (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk, in
|
||||
);
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2003 by Wilson Snyder.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2003 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
reg _ranit;
|
||||
reg _ranit;
|
||||
|
||||
reg [2:0] xor3;
|
||||
reg [1:0] xor2;
|
||||
|
@ -28,8 +29,8 @@ module t (/*AUTOARG*/
|
|||
|
||||
wire [4:0] cond_check = (( xor2 == 2'b11) ? 5'h1
|
||||
: (xor2 == 2'b00) ? 5'h2
|
||||
: (xor2 == 2'b01) ? 5'h3
|
||||
: 5'h4);
|
||||
: (xor2 == 2'b01) ? 5'h3
|
||||
: 5'h4);
|
||||
|
||||
wire ctrue = 1'b1 ? 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
|
||||
if (!_ranit) begin
|
||||
_ranit <= 1;
|
||||
_ranit <= 1;
|
||||
|
||||
if (rep6 != 6'b111111) $stop;
|
||||
if (!one) $stop;
|
||||
if (~one) $stop;
|
||||
if (rep6 != 6'b111111) $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;
|
||||
// verilator lint_off WIDTH
|
||||
if (( 8'h10 + 1'b0 ? 8'he : 8'hf) !== 8'he) $stop; // + is higher than ?
|
||||
// verilator lint_on WIDTH
|
||||
if (( 1'b0 ? 3'h3 : 1'b0 ? 3'h2 : 1'b1 ? 3'h1 : 3'h0) !== 3'h1) $stop;
|
||||
// verilator lint_off WIDTH
|
||||
if (( 8'h10 + 1'b0 ? 8'he : 8'hf) !== 8'he) $stop; // + is higher than ?
|
||||
// verilator lint_on WIDTH
|
||||
|
||||
// surefire lint_off SEQASS
|
||||
xor1 = 1'b1;
|
||||
xor2 = 2'b11;
|
||||
xor3 = 3'b111;
|
||||
// verilator lint_off WIDTH
|
||||
if (1'b1 & | (!xor3)) $stop;
|
||||
// verilator lint_on WIDTH
|
||||
if ({1{xor1}} != 1'b1) $stop;
|
||||
if ({4{xor1}} != 4'b1111) $stop;
|
||||
if (!(~xor1) !== ~(!xor1)) $stop;
|
||||
if ((^xor1) !== 1'b1) $stop;
|
||||
if ((^xor2) !== 1'b0) $stop;
|
||||
if ((^xor3) !== 1'b1) $stop;
|
||||
if (~(^xor2) !== 1'b1) $stop;
|
||||
if (~(^xor3) !== 1'b0) $stop;
|
||||
if ((^~xor1) !== 1'b0) $stop;
|
||||
if ((^~xor2) !== 1'b1) $stop;
|
||||
if ((^~xor3) !== 1'b0) $stop;
|
||||
if ((~^xor1) !== 1'b0) $stop;
|
||||
if ((~^xor2) !== 1'b1) $stop;
|
||||
if ((~^xor3) !== 1'b0) $stop;
|
||||
xor1 = 1'b0;
|
||||
xor2 = 2'b10;
|
||||
xor3 = 3'b101;
|
||||
if ((^xor1) !== 1'b0) $stop;
|
||||
if ((^xor2) !== 1'b1) $stop;
|
||||
if ((^xor3) !== 1'b0) $stop;
|
||||
if (~(^xor2) !== 1'b0) $stop;
|
||||
if (~(^xor3) !== 1'b1) $stop;
|
||||
if ((^~xor1) !== 1'b1) $stop;
|
||||
if ((^~xor2) !== 1'b0) $stop;
|
||||
if ((^~xor3) !== 1'b1) $stop;
|
||||
if ((~^xor1) !== 1'b1) $stop;
|
||||
if ((~^xor2) !== 1'b0) $stop;
|
||||
if ((~^xor3) !== 1'b1) $stop;
|
||||
// surefire lint_off SEQASS
|
||||
xor1 = 1'b1;
|
||||
xor2 = 2'b11;
|
||||
xor3 = 3'b111;
|
||||
// verilator lint_off WIDTH
|
||||
if (1'b1 & | (!xor3)) $stop;
|
||||
// verilator lint_on WIDTH
|
||||
if ({1{xor1}} != 1'b1) $stop;
|
||||
if ({4{xor1}} != 4'b1111) $stop;
|
||||
if (!(~xor1) !== ~(!xor1)) $stop;
|
||||
if ((^xor1) !== 1'b1) $stop;
|
||||
if ((^xor2) !== 1'b0) $stop;
|
||||
if ((^xor3) !== 1'b1) $stop;
|
||||
if (~(^xor2) !== 1'b1) $stop;
|
||||
if (~(^xor3) !== 1'b0) $stop;
|
||||
if ((^~xor1) !== 1'b0) $stop;
|
||||
if ((^~xor2) !== 1'b1) $stop;
|
||||
if ((^~xor3) !== 1'b0) $stop;
|
||||
if ((~^xor1) !== 1'b0) $stop;
|
||||
if ((~^xor2) !== 1'b1) $stop;
|
||||
if ((~^xor3) !== 1'b0) $stop;
|
||||
xor1 = 1'b0;
|
||||
xor2 = 2'b10;
|
||||
xor3 = 3'b101;
|
||||
if ((^xor1) !== 1'b0) $stop;
|
||||
if ((^xor2) !== 1'b1) $stop;
|
||||
if ((^xor3) !== 1'b0) $stop;
|
||||
if (~(^xor2) !== 1'b0) $stop;
|
||||
if (~(^xor3) !== 1'b1) $stop;
|
||||
if ((^~xor1) !== 1'b1) $stop;
|
||||
if ((^~xor2) !== 1'b0) $stop;
|
||||
if ((^~xor3) !== 1'b1) $stop;
|
||||
if ((~^xor1) !== 1'b1) $stop;
|
||||
if ((~^xor2) !== 1'b0) $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;
|
||||
mc = 10'h5;
|
||||
mc = 10'h5;
|
||||
|
||||
mr1 = ma * mb; // Lint ASWESB: Assignment width mismatch
|
||||
mr2 = 30'h5 * mc; // Lint ASWESB: Assignment width mismatch
|
||||
if (mr1 !== 5'd12) $stop;
|
||||
if (mr2 !== 31'd25) $stop; // Lint CWECBB: Comparison width mismatch
|
||||
mr1 = ma * mb; // Lint ASWESB: Assignment width mismatch
|
||||
mr2 = 30'h5 * mc; // Lint ASWESB: Assignment width mismatch
|
||||
if (mr1 !== 5'd12) $stop;
|
||||
if (mr2 !== 31'd25) $stop; // Lint CWECBB: Comparison width mismatch
|
||||
|
||||
sh1 = 68'hf_def1_9abc_5678_1234;
|
||||
shq = sh1 >> 16;
|
||||
if (shq !== 68'hf_def1_9abc_5678) $stop;
|
||||
shq = sh1 << 16; // Lint ASWESB: Assignment width mismatch
|
||||
if (shq !== 68'h1_9abc_5678_1234_0000) $stop;
|
||||
sh1 = 68'hf_def1_9abc_5678_1234;
|
||||
shq = sh1 >> 16;
|
||||
if (shq !== 68'hf_def1_9abc_5678) $stop;
|
||||
shq = sh1 << 16; // Lint ASWESB: Assignment width mismatch
|
||||
if (shq !== 68'h1_9abc_5678_1234_0000) $stop;
|
||||
|
||||
// surefire lint_on SEQASS
|
||||
// surefire lint_on SEQASS
|
||||
|
||||
// Test display extraction widthing
|
||||
$display("[%0t] %x %x %x(%d)", $time, shq[2:0], shq[2:0]<<2, xor3[2:0], xor3[2:0]);
|
||||
// Test display extraction widthing
|
||||
$display("[%0t] %x %x %x(%d)", $time, shq[2:0], shq[2:0]<<2, xor3[2:0], xor3[2:0]);
|
||||
|
||||
// bug736
|
||||
//verilator lint_off WIDTH
|
||||
if ((~| 4'b0000) != 4'b0001) $stop;
|
||||
if ((~| 4'b0010) != 4'b0000) $stop;
|
||||
if ((~& 4'b1111) != 4'b0000) $stop;
|
||||
if ((~& 4'b1101) != 4'b0001) $stop;
|
||||
//verilator lint_on WIDTH
|
||||
// bug736
|
||||
//verilator lint_off WIDTH
|
||||
if ((~| 4'b0000) != 4'b0001) $stop;
|
||||
if ((~| 4'b0010) != 4'b0000) $stop;
|
||||
if ((~& 4'b1111) != 4'b0000) $stop;
|
||||
if ((~& 4'b1101) != 4'b0001) $stop;
|
||||
//verilator lint_on WIDTH
|
||||
|
||||
// bug764
|
||||
//verilator lint_off WIDTH
|
||||
// X does not sign extend
|
||||
if (bug764_p11 !== 4'b000x) $stop;
|
||||
if (~& bug764_p11 !== 1'b1) $stop;
|
||||
//verilator lint_on WIDTH
|
||||
// However IEEE says for constants in 2012 5.7.1 that smaller-sizes do extend
|
||||
if (4'bx !== 4'bxxxx) $stop;
|
||||
if (4'bz !== 4'bzzzz) $stop;
|
||||
if (4'b1 !== 4'b0001) $stop;
|
||||
// bug764
|
||||
//verilator lint_off WIDTH
|
||||
// X does not sign extend
|
||||
if (bug764_p11 !== 4'b000x) $stop;
|
||||
if (~& bug764_p11 !== 1'b1) $stop;
|
||||
//verilator lint_on WIDTH
|
||||
// However IEEE 2017 5.7.1 says for constants that smaller-sizes do extend
|
||||
if (4'bx !== 4'bxxxx) $stop;
|
||||
if (4'bz !== 4'bzzzz) $stop;
|
||||
if (4'b1 !== 4'b0001) $stop;
|
||||
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
if ((0 -> 0) != 1'b1) $stop;
|
||||
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
|
||||
|
||||
|
@ -145,13 +190,13 @@ module t (/*AUTOARG*/
|
|||
reg [7:0] m_corr_data_b8;
|
||||
initial begin
|
||||
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_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[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[0], 3'b000 //m_corr_data_w0 [3: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[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[03:01], 1'b0, //m_corr_data_w0 [7:4]
|
||||
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_w1 != 32'h1a2b3c4c) $stop;
|
||||
if (m_corr_data_b8 != 8'h12) $stop;
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2003 by Wilson Snyder.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2003 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2004 by Wilson Snyder.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2004 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
|
@ -14,12 +15,20 @@ module t (/*AUTOARG*/
|
|||
reg [60:0] divisor;
|
||||
reg [60:0] qq;
|
||||
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] rqs;
|
||||
|
||||
always @* begin
|
||||
qq = 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);
|
||||
rqs = $signed(a[60:0]) % $signed(divisor);
|
||||
end
|
||||
|
@ -34,6 +43,10 @@ module t (/*AUTOARG*/
|
|||
divisor <= 61'h12371;
|
||||
a[60] <= 1'b0; divisor[60] <= 1'b0; // Unsigned
|
||||
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
|
||||
a <= 256'h0e17c88f3d5fe51a982646c8e2bd68c3e236ddfddddbdad20a48e039c9f395b8;
|
||||
divisor <= 61'h1238123771;
|
||||
|
@ -42,6 +55,8 @@ module t (/*AUTOARG*/
|
|||
if (rq!==61'h00000000000090ec) $stop;
|
||||
if (qqs!==61'h00000403ad81c0da) $stop;
|
||||
if (rqs!==61'h00000000000090ec) $stop;
|
||||
if (qq4 != 61'h01247cf6851f9fc9) $stop;
|
||||
if (rq4 != 61'h0000000000000002) $stop;
|
||||
end
|
||||
if (cyc==3) begin
|
||||
a <= 256'h0e17c88f00d5fe51a982646c8002bd68c3e236ddfd00ddbdad20a48e00f395b8;
|
||||
|
@ -51,6 +66,8 @@ module t (/*AUTOARG*/
|
|||
if (rq!==61'h0000000334becc6a) $stop;
|
||||
if (qqs!==61'h000000000090832e) $stop;
|
||||
if (rqs!==61'h0000000334becc6a) $stop;
|
||||
if (qq4 != 61'h0292380e727ce56e) $stop;
|
||||
if (rq4 != 61'h0000000000000000) $stop;
|
||||
end
|
||||
if (cyc==4) begin
|
||||
a[60] <= 1'b0; divisor[60] <= 1'b1; // Signed
|
||||
|
@ -58,6 +75,8 @@ module t (/*AUTOARG*/
|
|||
if (rq!==61'h0000000000000c40) $stop;
|
||||
if (qqs!==61'h1fffcf5187c76510) $stop;
|
||||
if (rqs!==61'h1ffffffffffffd08) $stop;
|
||||
if (qq4 != 61'h07482923803ce56e) $stop;
|
||||
if (rq4 != 61'h0000000000000000) $stop;
|
||||
end
|
||||
if (cyc==5) begin
|
||||
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 [31:0] d2;
|
||||
output [31:0] m2;
|
||||
output [63:0] d3;
|
||||
output [63:0] m3;
|
||||
// bug775
|
||||
// verilator lint_off WIDTH
|
||||
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
|
||||
b = 32'hffffffff;
|
||||
b3 = 64'hffffffff_ffffffff;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2004 by Wilson Snyder.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2004 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2003 by Wilson Snyder.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2003 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2003 by Wilson Snyder.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2003 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2015 by Wilson Snyder.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2015 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2003 by Wilson Snyder.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2003 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t_order_a (/*AUTOARG*/
|
||||
// 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
|
||||
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*/
|
||||
// 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
|
||||
|
||||
// surefire lint_off ASWEBB
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2003 by Wilson Snyder.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2003 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t_order_b (/*AUTOARG*/
|
||||
// Outputs
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2003 by Wilson Snyder.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2003 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
|
@ -10,14 +11,16 @@ module t (/*AUTOARG*/
|
|||
input clk;
|
||||
|
||||
// verilator lint_off COMBDLY
|
||||
// verilator lint_off LATCH
|
||||
// verilator lint_off UNOPT
|
||||
// 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;
|
||||
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;
|
||||
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);
|
||||
cyc <= cyc + 8'd1;
|
||||
case (cyc)
|
||||
8'd00: begin
|
||||
c1_start <= 1'b0;
|
||||
end
|
||||
8'd01: begin
|
||||
c1_start <= 1'b1;
|
||||
end
|
||||
default: ;
|
||||
8'd00: begin
|
||||
c1_start <= 1'b0;
|
||||
end
|
||||
8'd01: begin
|
||||
c1_start <= 1'b1;
|
||||
end
|
||||
default: ;
|
||||
endcase
|
||||
case (cyc)
|
||||
8'd02: begin
|
||||
if (c1_count!=32'h3) $stop;
|
||||
if (s2_count!=32'h3) $stop;
|
||||
if (c3_count!=32'h6) $stop;
|
||||
end
|
||||
8'd03: begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
default: ;
|
||||
8'd02: begin
|
||||
// On Verilator, we expect these comparisons to match exactly,
|
||||
// confirming that our settle loop repeated the exact number of
|
||||
// iterations we expect. No '$stop' should be called here, and we
|
||||
// should reach the normal '$finish' below on the next cycle.
|
||||
if (c1_count!=32'h3) $stop;
|
||||
if (s2_count!=32'h3) $stop;
|
||||
if (c3_count!=32'h5) $stop;
|
||||
end
|
||||
8'd03: begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
default: ;
|
||||
endcase
|
||||
end
|
||||
endmodule
|
||||
|
@ -62,12 +69,10 @@ module comb_loop (/*AUTOARG*/
|
|||
input start;
|
||||
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
|
||||
if (start) begin
|
||||
runner = 3;
|
||||
end
|
||||
always @ (posedge start) begin
|
||||
runner = 3;
|
||||
end
|
||||
|
||||
always @ (/*AS*/runner) begin
|
||||
|
@ -76,9 +81,9 @@ module comb_loop (/*AUTOARG*/
|
|||
|
||||
always @ (/*AS*/runnerm1) begin
|
||||
if (runner > 0) begin
|
||||
count = count + 1;
|
||||
runner = runnerm1;
|
||||
$write ("%m count=%d runner =%x\n",count, runnerm1);
|
||||
count = count + 1;
|
||||
runner = runnerm1;
|
||||
$write ("%m count=%d runner =%x\n",count, runnerm1);
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -93,12 +98,10 @@ module seq_loop (/*AUTOARG*/
|
|||
input start;
|
||||
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
|
||||
if (start) begin
|
||||
runner <= 3;
|
||||
end
|
||||
always @ (posedge start) begin
|
||||
runner <= 3;
|
||||
end
|
||||
|
||||
always @ (/*AS*/runner) begin
|
||||
|
@ -107,9 +110,9 @@ module seq_loop (/*AUTOARG*/
|
|||
|
||||
always @ (/*AS*/runnerm1) begin
|
||||
if (runner > 0) begin
|
||||
count = count + 1;
|
||||
runner <= runnerm1;
|
||||
$write ("%m count=%d runner<=%x\n",count, runnerm1);
|
||||
count = count + 1;
|
||||
runner <= runnerm1;
|
||||
$write ("%m count=%d runner<=%x\n",count, runnerm1);
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2003 by Wilson Snyder.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2003 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
|
@ -11,6 +12,7 @@ module t (/*AUTOARG*/
|
|||
|
||||
// verilator lint_off BLKANDNBLK
|
||||
// verilator lint_off COMBDLY
|
||||
// verilator lint_off LATCH
|
||||
// verilator lint_off UNOPT
|
||||
// verilator lint_off UNOPTFLAT
|
||||
// verilator lint_off MULTIDRIVEN
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2003 by Wilson Snyder.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2003 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
|
@ -10,6 +11,7 @@ module t (/*AUTOARG*/
|
|||
input clk;
|
||||
integer cyc; initial cyc=1;
|
||||
|
||||
// verilator lint_off LATCH
|
||||
// verilator lint_off UNOPT
|
||||
// verilator lint_off UNOPTFLAT
|
||||
reg [31:0] runner; initial runner = 5;
|
||||
|
@ -38,7 +40,7 @@ module t (/*AUTOARG*/
|
|||
end
|
||||
|
||||
// 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
|
||||
runnerm1 = runner - 32'd1;
|
||||
end
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2005 by Wilson Snyder.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2005 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
|
@ -10,6 +11,7 @@ module t (/*AUTOARG*/
|
|||
input clk;
|
||||
integer cyc; initial cyc=1;
|
||||
|
||||
// verilator lint_off LATCH
|
||||
// verilator lint_off UNOPT
|
||||
// verilator lint_off UNOPTFLAT
|
||||
// verilator lint_off MULTIDRIVEN
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2003 by Wilson Snyder.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2003 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2012 by Jeremy Bennett.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
|
@ -15,7 +16,7 @@ module t (/*AUTOARG*/
|
|||
);
|
||||
input clk;
|
||||
|
||||
reg ready;
|
||||
reg ready;
|
||||
|
||||
initial begin
|
||||
ready = 1'b0;
|
||||
|
@ -23,8 +24,8 @@ module t (/*AUTOARG*/
|
|||
|
||||
always @(posedge ready) begin
|
||||
if ((ready === 1'b1)) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2005 by Wilson Snyder.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2005 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
|
|
|
@ -2,11 +2,12 @@
|
|||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2013 by Ted Campbell.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
//With MULTI_CLK defined shows bug, without it is hidden
|
||||
`define MULTI_CLK
|
||||
|
||||
//bug634
|
||||
//bug634
|
||||
|
||||
module t (
|
||||
input i_clk_wr,
|
||||
|
@ -162,13 +163,13 @@ module FooMemImpl(
|
|||
input a_wen,
|
||||
input [7:0] a_addr,
|
||||
input [7:0] a_wdata,
|
||||
output [7:0] a_rdata,
|
||||
output reg [7:0] a_rdata,
|
||||
|
||||
input b_clk,
|
||||
input b_wen,
|
||||
input [7:0] b_addr,
|
||||
input [7:0] b_wdata,
|
||||
output [7:0] b_rdata
|
||||
output reg [7:0] b_rdata
|
||||
);
|
||||
|
||||
/* verilator lint_off MULTIDRIVEN */
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2014 by Wilson Snyder.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2014 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
//bug 762
|
||||
module t(a0, y);
|
||||
|
@ -12,5 +13,5 @@ module t(a0, y);
|
|||
assign y[30] = 0;
|
||||
// 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 };
|
||||
|
||||
|
||||
endmodule
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2005 by Wilson Snyder.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2005 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Outputs
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2012 by Wilson Snyder.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2012 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
|
@ -36,8 +37,8 @@ module updown #(parameter UP=0)
|
|||
endgenerate
|
||||
endmodule
|
||||
|
||||
module t_up (inout tri1 z);
|
||||
module t_up (inout tri1 z);
|
||||
endmodule
|
||||
|
||||
module t_down (inout tri0 z);
|
||||
module t_down (inout tri0 z);
|
||||
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 file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2012 by Jeremy Bennett.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
// 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
|
||||
clk
|
||||
);
|
||||
input clk;
|
||||
|
||||
tri pad_io_h;
|
||||
tri pad_io_l;
|
||||
tri pad_io_h;
|
||||
tri pad_io_l;
|
||||
|
||||
sub sub (.*);
|
||||
|
||||
|
@ -45,8 +48,7 @@ module sub (/*AUTOARG*/
|
|||
if (DIFFERENTIAL)
|
||||
assign pad_io_l = sig_l_r;
|
||||
end
|
||||
end
|
||||
end
|
||||
endgenerate
|
||||
|
||||
endmodule
|
||||
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// 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);
|
||||
io io1(.A(A), .OE( SEL), .Z(Z), .Y(Y1));
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2008 by Wilson Snyder.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2008 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
|
@ -22,7 +23,6 @@ module t (/*AUTOARG*/
|
|||
ChildA childa ( .A(a), .B(b), .en(en), .Y(y),.Yfix(y_fixed) );
|
||||
|
||||
initial in=0;
|
||||
initial en=0;
|
||||
|
||||
// Test loop
|
||||
always @ (posedge clk) begin
|
||||
|
@ -51,7 +51,7 @@ module t (/*AUTOARG*/
|
|||
end
|
||||
|
||||
if (in==3) begin
|
||||
$write("*-* All Finished *-*\n");
|
||||
$write("*-* All Finished *-*\n");
|
||||
$finish;
|
||||
end
|
||||
end
|
||||
|
@ -74,4 +74,3 @@ endmodule
|
|||
module ChildB(input A, output Y);
|
||||
assign Y = A;
|
||||
endmodule
|
||||
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// 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);
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2012 by Jeremy Bennett.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
|
@ -13,7 +14,7 @@ module t (/*AUTOARG*/
|
|||
|
||||
wire [1:0] b;
|
||||
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;
|
||||
|
||||
// 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
|
||||
//
|
||||
// This file ONLY is placed into the Public Domain, for any use,
|
||||
// without warranty, 2012 by Wilson Snyder.
|
||||
// This file ONLY is placed under the Creative Commons Public Domain, for
|
||||
// any use, without warranty, 2012 by Wilson Snyder.
|
||||
// SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
module t (/*AUTOARG*/
|
||||
// Inputs
|
||||
|
|
|
@ -1,5 +1,8 @@
|
|||
// DESCRIPTION: Verilator: Verilog Test module
|
||||
//
|
||||
// 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);
|
||||
input clk;
|
||||
|
@ -208,4 +211,3 @@ endmodule
|
|||
// end
|
||||
// end
|
||||
//endmodule
|
||||
|
||||
|
|
|
@ -1,18 +1,21 @@
|
|||
|
||||
var _require = require;
|
||||
var assert = require('assert');
|
||||
var fs = require('fs');
|
||||
var vm = require('vm');
|
||||
|
||||
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.exports = {};
|
||||
global.self = global;
|
||||
global.location = {href:'.'};
|
||||
global.require = (modname) => {
|
||||
console.log("REQUIRE",modname);
|
||||
//console.log("REQUIRE",modname);
|
||||
if (modname == 'path')
|
||||
return require(modname);
|
||||
return _require(modname);
|
||||
};
|
||||
|
||||
global.btoa = require('btoa');
|
||||
|
|
Loading…
Reference in New Issue