diff --git a/.gitignore b/.gitignore index 2823e3b..3989953 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,4 @@ coverage node_modules package-lock.json vcd_parser.* +tmp diff --git a/bin/build.js b/bin/build.js index b909ca0..638a40e 100755 --- a/bin/build.js +++ b/bin/build.js @@ -12,6 +12,17 @@ const p = new llparse.LLParse(prj); p.property('i8', 'command'); p.property('i8', 'type'); p.property('i32', 'size'); +p.property('i32', 'time'); +p.property('i32', 'start'); +p.property('i32', 'stop'); +p.property('ptr', 'trigger'); + +const scopeIdentifierSpan = p.span(p.code.span('scopeIdentifierSpan')); +const varSizeSpan = p.span(p.code.span('varSizeSpan')); +const idSpan = p.span(p.code.span('idSpan')); +const commandSpan = p.span(p.code.span('commandSpan')); +const timeSpan = p.span(p.code.span('timeSpan')); +const vectorSpan = p.span(p.code.span('vectorSpan')); const declaration = p.node('declaration'); @@ -19,26 +30,25 @@ const scopeType = p.node('scopeType'); const scopeTypeEnd = p.node('scopeTypeEnd'); const scopeIdentifier = p.node('scopeIdentifier'); -const scopeIdentifierSpan = p.span(p.code.span('scopeIdentifierSpan')); const scopeIdentifierEnd = p.node('scopeIdentifierEnd'); const varType = p.node('varType'); const varTypeEnd = p.node('varTypeEnd'); const varSize = p.node('varSize'); -const varSizeSpan = p.span(p.code.span('varSizeSpan')); const varSizeEnd = p.node('varSizeEnd'); const varId = p.node('varId'); -const varIdSpan = p.span(p.code.span('varIdSpan')); const varIdEnd = p.node('varIdEnd'); -const commandSpan = p.span(p.code.span('commandSpan')); const inDeclaration = p.node('inDeclaration'); const enddefinitions = p.node('inDeclarationEnd'); const simulation = p.node('simulation'); const inSimulation = p.node('inSimulation'); + const simulationTime = p.node('simulationTime'); +const simulationVector = p.node('simulationVector'); +const simulationId = p.node('simulationId'); const spaces = [' ', '\n', '\r', '\t']; @@ -113,10 +123,10 @@ varSizeEnd varId .match(spaces, varId) - .otherwise(varIdSpan.start(varIdEnd)); + .otherwise(idSpan.start(varIdEnd)); varIdEnd - .match(spaces, varIdSpan.end(inDeclaration)) + .match(spaces, idSpan.end(inDeclaration)) .skipTo(varIdEnd); // $end @@ -134,11 +144,15 @@ simulation .select({ $dumpall: 9, $dumpoff: 10, $dumpon: 11, $dumpvars: 12, $comment: 1 }, p.invoke(p.code.store('command'), commandSpan.start(inSimulation))) - .select({'#': 13}, p.invoke(p.code.store('command'), commandSpan.start(simulationTime))) + .select({ + '#': 13 + }, p.invoke(p.code.store('command'), timeSpan.start(simulationTime))) .select({ '0': 14, '1': 15, x: 16, X: 17, Z: 18 - }, p.invoke(p.code.store('command'), commandSpan.start(simulationTime))) - .select({}, p.invoke(p.code.store('command'), commandSpan.start(simulationTime))) + }, p.invoke(p.code.store('command'), idSpan.start(simulationId))) + .select({ + b: 19, B: 20, r: 21, R: 22 + }, p.invoke(p.code.store('command'), vectorSpan.start(simulationVector))) .otherwise(p.error(4, 'Expected simulation command')); inSimulation @@ -146,9 +160,16 @@ inSimulation .skipTo(inSimulation); simulationTime - .match(spaces, commandSpan.end(simulation)) + .match(spaces, timeSpan.end(simulation)) .skipTo(simulationTime); +simulationVector + .match(spaces, vectorSpan.end(idSpan.start(simulationId))) + .skipTo(simulationVector); + +simulationId + .match(spaces, idSpan.end(simulation)) + .skipTo(simulationId); // Build diff --git a/bin/find.js b/bin/find.js new file mode 100755 index 0000000..fca5e59 --- /dev/null +++ b/bin/find.js @@ -0,0 +1,39 @@ +#!/usr/bin/env node +'use strict'; + +const fs = require('fs-extra'); +const async = require('async'); +const lib = require('../index.js'); + +const dir = './tmp/'; + +fs.readdir(dir).then(files => { + // files.map(fileName => { + async.eachSeries(files, (fileName, callback) => { + let len = 0; + let chunks = 0; + let goodChunks = 0; + const t0 = Date.now(); + const cxt = lib.init(); + lib.setTrigger(cxt, 'D1'); + const s = fs.createReadStream(dir + fileName); + s.on('data', chunk => { + if (lib.execute(cxt, chunk) === 0) { + goodChunks++; + } + len += chunk.length; + chunks++; + }); + s.on('end', () => { + console.log( + fileName, + chunks, + len, + goodChunks, + lib.getStop(cxt) - lib.getStart(cxt), + ((Date.now() - t0) / 1000 + 's') + ); + callback(); + }); + }); +}); diff --git a/package.json b/package.json index 2f48721..5a5b15e 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,9 @@ }, "homepage": "https://github.com/wavedrom/vcd#readme", "dependencies": { + "async": "^3.1.0", "bindings": "^1.5.0", + "fs-extra": "^8.1.0", "llparse": "^6.2.0" }, "devDependencies": { diff --git a/test/basic.js b/test/basic.js index c6d6d89..a5922a8 100644 --- a/test/basic.js +++ b/test/basic.js @@ -44,7 +44,7 @@ $timescale 1ns $end $scope module top $end $var wire 1 "}G clock $end $scope module leaf $end - $var wire 64 "}> counter [63:0] $end + $var wire 64 {u counter [63:0] $end $upscope $end $upscope $end @@ -57,8 +57,15 @@ $timescale 1ns $end 0"}G #2 1"}G -#3 +#300 0"}G +b1111000000000000 {u +#301 +b0000111100000000 {u +#302 +b0000000011110000 {u +#303 +b0000000000001111 {u ` ))).to.eq(0); expect(lib.getError(cxt)).to.eq(0); diff --git a/vcd.c b/vcd.c index 59f98ef..b9f27b6 100644 --- a/vcd.c +++ b/vcd.c @@ -63,10 +63,26 @@ } \ } +#define ASSERT_STRING(name, var) \ + char var[256]; \ + { \ + napi_value tmp; \ + if (napi_coerce_to_string(env, name, &tmp) != napi_ok) { \ + napi_throw(env, name); \ + return 0; \ + } \ + size_t result; \ + if (napi_get_value_string_latin1(env, tmp, var, 256, &result) != napi_ok) { \ + napi_throw(env, name); \ + return 0; \ + } \ + } + METHOD(init) { struct vcd_parser_s *state = malloc(sizeof *state); const int32_t error = vcd_parser_init(state); + state->trigger = "HELLO"; napi_value res; if (error) { @@ -130,6 +146,49 @@ METHOD(getCommand) { return res; } +METHOD(getTime) { + ASSERT_ARGC(1) + struct vcd_parser_s *state; + ASSERT_EXTERNAL(args[0], state) + + napi_value res; + ASSERT(res, napi_create_int32(env, state->time, &res)) + return res; +} + +METHOD(getStart) { + ASSERT_ARGC(1) + struct vcd_parser_s *state; + ASSERT_EXTERNAL(args[0], state) + + napi_value res; + ASSERT(res, napi_create_int32(env, state->start, &res)) + return res; +} + +METHOD(getStop) { + ASSERT_ARGC(1) + struct vcd_parser_s *state; + ASSERT_EXTERNAL(args[0], state) + + napi_value res; + ASSERT(res, napi_create_int32(env, state->stop, &res)) + return res; +} + +METHOD(setTrigger) { + ASSERT_ARGC(2) + struct vcd_parser_s *state; + ASSERT_EXTERNAL(args[0], state) + ASSERT_STRING(args[1], trigger) + + state->trigger = *trigger; + + napi_value res; + ASSERT(res, napi_create_int32(env, state->error, &res)) + return res; +} + napi_value Init(napi_env env, napi_value exports) { DECLARE_NAPI_METHOD("init", init) DECLARE_NAPI_METHOD("execute", execute) @@ -137,16 +196,20 @@ napi_value Init(napi_env env, napi_value exports) { DECLARE_NAPI_METHOD("getReason", getReason) DECLARE_NAPI_METHOD("getErrorPos", getErrorPos) DECLARE_NAPI_METHOD("getCommand", getCommand) + DECLARE_NAPI_METHOD("getTime", getTime) + DECLARE_NAPI_METHOD("getStart", getStart) + DECLARE_NAPI_METHOD("getStop", getStop) + DECLARE_NAPI_METHOD("setTrigger", setTrigger) return exports; } int commandSpan(vcd_parser_t* s, const unsigned char* p, const unsigned char* endp) { - printf("(%d:%d:%d)(%.*s)\n", s->command, s->type, s->size, (int)(endp - p), p); + // printf("(%d:%d:%d:%d)(%.*s)\n", s->time, s->command, s->type, s->size, (int)(endp - p), p); return 0; }; int scopeIdentifierSpan(vcd_parser_t* s, const unsigned char* p, const unsigned char* endp) { - printf("{%.*s}", (int)(endp - p - 1), p); + // printf("{%.*s}", (int)(endp - p - 1), p); return 0; }; @@ -155,8 +218,42 @@ int varSizeSpan(vcd_parser_t* s, const unsigned char* p, const unsigned char* en return 0; }; -int varIdSpan(vcd_parser_t* s, const unsigned char* p, const unsigned char* endp) { - printf("{%.*s}", (int)(endp - p - 1), p); +bool stringEq ( + const unsigned char* gold, + const unsigned char* p, + const unsigned char* endp +) { + for (size_t i = 0; gold[i] != 0; i++) { + if (gold[i] != p[i]) { + return false; + } + } + return true; +} + +int idSpan(vcd_parser_t* s, const unsigned char* p, const unsigned char* endp) { + // printf("{%.*s}", (int)(endp - p - 1), p); + if (stringEq("D1", p, endp)) { + if (s->time < 10) { + return 0; + } + if (s->start == 0) { + s->start = s->time; + } else { + s->stop = s->time; + } + } + return 0; +}; + +int vectorSpan(vcd_parser_t* s, const unsigned char* p, const unsigned char* endp) { + // printf("{%.*s}", (int)(endp - p - 1), p); + return 0; +}; + +int timeSpan(vcd_parser_t* s, const unsigned char* p, const unsigned char* endp) { + s->time = strtol(p, &endp, 10); + // printf("%d\n", s->time); return 0; };