Add 2 benchmarks directories.
Add an algorithm to split an automaton in several automata. * bench/scc-stats: New directory. Contains input files and test program for computing statistics. * bench/split-product: New directory. Contains test program for synchronised product on splitted automata. * bench/split-product/models: New directory. Contains Promela files and LTL formulae that should be verified by the models. * src/tgba/tgbafromfile.cc, src/tgba/tgbafromfile.hh: New files. Small class to avoid long initializations with numerous constants when translating to TGBA many LTL formulae from a given file. * src/tgbaalgos/cutscc.cc, src/tgbaalgos/cutscc.hh: New file. From a single automaton, create, at most, X sub automata. * src/tgbaalgos/scc.cc, src/tgbaalgos/scc.hh: Adjust to compute self-loops count.
This commit is contained in:
parent
a160b3504b
commit
414956c51e
35 changed files with 2989 additions and 5 deletions
43
bench/split-product/models/cl3serv1.pml
Normal file
43
bench/split-product/models/cl3serv1.pml
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
#define w1 client[0]@wait
|
||||
#define s1 client[0]@served
|
||||
|
||||
#define C 3
|
||||
#define S 1
|
||||
|
||||
chan clserv = [C] of { int };
|
||||
chan servcl = [S] of { int };
|
||||
|
||||
active [C] proctype client() {
|
||||
/* the _pid's are: 0 .. C-1 */
|
||||
|
||||
served:
|
||||
if
|
||||
:: (1) -> goto request;
|
||||
fi;
|
||||
request:
|
||||
if
|
||||
:: (1) -> clserv!_pid; goto wait;
|
||||
fi;
|
||||
wait:
|
||||
if
|
||||
:: servcl?eval(_pid); goto served;
|
||||
fi;
|
||||
}
|
||||
|
||||
active [S] proctype server() {
|
||||
/* the _pid's are: 0 .. S-1 */
|
||||
byte id;
|
||||
|
||||
wait:
|
||||
if
|
||||
:: clserv?id -> goto work;
|
||||
fi;
|
||||
work:
|
||||
if
|
||||
:: (1) -> goto reply;
|
||||
fi;
|
||||
reply:
|
||||
if
|
||||
:: (1) -> servcl!id; goto wait;
|
||||
fi;
|
||||
}
|
||||
43
bench/split-product/models/cl3serv3.pml
Normal file
43
bench/split-product/models/cl3serv3.pml
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
#define w1 client[0]@wait
|
||||
#define s1 client[0]@served
|
||||
|
||||
#define C 3
|
||||
#define S 3
|
||||
|
||||
chan clserv = [C] of { int };
|
||||
chan servcl = [S] of { int };
|
||||
|
||||
active [C] proctype client() {
|
||||
/* the _pid's are: 0 .. C-1 */
|
||||
|
||||
served:
|
||||
if
|
||||
:: (1) -> goto request;
|
||||
fi;
|
||||
request:
|
||||
if
|
||||
:: (1) -> clserv!_pid; goto wait;
|
||||
fi;
|
||||
wait:
|
||||
if
|
||||
:: servcl?eval(_pid); goto served;
|
||||
fi;
|
||||
}
|
||||
|
||||
active [S] proctype server() {
|
||||
/* the _pid's are: 0 .. S-1 */
|
||||
byte id;
|
||||
|
||||
wait:
|
||||
if
|
||||
:: clserv?id -> goto work;
|
||||
fi;
|
||||
work:
|
||||
if
|
||||
:: (1) -> goto reply;
|
||||
fi;
|
||||
reply:
|
||||
if
|
||||
:: (1) -> servcl!id; goto wait;
|
||||
fi;
|
||||
}
|
||||
1
bench/split-product/models/clserv.ltl
Normal file
1
bench/split-product/models/clserv.ltl
Normal file
|
|
@ -0,0 +1 @@
|
|||
!([] (w1 -> <> s1))
|
||||
9
bench/split-product/models/eeaean.ltl
Normal file
9
bench/split-product/models/eeaean.ltl
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
!(<>[](noLeader U zeroLeads))
|
||||
!(<>[](noLeader U threeLeads))
|
||||
!(<>zeroLeads)
|
||||
!([]<>zeroLeads)
|
||||
!(<>threeLeads)
|
||||
!([](noLeader -> <>zeroLeads))
|
||||
!([](noLeader || zeroLeads))
|
||||
!((<>[](noLeader || zeroLeads || oneLeads || twoLeads)) && (<>[]((zeroLeads -> (zeroLeads U (noLeader U oneLeads))))) && (<>[]((oneLeads -> (oneLeads U (noLeader U twoLeads))))) && (<>[]((twoLeads -> (twoLeads U (noLeader U zeroLeads))))))
|
||||
!((<>[](noLeader || zeroLeads || oneLeads || twoLeads)) && (<>[]((zeroLeads -> (zeroLeads U (noLeader U twoLeads))))) && (<>[]((oneLeads -> (oneLeads U (noLeader U zeroLeads))))) && (<>[]((twoLeads -> (twoLeads U (noLeader U oneLeads))))))
|
||||
116
bench/split-product/models/eeaean1.pml
Normal file
116
bench/split-product/models/eeaean1.pml
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
/* Echo Election Algorithm with Extinction in an Arbitrary Network. */
|
||||
/* Variation 1: Node 0 wins every time. */
|
||||
|
||||
#define L 10 /* size of buffer */
|
||||
#define udef 3
|
||||
|
||||
#define noLeader (nr_leaders == 0)
|
||||
#define zeroLeads (nr_leaders == 1 && leader == 0)
|
||||
#define oneLeads (nr_leaders == 1 && leader == 1)
|
||||
#define twoLeads (nr_leaders == 1 && leader == 2)
|
||||
#define threeLeads (nr_leaders == 1 && leader == 3)
|
||||
|
||||
mtype = { tok, ldr };
|
||||
chan zero_one = [L] of { mtype, byte};
|
||||
chan zero_two = [L] of { mtype, byte};
|
||||
chan one_zero = [L] of { mtype, byte};
|
||||
chan one_two = [L] of { mtype, byte};
|
||||
chan two_zero = [L] of { mtype, byte};
|
||||
chan two_one = [L] of { mtype, byte};
|
||||
|
||||
chan nr0 = [0] of {mtype};
|
||||
chan nr1 = [0] of {mtype};
|
||||
chan nr2 = [0] of {mtype};
|
||||
|
||||
byte nr_leaders, done, leader;
|
||||
|
||||
inline recvldr ()
|
||||
{
|
||||
if
|
||||
:: lrec == 0 && r != myid ->
|
||||
out1!ldr(r);
|
||||
out2!ldr(r);
|
||||
:: else -> skip;
|
||||
fi;
|
||||
lrec++;
|
||||
win = r;
|
||||
}
|
||||
|
||||
inline recvtok (q,c)
|
||||
{
|
||||
if
|
||||
:: r < caw ->
|
||||
caw = r;
|
||||
rec = 0;
|
||||
father = q;
|
||||
c!tok(r);
|
||||
:: else -> skip;
|
||||
fi;
|
||||
|
||||
if
|
||||
:: r == caw ->
|
||||
rec++;
|
||||
if
|
||||
:: rec == 2 && caw == myid
|
||||
-> out1!ldr(myid); out2!ldr(myid);
|
||||
:: rec == 2 && caw != myid && father == neigh1
|
||||
-> out1!tok(caw)
|
||||
:: rec == 2 && caw != myid && father == neigh2
|
||||
-> out2!tok(caw)
|
||||
:: else -> skip;
|
||||
fi;
|
||||
:: else -> skip;
|
||||
fi;
|
||||
}
|
||||
|
||||
proctype node (chan nr; byte neigh1; chan out1, in1;
|
||||
byte neigh2; chan out2, in2)
|
||||
{ byte myid = 3 - neigh1 - neigh2;
|
||||
byte caw, rec, father, lrec, win, r;
|
||||
|
||||
xr in1; xr in2;
|
||||
xs out1; xs out2;
|
||||
|
||||
restart:
|
||||
nr?tok;
|
||||
caw = myid; rec = 0; lrec = 0;
|
||||
father = udef; win = udef; r = udef;
|
||||
|
||||
out1!tok(myid);
|
||||
out2!tok(myid);
|
||||
do
|
||||
:: lrec == 2 -> break;
|
||||
:: in1?ldr(r) -> recvldr();
|
||||
:: in2?ldr(r) -> recvldr();
|
||||
:: in1?tok(r) -> recvtok(neigh1,out2);
|
||||
:: in2?tok(r) -> recvtok(neigh2,out1);
|
||||
od;
|
||||
|
||||
if
|
||||
:: win == myid ->
|
||||
leader = myid;
|
||||
nr_leaders++;
|
||||
assert(nr_leaders == 1);
|
||||
:: else ->
|
||||
skip;
|
||||
fi;
|
||||
|
||||
done++;
|
||||
goto restart;
|
||||
}
|
||||
|
||||
init {
|
||||
atomic {
|
||||
run node (nr0,1,zero_one,one_zero,2,zero_two,two_zero);
|
||||
run node (nr1,0,one_zero,zero_one,2,one_two,two_one);
|
||||
run node (nr2,0,two_zero,zero_two,1,two_one,one_two);
|
||||
}
|
||||
do
|
||||
:: true ->
|
||||
done = 0;
|
||||
nr_leaders = 0;
|
||||
leader = udef;
|
||||
nr0!tok; nr1!tok; nr2!tok;
|
||||
done == 3;
|
||||
od;
|
||||
}
|
||||
118
bench/split-product/models/eeaean2.pml
Normal file
118
bench/split-product/models/eeaean2.pml
Normal file
|
|
@ -0,0 +1,118 @@
|
|||
/* Echo Election Algorithm with Extinction in an Arbitrary Network. */
|
||||
/* Variation 1: Node 0 wins every time. */
|
||||
|
||||
#define L 10 /* size of buffer */
|
||||
#define udef 3
|
||||
|
||||
#define noLeader (nr_leaders == 0)
|
||||
#define zeroLeads (nr_leaders == 1 && leader == 0)
|
||||
#define oneLeads (nr_leaders == 1 && leader == 1)
|
||||
#define twoLeads (nr_leaders == 1 && leader == 2)
|
||||
#define threeLeads (nr_leaders == 1 && leader == 3)
|
||||
|
||||
mtype = { tok, ldr };
|
||||
chan zero_one = [L] of { mtype, byte};
|
||||
chan zero_two = [L] of { mtype, byte};
|
||||
chan one_zero = [L] of { mtype, byte};
|
||||
chan one_two = [L] of { mtype, byte};
|
||||
chan two_zero = [L] of { mtype, byte};
|
||||
chan two_one = [L] of { mtype, byte};
|
||||
|
||||
chan nr0 = [0] of {mtype, byte};
|
||||
chan nr1 = [0] of {mtype, byte};
|
||||
chan nr2 = [0] of {mtype, byte};
|
||||
|
||||
byte nr_leaders, done, leader;
|
||||
|
||||
inline recvldr ()
|
||||
{
|
||||
if
|
||||
:: lrec == 0 && r != myid ->
|
||||
out1!ldr(r);
|
||||
out2!ldr(r);
|
||||
:: else -> skip;
|
||||
fi;
|
||||
lrec++;
|
||||
win = r;
|
||||
}
|
||||
|
||||
inline recvtok (q,c)
|
||||
{
|
||||
if
|
||||
:: (r+turn)%3 < (caw+turn)%3 ->
|
||||
caw = r;
|
||||
rec = 0;
|
||||
father = q;
|
||||
c!tok(r);
|
||||
:: else -> skip;
|
||||
fi;
|
||||
|
||||
if
|
||||
:: r == caw ->
|
||||
rec++;
|
||||
if
|
||||
:: rec == 2 && caw == myid
|
||||
-> out1!ldr(myid); out2!ldr(myid);
|
||||
:: rec == 2 && caw != myid && father == neigh1
|
||||
-> out1!tok(caw)
|
||||
:: rec == 2 && caw != myid && father == neigh2
|
||||
-> out2!tok(caw)
|
||||
:: else -> skip;
|
||||
fi;
|
||||
:: else -> skip;
|
||||
fi;
|
||||
}
|
||||
|
||||
proctype node (chan nr; byte neigh1; chan out1, in1;
|
||||
byte neigh2; chan out2, in2)
|
||||
{ byte myid = 3 - neigh1 - neigh2;
|
||||
byte caw, rec, father, lrec, win, r, turn;
|
||||
|
||||
xr in1; xr in2;
|
||||
xs out1; xs out2;
|
||||
|
||||
restart:
|
||||
nr?tok(turn);
|
||||
caw = myid; rec = 0; lrec = 0;
|
||||
father = udef; win = udef; r = udef;
|
||||
|
||||
out1!tok(myid);
|
||||
out2!tok(myid);
|
||||
do
|
||||
:: lrec == 2 -> break;
|
||||
:: in1?ldr(r) -> recvldr();
|
||||
:: in2?ldr(r) -> recvldr();
|
||||
:: in1?tok(r) -> recvtok(neigh1,out2);
|
||||
:: in2?tok(r) -> recvtok(neigh2,out1);
|
||||
od;
|
||||
|
||||
if
|
||||
:: win == myid ->
|
||||
leader = myid;
|
||||
nr_leaders++;
|
||||
assert(nr_leaders == 1);
|
||||
:: else ->
|
||||
skip;
|
||||
fi;
|
||||
|
||||
done++;
|
||||
goto restart;
|
||||
}
|
||||
|
||||
init {
|
||||
byte turn = 0;
|
||||
atomic {
|
||||
run node (nr0,1,zero_one,one_zero,2,zero_two,two_zero);
|
||||
run node (nr1,0,one_zero,zero_one,2,one_two,two_one);
|
||||
run node (nr2,0,two_zero,zero_two,1,two_one,one_two);
|
||||
}
|
||||
do
|
||||
:: true ->
|
||||
done = 0;
|
||||
nr_leaders = 0;
|
||||
leader = udef;
|
||||
nr0!tok(turn); nr1!tok(turn); nr2!tok(turn);
|
||||
done == 3;
|
||||
turn = (turn+1)%3;
|
||||
od;
|
||||
}
|
||||
55
bench/split-product/models/formulae.ltl
Normal file
55
bench/split-product/models/formulae.ltl
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
[](!p0)
|
||||
<>p1 -> (!p0 U p1)
|
||||
[](p2 -> [](!p0))
|
||||
[]((p2 & !p1 & <>p1) -> (!p0 U p1))
|
||||
[](p2 & !p1 -> (!p0 U (p1 | []!p0)))
|
||||
<>(p0)
|
||||
!p1 U ((p0 & !p1) | []!p1)
|
||||
[](!p2) | <>(p2 & <>p0)
|
||||
[](p2 & !p1 -> (!p1 U ((p0 & !p1) | []!p1)))
|
||||
[](p2 & !p1 -> (!p1 U (p0 & !p1)))
|
||||
<>p1 -> ((!p0 & !p1) U (p1 | ((p0 & !p1) U (p1 | ((!p0 & !p1) U (p1 | ((p0 & !p1) U (p1 | (!p0 U p1)))))))))
|
||||
[]((p2 & <>p1) -> ((!p0 & !p1) U (p1 | ((p0 & !p1) U (p1 | ((!p0 & !p1) U (p1 | ((p0 & !p1) U (p1 | (!p0 U p1))))))))))
|
||||
[](p2 -> ((!p0 & !p1) U (p1 | ((p0 & !p1) U (p1 | ((!p0 & !p1) U (p1 | ((p0 & !p1) U (p1 | (!p0 U (p1 | []!p0)) | []p0)))))))))
|
||||
[](p0)
|
||||
<>p1 -> (p0 U p1)
|
||||
[](p2 -> [](p0))
|
||||
[]((p2 & !p1 & <>p1) -> (p0 U p1))
|
||||
[](p2 & !p1 -> (p0 U (p1 | [] p0)))
|
||||
!p0 U (p3 | []!p0)
|
||||
<>p1 -> (!p0 U (p3 | p1))
|
||||
[]!p2 | <>(p2 & (!p0 U (p3 | []!p0)))
|
||||
[]((p2 & !p1 & <>p1) -> (!p0 U (p3 | p1)))
|
||||
[](p2 & !p1 -> (!p0 U ((p3 | p1) | []!p0)))
|
||||
[](p0 -> <>p3)
|
||||
<>p1 -> (p0 -> (!p1 U (p3 & !p1))) U p1
|
||||
[](p2 -> [](p0 -> <>p3))
|
||||
[]((p2 & !p1 & <>p1) -> (p0 -> (!p1 U (p3 & !p1))) U p1)
|
||||
[](p2 & !p1 -> ((p0 -> (!p1 U (p3 & !p1))) U (p1 | [](p0 -> (!p1 U (p3 & !p1))))))
|
||||
<>p0 -> (!p0 U (p3 & !p0 & X(!p0 U p4)))
|
||||
<>p1 -> (!p0 U (p1 | (p3 & !p0 & X(!p0 U p4))))
|
||||
([]!p2) | (!p2 U (p2 & <>p0 -> (!p0 U (p3 & !p0 & X(!p0 U p4)))))
|
||||
[]((p2 & <>p1) -> (!p0 U (p1 | (p3 & !p0 & X(!p0 U p4)))))
|
||||
[](p2 -> (<>p0 -> (!p0 U (p1 | (p3 & !p0 & X(!p0 U p4))))))
|
||||
(<>(p3 & X<>p4)) -> ((!p3) U p0)
|
||||
<>p1 -> ((!(p3 & (!p1) & X(!p1 U (p4 & !p1)))) U (p1 | p0))
|
||||
([]!p2) | ((!p2) U (p2 & ((<>(p3 & X<>p4)) -> ((!p3) U p0))))
|
||||
[]((p2 & <>p1) -> ((!(p3 & (!p1) & X(!p1 U (p4 & !p1)))) U (p1 | p0)))
|
||||
[](p2 -> (!(p3 & (!p1) & X(!p1 U (p4 & !p1))) U (p1 | p0) | [](!(p3 & X<>p4))))
|
||||
[] (p3 & X<> p4 -> X(<>(p4 & <> p0)))
|
||||
<>p1 -> (p3 & X(!p1 U p4) -> X(!p1 U (p4 & <> p0))) U p1
|
||||
[] (p2 -> [] (p3 & X<> p4 -> X(!p4 U (p4 & <> p0))))
|
||||
[] ((p2 & <>p1) -> (p3 & X(!p1 U p4) -> X(!p1 U (p4 & <> p0))) U p1)
|
||||
[] (p2 -> (p3 & X(!p1 U p4) -> X(!p1 U (p4 & <> p0))) U (p1 | [] (p3 & X(!p1 U p4) -> X(!p1 U (p4 & <> p0)))))
|
||||
[] (p0 -> <>(p3 & X<>p4))
|
||||
<>p1 -> (p0 -> (!p1 U (p3 & !p1 & X(!p1 U p4)))) U p1
|
||||
[] (p2 -> [] (p0 -> (p3 & X<> p4)))
|
||||
[] ((p2 & <>p1) -> (p0 -> (!p1 U (p3 & !p1 & X(!p1 U p4)))) U p1)
|
||||
[] (p2 -> (p0 -> (!p1 U (p3 & !p1 & X(!p1 U p4)))) U (p1 | [] (p0 -> (p3 & X<> p4))))
|
||||
[] (p0 -> <>(p3 & !p5 & X(!p5 U p4)))
|
||||
<>p1 -> (p0 -> (!p1 U (p3 & !p1 & !p5 & X((!p1 & !p5) U p4)))) U p1
|
||||
[] (p2 -> [] (p0 -> (p3 & !p5 & X(!p5 U p4))))
|
||||
[] ((p2 & <>p1) -> (p0 -> (!p1 U (p3 & !p1 & !p5 & X((!p1 & !p5) U p4)))) U p1)
|
||||
[] (p2 -> (p0 -> (!p1 U (p3 & !p1 & !p5 & X((!p1 & !p5) U p4)))) U (p1 | [] (p0 -> (p3 & !p5 & X(!p5 U p4)))))
|
||||
!p0 U ((p0 U ((!p0 U ((p0 U ([]!p0 | []p0)) | []!p0)) | []!p0)) | []!p0)
|
||||
<>p2 -> (!p2 U (p2 & (!p0 U ((p0 U ((!p0 U ((p0 U ([]!p0 | []p0)) | []!p0)) | []!p0)) | []!p0))))
|
||||
1
bench/split-product/models/leader.ltl
Normal file
1
bench/split-product/models/leader.ltl
Normal file
|
|
@ -0,0 +1 @@
|
|||
!(<>[]oneLeader)
|
||||
89
bench/split-product/models/leader.pml
Normal file
89
bench/split-product/models/leader.pml
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
/* Dolev, Klawe & Rodeh for leader election in unidirectional ring
|
||||
* `An O(n log n) unidirectional distributed algorithm for extrema
|
||||
* finding in a circle,' J. of Algs, Vol 3. (1982), pp. 245-260
|
||||
*/
|
||||
|
||||
#define elected (nr_leaders > 0)
|
||||
#define noLeader (nr_leaders == 0)
|
||||
#define oneLeader (nr_leaders == 1)
|
||||
|
||||
#define N 5 /* nr of processes (use 5 for demos) */
|
||||
#define I 3 /* node given the smallest number */
|
||||
#define L 10 /* size of buffer (>= 2*N) */
|
||||
|
||||
mtype = { one, two, winner };
|
||||
chan q[N] = [L] of { mtype, byte};
|
||||
|
||||
byte nr_leaders = 0;
|
||||
|
||||
proctype node (chan in, out; byte mynumber)
|
||||
{ bit Active = 1, know_winner = 0;
|
||||
byte nr, maximum = mynumber, neighbourR;
|
||||
|
||||
xr in;
|
||||
xs out;
|
||||
|
||||
printf("MSC: %d\n", mynumber);
|
||||
out!one(mynumber);
|
||||
end: do
|
||||
:: in?one(nr) ->
|
||||
if
|
||||
:: Active ->
|
||||
if
|
||||
:: nr != maximum ->
|
||||
out!two(nr);
|
||||
neighbourR = nr
|
||||
:: else ->
|
||||
/* Raynal p.39: max is greatest number */
|
||||
assert(nr == N);
|
||||
know_winner = 1;
|
||||
out!winner,nr;
|
||||
fi
|
||||
:: else ->
|
||||
out!one(nr)
|
||||
fi
|
||||
|
||||
:: in?two(nr) ->
|
||||
if
|
||||
:: Active ->
|
||||
if
|
||||
:: neighbourR > nr && neighbourR > maximum ->
|
||||
maximum = neighbourR;
|
||||
out!one(neighbourR)
|
||||
:: else ->
|
||||
Active = 0
|
||||
fi
|
||||
:: else ->
|
||||
out!two(nr)
|
||||
fi
|
||||
:: in?winner,nr ->
|
||||
if
|
||||
:: nr != mynumber ->
|
||||
printf("MSC: LOST\n");
|
||||
:: else ->
|
||||
printf("MSC: LEADER\n");
|
||||
nr_leaders++;
|
||||
assert(nr_leaders == 1)
|
||||
fi;
|
||||
if
|
||||
:: know_winner
|
||||
:: else -> out!winner,nr
|
||||
fi;
|
||||
break
|
||||
od
|
||||
}
|
||||
|
||||
init {
|
||||
byte proc;
|
||||
atomic {
|
||||
proc = 1;
|
||||
do
|
||||
:: proc <= N ->
|
||||
run node (q[proc-1], q[proc%N], (N+I-proc)%N+1);
|
||||
proc++
|
||||
:: proc > N ->
|
||||
break
|
||||
od
|
||||
}
|
||||
}
|
||||
|
||||
2
bench/split-product/models/mobile1.ltl
Normal file
2
bench/split-product/models/mobile1.ltl
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
!((![]<>(r)) -> [](<>p -> <>q))
|
||||
|
||||
155
bench/split-product/models/mobile1.pml
Normal file
155
bench/split-product/models/mobile1.pml
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
/*
|
||||
* Model of cell-phone handoff strategy in a mobile network.
|
||||
* A translation from the pi-calculus description of this
|
||||
* model presented in:
|
||||
* Fredrik Orava and Joachim Parrow, 'An algebraic verification
|
||||
* of a mobile network,' Formal aspects of computing, 4:497-543 (1992).
|
||||
* For more information on this model, email: joachim@it.kth.se
|
||||
*
|
||||
* See also the simplified version of this model in mobile2
|
||||
*
|
||||
* The ltl property definition for this version is in mobile1.ltl
|
||||
*
|
||||
* to perform the verification with xspin, simply use the ltl property
|
||||
* manager, which will load the above .ltl file by default.
|
||||
* to perform the verificaion from a Unix command line, type:
|
||||
* $ spin -a -N mobile1.ltl mobile1
|
||||
* $ cc -o pan pan.c
|
||||
* $ pan -a
|
||||
*/
|
||||
|
||||
#define p in?[red]
|
||||
#define q out?[red]
|
||||
#define r (BS[a_id]@progress || BS[p_id]@progress)
|
||||
|
||||
mtype = { data, ho_cmd, ho_com, ho_acc, ho_fail, ch_rel, white, red, blue };
|
||||
|
||||
chan in = [1] of { mtype };
|
||||
chan out = [1] of { mtype };
|
||||
|
||||
byte a_id, p_id; /* ids of processes refered to in the property */
|
||||
|
||||
proctype CC(chan fa, fp, l) /* communication controller */
|
||||
{ chan m_old, m_new, x;
|
||||
mtype v;
|
||||
|
||||
do
|
||||
:: in?v ->
|
||||
printf("MSC: DATA\n");
|
||||
fa!data; fa!v
|
||||
:: l?m_new ->
|
||||
fa!ho_cmd; fa!m_new;
|
||||
printf("MSC: HAND-OFF\n");
|
||||
if
|
||||
:: fp?ho_com ->
|
||||
printf("MSC: CH_REL\n");
|
||||
fa!ch_rel; fa?m_old;
|
||||
l!m_old;
|
||||
x = fa; fa = fp; fp = x
|
||||
:: fa?ho_fail ->
|
||||
printf("MSC: FAIL\n");
|
||||
l!m_new
|
||||
fi
|
||||
od
|
||||
}
|
||||
|
||||
proctype HC(chan l, m) /* handover controller */
|
||||
{
|
||||
do
|
||||
:: l!m; l?m
|
||||
od
|
||||
}
|
||||
|
||||
proctype MSC(chan fa, fp, m) /* mobile switching center */
|
||||
{ chan l = [0] of { chan };
|
||||
|
||||
atomic {
|
||||
run HC(l, m);
|
||||
run CC(fa, fp, l)
|
||||
}
|
||||
}
|
||||
|
||||
proctype BS(chan f, m; bit how) /* base station */
|
||||
{ chan v;
|
||||
|
||||
if
|
||||
:: how -> goto Active
|
||||
:: else -> goto Passive
|
||||
fi;
|
||||
|
||||
Active:
|
||||
printf("MSC: ACTIVE\n");
|
||||
do
|
||||
:: f?data -> f?v; m!data; m!v
|
||||
:: f?ho_cmd -> /* handover command */
|
||||
progress: f?v; m!ho_cmd; m!v;
|
||||
if
|
||||
:: f?ch_rel ->
|
||||
f!m;
|
||||
goto Passive
|
||||
:: m?ho_fail ->
|
||||
printf("MSC: FAILURE\n");
|
||||
f!ho_fail
|
||||
fi
|
||||
od;
|
||||
|
||||
Passive:
|
||||
printf("MSC: PASSIVE\n");
|
||||
m?ho_acc -> f!ho_com;
|
||||
goto Active
|
||||
}
|
||||
|
||||
proctype MS(chan m) /* mobile station */
|
||||
{ chan m_new;
|
||||
mtype v;
|
||||
|
||||
do
|
||||
:: m?data -> m?v; out!v
|
||||
:: m?ho_cmd; m?m_new;
|
||||
if
|
||||
:: m_new!ho_acc; m = m_new
|
||||
:: m!ho_fail
|
||||
fi
|
||||
od
|
||||
}
|
||||
|
||||
proctype P(chan fa, fp)
|
||||
{ chan m = [0] of { mtype };
|
||||
|
||||
atomic {
|
||||
run MSC(fa, fp, m);
|
||||
p_id = run BS(fp, m, 0) /* passive base station */
|
||||
}
|
||||
}
|
||||
|
||||
proctype Q(chan fa)
|
||||
{ chan m = [0] of { mtype }; /* mixed use as mtype/chan */
|
||||
|
||||
atomic {
|
||||
a_id = run BS(fa, m, 1); /* active base station */
|
||||
run MS(m)
|
||||
}
|
||||
}
|
||||
|
||||
active proctype System()
|
||||
{ chan fa = [0] of { mtype }; /* mixed use as mtype/chan */
|
||||
chan fp = [0] of { mtype }; /* mixed use as mtype/chan */
|
||||
|
||||
atomic {
|
||||
run P(fa, fp);
|
||||
run Q(fa)
|
||||
}
|
||||
}
|
||||
|
||||
active proctype top()
|
||||
{
|
||||
do
|
||||
:: in!red; in!white; in!blue
|
||||
od
|
||||
}
|
||||
active proctype bot()
|
||||
{
|
||||
do /* deadlock on loss or duplication */
|
||||
:: out?red; out?white; out?blue
|
||||
od
|
||||
}
|
||||
1
bench/split-product/models/mobile2.ltl
Normal file
1
bench/split-product/models/mobile2.ltl
Normal file
|
|
@ -0,0 +1 @@
|
|||
!((![]<>(r)) -> [](<>p -> <>q))
|
||||
136
bench/split-product/models/mobile2.pml
Normal file
136
bench/split-product/models/mobile2.pml
Normal file
|
|
@ -0,0 +1,136 @@
|
|||
/*
|
||||
* Simplified model of cell-phone handoff strategy in a mobile network.
|
||||
* A translation from the pi-calculus description of this
|
||||
* model presented in:
|
||||
* Fredrik Orava and Joachim Parrow, 'An algebraic verification
|
||||
* of a mobile network,' Formal aspects of computing, 4:497-543 (1992).
|
||||
* For more information on this model, email: joachim@it.kth.se
|
||||
*
|
||||
* This version exploits some Promela features to reduce the number
|
||||
* of processes -- which looks better in simulations, and reduces
|
||||
* complexity (by about 60%) in verification.
|
||||
*
|
||||
* See also the more literal version of this model in mobile1.
|
||||
*
|
||||
* The ltl property definition for this version is in mobile2.ltl
|
||||
*
|
||||
* to perform the verification with xspin, simply use the ltl property
|
||||
* manager, which will load the above .ltl file by default.
|
||||
* to perform the verificaion from a Unix command line, type:
|
||||
* $ spin -a -N mobile2.ltl mobile2
|
||||
* $ cc -o pan pan.c
|
||||
* $ pan -a
|
||||
*/
|
||||
|
||||
#define p in?[red]
|
||||
#define q out?[red]
|
||||
#define r (BS[a_id]@progress || BS[p_id]@progress)
|
||||
|
||||
mtype = { data, ho_cmd, ho_com, ho_acc, ho_fail, ch_rel, white, red, blue };
|
||||
|
||||
chan in = [1] of { mtype };
|
||||
chan out = [1] of { mtype };
|
||||
chan fa = [0] of { chan };
|
||||
chan fp = [0] of { chan };
|
||||
chan m1 = [0] of { chan };
|
||||
chan m2 = [0] of { chan };
|
||||
chan l = [0] of { chan };
|
||||
|
||||
byte a_id, p_id; /* ids of processes refered to in the property */
|
||||
|
||||
proctype CC() /* communication controller */
|
||||
{ chan m_old, m_new, x;
|
||||
mtype v;
|
||||
|
||||
do
|
||||
:: in?v ->
|
||||
printf("MSC: DATA\n");
|
||||
fa!data; fa!v
|
||||
:: l?m_new ->
|
||||
fa!ho_cmd; fa!m_new;
|
||||
printf("MSC: HAND-OFF\n");
|
||||
if
|
||||
:: fp?ho_com ->
|
||||
printf("MSC: CH_REL\n");
|
||||
fa!ch_rel; fa?m_old;
|
||||
l!m_old;
|
||||
x = fa; fa = fp; fp = x
|
||||
:: fa?ho_fail ->
|
||||
printf("MSC: FAIL\n");
|
||||
l!m_new
|
||||
fi
|
||||
od
|
||||
}
|
||||
|
||||
proctype HC(chan m) /* handover controller */
|
||||
{
|
||||
do
|
||||
:: l!m; l?m
|
||||
od
|
||||
}
|
||||
|
||||
proctype BS(chan f, m; bit how) /* base station */
|
||||
{ chan v;
|
||||
|
||||
if
|
||||
:: how -> goto Active
|
||||
:: else -> goto Passive
|
||||
fi;
|
||||
|
||||
Active:
|
||||
printf("MSC: ACTIVE\n");
|
||||
do
|
||||
:: f?data -> f?v; m!data; m!v
|
||||
:: f?ho_cmd -> /* handover command */
|
||||
progress: f?v; m!ho_cmd; m!v;
|
||||
if
|
||||
:: f?ch_rel ->
|
||||
f!m;
|
||||
goto Passive
|
||||
:: m?ho_fail ->
|
||||
printf("MSC: FAILURE\n");
|
||||
f!ho_fail
|
||||
fi
|
||||
od;
|
||||
|
||||
Passive:
|
||||
printf("MSC: PASSIVE\n");
|
||||
m?ho_acc -> f!ho_com;
|
||||
goto Active
|
||||
}
|
||||
|
||||
proctype MS(chan m) /* mobile station */
|
||||
{ chan m_new;
|
||||
mtype v;
|
||||
|
||||
do
|
||||
:: m?data -> m?v; out!v
|
||||
:: m?ho_cmd; m?m_new;
|
||||
if
|
||||
:: m_new!ho_acc; m = m_new
|
||||
:: m!ho_fail
|
||||
fi
|
||||
od
|
||||
}
|
||||
|
||||
active proctype System()
|
||||
{
|
||||
atomic {
|
||||
run HC(m1);
|
||||
run CC();
|
||||
p_id = run BS(fp, m1, 0); /* passive base station */
|
||||
a_id = run BS(fa, m2, 1); /* active base station */
|
||||
run MS(m2)
|
||||
}
|
||||
|
||||
end: do
|
||||
:: in!red; in!white; in!blue
|
||||
od
|
||||
}
|
||||
|
||||
active proctype Out()
|
||||
{
|
||||
end: do /* deadlocks if order is disturbed */
|
||||
:: out?red; out?white; out?blue
|
||||
od
|
||||
}
|
||||
1
bench/split-product/models/zune.ltl
Normal file
1
bench/split-product/models/zune.ltl
Normal file
|
|
@ -0,0 +1 @@
|
|||
![] (zune_at_S -> <> zune_at_E)
|
||||
70
bench/split-product/models/zune.pml
Normal file
70
bench/split-product/models/zune.pml
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* input: days elapsed since Jan 1, 1980
|
||||
* intended output: year and daynr in current year
|
||||
*
|
||||
* a bug caused all Zune-30 players to freeze on Dec 31, 2008
|
||||
* http://www.zuneboards.com/forums/zune-news/38143-cause-zune-30-leapyear-problem-isolated.html
|
||||
*
|
||||
* Wikepedia:
|
||||
* The bug was in the firmware clock-driver, which was written by Freescale
|
||||
* for their MC13783 PMIC processor. The same bug froze up Toshiba Gigabeat S
|
||||
* media players that share the same hardware and driver.
|
||||
*/
|
||||
|
||||
#define IsLeapYear(y) (((y%4 == 0) && (y%100 != 0)) || (y%400 == 0))
|
||||
|
||||
chan q = [0] of { short };
|
||||
|
||||
active proctype zune()
|
||||
{ short year = 1980;
|
||||
short days;
|
||||
|
||||
end: do
|
||||
:: q?days ->
|
||||
S: do
|
||||
:: days > 365 ->
|
||||
if
|
||||
:: IsLeapYear(year) ->
|
||||
if
|
||||
:: days > 366 ->
|
||||
days = days - 366;
|
||||
year++
|
||||
:: else
|
||||
#ifdef FIX
|
||||
-> break
|
||||
#endif
|
||||
fi
|
||||
:: else ->
|
||||
days = days - 365;
|
||||
year++
|
||||
fi
|
||||
:: else ->
|
||||
break
|
||||
od;
|
||||
E: printf("Year: %d, Day %d\n", year, days)
|
||||
od;
|
||||
/* check that the date is in a valid range */
|
||||
assert(days >= 1 && days <= 366);
|
||||
assert(days < 366 || IsLeapYear(year))
|
||||
}
|
||||
|
||||
init {
|
||||
/* jan 1, 2008 */
|
||||
short days = (2008 - 1980) * 365 + (2008-1980)/4;
|
||||
|
||||
if
|
||||
:: q!days + 365
|
||||
:: q!days + 366
|
||||
:: q!days + 367
|
||||
fi
|
||||
}
|
||||
|
||||
#define zune_at_S zune@S
|
||||
#define zune_at_E zune@E
|
||||
|
||||
/* sample analysis:
|
||||
spin -a zune.pml
|
||||
cc -o pan pan.c
|
||||
./pan -a # find matches of formula
|
||||
spin -t -p -l zune.pml # replay error sequence
|
||||
*/
|
||||
Loading…
Add table
Add a link
Reference in a new issue