Skip to content

My chart does not do what I expect

Troubleshooting a chart that compiles but misbehaves: the usual symptoms, their causes and fixes, problems setting up SCCharts Lab, and a checklist for testing a chart.

Your chart compiles, but it does something other than what you meant. Find the symptom below: each comes with its usual cause, the fix, and a link to the full explanation. If the compiler gives you a message instead, look it up in Compiler messages.

Tick 1 only starts the chart: it gives every variable its initial value and enters the initial states. An ordinary transition out of a state is checked from the tick after the state was entered, so the first one can fire in tick 2, whatever the inputs are in tick 1. If something must happen in tick 1, write it as an entry action of the initial state or make the transition immediate. What happens in tick 1

The same rule, one state further on: a transition is not checked in the tick its state is entered, so every state on a path costs a tick. ChimeLate reaches Pressed in the tick of the press and chimes in the next. In ChimeNow the transition out of Pressed is immediate, so it chimes at once:

ChimeLate and ChimeNowComparison

Diagrams

ChimeLate

Diagram of ChimeLateStates: Idle (initial), Pressed. Transitions: Idle to Pressed: press; Pressed to Idle: / chime.ChimeLateinput boolpressoutput signalchimeIdlePressedpress/ chime

ChimeNow

Diagram of ChimeNowStates: Idle (initial), Pressed. Transitions: Idle to Pressed: press; Pressed to Idle: / chime.ChimeNowinput boolpressoutput signalchimeIdlePressedpress/ chime

Code

ChimeLate

scchart ChimeLate {
input bool press
output signal chime
initial state Idle
if press go to Pressed
state Pressed
do chime go to Idle
}

ChimeNow

scchart ChimeNow {
input bool press
output signal chime
initial state Idle
if press go to Pressed
state Pressed
immediate do chime go to Idle
}
Tick 0 of 4
Inputs for tick 1, for both charts Boolean input: true while on. It keeps its value until you change it.
Timing diagram of ChimeLate and ChimeNow, no ticks yet
Tickinput bool pressChimeLate: output signal chimeChimeLate: Active state of the chartChimeNow: output signal chimeChimeNow: Active state of the chart
Click a tick to show it, or use the Left and Right arrow keys to go back and step.
Guided tour, 4 ticks Both charts get the same inputs. Press Next to run tick 1, or Take over to set the inputs yourself.

Guided tour, 4 ticks, the same inputs for both charts:

  1. press = falseTick 1 enters Idle in both charts.
  2. press = truepress: both charts go to Pressed. In ChimeNow the immediate transition out of Pressed fires at once, so it chimes in this tick and is back in Idle. In ChimeLate that transition is delayed: it is not checked in the tick Pressed is entered.
  3. press = falseChimeLate chimes now, one tick late.
  4. Both charts wait in Idle.
The press comes in tick 2: ChimeNow chimes in tick 2, ChimeLate in tick 3.

immediate is the fix when the transition should fire on arrival, but a cycle made only of immediate transitions is rejected, so at least one transition on every loop must stay delayed. Count delays (if 3 A) and a join to with a trigger do not count the entry tick either. Delayed and immediate transitions

A variable keeps its value until something writes it again. Setting ding = true on a transition does not set it back afterwards, however briefly you meant it to be true:

BellVariable and BellSignalComparison

Diagrams

BellVariable

Diagram of BellVariableStates: Waiting (initial). Transitions: Waiting to Waiting: press / ding = true.BellVariableinput boolpressoutput boolding = falseWaitingpress/ ding = true

BellSignal

Diagram of BellSignalStates: Waiting (initial). Transitions: Waiting to Waiting: press / ding.BellSignalinput boolpressoutput signaldingWaitingpress/ ding

Code

BellVariable

scchart BellVariable {
input bool press
output bool ding = false
initial state Waiting
if press do ding = true go to Waiting
}

BellSignal

