修复 parameter 的问题
This commit is contained in:
parent
a8804d9cc0
commit
60c77630cd
24
bin/vcd.js
24
bin/vcd.js
@ -26,7 +26,7 @@ const webVcdParser = require('../lib/web-vcd-parser.js');
|
|||||||
*
|
*
|
||||||
* @typedef {Object} VcdInfo
|
* @typedef {Object} VcdInfo
|
||||||
* @property {number} t0
|
* @property {number} t0
|
||||||
* @property {string} timescale
|
* @property {number} timescale
|
||||||
* @property {string} version
|
* @property {string} version
|
||||||
* @property {string} date
|
* @property {string} date
|
||||||
* @property {string} status
|
* @property {string} status
|
||||||
@ -103,6 +103,7 @@ function parseTimescale(timescale) {
|
|||||||
* write: (piece: Uint8Array) => void
|
* write: (piece: Uint8Array) => void
|
||||||
* consume: (arraybuffer: ArrayBuffer, config?: consumeConfig) => void
|
* consume: (arraybuffer: ArrayBuffer, config?: consumeConfig) => void
|
||||||
* getBasicInfo: () => VcdBasicInfo
|
* getBasicInfo: () => VcdBasicInfo
|
||||||
|
* clean: () => void
|
||||||
* }}
|
* }}
|
||||||
*/
|
*/
|
||||||
async function makeVcdStream() {
|
async function makeVcdStream() {
|
||||||
@ -120,12 +121,6 @@ async function makeVcdStream() {
|
|||||||
// console.log(time > MAX_SAFE_INTEGER);
|
// 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) {
|
if (cmd >= 14 && cmd <= 28) {
|
||||||
vcdBasicInfo.signalValues[id].kind = 'bit';
|
vcdBasicInfo.signalValues[id].kind = 'bit';
|
||||||
vcdBasicInfo.signalValues[id].wave.push([time53, cmd - 14]);
|
vcdBasicInfo.signalValues[id].wave.push([time53, cmd - 14]);
|
||||||
@ -147,6 +142,13 @@ async function makeVcdStream() {
|
|||||||
return vcdBasicInfo;
|
return vcdBasicInfo;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
vcdstream.clean = () => {
|
||||||
|
vcdBasicInfo.signalValues = {};
|
||||||
|
vcdBasicInfo.vcdInfo = undefined;
|
||||||
|
vcdBasicInfo.tgcd = undefined;
|
||||||
|
vcdBasicInfo.time = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
return vcdstream;
|
return vcdstream;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,11 +208,9 @@ async function getVcdStream() {
|
|||||||
// 测试时关闭该函数
|
// 测试时关闭该函数
|
||||||
// 部署时激活该函数
|
// 部署时激活该函数
|
||||||
try {
|
try {
|
||||||
if (self) {
|
self.getVcdStream = getVcdStream;
|
||||||
self.getVcdStream = getVcdStream;
|
self.makeVcdStream = makeVcdStream;
|
||||||
self.makeVcdStream = makeVcdStream;
|
self.vcdBasicInfo = vcdBasicInfo;
|
||||||
self.vcdBasicInfo = vcdBasicInfo;
|
|
||||||
}
|
|
||||||
} catch (error) {}
|
} catch (error) {}
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
|
@ -1,110 +1,66 @@
|
|||||||
'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;
|
||||||
|
|
||||||
const commandHandler = require('./command-handler.js');
|
const commandHandler = require('./command-handler.js');
|
||||||
|
|
||||||
// function _waitForStart(mod) {
|
|
||||||
// return new Promise((resolve)=>{
|
|
||||||
// mod.addOnPostRun(resolve);
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// function u8ToBn(u8) {
|
|
||||||
// let str = '';
|
|
||||||
// for (let i = 0; i < u8.length; i++) {
|
|
||||||
// const val = u8[i];
|
|
||||||
// str = val.toString(16) + str;
|
|
||||||
// if (val < 16) {
|
|
||||||
// str = '0' + str;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return BigInt('0x' + str);
|
|
||||||
// }
|
|
||||||
|
|
||||||
function h8ToBn(HEAPU8, start, len) {
|
function h8ToBn(HEAPU8, start, len) {
|
||||||
if (len === 0) {
|
if (len === 0) {
|
||||||
return 0n;
|
return 0n;
|
||||||
}
|
|
||||||
let str = '';
|
|
||||||
const fin = start + len * 8;
|
|
||||||
for (let i = start; i < fin; i++) {
|
|
||||||
const val = HEAPU8[i];
|
|
||||||
str = val.toString(16) + str;
|
|
||||||
if (val < 16) {
|
|
||||||
str = '0' + str;
|
|
||||||
}
|
}
|
||||||
}
|
let str = '';
|
||||||
return BigInt('0x' + str);
|
const fin = start + len * 8;
|
||||||
|
for (let i = start; i < fin; i++) {
|
||||||
|
const val = HEAPU8[i];
|
||||||
|
str = val.toString(16) + str;
|
||||||
|
if (val < 16) {
|
||||||
|
str = '0' + str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return BigInt('0x' + str);
|
||||||
}
|
}
|
||||||
|
|
||||||
// let startCalled = 0;
|
|
||||||
|
|
||||||
const bindCWrap = (c, wasm) => {
|
const bindCWrap = (c, wasm) => {
|
||||||
const w = wasm.cwrap;
|
const w = wasm.cwrap;
|
||||||
c.execute = w('execute', 'number', ['number', 'number', 'number', 'number', 'number', 'array', 'number']);
|
c.execute = w('execute', 'number', ['number', 'number', 'number', 'number', 'number', 'array', 'number']);
|
||||||
c.init = w('init', 'number', ['number', 'number', 'number', 'number']);
|
c.init = w('init', 'number', ['number', 'number', 'number', 'number']);
|
||||||
c.getTime = w('getTime', 'number', ['number']);
|
c.getTime = w('getTime', 'number', ['number']);
|
||||||
c.setTrigger = w('setTrigger', 'number', ['number', 'string']);
|
c.setTrigger = w('setTrigger', 'number', ['number', 'string']);
|
||||||
};
|
};
|
||||||
|
|
||||||
const getWrapper = wasm => {
|
const getWrapper = wasm => {
|
||||||
// console.log(wasm);
|
const c = {};
|
||||||
|
let bindCallback;
|
||||||
|
const start = async () => {
|
||||||
|
bindCWrap(c, wasm);
|
||||||
|
bindCallback();
|
||||||
|
};
|
||||||
|
|
||||||
const c = {};
|
// gets a string from a c heap pointer and length
|
||||||
|
const getString = (name, len) => {
|
||||||
|
let string = '';
|
||||||
|
const end = name + len;
|
||||||
|
for (let i = name; i < end; i++) {
|
||||||
|
string += String.fromCharCode(wasm.HEAPU8[i]);
|
||||||
|
}
|
||||||
|
return string;
|
||||||
|
|
||||||
let bindCallback;
|
};
|
||||||
|
|
||||||
|
let boundInfo;
|
||||||
|
|
||||||
|
let boundSet;
|
||||||
|
let boundGet;
|
||||||
|
|
||||||
|
let ee = [];
|
||||||
|
|
||||||
|
let boundEE0;
|
||||||
|
let boundEE1;
|
||||||
|
|
||||||
|
let context = -1;
|
||||||
|
|
||||||
|
|
||||||
const start = async() => {
|
const onEE1 = (
|
||||||
// if( !startCalled ) {
|
|
||||||
// await _waitForStart(wasm);
|
|
||||||
// startCalled++;
|
|
||||||
// }
|
|
||||||
// console.log('s1');
|
|
||||||
bindCWrap(c, wasm);
|
|
||||||
// console.log('s2');
|
|
||||||
bindCallback();
|
|
||||||
// console.log('s3');
|
|
||||||
};
|
|
||||||
|
|
||||||
// gets a string from a c heap pointer and length
|
|
||||||
const getString = (name, len) => {
|
|
||||||
|
|
||||||
// const view = wasm.HEAPU8.subarray(name, name+len);
|
|
||||||
// let string = '';
|
|
||||||
// for (let i = 0; i < len; i++) {
|
|
||||||
// string += String.fromCharCode(view[i]);
|
|
||||||
// }
|
|
||||||
// return string;
|
|
||||||
|
|
||||||
let string = '';
|
|
||||||
const end = name + len;
|
|
||||||
for (let i = name; i < end; i++) {
|
|
||||||
string += String.fromCharCode(wasm.HEAPU8[i]);
|
|
||||||
}
|
|
||||||
return string;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
let boundInfo;
|
|
||||||
|
|
||||||
let boundSet;
|
|
||||||
let boundGet;
|
|
||||||
|
|
||||||
let ee = [];
|
|
||||||
|
|
||||||
let boundEE0;
|
|
||||||
let boundEE1;
|
|
||||||
|
|
||||||
let context = -1;
|
|
||||||
|
|
||||||
|
|
||||||
const onEE1 = (
|
|
||||||
/* const char* */ eventName,
|
/* const char* */ eventName,
|
||||||
/* const size_t */ eventNameLength, // strlen(name)
|
/* const size_t */ eventNameLength, // strlen(name)
|
||||||
/* const int64_t */ time,
|
/* const int64_t */ time,
|
||||||
@ -113,168 +69,138 @@ const getWrapper = wasm => {
|
|||||||
/* uint64_t* */ value,
|
/* uint64_t* */ value,
|
||||||
/* const int */ maskWords,
|
/* const int */ maskWords,
|
||||||
/* uint64_t* */ mask
|
/* uint64_t* */ mask
|
||||||
) => {
|
) => {
|
||||||
const name = getString(eventName, eventNameLength);
|
const name = getString(eventName, eventNameLength);
|
||||||
// console.log(`event name`);
|
if (cmd >= 14 && cmd <= 28) {
|
||||||
// console.log({name, time, command, valueWords});
|
ee[1](name, time, cmd);
|
||||||
|
} else {
|
||||||
|
const bigValue = h8ToBn(wasm.HEAPU8, value, valueWords);
|
||||||
|
const bigMask = h8ToBn(wasm.HEAPU8, mask, maskWords);
|
||||||
|
ee[1](name, time, cmd, bigValue, bigMask);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// wasm.addFunction can't be called until after
|
||||||
|
// start finishes
|
||||||
|
bindCallback = () => {
|
||||||
|
boundSet = wasm.addFunction(function (name, len, type, v0, v1) {
|
||||||
|
let prop = getString(name, len);
|
||||||
|
let tmp;
|
||||||
|
|
||||||
|
switch (type) {
|
||||||
|
// set number
|
||||||
|
case 0:
|
||||||
|
boundInfo[prop] = v0;
|
||||||
|
break;
|
||||||
|
// set string
|
||||||
|
case 1:
|
||||||
|
boundInfo[prop] = getString(v0, v1);
|
||||||
|
break;
|
||||||
|
// set string to path
|
||||||
|
case 2:
|
||||||
|
break;
|
||||||
|
// path to path (any type)
|
||||||
|
case 3:
|
||||||
|
break;
|
||||||
|
// create empty object at path
|
||||||
|
case 4:
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
commandHandler(boundInfo, v0, prop);
|
||||||
|
break;
|
||||||
|
default: throw new Error();
|
||||||
|
}
|
||||||
|
// viiiii means returns void, accepts int int int int int
|
||||||
|
}, 'viiiii');
|
||||||
|
|
||||||
|
boundGet = wasm.addFunction(function (name, len) {
|
||||||
|
let prop = getString(name, len);
|
||||||
|
return prop;
|
||||||
|
}, 'iii');
|
||||||
|
|
||||||
|
|
||||||
|
boundEE0 = wasm.addFunction(function (name, len) {
|
||||||
|
ee[0](getString(name, len));
|
||||||
|
}, 'vii');
|
||||||
|
|
||||||
// const view0 = wasm.HEAPU8.subarray(value, value+(valueWords*8));
|
boundEE1 = wasm.addFunction(onEE1, 'viijiiiii');
|
||||||
// const view1 = wasm.HEAPU8.subarray(mask, mask+(valueWords*8));
|
};
|
||||||
|
|
||||||
// let bigValue = u8ToBn(view0);
|
return {
|
||||||
// let bigMask = u8ToBn(view1);
|
start,
|
||||||
// let bigValue = 0n;
|
c,
|
||||||
|
init: (cb0, cb1, info) => {
|
||||||
// console.log(bigValue.toString(16));
|
boundInfo = info;
|
||||||
|
ee[0] = cb0;
|
||||||
if (cmd >= 14 && cmd <= 28) {
|
ee[1] = cb1;
|
||||||
ee[1](name, time, cmd);
|
context = c.init(boundEE0, boundEE1, boundSet, boundGet);
|
||||||
} else {
|
return context;
|
||||||
const bigValue = h8ToBn(wasm.HEAPU8, value, valueWords);
|
},
|
||||||
const bigMask = h8ToBn(wasm.HEAPU8, mask, maskWords);
|
/**
|
||||||
ee[1](name, time, cmd, bigValue, bigMask);
|
*
|
||||||
}
|
* @param {*} ctx
|
||||||
};
|
* @param {*} cb0
|
||||||
|
* @param {*} cb1
|
||||||
// wasm.addFunction can't be called until after
|
* @param {*} info
|
||||||
// start finishes
|
* @param {*} chunk
|
||||||
bindCallback = () => {
|
* @returns
|
||||||
boundSet = wasm.addFunction(function(name, len, type, v0, v1) {
|
*/
|
||||||
|
execute: (ctx, cb0, cb1, info, chunk) => {
|
||||||
let prop = getString(name, len);
|
boundInfo = info;
|
||||||
let tmp;
|
ee[0] = cb0;
|
||||||
|
ee[1] = cb1;
|
||||||
switch(type) {
|
return c.execute(ctx, boundEE0, boundEE1, boundSet, boundGet, chunk, chunk.length);
|
||||||
// set number
|
},
|
||||||
case 0:
|
setTrigger: (ctx, triggerString) => {
|
||||||
boundInfo[prop] = v0;
|
return c.setTrigger(ctx, triggerString);
|
||||||
// console.log(`setting ${prop} to ${boundInfo[prop]}`);
|
},
|
||||||
break;
|
getTime: (ctx) => {
|
||||||
// set string
|
return BigInt(c.getTime(ctx));
|
||||||
case 1:
|
}
|
||||||
boundInfo[prop] = getString(v0, v1);
|
};
|
||||||
// console.log(`setting ${prop} to ${boundInfo[prop]}`);
|
|
||||||
break;
|
|
||||||
// set string to path
|
|
||||||
case 2:
|
|
||||||
break;
|
|
||||||
// path to path (any type)
|
|
||||||
case 3:
|
|
||||||
break;
|
|
||||||
// create empty object at path
|
|
||||||
case 4:
|
|
||||||
break;
|
|
||||||
case 5:
|
|
||||||
commandHandler(boundInfo, v0, prop);
|
|
||||||
break;
|
|
||||||
default: throw new Error();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// viiiii means returns void, accepts int int int int int
|
|
||||||
}, 'viiiii');
|
|
||||||
|
|
||||||
boundGet = wasm.addFunction(function(name, len) {
|
|
||||||
let prop = getString(name, len);
|
|
||||||
return prop;
|
|
||||||
}, 'iii');
|
|
||||||
|
|
||||||
|
|
||||||
boundEE0 = wasm.addFunction(function(name, len) {
|
|
||||||
ee[0](getString(name, len));
|
|
||||||
}, 'vii');
|
|
||||||
|
|
||||||
boundEE1 = wasm.addFunction(onEE1, 'viijiiiii');
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
return {
|
|
||||||
start,
|
|
||||||
c,
|
|
||||||
init: (cb0, cb1, info) => {
|
|
||||||
boundInfo = info;
|
|
||||||
ee[0] = cb0;
|
|
||||||
ee[1] = cb1;
|
|
||||||
context = c.init(boundEE0, boundEE1, boundSet, boundGet);
|
|
||||||
return context;
|
|
||||||
},
|
|
||||||
execute: (ctx, cb0, cb1, info, chunk) => {
|
|
||||||
boundInfo = info;
|
|
||||||
ee[0] = cb0;
|
|
||||||
ee[1] = cb1;
|
|
||||||
return c.execute(ctx, boundEE0, boundEE1, boundSet, boundGet, chunk, chunk.length);
|
|
||||||
},
|
|
||||||
setTrigger: (ctx, triggerString) => {
|
|
||||||
return c.setTrigger(ctx, triggerString);
|
|
||||||
},
|
|
||||||
getTime: (ctx) => {
|
|
||||||
return BigInt(c.getTime(ctx));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = async wasm => {
|
module.exports = async wasm => {
|
||||||
const lib = getWrapper(wasm);
|
const lib = getWrapper(wasm);
|
||||||
// console.log('getWrapper', lib);
|
await lib.start();
|
||||||
await lib.start();
|
const wires = { kind: 'scope', type: '.', name: '.', body: [] };
|
||||||
// console.log('vcd wasm srarted');
|
const info = { stack: [wires], wires };
|
||||||
const wires = {kind: 'scope', type: '.', name: '.', body: []};
|
const s = new stream.Writable();
|
||||||
const info = {stack: [wires], wires};
|
|
||||||
|
|
||||||
const s = new stream.Writable();
|
// gets called by c with 1 argument, a string
|
||||||
|
const lifemit = s.emit.bind(s);
|
||||||
|
const triee = new EventEmitter();
|
||||||
|
|
||||||
// gets called by c with 1 argument, a string
|
const triemit = triee.emit.bind(triee);
|
||||||
const lifemit = s.emit.bind(s);
|
let triemit2 = triemit;
|
||||||
|
|
||||||
const triee = new EventEmitter();
|
const cxt = lib.init(lifemit, triemit, info);
|
||||||
|
|
||||||
// gets called by c with 5 arguments
|
s._write = function (chunk, encoding, callback) {
|
||||||
// string eventName
|
const err = lib.execute(cxt, lifemit, triemit2, info, chunk);
|
||||||
// number state->time
|
if (err) {
|
||||||
// int command
|
console.log(err);
|
||||||
// int state->value
|
}
|
||||||
// int state->mask
|
callback();
|
||||||
|
};
|
||||||
|
|
||||||
const triemit = triee.emit.bind(triee);
|
s.change = {
|
||||||
let triemit2 = triemit;
|
on: (id, fn) => {
|
||||||
|
triemit2 = triemit;
|
||||||
|
triee.on(id, fn);
|
||||||
|
const triggerString = triee.eventNames().join(' ') + ' ';
|
||||||
|
lib.setTrigger(cxt, triggerString);
|
||||||
|
},
|
||||||
|
any: fn => {
|
||||||
|
triemit2 = fn;
|
||||||
|
lib.setTrigger(cxt, '\0');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const cxt = lib.init(lifemit, triemit, info);
|
s.info = info;
|
||||||
|
s.getTime = () => lib.getTime(cxt);
|
||||||
|
s.start = lib.start;
|
||||||
|
|
||||||
s._write = function (chunk, encoding, callback) {
|
return s;
|
||||||
// console.log('chunk:', chunk.length);
|
|
||||||
const err = lib.execute(cxt, lifemit, triemit2, info, chunk);
|
|
||||||
if (err) {
|
|
||||||
console.log(err);
|
|
||||||
}
|
|
||||||
// console.log(util.inspect(info, {showHidden: true, depth : null, colorize: true}));
|
|
||||||
// console.log(info.stack[0].top);
|
|
||||||
// console.log(info.stack[1]);
|
|
||||||
// console.log(info.stack[0].top == info.stack[1]);
|
|
||||||
callback();
|
|
||||||
};
|
|
||||||
|
|
||||||
s.change = {
|
|
||||||
on: (id, fn) => {
|
|
||||||
triemit2 = triemit;
|
|
||||||
triee.on(id, fn);
|
|
||||||
const triggerString = triee.eventNames().join(' ') + ' ';
|
|
||||||
// console.log(id, Buffer.from(triggerString));
|
|
||||||
lib.setTrigger(cxt, triggerString);
|
|
||||||
},
|
|
||||||
any: fn => {
|
|
||||||
triemit2 = fn;
|
|
||||||
lib.setTrigger(cxt, '\0');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
s.info = info;
|
|
||||||
|
|
||||||
s.getTime = () => lib.getTime(cxt);
|
|
||||||
|
|
||||||
s.start = lib.start;
|
|
||||||
|
|
||||||
return s;
|
|
||||||
};
|
};
|
||||||
|
BIN
out/vcd.wasm
BIN
out/vcd.wasm
Binary file not shown.
@ -13,6 +13,7 @@ async function main() {
|
|||||||
vcdstream.consume(arraybuffer);
|
vcdstream.consume(arraybuffer);
|
||||||
const info = vcdstream.getBasicInfo();
|
const info = vcdstream.getBasicInfo();
|
||||||
console.log(info.signalValues['*']);
|
console.log(info.signalValues['*']);
|
||||||
|
console.log(info.signalValues['+']);
|
||||||
}
|
}
|
||||||
|
|
||||||
main();
|
main();
|
@ -20,6 +20,7 @@ describe('wasm iverilog', () => {
|
|||||||
// task 2
|
// task 2
|
||||||
expect(info.vcdInfo.date.trim()).to.eq('Thu Jul 22 22:29:56 2021');
|
expect(info.vcdInfo.date.trim()).to.eq('Thu Jul 22 22:29:56 2021');
|
||||||
expect(info.vcdInfo.version.trim()).to.eq('Icarus Verilog');
|
expect(info.vcdInfo.version.trim()).to.eq('Icarus Verilog');
|
||||||
|
expect(info.vcdInfo.timescale).to.eq(-9);
|
||||||
|
|
||||||
// task 3
|
// task 3
|
||||||
for (const key of Object.keys(answers)) {
|
for (const key of Object.keys(answers)) {
|
||||||
@ -33,7 +34,7 @@ describe('wasm iverilog', () => {
|
|||||||
const vcdstream = await makeVcdStream();
|
const vcdstream = await makeVcdStream();
|
||||||
const arraybuffer = fs.readFileSync('./test/samples/iverilog.large.vcd');
|
const arraybuffer = fs.readFileSync('./test/samples/iverilog.large.vcd');
|
||||||
// const answers = JSON.parse(fs.readFileSync('./test/samples/iverilog.large.json'));
|
// const answers = JSON.parse(fs.readFileSync('./test/samples/iverilog.large.json'));
|
||||||
|
vcdstream.clean();
|
||||||
vcdstream.consume(arraybuffer);
|
vcdstream.consume(arraybuffer);
|
||||||
const info = vcdstream.getBasicInfo();
|
const info = vcdstream.getBasicInfo();
|
||||||
const values = info.signalValues;
|
const values = info.signalValues;
|
||||||
@ -43,12 +44,6 @@ describe('wasm iverilog', () => {
|
|||||||
expect(values['*']).to.not.be.undefined;
|
expect(values['*']).to.not.be.undefined;
|
||||||
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
|
// // task 2
|
||||||
// for (const key of Object.keys(answers)) {
|
// for (const key of Object.keys(answers)) {
|
||||||
@ -56,5 +51,15 @@ describe('wasm iverilog', () => {
|
|||||||
// expect(values[key]).to.not.be.undefined;
|
// expect(values[key]).to.not.be.undefined;
|
||||||
// expect(values[key]).to.deep.eq(ans);
|
// expect(values[key]).to.deep.eq(ans);
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
// console.log(info.signalValues['*']);
|
||||||
|
|
||||||
|
// task 3
|
||||||
|
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).to.eq(-9);
|
||||||
|
|
||||||
|
// task 4
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
365
vcd.c
365
vcd.c
@ -1,227 +1,234 @@
|
|||||||
#define NAPI_VERSION 6
|
#define NAPI_VERSION 6
|
||||||
#include <stdio.h>
|
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <stdlib.h>
|
|
||||||
#include "vcd_parser.h"
|
|
||||||
#include <node_api.h>
|
#include <node_api.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
#define DECLARE_NAPI_METHOD(name, func) { \
|
#include "vcd_parser.h"
|
||||||
napi_property_descriptor desc = { name, 0, func, 0, 0, 0, napi_default, 0 }; \
|
|
||||||
if (napi_define_properties(env, exports, 1, &desc) != napi_ok) { \
|
#define DECLARE_NAPI_METHOD(name, func) \
|
||||||
napi_throw_error(env, 0, "Error"); \
|
{ \
|
||||||
} \
|
napi_property_descriptor desc = {name, 0, func, 0, \
|
||||||
}
|
0, 0, napi_default, 0}; \
|
||||||
|
if (napi_define_properties(env, exports, 1, &desc) != napi_ok) { \
|
||||||
|
napi_throw_error(env, 0, "Error"); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
#define METHOD(name) napi_value name(napi_env env, napi_callback_info cbInfo)
|
#define METHOD(name) napi_value name(napi_env env, napi_callback_info cbInfo)
|
||||||
|
|
||||||
#define ASSERT(val, expr) \
|
#define ASSERT(val, expr) \
|
||||||
if (expr != napi_ok) { \
|
if (expr != napi_ok) { \
|
||||||
napi_throw(env, val); \
|
napi_throw(env, val); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ASSERT_ARGC(count) \
|
#define ASSERT_ARGC(count) \
|
||||||
napi_value args[count]; \
|
napi_value args[count]; \
|
||||||
{ \
|
{ \
|
||||||
size_t argc = count; \
|
size_t argc = count; \
|
||||||
if (napi_get_cb_info(env, cbInfo, &argc, args, 0, 0) != napi_ok) { \
|
if (napi_get_cb_info(env, cbInfo, &argc, args, 0, 0) != napi_ok) { \
|
||||||
napi_throw_error(env, 0, "Error"); \
|
napi_throw_error(env, 0, "Error"); \
|
||||||
return 0; \
|
return 0; \
|
||||||
} \
|
} \
|
||||||
if (argc < count) { \
|
if (argc < count) { \
|
||||||
napi_throw_type_error(env, 0, "Wrong number of arguments"); \
|
napi_throw_type_error(env, 0, "Wrong number of arguments"); \
|
||||||
return 0; \
|
return 0; \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ASSERT_BUFFER(name, var, len) \
|
#define ASSERT_BUFFER(name, var, len) \
|
||||||
const char * var; \
|
const char *var; \
|
||||||
size_t len; \
|
size_t len; \
|
||||||
{ \
|
{ \
|
||||||
bool result; \
|
bool result; \
|
||||||
if(napi_is_buffer(env, name, &result) != napi_ok) { \
|
if (napi_is_buffer(env, name, &result) != napi_ok) { \
|
||||||
napi_throw(env, name); \
|
napi_throw(env, name); \
|
||||||
return 0; \
|
return 0; \
|
||||||
} \
|
} \
|
||||||
if (napi_get_buffer_info(env, name, (void **)&var, &len) != napi_ok) { \
|
if (napi_get_buffer_info(env, name, (void **)&var, &len) != napi_ok) { \
|
||||||
napi_throw(env, name); \
|
napi_throw(env, name); \
|
||||||
return 0; \
|
return 0; \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ASSERT_STRING(name, var) \
|
#define ASSERT_STRING(name, var) \
|
||||||
{ \
|
{ \
|
||||||
napi_value tmp; \
|
napi_value tmp; \
|
||||||
if (napi_coerce_to_string(env, name, &tmp) != napi_ok) { \
|
if (napi_coerce_to_string(env, name, &tmp) != napi_ok) { \
|
||||||
napi_throw(env, name); \
|
napi_throw(env, name); \
|
||||||
return 0; \
|
return 0; \
|
||||||
} \
|
} \
|
||||||
size_t result; \
|
size_t result; \
|
||||||
if (napi_get_value_string_latin1(env, tmp, var, 4096, &result) != napi_ok) { \
|
if (napi_get_value_string_latin1(env, tmp, var, 4096, &result) != \
|
||||||
napi_throw(env, name); \
|
napi_ok) { \
|
||||||
return 0; \
|
napi_throw(env, name); \
|
||||||
} \
|
return 0; \
|
||||||
}
|
} \
|
||||||
|
}
|
||||||
#define ASSERT_EXTERNAL(name, var) { \
|
|
||||||
napi_valuetype valuetype; \
|
|
||||||
if (napi_typeof(env, name, &valuetype) != napi_ok) { \
|
|
||||||
napi_throw(env, name); \
|
|
||||||
return 0; \
|
|
||||||
} \
|
|
||||||
if (valuetype != napi_external) { \
|
|
||||||
napi_throw_type_error(env, 0, "Wrong arguments"); \
|
|
||||||
return 0; \
|
|
||||||
} \
|
|
||||||
if (napi_get_value_external(env, name, (void **)(&var)) != napi_ok) { \
|
|
||||||
napi_throw(env, name); \
|
|
||||||
return 0; \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ASSERT_FUNCTION(name, var) { \
|
|
||||||
napi_valuetype valuetype; \
|
|
||||||
if (napi_typeof(env, name, &valuetype) != napi_ok) { \
|
|
||||||
napi_throw(env, name); \
|
|
||||||
return 0; \
|
|
||||||
} \
|
|
||||||
if (valuetype != napi_function) { \
|
|
||||||
napi_throw_type_error(env, 0, "Wrong arguments"); \
|
|
||||||
return 0; \
|
|
||||||
} \
|
|
||||||
var = name; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define ASSERT_OBJECT(name, var) { \
|
|
||||||
napi_valuetype valuetype; \
|
|
||||||
if (napi_typeof(env, name, &valuetype) != napi_ok) { \
|
|
||||||
napi_throw(env, name); \
|
|
||||||
return 0; \
|
|
||||||
} \
|
|
||||||
if (valuetype != napi_object) { \
|
|
||||||
napi_throw_type_error(env, 0, "Wrong arguments"); \
|
|
||||||
return 0; \
|
|
||||||
} \
|
|
||||||
var = name; \
|
|
||||||
}
|
|
||||||
|
|
||||||
|
#define ASSERT_EXTERNAL(name, var) \
|
||||||
|
{ \
|
||||||
|
napi_valuetype valuetype; \
|
||||||
|
if (napi_typeof(env, name, &valuetype) != napi_ok) { \
|
||||||
|
napi_throw(env, name); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
if (valuetype != napi_external) { \
|
||||||
|
napi_throw_type_error(env, 0, "Wrong arguments"); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
if (napi_get_value_external(env, name, (void **)(&var)) != napi_ok) { \
|
||||||
|
napi_throw(env, name); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ASSERT_FUNCTION(name, var) \
|
||||||
|
{ \
|
||||||
|
napi_valuetype valuetype; \
|
||||||
|
if (napi_typeof(env, name, &valuetype) != napi_ok) { \
|
||||||
|
napi_throw(env, name); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
if (valuetype != napi_function) { \
|
||||||
|
napi_throw_type_error(env, 0, "Wrong arguments"); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
var = name; \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ASSERT_OBJECT(name, var) \
|
||||||
|
{ \
|
||||||
|
napi_valuetype valuetype; \
|
||||||
|
if (napi_typeof(env, name, &valuetype) != napi_ok) { \
|
||||||
|
napi_throw(env, name); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
if (valuetype != napi_object) { \
|
||||||
|
napi_throw_type_error(env, 0, "Wrong arguments"); \
|
||||||
|
return 0; \
|
||||||
|
} \
|
||||||
|
var = name; \
|
||||||
|
}
|
||||||
|
|
||||||
METHOD(init) {
|
METHOD(init) {
|
||||||
napi_value res;
|
napi_value res;
|
||||||
|
|
||||||
struct vcd_parser_s *state = malloc(sizeof *state);
|
struct vcd_parser_s *state = malloc(sizeof *state);
|
||||||
|
|
||||||
const int32_t error = vcd_parser_init(state);
|
const int32_t error = vcd_parser_init(state);
|
||||||
if (error) {
|
if (error) {
|
||||||
ASSERT(res, napi_create_int32(env, error, &res))
|
ASSERT(res, napi_create_int32(env, error, &res))
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
ASSERT_ARGC(3)
|
||||||
|
ASSERT_FUNCTION(args[0], state->lifee)
|
||||||
|
ASSERT_FUNCTION(args[1], state->triee)
|
||||||
|
ASSERT_OBJECT(args[2], state->info)
|
||||||
|
|
||||||
|
static char triggerString[4096] = {0};
|
||||||
|
static char tmpStr[4096] = {0};
|
||||||
|
static char tmpStr2[4096] = {0};
|
||||||
|
static char timeStampStr[4096] = {0};
|
||||||
|
static char idStr[4096] = {0};
|
||||||
|
static uint64_t valueBuf[4096] = {};
|
||||||
|
static uint64_t maskBuf[4096] = {};
|
||||||
|
|
||||||
|
state->trigger = triggerString;
|
||||||
|
state->reason = "NO REASON";
|
||||||
|
state->napi_env = env;
|
||||||
|
state->tmpStr = tmpStr;
|
||||||
|
state->tmpStr2 = tmpStr2;
|
||||||
|
state->timeStampStr = timeStampStr;
|
||||||
|
state->idStr = idStr;
|
||||||
|
state->value = valueBuf;
|
||||||
|
state->mask = maskBuf;
|
||||||
|
state->time = 0;
|
||||||
|
state->digitCount = 0;
|
||||||
|
state->maskCount = 0;
|
||||||
|
|
||||||
|
napi_value status;
|
||||||
|
ASSERT(status, napi_create_string_latin1(env, "declaration",
|
||||||
|
NAPI_AUTO_LENGTH, &status))
|
||||||
|
ASSERT(state->info,
|
||||||
|
napi_set_named_property(env, state->info, "status", status))
|
||||||
|
// ASSERT(status, napi_get_named_property(env, state->info, "wires",
|
||||||
|
// &state->wires))
|
||||||
|
|
||||||
|
// napi_value hierObj;
|
||||||
|
// ASSERT(hierObj, napi_create_object(env, &hierObj))
|
||||||
|
// state->info = hierObj;
|
||||||
|
|
||||||
|
// ASSERT(state->info, napi_create_object(env, &state->info))
|
||||||
|
|
||||||
|
ASSERT(res, napi_create_external(env, state, 0, 0, &res))
|
||||||
return res;
|
return res;
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT_ARGC(3)
|
|
||||||
ASSERT_FUNCTION(args[0], state->lifee)
|
|
||||||
ASSERT_FUNCTION(args[1], state->triee)
|
|
||||||
ASSERT_OBJECT(args[2], state->info)
|
|
||||||
|
|
||||||
static char triggerString [4096] = {0};
|
|
||||||
static char tmpStr [4096] = {0};
|
|
||||||
static char tmpStr2 [4096] = {0};
|
|
||||||
static char timeStampStr [4096] = {0};
|
|
||||||
static char idStr [4096] = {0};
|
|
||||||
static uint64_t valueBuf [4096] = {};
|
|
||||||
static uint64_t maskBuf [4096] = {};
|
|
||||||
|
|
||||||
state->trigger = triggerString;
|
|
||||||
state->reason = "NO REASON";
|
|
||||||
state->napi_env = env;
|
|
||||||
state->tmpStr = tmpStr;
|
|
||||||
state->tmpStr2 = tmpStr2;
|
|
||||||
state->timeStampStr = timeStampStr;
|
|
||||||
state->idStr = idStr;
|
|
||||||
state->value = valueBuf;
|
|
||||||
state->mask = maskBuf;
|
|
||||||
state->time = INT64_MAX;
|
|
||||||
state->digitCount = 0;
|
|
||||||
state->maskCount = 0;
|
|
||||||
|
|
||||||
napi_value status;
|
|
||||||
ASSERT(status, napi_create_string_latin1(env, "declaration", NAPI_AUTO_LENGTH, &status))
|
|
||||||
ASSERT(state->info, napi_set_named_property(env, state->info, "status", status))
|
|
||||||
// ASSERT(status, napi_get_named_property(env, state->info, "wires", &state->wires))
|
|
||||||
|
|
||||||
// napi_value hierObj;
|
|
||||||
// ASSERT(hierObj, napi_create_object(env, &hierObj))
|
|
||||||
// state->info = hierObj;
|
|
||||||
|
|
||||||
// ASSERT(state->info, napi_create_object(env, &state->info))
|
|
||||||
|
|
||||||
ASSERT(res, napi_create_external(env, state, 0, 0, &res))
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(done) {
|
METHOD(done) {
|
||||||
ASSERT_ARGC(4)
|
ASSERT_ARGC(4)
|
||||||
struct vcd_parser_s *state;
|
struct vcd_parser_s *state;
|
||||||
// last use of all external objects
|
// last use of all external objects
|
||||||
napi_value lifee, triee, info;
|
napi_value lifee, triee, info;
|
||||||
ASSERT_EXTERNAL(args[0], state)
|
ASSERT_EXTERNAL(args[0], state)
|
||||||
ASSERT_FUNCTION(args[1], lifee)
|
ASSERT_FUNCTION(args[1], lifee)
|
||||||
ASSERT_FUNCTION(args[2], triee)
|
ASSERT_FUNCTION(args[2], triee)
|
||||||
ASSERT_OBJECT(args[3], info)
|
ASSERT_OBJECT(args[3], info)
|
||||||
|
|
||||||
// FIXME destroy parser state
|
// FIXME destroy parser state
|
||||||
|
|
||||||
const int32_t error = 0;
|
const int32_t error = 0;
|
||||||
napi_value res;
|
napi_value res;
|
||||||
ASSERT(res, napi_create_int32(env, error, &res))
|
ASSERT(res, napi_create_int32(env, error, &res))
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(execute) {
|
METHOD(execute) {
|
||||||
ASSERT_ARGC(5)
|
ASSERT_ARGC(5)
|
||||||
struct vcd_parser_s *state;
|
struct vcd_parser_s *state;
|
||||||
ASSERT_EXTERNAL(args[0], state)
|
ASSERT_EXTERNAL(args[0], state)
|
||||||
ASSERT_FUNCTION(args[1], state->lifee)
|
ASSERT_FUNCTION(args[1], state->lifee)
|
||||||
ASSERT_FUNCTION(args[2], state->triee)
|
ASSERT_FUNCTION(args[2], state->triee)
|
||||||
ASSERT_OBJECT(args[3], state->info)
|
ASSERT_OBJECT(args[3], state->info)
|
||||||
ASSERT_BUFFER(args[4], p, plen)
|
ASSERT_BUFFER(args[4], p, plen)
|
||||||
|
|
||||||
state->napi_env = env;
|
state->napi_env = env;
|
||||||
|
|
||||||
const int32_t error = vcd_parser_execute(state, p, p + plen);
|
const int32_t error = vcd_parser_execute(state, p, p + plen);
|
||||||
napi_value res;
|
napi_value res;
|
||||||
ASSERT(res, napi_create_int32(env, error, &res))
|
ASSERT(res, napi_create_int32(env, error, &res))
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(setTrigger) {
|
METHOD(setTrigger) {
|
||||||
ASSERT_ARGC(2)
|
ASSERT_ARGC(2)
|
||||||
struct vcd_parser_s *state;
|
struct vcd_parser_s *state;
|
||||||
ASSERT_EXTERNAL(args[0], state)
|
ASSERT_EXTERNAL(args[0], state)
|
||||||
ASSERT_STRING(args[1], state->trigger)
|
ASSERT_STRING(args[1], state->trigger)
|
||||||
|
|
||||||
napi_value res;
|
napi_value res;
|
||||||
ASSERT(res, napi_create_int32(env, state->error, &res))
|
ASSERT(res, napi_create_int32(env, state->error, &res))
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
METHOD(getTime) {
|
METHOD(getTime) {
|
||||||
ASSERT_ARGC(1)
|
ASSERT_ARGC(1)
|
||||||
struct vcd_parser_s *state;
|
struct vcd_parser_s *state;
|
||||||
ASSERT_EXTERNAL(args[0], state)
|
ASSERT_EXTERNAL(args[0], state)
|
||||||
|
|
||||||
napi_value res;
|
napi_value res;
|
||||||
ASSERT(res, napi_create_bigint_int64(env, state->time, &res))
|
ASSERT(res, napi_create_bigint_int64(env, state->time, &res))
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
napi_value Init(napi_env env, napi_value exports) {
|
napi_value Init(napi_env env, napi_value exports) {
|
||||||
DECLARE_NAPI_METHOD("init", init)
|
DECLARE_NAPI_METHOD("init", init)
|
||||||
DECLARE_NAPI_METHOD("done", done)
|
DECLARE_NAPI_METHOD("done", done)
|
||||||
DECLARE_NAPI_METHOD("execute", execute)
|
DECLARE_NAPI_METHOD("execute", execute)
|
||||||
DECLARE_NAPI_METHOD("setTrigger", setTrigger)
|
DECLARE_NAPI_METHOD("setTrigger", setTrigger)
|
||||||
DECLARE_NAPI_METHOD("getTime", getTime)
|
DECLARE_NAPI_METHOD("getTime", getTime)
|
||||||
return exports;
|
return exports;
|
||||||
}
|
}
|
||||||
|
|
||||||
NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)
|
NAPI_MODULE(NODE_GYP_MODULE_NAME, Init)
|
||||||
|
257
wasm_main.cpp
257
wasm_main.cpp
@ -1,37 +1,33 @@
|
|||||||
|
#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 <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
#include "vcd_parser.h"
|
#include "vcd_parser.h"
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
|
|
||||||
/// Typedef used as part of c->js call
|
/// Typedef used as part of c->js call
|
||||||
typedef void externalJsMethodZero(const char* name, const size_t len);
|
typedef void externalJsMethodZero(const char* name, const size_t len);
|
||||||
|
|
||||||
// typedef void externalJsMethodOne (const char* name, const size_t len, const uint64_t time, const uint8_t command, const int valueWords, const int aValue, const int aMask);
|
// typedef void externalJsMethodOne (const char* name, const size_t len, const
|
||||||
|
// uint64_t time, const uint8_t command, const int valueWords, const int aValue,
|
||||||
typedef void externalJsMethodOne (
|
// const int aMask);
|
||||||
const char* name,
|
|
||||||
const size_t len,
|
|
||||||
const int64_t time,
|
|
||||||
const int command,
|
|
||||||
const int valueWords,
|
|
||||||
const int aValue,
|
|
||||||
const int maskWords,
|
|
||||||
const int aMask
|
|
||||||
);
|
|
||||||
|
|
||||||
typedef int externalJsGetProperty(const char* name, const size_t len);
|
|
||||||
typedef void externalJsSetProperty(const char* name, const size_t len, const int type, const int v0, const int v1);
|
|
||||||
|
|
||||||
|
typedef void externalJsMethodOne(const char* name, const size_t len,
|
||||||
|
const int64_t time, const int command,
|
||||||
|
const int valueWords, const int aValue,
|
||||||
|
const int maskWords, const int aMask);
|
||||||
|
|
||||||
|
typedef int externalJsGetProperty(const char* name, const size_t len);
|
||||||
|
typedef void externalJsSetProperty(const char* name, const size_t len,
|
||||||
|
const int type, const int v0, const int v1);
|
||||||
|
|
||||||
/// function pointer for c->js
|
/// function pointer for c->js
|
||||||
static externalJsMethodZero* externalZero = 0;
|
static externalJsMethodZero* externalZero = 0;
|
||||||
static externalJsMethodOne* externalOne = 0;
|
static externalJsMethodOne* externalOne = 0;
|
||||||
static externalJsSetProperty* bound_set_property = 0;
|
static externalJsSetProperty* bound_set_property = 0;
|
||||||
static externalJsGetProperty* bound_get_property = 0;
|
static externalJsGetProperty* bound_get_property = 0;
|
||||||
static struct vcd_parser_s* state;
|
static struct vcd_parser_s* state;
|
||||||
@ -39,177 +35,136 @@ static struct vcd_parser_s* state;
|
|||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
void set_property_int(const char* name, const int value) {
|
void set_property_int(const char* name, const int value) {
|
||||||
bound_set_property(name, strlen(name), 0, value, 0);
|
bound_set_property(name, strlen(name), 0, value, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_property_string(const char* name, const char* value) {
|
void set_property_string(const char* name, const char* value) {
|
||||||
bound_set_property(name, strlen(name), 1, (int)value, strlen(value));
|
bound_set_property(name, strlen(name), 1, (int)value, strlen(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_path_string(const char* name, const char* value) {
|
void set_path_string(const char* name, const char* value) {
|
||||||
bound_set_property(name, strlen(name), 2, (int)value, strlen(value));
|
bound_set_property(name, strlen(name), 2, (int)value, strlen(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
void set_path_to_path(const char* name, const char* value) {
|
void set_path_to_path(const char* name, const char* value) {
|
||||||
bound_set_property(name, strlen(name), 3, (int)value, strlen(value));
|
bound_set_property(name, strlen(name), 3, (int)value, strlen(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
void new_object_path(const char* name) {
|
void new_object_path(const char* name) {
|
||||||
bound_set_property(name, strlen(name), 4, 0, 0);
|
bound_set_property(name, strlen(name), 4, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void on_command(const char* body, const int command) {
|
void on_command(const char* body, const int command) {
|
||||||
bound_set_property(body, strlen(body), 5, command, 0);
|
bound_set_property(body, strlen(body), 5, command, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_property_int(const char* name) {
|
int get_property_int(const char* name) {
|
||||||
return bound_get_property(name, strlen(name));
|
return bound_get_property(name, strlen(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
void emit_lifee(const char* name) {
|
void emit_lifee(const char* name) { externalZero(name, strlen(name)); }
|
||||||
externalZero(name, strlen(name));
|
|
||||||
|
void emit_triee(const char* name, const int64_t time, const int command,
|
||||||
|
const int valueWords, uint64_t* aValue, const int maskWords,
|
||||||
|
uint64_t* aMask) {
|
||||||
|
// return;
|
||||||
|
// externalOne(
|
||||||
|
// "hi"
|
||||||
|
// ,2
|
||||||
|
// ,time
|
||||||
|
// ,command
|
||||||
|
// ,0
|
||||||
|
// ,0
|
||||||
|
// ,0
|
||||||
|
// );
|
||||||
|
externalOne(name, strlen(name), time, command, valueWords, (int)aValue,
|
||||||
|
maskWords, (int)aMask);
|
||||||
}
|
}
|
||||||
|
|
||||||
void emit_triee(
|
|
||||||
const char* name,
|
|
||||||
const int64_t time,
|
|
||||||
const int command,
|
|
||||||
const int valueWords,
|
|
||||||
uint64_t* aValue,
|
|
||||||
const int maskWords,
|
|
||||||
uint64_t* aMask
|
|
||||||
) {
|
|
||||||
|
|
||||||
// return;
|
|
||||||
// externalOne(
|
|
||||||
// "hi"
|
|
||||||
// ,2
|
|
||||||
// ,time
|
|
||||||
// ,command
|
|
||||||
// ,0
|
|
||||||
// ,0
|
|
||||||
// ,0
|
|
||||||
// );
|
|
||||||
externalOne(
|
|
||||||
name,
|
|
||||||
strlen(name),
|
|
||||||
time,
|
|
||||||
command,
|
|
||||||
valueWords,
|
|
||||||
(int)aValue,
|
|
||||||
maskWords,
|
|
||||||
(int)aMask
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// returns context
|
// returns context
|
||||||
int init(
|
int init(externalJsMethodZero* f0, externalJsMethodOne* f1,
|
||||||
externalJsMethodZero* f0,
|
externalJsSetProperty* sfn, externalJsGetProperty* gfn) {
|
||||||
externalJsMethodOne* f1,
|
state = (struct vcd_parser_s*)malloc(sizeof *state);
|
||||||
externalJsSetProperty* sfn,
|
|
||||||
externalJsGetProperty* gfn
|
|
||||||
) {
|
|
||||||
|
|
||||||
|
const int32_t error = vcd_parser_init(state);
|
||||||
|
if (error) {
|
||||||
|
cout << "ERROR: " << error << "\n";
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
state = (struct vcd_parser_s*) malloc(sizeof *state);
|
bound_set_property = sfn;
|
||||||
|
bound_get_property = gfn;
|
||||||
|
externalZero = f0;
|
||||||
|
externalOne = f1;
|
||||||
|
|
||||||
const int32_t error = vcd_parser_init(state);
|
state->lifee = 0;
|
||||||
if (error) {
|
state->triee = 0;
|
||||||
cout << "ERROR: " << error << "\n";
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bound_set_property = sfn;
|
static char triggerString[4096] = {0};
|
||||||
bound_get_property = gfn;
|
static char tmpStr[4096] = {0};
|
||||||
externalZero = f0;
|
static char tmpStr2[4096] = {0};
|
||||||
externalOne = f1;
|
static char timeStampStr[4096] = {0};
|
||||||
|
static char idStr[4096] = {0};
|
||||||
|
static uint64_t valueBuf[4096] = {};
|
||||||
|
static uint64_t maskBuf[4096] = {};
|
||||||
|
|
||||||
state->lifee = 0;
|
state->trigger = triggerString;
|
||||||
state->triee = 0;
|
state->reason = "NO REASON";
|
||||||
|
state->napi_env = 0;
|
||||||
|
state->tmpStr = tmpStr;
|
||||||
|
state->tmpStr2 = tmpStr2;
|
||||||
|
state->timeStampStr = timeStampStr;
|
||||||
|
state->idStr = idStr;
|
||||||
|
state->value = valueBuf;
|
||||||
|
state->mask = maskBuf;
|
||||||
|
// TODO: ensure here
|
||||||
|
state->time = 0;
|
||||||
|
state->digitCount = 0;
|
||||||
|
state->maskCount = 0;
|
||||||
|
|
||||||
static char triggerString [4096] = {0};
|
set_property_string("status", "declaration");
|
||||||
static char tmpStr [4096] = {0};
|
|
||||||
static char tmpStr2 [4096] = {0};
|
|
||||||
static char timeStampStr [4096] = {0};
|
|
||||||
static char idStr [4096] = {0};
|
|
||||||
static uint64_t valueBuf [4096] = {};
|
|
||||||
static uint64_t maskBuf [4096] = {};
|
|
||||||
|
|
||||||
state->trigger = triggerString;
|
static int context = 0;
|
||||||
state->reason = "NO REASON";
|
context++;
|
||||||
state->napi_env = 0;
|
|
||||||
state->tmpStr = tmpStr;
|
|
||||||
state->tmpStr2 = tmpStr2;
|
|
||||||
state->timeStampStr = timeStampStr;
|
|
||||||
state->idStr = idStr;
|
|
||||||
state->value = valueBuf;
|
|
||||||
state->mask = maskBuf;
|
|
||||||
state->time = INT64_MAX;
|
|
||||||
state->digitCount = 0;
|
|
||||||
state->maskCount = 0;
|
|
||||||
|
|
||||||
set_property_string("status", "declaration");
|
return context;
|
||||||
|
|
||||||
|
|
||||||
static int context = 0;
|
|
||||||
context++;
|
|
||||||
|
|
||||||
return context;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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";
|
||||||
|
bound_set_property = sfn;
|
||||||
|
bound_get_property = gfn;
|
||||||
|
externalZero = f0;
|
||||||
|
externalOne = f1;
|
||||||
|
|
||||||
|
// const size_t plen = strlen(p);
|
||||||
|
// printf("<chunk len|%d>\n", plen);
|
||||||
|
|
||||||
|
const int32_t error = vcd_parser_execute(state, p, p + plen);
|
||||||
|
|
||||||
int32_t execute(
|
return error;
|
||||||
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";
|
|
||||||
bound_set_property = sfn;
|
|
||||||
bound_get_property = gfn;
|
|
||||||
externalZero = f0;
|
|
||||||
externalOne = f1;
|
|
||||||
|
|
||||||
// const size_t plen = strlen(p);
|
|
||||||
// printf("<chunk len|%d>\n", plen);
|
|
||||||
|
|
||||||
|
|
||||||
const int32_t error = vcd_parser_execute(state, p, p + plen);
|
|
||||||
|
|
||||||
return error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int setTrigger(const int context, char* triggerString) {
|
int setTrigger(const int context, char* triggerString) {
|
||||||
int triggerStringLen = strlen((char *)triggerString) - 1;
|
int triggerStringLen = strlen((char*)triggerString) - 1;
|
||||||
// state->trigger = malloc(strlen(triggerString));
|
// state->trigger = malloc(strlen(triggerString));
|
||||||
char* p = (char *)state->tmpStr;
|
char* p = (char*)state->tmpStr;
|
||||||
for (int i = 0; i < triggerStringLen; i++) {
|
for (int i = 0; i < triggerStringLen; i++) {
|
||||||
char c = *(triggerString + i);
|
char c = *(triggerString + i);
|
||||||
if (c == 32) {
|
if (c == 32) {
|
||||||
c = 0;
|
c = 0;
|
||||||
|
}
|
||||||
|
*(p + i) = c;
|
||||||
}
|
}
|
||||||
*(p + i) = c;
|
// strcpy((char*)state->trigger, triggerString);
|
||||||
}
|
// cout << "[" << triggerString << "|" << p << "\n";
|
||||||
// strcpy((char*)state->trigger, triggerString);
|
return 0;
|
||||||
// cout << "[" << triggerString << "|" << p << "\n";
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int64_t getTime(const int context) {
|
int64_t getTime(const int context) { return state->time; }
|
||||||
return state->time;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// void execute(
|
// void execute(
|
||||||
// const int context,
|
// const int context,
|
||||||
@ -229,7 +184,6 @@ int64_t getTime(const int context) {
|
|||||||
|
|
||||||
// set_property_int("foo", 10);
|
// set_property_int("foo", 10);
|
||||||
|
|
||||||
|
|
||||||
// int got = get_property_int("bar");
|
// int got = get_property_int("bar");
|
||||||
|
|
||||||
// cout << "got " << got << " for bar\n";
|
// cout << "got " << got << " for bar\n";
|
||||||
@ -237,9 +191,8 @@ int64_t getTime(const int context) {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
int main(void) {
|
int main(void) {
|
||||||
// cout << "main()\n";
|
// cout << "main()\n";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // extern C
|
||||||
} // extern C
|
|
||||||
|
@ -9,12 +9,6 @@ void new_object_path(const char* name);
|
|||||||
void on_command(const char* body, const int command);
|
void on_command(const char* body, const int command);
|
||||||
int get_property_int(const char* name);
|
int get_property_int(const char* name);
|
||||||
void emit_lifee(const char* name);
|
void emit_lifee(const char* name);
|
||||||
void emit_triee(
|
void emit_triee(const char* name, const int64_t time, const int command,
|
||||||
const char* name,
|
const int valueWords, uint64_t* aValue, const int maskWords,
|
||||||
const int64_t time,
|
uint64_t* aMask);
|
||||||
const int command,
|
|
||||||
const int valueWords,
|
|
||||||
uint64_t* aValue,
|
|
||||||
const int maskWords,
|
|
||||||
uint64_t* aMask
|
|
||||||
);
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user