修复 parameter 的问题

This commit is contained in:
锦恢 2024-05-13 14:05:13 +08:00
parent a8804d9cc0
commit 60c77630cd
8 changed files with 483 additions and 597 deletions

View File

@ -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 = {

View File

@ -1,31 +1,9 @@
'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;
@ -42,8 +20,6 @@ function h8ToBn(HEAPU8, start, len) {
return BigInt('0x' + 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']);
@ -53,35 +29,15 @@ const bindCWrap = (c, wasm) => {
}; };
const getWrapper = wasm => { const getWrapper = wasm => {
// console.log(wasm);
const c = {}; const c = {};
let bindCallback; let bindCallback;
const start = async () => { const start = async () => {
// if( !startCalled ) {
// await _waitForStart(wasm);
// startCalled++;
// }
// console.log('s1');
bindCWrap(c, wasm); bindCWrap(c, wasm);
// console.log('s2');
bindCallback(); bindCallback();
// console.log('s3');
}; };
// gets a string from a c heap pointer and length // gets a string from a c heap pointer and length
const getString = (name, len) => { 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 = ''; let string = '';
const end = name + len; const end = name + len;
for (let i = name; i < end; i++) { for (let i = name; i < end; i++) {
@ -115,20 +71,6 @@ const getWrapper = wasm => {
/* uint64_t* */ mask /* uint64_t* */ mask
) => { ) => {
const name = getString(eventName, eventNameLength); const name = getString(eventName, eventNameLength);
// console.log(`event name`);
// console.log({name, time, command, valueWords});
// const view0 = wasm.HEAPU8.subarray(value, value+(valueWords*8));
// const view1 = wasm.HEAPU8.subarray(mask, mask+(valueWords*8));
// let bigValue = u8ToBn(view0);
// let bigMask = u8ToBn(view1);
// let bigValue = 0n;
// console.log(bigValue.toString(16));
if (cmd >= 14 && cmd <= 28) { if (cmd >= 14 && cmd <= 28) {
ee[1](name, time, cmd); ee[1](name, time, cmd);
} else { } else {
@ -142,7 +84,6 @@ const getWrapper = wasm => {
// start finishes // start finishes
bindCallback = () => { bindCallback = () => {
boundSet = wasm.addFunction(function (name, len, type, v0, v1) { boundSet = wasm.addFunction(function (name, len, type, v0, v1) {
let prop = getString(name, len); let prop = getString(name, len);
let tmp; let tmp;
@ -150,12 +91,10 @@ const getWrapper = wasm => {
// set number // set number
case 0: case 0:
boundInfo[prop] = v0; boundInfo[prop] = v0;
// console.log(`setting ${prop} to ${boundInfo[prop]}`);
break; break;
// set string // set string
case 1: case 1:
boundInfo[prop] = getString(v0, v1); boundInfo[prop] = getString(v0, v1);
// console.log(`setting ${prop} to ${boundInfo[prop]}`);
break; break;
// set string to path // set string to path
case 2: case 2:
@ -171,8 +110,6 @@ const getWrapper = wasm => {
break; break;
default: throw new Error(); default: throw new Error();
} }
// viiiii means returns void, accepts int int int int int // viiiii means returns void, accepts int int int int int
}, 'viiiii'); }, 'viiiii');
@ -187,7 +124,6 @@ const getWrapper = wasm => {
}, 'vii'); }, 'vii');
boundEE1 = wasm.addFunction(onEE1, 'viijiiiii'); boundEE1 = wasm.addFunction(onEE1, 'viijiiiii');
}; };
return { return {
@ -200,6 +136,15 @@ const getWrapper = wasm => {
context = c.init(boundEE0, boundEE1, boundSet, boundGet); context = c.init(boundEE0, boundEE1, boundSet, boundGet);
return context; return context;
}, },
/**
*
* @param {*} ctx
* @param {*} cb0
* @param {*} cb1
* @param {*} info
* @param {*} chunk
* @returns
*/
execute: (ctx, cb0, cb1, info, chunk) => { execute: (ctx, cb0, cb1, info, chunk) => {
boundInfo = info; boundInfo = info;
ee[0] = cb0; ee[0] = cb0;
@ -218,41 +163,25 @@ const getWrapper = wasm => {
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();
// console.log('vcd wasm srarted');
const wires = { kind: 'scope', type: '.', name: '.', body: [] }; const wires = { kind: 'scope', type: '.', name: '.', body: [] };
const info = { stack: [wires], wires }; const info = { stack: [wires], wires };
const s = new stream.Writable(); const s = new stream.Writable();
// gets called by c with 1 argument, a string // gets called by c with 1 argument, a string
const lifemit = s.emit.bind(s); const lifemit = s.emit.bind(s);
const triee = new EventEmitter(); const triee = new EventEmitter();
// gets called by c with 5 arguments
// string eventName
// number state->time
// int command
// int state->value
// int state->mask
const triemit = triee.emit.bind(triee); const triemit = triee.emit.bind(triee);
let triemit2 = triemit; let triemit2 = triemit;
const cxt = lib.init(lifemit, triemit, info); const cxt = lib.init(lifemit, triemit, info);
s._write = function (chunk, encoding, callback) { s._write = function (chunk, encoding, callback) {
// console.log('chunk:', chunk.length);
const err = lib.execute(cxt, lifemit, triemit2, info, chunk); const err = lib.execute(cxt, lifemit, triemit2, info, chunk);
if (err) { if (err) {
console.log(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(); callback();
}; };
@ -261,7 +190,6 @@ module.exports = async wasm => {
triemit2 = triemit; triemit2 = triemit;
triee.on(id, fn); triee.on(id, fn);
const triggerString = triee.eventNames().join(' ') + ' '; const triggerString = triee.eventNames().join(' ') + ' ';
// console.log(id, Buffer.from(triggerString));
lib.setTrigger(cxt, triggerString); lib.setTrigger(cxt, triggerString);
}, },
any: fn => { any: fn => {
@ -271,9 +199,7 @@ module.exports = async wasm => {
}; };
s.info = info; s.info = info;
s.getTime = () => lib.getTime(cxt); s.getTime = () => lib.getTime(cxt);
s.start = lib.start; s.start = lib.start;
return s; return s;

Binary file not shown.

View File

@ -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();

View File

@ -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
}); });
}); });

39
vcd.c
View File

@ -1,12 +1,15 @@
#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 }; \
#define DECLARE_NAPI_METHOD(name, func) \
{ \
napi_property_descriptor desc = {name, 0, func, 0, \
0, 0, napi_default, 0}; \
if (napi_define_properties(env, exports, 1, &desc) != napi_ok) { \ if (napi_define_properties(env, exports, 1, &desc) != napi_ok) { \
napi_throw_error(env, 0, "Error"); \ napi_throw_error(env, 0, "Error"); \
} \ } \
@ -56,13 +59,15 @@
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_ok) { \
napi_throw(env, name); \ napi_throw(env, name); \
return 0; \ return 0; \
} \ } \
} }
#define ASSERT_EXTERNAL(name, var) { \ #define ASSERT_EXTERNAL(name, var) \
{ \
napi_valuetype valuetype; \ napi_valuetype valuetype; \
if (napi_typeof(env, name, &valuetype) != napi_ok) { \ if (napi_typeof(env, name, &valuetype) != napi_ok) { \
napi_throw(env, name); \ napi_throw(env, name); \
@ -78,7 +83,8 @@
} \ } \
} }
#define ASSERT_FUNCTION(name, var) { \ #define ASSERT_FUNCTION(name, var) \
{ \
napi_valuetype valuetype; \ napi_valuetype valuetype; \
if (napi_typeof(env, name, &valuetype) != napi_ok) { \ if (napi_typeof(env, name, &valuetype) != napi_ok) { \
napi_throw(env, name); \ napi_throw(env, name); \
@ -91,7 +97,8 @@
var = name; \ var = name; \
} }
#define ASSERT_OBJECT(name, var) { \ #define ASSERT_OBJECT(name, var) \
{ \
napi_valuetype valuetype; \ napi_valuetype valuetype; \
if (napi_typeof(env, name, &valuetype) != napi_ok) { \ if (napi_typeof(env, name, &valuetype) != napi_ok) { \
napi_throw(env, name); \ napi_throw(env, name); \
@ -104,9 +111,6 @@
var = name; \ var = name; \
} }
METHOD(init) { METHOD(init) {
napi_value res; napi_value res;
@ -140,14 +144,17 @@ METHOD(init) {
state->idStr = idStr; state->idStr = idStr;
state->value = valueBuf; state->value = valueBuf;
state->mask = maskBuf; state->mask = maskBuf;
state->time = INT64_MAX; state->time = 0;
state->digitCount = 0; state->digitCount = 0;
state->maskCount = 0; state->maskCount = 0;
napi_value status; napi_value status;
ASSERT(status, napi_create_string_latin1(env, "declaration", NAPI_AUTO_LENGTH, &status)) ASSERT(status, napi_create_string_latin1(env, "declaration",
ASSERT(state->info, napi_set_named_property(env, state->info, "status", status)) NAPI_AUTO_LENGTH, &status))
// ASSERT(status, napi_get_named_property(env, state->info, "wires", &state->wires)) 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; // napi_value hierObj;
// ASSERT(hierObj, napi_create_object(env, &hierObj)) // ASSERT(hierObj, napi_create_object(env, &hierObj))

View File

@ -1,33 +1,29 @@
#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,
// const int aMask);
typedef void externalJsMethodOne ( typedef void externalJsMethodOne(const char* name, const size_t len,
const char* name, const int64_t time, const int command,
const size_t len, const int valueWords, const int aValue,
const int64_t time, const int maskWords, const int aMask);
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 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 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;
@ -66,20 +62,11 @@ 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
) {
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; // return;
// externalOne( // externalOne(
// "hi" // "hi"
@ -90,30 +77,13 @@ void emit_triee(
// ,0 // ,0
// ,0 // ,0
// ); // );
externalOne( externalOne(name, strlen(name), time, command, valueWords, (int)aValue,
name, maskWords, (int)aMask);
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,
externalJsSetProperty* sfn,
externalJsGetProperty* gfn
) {
state = (struct vcd_parser_s*)malloc(sizeof *state); state = (struct vcd_parser_s*)malloc(sizeof *state);
const int32_t error = vcd_parser_init(state); const int32_t error = vcd_parser_init(state);
@ -147,32 +117,22 @@ int init(
state->idStr = idStr; state->idStr = idStr;
state->value = valueBuf; state->value = valueBuf;
state->mask = maskBuf; state->mask = maskBuf;
state->time = INT64_MAX; // TODO: ensure here
state->time = 0;
state->digitCount = 0; state->digitCount = 0;
state->maskCount = 0; state->maskCount = 0;
set_property_string("status", "declaration"); set_property_string("status", "declaration");
static int context = 0; static int context = 0;
context++; context++;
return context; return context;
} }
int32_t execute(const int context, externalJsMethodZero* f0,
externalJsMethodOne* f1, externalJsSetProperty* sfn,
externalJsGetProperty* gfn, char* p, const int plen) {
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 got " << p << "\n";
// cout << "execute " << (int)sfn << " and got " << p << "\n"; // cout << "execute " << (int)sfn << " and got " << p << "\n";
bound_set_property = sfn; bound_set_property = sfn;
@ -183,7 +143,6 @@ int32_t execute(
// const size_t plen = strlen(p); // const size_t plen = strlen(p);
// printf("<chunk len|%d>\n", plen); // printf("<chunk len|%d>\n", plen);
const int32_t error = vcd_parser_execute(state, p, p + plen); const int32_t error = vcd_parser_execute(state, p, p + plen);
return error; return error;
@ -205,11 +164,7 @@ int setTrigger(const int context, char* triggerString) {
return 0; 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";
@ -241,5 +195,4 @@ int main(void) {
return 0; return 0;
} }
} // extern C } // extern C

View File

@ -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
);