scchart BellSignal {
input bool press
output signal ding
initial state Waiting
if press do ding go to Waiting
}
Tick 0 of 6
Inputs for tick 1, for both charts Boolean input: true while on. It keeps its value until you change it.
Timing diagram of BellVariable and BellSignal, no ticks yet
Tickinput bool pressBellVariable: output bool dingBellVariable: Active state of the chartBellSignal: output signal dingBellSignal: Active state of the chart
Click a tick to show it, or use the Left and Right arrow keys to go back and step.
Guided tour, 6 ticks Both charts get the same inputs. Press Next to run tick 1, or Take over to set the inputs yourself.

Guided tour, 6 ticks, the same inputs for both charts:

  1. press = falseTick 1 enters Waiting in both charts.
  2. press = truepress: BellVariable sets ding to true, BellSignal emits ding. Both read true after this tick.
  3. press = falseNothing fires. The variable keeps the value it was given; the signal is absent, because nothing emitted it in this tick.
  4. The same: the variable stays true.
  5. press = trueAnother press: the signal is present again. The variable was true all along.
  6. press = falseTo make the variable read like the signal, something would have to set it back to false in every tick after the press.
Both react to the presses in ticks 2 and 5: the variable stays true from tick 2 on, while the signal is present only in ticks 2 and 5.

If the output marks an event (“a coin was inserted”, “beep now”), declare it as a signal: a signal is present only in a tick that emits it. If it is a setting that lasts, keep the variable and write false where the setting ends, on the transition that leaves the state or in its exit action. Signals or variables? and Entry, during and exit actions

A chart sees values, not changes. While a button is held down, press is true in every tick, and an input in the simulators keeps its value until you change it, so a button you switched on stays pressed. To react once per press, react to the tick in which it becomes true, press && !pre(press):

PressCounter and PressCounterEdgeComparison

Diagrams

PressCounter

Diagram of PressCounterStates: Counting (initial). Transitions: Counting to Counting: press / count++.PressCounterinput boolpressoutput intcount = 0Countingpress/ count++

PressCounterEdge

Diagram of PressCounterEdgeStates: Counting (initial). Transitions: Counting to Counting: press && !pre(press) / count++.PressCounterEdgeinput boolpressoutput intcount = 0Countingpress && !pre(press)/ count++

Code

PressCounter

scchart PressCounter {
input bool press
output int count = 0
initial state Counting
if press do count++ go to Counting
}

PressCounterEdge

scchart PressCounterEdge {
input bool press
output int count = 0
initial state Counting
if press && !pre(press) do count++ go to Counting
}
Tick 0 of 7
Inputs for tick 1, for both charts Boolean input: true while on. It keeps its value until you change it.
Timing diagram of PressCounter and PressCounterEdge, no ticks yet
Tickinput bool pressPressCounter: output int countPressCounter: Active state of the chartPressCounterEdge: output int countPressCounterEdge: Active state of the chart
Click a tick to show it, or use the Left and Right arrow keys to go back and step.
Guided tour, 7 ticks Both charts get the same inputs. Press Next to run tick 1, or Take over to set the inputs yourself.

Guided tour, 7 ticks, the same inputs for both charts:

  1. press = falseTick 1 enters Counting in both charts.
  2. press = trueThe button goes down. Both charts count one.
  3. The button is still down: an input keeps its value. PressCounter sees press true again and counts two. PressCounterEdge waits for press to become true, and it already was.
  4. Still held: PressCounter is at three, PressCounterEdge still at one.
  5. press = falseThe button is released.
  6. press = trueA second press. PressCounterEdge counts two presses, PressCounter four ticks.
  7. press = falseReleased.
The first press is held for three ticks: PressCounter counts ticks, PressCounterEdge counts presses.

To press a button for a single tick in this guide’s simulations, use the pulse button next to its switch; in SCCharts Lab, switch the input on, step, and switch it off again. Edges and pulses has the recipes, and Debouncing the cure for a real button that bounces.

