type V2JS_Var = { wordlen:number, name:string, len:number, ofs:number, arrdim?:number[], input:boolean, output:boolean, } type V2JS_Code = { name:string, ports:V2JS_Var[], signals:V2JS_Var[], funcs:string[], } type V2JS_Output = { output:{ code:V2JS_Code, name:string, ports:V2JS_Var[], signals:V2JS_Var[], } } function translateVerilatorOutputToJS(htext:string, cpptext:string) { var moduleName : string; var symsName : string; function parseDecls(text:string, arr:V2JS_Var[], name:string, bin?:boolean, bout?:boolean) { var re = new RegExp(name + "(\\d*)[(](\\w+),(\\d+),(\\d+)[)]", 'gm'); var m; while ((m = re.exec(text))) { arr.push({ wordlen:parseInt(m[1]), name:m[2], len:parseInt(m[3])+1, ofs:parseInt(m[4]), input:bin, output:bout, }); } re = new RegExp(name + "(\\d*)[(](\\w+)\\[(\\d+)\\],(\\d+),(\\d+)[)]", 'gm'); var m; while ((m = re.exec(text))) { arr.push({ wordlen:parseInt(m[1]), name:m[2], arrdim:[parseInt(m[3])], len:parseInt(m[4])+1, ofs:parseInt(m[5]), input:bin, output:bout, }); } re = new RegExp(name + "(\\d*)[(](\\w+)\\[(\\d+)\\]\\[(\\d+)\\],(\\d+),(\\d+)[)]", 'gm'); var m; while ((m = re.exec(text))) { arr.push({ wordlen:parseInt(m[1]), name:m[2], arrdim:[parseInt(m[3]), parseInt(m[4])], len:parseInt(m[5])+1, ofs:parseInt(m[6]), input:bin, output:bout, }); } } function buildModule(o : V2JS_Code) : string { var m = '"use strict";\n'; for (var i=0; i\b/g, "."); text = text.replace('VL_INLINE_OPT', ''); text = text.replace(/[(]IData[)]/g, ''); text = text.replace(/\b(0x[0-9a-f]+)U/gi, '$1'); text = text.replace(/\b([0-9]+)U/gi, '$1'); text = text.replace(/\bQData /g, 'var '); text = text.replace(/\bbool /g, ''); text = text.replace(/\bint /g, 'var '); text = text.replace(/(\w+ = VL_RAND_RESET_)/g, 'this.$1'); // TODO? //text = text.replace(/^\s*(\w+ = \d+;)/gm, 'this.$1'); // TODO? //text = text.replace(/(\w+\[\w+\] = VL_RAND_RESET_I)/g, 'this.$1'); text = text.replace(/^#/gm, '//#'); text = text.replace(/VL_LIKELY/g, '!!'); text = text.replace(/VL_UNLIKELY/g, '!!'); // for memread text = text.replace(/VL_SIGW[(](\w+),(\d+),(\d+),(\d+)[)]/g, 'var $1 = new Uint32Array($4)'); // convert VL_ULL() 64-bits into an array of two 32-bits text = text.replace(/VL_ULL[(]0x([0-9a-f]+?)([0-9a-f]{8})[)]/g, '[0x$2, 0x$1]'); //[%0t] %Error: scoreboard.v:53: Assertion failed in %Nscoreboard_top.scoreboard_gen: reset 64 -935359306 Vscoreboard_top text = text.replace(/Verilated::(\w+)Error/g, 'console.log'); text = text.replace(/vlSymsp.name[(][)]/g, '"'+moduleName+'"'); return "function " + text + "\nthis." + funcname + " = " + funcname + ";\n"; } function translateStaticVars(text : string) : string { var s = ""; var m; var re = /VL_ST_SIG(\d+)[(](\w+?)::(\w+).(\d+).,(\d+),(\d+)[)]/g; while (m = re.exec(text)) { s += "var " + m[3] + " = this." + m[3] + " = new Uint" + m[1] + "Array(" + m[4] + ");\n"; } return s; } // parse header file moduleName = /VL_MODULE.(\w+)./.exec(htext)[1]; symsName = moduleName + "__Syms"; var ports = []; parseDecls(htext, ports, 'VL_IN', true, false); parseDecls(htext, ports, 'VL_OUT', false, true); var signals = []; parseDecls(htext, signals, 'VL_SIG'); // parse cpp file // split functions var re_fnsplit = new RegExp("(?:void|QData) " + moduleName + "::"); var functexts = cpptext.split(re_fnsplit); var funcs = []; funcs.push(translateStaticVars(functexts[0])); for (var i=4; i