Files
cnc_wams/wasm-port/docs/sim-configs-completion-plan.md
2026-06-09 06:13:28 +08:00

487 lines
16 KiB
Markdown

# LinuxCNC Sim Config Completion Plan
This plan tracks the work needed to run the LinuxCNC programs under
`linuxcnc/configs/sim` through the standalone native/WASM simulation runtime.
LinuxCNC source remains the semantic source of truth. Port code must live under
`wasm-port/`; do not edit `linuxcnc/` in place.
## Current Baseline
The latest strict harness run used `linuxcnc/configs/sim` as the program source,
selected the nearest INI/tool table for each `.ngc` unless an explicit sim
mapping is required, and ran `rs274` from the INI directory so relative
`SUBROUTINE_PATH` and `REMAP` entries resolve like a real sim config.
Result file:
```text
wasm-port/build/native/sim-configs/summary.tsv
```
Baseline:
```text
total: 159
pass: 151
fail: 8
timeout: 0
expected_fail: 8
unexpected_fail: 0
main: PASS 40, FAIL 8
macro_load: PASS 46, FAIL 0
remap_subroutine: PASS 65, FAIL 0
```
Remaining failures are explicit LinuxCNC-native baseline edges:
- `axis/external_offsets/*`: 4 failures from sim-only user M-codes `M111`.
- `axis/geometry/xyzc.ngc`: 1 failure from sim-only user M-code `M110`.
- `axis/foam/foam.ngc`: 1 failure from missing `U/V` axis support in the
LinuxCNC `bin/rs274` entry point.
- `axis/vismach/5axis/bridgemill/5axisgui.ngc`: 1 failure from missing `W`
axis support in the LinuxCNC `bin/rs274` entry point.
- `axis/vismach/5axis/table-rotary_spindle-rotary-nutating/demos/incremental_repetition_g533.ngc`:
1 failure from an upstream demo line that uses bare `X/Y/Z` words after
`G53.6` without an explicit motion G-code.
## Target
The first target is not a browser UI feature. It is a repeatable native and
WASM simulation harness that can load and execute all `linuxcnc/configs/sim`
programs that are meaningful in a standalone non-hardware simulation context.
Acceptance criteria:
- The native sim-config harness reports all executable sim programs as `PASS`.
- Macro/remap files are validated by the correct entry point: direct execution
only for real programs, load/parse or remap-call validation for subroutines.
- WASM tests cover the same representative classes after the native harness is
green.
- Any remaining unsupported files are explicitly classified as native GUI or
hardware-only and excluded by rule, not by accident.
## Phase 1: Make The Harness A First-Class Test
Status: complete. The tracked script exists and is wired into the native
validation entry point.
1. Add a tracked script:
```text
wasm-port/tests/native/verify_sim_configs.sh
```
2. Move the ad hoc test logic into the script:
- scan only `linuxcnc/configs/sim`;
- identify `.ngc`, nearest `.ini`, nearest `.tbl`;
- run from the INI directory;
- write `summary.tsv`, stdout, stderr, and interpreter output under
`wasm-port/build/native/sim-configs/`;
- classify programs as `main`, `macro_load`, `remap_subroutine`, or
`unsupported_runtime_edge`;
- fail the script only on unexpected failures.
3. Add deterministic classification rules:
- files under `remap_subs/` and `nc_subroutines/` are not standalone main
programs;
- files with no `M2`, `M30`, or `%` are load/parse fixtures unless the INI
references them through `REMAP`;
- user M-code files are tested through `USER_M_PATH` resolution, not by
pretending LinuxCNC native process services exist.
4. Wire the script into existing validation:
```text
wasm-port/tests/native/verify_native_probes.sh
```
5. Completion check:
```bash
wasm-port/tests/native/verify_sim_configs.sh
```
Latest result:
```text
total: 159
pass: 151
fail: 8
timeout: 0
expected_fail: 8
unexpected_fail: 0
skipped: 0
```
## Phase 2: Load Machine Axes From INI
Status: partially complete for the port runtime. The standalone native/WASM
runtime now parses `[TRAJ] COORDINATES`, updates the standalone external axis
mask used by LinuxCNC `GET_EXTERNAL_AXIS_MASK()`, and applies the same
`Interp::_readers` filtering that upstream `rs274ngc_pre.cc` uses. Native
regression coverage verifies that `axis_foam.ini` enables `U/V` readers and
`bridgemill/5axis.ini` enables the `W` reader.
The `verify_sim_configs.sh` baseline still records the LinuxCNC `bin/rs274`
entry-point failures as expected failures. That harness is intentionally kept
as a LinuxCNC-native baseline while the port runtime coverage tracks this
phase's standalone behavior.
Current failures:
- `axis/foam/foam.ngc`: `Bad character 'u' used`
- `axis/vismach/5axis/bridgemill/5axisgui.ngc`: `Bad character 'w' used`
Root cause:
The current standalone interpreter initialization does not configure the active
axis mask from `[TRAJ] COORDINATES` / `[KINS] KINEMATICS`. Native LinuxCNC
accepts `U/V/W` only when the machine config declares those axes.
Implementation steps:
1. Add a machine-config loader in `runtime/core/linuxcnc_wrap/`, for example:
```text
linuxcnc_machine_config.hh
linuxcnc_machine_config.cpp
```
2. Reuse vendored `inifile.cc` to parse:
- `[TRAJ] COORDINATES`
- `[KINS] KINEMATICS`
- `[DISPLAY] GEOMETRY`
- `[RS274NGC] PARAMETER_FILE`
- `[RS274NGC] SUBROUTINE_PATH`
- `[RS274NGC] USER_M_PATH`
- `[EMCIO] TOOL_TABLE`
3. Extend `initialize_minimal_interp()` / the runtime equivalent to set the
interpreter setup fields from the parsed machine config instead of hardcoded
`XYZ`.
4. Add focused native fixtures:
- `axis_foam.ini` + `foam.ngc` accepts `U/V`.
- `bridgemill/5axis.ini` + `5axisgui.ngc` accepts `W`.
5. Add the same coverage to the WASM SDK once native is green.
Completion check:
```bash
wasm-port/tests/native/verify_sim_configs.sh --only axis/foam/foam.ngc
wasm-port/tests/native/verify_sim_configs.sh --only axis/vismach/5axis/bridgemill/5axisgui.ngc
```
## Phase 3: Implement Standalone User M-Code Dispatch
Status: complete for the standalone native/WASM runtime boundary. The port now
reads `[DISPLAY] PROGRAM_PREFIX` and `[RS274NGC] USER_M_PATH`, searches
executable `M100` through `M199` files using the same order as LinuxCNC task
initialization, registers them in LinuxCNC's `USER_DEFINED_FUNCTION` table, and
records `USER_M_COMMAND` canonical boundary events instead of spawning host
processes. Native probes cover `axis/geometry` `M110` and
`axis/external_offsets` `M111`; Node WASM covers minimal `M110` and `M111`
fixtures through the Emscripten filesystem.
The `verify_sim_configs.sh` baseline still records these files as expected
failures because it intentionally runs LinuxCNC `bin/rs274`, not the standalone
task/runtime adapter.
Current failures:
- `axis/external_offsets/*.ngc`: unknown `M111`
- `axis/geometry/xyzc.ngc`: unknown `M110`
Root cause:
Native LinuxCNC resolves user M-codes through `[DISPLAY] PROGRAM_PREFIX` and
`[RS274NGC] USER_M_PATH` during task initialization, registers matching
executable `M100..M199` handlers with the interpreter, and later runs external
scripts through the task process boundary. The standalone runtime must register
the same interpreter boundary without running host processes in WASM/browser.
Implementation steps:
1. Locate the upstream M-code dispatch path in LinuxCNC and vendor the minimum
source needed to preserve semantics, or add a narrow runtime-edge adapter if
the upstream path is process-bound. Done: the adapter mirrors
`src/emc/task/emctask.cc` search/registration behavior and keeps process
execution outside CNC semantics.
2. Add `USER_M_PATH` parsing to the machine-config loader. Done.
3. For native standalone tests. Done:
- resolve `M100` through `M199` against configured search paths;
- register only executable files;
- emit deterministic `USER_M_COMMAND` boundary events.
4. For WASM/browser. Done for Node WASM:
- do not spawn host processes;
- use a host-boundary user-M adapter that registers deterministic
message-emitting handlers for sim-only notification M-codes;
- document this as a runtime edge, not CNC semantics.
5. Add tests. Done:
- `M110` from `axis/geometry`;
- `M111` from `axis/external_offsets`;
- minimal WASM `M110` and `M111` fixtures.
Completion check:
```bash
wasm-port/tests/native/verify_sim_configs.sh --only axis/external_offsets
wasm-port/tests/native/verify_sim_configs.sh --only axis/geometry/xyzc.ngc
```
Standalone runtime checks:
```bash
wasm-port/tests/native/verify_native_probes.sh
wasm-port/tests/wasm/node/verify_interp_wasm.sh
```
## Phase 4: Bring Up Python Remap Runtime Edges
Status: complete for the native sim-config harness. Current checks:
```text
gmoccapy: total 38, pass 38, fail 0
axis/laser: total 3, pass 3, fail 0
```
Root cause:
The configs use LinuxCNC Python remap modules. Earlier harness runs failed while
initializing `python/toplevel.py`; current native runs now resolve and execute
these configs under the LinuxCNC `rs274` baseline.
Implementation steps:
1. Preserve upstream behavior where possible:
- inspect vendored LinuxCNC Python plugin interfaces;
- identify exact APIs used by:
- `configs/sim/gmoccapy/python/toplevel.py`
- `configs/sim/gmoccapy/python/remap.py`
- `configs/sim/gmoccapy/python/stdglue.py`
- `configs/sim/axis/laser/python/toplevel.py`
- `configs/sim/axis/laser/python/remap.py`
2. Split the implementation into two layers:
- native harness support using the host Python runtime, if available;
- WASM support using a documented adapter boundary or a Python-free
equivalent only for runtime edges, not G-code semantics.
3. Add runtime state adapters required by Python remap:
- selected tool and pocket;
- tool table access;
- interpreter status object fields used by stdglue;
- message/error reporting;
- canonical tool-change side effects needed by `M6`, `M61`, and laser
remaps.
4. Make Python module path resolution match LinuxCNC:
- INI directory is the base directory;
- `PYTHONPATH` includes config `python/` directories;
- remap modules load relative to the sim config.
5. Add narrowly-scoped tests before running all 38 gmoccapy programs. Done:
- one gmoccapy tool-change macro;
- one gmoccapy lathe macro;
- one gmoccapy 5-axis example;
- one laser raster/vector program.
Completion check:
```bash
wasm-port/tests/native/verify_sim_configs.sh --only gmoccapy
wasm-port/tests/native/verify_sim_configs.sh --only axis/laser
```
## Phase 5: Support TWP Remaps Including G69
Status: mapping complete. The harness now maps
`axis/vismach/5axis/table-rotary_spindle-rotary-nutating/demos/*` through the
explicit `xyzacb-trsrn_twp/xyzacb-trsrn.ini` machine config instead of falling
back to `axis/axis.ini`. That loads the TWP `G69` remap declarations correctly,
and 14 of the 15 TWP demo/remap programs now pass.
Current failures:
- `axis/vismach/5axis/table-rotary_spindle-rotary-nutating/demos/incremental_repetition_g533.ngc`
fails in the LinuxCNC `rs274` baseline because line 10 uses bare
`x50y50z150` after `G53.6`; same-directory demos use explicit `G0` motion
words at this point.
Root cause:
The demo programs rely on table/spindle rotary TWP remaps. The original test
mapping fell back to `axis/axis.ini` for these demo files because the actual
INI is in a child directory:
```text
axis/vismach/5axis/table-rotary_spindle-rotary-nutating/
xyzacb-trsrn_twp/xyzacb-trsrn.ini
xyzbca-trsrn_twp/xyzbca-trsrn.ini
```
Implementation steps:
1. Improve sim-config mapping. Done:
- if a `.ngc` is under a `demos/` sibling of machine-specific INI
directories, map it to the appropriate TWP INI instead of walking upward
to `axis/axis.ini`;
- encode this as explicit metadata in the harness, not a fragile heuristic.
2. Ensure `SUBROUTINE_PATH` includes `../remap_subs:../demos` as declared by
the TWP INIs.
3. Verify remap subroutines:
- `g69remap.ngc`
- `g531remap.ngc`
- `g533remap.ngc`
- `g536remap.ngc`
4. Add a native test for each failing demo.
Latest result:
```text
total: 15
pass: 14
fail: 1
timeout: 0
expected_fail: 1
unexpected_fail: 0
skipped: 0
```
Completion check:
```bash
wasm-port/tests/native/verify_sim_configs.sh --only table-rotary_spindle-rotary-nutating
```
## Phase 6: Promote Native Coverage To WASM
Status: complete for representative Node and browser WASM coverage. Dedicated
Node and browser smokes now pass a representative vendored `configs/sim` subset
through the SDK `runSimConfigProgram()` host boundary, which copies files into
the Emscripten filesystem and forwards execution to existing LinuxCNC-backed C
ABI paths. They cover:
- `axis/foam/foam.ngc` with `axis_foam.ini`, verifying INI-driven `U/V` axis
mask handling in WASM.
- `axis/vismach/5axis/bridgemill/5axisgui.ngc` with `5axis.ini`, verifying
INI-driven `W` axis mask handling and bridge-mill NGC remap execution in
WASM.
- `axis/geometry/xyzc.ngc` with `xyzc.ini` and real executable `M110`, verifying
`USER_M_PATH` registration in WASM.
- `axis/external_offsets/dyn_demo.ngc` with `dynamic_offsets.ini` and real
executable `M111`, verifying the same user-M boundary against an upstream sim
program.
Completion checks:
```bash
wasm-port/tests/wasm/node/verify_sim_configs_wasm.sh
wasm-port/tests/browser/verify_interp_browser.sh
```
Remaining work:
1. Extend `runtime/core/linuxcnc_wrap/linuxcnc_interp_wasm.cpp` with the same
machine-config entry point used by native tests. Done for the existing
`runFileWithIni()` file-execution path.
2. Extend `runtime/sdk/src/linuxcnc-interp.js` with a host-boundary method such
as:
```js
runSimConfigProgram({ iniPath, programPath, files })
```
Done. The method only writes caller-provided text files into the
Emscripten filesystem, applies executable bits for user M-code files, and
forwards execution to the existing LinuxCNC-backed C ABI path. It does not
implement CNC semantics in JavaScript.
3. Copy required sim config files into the Emscripten FS:
- INI;
- tool table;
- parameter file;
- `.ngc` program;
- `SUBROUTINE_PATH` files;
- `USER_M_PATH` handler files or registered adapter handlers.
Done for the representative Node and browser subsets.
4. Add Node WASM coverage. Done:
```text
wasm-port/tests/wasm/node/verify_sim_configs_wasm.mjs
wasm-port/tests/wasm/node/verify_sim_configs_wasm.sh
```
5. Add representative browser coverage. Done in
`wasm-port/tests/browser/interp_smoke.html` through the existing browser
interpreter smoke and the same `runSimConfigProgram()` SDK boundary as Node.
## Phase 7: Documentation And Drift Control
Status: complete for the current representative sim-config WASM/browser
coverage. The documentation and manifest now record the native, Node WASM,
browser, source reuse, and vendor-sync state for the selected sim-config
programs.
1. Update `docs/compatibility-validation.md` with the sim-config matrix. Done.
2. Update `docs/source-reuse-map.md` for newly vendored source files. Done.
3. Update `tools/source-manifest.txt` and `tools/verify_vendor_sync.sh` if new
LinuxCNC files are copied into `wasm-port/vendor/linuxcnc`. Done for the
representative `axis/foam`, `axis/geometry`, and `axis/external_offsets`
sim-config files; no `verify_vendor_sync.sh` logic change was needed.
4. Preserve the latest result summary as a machine-readable artifact, but do
not commit generated logs unless they are intentionally used as fixtures.
Done: generated logs remain under build/test output directories, while the
tracked documentation records only the current summary values and validation
commands.
## Recommended Work Order
1. Harness first: make `verify_sim_configs.sh` reproducible.
2. Axis config next: unblock `U/V/W` failures.
3. TWP mapping: complete; remaining TWP demo failures are Python/HAL remap
runtime edges.
4. User M-code dispatch: small runtime-edge feature, unblocks five files.
5. Python remap runtime: largest block; do it after the harness and smaller
runtime edges are stable.
6. WASM promotion after native parity.
## Non-Goals
- Do not implement a new JavaScript or project-authored G-code interpreter.
- Do not edit `linuxcnc/configs/sim` or any upstream `linuxcnc/` file to make
tests pass.
- Do not fake path, modal, kinematic, tool, or parameter semantics in the SDK.
- Do not treat gmoccapy native GUI code as browser UI implementation. Only its
simulation/remap behavior is relevant to this runtime.