Skip to content

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

SegmentMeaningTypical content
INSnapshot of external inputsFieldbus values, sensor readings, block inputs
OUTWrites applied after cycleActuators, registers, relays, block outputs
TMPTemporary execution storageIntermediate arithmetic, expression results
K (Constants)Immutable valuesLiteral 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_index

The 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
PhaseDescription
PrefeedLoad IN values from hardware or fieldbus; prepare block state
Main ExecutionRun code top-down, evaluate expressions, update TMP
CommitWrite 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_BOOL
  • VT_INT, VT_DINT, VT_LINT, …
  • VT_REAL, VT_LREAL
  • VT_TIME, VT_DATE, VT_TOD, VT_DT

Type Families

Some functions accept broader categories rather than specific types:

FamilyMeaning
ANYAny basic scalar type
ANY_INTAll integer types, signed/unsigned
ANY_NUMIntegers + 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:

FamilyTypesExample OKExample ERROR
Signed integerSINT, INT, DINT, LINTINT + DINTINT + UINT
Unsigned integerUSINT, UINT, UDINT, ULINTUINT + UDINTUINT + BYTE
BitwordBYTE, WORD, DWORD, LWORDBYTE + WORDDWORD + DINT
RealREAL, LREALREAL + LREALREAL + 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 FOR loops when an upper bound is required.
  • Prefer built-in blocks (TON, TOF, counter) for timing logic rather than manual loops.
  • Keep computations inside PROGRAM tight; 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.