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 junction in a vending machine
Section titled “A junction in a vending machine”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:
Diagram
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 | input bool coin10 | input bool coin20 | output signal vend | output int credit | Active state of the chart |
|---|
Guided tour, 9 ticks:
- coin10 = false, coin20 = falseTick 1 enters
Waiting. A drink costs 30 cents. - coin20 = trueA 20c coin:
credit += 20, then straight on through the connectorCheckin the same tick.credit >= 30is false, so the second, untriggered transition takes the machine back toWaiting(credit= 20). - coin20 = falseNo coin.
Waitingwaits. - coin10 = trueA 10c coin:
creditbecomes 30, andChecksees the new value at once. The first transition fires:credit -= 30andvendis emitted, all in this tick. - coin10 = false
vendis a signal, so it is present only in the tick it was emitted. - coin20 = true20c again (
credit= 20). - coin20 = falseNo coin.
- 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, soCheckvends and leavescredit= 10. - coin10 = false, coin20 = falseBack in
Waitingwith 10c of credit.
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.
The rule
Section titled “The rule”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 >= 30reads thecreditthat 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.
Why connectors help
Section titled “Why connectors help”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:
Diagrams
Vending
VendingWithout
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 | input bool coin10 | input bool coin20 | Vending: output signal vend | Vending: output int credit | Vending: Active state of the chart | VendingWithout: output signal vend | VendingWithout: output int credit | VendingWithout: Active state of the chart |
|---|
Guided tour, 9 ticks, the same inputs for both charts:
- coin10 = false, coin20 = falseTick 1 enters
Waitingin both machines. A drink costs 30 cents. - coin20 = trueA 20c coin.
Vending:credit += 20, then straight on through the connectorCheckin the same tick;credit >= 30is false, so its untriggered transition goes back toWaiting.VendingWithout: the guardcoin20 && credit + 20 >= 30is false, so its second transition adds the coin.credit= 20 in both. - coin20 = falseNo coin. Both machines wait.
- coin10 = trueA 10c coin.
Vending:creditbecomes 30, andChecksees the new value at once, so it takes the price off and emitsvend.VendingWithout: the guardcredit + 10 >= 30works out the new credit in advance and holds, so one transition does all of it. Same result in both:vend, andcredit= 0. - coin10 = false
vendis a signal, so it is present only in the tick it was emitted. - coin20 = true20c again (
credit= 20). - coin20 = falseNo coin.
- 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. - coin10 = false, coin20 = falseBack in
Waitingwith 10c of credit, in both.
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.
Starting with a decision
Section titled “Starting with a decision”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:
Diagram
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 | input bool boost | input bool toggle | output int speed | Active state of the chart |
|---|
Guided tour, 4 ticks:
- boost = true, toggle = falseThe initial state is the connector
Start, so in tick 1 the chart passes straight through it.boostis true, so the fan starts inHigh(speed= 3). Setboostto false and reset to see it start inLow. - In
High.boostonly mattered in tick 1: nothing leads back toStart. - toggle = true
toggle:HightoLow(speed= 1). - toggle = falseIn
Low.
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.
What KIELER warns about
Section titled “What KIELER warns about”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:
Diagram
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 | input bool coin | input bool enough | output int coins | Active state of the chart |
|---|
Guided tour, 5 ticks:
- coin = false, enough = falseKIELER warns
Connector states should have an outgoing transition without trigger.Tick 1 entersWaiting. - coin = trueA coin:
WaitingtoCheck.enoughis false, so no transition out ofCheckcan fire, and control stays in the connector, as if it were a normal state. - coin = falseStill in
Check: control stays in the connector, and its transitions are checked again in every tick. - enough = true
enough:ChecktoServed. - 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 finalimmediate go to ...withoutif.About this message
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.
What KIELER rejects
Section titled “What KIELER rejects”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.Diagram
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
Checkhas no outgoing transitionKIELER says:Connector states must have an outgoing transition.
A connector only passes control on: addimmediate go to Targetbelow 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 finalimmediate go to ...withoutif.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).
Diagram
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→Addform a loop that could run for ever within one tickKIELER says:The SCG is NOT asc-schedulable!
Make one transition on the loop delayed (removeimmediate): 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 (removeimmediate).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 (removeimmediate).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.
Try it
Section titled “Try it”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}Check your understanding
Section titled “Check your understanding”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.
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
immediateand 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.