2017-11-11 19:45:32 +00:00
|
|
|
|
|
|
|
var moduleName, symsName;
|
|
|
|
|
|
|
|
function parseDecls(text, arr, name, bin, bout) {
|
|
|
|
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]),
|
|
|
|
ofs:parseInt(m[4]),
|
|
|
|
});
|
|
|
|
}
|
2017-11-15 00:12:52 +00:00
|
|
|
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],
|
|
|
|
arrlen:parseInt(m[3]),
|
|
|
|
len:parseInt(m[4]),
|
|
|
|
ofs:parseInt(m[5]),
|
|
|
|
});
|
|
|
|
}
|
2017-11-11 19:45:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
function buildModule(o) {
|
|
|
|
var m = '"use strict";\n';
|
|
|
|
m += '\tvar self = this;\n';
|
|
|
|
m += '\tvar VL_RAND_RESET_I = base.VL_RAND_RESET_I;\n';
|
|
|
|
for (var i=0; i<o.ports.length; i++) {
|
|
|
|
m += "\tself." + o.ports[i].name + ";\n";
|
|
|
|
}
|
|
|
|
for (var i=0; i<o.signals.length; i++) {
|
2017-11-15 00:12:52 +00:00
|
|
|
if (o.signals[i].arrlen)
|
|
|
|
m += "\tvar " + o.signals[i].name + " = self." + o.signals[i].name + " = [];\n";
|
|
|
|
else
|
|
|
|
m += "\tself." + o.signals[i].name + ";\n";
|
2017-11-11 19:45:32 +00:00
|
|
|
}
|
|
|
|
for (var i=0; i<o.funcs.length; i++) {
|
|
|
|
m += o.funcs[i];
|
|
|
|
}
|
|
|
|
return m;
|
|
|
|
}
|
|
|
|
|
|
|
|
function translateFunction(text) {
|
|
|
|
text = text.trim();
|
|
|
|
var funcname = text.match(/(\w+)/)[1];
|
|
|
|
text = text.replace(symsName + "* __restrict ", "");
|
|
|
|
text = text.replace(moduleName + "* __restrict vlTOPp VL_ATTR_UNUSED", "var vlTOPp");
|
|
|
|
text = text.replace(/VL_DEBUG_IF/g,"//VL_DEBUG_IF");
|
|
|
|
text = text.replace(/VL_SIG\d+[(](\w+),(\d+),(\d+)[)]/g, 'var $1');
|
|
|
|
text = text.replace(/\b->\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 /, 'var ');
|
|
|
|
text = text.replace(/\bbool /, '');
|
2017-11-15 00:12:52 +00:00
|
|
|
text = text.replace(/\bint /, 'var ');
|
2017-11-11 19:45:32 +00:00
|
|
|
text = text.replace(/(\w+ = VL_RAND_RESET_I)/g, 'self.$1');
|
2017-11-15 00:12:52 +00:00
|
|
|
//text = text.replace(/(\w+\[\w+\] = VL_RAND_RESET_I)/g, 'self.$1');
|
2017-11-11 19:45:32 +00:00
|
|
|
text = text.replace(/^#/gm, '//#');
|
|
|
|
text = text.replace(/VL_LIKELY/g, '!!');
|
|
|
|
text = text.replace(/VL_UNLIKELY/g, '!!');
|
|
|
|
text = text.replace(/Verilated::(\w+)Error/g, 'console.log');
|
|
|
|
return "function " + text + "\nself." + funcname + " = " + funcname + ";\n";
|
|
|
|
}
|
|
|
|
|
2017-11-13 05:24:19 +00:00
|
|
|
function translateStaticVars(text) {
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2017-11-11 19:45:32 +00:00
|
|
|
function translateVerilatorOutputToJS(htext, cpptext) {
|
|
|
|
// 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 = [];
|
2017-11-13 05:24:19 +00:00
|
|
|
funcs.push(translateStaticVars(functexts[0]));
|
2017-11-11 19:45:32 +00:00
|
|
|
for (var i=4; i<functexts.length; i++) {
|
|
|
|
var fntxt = translateFunction(functexts[i]);
|
|
|
|
funcs.push(fntxt);
|
|
|
|
}
|
|
|
|
|
|
|
|
return {
|
2017-11-14 14:33:15 +00:00
|
|
|
output:{
|
|
|
|
code:buildModule({
|
|
|
|
name:moduleName,
|
|
|
|
ports:ports,
|
|
|
|
signals:signals,
|
|
|
|
funcs:funcs,
|
|
|
|
}),
|
2017-11-11 19:45:32 +00:00
|
|
|
name:moduleName,
|
|
|
|
ports:ports,
|
|
|
|
signals:signals,
|
2017-11-14 14:33:15 +00:00
|
|
|
}
|
2017-11-11 19:45:32 +00:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
////
|
|
|
|
|
2017-11-13 05:24:19 +00:00
|
|
|
// TODO: unit test
|
2017-11-11 19:45:32 +00:00
|
|
|
/*
|
|
|
|
incpp = "obj_dir/Vhvsync_generator.cpp"
|
|
|
|
inh = "obj_dir/Vhvsync_generator.h"
|
|
|
|
|
|
|
|
fs = require('fs')
|
|
|
|
fs.readFile(incpp, 'utf8', function (err,datacpp) {
|
|
|
|
fs.readFile(inh, 'utf8', function (err,datah) {
|
|
|
|
var modtext = translateVerilatorOutputToJS(datah, datacpp);
|
|
|
|
console.log(modtext);
|
|
|
|
var mod = new Function('base',modtext);
|
|
|
|
var gen = new mod(new VerilatorBase());
|
|
|
|
console.log(gen);
|
|
|
|
gen._ctor_var_reset();
|
|
|
|
var top = {TOPp:gen};
|
|
|
|
gen._eval_settle(top);
|
|
|
|
for (var i=0; i<1000000; i++)
|
|
|
|
gen._eval(top);
|
|
|
|
console.log(gen);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
*/
|