完成 的支持 | 优化工具函数
This commit is contained in:
parent
55d5c51f29
commit
a8804d9cc0
25
README.md
25
README.md
@ -11,13 +11,11 @@ Value Change Dump ([VCD](https://en.wikipedia.org/wiki/Value_change_dump)) parse
|
|||||||
```bash
|
```bash
|
||||||
source $EMCC_HOME/emsdk_env.sh
|
source $EMCC_HOME/emsdk_env.sh
|
||||||
# once only
|
# once only
|
||||||
npm install browserify terser -g
|
npm install browserify terser node-gyp -g
|
||||||
# once only
|
# once only
|
||||||
node bin/build.js
|
npm i
|
||||||
# build
|
# build
|
||||||
make -j 12
|
make -j 12
|
||||||
# adjust to browser environment
|
|
||||||
browserify ./bin/vcd.js | terser --compress -o ./out/vcd.js
|
|
||||||
```
|
```
|
||||||
|
|
||||||
production are :
|
production are :
|
||||||
@ -27,6 +25,25 @@ production are :
|
|||||||
|
|
||||||
move them to your development worksapce.
|
move them to your development worksapce.
|
||||||
|
|
||||||
|
|
||||||
|
## Test
|
||||||
|
|
||||||
|
After first building, run following
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run test
|
||||||
|
```
|
||||||
|
|
||||||
|
note: don't run `browserify` if you want to test.
|
||||||
|
|
||||||
|
## Deploy to web
|
||||||
|
|
||||||
|
```bash
|
||||||
|
source deploy.sh /path/to/digital-vcd-render
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Only stream of Uint8 is supported as input. e.g. we want to parse a certain `*.vcd` read in browser-like environment. Mount vcd to window in your `index.html`:
|
Only stream of Uint8 is supported as input. e.g. we want to parse a certain `*.vcd` read in browser-like environment. Mount vcd to window in your `index.html`:
|
||||||
|
67
backup/napi_any.js
Normal file
67
backup/napi_any.js
Normal file
File diff suppressed because one or more lines are too long
138
backup/napi_basic.js
Normal file
138
backup/napi_basic.js
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
// 'use strict';
|
||||||
|
|
||||||
|
// /* eslint-disable no-console */
|
||||||
|
// /* eslint-disable indent */
|
||||||
|
|
||||||
|
// const expect = require('chai').expect;
|
||||||
|
// const parser = require('../lib/parser.js');
|
||||||
|
|
||||||
|
// describe('basic', () => {
|
||||||
|
|
||||||
|
// it('typeof vcd', done => {
|
||||||
|
// expect(parser).to.be.an('function');
|
||||||
|
// done();
|
||||||
|
// });
|
||||||
|
|
||||||
|
// it('typeof vcd instance', done => {
|
||||||
|
// expect(parser()).to.be.an('object');
|
||||||
|
// done();
|
||||||
|
// });
|
||||||
|
|
||||||
|
// it('fail: foo bar', done => {
|
||||||
|
// const inst = parser();
|
||||||
|
// expect(() => {
|
||||||
|
// inst.write(Buffer.from(' foo bar ???'));
|
||||||
|
// }).not.to.throw();
|
||||||
|
// expect(inst.info).to.deep.eq({
|
||||||
|
// stack: [{}],
|
||||||
|
// status: 'declaration',
|
||||||
|
// wires: {}
|
||||||
|
// });
|
||||||
|
// done();
|
||||||
|
// });
|
||||||
|
|
||||||
|
// it('fail: $comment', done => {
|
||||||
|
// const inst = parser();
|
||||||
|
// expect(() => {
|
||||||
|
// inst.write(Buffer.from(
|
||||||
|
// ' \n $comment some text $end $comment more text $end ???'
|
||||||
|
// ));
|
||||||
|
// }).not.to.throw();
|
||||||
|
// expect(inst.info).to.deep.eq({
|
||||||
|
// comment: ' more text ',
|
||||||
|
// stack: [{}],
|
||||||
|
// status: 'declaration',
|
||||||
|
// wires: {}
|
||||||
|
// });
|
||||||
|
// done();
|
||||||
|
// });
|
||||||
|
|
||||||
|
// it('$version', done => {
|
||||||
|
// const inst = parser();
|
||||||
|
// expect(inst.write(`
|
||||||
|
// $version Generated by VerilatedVcd $end
|
||||||
|
// $date Wed Sep 18 22:59:07 2019
|
||||||
|
// $end
|
||||||
|
// $timescale 1ns $end
|
||||||
|
|
||||||
|
// $scope module top $end
|
||||||
|
// $var wire 1 "}G clock $end
|
||||||
|
// $scope module leaf $end
|
||||||
|
// $var wire 64 {u counter [63:0] $end
|
||||||
|
// $upscope $end
|
||||||
|
// $scope module fruit $end
|
||||||
|
// $var wire 4 u) point [3:0] $end
|
||||||
|
// $upscope $end
|
||||||
|
// $upscope $end
|
||||||
|
|
||||||
|
// $enddefinitions $end
|
||||||
|
// `
|
||||||
|
// )).to.eq(true);
|
||||||
|
|
||||||
|
// expect(inst.write(`
|
||||||
|
|
||||||
|
// #1
|
||||||
|
// 0"}G
|
||||||
|
// #2
|
||||||
|
// 1"}G
|
||||||
|
// #300
|
||||||
|
// 0"}G
|
||||||
|
// b1111000000000000 {u
|
||||||
|
// #301
|
||||||
|
// b0000111100000000 {u
|
||||||
|
// #302
|
||||||
|
// b0000000011110000 {u
|
||||||
|
// #303
|
||||||
|
// b0000000000001111 {u
|
||||||
|
// `
|
||||||
|
// )).to.eq(true);
|
||||||
|
|
||||||
|
// console.log(inst.info);
|
||||||
|
|
||||||
|
// expect(inst.info).to.deep.eq({
|
||||||
|
// status: 'simulation',
|
||||||
|
// date: ' Wed Sep 18 22:59:07 2019\n ',
|
||||||
|
// version: ' Generated by VerilatedVcd ',
|
||||||
|
// timescale: ' 1ns ',
|
||||||
|
// t0: 1,
|
||||||
|
// varId: 'u)',
|
||||||
|
// wires: {
|
||||||
|
// top: {
|
||||||
|
// clock: '"}G',
|
||||||
|
// fruit: {
|
||||||
|
// point: 'u)'
|
||||||
|
// },
|
||||||
|
// leaf: {
|
||||||
|
// counter: '{u'
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// stack: [{
|
||||||
|
// top: {
|
||||||
|
// clock: '"}G',
|
||||||
|
// fruit: {
|
||||||
|
// point: 'u)'
|
||||||
|
// },
|
||||||
|
// leaf: {
|
||||||
|
// counter: '{u'
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// clock: '"}G',
|
||||||
|
// fruit: {
|
||||||
|
// point: 'u)'
|
||||||
|
// },
|
||||||
|
// leaf: {
|
||||||
|
// counter: '{u'
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// point: 'u)'
|
||||||
|
// }]
|
||||||
|
// });
|
||||||
|
// done();
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
|
||||||
|
// /* eslint-env mocha */
|
88
backup/napi_dump.js
Normal file
88
backup/napi_dump.js
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
// 'use strict';
|
||||||
|
|
||||||
|
// const fs = require('fs');
|
||||||
|
// const path = require('path');
|
||||||
|
|
||||||
|
// const expect = require('chai').expect;
|
||||||
|
// const parser = require('../lib/parser.js');
|
||||||
|
// const chopper = require('../lib/chopper.js');
|
||||||
|
|
||||||
|
// const expectaitions = [
|
||||||
|
// { id: '"}G', time: 100n, cmd: 14, value: 0n, mask: 0n },
|
||||||
|
// { id: '"}G', time: 200n, cmd: 15, value: 0n, mask: 0n },
|
||||||
|
// { id: '{u', time: 200n, cmd: 30, value: 0xf0f0f0f0f0f0f0f0n, mask: 0xff00ff00ff00ff00n },
|
||||||
|
// { id: '"}G', time: 300n, cmd: 14, value: 0n, mask: 0n },
|
||||||
|
// { id: '{u', time: 300n, cmd: 30, value: 0xf000000000000000n, mask: 0n },
|
||||||
|
// { id: 'u)', time: 300n, cmd: 30, value: 0n, mask: 0n },
|
||||||
|
// { id: '{u', time: 301n, cmd: 30, value: 0x0f00000000000000n, mask: 0n },
|
||||||
|
// { id: 'u)', time: 301n, cmd: 30, value: 1n, mask: 0n },
|
||||||
|
// { id: '{u', time: 302n, cmd: 30, value: 0x00f0000000000000n, mask: 0n },
|
||||||
|
// { id: 'u)', time: 302n, cmd: 30, value: 2n, mask: 0n },
|
||||||
|
// { id: '{u', time: 303n, cmd: 30, value: 0x000f000000000000n, mask: 0n },
|
||||||
|
// { id: 'u)', time: 303n, cmd: 30, value: 3n, mask: 0n },
|
||||||
|
// { id: '{u', time: 304n, cmd: 30, value: 0x0000f00000000000n, mask: 0n },
|
||||||
|
// { id: 'u)', time: 304n, cmd: 30, value: 4n, mask: 0n },
|
||||||
|
// { id: '{u', time: 305n, cmd: 30, value: 0x00000f0000000000n, mask: 0n },
|
||||||
|
// { id: 'u)', time: 305n, cmd: 30, value: 5n, mask: 0n },
|
||||||
|
// { id: '{u', time: 306n, cmd: 30, value: 0x000000f000000000n, mask: 0n },
|
||||||
|
// { id: 'u)', time: 306n, cmd: 30, value: 6n, mask: 0n },
|
||||||
|
// { id: '{u', time: 307n, cmd: 30, value: 0x0000000f00000000n, mask: 0n },
|
||||||
|
// { id: 'u)', time: 307n, cmd: 30, value: 7n, mask: 0n },
|
||||||
|
// { id: '{u', time: 308n, cmd: 31, value: 0x00000000f0000000n, mask: 0n },
|
||||||
|
// { id: 'u)', time: 308n, cmd: 30, value: 8n, mask: 0n },
|
||||||
|
// { id: '{u', time: 309n, cmd: 30, value: 0x000000000f000000n, mask: 0n },
|
||||||
|
// { id: 'u)', time: 309n, cmd: 30, value: 9n, mask: 0n },
|
||||||
|
// { id: '{u', time: 310n, cmd: 30, value: 0x0000000000f00000n, mask: 0n },
|
||||||
|
// { id: 'u)', time: 310n, cmd: 30, value: 10n, mask: 0n },
|
||||||
|
// { id: '{u', time: 311n, cmd: 30, value: 0x00000000000f0000n, mask: 0n },
|
||||||
|
// { id: 'u)', time: 311n, cmd: 30, value: 11n, mask: 0n },
|
||||||
|
// { id: '{u', time: 312n, cmd: 30, value: 0x000000000000f000n, mask: 0n },
|
||||||
|
// { id: 'u)', time: 312n, cmd: 30, value: 12n, mask: 0n },
|
||||||
|
// { id: '{u', time: 313n, cmd: 30, value: 0x0000000000000f00n, mask: 0n },
|
||||||
|
// { id: 'u)', time: 313n, cmd: 30, value: 13n, mask: 0n },
|
||||||
|
// { id: '{u', time: 314n, cmd: 30, value: 0x00000000000000f0n, mask: 0n },
|
||||||
|
// { id: 'u)', time: 314n, cmd: 30, value: 14n, mask: 0n },
|
||||||
|
// { id: '{u', time: 315n, cmd: 30, value: 0x000000000000000fn, mask: 0n },
|
||||||
|
// { id: 'u)', time: 315n, cmd: 30, value: 15n, mask: 0n },
|
||||||
|
// { id: '"}G', time: 316n, cmd: 15, value: 0n, mask: 0n }
|
||||||
|
// ];
|
||||||
|
|
||||||
|
// describe('napi dump', function () {
|
||||||
|
// it('simple napi', done => {
|
||||||
|
// fs.readFile(path.join(__dirname, 'dump.vcd'), function (err, src) {
|
||||||
|
// if (err) {
|
||||||
|
// throw new Error(err);
|
||||||
|
// }
|
||||||
|
// const inst = parser();
|
||||||
|
// const dump = [];
|
||||||
|
// ['"}G', '{u', 'u)'] // array of all signal ids
|
||||||
|
// .map(id =>
|
||||||
|
// inst.change.on(id, (time, cmd, value, mask) => {
|
||||||
|
// const row = {
|
||||||
|
// id,
|
||||||
|
// time: BigInt(time),
|
||||||
|
// cmd,
|
||||||
|
// value,
|
||||||
|
// mask
|
||||||
|
// };
|
||||||
|
// dump.push(row);
|
||||||
|
// // console.log(row);
|
||||||
|
// })
|
||||||
|
// );
|
||||||
|
|
||||||
|
// inst.on('finish', () => {
|
||||||
|
// expect(inst.getTime()).to.eq(316n);
|
||||||
|
// expect(dump).to.deep.eq(expectaitions);
|
||||||
|
// done();
|
||||||
|
// });
|
||||||
|
|
||||||
|
// for (const chunk of chopper(src, 100)) {
|
||||||
|
// // console.log('\u001b[31m[\u001b[0m' + chunk.toString() + '\u001b[31m]\u001b[0m');
|
||||||
|
// inst.write(chunk);
|
||||||
|
// }
|
||||||
|
// inst.end();
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
|
||||||
|
// /* eslint-env mocha */
|
79
backup/napi_events.js
Normal file
79
backup/napi_events.js
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
// 'use strict';
|
||||||
|
|
||||||
|
// const expect = require('chai').expect;
|
||||||
|
// const parser = require('../lib/parser.js');
|
||||||
|
|
||||||
|
// describe('events', () => {
|
||||||
|
|
||||||
|
// it('$enddefinitions', done => {
|
||||||
|
// const inst = parser();
|
||||||
|
// inst.on('$enddefinitions', () => {
|
||||||
|
// expect(inst.info).to.deep.eq({
|
||||||
|
// status: 'simulation',
|
||||||
|
// date: ' Wed Sep 18 22:59:07 2019\n ',
|
||||||
|
// version: ' Generated by VerilatedVcd ',
|
||||||
|
// timescale: ' 1ns ',
|
||||||
|
// varId: 'u)',
|
||||||
|
// wires: {
|
||||||
|
// top: {
|
||||||
|
// clock: '"}G',
|
||||||
|
// fruit: {
|
||||||
|
// point: 'u)'
|
||||||
|
// },
|
||||||
|
// leaf: {
|
||||||
|
// counter: '{u'
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// stack: [{
|
||||||
|
// top: {
|
||||||
|
// clock: '"}G',
|
||||||
|
// fruit: {
|
||||||
|
// point: 'u)'
|
||||||
|
// },
|
||||||
|
// leaf: {
|
||||||
|
// counter: '{u'
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// clock: '"}G',
|
||||||
|
// fruit: {
|
||||||
|
// point: 'u)'
|
||||||
|
// },
|
||||||
|
// leaf: {
|
||||||
|
// counter: '{u'
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// point: 'u)'
|
||||||
|
// }]
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
// expect(inst.write(`
|
||||||
|
// $version Generated by VerilatedVcd $end
|
||||||
|
// $date Wed Sep 18 22:59:07 2019
|
||||||
|
// $end
|
||||||
|
// $timescale 1ns $end
|
||||||
|
|
||||||
|
// $scope module top $end
|
||||||
|
// $var wire 1 "}G clock $end
|
||||||
|
// $scope module leaf $end
|
||||||
|
// $var wire 64 {u counter [63:0] $end
|
||||||
|
// $upscope $end
|
||||||
|
// $scope module fruit $end
|
||||||
|
// $var wire 4 u) point [3:0] $end
|
||||||
|
// $upscope $end
|
||||||
|
// $upscope $end
|
||||||
|
|
||||||
|
// $enddefinitions $end
|
||||||
|
// `
|
||||||
|
// )).to.eq(true);
|
||||||
|
|
||||||
|
// done();
|
||||||
|
// });
|
||||||
|
|
||||||
|
|
||||||
|
// });
|
||||||
|
|
||||||
|
// /* eslint-env mocha */
|
72
backup/wasm_any.js
Normal file
72
backup/wasm_any.js
Normal file
File diff suppressed because one or more lines are too long
135
backup/wasm_basic.js
Normal file
135
backup/wasm_basic.js
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
// 'use strict';
|
||||||
|
// /* eslint-disable no-console */
|
||||||
|
// /* eslint-disable indent */
|
||||||
|
// /* eslint-disable no-unused-vars */
|
||||||
|
|
||||||
|
// const expect = require('chai').expect;
|
||||||
|
// const createVCD = require('../out/vcd.js');
|
||||||
|
// const webVcdParser = require('../lib/web-vcd-parser.js');
|
||||||
|
|
||||||
|
// describe('wasm basic', () => {
|
||||||
|
|
||||||
|
// it('typeof vcd', async function () {
|
||||||
|
// const mod = await createVCD();
|
||||||
|
// expect(mod).to.be.an('object');
|
||||||
|
// });
|
||||||
|
|
||||||
|
// it('typeof vcd instance', async function () {
|
||||||
|
// const mod = await createVCD();
|
||||||
|
// const inst = await webVcdParser(mod);
|
||||||
|
// expect(inst).to.be.an('object');
|
||||||
|
// });
|
||||||
|
|
||||||
|
// it('fail: foo bar', async function () {
|
||||||
|
// const mod = await createVCD();
|
||||||
|
// const inst = await webVcdParser(mod);
|
||||||
|
// expect(inst.write(Buffer.from(' foo bar ???'))).to.eq(true);
|
||||||
|
// expect(inst.info).to.deep.eq({
|
||||||
|
// stack: [{}],
|
||||||
|
// status: 'declaration',
|
||||||
|
// wires: {}
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
|
||||||
|
// it('$comment', async function () {
|
||||||
|
// const mod = await createVCD();
|
||||||
|
// const inst = await webVcdParser(mod);
|
||||||
|
// expect(inst.write(Buffer.from(
|
||||||
|
// ' \n $comment some text $end $comment more text $end ???'
|
||||||
|
// ))).to.eq(true);
|
||||||
|
// expect(inst.info).to.deep.eq({
|
||||||
|
// comment: ' more text ',
|
||||||
|
// stack: [{}],
|
||||||
|
// status: 'declaration',
|
||||||
|
// wires: {}
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
|
||||||
|
// it('$version', async function () {
|
||||||
|
// const mod = await createVCD();
|
||||||
|
// const inst = await webVcdParser(mod);
|
||||||
|
// expect(inst.write(`
|
||||||
|
// $version Generated by VerilatedVcd $end
|
||||||
|
// $date Wed Sep 18 22:59:07 2019
|
||||||
|
// $end
|
||||||
|
// $timescale 1ns $end
|
||||||
|
|
||||||
|
// $scope module top $end
|
||||||
|
// $var wire 1 "}G clock $end
|
||||||
|
// $scope module leaf $end
|
||||||
|
// $var wire 64 {u counter [63:0] $end
|
||||||
|
// $upscope $end
|
||||||
|
// $scope module fruit $end
|
||||||
|
// $var wire 4 u) point [3:0] $end
|
||||||
|
// $upscope $end
|
||||||
|
// $upscope $end
|
||||||
|
|
||||||
|
// $enddefinitions $end
|
||||||
|
// `
|
||||||
|
// )).to.eq(true);
|
||||||
|
|
||||||
|
// expect(inst.write(`
|
||||||
|
|
||||||
|
// #1
|
||||||
|
// 0"}G
|
||||||
|
// #2
|
||||||
|
// 1"}G
|
||||||
|
// #300
|
||||||
|
// 0"}G
|
||||||
|
// b1111000000000000 {u
|
||||||
|
// #301
|
||||||
|
// b0000111100000000 {u
|
||||||
|
// #302
|
||||||
|
// b0000000011110000 {u
|
||||||
|
// #303
|
||||||
|
// b0000000000001111 {u
|
||||||
|
// `
|
||||||
|
// )).to.eq(true);
|
||||||
|
|
||||||
|
// expect(inst.info).to.deep.eq({
|
||||||
|
// status: 'simulation',
|
||||||
|
// date: ' Wed Sep 18 22:59:07 2019\n ',
|
||||||
|
// version: ' Generated by VerilatedVcd ',
|
||||||
|
// timescale: ' 1ns ',
|
||||||
|
// t0: 1,
|
||||||
|
// varId: 'u)',
|
||||||
|
// wires: {
|
||||||
|
// top: {
|
||||||
|
// clock: '"}G',
|
||||||
|
// fruit: {
|
||||||
|
// point: 'u)'
|
||||||
|
// },
|
||||||
|
// leaf: {
|
||||||
|
// counter: '{u'
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// stack: [{
|
||||||
|
// top: {
|
||||||
|
// clock: '"}G',
|
||||||
|
// fruit: {
|
||||||
|
// point: 'u)'
|
||||||
|
// },
|
||||||
|
// leaf: {
|
||||||
|
// counter: '{u'
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// clock: '"}G',
|
||||||
|
// fruit: {
|
||||||
|
// point: 'u)'
|
||||||
|
// },
|
||||||
|
// leaf: {
|
||||||
|
// counter: '{u'
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// point: 'u)'
|
||||||
|
// }]
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
|
||||||
|
// });
|
||||||
|
|
||||||
|
// /* eslint-env mocha */
|
98
backup/wasm_dump.js
Normal file
98
backup/wasm_dump.js
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
// 'use strict';
|
||||||
|
// /* eslint-disable no-console */
|
||||||
|
// /* eslint-disable indent */
|
||||||
|
// /* eslint-disable no-unused-vars */
|
||||||
|
|
||||||
|
// const fs = require('fs');
|
||||||
|
// const path = require('path');
|
||||||
|
|
||||||
|
// const expect = require('chai').expect;
|
||||||
|
// const createVCD = require('../out/vcd.js');
|
||||||
|
// const webVcdParser = require('../lib/web-vcd-parser.js');
|
||||||
|
// const chopper = require('../lib/chopper.js');
|
||||||
|
|
||||||
|
// const expectaitions = [
|
||||||
|
// { id: '"}G', time: 100n, cmd: 14, value: undefined, mask: undefined },
|
||||||
|
// { id: '"}G', time: 200n, cmd: 15, value: undefined, mask: undefined },
|
||||||
|
// { id: '{u', time: 200n, cmd: 30, value: 0xf0f0f0f0f0f0f0f0n, mask: 0xff00ff00ff00ff00n },
|
||||||
|
// { id: '"}G', time: 300n, cmd: 14, value: undefined, mask: undefined },
|
||||||
|
// { id: '{u', time: 300n, cmd: 30, value: 0xf000000000000000n, mask: 0n },
|
||||||
|
// { id: 'u)', time: 300n, cmd: 30, value: 0n, mask: 0n },
|
||||||
|
// { id: '{u', time: 301n, cmd: 30, value: 0x0f00000000000000n, mask: 0n },
|
||||||
|
// { id: 'u)', time: 301n, cmd: 30, value: 1n, mask: 0n },
|
||||||
|
// { id: '{u', time: 302n, cmd: 30, value: 0x00f0000000000000n, mask: 0n },
|
||||||
|
// { id: 'u)', time: 302n, cmd: 30, value: 2n, mask: 0n },
|
||||||
|
// { id: '{u', time: 303n, cmd: 30, value: 0x000f000000000000n, mask: 0n },
|
||||||
|
// { id: 'u)', time: 303n, cmd: 30, value: 3n, mask: 0n },
|
||||||
|
// { id: '{u', time: 304n, cmd: 30, value: 0x0000f00000000000n, mask: 0n },
|
||||||
|
// { id: 'u)', time: 304n, cmd: 30, value: 4n, mask: 0n },
|
||||||
|
// { id: '{u', time: 305n, cmd: 30, value: 0x00000f0000000000n, mask: 0n },
|
||||||
|
// { id: 'u)', time: 305n, cmd: 30, value: 5n, mask: 0n },
|
||||||
|
// { id: '{u', time: 306n, cmd: 30, value: 0x000000f000000000n, mask: 0n },
|
||||||
|
// { id: 'u)', time: 306n, cmd: 30, value: 6n, mask: 0n },
|
||||||
|
// { id: '{u', time: 307n, cmd: 30, value: 0x0000000f00000000n, mask: 0n },
|
||||||
|
// { id: 'u)', time: 307n, cmd: 30, value: 7n, mask: 0n },
|
||||||
|
// { id: '{u', time: 308n, cmd: 31, value: 0x00000000f0000000n, mask: 0n },
|
||||||
|
// { id: 'u)', time: 308n, cmd: 30, value: 8n, mask: 0n },
|
||||||
|
// { id: '{u', time: 309n, cmd: 30, value: 0x000000000f000000n, mask: 0n },
|
||||||
|
// { id: 'u)', time: 309n, cmd: 30, value: 9n, mask: 0n },
|
||||||
|
// { id: '{u', time: 310n, cmd: 30, value: 0x0000000000f00000n, mask: 0n },
|
||||||
|
// { id: 'u)', time: 310n, cmd: 30, value: 10n, mask: 0n },
|
||||||
|
// { id: '{u', time: 311n, cmd: 30, value: 0x00000000000f0000n, mask: 0n },
|
||||||
|
// { id: 'u)', time: 311n, cmd: 30, value: 11n, mask: 0n },
|
||||||
|
// { id: '{u', time: 312n, cmd: 30, value: 0x000000000000f000n, mask: 0n },
|
||||||
|
// { id: 'u)', time: 312n, cmd: 30, value: 12n, mask: 0n },
|
||||||
|
// { id: '{u', time: 313n, cmd: 30, value: 0x0000000000000f00n, mask: 0n },
|
||||||
|
// { id: 'u)', time: 313n, cmd: 30, value: 13n, mask: 0n },
|
||||||
|
// { id: '{u', time: 314n, cmd: 30, value: 0x00000000000000f0n, mask: 0n },
|
||||||
|
// { id: 'u)', time: 314n, cmd: 30, value: 14n, mask: 0n },
|
||||||
|
// { id: '{u', time: 315n, cmd: 30, value: 0x000000000000000fn, mask: 0n },
|
||||||
|
// { id: 'u)', time: 315n, cmd: 30, value: 15n, mask: 0n },
|
||||||
|
// { id: '"}G', time: 316n, cmd: 15, value: undefined, mask: undefined }
|
||||||
|
// ];
|
||||||
|
|
||||||
|
// describe('wasm dump', () => {
|
||||||
|
// it('simple wasm', done => {
|
||||||
|
// fs.readFile(path.join(__dirname, 'dump.vcd'), function (err, src) {
|
||||||
|
// if (err) {
|
||||||
|
// throw new Error(err);
|
||||||
|
// }
|
||||||
|
// createVCD().then((mod) => {
|
||||||
|
// webVcdParser(mod).then((inst) => {
|
||||||
|
// const dump = [];
|
||||||
|
// ['"}G', '{u', 'u)'] // array of all signal ids
|
||||||
|
// .map(id =>
|
||||||
|
// inst.change.on(id, (time, cmd, value, mask) => {
|
||||||
|
// const row = {
|
||||||
|
// id,
|
||||||
|
// time,
|
||||||
|
// cmd,
|
||||||
|
// value,
|
||||||
|
// mask
|
||||||
|
// };
|
||||||
|
// dump.push(row);
|
||||||
|
// // console.log(row);
|
||||||
|
// })
|
||||||
|
// );
|
||||||
|
|
||||||
|
// inst.on('finish', () => {
|
||||||
|
// expect(inst.getTime()).to.eq(316n);
|
||||||
|
// // console.log(dump);
|
||||||
|
// // expect(dump.length).to.eq(expectaitions.length);
|
||||||
|
// expect(dump).to.deep.eq(expectaitions);
|
||||||
|
// done();
|
||||||
|
// });
|
||||||
|
// const step = (Math.random() * 500) |0;
|
||||||
|
// for (const chunk of chopper(src, step)) {
|
||||||
|
// // console.log('\n\u001b[31m[\u001b[0m' + chunk.toString() + '\u001b[31m](\u001b[0m\n' + chunk.length + '\u001b[31m)\u001b[0m\n');
|
||||||
|
// inst.write(chunk);
|
||||||
|
// }
|
||||||
|
// inst.end();
|
||||||
|
// // console.log(step);
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
|
||||||
|
// /* eslint-env mocha */
|
83
backup/wasm_events.js
Normal file
83
backup/wasm_events.js
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
// 'use strict';
|
||||||
|
// /* eslint-disable no-console */
|
||||||
|
// /* eslint-disable indent */
|
||||||
|
// /* eslint-disable no-unused-vars */
|
||||||
|
|
||||||
|
// const expect = require('chai').expect;
|
||||||
|
// const createVCD = require('../out/vcd.js');
|
||||||
|
// const webVcdParser = require('../lib/web-vcd-parser.js');
|
||||||
|
|
||||||
|
// describe('wasm events', () => {
|
||||||
|
|
||||||
|
// it('$enddefinitions', async function () {
|
||||||
|
// const mod = await createVCD();
|
||||||
|
// const inst = await webVcdParser(mod);
|
||||||
|
|
||||||
|
// inst.on('$enddefinitions', () => {
|
||||||
|
// expect(inst.info).to.deep.eq({
|
||||||
|
// status: 'simulation',
|
||||||
|
// timescale: ' 1ns ',
|
||||||
|
// date: ' Wed Sep 18 22:59:07 2019\n ',
|
||||||
|
// version: ' Generated by VerilatedVcd ',
|
||||||
|
// varId: 'u)',
|
||||||
|
// wires: {
|
||||||
|
// top: {
|
||||||
|
// clock: '"}G',
|
||||||
|
// fruit: {
|
||||||
|
// point: 'u)'
|
||||||
|
// },
|
||||||
|
// leaf: {
|
||||||
|
// counter: '{u'
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// stack: [{
|
||||||
|
// top: {
|
||||||
|
// clock: '"}G',
|
||||||
|
// fruit: {
|
||||||
|
// point: 'u)'
|
||||||
|
// },
|
||||||
|
// leaf: {
|
||||||
|
// counter: '{u'
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// clock: '"}G',
|
||||||
|
// fruit: {
|
||||||
|
// point: 'u)'
|
||||||
|
// },
|
||||||
|
// leaf: {
|
||||||
|
// counter: '{u'
|
||||||
|
// }
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// point: 'u)'
|
||||||
|
// }]
|
||||||
|
// });
|
||||||
|
// });
|
||||||
|
// expect(inst.write(`
|
||||||
|
// $version Generated by VerilatedVcd $end
|
||||||
|
// $date Wed Sep 18 22:59:07 2019
|
||||||
|
// $end
|
||||||
|
// $timescale 1ns $end
|
||||||
|
|
||||||
|
// $scope module top $end
|
||||||
|
// $var wire 1 "}G clock $end
|
||||||
|
// $scope module leaf $end
|
||||||
|
// $var wire 64 {u counter [63:0] $end
|
||||||
|
// $upscope $end
|
||||||
|
// $scope module fruit $end
|
||||||
|
// $var wire 4 u) point [3:0] $end
|
||||||
|
// $upscope $end
|
||||||
|
// $upscope $end
|
||||||
|
|
||||||
|
// $enddefinitions $end
|
||||||
|
// `
|
||||||
|
// )).to.eq(true);
|
||||||
|
// });
|
||||||
|
|
||||||
|
|
||||||
|
// });
|
||||||
|
|
||||||
|
// /* eslint-env mocha */
|
44
bin/build.js
44
bin/build.js
@ -1,5 +1,6 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console */
|
||||||
|
/* eslint-disable indent */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
@ -137,48 +138,12 @@ const generate = (cb) => {
|
|||||||
|
|
||||||
declaration
|
declaration
|
||||||
.match(spaces, declaration)
|
.match(spaces, declaration)
|
||||||
// .select(cmd('$scope'),
|
|
||||||
// p.invoke(p.code.store('command'), commandSpan.start(scopeType)))
|
|
||||||
// .select(cmd('$var'),
|
|
||||||
// p.invoke(p.code.store('command'), commandSpan.start(varType)))
|
|
||||||
.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)))
|
p.invoke(p.code.store('command'), commandSpan.start(inDeclaration)))
|
||||||
.select(cmd('$enddefinitions'),
|
.select(cmd('$enddefinitions'),
|
||||||
p.invoke(p.code.store('command'), commandSpan.start(enddefinitions)))
|
p.invoke(p.code.store('command'), commandSpan.start(enddefinitions)))
|
||||||
.otherwise(p.error(1, 'Expected declaration command'));
|
.otherwise(p.error(1, 'Expected declaration command'));
|
||||||
|
|
||||||
// $scope module clkdiv2n_tb $end
|
|
||||||
// ^^^^^^
|
|
||||||
|
|
||||||
// scopeType.match(spaces, scopeType).otherwise(scopeTypeEnd);
|
|
||||||
// scopeTypeEnd
|
|
||||||
// .select(
|
|
||||||
// {
|
|
||||||
// module: 0,
|
|
||||||
// task: 1,
|
|
||||||
// function: 2,
|
|
||||||
// begin: 3,
|
|
||||||
// fork: 4,
|
|
||||||
// // extra scopes from Verilator
|
|
||||||
// generate: 5,
|
|
||||||
// struct: 6,
|
|
||||||
// union: 7,
|
|
||||||
// class: 8,
|
|
||||||
// interface: 9,
|
|
||||||
// package: 10,
|
|
||||||
// program: 11
|
|
||||||
// },
|
|
||||||
// p.invoke(p.code.store('type'), scopeIdentifier))
|
|
||||||
// .otherwise(p.error(2, 'Expected scope type'));
|
|
||||||
|
|
||||||
// $scope module clkdiv2n_tb $end
|
|
||||||
// ^^^^^^^^^^^
|
|
||||||
|
|
||||||
// scopeIdentifier.match(spaces, scopeIdentifier).otherwise(scopeIdentifierSpan.start(scopeIdentifierEnd));
|
|
||||||
// scopeIdentifierEnd.match(spaces, scopeIdentifierSpan.end(inDeclaration)).skipTo(scopeIdentifierEnd);
|
|
||||||
|
|
||||||
// $var reg 3 ( r_reg [2:0] $end
|
|
||||||
// ^^^
|
|
||||||
|
|
||||||
varType.match(spaces, varType).otherwise(varTypeEnd);
|
varType.match(spaces, varType).otherwise(varTypeEnd);
|
||||||
varTypeEnd
|
varTypeEnd
|
||||||
@ -233,8 +198,8 @@ const generate = (cb) => {
|
|||||||
.skipTo(enddefinitions);
|
.skipTo(enddefinitions);
|
||||||
|
|
||||||
simulation
|
simulation
|
||||||
.match([' ', '\r', '\n', '\t', '$dumpvars', '$end'], simulation)
|
.match([' ', '\r', '\n', '\t', '$dumpvars', '$dumpall', '$end'], simulation)
|
||||||
.select(cmd('$dumpall $dumpoff $dumpon $comment'),
|
.select(cmd('$dumpoff $dumpon $comment'),
|
||||||
p.invoke(p.code.store('command'), commandSpan.start(inSimulation)))
|
p.invoke(p.code.store('command'), commandSpan.start(inSimulation)))
|
||||||
.select(cmd('#'),
|
.select(cmd('#'),
|
||||||
p.invoke(p.code.store('command'), timeSpan.start(simulationTime)))
|
p.invoke(p.code.store('command'), timeSpan.start(simulationTime)))
|
||||||
@ -304,9 +269,12 @@ const generate = (cb) => {
|
|||||||
// const dot = new llparseDot.Dot();
|
// const dot = new llparseDot.Dot();
|
||||||
// fs.writeFileSync(prj + '.dot', dot.build(declaration));
|
// fs.writeFileSync(prj + '.dot', dot.build(declaration));
|
||||||
|
|
||||||
|
if (cb) {
|
||||||
cb();
|
cb();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
generate(gyp);
|
generate(gyp);
|
||||||
|
// generate();
|
||||||
|
|
||||||
/* eslint camelcase: 0 */
|
/* eslint camelcase: 0 */
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
'use strict';
|
'use strict';
|
||||||
|
/* eslint-disable no-console */
|
||||||
|
/* eslint-disable indent */
|
||||||
|
|
||||||
const fs = require('fs-extra');
|
const fs = require('fs-extra');
|
||||||
const async = require('async');
|
const async = require('async');
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
'use strict';
|
'use strict';
|
||||||
|
/* eslint-disable no-console */
|
||||||
|
/* eslint-disable indent */
|
||||||
|
|
||||||
const $version = () => '$version Generated by VerilatedVcd $end\n';
|
const $version = () => '$version Generated by VerilatedVcd $end\n';
|
||||||
|
|
||||||
|
217
bin/vcd.js
217
bin/vcd.js
@ -4,10 +4,217 @@
|
|||||||
const createVCD = require('../out/vcd.js');
|
const createVCD = require('../out/vcd.js');
|
||||||
const webVcdParser = require('../lib/web-vcd-parser.js');
|
const webVcdParser = require('../lib/web-vcd-parser.js');
|
||||||
|
|
||||||
async function getVcdStream() {
|
/**
|
||||||
const wasm = await createVCD();
|
* @typedef {{ maxChunkLength: number, useGcd: boolean }} consumeConfig
|
||||||
const ostream = await webVcdParser(wasm);
|
*
|
||||||
return ostream;
|
* @typedef {{ kind: string, wave: number[] }} vcdValue
|
||||||
|
*
|
||||||
|
* @typedef {Object} VarSignal
|
||||||
|
* @property { 'var' } kind
|
||||||
|
* @property { 'event' | 'integer' | 'parameter' | 'real' | 'realtime' | 'reg' | 'supply0' | 'supply1' | 'time' | 'tri' | 'triand' | 'trior' | 'trireg' | 'tri0' | 'tri1' | 'wand' | 'wire' | 'wor' | 'string' } type
|
||||||
|
* @property {string} name 信号的真实名字
|
||||||
|
* @property {string} link 信号的 id
|
||||||
|
* @property {number} size 位宽
|
||||||
|
*
|
||||||
|
* @typedef {Object} ScopeSignal
|
||||||
|
* @property { 'scope' } kind
|
||||||
|
* @property { 'module' | 'begin' | 'fork' | 'function' | 'task' } type
|
||||||
|
* @property {string} name
|
||||||
|
* @property {ScopeSignal[]} body
|
||||||
|
*
|
||||||
|
* @typedef { VarSignal | ScopeSignal } VcdSignal
|
||||||
|
*
|
||||||
|
* @typedef {Object} VcdInfo
|
||||||
|
* @property {number} t0
|
||||||
|
* @property {string} timescale
|
||||||
|
* @property {string} version
|
||||||
|
* @property {string} date
|
||||||
|
* @property {string} status
|
||||||
|
* @property {VcdSignal} wires
|
||||||
|
*
|
||||||
|
* @typedef {Object} VcdBasicInfo
|
||||||
|
* @property {number} time
|
||||||
|
* @property {number} tgcd
|
||||||
|
* @property {VcdInfo} vcdInfo
|
||||||
|
* @property {any} signalValues
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 结果变量
|
||||||
|
const vcdBasicInfo = {
|
||||||
|
signalValues: {},
|
||||||
|
vcdInfo: undefined,
|
||||||
|
tgcd: undefined,
|
||||||
|
time: undefined
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {number} a
|
||||||
|
* @param {number} b
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
function gcd(a, b) {
|
||||||
|
if (a === undefined) {
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
let r;
|
||||||
|
while (b !== 0) {
|
||||||
|
r = a % b;
|
||||||
|
a = b;
|
||||||
|
b = r;
|
||||||
|
}
|
||||||
|
return (a < 0) ? -a : a;
|
||||||
}
|
}
|
||||||
|
|
||||||
window.getVcdStream = getVcdStream;
|
const MAX_SAFE_INTEGER = BigInt(Number.MAX_SAFE_INTEGER);
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {BigInt} val
|
||||||
|
* @returns {string | number}
|
||||||
|
*/
|
||||||
|
function numberOrString(val) {
|
||||||
|
if (val < MAX_SAFE_INTEGER) {
|
||||||
|
return Number(val);
|
||||||
|
}
|
||||||
|
const stringNumber = '0x' + val.toString(16);
|
||||||
|
return stringNumber;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {string} timescale
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
function parseTimescale(timescale) {
|
||||||
|
if (typeof timescale !== 'string') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const str1 = timescale.trim();
|
||||||
|
const m = str1.match(/^(\d+)\s*(\w+)$/);
|
||||||
|
const res1 = ({ 1: 0, 10: 1, 100: 2 })[m[1]];
|
||||||
|
const res2 = ({ s: 0, ms: -3, us: -6, ns: -9, ps: -12, fs: -15 })[m[2]];
|
||||||
|
return res1 + res2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @returns {{
|
||||||
|
* write: (piece: Uint8Array) => void
|
||||||
|
* consume: (arraybuffer: ArrayBuffer, config?: consumeConfig) => void
|
||||||
|
* getBasicInfo: () => VcdBasicInfo
|
||||||
|
* }}
|
||||||
|
*/
|
||||||
|
async function makeVcdStream() {
|
||||||
|
const vcdstream = await getVcdStream();
|
||||||
|
// 使用 vcdstream 的 any 回调获取波形数据,并按照正确的格式进行解码和存储
|
||||||
|
// 这段处理来自 https://github.com/wavedrom/vcd 的 vcd-pipe-deso.js 的 58 行
|
||||||
|
// 请严格对准转换规则
|
||||||
|
vcdstream.change.any((id, time, cmd, value, mask) => {
|
||||||
|
const time53 = Number(time);
|
||||||
|
vcdBasicInfo.tgcd = gcd(vcdBasicInfo.tgcd, time53);
|
||||||
|
vcdBasicInfo.signalValues[id] = vcdBasicInfo.signalValues[id] || { kind: '', wave: [] };
|
||||||
|
|
||||||
|
// if (id === 'x#') {
|
||||||
|
// console.log(id, time, cmd, value, mask);
|
||||||
|
// console.log(time > MAX_SAFE_INTEGER);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// TODO: 解决这个问题,有关 parameter 参数读取
|
||||||
|
if (time > MAX_SAFE_INTEGER) {
|
||||||
|
vcdBasicInfo.signalValues[id].wave = [[0, Number(value)]];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cmd >= 14 && cmd <= 28) {
|
||||||
|
vcdBasicInfo.signalValues[id].kind = 'bit';
|
||||||
|
vcdBasicInfo.signalValues[id].wave.push([time53, cmd - 14]);
|
||||||
|
} else {
|
||||||
|
vcdBasicInfo.signalValues[id].kind = 'vec';
|
||||||
|
const point = [time53, numberOrString(value)];
|
||||||
|
if (mask !== 0n) {
|
||||||
|
point.push(numberOrString(mask));
|
||||||
|
}
|
||||||
|
vcdBasicInfo.signalValues[id].wave.push(point);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
vcdstream.consume = (arraybuffer, config) => {
|
||||||
|
return consume(vcdstream, arraybuffer, config);
|
||||||
|
};
|
||||||
|
|
||||||
|
vcdstream.getBasicInfo = () => {
|
||||||
|
return vcdBasicInfo;
|
||||||
|
};
|
||||||
|
|
||||||
|
return vcdstream;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {ArrayBuffer} arraybuffer
|
||||||
|
* @param {consumeConfig} config
|
||||||
|
*/
|
||||||
|
function consume(vcdstream, arraybuffer, config) {
|
||||||
|
config = config || { maxChunkLength: 1 << 17, useGcd: true };
|
||||||
|
|
||||||
|
const maxChunkLength = config.maxChunkLength;
|
||||||
|
const uint8array = new Uint8Array(arraybuffer);
|
||||||
|
for (let i = 0; i < uint8array.length; i += maxChunkLength) {
|
||||||
|
const piece = uint8array.slice(i, i + maxChunkLength);
|
||||||
|
vcdstream.write(piece);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 装载信息
|
||||||
|
if (vcdBasicInfo.time === undefined) {
|
||||||
|
vcdBasicInfo.time = Number(vcdstream.getTime());
|
||||||
|
}
|
||||||
|
if (vcdBasicInfo.vcdInfo === undefined) {
|
||||||
|
vcdBasicInfo.vcdInfo = vcdstream.info;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 通过 gcd 来缩放时间
|
||||||
|
const tgcd = vcdBasicInfo.tgcd;
|
||||||
|
const signalValues = vcdBasicInfo.signalValues;
|
||||||
|
|
||||||
|
vcdBasicInfo.time /= tgcd;
|
||||||
|
vcdBasicInfo.vcdInfo.t0 /= tgcd;
|
||||||
|
vcdBasicInfo.vcdInfo.timescale = parseTimescale(vcdBasicInfo.vcdInfo.timescale);
|
||||||
|
|
||||||
|
for (const id of Object.keys(signalValues)) {
|
||||||
|
// point[0] 是当前这个点的时间点
|
||||||
|
signalValues[id].wave.map(point => { point[0] /= tgcd });
|
||||||
|
}
|
||||||
|
|
||||||
|
const exp = Math.log10(tgcd) | 0;
|
||||||
|
if (exp > 0) {
|
||||||
|
const scale = Math.pow(10, exp);
|
||||||
|
const scaleGcd = tgcd / scale;
|
||||||
|
if (scaleGcd === (scaleGcd | 0)) {
|
||||||
|
vcdBasicInfo.tgcd = scaleGcd;
|
||||||
|
vcdBasicInfo.vcdInfo.timescale += exp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getVcdStream() {
|
||||||
|
const wasm = await createVCD();
|
||||||
|
const vcdstream = await webVcdParser(wasm);
|
||||||
|
return vcdstream;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试时关闭该函数
|
||||||
|
// 部署时激活该函数
|
||||||
|
try {
|
||||||
|
if (self) {
|
||||||
|
self.getVcdStream = getVcdStream;
|
||||||
|
self.makeVcdStream = makeVcdStream;
|
||||||
|
self.vcdBasicInfo = vcdBasicInfo;
|
||||||
|
}
|
||||||
|
} catch (error) {}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getVcdStream,
|
||||||
|
makeVcdStream,
|
||||||
|
vcdBasicInfo
|
||||||
|
};
|
4
deploy.sh
Normal file
4
deploy.sh
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
browserify ./bin/vcd.js | terser --compress -o ./out/vcd-web.js
|
||||||
|
sed -i -e 's/wasmBinaryFile=Module.locateFile?Module.locateFile(path,scriptDirectory):scriptDirectory+path/wasmBinaryFile=self.location.href.replace("worker.js", "vcd.wasm")/g' out/vcd-web.js
|
||||||
|
cp out/vcd-web.js $1/public/vcd.js
|
||||||
|
cp out/vcd.wasm $1/public/vcd.wasm
|
3
install.sh
Normal file
3
install.sh
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
source $EMCC_HOME/emsdk_env.sh
|
||||||
|
npm install browserify terser node-gyp -g
|
||||||
|
npm i
|
@ -1,4 +1,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
/* eslint-disable no-console */
|
||||||
|
/* eslint-disable indent */
|
||||||
|
|
||||||
module.exports = skip => {
|
module.exports = skip => {
|
||||||
let start = 0;
|
let start = 0;
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
/* eslint-disable no-console */
|
||||||
|
/* eslint-disable indent */
|
||||||
|
|
||||||
const handleScope = (info, str) => {
|
const handleScope = (info, str) => {
|
||||||
const [type, name] = str.split(/\s+/);
|
const [type, name] = str.split(/\s+/);
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
/* eslint-disable no-console */
|
||||||
|
/* eslint-disable indent */
|
||||||
|
|
||||||
const stream = require('stream');
|
const stream = require('stream');
|
||||||
const EventEmitter = require('events').EventEmitter;
|
const EventEmitter = require('events').EventEmitter;
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
/* eslint-disable no-console */
|
||||||
|
/* eslint-disable indent */
|
||||||
|
|
||||||
const parseTimescale = require('./parse-time-scale.js');
|
const parseTimescale = require('./parse-time-scale.js');
|
||||||
|
|
||||||
|
@ -1,4 +1,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
/* eslint-disable no-console */
|
||||||
|
/* eslint-disable indent */
|
||||||
|
/* eslint-disable no-unused-vars */
|
||||||
|
|
||||||
const stream = require('stream');
|
const stream = require('stream');
|
||||||
const EventEmitter = require('events').EventEmitter;
|
const EventEmitter = require('events').EventEmitter;
|
||||||
|
12
out/vcd-web.js
Normal file
12
out/vcd-web.js
Normal file
File diff suppressed because one or more lines are too long
31
out/vcd.js
31
out/vcd.js
File diff suppressed because one or more lines are too long
BIN
out/vcd.wasm
BIN
out/vcd.wasm
Binary file not shown.
@ -9,7 +9,7 @@
|
|||||||
"nyc_mocha_napi": "nyc -r=text -r=lcov mocha test/napi_* ",
|
"nyc_mocha_napi": "nyc -r=text -r=lcov mocha test/napi_* ",
|
||||||
"nyc_mocha_wasm": "nyc -r=text -r=lcov mocha test/wasm_*",
|
"nyc_mocha_wasm": "nyc -r=text -r=lcov mocha test/wasm_*",
|
||||||
"nyc_mocha": "nyc -r=text -r=lcov mocha",
|
"nyc_mocha": "nyc -r=text -r=lcov mocha",
|
||||||
"test": "eslint bin lib test && npm run nyc_mocha",
|
"test": "npm run nyc_mocha",
|
||||||
"testonly": "nyc -r=text -r=lcov mocha",
|
"testonly": "nyc -r=text -r=lcov mocha",
|
||||||
"watch": "mocha --watch",
|
"watch": "mocha --watch",
|
||||||
"build.web": "browserify ./lib/vcd-web.js | terser --compress -o demo/vcd-web.min.js",
|
"build.web": "browserify ./lib/vcd-web.js | terser --compress -o demo/vcd-web.min.js",
|
||||||
|
9
test/debug/base.vcd
Normal file
9
test/debug/base.vcd
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
$date
|
||||||
|
Thu Jul 22 22:29:56 2021
|
||||||
|
$end
|
||||||
|
$version
|
||||||
|
Icarus Verilog
|
||||||
|
$end
|
||||||
|
$timescale
|
||||||
|
1ps
|
||||||
|
$end
|
18
test/debug/basic.js
Normal file
18
test/debug/basic.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
'use strict';
|
||||||
|
/* eslint-disable no-console */
|
||||||
|
/* eslint-disable indent */
|
||||||
|
/* eslint-disable no-unused-vars */
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
const { makeVcdStream } = require('../../bin/vcd');
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
const arraybuffer = fs.readFileSync('./test/debug/pe_tb.vcd');
|
||||||
|
const vcdstream = await makeVcdStream();
|
||||||
|
vcdstream.consume(arraybuffer);
|
||||||
|
const info = vcdstream.getBasicInfo();
|
||||||
|
console.log(info.signalValues['*']);
|
||||||
|
}
|
||||||
|
|
||||||
|
main();
|
1586309
test/debug/pe_tb.vcd
Normal file
1586309
test/debug/pe_tb.vcd
Normal file
File diff suppressed because it is too large
Load Diff
9529
test/debug/small.vcd
Normal file
9529
test/debug/small.vcd
Normal file
File diff suppressed because it is too large
Load Diff
30
test/debug/verilater.vcd
Normal file
30
test/debug/verilater.vcd
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
$version Generated by VerilatedVcd $end
|
||||||
|
$date Wed Sep 18 22:59:07 2019
|
||||||
|
$end
|
||||||
|
$timescale 1ns $end
|
||||||
|
|
||||||
|
$scope module top $end
|
||||||
|
$var wire 1 "}G clock $end
|
||||||
|
$scope module leaf $end
|
||||||
|
$var wire 64 {u counter [63:0] $end
|
||||||
|
$upscope $end
|
||||||
|
$scope module fruit $end
|
||||||
|
$var wire 4 u) point [3:0] $end
|
||||||
|
$upscope $end
|
||||||
|
$upscope $end
|
||||||
|
|
||||||
|
$enddefinitions $end
|
||||||
|
|
||||||
|
#1
|
||||||
|
0"}G
|
||||||
|
#2
|
||||||
|
1"}G
|
||||||
|
#300
|
||||||
|
0"}G
|
||||||
|
b1111000000000000 {u
|
||||||
|
#301
|
||||||
|
b0000111100000000 {u
|
||||||
|
#302
|
||||||
|
b0000000011110000 {u
|
||||||
|
#303
|
||||||
|
b0000000000001111 {u
|
File diff suppressed because one or more lines are too long
@ -1,133 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const expect = require('chai').expect;
|
|
||||||
const parser = require('../lib/parser.js');
|
|
||||||
|
|
||||||
describe('basic', () => {
|
|
||||||
|
|
||||||
it('typeof vcd', done => {
|
|
||||||
expect(parser).to.be.an('function');
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('typeof vcd instance', done => {
|
|
||||||
expect(parser()).to.be.an('object');
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('fail: foo bar', done => {
|
|
||||||
const inst = parser();
|
|
||||||
expect(() => {
|
|
||||||
inst.write(Buffer.from(' foo bar ???'));
|
|
||||||
}).not.to.throw();
|
|
||||||
expect(inst.info).to.deep.eq({
|
|
||||||
stack: [{}],
|
|
||||||
status: 'declaration',
|
|
||||||
wires: {}
|
|
||||||
});
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('fail: $comment', done => {
|
|
||||||
const inst = parser();
|
|
||||||
expect(() => {
|
|
||||||
inst.write(Buffer.from(
|
|
||||||
' \n $comment some text $end $comment more text $end ???'
|
|
||||||
));
|
|
||||||
}).not.to.throw();
|
|
||||||
expect(inst.info).to.deep.eq({
|
|
||||||
comment: ' more text ',
|
|
||||||
stack: [{}],
|
|
||||||
status: 'declaration',
|
|
||||||
wires: {}
|
|
||||||
});
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('$version', done => {
|
|
||||||
const inst = parser();
|
|
||||||
expect(inst.write(`
|
|
||||||
$version Generated by VerilatedVcd $end
|
|
||||||
$date Wed Sep 18 22:59:07 2019
|
|
||||||
$end
|
|
||||||
$timescale 1ns $end
|
|
||||||
|
|
||||||
$scope module top $end
|
|
||||||
$var wire 1 "}G clock $end
|
|
||||||
$scope module leaf $end
|
|
||||||
$var wire 64 {u counter [63:0] $end
|
|
||||||
$upscope $end
|
|
||||||
$scope module fruit $end
|
|
||||||
$var wire 4 u) point [3:0] $end
|
|
||||||
$upscope $end
|
|
||||||
$upscope $end
|
|
||||||
|
|
||||||
$enddefinitions $end
|
|
||||||
`
|
|
||||||
)).to.eq(true);
|
|
||||||
|
|
||||||
expect(inst.write(`
|
|
||||||
|
|
||||||
#1
|
|
||||||
0"}G
|
|
||||||
#2
|
|
||||||
1"}G
|
|
||||||
#300
|
|
||||||
0"}G
|
|
||||||
b1111000000000000 {u
|
|
||||||
#301
|
|
||||||
b0000111100000000 {u
|
|
||||||
#302
|
|
||||||
b0000000011110000 {u
|
|
||||||
#303
|
|
||||||
b0000000000001111 {u
|
|
||||||
`
|
|
||||||
)).to.eq(true);
|
|
||||||
|
|
||||||
expect(inst.info).to.deep.eq({
|
|
||||||
status: 'simulation',
|
|
||||||
date: ' Wed Sep 18 22:59:07 2019\n ',
|
|
||||||
version: ' Generated by VerilatedVcd ',
|
|
||||||
timescale: ' 1ns ',
|
|
||||||
t0: 1,
|
|
||||||
varId: 'u)',
|
|
||||||
wires: {
|
|
||||||
top: {
|
|
||||||
clock: '"}G',
|
|
||||||
fruit: {
|
|
||||||
point: 'u)'
|
|
||||||
},
|
|
||||||
leaf: {
|
|
||||||
counter: '{u'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
stack: [{
|
|
||||||
top: {
|
|
||||||
clock: '"}G',
|
|
||||||
fruit: {
|
|
||||||
point: 'u)'
|
|
||||||
},
|
|
||||||
leaf: {
|
|
||||||
counter: '{u'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
clock: '"}G',
|
|
||||||
fruit: {
|
|
||||||
point: 'u)'
|
|
||||||
},
|
|
||||||
leaf: {
|
|
||||||
counter: '{u'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
point: 'u)'
|
|
||||||
}]
|
|
||||||
});
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
/* eslint-env mocha */
|
|
@ -1,88 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const fs = require('fs');
|
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
const expect = require('chai').expect;
|
|
||||||
const parser = require('../lib/parser.js');
|
|
||||||
const chopper = require('../lib/chopper.js');
|
|
||||||
|
|
||||||
const expectaitions = [
|
|
||||||
{ id: '"}G', time: 100n, cmd: 14, value: 0n, mask: 0n },
|
|
||||||
{ id: '"}G', time: 200n, cmd: 15, value: 0n, mask: 0n },
|
|
||||||
{ id: '{u', time: 200n, cmd: 30, value: 0xf0f0f0f0f0f0f0f0n, mask: 0xff00ff00ff00ff00n },
|
|
||||||
{ id: '"}G', time: 300n, cmd: 14, value: 0n, mask: 0n },
|
|
||||||
{ id: '{u', time: 300n, cmd: 30, value: 0xf000000000000000n, mask: 0n },
|
|
||||||
{ id: 'u)', time: 300n, cmd: 30, value: 0n, mask: 0n },
|
|
||||||
{ id: '{u', time: 301n, cmd: 30, value: 0x0f00000000000000n, mask: 0n },
|
|
||||||
{ id: 'u)', time: 301n, cmd: 30, value: 1n, mask: 0n },
|
|
||||||
{ id: '{u', time: 302n, cmd: 30, value: 0x00f0000000000000n, mask: 0n },
|
|
||||||
{ id: 'u)', time: 302n, cmd: 30, value: 2n, mask: 0n },
|
|
||||||
{ id: '{u', time: 303n, cmd: 30, value: 0x000f000000000000n, mask: 0n },
|
|
||||||
{ id: 'u)', time: 303n, cmd: 30, value: 3n, mask: 0n },
|
|
||||||
{ id: '{u', time: 304n, cmd: 30, value: 0x0000f00000000000n, mask: 0n },
|
|
||||||
{ id: 'u)', time: 304n, cmd: 30, value: 4n, mask: 0n },
|
|
||||||
{ id: '{u', time: 305n, cmd: 30, value: 0x00000f0000000000n, mask: 0n },
|
|
||||||
{ id: 'u)', time: 305n, cmd: 30, value: 5n, mask: 0n },
|
|
||||||
{ id: '{u', time: 306n, cmd: 30, value: 0x000000f000000000n, mask: 0n },
|
|
||||||
{ id: 'u)', time: 306n, cmd: 30, value: 6n, mask: 0n },
|
|
||||||
{ id: '{u', time: 307n, cmd: 30, value: 0x0000000f00000000n, mask: 0n },
|
|
||||||
{ id: 'u)', time: 307n, cmd: 30, value: 7n, mask: 0n },
|
|
||||||
{ id: '{u', time: 308n, cmd: 31, value: 0x00000000f0000000n, mask: 0n },
|
|
||||||
{ id: 'u)', time: 308n, cmd: 30, value: 8n, mask: 0n },
|
|
||||||
{ id: '{u', time: 309n, cmd: 30, value: 0x000000000f000000n, mask: 0n },
|
|
||||||
{ id: 'u)', time: 309n, cmd: 30, value: 9n, mask: 0n },
|
|
||||||
{ id: '{u', time: 310n, cmd: 30, value: 0x0000000000f00000n, mask: 0n },
|
|
||||||
{ id: 'u)', time: 310n, cmd: 30, value: 10n, mask: 0n },
|
|
||||||
{ id: '{u', time: 311n, cmd: 30, value: 0x00000000000f0000n, mask: 0n },
|
|
||||||
{ id: 'u)', time: 311n, cmd: 30, value: 11n, mask: 0n },
|
|
||||||
{ id: '{u', time: 312n, cmd: 30, value: 0x000000000000f000n, mask: 0n },
|
|
||||||
{ id: 'u)', time: 312n, cmd: 30, value: 12n, mask: 0n },
|
|
||||||
{ id: '{u', time: 313n, cmd: 30, value: 0x0000000000000f00n, mask: 0n },
|
|
||||||
{ id: 'u)', time: 313n, cmd: 30, value: 13n, mask: 0n },
|
|
||||||
{ id: '{u', time: 314n, cmd: 30, value: 0x00000000000000f0n, mask: 0n },
|
|
||||||
{ id: 'u)', time: 314n, cmd: 30, value: 14n, mask: 0n },
|
|
||||||
{ id: '{u', time: 315n, cmd: 30, value: 0x000000000000000fn, mask: 0n },
|
|
||||||
{ id: 'u)', time: 315n, cmd: 30, value: 15n, mask: 0n },
|
|
||||||
{ id: '"}G', time: 316n, cmd: 15, value: 0n, mask: 0n }
|
|
||||||
];
|
|
||||||
|
|
||||||
describe('napi dump', function () {
|
|
||||||
it('simple napi', done => {
|
|
||||||
fs.readFile(path.join(__dirname, 'dump.vcd'), function (err, src) {
|
|
||||||
if (err) {
|
|
||||||
throw new Error(err);
|
|
||||||
}
|
|
||||||
const inst = parser();
|
|
||||||
const dump = [];
|
|
||||||
['"}G', '{u', 'u)'] // array of all signal ids
|
|
||||||
.map(id =>
|
|
||||||
inst.change.on(id, (time, cmd, value, mask) => {
|
|
||||||
const row = {
|
|
||||||
id,
|
|
||||||
time: BigInt(time),
|
|
||||||
cmd,
|
|
||||||
value,
|
|
||||||
mask
|
|
||||||
};
|
|
||||||
dump.push(row);
|
|
||||||
// console.log(row);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
inst.on('finish', () => {
|
|
||||||
expect(inst.getTime()).to.eq(316n);
|
|
||||||
expect(dump).to.deep.eq(expectaitions);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
for (const chunk of chopper(src, 100)) {
|
|
||||||
// console.log('\u001b[31m[\u001b[0m' + chunk.toString() + '\u001b[31m]\u001b[0m');
|
|
||||||
inst.write(chunk);
|
|
||||||
}
|
|
||||||
inst.end();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
/* eslint-env mocha */
|
|
@ -1,79 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const expect = require('chai').expect;
|
|
||||||
const parser = require('../lib/parser.js');
|
|
||||||
|
|
||||||
describe('events', () => {
|
|
||||||
|
|
||||||
it('$enddefinitions', done => {
|
|
||||||
const inst = parser();
|
|
||||||
inst.on('$enddefinitions', () => {
|
|
||||||
expect(inst.info).to.deep.eq({
|
|
||||||
status: 'simulation',
|
|
||||||
date: ' Wed Sep 18 22:59:07 2019\n ',
|
|
||||||
version: ' Generated by VerilatedVcd ',
|
|
||||||
timescale: ' 1ns ',
|
|
||||||
varId: 'u)',
|
|
||||||
wires: {
|
|
||||||
top: {
|
|
||||||
clock: '"}G',
|
|
||||||
fruit: {
|
|
||||||
point: 'u)'
|
|
||||||
},
|
|
||||||
leaf: {
|
|
||||||
counter: '{u'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
stack: [{
|
|
||||||
top: {
|
|
||||||
clock: '"}G',
|
|
||||||
fruit: {
|
|
||||||
point: 'u)'
|
|
||||||
},
|
|
||||||
leaf: {
|
|
||||||
counter: '{u'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
clock: '"}G',
|
|
||||||
fruit: {
|
|
||||||
point: 'u)'
|
|
||||||
},
|
|
||||||
leaf: {
|
|
||||||
counter: '{u'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
point: 'u)'
|
|
||||||
}]
|
|
||||||
});
|
|
||||||
});
|
|
||||||
expect(inst.write(`
|
|
||||||
$version Generated by VerilatedVcd $end
|
|
||||||
$date Wed Sep 18 22:59:07 2019
|
|
||||||
$end
|
|
||||||
$timescale 1ns $end
|
|
||||||
|
|
||||||
$scope module top $end
|
|
||||||
$var wire 1 "}G clock $end
|
|
||||||
$scope module leaf $end
|
|
||||||
$var wire 64 {u counter [63:0] $end
|
|
||||||
$upscope $end
|
|
||||||
$scope module fruit $end
|
|
||||||
$var wire 4 u) point [3:0] $end
|
|
||||||
$upscope $end
|
|
||||||
$upscope $end
|
|
||||||
|
|
||||||
$enddefinitions $end
|
|
||||||
`
|
|
||||||
)).to.eq(true);
|
|
||||||
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
/* eslint-env mocha */
|
|
1586309
test/samples/iverilog.large.vcd
Normal file
1586309
test/samples/iverilog.large.vcd
Normal file
File diff suppressed because it is too large
Load Diff
37141
test/samples/iverilog.small.json
Normal file
37141
test/samples/iverilog.small.json
Normal file
File diff suppressed because it is too large
Load Diff
9529
test/samples/iverilog.small.vcd
Normal file
9529
test/samples/iverilog.small.vcd
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@ -1,132 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const expect = require('chai').expect;
|
|
||||||
const createVCD = require('../out/vcd.js');
|
|
||||||
const webVcdParser = require('../lib/web-vcd-parser.js');
|
|
||||||
|
|
||||||
describe('wasm basic', () => {
|
|
||||||
|
|
||||||
it('typeof vcd', async function () {
|
|
||||||
const mod = await createVCD();
|
|
||||||
expect(mod).to.be.an('object');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('typeof vcd instance', async function () {
|
|
||||||
const mod = await createVCD();
|
|
||||||
const inst = await webVcdParser(mod);
|
|
||||||
expect(inst).to.be.an('object');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('fail: foo bar', async function () {
|
|
||||||
const mod = await createVCD();
|
|
||||||
const inst = await webVcdParser(mod);
|
|
||||||
expect(inst.write(Buffer.from(' foo bar ???'))).to.eq(true);
|
|
||||||
expect(inst.info).to.deep.eq({
|
|
||||||
stack: [{}],
|
|
||||||
status: 'declaration',
|
|
||||||
wires: {}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('$comment', async function () {
|
|
||||||
const mod = await createVCD();
|
|
||||||
const inst = await webVcdParser(mod);
|
|
||||||
expect(inst.write(Buffer.from(
|
|
||||||
' \n $comment some text $end $comment more text $end ???'
|
|
||||||
))).to.eq(true);
|
|
||||||
expect(inst.info).to.deep.eq({
|
|
||||||
comment: ' more text ',
|
|
||||||
stack: [{}],
|
|
||||||
status: 'declaration',
|
|
||||||
wires: {}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('$version', async function () {
|
|
||||||
const mod = await createVCD();
|
|
||||||
const inst = await webVcdParser(mod);
|
|
||||||
expect(inst.write(`
|
|
||||||
$version Generated by VerilatedVcd $end
|
|
||||||
$date Wed Sep 18 22:59:07 2019
|
|
||||||
$end
|
|
||||||
$timescale 1ns $end
|
|
||||||
|
|
||||||
$scope module top $end
|
|
||||||
$var wire 1 "}G clock $end
|
|
||||||
$scope module leaf $end
|
|
||||||
$var wire 64 {u counter [63:0] $end
|
|
||||||
$upscope $end
|
|
||||||
$scope module fruit $end
|
|
||||||
$var wire 4 u) point [3:0] $end
|
|
||||||
$upscope $end
|
|
||||||
$upscope $end
|
|
||||||
|
|
||||||
$enddefinitions $end
|
|
||||||
`
|
|
||||||
)).to.eq(true);
|
|
||||||
|
|
||||||
expect(inst.write(`
|
|
||||||
|
|
||||||
#1
|
|
||||||
0"}G
|
|
||||||
#2
|
|
||||||
1"}G
|
|
||||||
#300
|
|
||||||
0"}G
|
|
||||||
b1111000000000000 {u
|
|
||||||
#301
|
|
||||||
b0000111100000000 {u
|
|
||||||
#302
|
|
||||||
b0000000011110000 {u
|
|
||||||
#303
|
|
||||||
b0000000000001111 {u
|
|
||||||
`
|
|
||||||
)).to.eq(true);
|
|
||||||
|
|
||||||
expect(inst.info).to.deep.eq({
|
|
||||||
status: 'simulation',
|
|
||||||
date: ' Wed Sep 18 22:59:07 2019\n ',
|
|
||||||
version: ' Generated by VerilatedVcd ',
|
|
||||||
timescale: ' 1ns ',
|
|
||||||
t0: 1,
|
|
||||||
varId: 'u)',
|
|
||||||
wires: {
|
|
||||||
top: {
|
|
||||||
clock: '"}G',
|
|
||||||
fruit: {
|
|
||||||
point: 'u)'
|
|
||||||
},
|
|
||||||
leaf: {
|
|
||||||
counter: '{u'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
stack: [{
|
|
||||||
top: {
|
|
||||||
clock: '"}G',
|
|
||||||
fruit: {
|
|
||||||
point: 'u)'
|
|
||||||
},
|
|
||||||
leaf: {
|
|
||||||
counter: '{u'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
clock: '"}G',
|
|
||||||
fruit: {
|
|
||||||
point: 'u)'
|
|
||||||
},
|
|
||||||
leaf: {
|
|
||||||
counter: '{u'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
point: 'u)'
|
|
||||||
}]
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
/* eslint-env mocha */
|
|
@ -1,95 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const fs = require('fs');
|
|
||||||
const path = require('path');
|
|
||||||
|
|
||||||
const expect = require('chai').expect;
|
|
||||||
const createVCD = require('../out/vcd.js');
|
|
||||||
const webVcdParser = require('../lib/web-vcd-parser.js');
|
|
||||||
const chopper = require('../lib/chopper.js');
|
|
||||||
|
|
||||||
const expectaitions = [
|
|
||||||
{ id: '"}G', time: 100n, cmd: 14, value: undefined, mask: undefined },
|
|
||||||
{ id: '"}G', time: 200n, cmd: 15, value: undefined, mask: undefined },
|
|
||||||
{ id: '{u', time: 200n, cmd: 30, value: 0xf0f0f0f0f0f0f0f0n, mask: 0xff00ff00ff00ff00n },
|
|
||||||
{ id: '"}G', time: 300n, cmd: 14, value: undefined, mask: undefined },
|
|
||||||
{ id: '{u', time: 300n, cmd: 30, value: 0xf000000000000000n, mask: 0n },
|
|
||||||
{ id: 'u)', time: 300n, cmd: 30, value: 0n, mask: 0n },
|
|
||||||
{ id: '{u', time: 301n, cmd: 30, value: 0x0f00000000000000n, mask: 0n },
|
|
||||||
{ id: 'u)', time: 301n, cmd: 30, value: 1n, mask: 0n },
|
|
||||||
{ id: '{u', time: 302n, cmd: 30, value: 0x00f0000000000000n, mask: 0n },
|
|
||||||
{ id: 'u)', time: 302n, cmd: 30, value: 2n, mask: 0n },
|
|
||||||
{ id: '{u', time: 303n, cmd: 30, value: 0x000f000000000000n, mask: 0n },
|
|
||||||
{ id: 'u)', time: 303n, cmd: 30, value: 3n, mask: 0n },
|
|
||||||
{ id: '{u', time: 304n, cmd: 30, value: 0x0000f00000000000n, mask: 0n },
|
|
||||||
{ id: 'u)', time: 304n, cmd: 30, value: 4n, mask: 0n },
|
|
||||||
{ id: '{u', time: 305n, cmd: 30, value: 0x00000f0000000000n, mask: 0n },
|
|
||||||
{ id: 'u)', time: 305n, cmd: 30, value: 5n, mask: 0n },
|
|
||||||
{ id: '{u', time: 306n, cmd: 30, value: 0x000000f000000000n, mask: 0n },
|
|
||||||
{ id: 'u)', time: 306n, cmd: 30, value: 6n, mask: 0n },
|
|
||||||
{ id: '{u', time: 307n, cmd: 30, value: 0x0000000f00000000n, mask: 0n },
|
|
||||||
{ id: 'u)', time: 307n, cmd: 30, value: 7n, mask: 0n },
|
|
||||||
{ id: '{u', time: 308n, cmd: 31, value: 0x00000000f0000000n, mask: 0n },
|
|
||||||
{ id: 'u)', time: 308n, cmd: 30, value: 8n, mask: 0n },
|
|
||||||
{ id: '{u', time: 309n, cmd: 30, value: 0x000000000f000000n, mask: 0n },
|
|
||||||
{ id: 'u)', time: 309n, cmd: 30, value: 9n, mask: 0n },
|
|
||||||
{ id: '{u', time: 310n, cmd: 30, value: 0x0000000000f00000n, mask: 0n },
|
|
||||||
{ id: 'u)', time: 310n, cmd: 30, value: 10n, mask: 0n },
|
|
||||||
{ id: '{u', time: 311n, cmd: 30, value: 0x00000000000f0000n, mask: 0n },
|
|
||||||
{ id: 'u)', time: 311n, cmd: 30, value: 11n, mask: 0n },
|
|
||||||
{ id: '{u', time: 312n, cmd: 30, value: 0x000000000000f000n, mask: 0n },
|
|
||||||
{ id: 'u)', time: 312n, cmd: 30, value: 12n, mask: 0n },
|
|
||||||
{ id: '{u', time: 313n, cmd: 30, value: 0x0000000000000f00n, mask: 0n },
|
|
||||||
{ id: 'u)', time: 313n, cmd: 30, value: 13n, mask: 0n },
|
|
||||||
{ id: '{u', time: 314n, cmd: 30, value: 0x00000000000000f0n, mask: 0n },
|
|
||||||
{ id: 'u)', time: 314n, cmd: 30, value: 14n, mask: 0n },
|
|
||||||
{ id: '{u', time: 315n, cmd: 30, value: 0x000000000000000fn, mask: 0n },
|
|
||||||
{ id: 'u)', time: 315n, cmd: 30, value: 15n, mask: 0n },
|
|
||||||
{ id: '"}G', time: 316n, cmd: 15, value: undefined, mask: undefined }
|
|
||||||
];
|
|
||||||
|
|
||||||
describe('wasm dump', () => {
|
|
||||||
it('simple wasm', done => {
|
|
||||||
fs.readFile(path.join(__dirname, 'dump.vcd'), function (err, src) {
|
|
||||||
if (err) {
|
|
||||||
throw new Error(err);
|
|
||||||
}
|
|
||||||
createVCD().then((mod) => {
|
|
||||||
webVcdParser(mod).then((inst) => {
|
|
||||||
const dump = [];
|
|
||||||
['"}G', '{u', 'u)'] // array of all signal ids
|
|
||||||
.map(id =>
|
|
||||||
inst.change.on(id, (time, cmd, value, mask) => {
|
|
||||||
const row = {
|
|
||||||
id,
|
|
||||||
time,
|
|
||||||
cmd,
|
|
||||||
value,
|
|
||||||
mask
|
|
||||||
};
|
|
||||||
dump.push(row);
|
|
||||||
// console.log(row);
|
|
||||||
})
|
|
||||||
);
|
|
||||||
|
|
||||||
inst.on('finish', () => {
|
|
||||||
expect(inst.getTime()).to.eq(316n);
|
|
||||||
// console.log(dump);
|
|
||||||
// expect(dump.length).to.eq(expectaitions.length);
|
|
||||||
expect(dump).to.deep.eq(expectaitions);
|
|
||||||
done();
|
|
||||||
});
|
|
||||||
const step = (Math.random() * 500) |0;
|
|
||||||
for (const chunk of chopper(src, step)) {
|
|
||||||
// console.log('\n\u001b[31m[\u001b[0m' + chunk.toString() + '\u001b[31m](\u001b[0m\n' + chunk.length + '\u001b[31m)\u001b[0m\n');
|
|
||||||
inst.write(chunk);
|
|
||||||
}
|
|
||||||
inst.end();
|
|
||||||
// console.log(step);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
/* eslint-env mocha */
|
|
@ -1,80 +0,0 @@
|
|||||||
'use strict';
|
|
||||||
|
|
||||||
const expect = require('chai').expect;
|
|
||||||
const createVCD = require('../out/vcd.js');
|
|
||||||
const webVcdParser = require('../lib/web-vcd-parser.js');
|
|
||||||
|
|
||||||
describe('wasm events', () => {
|
|
||||||
|
|
||||||
it('$enddefinitions', async function () {
|
|
||||||
const mod = await createVCD();
|
|
||||||
const inst = await webVcdParser(mod);
|
|
||||||
|
|
||||||
inst.on('$enddefinitions', () => {
|
|
||||||
expect(inst.info).to.deep.eq({
|
|
||||||
status: 'simulation',
|
|
||||||
timescale: ' 1ns ',
|
|
||||||
date: ' Wed Sep 18 22:59:07 2019\n ',
|
|
||||||
version: ' Generated by VerilatedVcd ',
|
|
||||||
varId: 'u)',
|
|
||||||
wires: {
|
|
||||||
top: {
|
|
||||||
clock: '"}G',
|
|
||||||
fruit: {
|
|
||||||
point: 'u)'
|
|
||||||
},
|
|
||||||
leaf: {
|
|
||||||
counter: '{u'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
stack: [{
|
|
||||||
top: {
|
|
||||||
clock: '"}G',
|
|
||||||
fruit: {
|
|
||||||
point: 'u)'
|
|
||||||
},
|
|
||||||
leaf: {
|
|
||||||
counter: '{u'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
clock: '"}G',
|
|
||||||
fruit: {
|
|
||||||
point: 'u)'
|
|
||||||
},
|
|
||||||
leaf: {
|
|
||||||
counter: '{u'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
point: 'u)'
|
|
||||||
}]
|
|
||||||
});
|
|
||||||
});
|
|
||||||
expect(inst.write(`
|
|
||||||
$version Generated by VerilatedVcd $end
|
|
||||||
$date Wed Sep 18 22:59:07 2019
|
|
||||||
$end
|
|
||||||
$timescale 1ns $end
|
|
||||||
|
|
||||||
$scope module top $end
|
|
||||||
$var wire 1 "}G clock $end
|
|
||||||
$scope module leaf $end
|
|
||||||
$var wire 64 {u counter [63:0] $end
|
|
||||||
$upscope $end
|
|
||||||
$scope module fruit $end
|
|
||||||
$var wire 4 u) point [3:0] $end
|
|
||||||
$upscope $end
|
|
||||||
$upscope $end
|
|
||||||
|
|
||||||
$enddefinitions $end
|
|
||||||
`
|
|
||||||
)).to.eq(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
/* eslint-env mocha */
|
|
60
test/wasm_iverilog.js
Normal file
60
test/wasm_iverilog.js
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const expect = require('chai').expect;
|
||||||
|
const { makeVcdStream } = require('../bin/vcd');
|
||||||
|
|
||||||
|
describe('wasm iverilog', () => {
|
||||||
|
it('small vcd', async () => {
|
||||||
|
const vcdstream = await makeVcdStream();
|
||||||
|
const arraybuffer = fs.readFileSync('./test/samples/iverilog.small.vcd');
|
||||||
|
const answers = JSON.parse(fs.readFileSync('./test/samples/iverilog.small.json'));
|
||||||
|
|
||||||
|
vcdstream.consume(arraybuffer);
|
||||||
|
const info = vcdstream.getBasicInfo();
|
||||||
|
const values = info.signalValues;
|
||||||
|
|
||||||
|
// task 1
|
||||||
|
expect(Object.keys(values)).to.have.length.above(0);
|
||||||
|
|
||||||
|
// task 2
|
||||||
|
expect(info.vcdInfo.date.trim()).to.eq('Thu Jul 22 22:29:56 2021');
|
||||||
|
expect(info.vcdInfo.version.trim()).to.eq('Icarus Verilog');
|
||||||
|
|
||||||
|
// task 3
|
||||||
|
for (const key of Object.keys(answers)) {
|
||||||
|
const ans = answers[key];
|
||||||
|
expect(values[key]).to.not.be.undefined;
|
||||||
|
expect(values[key]).to.deep.eq(ans);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it('large vcd', async () => {
|
||||||
|
const vcdstream = await makeVcdStream();
|
||||||
|
const arraybuffer = fs.readFileSync('./test/samples/iverilog.large.vcd');
|
||||||
|
// const answers = JSON.parse(fs.readFileSync('./test/samples/iverilog.large.json'));
|
||||||
|
|
||||||
|
vcdstream.consume(arraybuffer);
|
||||||
|
const info = vcdstream.getBasicInfo();
|
||||||
|
const values = info.signalValues;
|
||||||
|
|
||||||
|
// task 1
|
||||||
|
expect(Object.keys(values)).to.have.length.above(0);
|
||||||
|
expect(values['*']).to.not.be.undefined;
|
||||||
|
expect(values['+']).to.not.be.undefined;
|
||||||
|
|
||||||
|
console.log(info.signalValues['*']);
|
||||||
|
|
||||||
|
// task 2
|
||||||
|
// expect(info.vcdInfo.date.trim()).to.eq('Sat Apr 20 20:06:14 2024');
|
||||||
|
// expect(info.vcdInfo.version.trim()).to.eq('Icarus Verilog');
|
||||||
|
// expect(info.vcdInfo.timescale.trim()).to.eq('1ns');
|
||||||
|
|
||||||
|
// // task 2
|
||||||
|
// for (const key of Object.keys(answers)) {
|
||||||
|
// const ans = answers[key];
|
||||||
|
// expect(values[key]).to.not.be.undefined;
|
||||||
|
// expect(values[key]).to.deep.eq(ans);
|
||||||
|
// }
|
||||||
|
});
|
||||||
|
});
|
144
vcd_spans.c
144
vcd_spans.c
@ -1,7 +1,8 @@
|
|||||||
|
#include <limits.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <limits.h>
|
|
||||||
#include "vcd_parser.h"
|
#include "vcd_parser.h"
|
||||||
|
|
||||||
#ifndef VCDWASM
|
#ifndef VCDWASM
|
||||||
@ -14,17 +15,16 @@
|
|||||||
typedef void* napi_env;
|
typedef void* napi_env;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// #define LOGSPAN
|
// #define LOGSPAN
|
||||||
// #define LOGSPAN printf("%s\n", __FUNCTION__);
|
// #define LOGSPAN printf("%s\n", __FUNCTION__);
|
||||||
|
|
||||||
|
|
||||||
#define ASSERT(val, expr) \
|
#define ASSERT(val, expr) \
|
||||||
if (expr != napi_ok) { \
|
if (expr != napi_ok) { \
|
||||||
napi_throw(env, val); \
|
napi_throw(env, val); \
|
||||||
}
|
}
|
||||||
|
|
||||||
void strcopy(const unsigned char* p, const unsigned char* endp, unsigned char* dst) {
|
void strcopy(const unsigned char* p, const unsigned char* endp,
|
||||||
|
unsigned char* dst) {
|
||||||
const unsigned char* src;
|
const unsigned char* src;
|
||||||
src = p;
|
src = p;
|
||||||
while (src < (endp - 1)) {
|
while (src < (endp - 1)) {
|
||||||
@ -35,7 +35,8 @@ void strcopy(const unsigned char* p, const unsigned char* endp, unsigned char* d
|
|||||||
*dst = 0;
|
*dst = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void strconcat(const unsigned char* p, const unsigned char* endp, unsigned char* dst) {
|
void strconcat(const unsigned char* p, const unsigned char* endp,
|
||||||
|
unsigned char* dst) {
|
||||||
// printf("<len:%d>", endp - p);
|
// printf("<len:%d>", endp - p);
|
||||||
dst += strlen((char*)dst); // go to the end of string
|
dst += strlen((char*)dst); // go to the end of string
|
||||||
while (p < endp) {
|
while (p < endp) {
|
||||||
@ -47,11 +48,8 @@ void strconcat(const unsigned char* p, const unsigned char* endp, unsigned char*
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FIXME use a better structure to match strings
|
// FIXME use a better structure to match strings
|
||||||
int stringEq (
|
int stringEq(const unsigned char* i, // search pattern
|
||||||
const unsigned char* i, // search pattern
|
const unsigned char* p, const unsigned char* endp) {
|
||||||
const unsigned char* p,
|
|
||||||
const unsigned char* endp
|
|
||||||
) {
|
|
||||||
if (*i == 0) {
|
if (*i == 0) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -76,7 +74,8 @@ int stringEq (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int commandSpan(vcd_parser_t* state, const unsigned char* p, const unsigned char* endp) {
|
int commandSpan(vcd_parser_t* state, const unsigned char* p,
|
||||||
|
const unsigned char* endp) {
|
||||||
const uint8_t command = state->command;
|
const uint8_t command = state->command;
|
||||||
#ifndef VCDWASM
|
#ifndef VCDWASM
|
||||||
napi_env env = state->napi_env;
|
napi_env env = state->napi_env;
|
||||||
@ -86,8 +85,7 @@ int commandSpan(vcd_parser_t* state, const unsigned char* p, const unsigned char
|
|||||||
// return 0;
|
// return 0;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if (
|
if ((command == 1) || // $comment
|
||||||
(command == 1) || // $comment
|
|
||||||
(command == 2) || // $date
|
(command == 2) || // $date
|
||||||
(command == 3) || // $scope
|
(command == 3) || // $scope
|
||||||
(command == 4) || // $timescale
|
(command == 4) || // $timescale
|
||||||
@ -97,15 +95,24 @@ int commandSpan(vcd_parser_t* state, const unsigned char* p, const unsigned char
|
|||||||
) {
|
) {
|
||||||
char* key;
|
char* key;
|
||||||
switch (command) {
|
switch (command) {
|
||||||
case 1: key = "comment"; break;
|
case 1:
|
||||||
case 2: key = "date"; break;
|
key = "comment";
|
||||||
case 4: key = "timescale"; break;
|
break;
|
||||||
|
case 2:
|
||||||
|
key = "date";
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
key = "timescale";
|
||||||
|
break;
|
||||||
// case 6: key = "var"; break;
|
// case 6: key = "var"; break;
|
||||||
case 7: key = "version"; break;
|
case 7:
|
||||||
|
key = "version";
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
napi_value val;
|
napi_value val;
|
||||||
ASSERT(val, napi_create_string_latin1(env, (char*)p, (endp - p - 4), &val))
|
ASSERT(val,
|
||||||
|
napi_create_string_latin1(env, (char*)p, (endp - p - 4), &val))
|
||||||
ASSERT(state->info, napi_set_named_property(env, state->info, key, val))
|
ASSERT(state->info, napi_set_named_property(env, state->info, key, val))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -128,13 +135,19 @@ int commandSpan(vcd_parser_t* state, const unsigned char* p, const unsigned char
|
|||||||
*(char*)state->timeStampStr = 0;
|
*(char*)state->timeStampStr = 0;
|
||||||
#ifndef VCDWASM
|
#ifndef VCDWASM
|
||||||
napi_value status, undefined, eventName, eventPayload, return_val;
|
napi_value status, undefined, eventName, eventPayload, return_val;
|
||||||
ASSERT(status, napi_create_string_latin1(env, "simulation", NAPI_AUTO_LENGTH, &status))
|
ASSERT(status, napi_create_string_latin1(env, "simulation",
|
||||||
ASSERT(state->info, napi_set_named_property(env, state->info, "status", status))
|
NAPI_AUTO_LENGTH, &status))
|
||||||
|
ASSERT(state->info,
|
||||||
|
napi_set_named_property(env, state->info, "status", status))
|
||||||
ASSERT(undefined, napi_get_undefined(env, &undefined))
|
ASSERT(undefined, napi_get_undefined(env, &undefined))
|
||||||
ASSERT(eventName, napi_create_string_latin1(env, "$enddefinitions", NAPI_AUTO_LENGTH, &eventName))
|
ASSERT(eventName,
|
||||||
// ASSERT(eventPayload, napi_create_string_latin1(env, "payload", NAPI_AUTO_LENGTH, &eventPayload))
|
napi_create_string_latin1(env, "$enddefinitions",
|
||||||
|
NAPI_AUTO_LENGTH, &eventName))
|
||||||
|
// ASSERT(eventPayload, napi_create_string_latin1(env, "payload",
|
||||||
|
// NAPI_AUTO_LENGTH, &eventPayload))
|
||||||
napi_value* argv[] = {&eventName}; // , &eventPayload };
|
napi_value* argv[] = {&eventName}; // , &eventPayload };
|
||||||
ASSERT(state->lifee, napi_call_function(env, undefined, state->lifee, 1, *argv, &return_val))
|
ASSERT(state->lifee, napi_call_function(env, undefined, state->lifee, 1,
|
||||||
|
*argv, &return_val))
|
||||||
#else
|
#else
|
||||||
set_property_string("status", "simulation");
|
set_property_string("status", "simulation");
|
||||||
emit_lifee("$enddefinitions");
|
emit_lifee("$enddefinitions");
|
||||||
@ -145,14 +158,15 @@ int commandSpan(vcd_parser_t* state, const unsigned char* p, const unsigned char
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int scopeIdentifierSpan(vcd_parser_t* state, const unsigned char* p, const unsigned char* endp) {
|
int scopeIdentifierSpan(vcd_parser_t* state, const unsigned char* p,
|
||||||
|
const unsigned char* endp) {
|
||||||
strcopy(p, endp, state->tmpStr); // load the value into temp string 1
|
strcopy(p, endp, state->tmpStr); // load the value into temp string 1
|
||||||
#ifndef VCDWASM
|
#ifndef VCDWASM
|
||||||
napi_env env = state->napi_env;
|
napi_env env = state->napi_env;
|
||||||
napi_value obj, stack, top;
|
napi_value obj, stack, top;
|
||||||
ASSERT(obj, napi_create_object(env, &obj))
|
ASSERT(obj, napi_create_object(env, &obj))
|
||||||
ASSERT(state->info, napi_get_named_property(env, state->info, "stack", &stack))
|
ASSERT(state->info,
|
||||||
|
napi_get_named_property(env, state->info, "stack", &stack))
|
||||||
|
|
||||||
// get the top of the stack in top
|
// get the top of the stack in top
|
||||||
ASSERT(top, napi_get_element(env, stack, state->stackPointer, &top))
|
ASSERT(top, napi_get_element(env, stack, state->stackPointer, &top))
|
||||||
@ -164,7 +178,8 @@ int scopeIdentifierSpan(vcd_parser_t* state, const unsigned char* p, const unsig
|
|||||||
ASSERT(top, napi_set_element(env, stack, state->stackPointer, obj))
|
ASSERT(top, napi_set_element(env, stack, state->stackPointer, obj))
|
||||||
#else
|
#else
|
||||||
// set stack[sp].`tmpStr` to {}
|
// set stack[sp].`tmpStr` to {}
|
||||||
snprintf(state->tmpStr2, 4096, "stack.%d.%s", state->stackPointer, (char *)state->tmpStr);
|
snprintf(state->tmpStr2, 4096, "stack.%d.%s", state->stackPointer,
|
||||||
|
(char*)state->tmpStr);
|
||||||
new_object_path(state->tmpStr2);
|
new_object_path(state->tmpStr2);
|
||||||
|
|
||||||
// bump
|
// bump
|
||||||
@ -178,7 +193,8 @@ int scopeIdentifierSpan(vcd_parser_t* state, const unsigned char* p, const unsig
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int varSizeSpan(vcd_parser_t* state, const unsigned char* p, const unsigned char* endp) {
|
int varSizeSpan(vcd_parser_t* state, const unsigned char* p,
|
||||||
|
const unsigned char* endp) {
|
||||||
const int32_t size = strtol((const char*)p, (char**)&endp, 10);
|
const int32_t size = strtol((const char*)p, (char**)&endp, 10);
|
||||||
state->size = size;
|
state->size = size;
|
||||||
#ifndef VCDWASM
|
#ifndef VCDWASM
|
||||||
@ -189,12 +205,15 @@ int varSizeSpan(vcd_parser_t* state, const unsigned char* p, const unsigned char
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int varIdSpan(vcd_parser_t* state, const unsigned char* p, const unsigned char* endp) {
|
int varIdSpan(vcd_parser_t* state, const unsigned char* p,
|
||||||
|
const unsigned char* endp) {
|
||||||
#ifndef VCDWASM
|
#ifndef VCDWASM
|
||||||
napi_env env = state->napi_env;
|
napi_env env = state->napi_env;
|
||||||
napi_value varId;
|
napi_value varId;
|
||||||
ASSERT(varId, napi_create_string_latin1(env, (char*)p, (endp - p - 1), &varId))
|
ASSERT(varId,
|
||||||
ASSERT(state->info, napi_set_named_property(env, state->info, "varId", varId))
|
napi_create_string_latin1(env, (char*)p, (endp - p - 1), &varId))
|
||||||
|
ASSERT(state->info,
|
||||||
|
napi_set_named_property(env, state->info, "varId", varId))
|
||||||
#else
|
#else
|
||||||
strcopy(p, endp, state->tmpStr);
|
strcopy(p, endp, state->tmpStr);
|
||||||
set_property_string("varId", state->tmpStr);
|
set_property_string("varId", state->tmpStr);
|
||||||
@ -202,33 +221,39 @@ int varIdSpan(vcd_parser_t* state, const unsigned char* p, const unsigned char*
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int varNameSpan(vcd_parser_t* state, const unsigned char* p, const unsigned char* endp) {
|
int varNameSpan(vcd_parser_t* state, const unsigned char* p,
|
||||||
|
const unsigned char* endp) {
|
||||||
#ifndef VCDWASM
|
#ifndef VCDWASM
|
||||||
napi_env env = state->napi_env;
|
napi_env env = state->napi_env;
|
||||||
// *(endp - 1) = 0; // FIXME NULL termination of ASCII string
|
// *(endp - 1) = 0; // FIXME NULL termination of ASCII string
|
||||||
strcopy(p, endp, state->tmpStr);
|
strcopy(p, endp, state->tmpStr);
|
||||||
napi_value stack, top, varId;
|
napi_value stack, top, varId;
|
||||||
ASSERT(state->info, napi_get_named_property(env, state->info, "stack", &stack))
|
ASSERT(state->info,
|
||||||
|
napi_get_named_property(env, state->info, "stack", &stack))
|
||||||
ASSERT(top, napi_get_element(env, stack, state->stackPointer, &top))
|
ASSERT(top, napi_get_element(env, stack, state->stackPointer, &top))
|
||||||
ASSERT(state->info, napi_get_named_property(env, state->info, "varId", &varId))
|
ASSERT(state->info,
|
||||||
|
napi_get_named_property(env, state->info, "varId", &varId))
|
||||||
ASSERT(state->info, napi_set_named_property(env, top, state->tmpStr, varId))
|
ASSERT(state->info, napi_set_named_property(env, top, state->tmpStr, varId))
|
||||||
#else
|
#else
|
||||||
strcopy(p, endp, state->tmpStr);
|
strcopy(p, endp, state->tmpStr);
|
||||||
// set
|
// set
|
||||||
// info.stack[sp].`tmpStr` = info.varId
|
// info.stack[sp].`tmpStr` = info.varId
|
||||||
snprintf(state->tmpStr2, 4096, "stack.%d.%s", state->stackPointer, (char *)state->tmpStr);
|
snprintf(state->tmpStr2, 4096, "stack.%d.%s", state->stackPointer,
|
||||||
|
(char*)state->tmpStr);
|
||||||
set_path_to_path(state->tmpStr2, "varType,varSize,varId");
|
set_path_to_path(state->tmpStr2, "varType,varSize,varId");
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int idSpan(vcd_parser_t* state, const unsigned char* p, const unsigned char* endp) {
|
int idSpan(vcd_parser_t* state, const unsigned char* p,
|
||||||
|
const unsigned char* endp) {
|
||||||
strconcat(p, endp, state->idStr);
|
strconcat(p, endp, state->idStr);
|
||||||
// printf("<idSpan|%s>\n", (char *)state->idStr);
|
// printf("<idSpan|%s>\n", (char *)state->idStr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int onId (vcd_parser_t* state, const unsigned char* _p, const unsigned char* _endp) {
|
int onId(vcd_parser_t* state, const unsigned char* _p,
|
||||||
|
const unsigned char* _endp) {
|
||||||
#ifndef VCDWASM
|
#ifndef VCDWASM
|
||||||
napi_env env = state->napi_env;
|
napi_env env = state->napi_env;
|
||||||
#endif
|
#endif
|
||||||
@ -254,19 +279,24 @@ int onId (vcd_parser_t* state, const unsigned char* _p, const unsigned char* _en
|
|||||||
// mask[0] = 0;
|
// mask[0] = 0;
|
||||||
// }
|
// }
|
||||||
#ifndef VCDWASM
|
#ifndef VCDWASM
|
||||||
napi_value undefined, eventName, aTime, aCommand, aValue, aMask, return_val;
|
napi_value undefined, eventName, aTime, aCommand, aValue, aMask,
|
||||||
|
return_val;
|
||||||
ASSERT(undefined, napi_get_undefined(env, &undefined))
|
ASSERT(undefined, napi_get_undefined(env, &undefined))
|
||||||
ASSERT(eventName, napi_create_string_latin1(env, (char*)p, NAPI_AUTO_LENGTH, &eventName))
|
ASSERT(eventName, napi_create_string_latin1(
|
||||||
|
env, (char*)p, NAPI_AUTO_LENGTH, &eventName))
|
||||||
ASSERT(aTime, napi_create_int64(env, state->time, &aTime))
|
ASSERT(aTime, napi_create_int64(env, state->time, &aTime))
|
||||||
ASSERT(aCommand, napi_create_int32(env, command, &aCommand))
|
ASSERT(aCommand, napi_create_int32(env, command, &aCommand))
|
||||||
ASSERT(aValue, napi_create_bigint_words(env, 0, valueWords, value, &aValue))
|
ASSERT(aValue,
|
||||||
|
napi_create_bigint_words(env, 0, valueWords, value, &aValue))
|
||||||
ASSERT(aMask, napi_create_bigint_words(env, 0, maskWords, mask, &aMask))
|
ASSERT(aMask, napi_create_bigint_words(env, 0, maskWords, mask, &aMask))
|
||||||
napi_value* argv[] = {&eventName, &aTime, &aCommand, &aValue, &aMask};
|
napi_value* argv[] = {&eventName, &aTime, &aCommand, &aValue, &aMask};
|
||||||
ASSERT(state->triee, napi_call_function(env, undefined, state->triee, 5, *argv, &return_val))
|
ASSERT(state->triee, napi_call_function(env, undefined, state->triee, 5,
|
||||||
|
*argv, &return_val))
|
||||||
// printf("<id='%s'>", (char *)p);
|
// printf("<id='%s'>", (char *)p);
|
||||||
#else
|
#else
|
||||||
// strcopy(p, endp, state->tmpStr);
|
// strcopy(p, endp, state->tmpStr);
|
||||||
emit_triee((char *)p, state->time, command, valueWords, value, maskWords, mask);
|
emit_triee((char*)p, state->time, command, valueWords, value, maskWords,
|
||||||
|
mask);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
for (int i = 0; i < valueWords; i++) {
|
for (int i = 0; i < valueWords; i++) {
|
||||||
@ -281,15 +311,9 @@ int onId (vcd_parser_t* state, const unsigned char* _p, const unsigned char* _en
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 匹配 value id 这样的格式
|
||||||
|
int onDigit(vcd_parser_t* state, const unsigned char* _p,
|
||||||
int onDigit(
|
const unsigned char* _endp, int digit) {
|
||||||
vcd_parser_t* state,
|
|
||||||
const unsigned char* _p,
|
|
||||||
const unsigned char* _endp,
|
|
||||||
int digit
|
|
||||||
) {
|
|
||||||
|
|
||||||
unsigned int valueCin = (digit & 1);
|
unsigned int valueCin = (digit & 1);
|
||||||
unsigned int maskCin = ((digit >> 1) & 1);
|
unsigned int maskCin = ((digit >> 1) & 1);
|
||||||
|
|
||||||
@ -318,25 +342,22 @@ int onDigit(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int onRecover(
|
int onRecover(vcd_parser_t* state, const unsigned char* p,
|
||||||
vcd_parser_t* state,
|
const unsigned char* endp, int digit) {
|
||||||
const unsigned char* p,
|
|
||||||
const unsigned char* endp,
|
|
||||||
int digit
|
|
||||||
) {
|
|
||||||
state->digitCount = 0;
|
state->digitCount = 0;
|
||||||
state->maskCount = 0;
|
state->maskCount = 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int timeSpan(vcd_parser_t* state, const unsigned char* p,
|
||||||
int timeSpan(vcd_parser_t* state, const unsigned char* p, const unsigned char* endp) {
|
const unsigned char* endp) {
|
||||||
strconcat(p, endp, state->timeStampStr);
|
strconcat(p, endp, state->timeStampStr);
|
||||||
// printf("<timeSpan|%s>\n", (char *)state->timeStampStr);
|
// printf("<timeSpan|%s>\n", (char *)state->timeStampStr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int onTime (vcd_parser_t* state, const unsigned char* _p, const unsigned char* _endp) {
|
int onTime(vcd_parser_t* state, const unsigned char* _p,
|
||||||
|
const unsigned char* _endp) {
|
||||||
char* end;
|
char* end;
|
||||||
const int64_t time = strtoul(state->timeStampStr, &end, 10);
|
const int64_t time = strtoul(state->timeStampStr, &end, 10);
|
||||||
// printf("<onTime|%lu>\n", time);
|
// printf("<onTime|%lu>\n", time);
|
||||||
@ -345,7 +366,8 @@ int onTime (vcd_parser_t* state, const unsigned char* _p, const unsigned char* _
|
|||||||
napi_env env = state->napi_env;
|
napi_env env = state->napi_env;
|
||||||
napi_value val;
|
napi_value val;
|
||||||
ASSERT(val, napi_create_int64(env, time, &val))
|
ASSERT(val, napi_create_int64(env, time, &val))
|
||||||
ASSERT(state->info, napi_set_named_property(env, state->info, "t0", val))
|
ASSERT(state->info,
|
||||||
|
napi_set_named_property(env, state->info, "t0", val))
|
||||||
#else
|
#else
|
||||||
set_property_int("t0", time);
|
set_property_int("t0", time);
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
x
Reference in New Issue
Block a user