Appearance
Architecture & Internals
This chapter is intended for integrators, tool developers, and engineers who need precise insight into how the Coldwave Script VM works internally. This knowledge is not required for writing scripts but becomes essential when building external tooling, analyzing execution timing, or integrating the VM into custom systems.
Memory Segments and Banking
The VM organizes memory into logically separated segments. Each segment may exist in multiple banks, allowing isolation of contexts such as multiple programs or I/O spaces.
+-------+ +-------+ +-------+ +---------+
| IN | | OUT | | TMP | | CONST |
| Bank0 | | Bank0 | | Bank0 | | Literals|
| BankX | | BankX | | BankX | | |
+-------+ +-------+ +-------+ +---------+Segment Purposes
| Segment | Meaning | Typical content |
|---|---|---|
IN | Snapshot of external inputs | Fieldbus values, sensor readings, block inputs |
OUT | Writes applied after cycle | Actuators, registers, relays, block outputs |
TMP | Temporary execution storage | Intermediate arithmetic, expression results |
K (Constants) | Immutable values | Literal constants, parameters |
Why Banking?
Each IR instruction encodes operand indices in 6 bits, allowing direct access to slots 0-63 per segment. Banking extends this to 256 slots by setting a bank selector via the SETBANK instruction:
effective_index = (bank << 6) | local_6bit_indexThe compiler emits SETBANK automatically when a program uses more than 64 variables in a segment. Banking is transparent to the script author.
Each segment (IN, OUT, TMP, CONST) has its own independent bank selector.
Execution Phases
Each cycle executes in three steps:
Prefeed → Main Execution → Commit| Phase | Description |
|---|---|
| Prefeed | Load IN values from hardware or fieldbus; prepare block state |
| Main Execution | Run code top-down, evaluate expressions, update TMP |
| Commit | Write OUT to physical outputs |
This ensures that all logic in a cycle operates on a consistent snapshot and outputs are written atomically.
Internal Type System
The runtime uses explicit type tags (VT_*) to classify values:
VT_BOOLVT_INT,VT_DINT,VT_LINT, …VT_REAL,VT_LREALVT_TIME,VT_DATE,VT_TOD,VT_DT
Type Families
Some functions accept broader categories rather than specific types:
| Family | Meaning |
|---|---|
ANY | Any basic scalar type |
ANY_INT | All integer types, signed/unsigned |
ANY_NUM | Integers + floating point |
Generic functions like MAX, LIMIT or ADD select the correct implementation based on the actual runtime type.
Strict Type Families (Compiler)
For user-written expressions, the compiler enforces strict family boundaries. Operations between different families are compile errors:
| Family | Types | Example OK | Example ERROR |
|---|---|---|---|
| Signed integer | SINT, INT, DINT, LINT | INT + DINT | INT + UINT |
| Unsigned integer | USINT, UINT, UDINT, ULINT | UINT + UDINT | UINT + BYTE |
| Bitword | BYTE, WORD, DWORD, LWORD | BYTE + WORD | DWORD + DINT |
| Real | REAL, LREAL | REAL + LREAL | REAL + DINT |
Use explicit conversion functions (TO_DINT(), TO_REAL(), etc.) to cross family boundaries.
Note: The generic families (ANY_INT, ANY_NUM) listed above apply to built-in function signatures, where the VM handles type dispatch internally. They do not relax the strict family rules for user code.
Determinism & WCET
The VM is explicitly designed to guarantee analyzable runtime behavior.
Design Constraints
- No dynamic memory allocation in scripts
- No recursion
- Loops must have statically bounded iteration counts
- Saturating arithmetic prevents undefined overflow behavior
- Strings have bounded maximum length
These rules make worst-case execution time predictable, though the exact timing still depends on:
- CPU clock
- platform-specific VM implementation
- presence of hardware accelerators
- runtime libraries
Practical Guidelines
- Use
FORloops when an upper bound is required. - Prefer built-in blocks (TON, TOF, counter) for timing logic rather than manual loops.
- Keep computations inside
PROGRAMtight; place static wiring outside.
When This Chapter Matters
This information becomes relevant when:
- Building custom tooling (e.g., code generators, safety audits, static analyzers)
- Running multiple VM scripts on the same device and needing clean isolation
- Designing memory layouts for bus mapping or device-specific tasks
- Analyzing system timing in EN50128/IEC61508-adjacent applications
For everyday scripting, the user-level chapters are sufficient; this chapter provides deeper architectural context.