A variable declared inside a state is initialised again every time that state is entered: by a self-loop, by a transition back into its superstate, even by a history transition. So a counter declared there starts over on every visit, and an entry do n = 0 does the same on every self-loop. Declare the counter one level further out, at the top of the chart or in a superstate that stays active, or make it static. Fresh on every entry, Self-loops leave and come back and History restores states, not data

KIELER rejects a chart in which two concurrent regions could set one variable to different values, with The SCG is NOT asc-schedulable! and a list of Can't schedule from … lines. It does so even when you know that the two writes never happen in the same tick: the check looks at the chart’s structure, not at its triggers. Give the variable one owner, a single region that does all the writing, and let the other regions send it requests with signals. Increments such as count += 1 from several regions are allowed: they add up. Write–write conflicts, One writer per variable, and Sharing a resource for an owner that hands a device to one region at a time.

If such a chart compiles but its result changes when you swap the order of its regions in the file, look for updates written the old way, x = x + 1, in two regions. A trap: old-style updates

A chart counts ticks, not seconds. If whatever runs it ticks at a fixed rate, counting ticks is measuring time: at one tick every 10 ms, if 300 true go to Off waits three seconds. If the hardware has a timer that sets an input once a second, count that input instead, if 3 second, as the oven in Short on time? does. And if the environment can say how much time has passed, a clock measures it directly. Counters and timeouts and Time

I cannot leave a superstate from inside it

Section titled “I cannot leave a superstate from inside it”

A transition connects two states on the same level, so a state inside a superstate cannot go to a state outside it: KIELER says Couldn't resolve reference to State 'Idle'., with your state’s name. There are two ways out. A transition written on the superstate itself, after its closing brace, leaves it whatever the inside is doing. Or the inside reaches a final state, and the superstate’s join to fires. Leaving from anywhere and Final states and join to

A join to fires when every region of its superstate is in a final state at the same time. Look for one of these:

  • A region without a final state, or one whose final state is never reached. KIELER warns about a missing one (Every region should have a final state…, All or none concurrent regions…). Give every region a final state that it can reach.
  • A region that leaves its final state again. A final state may have outgoing transitions; if a region moves on before the others arrive, the regions are never final together.
  • A signal declared in the superstate, together with an action. In KIELER a superstate that declares a signal and also has an entry, during or exit action never terminates, even when all its regions are final. There is no warning:
PrintStuck and PrintFixedComparison

Diagrams

PrintStuck

Diagram of PrintStuckStates: Idle (initial), Printing (superstate), Feeding (initial), Fed (final), Waiting (initial), Counted (final). Transitions: Feeding to Fed: / fed; Waiting to Counted: fed / pages++; Idle to Printing: job; Printing to Idle: / busy = false.PrintStuckinput booljoboutput intpages = 0output boolbusyIdlePrintingsignalfedentry/ busy = trueFeedFeedingFed/ fedCountWaitingCountedfed/ pages++job/ busy = false

PrintFixed

Diagram of PrintFixedStates: Idle (initial), Printing (superstate), Feeding (initial), Fed (final), Waiting (initial), Counted (final). Transitions: Feeding to Fed: / fed; Waiting to Counted: fed / pages++; Idle to Printing: job; Printing to Idle: / busy = false.PrintFixedinput booljoboutput intpages = 0output boolbusysignalfedIdlePrintingentry/ busy = trueFeedFeedingFed/ fedCountWaitingCountedfed/ pages++job/ busy = false

Code

PrintStuck

scchart PrintStuck {
input bool job
output int pages = 0
output bool busy
initial state Idle
if job go to Printing
state Printing {
signal fed
entry do busy = true
region Feed:
initial state Feeding
do fed go to Fed
final state Fed
region Count:
initial state Waiting
if fed do pages++ go to Counted
final state Counted
}
do busy = false join to Idle
}

PrintFixed

