(WIP) new hdl package, verilator 4 (emscripten 2.0.6), hdlwasm

This commit is contained in:
Steven Hugg 2021-06-28 15:36:47 -05:00
parent 7b492622c2
commit 9bb79c318f
81 changed files with 8753 additions and 626 deletions

14
package-lock.json generated
View File

@ -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",

View File

@ -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",

View File

@ -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)

View File

@ -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;

View File

@ -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;

View File

@ -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>
{

View File

@ -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;

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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"]},

View File

@ -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)

View File

@ -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

View File

@ -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;

View File

@ -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 #

View File

@ -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

View File

@ -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(

View File

@ -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'

0
presets/verilog/tile.tga Executable file → Normal file
View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -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 {

View File

@ -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"); }
}
}
}
*/

196
src/common/hdl/hdltypes.ts Normal file
View File

@ -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[];

485
src/common/hdl/hdlwasm.ts Normal file
View File

@ -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));
}
}

View File

@ -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(/&apos;/g, "'")
.replace(/&quot;/g, '"')
.replace(/&gt;/g, '>')
.replace(/&lt;/g, '<')
.replace(/&amp;/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();
}
}

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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.

View File

@ -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);

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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
);

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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
);

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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));

View File

@ -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

View File

@ -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);

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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');