Limitations
The Ladder Diagram frontend is under active development and is gated behind the
ENABLE_LD_FRONTEND build option. This page records what is currently
supported and the known restrictions.
Supported constructs
- Contacts and coils — normally-open and normally-closed contacts; output,
Set, and Reset coils. Contacts carrying
edge="rising"/edge="falling"(and the vendor spellingspositive/negative,R/P,F/N) are sensed against the operand’s value at the contact’s previous evaluation, one sample per coil the contact feeds, rather than treated as level contacts. - Rung topology — parallel paths that reach the same coil are OR-ed, not
overwritten by the last branch. Rungs are evaluated sequentially, as in the
code Beremiz generates for MATIEC: each coil re-reads its contacts, so a rung
sees an earlier rung’s write in the same scan, and a block steps once per
scan. Graphical coils run in Beremiz’s layout order (coils less than 10 units
apart vertically share a row and are ordered left to right; rows top to
bottom), whether or not the right power rail lists them. When one variable
has both set and reset coils, the last powered coil wins and ESBMC warns. A rung path that passes through a function
block resolves the block into synthesised pins instead of being dropped, and
no path is silently dropped for being unmodellable. Power flow is solved per
node —
pf(n) = (OR over predecessors) AND cond(n)— rather than by enumerating rail-to-sink paths, so a network with re-convergent branches lowers in time linear in its size instead of exponentially. - Declared initial values —
<initialValue>on a variable declaration is parsed, so declared presets no longer read as zero. - Timers —
TON(on-delay),TOF(off-delay) andTP(pulse), with their retainedET/Qstate evaluated per scan.ETstops atPTas IEC 61131-3 §2.5.2.3.2 requires, so a timer held on indefinitely cannot overflowETand flipQback. As in MATIEC, no time elapses on the scan in whichINchanges: aTONdoes not advanceETor setQon the scanINrises, and aTOFholdsQthrough the scanINfalls. A risingINstarts aTPpulse ofPTscans that ignoresINuntil it expires. - Direction inference — a variable with no address and no interface
section is an input when something reads it and nothing writes it. The output
pins of timers, counters, arithmetic blocks and user function blocks count as
writes, so a contact that reads a timer’s
Qdoes not turn it into a free input (#8445). - Counters —
CTU(count-up) andCTD(count-down), edge-triggered on the count input. As in MATIEC,CTUcounts only whileCV < PVandCTDonly whileCV > 0.CTU’sRandCTD’sLD(or CODESYS’sLOAD) take the power flow of the contact or blockQwired to them;LDreloadsCV := PVbefore the count-down. - Non-numeric presets — a
PT/PVgiven as a variable rather than a literal is resolved rather than aborting the run. - Arithmetic function blocks —
ADD,SUB,MUL,DIV, andMOVE. - User-defined function blocks — function blocks with a Structured Text (ST)
body are translated and inlined into the scan, so custom logic (assignments,
IF/WHILE, arithmetic, comparisons, andAND/&,OR,XOR,NOTonBOOLoperands) participates in the proof. An instance’s inputs take the value of their wiring — a program variable, another block’s output pin, or aBOOLor integer literal; an unwired input, or one fed by something not modelled, is nondeterministic with a warning. Constructs the translator cannot lower over-approximate the block’s outputs as nondeterministic; a body that cannot be translated at all makes every output and in/out pin nondeterministic each scan (see Usage). - Variables written outside the program —
VAR_IN_OUT,VAR_EXTERNALand%Mmarker variables take any value at the start of each scan, since a caller, an HMI or a fieldbus may write them;--ld-closed-worldassumes only the program writes them. - Variable types —
BOOL;INTas a 16-bit signed integer andDINTandTIMEas 32-bit signed integers, as in IEC 61131-3 and MATIEC;REALas IEEE binary32 andLREALas binary64. Timers, counters and arithmetic compute in the common type of their operands, so anINTmeeting aDINTorTIMEis computed at 32 bits, and an unsuffixed real literal that meets aREALis rounded once to binary32 from its source text (#8198, #8910).--overflow-checkreports anINTsum, difference or product outside 16 bits; without it the result wraps, as MATIEC’s C does. - Properties — the five kinds described in Property Format.
Restrictions
- Input format. Programs must be supplied as PLCopen XML. Other LD serialisations are not parsed.
- POU body notations. Only the
<LD>/<ladderDiagram>body of a program POU, and the<ST>body of a function block, are translated. A POU whose body is<ST>,<FBD>,<SFC>or<IL>is rejected withUnsupportedConstruct(<notation> body of POU '<name>', tier=2). Ladder nested in<SFC>step actions is rejected with the rest of the chart: the step and transition sequencing that gates those actions is not modelled, so running them is a different program. Rejecting rather than skipping is deliberate — a body that is skipped leaves the scan cycle empty, and every property then holds vacuously. - One program, one task. A document must contain one program POU, run by
one task as one instance. More than one program POU, task or program instance
is rejected with
UnsupportedConstruct: a single scan loop cannot model a faster task preempting the program mid-scan. A function block with an LD body is rejected too; only ST bodies of function blocks are translated. - Data-path wiring. Graphical rungs translate power flow and user
function-block outputs. An operator block or a timer/counter output wired to
an
outVariable, a block wired to aPT/PVpin, aCTURorCTDLDpin fed by anything other than power flow or a block’sQ, and an unparsable literal or initial value ("1.5"for an integer) are rejected withUnsupportedConstructrather than read as 0. - Declarations and block pins. The parser refuses, rather than reads as
something else: a name declared twice in one interface, a name that starts
with
__edge_prev_,__edge_q_,__timer_prev_or__ctr_prev_, a variable of a derived type used as a contact, coil or block pin, a coilkindorstorageother thanset,resetornone, two timers or two counters that resolve to one instance name (an unnamed block takes the name of itsQvariable), anENof a standard or user function block wired to anything but the left power rail, and anENOthat feeds anything but the right power rail (#8859). A Boolean variable that only a block pin reads (IN,CU,CD,R,LD) and nothing writes is a free input, as one that only a contact reads is. - Types and values. An elementary type with no model, such as
BYTE,WORD,UINT,SINTorLINT, is refused rather than read as another type. So are anINTinitial value or literal outside 16 bits, aDINTorTIMEinitial value outside 32 bits, and a timer whoseETisINTwith a widerPT. A coil on an input variable is refused, a timer’sINandQand itsPTandET, and a counter’sPVandCV, must be distinct variables, and a counter with anINTCVneeds anINTpreset. An unparsable task interval is refused (PT0Sis accepted). - Coils, wires and blocks the translation cannot honour. Refused with
UnsupportedConstructrather than translated as something else: a negated or edge-triggered coil; a negation or edge attribute spelled in a way the parser does not recognise; a continuation wire; a block wire whoseformalParameteris not a pin of the block’s type (such asPTTfor aTON’sPT); a graphical block other than a timer or counter acting as a power-flow source; a textual<rung>that mixes a timer, counter or arithmetic block with contacts or coils; a block or output variable with a positiveexecutionOrderId; and a graphicaljump,labelorreturn, which would otherwise be dropped so that every rung ran (#8216, #8217, #8186, #8435, #8858). - Property expression syntax. Expressions in
invariantandabsenceproperties are Boolean-only: variable names combined with!,&&,||, and parentheses. Arithmetic relations (for exampleCounter >= 5) are not yet accepted in property expressions, and a variable that is notBOOLis rejected with a diagnostic (#8846). - Bounded results.
responseproperties are complete only up to their justifiedmax_scans. Under BMC,reachabilityand all other properties are checked only up to the unwind bound; use--k-inductionfor an unbounded safety proof. - Integer width. Each integer type has its IEC width (
INT16 bits,DINTandTIME32 bits); the types without a model are refused, and configurable widths are not modelled. ST intermediates between twoINToperands are 16-bit, as in IEC; MATIEC’s C promotes them toint, so the two differ only when an unstored intermediate overflows 16 bits.
Reporting issues
The frontend is evolving. Please report bugs or missing constructs on the GitHub issue tracker, ideally with the PLCopen XML and the property file that reproduce the problem.