System Architecture
ZPLC is intentionally split into engineering surfaces and execution surfaces.
This separation protects deterministic runtime behavior in the underlying control hardware while still delivering modern IDE, compiler, and simulation workflows.
Architecture at a Glance
Primary System Boundaries
ZPLC is easier to understand if you treat it as four boundaries instead of one monolithic application:
- Authoring Boundary — Users work in the IDE, manipulating
.st,.ld, or visual models. - Compilation Boundary — Language-specific authoring converges to a canonical ST transpilation, generating the shared
.zplcbytecode. - Runtime Boundary — The C99 execution core interprets the bytecode deterministically on the target hardware.
- Platform Boundary — Hardware, persistence, timers, sockets, and OS services stay behind the Hardware Abstraction Layer (HAL).
The Major Components
1. The IDE
The IDE is the operator-facing and developer-facing engineering surface. It manages text authoring for Structured Text and Instruction List, visual authoring for Ladder Logic, FBD, and SFC, and project orchestration (compilation, deployment, debugging).
2. The Compiler
The compiler normalizes all IEC language paths into the same bytecode/runtime contract. The unified .zplc output means that ZPLC provides "one execution core, many authoring paths" without inconsistencies in runtime behavior.
3. The Runtime Core
The runtime (libzplc_core) is the execution boundary written in strict C99. It relies on standard operational models:
- Shared memory regions globally defined for Inputs (IPI), Outputs (OPI), Work, Retain, and Code.
- VM instances holding private execution states (stack pointers, registers) per task.
- Scheduler APIs managing task registration, polling, and cyclical timing.
4. The HAL Contract
The Hardware Abstraction Layer (HAL) is the bridge between the deterministic core and the physical microcontrollers.
To port ZPLC to a new architecture, a developer only needs to implement zplc_hal.h:
- Timing (
zplc_hal_tick,zplc_hal_sleep) - Digital and analog I/O manipulation
- NVS Persistence
- Networking and Sockets
- Logging Initialization
By restricting everything to the HAL, ZPLC guarantees deep portability.
Working Principles
- Keep platform code out of the core: The core must never talk directly to MCU registers or Zephyr drivers. All hardware requests go through the generic HAL.
- Deterministic execution: Memory allocation is static at compilation time. The runtime parses and executes bytecode within guaranteed bounds.
- Multi-task execution: The system isolates the execution context of individual programs while safely exposing shared global data blocks (like Modbus tags or physical Inputs).