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

16 KiB

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:

wasm-port/build/native/sim-configs/summary.tsv

Baseline:

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:

    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:

    wasm-port/tests/native/verify_native_probes.sh
    
  5. Completion check:

    wasm-port/tests/native/verify_sim_configs.sh
    

    Latest result:

    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:

    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:

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:

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:

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:

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:

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:

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:

total: 15
pass: 14
fail: 1
timeout: 0
expected_fail: 1
unexpected_fail: 0
skipped: 0

Completion check:

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:

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:

    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:

    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.

  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.