mirror of
https://github.com/sehugg/8bitworkshop.git
synced 2025-02-26 22:29:56 +00:00
verilog: fuzzhdl
This commit is contained in:
parent
ac55082863
commit
1ab0d290f8
@ -63,6 +63,7 @@
|
||||
"test-web": "nightwatch -e chrome test/web",
|
||||
"start": "electron .",
|
||||
"fuzzbasic": "jsfuzz gen/common/basic/fuzz.js ~/basic/corpus/ --versifier false",
|
||||
"fuzzhdl": "jsfuzz -r binaryen gen/common/hdl/fuzz.js ~/verilator/corpus/ --versifier false",
|
||||
"machine": "node gen/tools/runmachine.js",
|
||||
"mkdoc": "typedoc --out web/jsdoc src/common/"
|
||||
},
|
||||
|
35
src/common/hdl/fuzz.ts
Normal file
35
src/common/hdl/fuzz.ts
Normal file
@ -0,0 +1,35 @@
|
||||
|
||||
//import binaryen = require('binaryen');
|
||||
import { HDLModuleJS } from "./hdlruntime";
|
||||
import { HDLModuleWASM } from "./hdlwasm";
|
||||
import { CompileError, VerilogXMLParser } from "./vxmlparser";
|
||||
|
||||
export function fuzz(buf) {
|
||||
var parser = new VerilogXMLParser();
|
||||
var str = buf.toString();
|
||||
try {
|
||||
parser.parse(str);
|
||||
} catch (e) {
|
||||
if (e instanceof CompileError) return;
|
||||
throw e;
|
||||
}
|
||||
/*
|
||||
if (0) {
|
||||
var wmod = new HDLModuleWASM(parser.modules['TOP'], parser.modules['@CONST-POOL@']);
|
||||
wmod.traceBufferSize = 0x8000;
|
||||
wmod.maxMemoryMB = 0.25;
|
||||
wmod.init().then(() => {
|
||||
wmod.powercycle();
|
||||
wmod.tick2(10000);
|
||||
wmod.dispose();
|
||||
})
|
||||
}
|
||||
*/
|
||||
if (1) {
|
||||
var jmod = new HDLModuleJS(parser.modules['TOP'], parser.modules['@CONST-POOL@']);
|
||||
jmod.init();
|
||||
jmod.powercycle();
|
||||
jmod.tick2(10000);
|
||||
jmod.dispose();
|
||||
}
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
|
||||
import { byteArrayToString, safe_extend } from "../util";
|
||||
import { HDLBinop, HDLBlock, HDLConstant, HDLDataType, HDLExpr, HDLExtendop, HDLFuncCall, HDLModuleDef, HDLModuleRunner, HDLTriop, HDLUnop, HDLValue, HDLVariableDef, HDLVarRef, isArrayItem, isArrayType, isBinop, isBlock, isConstExpr, isFuncCall, isLogicType, isTriop, isUnop, isVarDecl, isVarRef, isWhileop } from "./hdltypes";
|
||||
import { HDLBinop, HDLBlock, HDLConstant, HDLDataType, HDLExpr, HDLExtendop, HDLFuncCall, HDLModuleDef, HDLModuleRunner, HDLSourceLocation, HDLTriop, HDLUnop, HDLValue, HDLVariableDef, HDLVarRef, isArrayItem, isArrayType, isBigConstExpr, isBinop, isBlock, isConstExpr, isFuncCall, isLogicType, isTriop, isUnop, isVarDecl, isVarRef, isWhileop } from "./hdltypes";
|
||||
|
||||
interface VerilatorUnit {
|
||||
_ctor_var_reset(state) : void;
|
||||
@ -10,6 +10,18 @@ interface VerilatorUnit {
|
||||
_change_request(state) : boolean;
|
||||
}
|
||||
|
||||
export class HDLError extends Error {
|
||||
obj: any;
|
||||
$loc: HDLSourceLocation;
|
||||
constructor(obj: any, msg: string) {
|
||||
super(msg);
|
||||
Object.setPrototypeOf(this, HDLError.prototype);
|
||||
this.obj = obj;
|
||||
if (obj && obj.$loc) this.$loc = obj.$loc;
|
||||
if (obj) console.log(obj);
|
||||
}
|
||||
}
|
||||
|
||||
export class HDLModuleJS implements HDLModuleRunner {
|
||||
|
||||
mod: HDLModuleDef;
|
||||
@ -114,7 +126,7 @@ export class HDLModuleJS implements HDLModuleRunner {
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new Error(`model did not converge on reset()`)
|
||||
throw new HDLError(null, `model did not converge on reset()`)
|
||||
}
|
||||
|
||||
eval() {
|
||||
@ -139,7 +151,7 @@ export class HDLModuleJS implements HDLModuleRunner {
|
||||
return;
|
||||
}
|
||||
}
|
||||
throw new Error(`model did not converge on eval()`)
|
||||
throw new HDLError(null, `model did not converge on eval()`)
|
||||
}
|
||||
|
||||
tick2(iters: number) {
|
||||
@ -180,20 +192,20 @@ export class HDLModuleJS implements HDLModuleRunner {
|
||||
if (isArrayItem(e) && isConstExpr(e.expr)) {
|
||||
arr[e.index] = e.expr.cvalue;
|
||||
} else {
|
||||
throw new Error(`non-const expr in initarray`);
|
||||
throw new HDLError(dt, `non-const expr in initarray`);
|
||||
}
|
||||
}
|
||||
}
|
||||
return arr;
|
||||
}
|
||||
throw new Error(`no default value for var type: ${vardef.name}`);
|
||||
throw new HDLError(dt, `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`);
|
||||
throw new HDLError(expr, `no const value for expr`);
|
||||
}
|
||||
}
|
||||
|
||||
@ -220,7 +232,7 @@ export class HDLModuleJS implements HDLModuleRunner {
|
||||
s += ` = ${this.constValue(e)}`; // TODO?
|
||||
} else if (e.initValue != null) {
|
||||
// TODO?
|
||||
throw new Error(`can't init array here`);
|
||||
throw new HDLError(e, `can't init array here`);
|
||||
} else if (isLogicType(e.dtype) && e.dtype.left > 31) {
|
||||
// TODO: hack for big ints ($readmem)
|
||||
s += ` = []`;
|
||||
@ -228,6 +240,8 @@ export class HDLModuleJS implements HDLModuleRunner {
|
||||
return s;
|
||||
} else if (isConstExpr(e)) {
|
||||
return `0x${e.cvalue.toString(16)}`;
|
||||
} else if (isBigConstExpr(e)) {
|
||||
return e.bigvalue.toString(); // TODO?
|
||||
} else if (isTriop(e)) {
|
||||
switch (e.op) {
|
||||
case 'if':
|
||||
@ -239,8 +253,7 @@ export class HDLModuleJS implements HDLModuleRunner {
|
||||
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}`);
|
||||
throw new HDLError(e, `unknown triop ${e.op}`);
|
||||
}
|
||||
} else if (isBinop(e)) {
|
||||
switch (e.op) {
|
||||
@ -260,8 +273,7 @@ export class HDLModuleJS implements HDLModuleRunner {
|
||||
default:
|
||||
var jsop = OP2JS[e.op];
|
||||
if (!jsop) {
|
||||
console.log(e);
|
||||
throw Error(`unknown binop ${e.op}`)
|
||||
throw new HDLError(e, `unknown binop ${e.op}`)
|
||||
}
|
||||
if (jsop.startsWith('?')) {
|
||||
jsop = jsop.substr(1);
|
||||
@ -287,9 +299,10 @@ export class HDLModuleJS implements HDLModuleRunner {
|
||||
case 'extends':
|
||||
let shift = 32 - (e as HDLExtendop).widthminv;
|
||||
return `((${this.expr2js(e.left)} << ${shift}) >> ${shift})`;
|
||||
case 'redxor':
|
||||
return `this.$$${e.op}(${this.expr2js(e.left)})`;
|
||||
default:
|
||||
console.log(e);
|
||||
throw Error(`unknown unop ${e.op}`);
|
||||
throw new HDLError(e, `unknown unop ${e.op}`);
|
||||
}
|
||||
} else if (isBlock(e)) {
|
||||
// TODO: { e } ?
|
||||
@ -330,11 +343,11 @@ export class HDLModuleJS implements HDLModuleRunner {
|
||||
return `${this.expr2js(e)}.forEach((a) => a.fill(0))`
|
||||
} else {
|
||||
// TODO: 3d arrays?
|
||||
throw Error(`unsupported data type for reset: ${JSON.stringify(e.dtype)}`);
|
||||
throw new HDLError(e, `unsupported data type for reset: ${JSON.stringify(e.dtype)}`);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw Error(`can only reset var refs`);
|
||||
throw new HDLError(e, `can only reset var refs`);
|
||||
}
|
||||
}
|
||||
|
||||
@ -379,16 +392,27 @@ export class HDLModuleJS implements HDLModuleRunner {
|
||||
var strfn = byteArrayToString(barr); // convert to string
|
||||
// parse hex/binary file
|
||||
var strdata = this.getFileData(strfn) as string;
|
||||
if (strdata == null) throw Error("Could not $readmem '" + strfn + "'");
|
||||
if (strdata == null) throw new HDLError(null, "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);
|
||||
if (memp === null) throw new HDLError(null, "No destination array to $readmem " + strfn);
|
||||
if (memp.length < data.length) throw new HDLError(null, "Destination array too small to $readmem " + strfn);
|
||||
for (i=0; i<data.length; i++)
|
||||
memp[i] = data[i];
|
||||
}
|
||||
|
||||
$time(o) {
|
||||
return new Date().getTime();
|
||||
}
|
||||
|
||||
$$redxor(r: number) : number {
|
||||
r=(r^(r>>1)); r=(r^(r>>2)); r=(r^(r>>4)); r=(r^(r>>8)); r=(r^(r>>16));
|
||||
return r;
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
isStopped() { return this.stopped; }
|
||||
isFinished() { return this.finished; }
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
|
||||
import { hasDataType, HDLBinop, HDLBlock, HDLConstant, HDLDataType, HDLDataTypeObject, HDLExpr, HDLExtendop, HDLFuncCall, HDLModuleDef, HDLModuleRunner, HDLSourceLocation, HDLTriop, HDLUnop, HDLValue, HDLVariableDef, HDLVarRef, HDLWhileOp, isArrayItem, isArrayType, isBigConstExpr, isBinop, isBlock, isConstExpr, isFuncCall, isLogicType, isTriop, isUnop, isVarDecl, isVarRef, isWhileop } from "./hdltypes";
|
||||
import binaryen = require('binaryen');
|
||||
import { hasDataType, HDLBinop, HDLBlock, HDLConstant, HDLDataType, HDLDataTypeObject, HDLExpr, HDLExtendop, HDLFuncCall, HDLModuleDef, HDLModuleRunner, HDLSourceLocation, HDLTriop, HDLUnop, HDLValue, HDLVariableDef, HDLVarRef, HDLWhileOp, isArrayItem, isArrayType, isBigConstExpr, isBinop, isBlock, isConstExpr, isFuncCall, isLogicType, isTriop, isUnop, isVarDecl, isVarRef, isWhileop } from "./hdltypes";
|
||||
import { HDLError } from "./hdlruntime";
|
||||
|
||||
const VERILATOR_UNIT_FUNCTIONS = [
|
||||
"_ctor_var_reset",
|
||||
@ -27,18 +28,6 @@ const TRACEBUF = "$$tbuf";
|
||||
|
||||
///
|
||||
|
||||
export class HDLError extends Error {
|
||||
obj: any;
|
||||
$loc: HDLSourceLocation;
|
||||
constructor(obj: any, msg: string) {
|
||||
super(msg);
|
||||
Object.setPrototypeOf(this, HDLError.prototype);
|
||||
this.obj = obj;
|
||||
if (obj && obj.$loc) this.$loc = obj.$loc;
|
||||
if (obj) console.log(obj);
|
||||
}
|
||||
}
|
||||
|
||||
function getDataTypeSize(dt: HDLDataType) : number {
|
||||
if (isLogicType(dt)) {
|
||||
if (dt.left <= 7)
|
||||
@ -195,15 +184,13 @@ export class HDLModuleWASM implements HDLModuleRunner {
|
||||
traceEndOffset: number;
|
||||
trace: any;
|
||||
getFileData = null;
|
||||
maxMemoryMB : number;
|
||||
|
||||
constructor(moddef: HDLModuleDef, constpool: HDLModuleDef) {
|
||||
constructor(moddef: HDLModuleDef, constpool: HDLModuleDef, maxMemoryMB?: number) {
|
||||
this.hdlmod = moddef;
|
||||
this.constpool = constpool;
|
||||
this.bmod = new binaryen.Module();
|
||||
this.genTypes();
|
||||
var membytes = this.globals.len;
|
||||
var memblks = Math.ceil(membytes / 65536);
|
||||
this.bmod.setMemory(memblks, memblks, MEMORY); // memory is in 64k chunks
|
||||
this.maxMemoryMB = maxMemoryMB || 16;
|
||||
this.genMemory();
|
||||
this.genFuncs();
|
||||
}
|
||||
|
||||
@ -300,11 +287,26 @@ export class HDLModuleWASM implements HDLModuleRunner {
|
||||
if (this.bmod) {
|
||||
this.bmod.dispose();
|
||||
this.bmod = null;
|
||||
this.instance = null;
|
||||
this.databuf = null;
|
||||
this.data8 = null;
|
||||
this.data16 = null;
|
||||
this.data32 = null;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
private genMemory() {
|
||||
this.bmod = new binaryen.Module();
|
||||
this.genTypes();
|
||||
var membytes = this.globals.len;
|
||||
if (membytes > this.maxMemoryMB*1024*1024)
|
||||
throw new HDLError(null, `cannot allocate ${membytes} bytes, limit is ${this.maxMemoryMB} MB`);
|
||||
var memblks = Math.ceil(membytes / 65536);
|
||||
this.bmod.setMemory(memblks, memblks, MEMORY); // memory is in 64k chunks
|
||||
}
|
||||
|
||||
private genTypes() {
|
||||
// generate global variables
|
||||
var state = new Struct();
|
||||
|
@ -1,4 +1,5 @@
|
||||
|
||||
import { HDLError } from "./hdlruntime";
|
||||
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";
|
||||
|
||||
/**
|
||||
@ -16,6 +17,13 @@ import { HDLAlwaysBlock, HDLArrayItem, HDLBinop, HDLBlock, HDLConstant, HDLDataT
|
||||
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer
|
||||
*/
|
||||
|
||||
export class CompileError extends Error {
|
||||
constructor(obj: HDLSourceLocation|XMLNode, msg: string) {
|
||||
super(msg);
|
||||
Object.setPrototypeOf(this, CompileError.prototype);
|
||||
}
|
||||
}
|
||||
|
||||
interface XMLNode {
|
||||
type: string;
|
||||
text: string | null;
|
||||
@ -47,10 +55,11 @@ function parseXMLPoorly(s: string, openfn?: XMLVisitFunction, closefn?: XMLVisit
|
||||
|
||||
function closetop() {
|
||||
top = stack.pop();
|
||||
if (top.type != ident) throw Error("mismatch close tag: " + ident);
|
||||
if (top == null || top.type != ident) throw new CompileError(node, "mismatch close tag: " + ident);
|
||||
if (closefn) {
|
||||
top.obj = closefn(top);
|
||||
}
|
||||
if (stack.length == 0) throw new CompileError(null, "close tag without open: " + ident);
|
||||
stack[stack.length - 1].children.push(top);
|
||||
}
|
||||
function parseattrs(as: string): { [id: string]: string } {
|
||||
@ -79,24 +88,16 @@ function parseXMLPoorly(s: string, openfn?: XMLVisitFunction, closefn?: XMLVisit
|
||||
}
|
||||
if (attrs && attrs.endsWith('/')) closetop();
|
||||
} else if (content != null) {
|
||||
if (stack.length == 0) throw new CompileError(null, "content without element");
|
||||
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");
|
||||
if (stack.length != 1) throw new CompileError(null, "tag not closed");
|
||||
if (stack[0].type != '?xml') throw new CompileError(null, "?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 } = {};
|
||||
@ -131,12 +132,13 @@ export class VerilogXMLParser implements HDLUnit {
|
||||
}
|
||||
|
||||
name2js(s: string) {
|
||||
if (s == null) throw new CompileError(null, `no name`);
|
||||
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}`);
|
||||
if (arr.length == 0 && required) throw new CompileError(node, `no child of type ${type}`);
|
||||
return arr;
|
||||
}
|
||||
|
||||
@ -165,7 +167,7 @@ export class VerilogXMLParser implements HDLUnit {
|
||||
instances: [],
|
||||
vardefs: {},
|
||||
}
|
||||
if (this.cur_module) throw new Error(`nested modules not supported`);
|
||||
if (this.cur_module) throw new CompileError(node, `nested modules not supported`);
|
||||
this.cur_module = module;
|
||||
return module;
|
||||
}
|
||||
@ -176,8 +178,7 @@ export class VerilogXMLParser implements HDLUnit {
|
||||
this.defer(() => {
|
||||
def.dtype = this.dtypes[dtype_id];
|
||||
if (!def.dtype) {
|
||||
console.log(node);
|
||||
throw Error(`Unknown data type ${dtype_id} for ${node.type}`);
|
||||
throw new CompileError(node, `Unknown data type ${dtype_id} for ${node.type}`);
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -193,19 +194,19 @@ export class VerilogXMLParser implements HDLUnit {
|
||||
else
|
||||
return BigInt('0x' + numstr);
|
||||
} else {
|
||||
throw Error(`could not parse constant "${s}"`);
|
||||
throw new CompileError(null, `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}"`);
|
||||
if (def == null) throw new CompileError(null, `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}"`);
|
||||
if (mod == null) throw new CompileError(null, `could not resolve module "${s}"`);
|
||||
return mod;
|
||||
}
|
||||
|
||||
@ -325,7 +326,7 @@ export class VerilogXMLParser implements HDLUnit {
|
||||
}
|
||||
|
||||
visit_inititem(node: XMLNode) : HDLArrayItem {
|
||||
if (node.children.length != 1) throw Error('expected 1 children');
|
||||
this.expectChildren(node, 1, 1);
|
||||
return {
|
||||
index: parseInt(node.attrs['index']),
|
||||
expr: node.children[0].obj
|
||||
@ -334,7 +335,7 @@ export class VerilogXMLParser implements HDLUnit {
|
||||
|
||||
visit_cfunc(node: XMLNode) : HDLBlock {
|
||||
if (this.cur_module == null) { // TODO?
|
||||
console.log('no module open, skipping', node);
|
||||
//console.log('no module open, skipping', node);
|
||||
return;
|
||||
}
|
||||
var block = this.visit_begin(node);
|
||||
@ -363,7 +364,7 @@ export class VerilogXMLParser implements HDLUnit {
|
||||
}
|
||||
|
||||
visit_port(node: XMLNode) : HDLPort {
|
||||
if (node.children.length != 1) throw Error('expected 1 children');
|
||||
this.expectChildren(node, 1, 1);
|
||||
var varref: HDLPort = {
|
||||
$loc: this.parseSourceLocation(node),
|
||||
name: node.attrs['name'],
|
||||
@ -379,7 +380,12 @@ export class VerilogXMLParser implements HDLUnit {
|
||||
}
|
||||
|
||||
visit_module_files(node: XMLNode) {
|
||||
node.children.forEach((n) => this.files[(n.obj as HDLFile).id].isModule = true);
|
||||
node.children.forEach((n) => {
|
||||
if (n.obj) {
|
||||
var file = this.files[(n.obj as HDLFile).id];
|
||||
if (file) file.isModule = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
visit_file(node: XMLNode) {
|
||||
@ -404,10 +410,13 @@ export class VerilogXMLParser implements HDLUnit {
|
||||
}
|
||||
|
||||
visit_cells(node: XMLNode) {
|
||||
this.expectChildren(node, 1, 9999);
|
||||
var hier = node.children[0].obj as HDLHierarchyDef;
|
||||
if (hier != null) {
|
||||
var hiername = hier.name;
|
||||
this.hierarchies[hiername] = hier;
|
||||
}
|
||||
}
|
||||
|
||||
visit_cell(node: XMLNode) : HDLHierarchyDef {
|
||||
var hier = {
|
||||
@ -449,8 +458,7 @@ export class VerilogXMLParser implements HDLUnit {
|
||||
default:
|
||||
dtype = this.dtypes[dtypename];
|
||||
if (dtype == null) {
|
||||
console.log(node);
|
||||
throw Error(`unknown data type ${dtypename}`);
|
||||
throw new CompileError(node, `unknown data type ${dtypename}`);
|
||||
}
|
||||
}
|
||||
this.dtypes[id] = dtype;
|
||||
@ -471,18 +479,18 @@ export class VerilogXMLParser implements HDLUnit {
|
||||
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`);
|
||||
if (!dtype.subtype) throw new CompileError(node, `Unknown data type ${sub_dtype_id} for array`);
|
||||
})
|
||||
return dtype;
|
||||
} else {
|
||||
throw Error(`could not parse constant exprs in array`)
|
||||
throw new CompileError(node, `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")
|
||||
throw new CompileError(node, "POS/NEG required")
|
||||
return {
|
||||
$loc: this.parseSourceLocation(node),
|
||||
edgeType: edgeType,
|
||||
@ -505,8 +513,13 @@ export class VerilogXMLParser implements HDLUnit {
|
||||
visit_constpool(node: XMLNode) {
|
||||
}
|
||||
|
||||
expectChildren(node: XMLNode, low: number, high: number) {
|
||||
if (node.children.length < low || node.children.length > high)
|
||||
throw new CompileError(node, `expected between ${low} and ${high} children`);
|
||||
}
|
||||
|
||||
__visit_unop(node: XMLNode) : HDLUnop {
|
||||
if (node.children.length != 1) throw Error('expected 1 children');
|
||||
this.expectChildren(node, 1, 1);
|
||||
var expr: HDLUnop = {
|
||||
$loc: this.parseSourceLocation(node),
|
||||
op: node.type,
|
||||
@ -521,12 +534,12 @@ export class VerilogXMLParser implements HDLUnit {
|
||||
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`)
|
||||
if (unop.width != 32) throw new CompileError(node, `extends width ${unop.width} != 32`)
|
||||
return unop;
|
||||
}
|
||||
|
||||
__visit_binop(node: XMLNode) : HDLBinop {
|
||||
if (node.children.length != 2) throw Error('expected 2 children');
|
||||
this.expectChildren(node, 2, 2);
|
||||
var expr: HDLBinop = {
|
||||
$loc: this.parseSourceLocation(node),
|
||||
op: node.type,
|
||||
@ -539,7 +552,7 @@ export class VerilogXMLParser implements HDLUnit {
|
||||
}
|
||||
|
||||
visit_if(node: XMLNode) : HDLTriop {
|
||||
if (node.children.length < 2 || node.children.length > 3) throw Error('expected 2 or 3 children');
|
||||
this.expectChildren(node, 2, 3);
|
||||
var expr: HDLTriop = {
|
||||
$loc: this.parseSourceLocation(node),
|
||||
op: 'if',
|
||||
@ -553,7 +566,7 @@ export class VerilogXMLParser implements HDLUnit {
|
||||
|
||||
// while and for loops
|
||||
visit_while(node: XMLNode) : HDLWhileOp {
|
||||
if (node.children.length < 2 || node.children.length > 4) throw Error('expected 2-4 children');
|
||||
this.expectChildren(node, 2, 4);
|
||||
var expr: HDLWhileOp = {
|
||||
$loc: this.parseSourceLocation(node),
|
||||
op: 'while',
|
||||
@ -567,7 +580,7 @@ export class VerilogXMLParser implements HDLUnit {
|
||||
}
|
||||
|
||||
__visit_triop(node: XMLNode) : HDLBinop {
|
||||
if (node.children.length != 3) throw Error('expected 2 children');
|
||||
this.expectChildren(node, 3, 3);
|
||||
var expr: HDLTriop = {
|
||||
$loc: this.parseSourceLocation(node),
|
||||
op: node.type,
|
||||
@ -677,8 +690,7 @@ export class VerilogXMLParser implements HDLUnit {
|
||||
if (method) {
|
||||
return method.bind(this)(node);
|
||||
} else {
|
||||
console.log(node);
|
||||
throw Error(`no visitor for ${node.type}`)
|
||||
throw new CompileError(node, `no visitor for ${node.type}`)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,6 +107,6 @@ async function testJSvsWASM() {
|
||||
}
|
||||
}
|
||||
|
||||
testJSvsWASM();
|
||||
//testWASM().then(testJS);
|
||||
//testJSvsWASM();
|
||||
testWASM().then(testJS).then(testJSvsWASM);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user