scchart PrintFixed {
input bool job
output int pages = 0
output bool busy
signal fed
initial state Idle
if job go to Printing
state Printing {
entry do busy = true
region Feed:
initial state Feeding
do fed go to Fed
final state Fed
region Count:
initial state Waiting
if fed do pages++ go to Counted
final state Counted
}
do busy = false join to Idle
}
Tick 0 of 6
Inputs for tick 1, for both charts Boolean input: true while on. It keeps its value until you change it.
Timing diagram of PrintStuck and PrintFixed, no ticks yet
Tickinput bool jobPrintStuck: output int pagesPrintStuck: output bool busyPrintStuck: Active state of the chartPrintStuck: Active state of region Feed (in Printing)PrintStuck: Active state of region Count (in Printing)PrintFixed: output int pagesPrintFixed: output bool busyPrintFixed: Active state of the chartPrintFixed: Active state of region Feed (in Printing)PrintFixed: Active state of region Count (in Printing)
Click a tick to show it, or use the Left and Right arrow keys to go back and step.
Guided tour, 6 ticks Both charts get the same inputs. Press Next to run tick 1, or Take over to set the inputs yourself.

Guided tour, 6 ticks, the same inputs for both charts:

  1. job = falseTick 1 enters Idle in both charts.
  2. job = truejob: both charts enter Printing and set busy.
  3. job = falseIn both charts both regions reach their final states. In PrintFixed the join to fires at once, and busy is false again. In PrintStuck, whose Printing declares the signal fed and has an entry action, it never fires.
  4. PrintStuck stays in Printing for good.
  5. job = trueA second job: only PrintFixed can start again.
  6. job = falsePrintFixed has counted two pages, PrintStuck one.
Note: KIELER never takes the join of Printing: it declares signals (fed) and has state actions (PrintStuck)
  • Note in PrintStuck, line 9, column 9KIELER moves the regions of such a state into a helper state that never finishes. Declare the signals one level up, or move the actions out of the state.
Both charts reach Fed and Counted in tick 3, but only PrintFixed, which declares fed in the chart instead of in Printing, leaves through its join to.

Declare the signal one level further out, as PrintFixed does, or move the action onto the transition that enters the superstate. Final states and join to ends with this case.

Only go to S history (or shallow history) resumes S where it was left; a plain go to S always starts it again from its initial states. If you did write history and the state still starts over, look at where it is nested. KIELER honours a history transition into a nested state only if every superstate around that state is itself the target of some history transition, and silently treats any other one as a plain go to:

MenuNested and MenuNestedFixedComparison

Diagrams

MenuNested

Diagram of MenuNestedStates: Off (initial, superstate), On (superstate), Home (initial, superstate), Settings (superstate), Brightness (initial, superstate), Contrast (superstate). Transitions: Brightness to Contrast: right; Home to Settings: menu; Settings to Home: home; Off to On: power; On to Off: !power.MenuNestedinput boolpower, menu, home, rightoutput intscreen = 0Offentry/ screen = -1OnHomeentry/ screen = 0SettingsBrightnessentry/ screen = 11Contrastentry/ screen = 12rightmenuhomepower!power

MenuNestedFixed

Diagram of MenuNestedFixedStates: Off (initial, superstate), On (superstate), Home (initial, superstate), Settings (superstate), Brightness (initial, superstate), Contrast (superstate). Transitions: Brightness to Contrast: right; Home to Settings: menu; Settings to Home: home; Off to On: power; On to Off: !power.MenuNestedFixedinput boolpower, menu, home, rightoutput intscreen = 0Offentry/ screen = -1OnHomeentry/ screen = 0SettingsBrightnessentry/ screen = 11Contrastentry/ screen = 12rightmenuhomepower!power

Code

MenuNested

@layout[elk.direction] DOWN
scchart MenuNested {
input bool power, menu, home, right
output int screen = 0
initial state Off {
entry do screen = -1
}
if power go to On
state On {
initial state Home {
entry do screen = 0
}
if menu go to Settings history
state Settings {
initial state Brightness {
entry do screen = 11
}
if right go to Contrast
state Contrast {
entry do screen = 12
}
}
if home go to Home
}
if !power go to Off
}

MenuNestedFixed

