Alan Shaw, Spring 98

1. Requirements and Design Languages

The particular notations that are selected to express requirements or designs can have a very important impact on the construction time, correctness, efficiency, and maintainability of the target system. One desirable property for such a language is that it be precise and unambiguous, so that clients and implementors can agree on the required behaviors and recognize them in operation; the need for this feature, often called "formality", eliminates natural languages, e.g. English. The notation should be easy to use by the involved parties. For example, many designers prefer graphical languages over textual ones for documentation purposes but may need symbolic, i.e. mathematical, notation for analysis.

It should also be possible to state and prove properties of a system before it is built. This means that the selected notation is amenable to formal manipulation. For most actual systems, behaviors cannot be proven a priori; however, they can frequently be demonstrated through simulation or prototyping. This is particularly convenient to do if the specification language is executable. Executable specifications are also useful for clarifying and refining requirements and designs. Another desirable feature - one that is particularly difficult to achieve - is scalability; many systems are quite large, and notations that work well in-the-small often become intractable when applied to larger applications.

It is convenient to distinguish between imperative and descriptive languages. Imperative or operational methods specify behaviors by describing and listing sequences of instructions or actions to be taken by some agent, that generate the behaviors. They are directly executable in that they translate easily into corresponding computer procedures. With these notations, it is straightforward to generate examples of the specified behaviors, either manually or automatically, and thereby debug specifications. This executability allows fast prototyping of systems; in principle, such prototypes can evolve into implementations. Operational techniques also appeal to engineers because they are trained to understand systems in these terms, making it relatively easy to visualize the behaviors.

Descriptive, denotational, or assertional notations directly specify properties that must be satisfied, rather than directly generate behaviors with the desired properties. They are based on conventional mathematics, such as set theory, algebra, and symbolic logic. Some of the descriptive schemes can also be "executed" to generate their implied behaviors. It is normally easier to state and prove properties with these languages, but more difficult to use them for design. A common approach is to describe and test a system operationally, and then use an assertional notation to express and verify its properties.

Examples of denotational methods include : algebraic and set theoretic schemes such as OBJ [Goguen_et_al88] and Z [Spivey89]; language-based notations such as regular expressions and flow expressions [Shaw78]; and assertional logics such as various temporal logics (e.g., [Manna&Pnueli92; Bernstein&Harter81]) and real-time logic [Jahanian&Mok86]. Combinations of English and mathematics have also been employed.

Most of the imperative notations are similar to or derived from programming languages. Examples are CSP [Hoare84], UNITY [Chandy&Misra88], and CSR [Gerber&Lee92]. A popular but informal notation related to functional programming is data flow diagrams (DFDs) [Ghezzi_et_al91b; Ward&Mellor85]. They have been used extensively in information systems applications and, to a lesser extent, for real-time specifications. One attraction of DFDs is their simple graphical representation.

Another popular class of operational notations is state-based and admits to natural graphical representations. Many of these are variations of the Petri-net formalism (e.g., [ Ghezzi_et_al91] ). Others, such as statecharts [Harel87], Modecharts [Jahanian&Mok94], ESL [Ostroff&Wonham87], input-output automata [Lynch&Tuttle89], and CRSMs [Shaw92], are extensions of standard state machines or automata. Tabular methods, for example, those used in the SCR project [Heninger80], are based on decision tables; they are mainly imperative and state-based, but also have a descriptive flavor.

2. State Machines

Various forms of state machines have been used since the first days of computing for modelling and design. They are natural notations for describing and reasoning about switching circuits, and many event-driven algorithms and software; and have an appealing graphical representation. In addition, a major part of computer science theory, automata theory, is based on these machines [Hopcroft&Ullman79]. The systems model that we defined informally in Section 2.1 is in fact a state machine.

The standard finite state machine (fsm) contains a finite number of states, and a transition or next-state function that maps states and events (inputs) into states. At any point, the system is in a given state. The occurrence of an event causes the system to change state according to the transition function definition. A machine normally has one start state and zero or more halt states. An fsm starts executing in its start state, changing states according to the input that it receives, until it reaches a halt state. The graphical form of an fsm is a state diagram; this is a directed labelled graph, where the vertices denote states and edges represent transitions.

 

Example

Consider the behavior and associated events of a gate at a train crossing . The gate could be in one of four states: open, closed, opening, and closing. The relevant events are: cg and og which are commands to close and open the gate, respectively; and o-o and c-c indicating, for example from sensors, that the gate has completed opening (and thus changed from the opening to theopened state), and that the gate has completed closing, respectively. Figure 3.5 is a finite state machine description of this behavior given in state diagram form.

