Skip to main content

ControlForge Compute Tier (RTBC)

June 2026 | ControlForge v1.0.1064

The compute tier runs a task's scans on a value-typed bytecode VM (RTBC — Real-Time ByteCode, VMf64) instead of the tree-walking interpreter, giving roughly 85–103× speedup on REAL-dominated kernels (scalar, array, and struct math). REAL is float32 per IEC, and the VM preserves that exactly.

It is opt-in per task and provably safe: flagging a task never changes results — an equivalence gate only switches a task to the VM after proving the outputs are byte-identical to the interpreter.


Enabling it — a task flag, not an ST pragma

compute is set on the task, not in ST source. Nothing in your ST changes.

tasks:
- name: KinematicsTask
scan_time_ms: 10
compute: true # request the RTBC fast path
programs: [forward_kinematics, jacobian]

Or via the API: POST /api/tasks with {"name":"KinematicsTask","scan_time_ms":10,"compute":true,"programs":[...]}.


The equivalence gate — why a flagged task may stay on the interpreter

Eligibility is about observability, not op support. On every (re)build the runtime runs the task on both the interpreter and the VM and certifies the outputs are byte-identical for a number of scans. Only then does it switch to the VM. If anything diverges, the task stays on the interpreter and records why. So compute: true is a request — it speeds up a task when that's provably safe, and silently falls back otherwise.

What this means in practice:

  • Scalar locals count as observable (since v1.0.995) — a compute task whose results live in plain locals auto-accelerates; no GVL required.
  • Cross-task or northbound reads need a GVL so the value is observable outside the task.
  • Multi-POU tasks work, including same-named locals across POUs (per-POU scoping).
  • Falls back to the interpreter on: function-block-only state, AT %QW direct addresses, and wall-clock timers.

Verifying which backend a task is on

Read the task's backend field from the task API. vm means the compute fast path is live; interpreter means it fell back (a flagged-but-ineligible task, or one you never flagged).

# GET /api/tasks → each task carries its backend
curl -s localhost:8302/api/tasks -H "Authorization: Bearer $TOKEN" \
| python3 -c 'import sys,json;[print(t["name"],t.get("backend")) for t in json.load(sys.stdin)["tasks"]]'

The runtime also logs Task '<name>' compute fast-path ENABLED (RTBC VMf64, N scans verified byte-identical) when it switches a task to the VM.


When to use it

Reach for the compute tier on tasks that do heavy REAL math every scan — kinematics, transforms, filtering, signal processing, per-symbol indicators — where the interpreter's per-node overhead dominates. For occasional or branchy logic the interpreter is already fast enough and the gate will often keep it there. Flag the task, deploy, and check that backend reads vm; if it reads interpreter, the logged divergence reason tells you what kept it on the interpreter.


  • GVL guide — when results must be read cross-task, declare them in a Global Variable List so the gate can observe them.
  • Physics twin — the physics sidecar is a separate accelerator (a supervised Rust process); the compute tier is in-process VM acceleration of your ST itself.