@layout[elk.direction] DOWN
scchart MenuNestedFixed {
input bool power, menu, home, right
output int screen = 0
initial state Off {
entry do screen = -1
}
if power go to On shallow history
state On {
initial state Home {
entry do screen = 0
}
if menu go to Settings history
state Settings {
initial state Brightness {
entry do screen = 11
}
if right go to Contrast
state Contrast {
entry do screen = 12
}
}
if home go to Home
}
if !power go to Off
}
Tick 0 of 9
Inputs for tick 1, for both charts Boolean input: true while on. It keeps its value until you change it. Boolean input: true while on. It keeps its value until you change it. Boolean input: true while on. It keeps its value until you change it. Boolean input: true while on. It keeps its value until you change it.
Timing diagram of MenuNested and MenuNestedFixed, no ticks yet
Tickinput bool powerinput bool menuinput bool homeinput bool rightMenuNested: output int screenMenuNested: Active state of the chartMenuNested: Active state of the region of OnMenuNested: Active state of the region of On.SettingsMenuNestedFixed: output int screenMenuNestedFixed: Active state of the chartMenuNestedFixed: Active state of the region of OnMenuNestedFixed: Active state of the region of On.Settings
Click a tick to show it, or use the Left and Right arrow keys to go back and step.
Guided tour, 9 ticks Both charts get the same inputs. Press Next to run tick 1, or Take over to set the inputs yourself.

Guided tour, 9 ticks, the same inputs for both charts:

  1. power = false, menu = false, home = false, right = falseTick 1 enters Off in both (screen = −1).
  2. power = truePower on: the first visit to On starts in Home (0).
  3. menu = trueThe first visit to Settings: Brightness (11).
  4. menu = false, right = trueContrast (12).
  5. right = false, home = trueHome (0).
  6. home = false, menu = trueBack to Settings with history. MenuNested: surprise, Settings starts again in Brightness (11). On is not the target of a history transition, so KIELER silently treats go to Settings history as a plain go to Settings. MenuNestedFixed: On is a history target (from Off), so the history inside it works: Contrast (12).
  7. menu = false, power = falsePower off: Off (−1).
  8. power = truePower on. MenuNested starts On in Home (0). MenuNestedFixed enters On with shallow history, so it resumes in Settings, which starts again in Brightness (11). The fix changed what switching on does.
  9. Home in MenuNested, Brightness in MenuNestedFixed.
Note: KIELER ignores this history: Settings restarts from its initial state (MenuNested)
  • Note in MenuNested, line 15, column 5KIELER only handles history on transitions into states of the chart's top-level regions, or inside a state that is itself the target of a history transition. Here Settings is nested in a state without one, so this transition behaves like a normal transition. Move the mode switch to the top level, or give the enclosing state a history transition too.
Both open Contrast in tick 4, go home and open the menu again in tick 6: MenuNested starts Settings again, MenuNestedFixed resumes it.

A history transition that is silently ignored has the details and the fix.

A chart terminates when every region at its top level is in a final state, and then it does nothing more. If yours runs on:

  • Check the final states, as for a join to above: every top-level region needs one, and all of them must be final in the same tick.
  • A chart that declares any signal never terminates in KIELER’s simulator, even in its final states: an input, output or local signal is enough. The simulation adds an action of its own to every chart, so the rule of the previous section applies to the chart itself. This guide’s simulations do the same.

Most reactive systems never terminate, and do not need to. If yours should stop, letting it rest in final states without outgoing transitions is usually all you need: the chart then stays there. Signals and termination

When several transitions could fire, the order decides:

  • The first transition written wins. A state’s transitions are tried in the order they are written (1:, 2: in the diagram), and only the first whose trigger holds fires. Put the one that must win first; a safety check goes at the top. Priority
  • A transition without a trigger hides the ones after it. It always holds, so a delayed transition written after it can never fire, and KIELER warns The transition is not reachable. Write it last.
  • abort to beats go to. Strong aborts must be written first, so they win over weak aborts and join to in the same tick. Several ways out
  • The inside of a superstate still fired in the tick you left it. That is a weak abort, go to: the inside finishes its tick first. If it must not, use abort to. Weak and strong