The initial (start) state is closed and there are no stop (halt) states. This fsm accepts the cg and og commands in all of its states; thus, for example, the gate may be commanded to close while it is opening. Another kind of gate may not accept these two commands while opening or closing.

 

 

A more interesting and powerful version of the state machine model allows guards, inputs, outputs, and actions on transitions. A transition between states U and V is defined by an expression:

G ® I / A / O

where G is a Boolean guard, I is an input event, A is an action, and O is an output . The meaning is:

If the machine is in state U, the guard G is true, and event I occurs, then perform action A, generate the output event O, and enter state V.

The actions are usually computations, but they could also denote physical activities such as opening a valve. The guard can be interpreted as an enabling condition for the transition.

 

Example

Figure 3.6 contains the state diagram for an extended fsm specifying a simple controller for our train crossing gate. Input events are Train_Entering and Train_Leaving signals; the output events are Open_Gate and Close_Gate commands. As in Figure 3.2, the state variable count keeps track of the number of trains in the crossing area. The guards (count=1 and count>1) determine which transition is taken on a Train_Leaving event. Note the similiarity between the controller here and the decision table version given in Figure 3.2.

These state machine models need to be extended further in order to handle specifications for real-time systems more completely. The principal required additional features are concurrency and time. Concurrency is added by permitting several fsms to run in parallel. Suitable communication and synchronization mechanisms must be defined; also, an appropriate parallel model needs to be selected, for example, some variation or combination of a distributed or shared memory model. For describing timing constraints, some means of specifying transition times or state resident times are also necessary.

All state machine techniques, including those for conventional sequential systems, suffer from a "state explosion" problem: large systems tend to have unmanageably large numbers of states. This problem is exacerbated with the additions of concurrency and time.

 

3. Statecharts

A major breakthrough in extending state machine ideas for use in realistic real-time applications was made by Harel and his colleagues. This work was started in the early 1980s, and culminated in the statechart notation and an associated software development environment named STATEMATE [Harel87; Harel_et_al90]. The language was invented originally for the development of the avionics system for an Israeli aircraft, and has seen widespread use since then (e.g., [Leveson_et_al94]).

The principal innovations in statecharts lay in their techniques for defining the structure of state machines through superstates. Statecharts may be composed in series or in parallel. The formalism has efficient ways to specify transitions into and out of superstates and composed machines. Communication among machines occurs by broadcasting events. Timing constraints can be described at any level by translating them into timeout events. In addition, the notation is essentially graphical - the authors term it a visual language. This visual aspect is especially significant because it provides a natural, compact, and easy-to-use interface.

At the lowest level, a statechart is a state transition diagram as described in the last section. Transitions between states are similar to those in the more general extended fsms, except that the A/O components are combined. They have the form:

G ® I/A'

where A' can be either an internal action, an output (event generation), or a sequence of these. The examples in Figures 3.5 and 3.6 are simple statecharts, if the syntax of the transitions is changed slightly, for example,

count=1 ® Train_Leaving / count:=0; Open_Gate

 

Groups of states can be collected into superstates, which can themselves be collected further into superstates. Conversely, a superstate can be refined into its component states or superstates. Transitions between superstates denote their potential execution in sequence. They also model "interrupts" in the following clever but natural manner. Suppose two superstates S1 and S2 are connected by the transition a as shown in Figure 3.7. The meaning of this visual form is that all states in S1 are connected by transition a to the entry state of S2. This simple convention saves an enormous amount of space, otherwise taken up by identical transitions, and substantially enhances the clarity of a diagram. The interrupt transition is used in many applications, for example, S1 could describe the normal operation of some subsystem, S2 the emergency operation, and a the fault event causing the transition between normal and emergency modes.

 

Watch Example

Consider a simple digital watch with time, date, hourly chime, and alarm clock functions and 4 buttons, a, b, c, and d, for user control (Figure 3.8).

Suppose, for now, that there are three main modes of operation:

Normal_Display wherein either the time or date is displayed;

Clock_Update within which a user can update the time and date; and

Chime_Alarm_Set where the chime and alarm clock are set.

The statechart of Figure 3.9 shows a possible behavior for parts of these modes and for the interactions among them.

Input events caused by pressing one of the 4 buttons are represented on the transitions by the button identifiers. Thus, the watch is normally entered through the Normal_Display superstate and into the Time state (or superstate, since Time could also be refined). Button a could then be used to move the system to and from Date . Pressing c while in any state in Normal_Display will result in a transition to the entry state (min) of Update; upon pressing button d while in any state inside Update, a transition back to the entry state of Normal_Display occurs. Without the exit and entry conventions for superstates, these two transitions would have to be replaced by (at least) 7 transitions, 2 leaving Normal_Display and 5 leaving Update. A similar behavior results between Normal_Display and Chime_Alarm_Set using buttons b and d.

