Skip to content

Connector states

Connector states let transitions meet and branch again within a tick, so that a decision is written once.

A railway junction is not a station: trains pass over it without stopping, and which way they go depends on how the points are set. A connector state is a junction for transitions. Control arrives at it and leaves it again in the same tick, along the first of its outgoing transitions whose trigger holds.

Connectors add no new behaviour to the language. They let you write a decision once, at the point where several paths meet, instead of copying it onto every path.

A drink costs 30 cents, and the machine takes 10c and 20c coins. Both coin transitions add to credit and lead to the connector Check, which decides whether to vend:

VendingSimulation

Diagram

Diagram of VendingStates: Waiting (initial), Check (connector). Transitions: Waiting to Check: 1: coin20 / credit += 20; Waiting to Check: 2: coin10 / credit += 10; Check to Waiting: 1: credit >= 30 / credit -= 30; vend; Check to Waiting: 2:.Vendinginput boolcoin10, coin20output signalvendoutput intcredit = 0Waiting1: coin20/ credit += 202: coin10/ credit += 101: credit >= 30/ credit -= 30;vend2:

Code

scchart Vending {
input bool coin10, coin20
output signal vend
output int credit = 0
initial state Waiting
if coin20 do credit += 20 go to Check
if coin10 do credit += 10 go to Check
connector state Check
immediate if credit >= 30 do credit -= 30; vend go to Waiting
immediate go to Waiting
}
Tick 0 of 9
Inputs for tick 1 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 Vending
Tickinput bool coin10input bool coin20output signal vendoutput int creditActive 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, 9 ticks Press Next to run tick 1, or Take over to set the inputs yourself.

Guided tour, 9 ticks:

  1. coin10 = false, coin20 = falseTick 1 enters Waiting. A drink costs 30 cents.
  2. coin20 = trueA 20c coin: credit += 20, then straight on through the connector Check in the same tick. credit >= 30 is false, so the second, untriggered transition takes the machine back to Waiting (credit = 20).
  3. coin20 = falseNo coin. Waiting waits.
  4. coin10 = trueA 10c coin: credit becomes 30, and Check sees the new value at once. The first transition fires: credit -= 30 and vend is emitted, all in this tick.
  5. coin10 = falsevend is a signal, so it is present only in the tick it was emitted.
  6. coin20 = true20c again (credit = 20).
  7. coin20 = falseNo coin.
  8. coin10 = true, coin20 = trueBoth coins in one tick: Waiting’s transitions are tried in priority order, so the 20c one wins and the 10c coin is ignored: the machine keeps it, and the customer loses 10 cents. 20 + 20 = 40, so Check vends and leaves credit = 10.
  9. coin10 = false, coin20 = falseBack in Waiting with 10c of credit.
Each coin passes through Check in the tick it is inserted. In tick 4 of the tour, credit reaches 30 and is spent in the same tick.

In tick 4 the 10c coin brings credit to 30. The transition into Check and the transition out of it run in the same tick, one after the other: credit += 10, then the test credit >= 30, which sees the new value, then credit -= 30; vend. Without a coin, the machine stays in Waiting. It never rests in Check.

The ticks of the tour in which a coin arrives:

Tick Coin credit after vend
2 20c 20 absent
4 10c 0 present
6 20c 20 absent
8 20c and 10c 10 present

Tick 8 shows the priorities at work: both coins arrive in one tick, and Waiting’s first transition (the 20c one) wins: 20 + 20 = 40 vends, with 10 left over. The 10c coin is ignored: the machine keeps it, and the customer has lost 10 cents. A real machine would handle the two coins together, with a first transition if coin10 && coin20 do credit += 30 go to Check.

A connector is declared with the keyword connector: connector state Check. The diagram draws it as a small filled dot, without its name. Then:

  • Its outgoing transitions are always immediate, whether or not they say immediate. Control that reaches a connector leaves it in the same tick, as in a chain of immediate transitions. The diagram draws them dashed, like every immediate transition.
  • They are tried in priority order, like the outgoing transitions of any state: the first one whose trigger holds is taken. Give the last one no trigger, so that one of them always fires.
  • They see what the incoming transition did. Effects run in sequence along the whole path, so the test credit >= 30 reads the credit that the coin transition has just updated.

A connector may also have entry actions, which run as control passes through, and it may be the initial state of a region (see below).

KIELER implements a connector as an ordinary state whose outgoing transitions are made immediate. The keyword is a convenience and a piece of notation: it tells the reader, and the compiler’s checks, that this state is only a branching point.