An exit action ran although I used abort to

Section titled “An exit action ran although I used abort to”

That is KIELER’s rule: exit actions run however a state is left, a strong abort included. abort to skips the inner transitions and the during actions of the tick it fires in, never the exit actions (the KIELER wiki says otherwise, and is out of date there). Write exit actions as clean-up that always happens, and put what must not happen on an emergency stop on the transitions that end the state normally. Actions and aborts

Tick 1 has no previous tick, so in tick 1 pre(x) is the default of the type, 0 or false, not the initial value of x. A test such as temp > pre(temp) is then true in tick 1 although nothing has changed. A plain during action does not run in the tick its state is entered, so for the initial state it skips tick 1:

Rising and RisingFromTick2Comparison

Diagrams

Rising

Diagram of RisingStates: Watch (initial, superstate). Transitions: none.Risinginput inttempoutput boolrisingWatchimmediate during/ rising = temp > pre(temp)

RisingFromTick2

Diagram of RisingFromTick2States: Watch (initial, superstate). Transitions: none.RisingFromTick2input inttempoutput boolrisingWatchduring/ rising = temp > pre(temp)

Code

Rising

scchart Rising {
input int temp
output bool rising
initial state Watch {
immediate during do rising = temp > pre(temp)
}
}

RisingFromTick2

scchart RisingFromTick2 {
input int temp
output bool rising
initial state Watch {
during do rising = temp > pre(temp)
}
}
Tick 0 of 5
Inputs for tick 1, for both charts
Timing diagram of Rising and RisingFromTick2, no ticks yet
Tickinput int tempRising: output bool risingRising: Active state of the chartRisingFromTick2: output bool risingRisingFromTick2: Active state of the chart
Click a tick to show it, or use the Left and Right arrow keys to go back and step.
Guided tour, 5 ticks Both charts get the same inputs. Press Next to run tick 1, or Take over to set the inputs yourself.

Guided tour, 5 ticks, the same inputs for both charts:

  1. temp = 20Tick 1. In Rising the immediate during action runs at once and compares 20 with pre(temp), which is 0 in tick 1: rising is true. In RisingFromTick2 the plain during action waits for the next tick, so rising stays false.
  2. From here on both charts compare temp with its real previous value, and agree.
  3. temp = 2121 after 20: rising, in both.
  4. temp = 2323 after 21: rising.
  5. temp = 2222 after 23: not rising.
temp is 20 from tick 1, and only Rising, with immediate during, reports a rise in tick 1.

So if a comparison with pre must skip tick 1, put it in a plain during action, as RisingFromTick2 does, or on a delayed transition: neither runs in the tick its state is entered.

Another cause: a variable whose initial value is built on another one that reads an input can come out wrong in tick 1, because of a bug in KIELER’s compiler; compute it on a transition instead (Tick 1 runs input-free initial values first). Tick 1 has no past has more on pre in tick 1.

The playground runs this guide’s own engine, a reimplementation of KIELER’s compiler checks and simulator that runs in the browser. Every example in the guide has been checked against KIELER, but your own chart has not, and SCCharts Lab runs KIELER’s actual compiler. Before you suspect either of them, check that the two runs really are the same:

  • The same inputs in the same ticks. Both keep an input’s value until you change it, so an input left on in one and switched off in the other gives different runs.
  • The same simulation system. The guide follows Netlist-based Simulation (C). Others, such as Priority-based Simulation (C), differ in a few details, for example in tick 1.
  • The same chart. Both run the first scchart in the file.
  • The same KIELER. The official KIELER VS Code extension (0.3.0) has an older compiler than SCCharts Lab. They behave the same on the charts checked so far, but they do not accept quite the same charts. How this guide is checked lists the differences.

If they still disagree, trust SCCharts Lab, and please report it, with the playground’s Copy link for your chart and the inputs that show the difference.

