simplify build process
This commit is contained in:
parent
f35f172189
commit
55d5c51f29
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,4 +1,3 @@
|
|||||||
/.vscode
|
|
||||||
/.nyc_output
|
/.nyc_output
|
||||||
/node_modules
|
/node_modules
|
||||||
/package-lock.json
|
/package-lock.json
|
||||||
|
17
.vscode/c_cpp_properties.json
vendored
Normal file
17
.vscode/c_cpp_properties.json
vendored
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Linux",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}/**",
|
||||||
|
"${EMCC_HOME}/node/14.18.2_64bit/include/node/*"
|
||||||
|
],
|
||||||
|
"defines": [],
|
||||||
|
"compilerPath": "/usr/bin/gcc",
|
||||||
|
"cStandard": "c17",
|
||||||
|
"cppStandard": "gnu++14",
|
||||||
|
"intelliSenseMode": "linux-gcc-x64"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"version": 4
|
||||||
|
}
|
7
.vscode/settings.json
vendored
Normal file
7
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"files.associations": {
|
||||||
|
"*.rmd": "markdown",
|
||||||
|
"node_api.h": "c",
|
||||||
|
"typeinfo": "c"
|
||||||
|
}
|
||||||
|
}
|
59
Makefile
59
Makefile
@ -1,7 +1,6 @@
|
|||||||
.PHONY: wasm all important clean
|
.PHONY: wasm all important clean
|
||||||
|
|
||||||
all: wasm
|
all: wasm
|
||||||
wasm: out/vcd.wasm
|
|
||||||
|
|
||||||
WASM_MAIN = wasm_main.cpp
|
WASM_MAIN = wasm_main.cpp
|
||||||
|
|
||||||
@ -13,10 +12,6 @@ CPP_FILES = \
|
|||||||
vcd_parser.c \
|
vcd_parser.c \
|
||||||
vcd_spans.c \
|
vcd_spans.c \
|
||||||
|
|
||||||
# this is a list of all C functions we want to publish to javascript
|
|
||||||
# In the main cpp file, each of these is wrapped in extern "C" {}
|
|
||||||
# the version here has a prepended underscore
|
|
||||||
# all lines must have trailing comma
|
|
||||||
EXPORT_STRING = \
|
EXPORT_STRING = \
|
||||||
"_execute", \
|
"_execute", \
|
||||||
"_init", \
|
"_init", \
|
||||||
@ -26,16 +21,6 @@ EXPORT_STRING = \
|
|||||||
# warning and error flags
|
# warning and error flags
|
||||||
CLANG_WARN_FLAGS = \
|
CLANG_WARN_FLAGS = \
|
||||||
-fno-exceptions \
|
-fno-exceptions \
|
||||||
-Wall \
|
|
||||||
-Wextra \
|
|
||||||
-Wno-ignored-qualifiers \
|
|
||||||
-Wundef \
|
|
||||||
-Werror=return-type \
|
|
||||||
-Wshadow \
|
|
||||||
|
|
||||||
# -Wconversion
|
|
||||||
# -flto \
|
|
||||||
# -Wl,--lto-O3 \
|
|
||||||
|
|
||||||
CLANG_OTHER_FLAGS = \
|
CLANG_OTHER_FLAGS = \
|
||||||
-DVCDWASM \
|
-DVCDWASM \
|
||||||
@ -50,15 +35,12 @@ ifdef OPT3
|
|||||||
CLANG_O_FLAG = '-O3'
|
CLANG_O_FLAG = '-O3'
|
||||||
endif
|
endif
|
||||||
|
|
||||||
# works however slows down
|
wasm: $(WASM_MAIN) $(CPP_FILES) $(HPP_FILES) Makefile
|
||||||
#-s DISABLE_EXCEPTION_CATCHING=0 \
|
|
||||||
|
|
||||||
out/vcd.wasm: $(WASM_MAIN) $(CPP_FILES) $(HPP_FILES) Makefile
|
|
||||||
mkdir -p out
|
mkdir -p out
|
||||||
emcc \
|
emcc \
|
||||||
$(WASM_MAIN) \
|
$(WASM_MAIN) \
|
||||||
$(CPP_FILES) \
|
$(CPP_FILES) \
|
||||||
-o out/vcd.html \
|
-o out/vcd.js \
|
||||||
-s DISABLE_EXCEPTION_CATCHING=1 \
|
-s DISABLE_EXCEPTION_CATCHING=1 \
|
||||||
-s WASM_BIGINT \
|
-s WASM_BIGINT \
|
||||||
-s ALLOW_MEMORY_GROWTH=1 \
|
-s ALLOW_MEMORY_GROWTH=1 \
|
||||||
@ -66,48 +48,11 @@ out/vcd.wasm: $(WASM_MAIN) $(CPP_FILES) $(HPP_FILES) Makefile
|
|||||||
-s MAXIMUM_MEMORY=2GB \
|
-s MAXIMUM_MEMORY=2GB \
|
||||||
-s ALLOW_TABLE_GROWTH=1 \
|
-s ALLOW_TABLE_GROWTH=1 \
|
||||||
-s MODULARIZE=1 \
|
-s MODULARIZE=1 \
|
||||||
-s EXPORT_NAME=createVCD \
|
|
||||||
-s EXPORTED_FUNCTIONS='[$(EXPORT_STRING) "_main"]' \
|
-s EXPORTED_FUNCTIONS='[$(EXPORT_STRING) "_main"]' \
|
||||||
-s EXPORTED_RUNTIME_METHODS='["ccall", "cwrap", "addOnPostRun", "addFunction", "setValue", "getValue"]' \
|
-s EXPORTED_RUNTIME_METHODS='["ccall", "cwrap", "addOnPostRun", "addFunction", "setValue", "getValue"]' \
|
||||||
$(CLANG_O_FLAG) $(CLANG_WARN_FLAGS) $(CLANG_OTHER_FLAGS)
|
$(CLANG_O_FLAG) $(CLANG_WARN_FLAGS) $(CLANG_OTHER_FLAGS)
|
||||||
|
|
||||||
# -s WASM=0 \
|
|
||||||
|
|
||||||
.PHONY: patchlib patchlib1 patchlib2
|
.PHONY: patchlib patchlib1 patchlib2
|
||||||
|
|
||||||
# patchlib: patchlib1 patchlib2
|
|
||||||
|
|
||||||
# PTSRC1=lib/BehaviorTree.CPP/src/xml_parsing.cpp
|
|
||||||
# PTPAT1=patch/xml_parsing.patch
|
|
||||||
# # see https://stackoverflow.com/questions/7394290/how-to-check-return-value-from-the-shell-directive
|
|
||||||
# PAPPLIED1 := $(shell patch -R -p0 -s -f --dry-run $(PTSRC1) < $(PTPAT1) 1>&2 2> /dev/null > /dev/null; echo $$?)
|
|
||||||
|
|
||||||
# # patch is pretty annoying to use here
|
|
||||||
# # we would like to apply the patch, or skip if already applied exit 0
|
|
||||||
# # inorder to do this, we first need to run a dry-run in the reverse direction
|
|
||||||
# # then check the exit code, then run it in the forward direction if actually needed
|
|
||||||
# # we also have to do the complicated line above to deal with exit codes
|
|
||||||
# # see https://unix.stackexchange.com/questions/55780/check-if-a-file-or-folder-has-been-patched-already
|
|
||||||
# patchlib1: $(PTPAT1)
|
|
||||||
# ifneq ($(PAPPLIED1),0)
|
|
||||||
# @echo "$(PTSRC1) is unpatched.\n"
|
|
||||||
# patch --forward --reject-file=- $(PTSRC1) < $(PTPAT1)
|
|
||||||
# else
|
|
||||||
# @echo "$(PTSRC1) already patched, skipping..."
|
|
||||||
# endif
|
|
||||||
|
|
||||||
# PTSRC2=lib/BehaviorTree.CPP/src/tree_node.cpp
|
|
||||||
# PTPAT2=patch/tree_node.patch
|
|
||||||
# PAPPLIED2 := $(shell patch -R -p0 -s -f --dry-run $(PTSRC2) < $(PTPAT2) 1>&2 2> /dev/null > /dev/null; echo $$?)
|
|
||||||
|
|
||||||
# patchlib2: $(PTPAT2)
|
|
||||||
# ifneq ($(PAPPLIED2),0)
|
|
||||||
# @echo "$(PTSRC2) is unpatched.\n"
|
|
||||||
# patch --forward --reject-file=- $(PTSRC2) < $(PTPAT2)
|
|
||||||
# else
|
|
||||||
# @echo "$(PTSRC2) already patched, skipping..."
|
|
||||||
# endif
|
|
||||||
|
|
||||||
.PHONY: all build watch dev start test pretest lint jestc copydist cleandist prepare
|
.PHONY: all build watch dev start test pretest lint jestc copydist cleandist prepare
|
||||||
.PHONY: test testonly
|
.PHONY: test testonly
|
||||||
|
|
||||||
|
140
README.md
140
README.md
@ -1,85 +1,91 @@
|
|||||||
[](https://github.com/wavedrom/vcd/actions/workflows/linux-napi.yml)[](https://github.com/wavedrom/vcd/actions/workflows/linux-wasm.yml)[](https://github.com/wavedrom/vcd/actions/workflows/macos-napi.yml)[](https://github.com/wavedrom/vcd/actions/workflows/macos-wasm.yml)[](https://github.com/wavedrom/vcd/actions/workflows/windows-wasm.yml)
|
Value Change Dump ([VCD](https://en.wikipedia.org/wiki/Value_change_dump)) parser using [llparse](https://github.com/nodejs/llparse) based on [wavedrom](https://github.com/wavedrom/vcd).
|
||||||
[](https://www.npmjs.org/package/vcd-stream)
|
|
||||||
|
|
||||||
Value Change Dump ([VCD](https://en.wikipedia.org/wiki/Value_change_dump)) parser using [llparse](https://github.com/nodejs/llparse)
|
## Prepare
|
||||||
|
|
||||||
|
1. [Install emcc compiler](https://kirigaya.cn/blog/article?seq=55)
|
||||||
|
|
||||||
|
2. clone https://github.com/Digital-EDA/digital-vcd-parser
|
||||||
|
|
||||||
|
## Build
|
||||||
|
|
||||||
|
```bash
|
||||||
|
source $EMCC_HOME/emsdk_env.sh
|
||||||
|
# once only
|
||||||
|
npm install browserify terser -g
|
||||||
|
# once only
|
||||||
|
node bin/build.js
|
||||||
|
# build
|
||||||
|
make -j 12
|
||||||
|
# adjust to browser environment
|
||||||
|
browserify ./bin/vcd.js | terser --compress -o ./out/vcd.js
|
||||||
|
```
|
||||||
|
|
||||||
|
production are :
|
||||||
|
|
||||||
|
- `./out/vcd.js`
|
||||||
|
- `./out/vcd.wasm`
|
||||||
|
|
||||||
|
move them to your development worksapce.
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
Install
|
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`:
|
||||||
|
|
||||||
```
|
```html
|
||||||
npm i vcd-stream
|
<!DOCTYPE html>
|
||||||
make wasm
|
<html lang="">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||||
|
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
|
||||||
|
<link rel="stylesheet" href="./vcd.css">
|
||||||
|
<title>
|
||||||
|
<%= htmlWebpackPlugin.options.title %>
|
||||||
|
</title>
|
||||||
|
<script src="./vcd.js"></script>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<noscript>
|
||||||
|
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled.
|
||||||
|
Please enable it to continue.</strong>
|
||||||
|
</noscript>
|
||||||
|
<div id="app"></div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
```
|
```
|
||||||
|
|
||||||
Require
|
In your main workspace (`App.vue` for example), goes like this:
|
||||||
|
|
||||||
```js
|
```javascript
|
||||||
let vcd = require('vcd-stream');
|
const uint8array = await readVcdFile();
|
||||||
```
|
const vcdstream = await getVcdStream();
|
||||||
|
|
||||||
Create parser writable stream instance
|
// level size diagram data
|
||||||
|
const values = {};
|
||||||
|
|
||||||
```js
|
vcdstream.change.any((id, time, cmd, value, mask) => {
|
||||||
let inst = vcd.parser();
|
if (values[id] === undefined) {
|
||||||
```
|
values[id] = [];
|
||||||
|
}
|
||||||
|
values[id].push({time, cmd, value, mask});
|
||||||
|
})
|
||||||
|
|
||||||
General event emitter
|
const maxChunkLength = 1 << 17;
|
||||||
|
for (let i = 0; i < uint8array.length; i += maxChunkLength) {
|
||||||
|
const piece = uint8array.slice(i, i + maxChunkLength);
|
||||||
|
vcdstream.write(piece);
|
||||||
|
}
|
||||||
|
|
||||||
```js
|
// structure info of wires in vcdstream.info
|
||||||
inst.on(<eventName>, () => {});
|
console.log(vcdstream.info);
|
||||||
```
|
|
||||||
|
|
||||||
Events:
|
|
||||||
* `$enddefinitions` - when all modules/wires are defined
|
|
||||||
* `finish` - end of stream
|
|
||||||
* `error` - error during parsing process
|
|
||||||
|
|
||||||
Change event emitter
|
|
||||||
|
|
||||||
```js
|
|
||||||
inst.change.on(<wireName>, (time, cmd) => {});
|
|
||||||
```
|
|
||||||
|
|
||||||
* `time` -- change time
|
|
||||||
* `cmd` -- change type
|
|
||||||
|
|
||||||
Info object
|
|
||||||
|
|
||||||
```js
|
|
||||||
let info = inst.info;
|
|
||||||
```
|
|
||||||
|
|
||||||
* `info.status` - (`'declaration'`|`'simulation'`)
|
|
||||||
* `info.wires` - hierarchy object of modules and wires
|
|
||||||
|
|
||||||
Pipe data into the instance
|
|
||||||
|
|
||||||
```js
|
|
||||||
myStream.pipe(inst);
|
|
||||||
```
|
|
||||||
|
|
||||||
## Test
|
|
||||||
|
|
||||||
### Build / Test Napi version
|
|
||||||
|
|
||||||
```
|
|
||||||
npm i
|
|
||||||
npm run mocha_napi
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### Build / Test Wasm version
|
---
|
||||||
|
|
||||||
```
|
|
||||||
make
|
|
||||||
npm run mocha_wasm
|
|
||||||
```
|
|
||||||
|
|
||||||
### Test all
|
|
||||||
|
|
||||||
```
|
|
||||||
npm test
|
|
||||||
```
|
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
/* eslint-disable no-console */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
13
bin/vcd.js
Normal file
13
bin/vcd.js
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/* eslint-disable no-undef */
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
const createVCD = require('../out/vcd.js');
|
||||||
|
const webVcdParser = require('../lib/web-vcd-parser.js');
|
||||||
|
|
||||||
|
async function getVcdStream() {
|
||||||
|
const wasm = await createVCD();
|
||||||
|
const ostream = await webVcdParser(wasm);
|
||||||
|
return ostream;
|
||||||
|
}
|
||||||
|
|
||||||
|
window.getVcdStream = getVcdStream;
|
@ -3,8 +3,6 @@
|
|||||||
const stream = require('stream');
|
const stream = require('stream');
|
||||||
const EventEmitter = require('events').EventEmitter;
|
const EventEmitter = require('events').EventEmitter;
|
||||||
|
|
||||||
const dotProp = require('dot-prop');
|
|
||||||
|
|
||||||
const commandHandler = require('./command-handler.js');
|
const commandHandler = require('./command-handler.js');
|
||||||
|
|
||||||
// function _waitForStart(mod) {
|
// function _waitForStart(mod) {
|
||||||
@ -158,24 +156,12 @@ const getWrapper = wasm => {
|
|||||||
break;
|
break;
|
||||||
// set string to path
|
// set string to path
|
||||||
case 2:
|
case 2:
|
||||||
dotProp.set(boundInfo, prop, getString(v0, v1));
|
|
||||||
// console.log(`setting ${prop} to ${getString(v0, v1)}`);
|
|
||||||
break;
|
break;
|
||||||
// path to path (any type)
|
// path to path (any type)
|
||||||
case 3:
|
case 3:
|
||||||
tmp = getString(v0, v1)
|
|
||||||
.split(',')
|
|
||||||
.map(e => dotProp.get(boundInfo, e));
|
|
||||||
if (tmp.length === 1) {
|
|
||||||
dotProp.set(boundInfo, prop, tmp[0]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
dotProp.set(boundInfo, prop, tmp);
|
|
||||||
break;
|
break;
|
||||||
// create empty object at path
|
// create empty object at path
|
||||||
case 4:
|
case 4:
|
||||||
// console.log(`${prop} is new {}`);
|
|
||||||
dotProp.set(boundInfo, prop, {});
|
|
||||||
break;
|
break;
|
||||||
case 5:
|
case 5:
|
||||||
commandHandler(boundInfo, v0, prop);
|
commandHandler(boundInfo, v0, prop);
|
||||||
|
33
out/vcd.js
33
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.
@ -42,7 +42,8 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"bindings": "^1.5.0",
|
"bindings": "^1.5.0",
|
||||||
"dot-prop": "^6.0.1",
|
"dot-prop": "^6.0.1",
|
||||||
"llparse": "^7.1.1"
|
"llparse": "^7.1.1",
|
||||||
|
"vcd-stream": "^1.5.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@drom/eslint-config": "^0.12.0",
|
"@drom/eslint-config": "^0.12.0",
|
||||||
|
@ -164,7 +164,7 @@ 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, 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
|
||||||
@ -216,7 +216,7 @@ int varNameSpan(vcd_parser_t* state, const unsigned char* p, const unsigned char
|
|||||||
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, 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;
|
||||||
@ -232,7 +232,7 @@ int onId (vcd_parser_t* state, const unsigned char* _p, const unsigned char* _en
|
|||||||
#ifndef VCDWASM
|
#ifndef VCDWASM
|
||||||
napi_env env = state->napi_env;
|
napi_env env = state->napi_env;
|
||||||
#endif
|
#endif
|
||||||
const unsigned char* p = (char *)state->idStr;
|
const unsigned char* p = (unsigned char *)state->idStr;
|
||||||
const unsigned int plen = strlen((char *)p) - 1;
|
const unsigned int plen = strlen((char *)p) - 1;
|
||||||
*(char *)(p + plen) = 0; // null instead of space
|
*(char *)(p + plen) = 0; // null instead of space
|
||||||
const unsigned char* endp = p + plen - 1;
|
const unsigned char* endp = p + plen - 1;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user