Here is the same machine without a connector. Each coin now needs two transitions of its own, one that vends and one that does not, and each vending guard has to work out the new credit in advance:

Vending and VendingWithoutComparison

Diagrams

Vending

Diagram of VendingStates: Waiting (initial), Check (connector). Transitions: Waiting to Check: 1: coin20 / credit += 20; Waiting to Check: 2: coin10 / credit += 10; Check to Waiting: 1: credit >= 30 / credit -= 30; vend; Check to Waiting: 2:.Vendinginput boolcoin10, coin20output signalvendoutput intcredit = 0Waiting1: coin20/ credit += 202: coin10/ credit += 101: credit >= 30/ credit -= 30;vend2:

VendingWithout

Diagram of VendingWithoutStates: Waiting (initial). Transitions: Waiting to Waiting: 1: coin20 && credit + 20 >= 30 / credit += 20; credit -= 30; vend; Waiting to Waiting: 2: coin20 / credit += 20; Waiting to Waiting: 3: coin10 && credit + 10 >= 30 / credit += 10; credit -= 30; vend; Waiting to Waiting: 4: coin10 / credit += 10.VendingWithoutinput boolcoin10, coin20output signalvendoutput intcredit = 0Waiting1: coin20 && credit + 20 >= 30/ credit += 20;credit -= 30;vend2: coin20/ credit += 203: coin10 && credit + 10 >= 30/ credit += 10;credit -= 30;vend4: coin10/ credit += 10

Code

Vending

scchart Vending {
input bool coin10, coin20
output signal vend
output int credit = 0
initial state Waiting
if coin20 do credit += 20 go to Check
if coin10 do credit += 10 go to Check
connector state Check
immediate if credit >= 30 do credit -= 30; vend go to Waiting
immediate go to Waiting
}

VendingWithout

scchart VendingWithout {
input bool coin10, coin20
output signal vend
output int credit = 0
initial state Waiting
if coin20 && credit + 20 >= 30 do credit += 20; credit -= 30; vend go to Waiting
if coin20 do credit += 20 go to Waiting
if coin10 && credit + 10 >= 30 do credit += 10; credit -= 30; vend go to Waiting
if coin10 do credit += 10 go to Waiting
}
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.
Timing diagram of Vending and VendingWithout, no ticks yet
Tickinput bool coin10input bool coin20Vending: output signal vendVending: output int creditVending: Active state of the chartVendingWithout: output signal vendVendingWithout: output int creditVendingWithout: 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, 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. coin10 = false, coin20 = falseTick 1 enters Waiting in both machines. A drink costs 30 cents.
  2. coin20 = trueA 20c coin. Vending: credit += 20, then straight on through the connector Check in the same tick; credit >= 30 is false, so its untriggered transition goes back to Waiting. VendingWithout: the guard coin20 && credit + 20 >= 30 is false, so its second transition adds the coin. credit = 20 in both.
  3. coin20 = falseNo coin. Both machines wait.
  4. coin10 = trueA 10c coin. Vending: credit becomes 30, and Check sees the new value at once, so it takes the price off and emits vend. VendingWithout: the guard credit + 10 >= 30 works out the new credit in advance and holds, so one transition does all of it. Same result in both: vend, and credit = 0.
  5. coin10 = falsevend is a signal, so it is present only in the tick it was emitted.
  6. coin20 = true20c again (credit = 20).
  7. coin20 = falseNo coin.
  8. coin10 = true, coin20 = trueBoth coins in one tick. In both charts the 20c transitions come first in Waiting’s priority order, so the 10c coin is ignored. 20 + 20 = 40: both machines vend and keep 10c.
  9. coin10 = false, coin20 = falseBack in Waiting with 10c of credit, in both.
The same coins go into both machines, and they always agree. Switch to Code to compare them: the price, 30, appears twice in Vending and four times in VendingWithout.

Both charts behave the same in every tick. But in VendingWithout the price appears in four places, and a 50c coin would need two more transitions, one of them with yet another copy of the test. With the connector, a new coin is one new transition into Check, and the test is written once. The bigger the decision, the more this matters: with n ways in and m ways out, a connector needs n + m transitions instead of n × m.

Connectors are also handy right after a superstate finishes: join to Decide followed by a connector that looks at what the superstate computed and picks the next state.

A connector can be a region’s initial state. Then the region makes its first decision in the tick it starts. This fan starts in High or Low, depending on boost in tick 1:

FanStartSimulation

Diagram

