fixes #3 ; make callback on trigger

This commit is contained in:
Aliaksei Chapyzhenka 2019-10-28 13:57:31 -07:00
parent bf6a8f5b63
commit 31bca500a0
5 changed files with 137 additions and 98 deletions

View File

@ -13,10 +13,10 @@ p.property('i8', 'command');
p.property('i8', 'type'); p.property('i8', 'type');
p.property('i32', 'size'); p.property('i32', 'size');
p.property('i32', 'time'); p.property('i32', 'time');
p.property('i32', 'start');
p.property('i32', 'stop');
p.property('ptr', 'trigger'); p.property('ptr', 'trigger');
p.property('ptr', 'info'); p.property('ptr', 'info');
p.property('ptr', 'emit');
p.property('ptr', 'napi_env');
const scopeIdentifierSpan = p.span(p.code.span('scopeIdentifierSpan')); const scopeIdentifierSpan = p.span(p.code.span('scopeIdentifierSpan'));
const varSizeSpan = p.span(p.code.span('varSizeSpan')); const varSizeSpan = p.span(p.code.span('varSizeSpan'));

View File

@ -1,38 +1,52 @@
#!/usr/bin/env node #!/usr/bin/env node
'use strict'; 'use strict';
const EventEmitter = require('events').EventEmitter;
const fs = require('fs-extra'); const fs = require('fs-extra');
const async = require('async'); const async = require('async');
const lib = require('../index.js'); const lib = require('../index.js');
const dir = './tmp/'; const dir = './tmp/';
fs.readdir(dir).then(files => { fs.readdir(dir).then(files => {
const tt0 = Date.now(); const tt0 = Date.now();
async.eachLimit(files, 2, (fileName, callback) => { async.eachLimit(files, 1, (fileName, callback) => {
let len = 0; let len = 0;
let chunks = 0; let chunks = 0;
let goodChunks = 0; let goodChunks = 0;
let start = 0;
let stop = 0;
const t0 = Date.now(); const t0 = Date.now();
const ee = new EventEmitter();
const cxt = lib.init(); const cxt = lib.init();
lib.setTrigger(cxt, 'D1'); lib.setTrigger(cxt, 'D1');
ee.on('trigger', time => {
if (time < 10) {
return 0;
}
if (start == 0) {
start = time;
} else {
stop = time;
}
});
const s = fs.createReadStream(dir + fileName); const s = fs.createReadStream(dir + fileName);
s.on('data', chunk => { s.on('data', chunk => {
if (lib.execute(cxt, chunk) === 0) { if (lib.execute(cxt, ee.emit.bind(ee), chunk) === 0) {
goodChunks++; goodChunks++;
} }
len += chunk.length; len += chunk.length;
chunks++; chunks++;
}); });
s.on('end', () => { s.on('end', () => {
const info = lib.getInfo(cxt); // const info = lib.getInfo(cxt);
// console.log(info); // console.log(info);
console.log( console.log(fileName, chunks, len, goodChunks, (stop - start),
fileName,
chunks,
len,
goodChunks,
info.stop - info.start,
((Date.now() - t0) / 1000 + 's') ((Date.now() - t0) / 1000 + 's')
); );
callback(); callback();

View File

@ -15,7 +15,7 @@ describe('basic', () => {
}); });
it('fail: foo bar', done => { it('fail: foo bar', done => {
const cxt = lib.init(); const cxt = lib.init();
expect(lib.execute(cxt, Buffer.from(' foo bar ???'))).to.eq(1); expect(lib.execute(cxt, () => {}, Buffer.from(' foo bar ???'))).to.eq(1);
expect(lib.getInfo(cxt)).to.deep.eq({ expect(lib.getInfo(cxt)).to.deep.eq({
error: 1, error: 1,
reason: 'Expected declaration command', reason: 'Expected declaration command',
@ -23,15 +23,13 @@ describe('basic', () => {
type: 0, type: 0,
size: 0, size: 0,
time: 0, time: 0,
start: 0,
stop: 0,
trigger: '' trigger: ''
}); });
done(); done();
}); });
it('$comment', done => { it('$comment', done => {
const cxt = lib.init(); const cxt = lib.init();
expect(lib.execute(cxt, Buffer.from( expect(lib.execute(cxt, () => {}, Buffer.from(
' \n $comment some text $end $comment more text $end ???' ' \n $comment some text $end $comment more text $end ???'
))).to.eq(1); ))).to.eq(1);
expect(lib.getInfo(cxt)).to.deep.eq({ expect(lib.getInfo(cxt)).to.deep.eq({
@ -41,15 +39,13 @@ describe('basic', () => {
type: 0, type: 0,
size: 0, size: 0,
time: 0, time: 0,
start: 0,
stop: 0,
trigger: '' trigger: ''
}); });
done(); done();
}); });
it('$version', done => { it('$version', done => {
const cxt = lib.init(); const cxt = lib.init();
expect(lib.execute(cxt, Buffer.from( expect(lib.execute(cxt, () => {}, Buffer.from(
` `
$version Generated by VerilatedVcd $end $version Generated by VerilatedVcd $end
$date Wed Sep 18 22:59:07 2019 $date Wed Sep 18 22:59:07 2019
@ -65,7 +61,7 @@ $timescale 1ns $end
$enddefinitions $end $enddefinitions $end
` `
))).to.eq(0); expect(lib.execute(cxt, Buffer.from( ))).to.eq(0); expect(lib.execute(cxt, () => {}, Buffer.from(
` `
#1 #1
@ -83,17 +79,17 @@ b0000000011110000 {u
b0000000000001111 {u b0000000000001111 {u
` `
))).to.eq(0); ))).to.eq(0);
expect(lib.getInfo(cxt)).to.deep.eq({ // expect(lib.getInfo(cxt)).to.deep.eq({
error: 0, // error: 0,
reason: 'NO REASON', // reason: 'NO REASON',
command: 19, // command: 19,
type: 17, // type: 17,
size: 64, // size: 64,
time: 303, // time: 303,
start: 300, // start: 300,
stop: 303, // stop: 303,
trigger: '' // trigger: ''
}); // });
done(); done();
}); });
}); });

66
vcd.c
View File

@ -11,8 +11,7 @@
} \ } \
} }
#define METHOD(name) \ #define METHOD(name) napi_value name(napi_env env, napi_callback_info info)
napi_value name(napi_env env, napi_callback_info info)
#define ASSERT(val, expr) \ #define ASSERT(val, expr) \
if (expr != napi_ok) { \ if (expr != napi_ok) { \
@ -33,22 +32,6 @@
} \ } \
} }
#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_BUFFER(name, var, len) \ #define ASSERT_BUFFER(name, var, len) \
const char * var; \ const char * var; \
size_t len; \ size_t len; \
@ -78,6 +61,38 @@
} \ } \
} }
#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; \
}
// napi_value * var;
METHOD(init) { METHOD(init) {
struct vcd_parser_s *state = malloc(sizeof *state); struct vcd_parser_s *state = malloc(sizeof *state);
@ -98,10 +113,13 @@ METHOD(init) {
} }
METHOD(execute) { METHOD(execute) {
ASSERT_ARGC(2) ASSERT_ARGC(3)
struct vcd_parser_s *state; struct vcd_parser_s *state;
ASSERT_EXTERNAL(args[0], state) ASSERT_EXTERNAL(args[0], state)
ASSERT_BUFFER(args[1], p, plen) ASSERT_FUNCTION(args[1], state->emit)
ASSERT_BUFFER(args[2], p, plen)
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);
@ -115,7 +133,7 @@ METHOD(getInfo) {
struct vcd_parser_s *state; struct vcd_parser_s *state;
ASSERT_EXTERNAL(args[0], state) ASSERT_EXTERNAL(args[0], state)
napi_value infObj, error, reason, command, type, size, time, start, stop, trigger; napi_value infObj, error, reason, command, type, size, time, trigger;
ASSERT(infObj, napi_create_object(env, &infObj)) ASSERT(infObj, napi_create_object(env, &infObj))
ASSERT(error, napi_create_int32(env, state->error, &error)) ASSERT(error, napi_create_int32(env, state->error, &error))
@ -136,12 +154,6 @@ METHOD(getInfo) {
ASSERT(time, napi_create_int32(env, state->time, &time)) ASSERT(time, napi_create_int32(env, state->time, &time))
ASSERT(infObj, napi_set_named_property(env, infObj, "time", time)) ASSERT(infObj, napi_set_named_property(env, infObj, "time", time))
ASSERT(start, napi_create_int32(env, state->start, &start))
ASSERT(infObj, napi_set_named_property(env, infObj, "start", start))
ASSERT(stop, napi_create_int32(env, state->stop, &stop))
ASSERT(infObj, napi_set_named_property(env, infObj, "stop", stop))
ASSERT(trigger, napi_create_string_latin1(env, state->trigger, NAPI_AUTO_LENGTH, &trigger)) ASSERT(trigger, napi_create_string_latin1(env, state->trigger, NAPI_AUTO_LENGTH, &trigger))
ASSERT(infObj, napi_set_named_property(env, infObj, "trigger", trigger)) ASSERT(infObj, napi_set_named_property(env, infObj, "trigger", trigger))

View File

@ -1,12 +1,16 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "vcd_parser.h" #include "vcd_parser.h"
#include <node_api.h>
int stringEq ( int stringEq (
const unsigned char* gold, const unsigned char* gold,
const unsigned char* p, const unsigned char* p,
const unsigned char* endp const unsigned char* endp
) { ) {
if (gold[0] == 0) {
return 0;
}
for (size_t i = 0; gold[i] != 0; i++) { for (size_t i = 0; gold[i] != 0; i++) {
if (gold[i] != p[i]) { if (gold[i] != p[i]) {
return 0; return 0;
@ -16,12 +20,10 @@ int stringEq (
} }
int commandSpan(vcd_parser_t* s, const unsigned char* p, const unsigned char* endp) { int commandSpan(vcd_parser_t* s, const unsigned char* p, const unsigned char* endp) {
// printf("(%d:%d:%d:%d)(%.*s)\n", s->time, s->command, s->type, s->size, (int)(endp - p), p);
return 0; return 0;
}; };
int scopeIdentifierSpan(vcd_parser_t* s, const unsigned char* p, const unsigned char* endp) { int scopeIdentifierSpan(vcd_parser_t* s, const unsigned char* p, const unsigned char* endp) {
// printf("{%.*s}", (int)(endp - p - 1), p);
return 0; return 0;
}; };
@ -30,16 +32,32 @@ int varSizeSpan(vcd_parser_t* s, const unsigned char* p, const unsigned char* en
return 0; return 0;
}; };
int idSpan(vcd_parser_t* s, const unsigned char* p, const unsigned char* endp) { int idSpan(vcd_parser_t* state, const unsigned char* p, const unsigned char* endp) {
// printf("{%.*s}", (int)(endp - p - 1), p); if (stringEq((state->trigger), p, endp)) {
if (stringEq((s->trigger), p, endp)) { napi_value undefined;
if (s->time < 10) { if (napi_get_undefined(state->napi_env, &undefined) != napi_ok) {
napi_throw(state->napi_env, undefined);
return 0; return 0;
} }
if (s->start == 0) {
s->start = s->time; napi_value eventName;
} else { if (napi_create_string_latin1(state->napi_env, "trigger", NAPI_AUTO_LENGTH, &eventName) != napi_ok) {
s->stop = s->time; napi_throw(state->napi_env, eventName);
return 0;
};
napi_value eventPayload;
if (napi_create_int32(state->napi_env, state->time, &eventPayload) != napi_ok) {
napi_throw(state->napi_env, eventPayload);
return 0;
};
napi_value* argv[] = { &eventName, &eventPayload };
napi_value return_val;
if (napi_call_function(state->napi_env, undefined, state->emit, 2, *argv, &return_val) != napi_ok) {
napi_throw(state->napi_env, state->emit);
return 0;
} }
} }
return 0; return 0;
@ -52,6 +70,5 @@ int vectorSpan(vcd_parser_t* s, const unsigned char* p, const unsigned char* end
int timeSpan(vcd_parser_t* s, const unsigned char* p, const unsigned char* endp) { int timeSpan(vcd_parser_t* s, const unsigned char* p, const unsigned char* endp) {
s->time = strtol((const char *)p, (char **)&endp, 10); s->time = strtol((const char *)p, (char **)&endp, 10);
// printf("%d\n", s->time);
return 0; return 0;
}; };