Short on time?
For the evening before a lab: set up in three steps, build one small chart in five, meet the eight surprises that catch everyone, and revise every chapter’s key ideas.
Every part links to the chapter with the full story. If you only want to revise, skip to the key ideas at the end. When you have more time, Learn teaches all of it properly, with exercises.
Set up in three steps
Section titled “Set up in three steps”-
Install VS Code, then the SCCharts Lab extension from the Extensions view (
Ctrl+Shift+X, orCmd+Shift+Xon a Mac). If KIELER’s own extension, KIELER VS Code, is installed, disable or uninstall it and reload the window: the two cannot run side by side. -
Make sure there is a C compiler, because simulation compiles your chart to C. On Windows the first simulation offers to download one. On Linux install
gccwith your package manager. On macOS run this in a terminal:Terminal window xcode-select --installJava comes with the extension on Windows (x64), Apple Silicon Macs and Linux (x64).
-
Save a chart as a file ending in
.sctx, open the diagram preview (Ctrl+Alt+V), press Simulate… and choose Netlist-based Simulation (C). Then Step runs one tick.
Getting SCCharts has the details, a chart to check your setup with, and the other tools. Everything below also runs in this page, and in the playground, with nothing installed.
One chart in five steps
Section titled “One chart in five steps”The chart is a microwave oven: a start button, a door, a heater and a lamp. Each step adds one idea
to the version before. Press Step to run a tick yourself, or Next to follow the guided tour,
which explains every tick.
States, inputs and outputs
Section titled “States, inputs and outputs”Diagram
Code
scchart Microwave { input bool start, door output bool heating = false
initial state Idle if start do heating = true go to Cooking
state Cooking if door do heating = false go to Idle}| Tick | input bool start | input bool door | output bool heating | Active state of the chart |
|---|
Guided tour, 5 ticks:
- start = true, door = falseTick 1 enters
Idle.startis already true, but a transition is not checked in the tick its state is entered, so nothing else happens. startis still true: an input keeps its value until it is changed. NowIdle’s transition is checked. It fires, setsheatingto true and moves toCooking, all in this tick.- start = false
startis released.Cookingonly reacts todoor, so nothing fires, andheatingkeeps the value it was given in tick 2. - door = trueThe door opens. The transition back to
Idlefires and switchesheatingoff in the same tick. - door = falseThe door shuts.
Idlewaits for the nextstart.
start is already true in tick 1, but the oven only starts heating in tick 2.A chart is scchart Name { … }. Declarations come first, without semicolons: an input is set by
the environment (you, in the simulator), an output by the chart. Then the states, one of them
initial. Under each state come its transitions, written if trigger do effect go to Target.
Each tick the chart reads its inputs, checks the transitions of the state it is in, takes the first whose trigger holds, and writes its outputs. Tick 1 only enters the initial state: a transition is checked from the tick after its state was entered. Thinking in ticks and Your first SCChart explain both.
A transition that wins
Section titled “A transition that wins”The first version has a flaw. Press start with the door open and it heats anyway: with both inputs
left on, it switches the heater on and off in alternate ticks. The fix is a second transition out of
Idle, written first:
Diagram
Code
scchart Microwave { input bool start, door output bool heating = false
initial state Idle if door go to DoorOpen if start do heating = true go to Cooking
state DoorOpen if !door go to Idle
state Cooking if door do heating = false go to DoorOpen}| Tick | input bool start | input bool door | output bool heating | Active state of the chart |
|---|
Guided tour, 6 ticks:
- start = false, door = falseTick 1 enters
Idle. - start = true, door = trueThe door is open and
startis pressed, in the same tick. Both ofIdle’s transitions are enabled. The one written first, numbered 1 in the diagram, wins: the chart goes toDoorOpen, andheatingstays false. - start = false, door = falseThe door shuts, and
DoorOpengoes back toIdle. - start = true
startwith the door shut. Only transition 2 is enabled now, and the oven heats. - start = false, door = trueThe door opens while the oven is cooking.
heatinggoes off, and the chart waits inDoorOpen. - door = falseThe door shuts, and the chart is back in
Idle. It does not carry on cooking: that takes anotherstart.
start is pressed. Transition 1 wins, so the oven does not heat.When several transitions of a state could fire in the same tick, the one written first wins; the
diagram numbers them 1:, 2:. Write the one that must win, here the door, first.
Triggers, effects and priority
has the rules.
A signal
Section titled “A signal”The oven should beep when it starts. A beep is an event, not a setting, so it is a signal:
Diagram
Code
scchart Microwave { input bool start, door output bool heating = false output signal beep
initial state Idle if door go to DoorOpen if start do heating = true; beep go to Cooking
state DoorOpen if !door go to Idle
state Cooking if door do heating = false go to DoorOpen}| Tick | input bool start | input bool door | output bool heating | output signal beep | Active state of the chart |
|---|
Guided tour, 5 ticks:
- start = false, door = falseTick 1 enters
Idle.beepis absent: a signal is present only in a tick in which something emits it. - start = true
start: the transition setsheatingand emitsbeep. Both are true after this tick. - start = falseNothing fires.
heatingkeeps its value, butbeepis absent again: nothing emitted it in this tick. - start = true
startagain, while the oven is cooking.Cookingdoes not react tostart, so nothing is emitted. - start = false, door = trueThe door opens:
heatinggoes off. This transition emits nothing, so there is no beep.
beep is present only in tick 2, the tick that emits it; heating stays true.output signal beep declares it, and naming it as an effect, do heating = true; beep, emits it.
Several effects are separated by ;. A signal is present only in a tick in which something emits it.
A variable such as heating keeps its last value until something writes it again. That difference
is the subject of Signals.
A second region
Section titled “A second region”The lamp inside the oven is on while the door is open or the oven is heating. It gets a state machine of its own, a second region, next to the oven’s:
Diagram
Code
scchart Microwave { input bool start, door output bool heating = false output bool lamp = false output signal beep
region Oven { initial state Idle if door go to DoorOpen if start do heating = true; beep go to Cooking
state DoorOpen if !door go to Idle
state Cooking if door do heating = false go to DoorOpen }
region Lamp { initial state Dark if door || heating do lamp = true go to Lit
state Lit if !door && !heating do lamp = false go to Dark }}| Tick | input bool start | input bool door | output bool heating | output bool lamp | output signal beep | Active state of region Oven | Active state of region Lamp |
|---|
Guided tour, 5 ticks:
- start = false, door = falseTick 1 enters the initial state of each region:
IdleinOven,DarkinLamp. - start = true
Ovenstarts cooking and setsheating.Lampreadsheatingin the same tick, sees true and switcheslampon. Regions react together, and a region sees what another has written in the same tick. - start = falseBoth regions wait.
- door = trueThe door opens.
Ovenswitchesheatingoff and goes toDoorOpen.Lampstays inLit, because the door is open. - door = falseThe door shuts.
Ovenreturns toIdle, andLamp, seeing neither the door norheating, goes dark.
Oven sets heating, and Lamp sees it in the same tick.Each region Name { … } is in one of its own states, and every region reacts in every tick. Regions
talk through variables within the tick: Lamp reads heating after Oven has written it, whichever
region comes first in the file. Give each variable one writer: if two regions could set the same
variable to different values, KIELER rejects the chart. Concurrent regions and
Why the compiler says no explain why.
Timing, an abort and an edge
Section titled “Timing, an abort and an edge”The finished oven cooks for three seconds, stops when the door opens, and starts only on a fresh
press of start:
Diagram
Code
scchart Microwave { input bool start, door, second output bool heating = false output bool lamp = false output signal beep
region Oven { initial state Idle if door go to DoorOpen if start && !pre(start) do heating = true; beep go to Cooking
state DoorOpen if !door go to Idle
state Cooking { initial state Heat if 3 second go to Done
final state Done } if door do heating = false abort to DoorOpen do heating = false; beep join to Idle }
region Lamp { initial state Dark if door || heating do lamp = true go to Lit
state Lit if !door && !heating do lamp = false go to Dark }}| Tick | input bool start | input bool door | input bool second | output bool heating | output bool lamp | output signal beep | Active state of region Oven | Active state of the region of Cooking | Active state of region Lamp |
|---|
Guided tour, 12 ticks:
- start = false, door = false, second = falseTick 1 enters
IdleandDark. - start = true
startbecomes true.start && !pre(start)holds, becausestartwas false in the previous tick. The oven beeps, heats and entersCooking, and with itHeat. The lamp comes on. - second = trueThe timer reports a second.
if 3 secondcounts it: one. - second = falseNo second has passed in this tick, so the count stays at one.
- second = trueTwo.
- second = falseStill two.
- second = trueThree:
Heatgoes toDone, a final state, soCookinghas finished. Itsjoin tofires in the same tick:heatinggoes off and the oven beeps. The lamp goes dark. - second = false
startis still true: nobody has released it. Without!pre(start)the oven would start again now. With it, nothing happens, becausestartdid not become true in this tick. - start = false
startis released. - start = trueA new press: the oven beeps and cooks again, and
if 3 secondstarts counting from zero. - door = trueThe door opens in the middle of cooking. The strong abort
abort to DoorOpenleavesCookingat once, beforeHeatreacts, and switchesheatingoff. The lamp stays on: the door is open. - door = falseThe door shuts:
DoorOpenreturns toIdle, and the lamp goes dark.startis still true, but that is not a new press.
- A count delay.
if 3 second go to Donefires in the third tick in whichsecondis true, counted from the tick afterHeatwas entered. Ticks are not seconds, so the oven needs an input that says when a second has passed, which a hardware timer would provide; in the simulator you set it yourself. The previous tick covers count delays and Counters and timeouts other ways to time things. - A superstate and an abort.
Cookinghas states inside it. Its own transitions, written after its closing brace, leave it whatever the inside is doing:if door … abort to DoorOpenstops the cooking at once, before the inside reacts (a strong abort; withgo tothe inside would react first). See Superstates and Aborts. - Termination. When the inside reaches its final state
Done, the transitiondo heating = false; beep join to Idlefires, in the same tick. - An edge.
start && !pre(start)is true only in the tick in whichstartbecomes true:pre(start)is its value in the previous tick. Without it, astartleft on would start the oven again the moment it finished. The previous tick explainspre.
Each frame’s Open in the playground link opens its chart in an editor, where you can change it and run your version.
Eight surprises
Section titled “Eight surprises”Nearly everyone meets these in their first week.
- Tick 1 only enters. In tick 1 the chart enters its initial states; their transitions are checked from tick 2 on. What happens in tick 1
- Transitions wait a tick unless they are
immediate. A transition is not checked in the tick its state is entered, so a chain of states moves one step per tick; animmediatetransition can fire in the entry tick. Delayed and immediate transitions - Inputs keep their value. In the simulators an input stays as you set it until you change it, so a button you switched on is pressed in every tick that follows. Inputs keep their value
- Signals vanish, variables stay. A signal is present only in a tick that emits it; a variable keeps the last value written to it. Signals or variables?
- Two regions cannot set one variable to different values. KIELER rejects the chart, with
The SCG is NOT asc-schedulable!, even if the two writes could never happen in the same tick. Write–write conflicts - Effects need
do, and comparisons need==.if A x = 1 go to Bandif x = 3 go to Bare both syntax errors; writeif A do x = 1 go to Bandif x == 3 go to B. Grammar traps - No
;after a declaration.input bool A;is a syntax error, reported asno viable alternative at input ';'together with a puzzling message aboutbool:mismatched input 'bool' expecting 'primitive'in SCCharts Lab,no viable alternative at input 'bool'in KIELER VS Code. A semicolon after a declaration - The first chart in the file is the one that runs. With several
sccharts in one file, KIELER simulates the first, not the one you are looking at. Several charts in one file
When it fails
Section titled “When it fails”- A message. Search Compiler messages for its words. The box at the top of that page, The messages you will meet first, covers the five that come up most. When there are several messages, start with the earliest line KIELER complains about, fix it, and look again.
- No message, wrong behaviour. My chart does not do what I expect goes through the usual symptoms, from “nothing happens in tick 1” to “my output stays true”.
- Syntax you half remember. The cheat sheet has all of it on one page, and its grammar traps list the mistakes the parser punishes.
Revision: the key ideas
Section titled “Revision: the key ideas”The summaries that end the twelve Learn chapters, in one place. If a line surprises you, its chapter is one click away.
1 Thinking in ticks
- A reactive program runs for ever, responding to its environment. SCCharts describes such programs as a sequence of ticks.
- In each tick the chart reads a snapshot of its inputs, reacts, and writes its outputs. It sees values, not changes: a held input looks the same in every tick.
- Under the synchrony hypothesis a reaction takes no time, so outputs belong to the same tick as the inputs that caused them.
- Ticks are logical time. How long a tick lasts in physical time is up to the program that runs the chart.
- The same inputs always give the same outputs.
- Tick 1 starts the chart in its initial state. Ordinary transitions out of a state are checked only from the tick after the state was entered.
2 Your first SCChart
- A chart is
scchart Name { ... }in a.sctxfile. If a file has several, the first one is run. - Inside the braces: declarations first (
input bool button,output int level = 0, no semicolons), then actions, then states. - Exactly one state is
initial; the chart starts there in tick 1. - A transition is written under its source state:
if trigger do effect go to Target. Trigger and effect are optional. - In the diagram, the initial state has a heavy outline and each transition is labelled
trigger / effect. - Start with the earliest line KIELER complains about; the other messages often follow from it.
3 Triggers, effects and priority
- A trigger is a boolean expression over the chart’s variables. Only the active state’s triggers count, with the current tick’s values.
- An effect is an assignment. Several effects are separated by
;and run left to right, each seeing the writes before it. - A state’s transitions are tried in written order; the first whose trigger holds fires, and only its effects run. The diagram numbers them when there are several.
- A transition without a trigger fires in the first tick after its state was entered. Put it last.
- A self-loop leaves its state and enters it again. To stay in a state, you need no transition.
The transition is not reachable.means an untriggered transition is hiding the ones after it.
4 Delayed and immediate transitions
- A state’s entry tick is the tick in which it is entered. Delayed transitions (no keyword,
delayedorauto) are not checked in it; immediate transitions are. - After the entry tick, all of a state’s transitions compete in priority order.
immediatenever raises a transition’s priority. - A tick follows immediate transitions until it reaches a state where none is enabled. A delayed transition can start such a chain.
- KIELER rejects every cycle made only of immediate transitions, whatever the guards. Make one transition on the cycle delayed.
- When the top level is in a final state at the end of a tick, the chart terminates and does nothing from then on.
5 Variables, types and expressions
- Inputs are written by the environment, outputs and locals by the chart. In the simulator an input keeps its value until you change it.
- Variables start at their type’s default (0, false, 0.0) or their initial value, assigned once in tick 1, in declaration order, with tick 1’s inputs available.
- Arithmetic is C’s: integer division truncates towards zero, ints wrap at 32 bits, and storing a float in an int truncates. Float literals are rounded to single precision, so never compare floats with
==. - The conditional
c ? a : bbinds tighter than everything else. Parenthesise its parts. - Prefer
x += eandx++tox = x + e. A vector assignment runs element by element, in order. - Some C details show through: strings compare as pointers, and nothing checks for division by zero or for indices out of range.
6 Signals
- A signal is present in a tick if and only if something emits it in that tick; output and local signals start every tick absent.
- Emit with the signal’s name as an effect (
do S), test with its name as a condition (if S,!S). Emitting a variable or assigning a signal is an error. - In the simulator, an input signal stays present until you set it absent.
- A valued signal adds a value: emit with
V(e), read withval(V). The value persists while the signal is absent. - Several emissions in one tick: without a combine function the last one wins; with
combine opthey are combined from the operator’s start value. - To build on a signal’s value, use last tick’s:
pre(val(V)). - In KIELER’s simulator, a chart that declares a signal never terminates.
7 Superstates
- A superstate is a state with states inside. Entering it enters its initial state in the same tick, all the way down.
- A superstate’s own transitions, written after its closing brace, leave it whichever inner state is active. The next entry starts again at the initial state.
- Declarations inside a superstate are local to it. The nearest declaration wins, and locals are initialised again on every entry.
- When the inside reaches a final state the superstate terminates, and
join tocan fire in that same tick. A join without a trigger is immediate;if c join towaits at least one tick.
8 Concurrent regions
- A region is a state machine of its own. A chart or a superstate can have several, side by side; each is in one state at a time, and all of them react in every tick.
- Regions communicate within a tick. For each variable, absolute writes come first, then updates, then reads. The order of the regions in the file does not matter, as long as you write updates with
+=and++. - A superstate with regions terminates when all of them are in final states at the same time, and its
join tofires in that tick. - The same inputs always give the same outputs. A chart without a valid order, such as two regions setting one output to different values, is rejected.
9 Aborts
- A transition written on a superstate is an abort: it can cut the inside short. A weak abort (
go to) lets the inside finish its tick first; a strong abort (abort to) leaves before the inside moves. - Aborts are delayed unless written
immediate. A strong abort reads its trigger before the inside reacts, a weak abort after. - Transitions are tried in the order written, and strong aborts must come first. A join behaves like a weak abort; when a join and a weak abort both apply, the first written wins.
- On a simple state there is no inside to skip:
go toandabort tobehave alike unless the state has aduringaction.
10 Entry, during and exit actions
- An entry action runs every time its state is entered and an exit action every time it is left, whichever transition did it. Put an effect in a state when it belongs to being in that state.
- A
duringaction runs in every tick in which its state is already active: not in the entry tick, but in the tick the state is left bygo to.immediate duringadds the entry tick. - When a transition is taken: the source’s during actions (not for
abort to), exit actions innermost first, the transition’s effects, entry actions outermost first, then the target’s immediate behaviour. - Exit actions run on strong aborts too. Only during actions depend on the kind of abort.
- A self-loop leaves and re-enters its state, so its exit and entry actions run.
- A trigger on an action is checked at that moment; a label changes only the diagram.
11 The previous tick
pre(x)is the valuexhad at the end of the previous tick. Writes in the current tick don’t change it.- In tick 1, and when a superstate is entered again for its own locals,
pre(x)is the default of the type (0,false), not the initial value. b && !pre(b)is a rising edge and!b && pre(b)a falling edge: each is true for exactly one tick. Trigger on the edge when one press should do one thing.pre(S)asks whether a signal was present in the previous tick;pre(val(V))is a valued signal’s previous value.if n Tfires in the n-th tick in whichTholds since the state was entered. Onlyimmediatecounts the entry tick, and every entry restarts the count. Inside a state with a reset self-loop KIELER rejects count delays: count by hand there.
12 Why the compiler says no
- KIELER accepts a chart only if it can order every tick so that the result cannot depend on the order of the regions. The one hole: old-style updates such as
x = x + 1in two regions; write+=. - For each variable, every tick runs all absolute writes first, then all updates, then all reads, while each region keeps its own order. Concurrent writes must agree; updates must commute.
- The check is static: it ignores triggers and values, so conflicts that only exist on paper are rejected too.
- An emission is an update and a test is a read, so emissions come before tests; a region may test a signal before emitting it.
- A cycle of immediate transitions is rejected whatever its guards; something must take time.
- Fixes: one owner, updates with
+=, a one-way dependency,pre, a delayed transition, or one region instead of two.
When the lab is over, start properly with Thinking in ticks. At the end of Learn, Put it together asks you to write a whole chart from its interface alone.