Uppaal 4.0: Small Tutorial: This Description Covers Version 4.0.7
Uppaal 4.0: Small Tutorial: This Description Covers Version 4.0.7
0 : Small Tutorial
16 November 2009
Introduction
Uppaal
Uppaal is a tool box for validation (via graphical simulation) and verification (via automatic
model-checking) of real-time systems. It consists of two main parts: a graphical user interface and
a model-checker engine. The user interface is implemented in Java and is executed on the users
work station. Version 4.0 of Uppaal requires that the Java Runtime Environment 5 or higher is
installed on the computer. The engine part is by default executed on the same computer as the
user interface, but can also run on a more powerful server.
The idea is to model a system using timed automata, simulate it and then verify properties on
it. Timed automata are finite state machines with time (clocks). A system consists of a network
of processes that are composed of locations. Transitions between these locations define how the
system behaves. The simulation step consists of running the system interactively to check that it
works as intended. Then we can ask the verifier to check reachability properties, i.e., if a certain
state is reachable or not. This is called model-checking and it is basically an exhaustive search
that covers all possible dynamic behaviours of the system.
More precisely, the engine uses on-the-fly verification combined with a symbolic technique reducing the verification problem to that of solving simple constraint systems [YPD94, LPY95]. The
verifier checks for simple invariants and reachability properties for efficiency reasons. Other properties may be checked by using testing automata [JLS96] or the decorated system with debugging
information [LPY97].
Learning Uppaal
Uppaal is based on timed automata, that is finite state machine with clocks. The clocks are the
way to handle time in Uppaal. Time is continuous and the clocks measure time progress. It is
allowed to test the value of a clock or to reset it. Time will progress globally at the same pace for
the whole system.
A system in Uppaal is composed of concurrent processes, each of them modeled as an automaton. The automaton has a set of locations. Transitions are used to change location. To control
when to take a transition (to fire it), it is possible to have a guard and a synchronization. A
guard is a condition on the variables and the clocks saying when the transition is enabled. The
synchronization mechanism in Uppaal is a hand-shaking synchronization: two processes take a
This
transition at the same time, one will have an a! and the other an a?, with a being the synchronization channel. When taking a transition, two actions are possible: assignment of variables or
reset of clocks.
The following examples will make you familiar with this short description.
3.1
Overview
The Uppaal main window (Figure 1) has two main parts: the menu and the tabs.
start
end
Now, click on the Simulator tab to start the simulator, click on the yes button that will pop
up and you are ready to run your first system.
notation for the temporal logic formula P rocess.end and should be understood as it is possible
to reach the location end in automaton Process. Click Check to let the engine verify this. The
bullet in the overview will turn green indicating that he property indeed is satisfied.
The goal of the rest of this document is to explore some key points of Uppaal through examples.
3.2
We will study now the known Pettersons mutual exclusion algorithm to see how we can derive a
model as an automaton from a program/algorithm and check properties related to it.
The algorithm for two processes is as follows in C:
Process 1
req1=1;
turn=2;
while(turn!=1 && req2!=0);
// critical section:
job1();
req1=0;
Process 2
req2=1;
turn=1;
while(turn!=2 && req1!=0);
// critical section:
job2();
req2=0;
You will construct the corresponding automata. Notice that the protocol is symmetric, so we
may use a template of Uppaal to simplify the model. First reset the system (New system) to
clear the Hello World example. Rename the default template P to mutex.
We will abstract the actual work in the critical section since it has no interest here. The
protocol has four states that come directly from the described algorithm, similar to goto labels.
Using these, both processes can be written as follows:
Process 2
idle:
req2=1;
want:
turn=1;
wait:
while(turn!=2 && req1!=0);
CS:
//critical section
job2();
req2=0;
//and return to idle
Process 1
idle:
req1=1;
want:
turn=2;
wait:
while(turn!=1 && req2!=0);
CS:
//critical section
job1();
req1=0;
//and return to idle
req1 := 1
req1 := 0
want
idle
turn := 2
req2 := 0
turn == 1
CS
req2 := 1
want
turn := 1
turn == 2
wait
CS
req2 == 0
wait
req1 == 0
req_self := 1
want
req_self := 0
turn := (me == 1 ? 2 : 1)
turn == me
CS
wait
req_other == 0
call this template mutex, which you specify in the Name: field right above the drawing area. In
addition, you must specify the template parameters me, req self and req other. You do this by
writing them in the Parameters: field right next to the Name: field. Write the following:
const int[1,2] me, int[0,1] &req_self, int[0,1] &req_other
This means that you define three variables for instantiation of type integer, bounded to two
values each. The first one, me, is a constant, and the other two have to be variables with boolean
values (0 or 1).
As you can guess now from your drawing, two instances of the type P1 = mutex(1, req1,
req2); and P2 = mutex(2, req2, req1); will do the job. Examine how the expression (like C
syntax) turn := (me == 1 ? 2 : 1) will evaluate. To create the instances open the System
declarations label in the Project tree and type the declarations above (replacing the default line
that instantiates the default template). In addition, specify that the system now consists of P1 and
P2 by writing them behind the keyword system, comma-separated. The System declarations
contain now:
// Place template instantiations here.
P1 = mutex(1, req1, req2);
P2 = mutex(2, req2, req1);
// List one or more processes to be composed into a system.
system P1, P2;
Something is still missing: the variables also have to be declared. Click on the Declarations
label and declare: int[0,1] req1,req2; and int[1,2] turn;
Now you have defined your template, instantiated it twice, used the instantiations in the system
and declared proper variables. As you may notice, the variables declared are global. This is used
for turn that is shared. The scope of the name declaration are local first and then global. Before
we go on, do a syntax check (Tools menu or press F7) and have a look in the list that you can
drag up below the drawing area. It should be empty, otherwise fix the reported issues.
Now, click on the Simulator tab and examine how the two automata were instantiated. Look
particularly at the names of the two automata that are symmetric. You can simulate your system
by choosing interactively the transitions. Try to reach the critical section in both processes at the
same time . . . well you cannot, thats the point of the protocol. But using simulation, we cant
be sure about this. A better idea is to use the verifier.
Click on the Verifier tab, click on the Insert button, click in the Query text area and write
the mutual exclusion property: A[] not (P1.CS and P2.CS). Press the Check button and you
are done. There should be a green button lighted on, which means that the property was verified.
If the button were red it would mean that the property was not verified. The property A[] is a
safety property: you check that not (P1.CS and P2.CS) is always true. Another type of property,
the E<> may be used for reachability properties. For example insert a new property E<> P1.CS,
that checks if process P1 may reach the critical section.
If the system was not correct Uppaal can return an diagnostic trace. First change the model so
it is faulty. E.g. change the guard req other == 0 to req other == 1. Then go to the Options
menu and activate one of the Diagnostic Trace options; select the mutual exclusion property,
then press the Check button. Now this property should not be satisfied. You can now return to
the simulator and go through the found trace. Choose the first entry in the trace and then press
Replay for this.
You have now modeled, simulated and verified a simple mutual exclusion protocol. In the
demo folder in the distribution directory there are a few other simple examples. For example the
file fischer.xml contains another mutual exclusion protocol, together with some example queries
in fischer.q.
3.3
Time in Uppaal
taken
loop
x >= 2
reset!
x := 0
clock x
Draw the model, name the automata P1 and Obs, define them in the system. A new template
is created with Insert Template in the Edit menu. (You can just write the template names directly
in the system statement, Uppaal will automatically instantiate them for you.) Notice that the
state taken of the observer is of type committed. If you simulate the system you will not see
much. To train to interpret what you see we will use queries and modify the system progressively.
The expected behaviour of our system is depicted in Figure 8.
"time"
Figure 8: Time behaviour of the first example: this is one possible run.
Try these properties to exhibit this behaviour:
A[] Obs.taken imply x>=2 : all fall-down of the clock value (see curve) are above 2. This
query means: for all states, being in the location Obs.taken implies that x>=2.
E<> Obs.idle and x>3 : this is for the waiting period, you can try values like 30000 and
you will get the same result. This question means: is it possible to reach a state where Obs
is in the location idle and x>3.
clock x
loop
x >= 2
reset!
x <= 3
"time"
clock x
Now, remove the invariant and change the guard to x >= 2 and x <= 3. You may think that
it is the same as before but it is not! The system has no progress condition anymore, just a new
condition on the guard now. Figure 10 shows the new system.
loop
x >=2 and x <= 3
reset!
"time"
3.4
Urgent/Committed Locations
We will now look at the different kinds of locations of Uppaal. You already saw the type
committed in the previous example. There are three different types of locations in Uppaal:
Normal locations with or without invariants (like x <= 3 above),
Urgent locations and
Committed locations as used in the Obs automaton.
Draw the automata depicted in Figure 11 and name them P0, P1 and P2. Define the clocks x
locally for each automaton, in order to try this feature: open the sub-tree of their templates in
the Project tree. There you will see a Declarations label under the template in question. Click
on it and define clock x;. Repeat for the other two automata.
S0
x := 0
S1
S2
S0
x := 0
S1
S2
S0
x := 0
S1
S2
3.5
Verifying properties
In the examples above we have used the verifier several times. We will now give a more complete
treatment of the language that the verifier understands. In summary, the queries available in the
verifier are:
E<> p: there exists a path where p eventually holds.
A[] p: for all paths p always holds.
E[] p: there exists a path where p always holds.
A<> p: for all paths p will eventually hold.
p --> q: whenever p holds q will eventually hold.
where p and q are state formulas like for example (P1.cs and x<3). The full grammar of the
query language is available in the on-line help. Note the useful special form A[] not deadlock
that checks for deadlocks.
9
3.6
Uppaal offers urgent channels (defined using urgent chan) that are synchronization that must
be taken when the transition is enabled, without delay. Clock conditions on these transitions are
not allowed. It is possible to encode urgent transitions with a guard on a variable, i.e. busy wait
on a variable, by using urgent channels. Use a dummy process with one state looping with one
transition read!. The urgent transition will be x>0 read? for example.
There is no value passing through the channels but this is easily encoded by shared variable:
define globally a variable x, and use it for reading and writing. Notice that it is not clean to do
read! x:=3; and read? y:=x; but it is better to use a committed location in between: First
the read? transition into the committed location, then the transition setting y:=x;.
Since Uppaal 4, broadcast communication is also possible: The intuition is that an edge with
synchronisation label e! emits a broadcast on the channel e and that any enabled edge with
synchronisation label e? will synchronise with the emitting process. More details are given in the
online help.
Arrays of integers may be useful, declare them as int a[3]; to have an array indexable from
0 to 2. The index can be another variable i typically int[0,2] i; to be clean.
To keep a model manageable, one has to pay attention to some points:
The number of clocks has an important impact on the complexity, i.e., on the verification
time, since it highly influences the state space.
The use of committed locations can reduce significantly the state space, but one has to be
careful with this feature because it can possibly take away relevant states.
The number of variables plays an important role as well and more importantly their range.
One should be careful that the integer will not use all the values from -32000 to 32000 for
example. In particular avoid unbounded loops on integers since the values will then span
over the full range.
References
[YPD94] Wang Yi, Paul Pettersson, and Mats Daniels. Automatic Verification of Real-Time Communicating Systems By Constraint-Solving. In Proc. of the 7th International Conference
on Formal Description Techniques, 1994.
[LPY95] Kim G. Larsen, Paul Pettersson, and Wang Yi. Model-Checking for Real-Time Systems. In Proc. of Fundamentals of Computation Theory, volume 965 of Lecture Notes in
Computer Science, pages 6288, August 1995.
[JLS96] H.E. Jensen, K.G. Larsen, and A. Skou. Modelling and Analysis of a Collision Avoidance
Protocol Using SPIN and Uppaal. In Proc. of 2nd International Workshop on the SPIN
Verification System, pages 120, August 1996.
[LPY97] Magnus Lindahl, Paul Pettersson, and Wang Yi. Formal Design and Analysis of a GearBox Controller: an Industrial Case Study using Uppaal. In preparation, 1997.
[AD94] R. Alur and D. Dill. A Theory for Timed Automata In Theoretical Computer Science,
volume 125, pages 183235, 1994.
10
Version history
March 2001 First version by Alexandre David.
28 Apr 2001 Corrections by Alexandre David. Bug in a requirement, added: chan declaration,
bug in declarations: int[0,1] req1,req2, turn; turn is int, not int[0,1]!
17 Dec 2001 Updates by Alexandre David. Added how to mark initial states (because the new
UPPAAL does not make the first state initial by default anymore).
16 0ct 2002 Updates by Tobias Amnell. Changed screen-shoots to recent version (3.2.11), added
verification walk-through in start-end example, added section on query language plus text
updates on several places.
16 Nov 2009 Updates by Martin Stigge. Adapted document to version 4.0.7 of Uppaal (syntax
and screenshots). More detailed version of the mutex example to decrease confusion. A
bunch of minor fixes and clarifications, thanks to Pontus Ekberg.
11