Getting SCCharts has the installation steps. When something still does not work:

The file must end in .sctx: the status bar then shows the language mode SCTX. Open the diagram with the preview button in the editor’s title bar or Open Diagram Preview (Ctrl+Alt+V). If no SCCharts Lab command works at all, the extension has not started: look for one of the two messages below, about KIELER VS Code or about Java. A diagram that stops updating comes back with Restart diagram (Ctrl+Alt+D), or with Restart KIELER language server from the Command Palette.

  • Fix the errors first. A chart with errors in the Problems panel does not compile, so it cannot run.
  • Choose a system. Simulate… in the preview’s toolbar asks for one: choose Netlist-based Simulation (C). The first run compiles the chart to C and takes a few seconds.
  • A C compiler. The C simulation needs one. Without it SCCharts Lab says C simulation needs a C compiler. On Windows it offers to download a portable GCC; on macOS run xcode-select --install; on Linux install gcc (sudo apt install build-essential on Debian or Ubuntu).
  • In the KIELER VS Code extension, a chart with certain syntax errors never finishes compiling, and no message says so: a keyword used as a name (input bool reset, go, period), a number above 2147483647, or if 3 == level. Fix the errors the editor marks, and simulate again. Compiler messages explains them; SCCharts Lab stops at them with an error instead.

SCCharts Lab: Show Java runtime and C compiler in use in the Command Palette says what the extension found.

On Windows (x64), Apple Silicon Macs and Linux (x64) the extension brings its own Java. On other platforms it needs Java 21 or newer, and says so if it finds none:

SCCharts Lab needs Java 21 or newer and found none.

Install a Java 21 JDK, or point the setting keith-vscode.javaHome at one, then reload the window. To use a C compiler that is not on your PATH, such as an existing MinGW or MSYS2 gcc.exe on Windows, set keith-vscode.cCompilerPath to it; if that path is wrong, the message is The configured C compiler was not found: followed by the path. You never need javac: it is only for the Java simulations, and the C simulation is the one to use. KIELER’s own extension needs Java on your PATH and a C compiler too.

The two extensions register the same commands and languages, so they cannot run side by side. With KIELER VS Code enabled, SCCharts Lab does not start and says:

SCCharts Lab cannot run beside KIELER VS Code. Uninstall it, then reload the window.

Uninstall and reload does exactly that; disabling KIELER VS Code in the Extensions view and reloading works too. If your course needs the official extension, disable SCCharts Lab instead: your .sctx files work in both.

A chart is only as good as the runs you have tried. Before you hand one in:

  • Set every input in tick 1, and remember that tick 1 only enters the initial states.
  • Press and hold. Try each button for a single tick and held down for several. Inputs keep their value, so a held button is what you get if you forget to switch it off.
  • Run the coincidences. Two inputs in the same tick, an input in the very tick a timeout fires, an input in the tick a state is entered. Each is decided by one detail of the chart, a priority or a delay, and each takes one tick to try.
  • Run the failures, not only the expected sequence: a sensor that never reports, a door opened at the worst moment, two inputs that should never come together.
  • Check the end of every phase, not only its start: does the output go off in the tick you expect, or one tick later?

SCCharts Lab helps with all of this:

  • Save and Load, at the right end of the trace’s top line, write a run to a .ktrace file and replay it. Save a test once and replay it after every change to the chart.
  • Breakpoints, in the preview’s toolbar, pause the simulation when a state is entered, or after a tick in which a condition holds, such as heating && door. The C key runs ticks until one fires.
  • Watch expressions, in the trace’s top line, are evaluated after every tick: pre(count) != count, say.
  • Back (Backspace) rewinds one tick, and clicking an earlier tick’s header in the trace rewinds to it, so you can try another input from there.

In the playground, Rebuild after an edit replays the inputs you have given so far on the new version of the chart, as long as its inputs and outputs are unchanged. Under Variables, Watch shows the value of an expression in the tick shown, and Run until steps until the watch holds or a state you choose is active.

Report a mistake on this page