Diagram of FanStartStates: Start (initial, connector), Low (superstate), High (superstate). Transitions: Start to High: 1: boost; Start to Low: 2:; Low to High: toggle; High to Low: toggle.FanStartinput boolboost, toggleoutput intspeed = 0Lowentry/ speed = 1Highentry/ speed = 31: boost2:toggletoggle

Code

scchart FanStart {
input bool boost, toggle
output int speed = 0
initial connector state Start
immediate if boost go to High
immediate go to Low
state Low {
entry do speed = 1
}
if toggle go to High
state High {
entry do speed = 3
}
if toggle go to Low
}
Tick 0 of 4
Inputs for tick 1 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 FanStart
Tickinput bool boostinput bool toggleoutput int speedActive 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 Press Next to run tick 1, or Take over to set the inputs yourself.

Guided tour, 4 ticks:

  1. boost = true, toggle = falseThe initial state is the connector Start, so in tick 1 the chart passes straight through it. boost is true, so the fan starts in High (speed = 3). Set boost to false and reset to see it start in Low.
  2. In High. boost only mattered in tick 1: nothing leads back to Start.
  3. toggle = truetoggle: High to Low (speed = 1).
  4. toggle = falseIn Low.
Tick 1 passes through Start and enters High because boost is true. Set boost to false and reset to start in Low.

Because a connector is left in the tick it is entered, the region is never “in” Start at the end of a tick, and nothing leads back to it, so boost matters only in tick 1.

Two habits keep a connector honest, and KIELER warns when you break them.

Write immediate on its outgoing transitions. They are immediate anyway, but without the keyword the chart reads as if they were delayed. KIELER warns, once for each such transition,

Outgoing transitions of connector states should be marked as immediate.

and treats them as immediate. Writing if credit >= 30 do ... instead of immediate if credit >= 30 do ... in the vending machine changes nothing in its behaviour.

Give it an outgoing transition without a trigger. Otherwise there may be ticks in which no way out is open, and then control simply stays in the connector, as in a normal state:

ConnectorRestsSimulation

Diagram

Diagram of ConnectorRestsStates: Waiting (initial), Check (connector), Served. Transitions: Waiting to Check: coin / coins++; Check to Served: enough.ConnectorRestsinput boolcoin, enoughoutput intcoins = 0WaitingServedcoin/ coins++enough

Code

scchart ConnectorRests {
input bool coin, enough
output int coins = 0
initial state Waiting
if coin do coins++ go to Check
connector state Check
immediate if enough go to Served
state Served
}
Tick 0 of 5
Inputs for tick 1 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 ConnectorRests
Tickinput bool coininput bool enoughoutput int coinsActive 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 Press Next to run tick 1, or Take over to set the inputs yourself.

Guided tour, 5 ticks:

  1. coin = false, enough = falseKIELER warns Connector states should have an outgoing transition without trigger. Tick 1 enters Waiting.
  2. coin = trueA coin: Waiting to Check. enough is false, so no transition out of Check can fire, and control stays in the connector, as if it were a normal state.
  3. coin = falseStill in Check: control stays in the connector, and its transitions are checked again in every tick.
  4. enough = trueenough: Check to Served.
  5. enough = falseIn Served.
Warning: A connector needs a transition without a trigger
  • Warning, line 9, column 5KIELER says: Connector states should have an outgoing transition without trigger.Otherwise the connector can get stuck. Add a final immediate go to ... without if.About this message
In tick 2 enough is false, so control stops in Check and waits there until tick 4.

KIELER warns

Connector states should have an outgoing transition without trigger.

The chart still works: control stays in Check, and its transitions are checked again in every tick. But a connector that can hold control is a state in disguise. If waiting is what you mean, use a normal state.

A connector with no way out. A connector must have at least one outgoing transition. Without one, KIELER rejects the chart:

Connector states must have an outgoing transition.
ConnectorDeadEndChart

Diagram

Diagram of ConnectorDeadEndStates: Waiting (initial), Check (connector). Transitions: Waiting to Check: coin / coins++.ConnectorDeadEndinput boolcoinoutput intcoins = 0Waitingcoin/ coins++

Code

scchart ConnectorDeadEnd {
input bool coin
output int coins = 0
initial state Waiting
if coin do coins++ go to Check
connector state Check
}

KIELER rejects this chart

  • Line 8, column 3Connector Check has no outgoing transitionKIELER says: Connector states must have an outgoing transition.A connector only passes control on: add immediate go to Target below it.About this message
