diff --git a/README.md b/README.md index e0610ff..2cbe76c 100644 --- a/README.md +++ b/README.md @@ -6,25 +6,34 @@ Value Change Dump ([VCD](https://en.wikipedia.org/wiki/Value_change_dump)) parse 2. clone https://github.com/Digital-EDA/digital-vcd-parser -## Build +## 构建 ```bash source $EMCC_HOME/emsdk_env.sh -# once only + +# 只需要运行一次 npm install browserify terser node-gyp -g -# once only +# 只需要运行一次 npm i + +# 构建左推解析器代码(每次修改 ./bin/build.js 都需要重新运行) +node bin/build.js + # build make -j 12 ``` -production are : +生成 : - `./out/vcd.js` - `./out/vcd.wasm` -move them to your development worksapce. +部署代码: +```bash +# 将生成的 wasm 通过 浏览器化和特殊处理后部署到 render 项目中 +source deploy.sh /mnt/c/Users/11934/Project/Digital-IDE/digital-vcd-render +``` ## Test diff --git a/bin/build.js b/bin/build.js index bf0d7a8..f042ada 100755 --- a/bin/build.js +++ b/bin/build.js @@ -125,7 +125,8 @@ const generate = (cb) => { $dumpon: 11, $dumpvars: 12, '#': 13, - '0': 14, '1': 15, + '0': 14, + '1': 15, x: 16, X: 17, z: 18, Z: 19, u: 20, U: 21, // VHDL states @@ -136,9 +137,12 @@ const generate = (cb) => { b: 30, B: 31, r: 32, R: 33 }); + console.log(cmd); + + // p.code.store('command') 的具体执行逻辑移步 command-handler.js 中的 commandHandler declaration .match(spaces, declaration) - .select(cmd('$scope $var $upscope $comment $date $timescale $version'), + .select(cmd('$scope $var $upscope $comment $date $timescale $version #'), p.invoke(p.code.store('command'), commandSpan.start(inDeclaration))) .select(cmd('$enddefinitions'), p.invoke(p.code.store('command'), commandSpan.start(enddefinitions))) diff --git a/bin/vcd.js b/bin/vcd.js index 1a67be1..00f49cb 100644 --- a/bin/vcd.js +++ b/bin/vcd.js @@ -5,9 +5,13 @@ const createVCD = require('../out/vcd.js'); const webVcdParser = require('../lib/web-vcd-parser.js'); /** - * @typedef {{ maxChunkLength: number, useGcd: boolean }} consumeConfig + * @typedef {Object} consumeConfig + * @property {number} maxChunkLength + * @property {boolean} useGcd * - * @typedef {{ kind: string, wave: number[] }} vcdValue + * @typedef {Object} vcdValue + * @property {string} kind + * @property {number[]} wave * * @typedef {Object} VarSignal * @property { 'var' } kind diff --git a/install.sh b/install.sh index 0b6d712..4e4a6ba 100644 --- a/install.sh +++ b/install.sh @@ -1,3 +1,3 @@ source $EMCC_HOME/emsdk_env.sh npm install browserify terser node-gyp -g -npm i \ No newline at end of file +npm i diff --git a/lib/command-handler.js b/lib/command-handler.js index 3502b1a..a53ede4 100644 --- a/lib/command-handler.js +++ b/lib/command-handler.js @@ -3,72 +3,79 @@ /* eslint-disable indent */ const handleScope = (info, str) => { - const [type, name] = str.split(/\s+/); - const ero = {kind: 'scope', type, name, body: []}; - const current = info.stack[info.stack.length - 1]; - current.body.push(ero); - info.stack.push(ero); - // console.log(ero); + const [type, name] = str.split(/\s+/); + const ero = { kind: 'scope', type, name, body: [] }; + const current = info.stack[info.stack.length - 1]; + current.body.push(ero); + info.stack.push(ero); + // console.log(ero); }; const handleUpScope = (info /* , str */) => { - info.stack.pop(); - // console.log(['upscope', str]); + info.stack.pop(); + // console.log(['upscope', str]); }; const handleVar = (info, str) => { - // reg 3 ( r_reg [2:0] - // 0 1 2 3+ - const eroj = str.split(/\s+/); - const ero = { - kind: 'var', - type: eroj[0], - size: parseInt(eroj[1]), - link: eroj[2], - name: eroj.slice(3).join('') - }; - { - const m = ero.name.match('^(?\\w+)\\[' + (ero.size - 1) + ':0]$'); - if (m) { - ero.name = m.groups.name; + // reg 3 ( r_reg [2:0] + // 0 1 2 3+ + const eroj = str.split(/\s+/); + const ero = { + kind: 'var', + type: eroj[0], + size: parseInt(eroj[1]), + link: eroj[2], + name: eroj.slice(3).join('') + }; + { + const m = ero.name.match('^(?\\w+)\\[' + (ero.size - 1) + ':0]$'); + if (m) { + ero.name = m.groups.name; + } } - } - const current = info.stack[info.stack.length - 1]; - current.body.push(ero); - // console.log(ero); + const current = info.stack[info.stack.length - 1]; + current.body.push(ero); + // console.log(ero); }; +/** + * @description 处理 C++ 中的 on_command 函数,也就是 llparse 框架中的 p.code.store('command') 触发的函数 + * @param {} info + * @param {*} cmd + * @param {*} str + */ const commandHandler = (info, cmd, str) => { - str = str.trim(); - switch(cmd) { - case 1: - info.comment = str; - // console.log(['comment', str]); - break; - case 2: - info.date = str; - // console.log(['date', str]); - break; - case 3: - handleScope(info, str); - break; - case 4: - info.timescale = str; - // console.log(['timescale', str]); - break; - case 5: - handleUpScope(info, str); - break; - case 6: - handleVar(info, str); - break; - case 7: - info.version = str; - // console.log(['version', str]); - break; - default: - console.log([cmd, str]); - } + str = str.trim(); + + switch (cmd) { + case 1: + info.comment = str; + // console.log(['comment', str]); + break; + case 2: + info.date = str; + // console.log(['date', str]); + break; + case 3: + handleScope(info, str); + break; + case 4: + info.timescale = str; + // console.log(['timescale', str]); + break; + case 5: + handleUpScope(info, str); + break; + case 6: + handleVar(info, str); + break; + case 7: + info.version = str; + // console.log(['version', str]); + break; + default: + console.log([cmd, str]); + } }; module.exports = commandHandler; diff --git a/lib/vcd-pipe-deso.js b/lib/vcd-pipe-deso.js index c2d2abf..db7bc78 100644 --- a/lib/vcd-pipe-deso.js +++ b/lib/vcd-pipe-deso.js @@ -86,7 +86,7 @@ module.exports = async (deso, inst, done) => { inst.change.any(onAnyChange); inst.on('finish', () => { - console.log((Date.now() - t0) / 1000); + // console.log((Date.now() - t0) / 1000); deso.tgcd = tgcd; deso.t0 = (inst.info.t0 || 0); // console.log(inst.getTime()); diff --git a/lib/web-vcd-parser.js b/lib/web-vcd-parser.js index c23fa4a..d7c5a34 100644 --- a/lib/web-vcd-parser.js +++ b/lib/web-vcd-parser.js @@ -145,7 +145,7 @@ const getWrapper = wasm => { * @param {*} chunk * @returns */ - execute: (ctx, cb0, cb1, info, chunk) => { + execute: (ctx, cb0, cb1, info, chunk) => { boundInfo = info; ee[0] = cb0; ee[1] = cb1; diff --git a/test/debug/basic.js b/test/debug/basic.js index 52f6b8a..e74c40a 100644 --- a/test/debug/basic.js +++ b/test/debug/basic.js @@ -8,12 +8,11 @@ const fs = require('fs'); const { makeVcdStream } = require('../../bin/vcd'); async function main() { - const arraybuffer = fs.readFileSync('./test/debug/pe_tb.vcd'); + const arraybuffer = fs.readFileSync('./test/debug/small.vcd'); const vcdstream = await makeVcdStream(); vcdstream.consume(arraybuffer); const info = vcdstream.getBasicInfo(); - console.log(info.signalValues['*']); - console.log(info.signalValues['+']); + console.log(info); } main(); \ No newline at end of file diff --git a/test/debug/la0_waveform.vcd b/test/debug/la0_waveform.vcd new file mode 100644 index 0000000..2d65221 --- /dev/null +++ b/test/debug/la0_waveform.vcd @@ -0,0 +1,114 @@ +#0 $dumpon +$date today $end +$timescale 1 ns $end +$scope module top $end +$var wire 1 0 ins_top_s4/inst_apb3_device/extern_trigger_top_inst/line1_debounced $end +$var wire 1 1 ins_top_s4/inst_apb3_device/extern_trigger_top_inst/line2_debounced $end +$var wire 4 2 ins_top_s4/inst_apb3_device/extern_trigger_top_inst/encoder_control_top_inst/trigger_line $end +$var wire 2 3 ins_top_s4/inst_apb3_device/extern_trigger_top_inst/encoder_control_top_inst/encoder_trigger_mode $end +$var wire 2 4 ins_top_s4/inst_apb3_device/extern_trigger_top_inst/encoder_control_top_inst/encoder_sourceA_sel $end +$var wire 2 5 ins_top_s4/inst_apb3_device/extern_trigger_top_inst/encoder_control_top_inst/encoder_sourceB_sel $end +$var wire 1 6 ins_top_s4/inst_apb3_device/extern_trigger_top_inst/encoder_control_top_inst/encoder_counter_rst $end +$var wire 32 7 ins_top_s4/inst_apb3_device/extern_trigger_top_inst/encoder_control_top_inst/encoder_counter $end +$var wire 2 8 ins_top_s4/inst_apb3_device/extern_trigger_top_inst/encoder_control_top_inst/encoder_counter_mode $end +$var wire 1 9 ins_top_s4/inst_apb3_device/extern_trigger_top_inst/encoder_trigger_out $end +$var wire 1 a ins_top_s4/inst_apb3_device/extern_trigger_top_inst/encoder_control_top_inst/encoder_sourceA $end +$var wire 1 b ins_top_s4/inst_apb3_device/extern_trigger_top_inst/encoder_control_top_inst/encoder_sourceB $end +$var wire 1 c ins_top_s4/inst_apb3_device/extern_trigger_top_inst/encoder_control_top_inst/trigger_forward $end +$var wire 1 d ins_top_s4/inst_apb3_device/extern_trigger_top_inst/encoder_control_top_inst/trigger_backward $end +$var wire 2 e ins_top_s4/inst_apb3_device/extern_trigger_top_inst/encoder_control_top_inst/u1_encoder2trigger/encoder_sourceA_dly $end +$var wire 2 f ins_top_s4/inst_apb3_device/extern_trigger_top_inst/encoder_control_top_inst/u1_encoder2trigger/encoder_sourceB_dly $end +$var wire 1 10 ins_top_s4/inst_apb3_device/extern_trigger_top_inst/encoder_control_top_inst/u1_encoder2trigger/encoder_sourceA_pos $end +$var wire 1 11 ins_top_s4/inst_apb3_device/extern_trigger_top_inst/encoder_control_top_inst/u1_encoder2trigger/encoder_sourceA_neg $end +$var wire 1 12 ins_top_s4/inst_apb3_device/extern_trigger_top_inst/encoder_control_top_inst/u1_encoder2trigger/encoder_sourceB_neg $end +$var wire 1 13 ins_top_s4/inst_apb3_device/extern_trigger_top_inst/encoder_control_top_inst/u1_encoder2trigger/trigger_forward0 $end +$var wire 1 14 ins_top_s4/inst_apb3_device/extern_trigger_top_inst/encoder_control_top_inst/u1_encoder2trigger/trigger_forward1 $end +$var wire 1 15 ins_top_s4/inst_apb3_device/extern_trigger_top_inst/encoder_control_top_inst/u1_encoder2trigger/trigger_forward2 $end +$var wire 1 16 ins_top_s4/inst_apb3_device/extern_trigger_top_inst/encoder_control_top_inst/u1_encoder2trigger/trigger_forward3 $end +$var wire 1 17 ins_top_s4/inst_apb3_device/extern_trigger_top_inst/encoder_control_top_inst/u1_encoder2trigger/trigger_backward0 $end +$var wire 1 18 ins_top_s4/inst_apb3_device/extern_trigger_top_inst/encoder_control_top_inst/u1_encoder2trigger/trigger_backward1 $end +$var wire 1 19 ins_top_s4/inst_apb3_device/extern_trigger_top_inst/encoder_control_top_inst/u1_encoder2trigger/trigger_backward3 $end +$var wire 1 1a ins_top_s4/inst_apb3_device/extern_trigger_top_inst/encoder_control_top_inst/u1_encoder2trigger/trigger_backward2 $end +$var wire 32 1b ins_top_s4/inst_apb3_device/extern_trigger_top_inst/encode_rcounter $end +$upscope $end +$enddefinitions $end +#0 +$dumpvars +00 +11 +b1110 2 +b00 3 +b00 4 +b01 5 +06 +b00000000000000000010000111001101 7 +b00 8 +09 +0a +1b +0c +0d +b00 e +b11 f +010 +011 +012 +013 +014 +015 +016 +017 +018 +019 +01a +b00000000000000000000000000000000 1b +$end +#1021 +10 +b1111 2 +#1022 +1a +#1023 +b01 e +110 +117 +#1024 +1d +b11 e +010 +017 +#1025 +b00000000000000000010000111001110 7 +19 +0d +#1026 +09 +#2047 +10 +11 +b1111 2 +b00 3 +b00 4 +b01 5 +06 +b00000000000000000010000111001110 7 +b00 8 +09 +1a +1b +0c +0d +b11 e +b11 f +010 +011 +012 +013 +014 +015 +016 +017 +018 +019 +01a +b00000000000000000000000000000000 1b diff --git a/vcd_spans.c b/vcd_spans.c index 9b9f8f4..1d8f833 100644 --- a/vcd_spans.c +++ b/vcd_spans.c @@ -77,6 +77,7 @@ int stringEq(const unsigned char* i, // search pattern int commandSpan(vcd_parser_t* state, const unsigned char* p, const unsigned char* endp) { const uint8_t command = state->command; + #ifndef VCDWASM napi_env env = state->napi_env; @@ -117,7 +118,7 @@ int commandSpan(vcd_parser_t* state, const unsigned char* p, return 0; } #else - if ((command > 0) && (command < 8)) { + if ((command > 0) && (command < 8)) { const int len = endp - p; int tailLen = 3; if (len < 4) { diff --git a/wasm_main.cpp b/wasm_main.cpp index b859144..61899bc 100644 --- a/wasm_main.cpp +++ b/wasm_main.cpp @@ -133,15 +133,17 @@ int init(externalJsMethodZero* f0, externalJsMethodOne* f1, int32_t execute(const int context, externalJsMethodZero* f0, externalJsMethodOne* f1, externalJsSetProperty* sfn, externalJsGetProperty* gfn, char* p, const int plen) { - // cout << "execute got " << p << "\n"; - // cout << "execute " << (int)sfn << " and got " << p << "\n"; + // 详见 web-vcd-parser.js 中的 boundSet bound_set_property = sfn; - bound_get_property = gfn; - externalZero = f0; - externalOne = f1; - // const size_t plen = strlen(p); - // printf("\n", plen); + // 详见 web-vcd-parser.js 中的 boundGet + bound_get_property = gfn; + + // 详见 web-vcd-parser.js 中的 boundEE0 + externalZero = f0; + + // 详见 web-vcd-parser.js 中的 boundEE1 + externalOne = f1; const int32_t error = vcd_parser_execute(state, p, p + plen);