divine/examples
you can find a set of case studies already modelled for DiVinE in C language.
You want to model a system. System is composed from processes. Processes can transit from one process state to another through transitions. Transitions can be guarded by a condition - this condition says when the transition can be activated.
Transitions can be synchronized through (named) channels. There are always just 2 processes which can be synchronized in one moment. When more than 2 processes can synchronize through the same channel, there are possible all combinations of such processes to synchronize, but always just 2 of them in one moment. During the synchronization through the channel the value can be optionally transmitted between processes.
The transitions have co called "effects". Effects are assignments to local or global variables. Two synchronized processes should not be able to assign the same variable - it is an error in your model!
The system can be synchronous or asynchronous.
The namespace is common for channels, variables, processes and states. Identifier has to be unique in the current scope of visibility. It means that e. g. when variable A is declared in the process P1 then there cannot be more variables A and states A in that process and more global variables A, channels A and processes A. But there may be another variable called A in the process P2.
process My_really_nice_process { <code of a process> }
byte
or int
type. E.g.: byte A[9]; int i,j;
const
: const byte k = 3;
byte field[k];
state start, run, reading_input, writing_output; init start; accept reading_input, writing_output;
reading_input
and writing_output
are commited: state start, run, reading_input, writing_output; init start; commit reading_input, writing_output;
run -> writing_output
). The transition can be executed only if the process in the initial process state of a transition (in the above mentioned example in a state run
). You should also define an additional condition when the transition can be executed (keyword guard
) and sometimes also a channel to synchonize through (keyword sync
with followed by the channel name and !
or ?
). There can synchronize only transitions with the same channel name and opposite operators !
and ?
. When you want to transmit a value through the channel, you can write a value after !
and a variable (where the value will be transmitted) after ?
. The last but not least element of transitions are effects - they are simple assignments to the variables. Example: process Sender { byte value, sab, retry; state ready, sending, wait_ack, failed; init ready; trans ready -> sending {sync send?value; effect sab = 1 -sab; }, sending -> wait_ack {sync toK!(value*2+sab); effect retry = 1;}, wait_ack -> wait_ack {guard retry <2; sync toK!(value*2+sab); effect retry = retry+1;}, wait_ack -> ready {sync fromL?;}, wait_ack -> failed { guard retry == 2;}; }
true
, false
( ,
)-
, ~
(= negation of bits) and not
(= boolean negation)
imply,
or,
and,
|,
^,
&,
==,!=,
<,<=,>,>=,
<<,>>,
-,+
/,*,%
their semantics is the same as in C programming language except for boolean operators and, or
and imply
(but their meaning is obvious).Sender.ready
is equal to 1
, iff process Sender
is in a state ready
. Otherwise it is equal to 0
).byte i_am_a_variable; channel send, receive, toK, fromK, toL, fromL; //untyped unbuffered channels channel {byte} b_send[0], b_receive[0]; //typed unbuffered channels channel {byte,int} bi_send[0], bi_receive[0]; //typed unbuffered channels (transmitting 2 values simultaneously) channel {byte,int} buf_bi_send[4], buf_bi_receive[1]; //typed buffered channels
channel xxx
and channel {byte} xxx[0]
are both unbuffered channels and they behave almost the same way, but the second declaration is typed and the transmitted value is type casted (in this case to byte
) before its transmission.system sync;
system async;
process My_really_nice_process { byte hello = 1; state one, two, three; init one assert one: hello >= 1, two: hello < 1, one: hello < 6; trans ... }