simplify build process

This commit is contained in:
锦恢 2024-02-20 21:01:11 +08:00
parent f35f172189
commit 55d5c51f29
12 changed files with 131 additions and 165 deletions

1
.gitignore vendored
View File

@ -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
View 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
View File

@ -0,0 +1,7 @@
{
"files.associations": {
"*.rmd": "markdown",
"node_api.h": "c",
"typeinfo": "c"
}
}

View File

@ -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
View File

@ -1,85 +1,91 @@
[![Linux NAPI](https://github.com/wavedrom/vcd/actions/workflows/linux-napi.yml/badge.svg)](https://github.com/wavedrom/vcd/actions/workflows/linux-napi.yml)[![Linux WASM](https://github.com/wavedrom/vcd/actions/workflows/linux-wasm.yml/badge.svg)](https://github.com/wavedrom/vcd/actions/workflows/linux-wasm.yml)[![MacOS NAPI](https://github.com/wavedrom/vcd/actions/workflows/macos-napi.yml/badge.svg)](https://github.com/wavedrom/vcd/actions/workflows/macos-napi.yml)[![MacOS WASM](https://github.com/wavedrom/vcd/actions/workflows/macos-wasm.yml/badge.svg)](https://github.com/wavedrom/vcd/actions/workflows/macos-wasm.yml)[![Windows WASM](https://github.com/wavedrom/vcd/actions/workflows/windows-wasm.yml/badge.svg)](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).
[![NPM version](https://img.shields.io/npm/v/vcd-stream.svg)](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

View File

@ -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');
@ -108,7 +109,7 @@ const generate = (cb) => {
// scopeIdentifier scopeIdentifierEnd // scopeIdentifier scopeIdentifierEnd
const enddefinitions = p.node('inDeclarationEnd'); const enddefinitions = p.node('inDeclarationEnd');
const cmd = objection({ const cmd = objection({
$comment: 1, $comment: 1,
$date: 2, $date: 2,

13
bin/vcd.js Normal file
View 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;

View File

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

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@ -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",

View File

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