Within the Update superstate, the transitions fired by button b cause the updating of internal variables, m, h, D, M, and Y, denoting the current minute, hour, day, month, and year, repectively. The notation xn++ means:

    x := x+1 mod n .

Note the use of the a transition from the year state; it is still possible to easily express a superstate exit from a single inside state. One could similarly override the default entry state by simply drawing the transition arrow through the superstate box into the desired state.

 

It is occasionally desirable to "save" the state when leaving a mode and subsequently restore the old state when reentering. State charts provide such a facility with a transition type called "entry with history" (H) which enters a superstate at the (first-level) state that it last left. H only specifies reentry to the superstate at the same level that the H designator appears; lower levels are reentered at their default normal entries. A "deep history" entry, denoted H*, is also defined; it restores state down to the lowest level, i.e., down to the state level.

A general timeout mechanism is provided. The notation timeout(E, dt) designates an event occurring dt time units after the event E. E is often the event associated with the entry to some state or superstate. For this common case, a labelled "resistor" squiggle and a timeout exit have been suggested as illustrated in Figure 3.10(a); alternatively, a timeout exit of the form timeout(entered(S), dt) could be employed, where entered(S) is the event associated with entering state S. The figure also shows how an entry (a) with history is drawn.

 

A statechart with these features (Figure 3.10(b)) describes the nuclear power plant monitor of Section 2.2.2. Note that B is entered with history. Thus, during each cycle, the background processes in B are continued starting from their point of interruption during the previous cycle.

The history and timeout features also appear in Figure 3.11 which adds alarm ringing to the watch behavior described earlier in Figure 3.9. The triggering event

    T(ct = talarm)

occurs when the condition ct=talarm becomes true (T). The notation for events given in Section 3.2 is used; ct denotes current time and talarm is the time to which the alarm clock is set. Pressing any button (the any_button event) will cause the alarm to stop ringing; otherwise, the ringing will stop after 30 seconds. In either case, the Main superstate is reentered at the same point where it was interrupted by the alarm (H entry). The a transition from inside of Update to Normal_Display indicates that the transition only occurs from some, but not all, of the states of Update.

 

The concurrent operation of two statecharts is represented by attaching their boxes with a dashed common edge, as shown in Figure 3.12. The watch, as we have so far defined it, is encapsulated in a superstate named Clock. In parallel with this is a machine, Light, which specifies that the light can be turned on or off with the d button. d' is the event associated with letting go of the button. (If we let d be a condition which is true while the button is depressed and false otherwise, then we could use T(d) and F(d) to represent d and d' respectively.)

When events are generated, they are broadcast throughout the system. This is the principal way that machines interact and communicate. Thus, in Figure 12, the depress button event d is broadcast to both the Light and the Clock superstates. In Light, the event causes a transition to the on state. At the same time, if the Clock machine were in either Chime_Alarm_Set or Update, d would also cause a transition back to Normal_Display; if the Clock machine was in Ring_Alarm, the transition back to Main would be fired instead.

Events are not the only object that is "shared" across machines. Statecharts implement a shared storage model of parallelism. Variables may be shared among parallel superstates; and conditions and events can refer to states. The events entered(S) and exit(S) are associated with entering and leaving state S, respectively; in the timeout mechanism discussed above, we showed one application of entered(S). in(S) is a condition stating that some component of the system is in state S. For example, if there is a requirement that the light not be turned on if the Clock is in Ring_Alarm, the transition from off to on in Light should be changed to:

    Øin(Ring_Alarm) ® d

 

Statecharts have several other features, similar to those in programming languages, that simplify their construction. There is a "scoping" convention that associates identifiers, e.g., for variables and superstates, with superstate blocks so that they are hidden outside of the block. Another useful mechanism is an array-like scheme to define many parallel instances of the same machine. Recall the air traffic monitoring (ATM) example presented in Chapter 1. The behavior of an aircraft i - entering the airspace, travelling through it, and departing - can be specified by a statechart AC(i); the notation AC(i: 1..n) represents n instances: AC(1), ... , AC(n), as shown in Figure 3.13.

 

The precise meaning (semantics) of statecharts is quite complicated, and is only introduced here briefly and informally. The behavior of a statechart is explained by tracing through or simulating a "step" of its execution. One or more events trigger the start of a step. The execution of a step involves selecting one or more transitions to fire from the set that are enabled in the current state, taking the selected transitions by performing their actions and moving to the next state, and repeating this until no further transitions can be taken. Events generated in one step are not handled or accepted until the next step.

Transitions take zero time in the original statechart model. Time passes inside states while the system is waiting for external events to occur.

In this notation, "?" denotes receiving a message (an input event) and "!" means sending a message (an output event).