Also a warning: A connector needs a transition without a trigger
  • Warning, line 1, column 1KIELER says: Connector states should have an outgoing transition without trigger.Otherwise the connector can get stuck. Add a final immediate go to ... without if.About this message
Check has no outgoing transition: KIELER rejects the chart.

Connectors in a cycle. Connectors that lead back to each other, directly or through other immediate transitions, form a cycle of immediate transitions. Below, Add and Check send control round and round, and the guard coins < 3 would end the cycle after three rounds. KIELER rejects the chart all the same: it rejects every cycle of immediate transitions, whatever its guards (see Delayed and immediate transitions).

ConnectorCycleChart

Diagram

Diagram of ConnectorCycleStates: Waiting (initial), Add (connector), Check (connector). Transitions: Waiting to Add: coin; Add to Check: 1: coins < 3 / coins++; Add to Waiting: 2:; Check to Add.ConnectorCycleinput boolcoinoutput intcoins = 0Waitingcoin1: coins < 3/ coins++2:

Code

scchart ConnectorCycle {
input bool coin
output int coins = 0
initial state Waiting
if coin go to Add
connector state Add
immediate if coins < 3 do coins++ go to Check
immediate go to Waiting
connector state Check
immediate go to Add
}

KIELER rejects this chart

  • Line 13, column 5The immediate transitions Add → Check → Add form a loop that could run for ever within one tickKIELER says: The SCG is NOT asc-schedulable!Make one transition on the loop delayed (remove immediate): a tick must always end. KIELER rejects such a loop even if the triggers would stop it.About this message
Also 2 warnings: These immediate transitions form a loop (Add → Check)
  • Warning, line 9, column 5KIELER says: There is an immediate loop. The model is not SASC. Involved states: [Check, Add]If all of them fire, the chart would run around the loop forever in one tick. Make at least one transition of the loop delayed (remove immediate).About this message
  • Warning, line 13, column 5KIELER says: There is an immediate loop. The model is not SASC. Involved states: [Check, Add]If all of them fire, the chart would run around the loop forever in one tick. Make at least one transition of the loop delayed (remove immediate).About this message
Add and Check form a cycle of immediate transitions: KIELER rejects the chart, although the guard would end the cycle.

The editor warns, once for each connector,

There is an immediate loop. The model is not SASC.
Involved states: [Check, Add]

and compiling fails with The SCG is NOT asc-schedulable!. To repeat something, let a tick pass: go through a normal state with a delayed transition.

A dial that wraps round

Dial shows a digit that up and down change by one. Make it wrap round, like the wheel of a combination lock: up at 9 gives 0, and down at 0 gives 9. Use one connector, so that the wrapping is written only once for both buttons. (Inputs keep their value, so release a button before you press it again.)

Show the starter chart
scchart Dial {
input bool up, down
output int digit = 0
initial state Idle
if up do digit++ go to Idle
if down do digit-- go to Idle
}
Show a solution
scchart Dial {
input bool up, down
output int digit = 0
initial state Idle
if up do digit++ go to Wrap
if down do digit-- go to Wrap
connector state Wrap
immediate if digit > 9 do digit = 0 go to Idle
immediate if digit < 0 do digit = 9 go to Idle
immediate go to Idle
}
Which of these makes KIELER reject a chart, rather than just warn?
Show the answer

Answer C: A connector with no outgoing transitions at all

A connector with no way out is an error: Connector states must have an outgoing transition. The first two are only warnings (the transitions are immediate anyway; without a default, control may rest in the connector), and an initial connector is fine.

A delayed transition if coin do credit += 10 go to Check leads into a connector whose first transition is immediate if credit >= 30 do vend go to Waiting. credit was 20 and coin is true in this tick. What happens?
Show the answer

Answer A: credit becomes 30, and vend is emitted in the same tick

Control passes through a connector within the tick, and the effects along the path run in order, so the test sees credit = 30 and the connector’s first transition fires at once.

Key ideas

  • A connector (connector state C, drawn as a dot) is a junction: control passes through it within the tick.
  • Its outgoing transitions are always immediate and are tried in priority order; they see the effects of the transition that led in.
  • Use a connector to write a decision once where several paths meet, or as an initial state that picks where a region starts.
  • Mark its transitions immediate and give it an untriggered last transition, or KIELER warns (and control may stop in it).
  • A connector without outgoing transitions, or a cycle of connectors, is rejected.

Next, Reusing charts: one chart used inside another, wired to its variables.

Report a mistake on this page