Adding support for promela models via SpinS.
* configure.ac, iface/Makefile.am: Adjust. * iface/dve2/finite.test, iface/dve2/.gitignore, iface/dve2/Makefile.am, iface/dve2/README, iface/dve2/beem-peterson.4.dve, iface/dve2/dve2check.test, iface/dve2/defs.in, iface/dve2/finite.dve, iface/ltsmin/finite.test, iface/dve2/kripke.test, iface/dve2/dve2.cc, iface/dve2/dve2.hh, iface/dve2/dve2check.cc: Move to iface/ltsmin. * iface/ltsmin/.gitignore, iface/ltsmin/Makefile.am, iface/ltsmin/README, iface/ltsmin/beem-peterson.4.dve, iface/ltsmin/check.test, iface/ltsmin/defs.in, iface/ltsmin/finite.dve, iface/ltsmin/finite.test, iface/ltsmin/kripke.test, iface/ltsmin/ltsmin.cc, iface/ltsmin/ltsmin.hh, iface/ltsmin/modelcheck.cc: Factorize dve2 and spins interface in iface/ltsmin/ * iface/ltsmin/elevator2.1.pm, iface/ltsmin/finite.pm: Test promela models. * README: Document iface/ltsmin/ directory.
This commit is contained in:
parent
6dd2749c25
commit
dd4b821d93
18 changed files with 396 additions and 232 deletions
2
README
2
README
|
|
@ -180,7 +180,7 @@ wrap/ Wrappers for other languages.
|
||||||
tests/ Tests for these bindings
|
tests/ Tests for these bindings
|
||||||
ajax/ LTL-to-TGBA translator with web interface, using Ajax.
|
ajax/ LTL-to-TGBA translator with web interface, using Ajax.
|
||||||
iface/ Interfaces to other libraries.
|
iface/ Interfaces to other libraries.
|
||||||
dve2/ Interface with DiVinE2.
|
ltsmin/ Interface with DiVinE2 and SpinS.
|
||||||
|
|
||||||
Third party software
|
Third party software
|
||||||
--------------------
|
--------------------
|
||||||
|
|
|
||||||
|
|
@ -169,8 +169,8 @@ AC_CONFIG_FILES([
|
||||||
doc/Makefile
|
doc/Makefile
|
||||||
doc/tl/Makefile
|
doc/tl/Makefile
|
||||||
doc/org/init.el
|
doc/org/init.el
|
||||||
iface/dve2/defs
|
iface/ltsmin/defs
|
||||||
iface/dve2/Makefile
|
iface/ltsmin/Makefile
|
||||||
iface/Makefile
|
iface/Makefile
|
||||||
lib/Makefile
|
lib/Makefile
|
||||||
src/bin/Makefile
|
src/bin/Makefile
|
||||||
|
|
|
||||||
|
|
@ -17,4 +17,4 @@
|
||||||
## You should have received a copy of the GNU General Public License
|
## You should have received a copy of the GNU General Public License
|
||||||
## along with this program. If not, see <http://www.gnu.org/licenses/>.
|
## along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
SUBDIRS = dve2
|
SUBDIRS = ltsmin
|
||||||
|
|
|
||||||
|
|
@ -1,57 +0,0 @@
|
||||||
#!/bin/sh
|
|
||||||
# Copyright (C) 2011, 2013 Laboratoire de Recherche et Développement
|
|
||||||
# de l'Epita (LRDE).
|
|
||||||
#
|
|
||||||
# This file is part of Spot, a model checking library.
|
|
||||||
#
|
|
||||||
# Spot is free software; you can redistribute it and/or modify it
|
|
||||||
# under the terms of the GNU General Public License as published by
|
|
||||||
# the Free Software Foundation; either version 3 of the License, or
|
|
||||||
# (at your option) any later version.
|
|
||||||
#
|
|
||||||
# Spot is distributed in the hope that it will be useful, but WITHOUT
|
|
||||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
|
||||||
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
|
||||||
# License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License
|
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
|
|
||||||
. ./defs
|
|
||||||
|
|
||||||
divine compile > output 2>&1
|
|
||||||
|
|
||||||
if grep -i ltsmin output; then
|
|
||||||
:
|
|
||||||
else
|
|
||||||
echo "divine not installed, or no ltsmin interface"
|
|
||||||
exit 77
|
|
||||||
fi
|
|
||||||
|
|
||||||
set -e
|
|
||||||
run 0 ../dve2check -gm $srcdir/finite.dve '"P.a < 10"' > stdout
|
|
||||||
test `grep ' -> ' stdout | wc -l` = 25
|
|
||||||
test `grep 'P.a=' stdout | wc -l` = 15
|
|
||||||
|
|
||||||
run 0 ../dve2check -dtrue -gm $srcdir/finite.dve '"P.a < 10"' > stdout2
|
|
||||||
cmp stdout stdout2
|
|
||||||
|
|
||||||
run 0 ../dve2check -dfalse -gm $srcdir/finite.dve '"P.a < 10"' > stdout
|
|
||||||
test `grep ' -> ' stdout | wc -l` = 19
|
|
||||||
test `grep 'P.a=' stdout | wc -l` = 15
|
|
||||||
|
|
||||||
# the same with compressed states
|
|
||||||
run 0 ../dve2check -z -dfalse -gm $srcdir/finite.dve '"P.a < 10"' > stdout
|
|
||||||
test `grep ' -> ' stdout | wc -l` = 19
|
|
||||||
test `grep 'P.a=' stdout | wc -l` = 15
|
|
||||||
|
|
||||||
run 0 ../dve2check -ddead -E $srcdir/finite.dve \
|
|
||||||
'!(G(dead -> ("P.a==3" | "P.b==3")))'
|
|
||||||
|
|
||||||
run 0 ../dve2check -ddead -e $srcdir/finite.dve \
|
|
||||||
'!(G(dead -> ("P.a==2" | "P.b==3")))'
|
|
||||||
|
|
||||||
# This used to segfault because of a bug in
|
|
||||||
# tgba_product::transition_annotation.
|
|
||||||
run 0 ../dve2check -gp $srcdir/finite.dve true
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
*.dve2C
|
*.dve2C
|
||||||
*.dve.cpp
|
*.dve.cpp
|
||||||
dve2check
|
|
||||||
defs
|
defs
|
||||||
*.dir
|
*.dir
|
||||||
|
*.spins
|
||||||
|
*.c
|
||||||
|
check
|
||||||
|
|
@ -18,26 +18,26 @@
|
||||||
|
|
||||||
AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src \
|
AM_CPPFLAGS = -I$(top_srcdir)/src -I$(top_builddir)/src \
|
||||||
$(BUDDY_CPPFLAGS) -I$(top_srcdir)/ltdl
|
$(BUDDY_CPPFLAGS) -I$(top_srcdir)/ltdl
|
||||||
AM_CXXFLAGS = $(WARNING_CXXFLAGS)
|
AM_CXXFLAGS = $(WARNING_CXXFLAGS) -lpthread
|
||||||
|
|
||||||
dve2dir = $(pkgincludedir)/iface/dve2
|
ltsmindir = $(pkgincludedir)/iface/ltsmin
|
||||||
|
|
||||||
dve2_HEADERS = dve2.hh
|
ltsmin_HEADERS = ltsmin.hh
|
||||||
|
|
||||||
lib_LTLIBRARIES = libspotdve2.la
|
lib_LTLIBRARIES = libspotltsmin.la
|
||||||
libspotdve2_la_LIBADD = \
|
libspotltsmin_la_LIBADD = \
|
||||||
$(top_builddir)/src/libspot.la \
|
$(top_builddir)/src/libspot.la \
|
||||||
$(top_builddir)/ltdl/libltdlc.la
|
$(top_builddir)/ltdl/libltdlc.la
|
||||||
libspotdve2_la_SOURCES = dve2.cc
|
libspotltsmin_la_SOURCES = ltsmin.cc
|
||||||
|
|
||||||
noinst_PROGRAMS = dve2check
|
noinst_PROGRAMS = modelcheck
|
||||||
|
|
||||||
dve2check_SOURCES = dve2check.cc
|
modelcheck_SOURCES = modelcheck.cc
|
||||||
dve2check_LDADD = libspotdve2.la
|
modelcheck_LDADD = libspotltsmin.la
|
||||||
|
|
||||||
check_SCRIPTS = defs
|
check_SCRIPTS = defs
|
||||||
|
|
||||||
TESTS = dve2check.test finite.test kripke.test
|
TESTS = check.test finite.test kripke.test
|
||||||
EXTRA_DIST = $(TESTS) beem-peterson.4.dve finite.dve
|
EXTRA_DIST = $(TESTS) beem-peterson.4.dve finite.dve
|
||||||
|
|
||||||
kripke.test: $(top_builddir)/src/kripketest/parse_print$(EXEEXT)
|
kripke.test: $(top_builddir)/src/kripketest/parse_print$(EXEEXT)
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
This directory contains an interface that presents DiVinE models as
|
This directory contains an interface that presents DiVinE and PROMELA
|
||||||
kripke* objects for Spot.
|
models as kripke* objects for Spot.
|
||||||
|
|
||||||
The DiVinE model checker [http://anna.fi.muni.cz/divine/] has a
|
The DiVinE model checker [http://anna.fi.muni.cz/divine/] has a
|
||||||
specification language called DVE that makes it easy to model
|
specification language called DVE that makes it easy to model
|
||||||
|
|
@ -9,16 +9,12 @@ processes synchonizing through channels
|
||||||
A lot of models can be found in the BEEM database at
|
A lot of models can be found in the BEEM database at
|
||||||
http://anna.fi.muni.cz/models/
|
http://anna.fi.muni.cz/models/
|
||||||
|
|
||||||
For efficient generation of the state space of the model, DiVinE
|
The LTSmin people [http://fmt.cs.utwente.nl/tools/ltsmin/] patched
|
||||||
compiles the DVE input into a dynamic library that contains anything
|
DiVinE and SpinJa to compile models as dynamic libraries. This dynamic
|
||||||
needed to generate the state-space.
|
library provides a very simple C interface (no C++) and extra
|
||||||
|
information about state variables (name, type, possible values). We
|
||||||
The LTSmin people [http://fmt.cs.utwente.nl/tools/ltsmin/] have made a
|
use this interface so you will need to install their version of these
|
||||||
patched version of DiVinE that compiles a dynamic library with a very
|
tools to use Spot with DVE or PROMELA models.
|
||||||
simple C interface (no C++) and extra information about state
|
|
||||||
variables (name, type, possible values). We are using this interface,
|
|
||||||
therefore you need to install their version of DiVinE in order to use
|
|
||||||
Spot's DVE interface.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -47,14 +43,32 @@ model.dve2C (which is a dynamic library).
|
||||||
divine compile --ltsmin model.dve
|
divine compile --ltsmin model.dve
|
||||||
|
|
||||||
|
|
||||||
|
Installation of SpinS
|
||||||
|
======================
|
||||||
|
|
||||||
|
The extended version of SpinJa is called SpinS and should be included
|
||||||
|
with LTSmin.
|
||||||
|
You can download LTSmin from their website:
|
||||||
|
[http://fmt.cs.utwente.nl/tools/ltsmin/] and install it following the
|
||||||
|
INSTALL instructions.
|
||||||
|
|
||||||
|
To compile a promela model, simply run the following command:
|
||||||
|
spins model.pm
|
||||||
|
|
||||||
|
It should create a dynamic library called model.pm.spins in the
|
||||||
|
current directory.
|
||||||
|
|
||||||
|
|
||||||
Usage with Spot
|
Usage with Spot
|
||||||
===============
|
===============
|
||||||
|
|
||||||
The function load_dve2() defined in dve2.hh in this directory
|
The function load_dve2() defined in dve2.hh in this directory will
|
||||||
will accept "model.dve" or "model.dve2C" as file argument.
|
accept either a model or its compiled version as file argument. In
|
||||||
In the former case, it will call "divine compile --ltsmin"
|
the former case, it will call "divine compile --ltsmin model.dve" or
|
||||||
if "model.dve2C" does not exist or is older. Then it will
|
"spins model.pm" depending on the file extension, only if a compiled
|
||||||
load "model.dve2C" dynamically.
|
model with the corresponding file extension (.dve2C or .spins) does
|
||||||
|
not exist or is older. Then it will load the compiled model
|
||||||
|
dynamically.
|
||||||
|
|
||||||
load_dve2() also requires a set of atomic propositions that should
|
load_dve2() also requires a set of atomic propositions that should
|
||||||
be observed in the model. These are usually the atomic propositions
|
be observed in the model. These are usually the atomic propositions
|
||||||
|
|
@ -89,15 +103,15 @@ Usage with Spot
|
||||||
"P_0.j >= 2" Process P_0's variable j is greater or equal to 2.
|
"P_0.j >= 2" Process P_0's variable j is greater or equal to 2.
|
||||||
P_0.j This is equivalent to "P_0.j != 0".
|
P_0.j This is equivalent to "P_0.j != 0".
|
||||||
|
|
||||||
Comparisons operators available are "<", ">", ">=", "<=", "==", and
|
Comparison operators available are "<", ">", ">=", "<=", "==", and
|
||||||
"!=". The left operant should always be a variable and the right
|
"!=". The left operand should always be a variable and the right
|
||||||
operand should always be a number, so you cannot write something
|
operand should always be a number, so you cannot write something
|
||||||
like "P_0.j <= P_0.i".
|
like "P_0.j <= P_0.i".
|
||||||
|
|
||||||
Because the LTL parser knows nothing about the details of the
|
Because the LTL parser knows nothing about the details of the
|
||||||
languages we interface with, every atomic proposition that cannot be
|
languages we interface with, every atomic proposition that cannot be
|
||||||
express using only alphanumeric characters (plus `_' and `.') should
|
expressed using only alphanumeric characters (plus `_' and `.')
|
||||||
be enclosed in double quote.
|
should be enclosed in double quote.
|
||||||
|
|
||||||
Caveat: "P_0.j >= 2" and " P_0.j>=2" (watch the spaces!) are
|
Caveat: "P_0.j >= 2" and " P_0.j>=2" (watch the spaces!) are
|
||||||
considered to be two distinct atomic propositions with the same
|
considered to be two distinct atomic propositions with the same
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
# Copyright (C) 2011, 2012 Laboratoire de Recherche et Développement
|
# Copyright (C) 2011, 2012, 2014 Laboratoire de Recherche et Développement
|
||||||
# de l'Epita (LRDE).
|
# de l'Epita (LRDE).
|
||||||
#
|
#
|
||||||
# This file is part of Spot, a model checking library.
|
# This file is part of Spot, a model checking library.
|
||||||
|
|
@ -29,32 +29,47 @@ else
|
||||||
exit 77
|
exit 77
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if ! test -x "$(which spins)"; then
|
||||||
|
echo "spins not installed."
|
||||||
|
exit 77
|
||||||
|
fi
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
|
# Promela
|
||||||
|
for opt in '' '-z'; do
|
||||||
|
|
||||||
|
run 0 ../modelcheck $opt -E $srcdir/elevator2.1.pm \
|
||||||
|
'!G("req[1]==1" -> (F("p==1" && "cabin_0._pc==2")))'
|
||||||
|
run 0 ../modelcheck $opt -e $srcdir/elevator2.1.pm \
|
||||||
|
'F("p==2")'
|
||||||
|
done
|
||||||
|
|
||||||
|
# dve2
|
||||||
for opt in '' '-z'; do
|
for opt in '' '-z'; do
|
||||||
# The three examples from the README.
|
# The three examples from the README.
|
||||||
# (Don't run the first one using "run 0" because it would take too much
|
# (Don't run the first one using "run 0" because it would take too much
|
||||||
# time with valgrind.).
|
# time with valgrind.).
|
||||||
|
|
||||||
../dve2check $opt -E $srcdir/beem-peterson.4.dve \
|
../modelcheck $opt -E $srcdir/beem-peterson.4.dve \
|
||||||
'!GF(P_0.CS|P_1.CS|P_2.CS|P_3.CS)' \
|
'!GF(P_0.CS|P_1.CS|P_2.CS|P_3.CS)' \
|
||||||
| grep -v pages > stdout1
|
| grep -v pages > stdout1
|
||||||
# same formula, different syntax.
|
# same formula, different syntax.
|
||||||
../dve2check $opt -E $srcdir/beem-peterson.4.dve \
|
../modelcheck $opt -E $srcdir/beem-peterson.4.dve \
|
||||||
'!GF("P_0==CS"|"P_1 == CS"|"P_2 ==CS"|"P_3== CS")' \
|
'!GF("P_0==CS"|"P_1 == CS"|"P_2 ==CS"|"P_3== CS")' \
|
||||||
| grep -v pages > stdout2
|
| grep -v pages > stdout2
|
||||||
cmp stdout1 stdout2
|
cmp stdout1 stdout2
|
||||||
run 0 ../dve2check $opt -e $srcdir/beem-peterson.4.dve \
|
run 0 ../modelcheck $opt -e $srcdir/beem-peterson.4.dve \
|
||||||
'!G(P_0.wait -> F P_0.CS)'
|
'!G(P_0.wait -> F P_0.CS)'
|
||||||
run 0 ../dve2check $opt -e $srcdir/beem-peterson.4.dve '!G("pos[1] < 3")'
|
run 0 ../modelcheck $opt -e $srcdir/beem-peterson.4.dve '!G("pos[1] < 3")'
|
||||||
done
|
done
|
||||||
|
|
||||||
# Now check some error messages.
|
# Now check some error messages.
|
||||||
run 1 ../dve2check foo.dve "F(P_0.CS)" 2>stderr
|
run 1 ../modelcheck foo.dve "F(P_0.CS)" 2>stderr
|
||||||
cat stderr
|
cat stderr
|
||||||
grep 'Cannot open' stderr
|
grep 'Cannot open' stderr
|
||||||
# the dve2C file was generated in the current directory
|
# the dve2C file was generated in the current directory
|
||||||
run 1 ../dve2check beem-peterson.4.dve2C \
|
run 1 ../modelcheck beem-peterson.4.dve2C \
|
||||||
'Xfoo | P_0.f & X"P_0.k < 2xx" | G"pos[0]"' 2>stderr
|
'Xfoo | P_0.f & X"P_0.k < 2xx" | G"pos[0]"' 2>stderr
|
||||||
cat stderr
|
cat stderr
|
||||||
grep 'variable `foo' stderr
|
grep 'variable `foo' stderr
|
||||||
61
iface/ltsmin/elevator2.1.pm
Normal file
61
iface/ltsmin/elevator2.1.pm
Normal file
|
|
@ -0,0 +1,61 @@
|
||||||
|
byte req[4];
|
||||||
|
int t=0;
|
||||||
|
int p=0;
|
||||||
|
byte v=0;
|
||||||
|
|
||||||
|
|
||||||
|
active proctype cabin() {
|
||||||
|
|
||||||
|
idle: if
|
||||||
|
:: v>0; goto mov;
|
||||||
|
|
||||||
|
fi;
|
||||||
|
mov: if
|
||||||
|
:: t==p; goto open;
|
||||||
|
|
||||||
|
:: d_step {t<p;p = p-1;} goto mov;
|
||||||
|
|
||||||
|
:: d_step {t>p;p = p+1;} goto mov;
|
||||||
|
|
||||||
|
fi;
|
||||||
|
open: if
|
||||||
|
:: d_step {req[p] = 0;v = 0;} goto idle;
|
||||||
|
|
||||||
|
fi;
|
||||||
|
}
|
||||||
|
|
||||||
|
active proctype environment() {
|
||||||
|
|
||||||
|
read: if
|
||||||
|
:: d_step {req[0]==0;req[0] = 1;} goto read;
|
||||||
|
|
||||||
|
:: d_step {req[1]==0;req[1] = 1;} goto read;
|
||||||
|
|
||||||
|
:: d_step {req[2]==0;req[2] = 1;} goto read;
|
||||||
|
|
||||||
|
:: d_step {req[3]==0;req[3] = 1;} goto read;
|
||||||
|
|
||||||
|
fi;
|
||||||
|
}
|
||||||
|
|
||||||
|
active proctype controller() {
|
||||||
|
byte ldir=0;
|
||||||
|
|
||||||
|
wait: if
|
||||||
|
:: d_step {v==0;t = t+(2*ldir)-1;} goto work;
|
||||||
|
|
||||||
|
fi;
|
||||||
|
work: if
|
||||||
|
:: d_step {t<0 || t==4;ldir = 1-ldir;} goto wait;
|
||||||
|
|
||||||
|
:: t>=0 && t<4 && req[t]==1; goto done;
|
||||||
|
|
||||||
|
:: d_step {t>=0 && t<4 && req[t]==0;t = t+(2*ldir)-1;} goto work;
|
||||||
|
|
||||||
|
fi;
|
||||||
|
done: if
|
||||||
|
:: v = 1; goto wait;
|
||||||
|
|
||||||
|
fi;
|
||||||
|
}
|
||||||
|
|
||||||
8
iface/ltsmin/finite.pm
Normal file
8
iface/ltsmin/finite.pm
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
active proctype P() {
|
||||||
|
int a = 0;
|
||||||
|
int b = 0;
|
||||||
|
x: if
|
||||||
|
:: d_step {a < 3 && b < 3; a = a + 1; } goto x;
|
||||||
|
:: d_step {a < 3 && b < 3; b = b + 1; } goto x;
|
||||||
|
fi;
|
||||||
|
}
|
||||||
90
iface/ltsmin/finite.test
Executable file
90
iface/ltsmin/finite.test
Executable file
|
|
@ -0,0 +1,90 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# Copyright (C) 2011, 2013 Laboratoire de Recherche et Développement
|
||||||
|
# de l'Epita (LRDE).
|
||||||
|
#
|
||||||
|
# This file is part of Spot, a model checking library.
|
||||||
|
#
|
||||||
|
# Spot is free software; you can redistribute it and/or modify it
|
||||||
|
# under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# Spot is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
# or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
|
||||||
|
# License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
. ./defs
|
||||||
|
|
||||||
|
divine compile > output 2>&1
|
||||||
|
|
||||||
|
if grep -i ltsmin output; then
|
||||||
|
:
|
||||||
|
else
|
||||||
|
echo "divine not installed, or no ltsmin interface"
|
||||||
|
exit 77
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! test -x "$(which spins)"; then
|
||||||
|
echo "spins not installed."
|
||||||
|
exit 77
|
||||||
|
fi
|
||||||
|
|
||||||
|
set -e
|
||||||
|
run 0 ../modelcheck -gm $srcdir/finite.dve '"P.a < 10"' > stdout
|
||||||
|
test `grep ' -> ' stdout | wc -l` = 25
|
||||||
|
test `grep 'P.a=' stdout | wc -l` = 15
|
||||||
|
|
||||||
|
run 0 ../modelcheck -dtrue -gm $srcdir/finite.dve '"P.a < 10"' > stdout2
|
||||||
|
cmp stdout stdout2
|
||||||
|
|
||||||
|
run 0 ../modelcheck -dfalse -gm $srcdir/finite.dve '"P.a < 10"' > stdout
|
||||||
|
test `grep ' -> ' stdout | wc -l` = 19
|
||||||
|
test `grep 'P.a=' stdout | wc -l` = 15
|
||||||
|
|
||||||
|
# the same with compressed states
|
||||||
|
run 0 ../modelcheck -z -dfalse -gm $srcdir/finite.dve '"P.a < 10"' > stdout
|
||||||
|
test `grep ' -> ' stdout | wc -l` = 19
|
||||||
|
test `grep 'P.a=' stdout | wc -l` = 15
|
||||||
|
|
||||||
|
run 0 ../modelcheck -ddead -E $srcdir/finite.dve \
|
||||||
|
'!(G(dead -> ("P.a==3" | "P.b==3")))'
|
||||||
|
|
||||||
|
run 0 ../modelcheck -ddead -e $srcdir/finite.dve \
|
||||||
|
'!(G(dead -> ("P.a==2" | "P.b==3")))'
|
||||||
|
|
||||||
|
# This used to segfault because of a bug in
|
||||||
|
# tgba_product::transition_annotation.
|
||||||
|
run 0 ../modelcheck -gp $srcdir/finite.dve true
|
||||||
|
|
||||||
|
# Same tests with finite.pm.
|
||||||
|
# Compile it beforehand to avoid compiler's output interference.
|
||||||
|
spins $srcdir/finite.pm
|
||||||
|
run 0 ../modelcheck -gm $srcdir/finite.pm.spins '"P_0.a < 10"' > stdout
|
||||||
|
test `grep ' -> ' stdout | wc -l` = 25
|
||||||
|
test `grep 'P_0.a=' stdout | wc -l` = 15
|
||||||
|
|
||||||
|
run 0 ../modelcheck -dtrue -gm $srcdir/finite.pm.spins '"P_0.a < 10"' > stdout2
|
||||||
|
diff stdout stdout2
|
||||||
|
|
||||||
|
run 0 ../modelcheck -dfalse -gm $srcdir/finite.pm.spins '"P_0.a < 10"' > stdout
|
||||||
|
test `grep ' -> ' stdout | wc -l` = 19
|
||||||
|
test `grep 'P_0.a=' stdout | wc -l` = 15
|
||||||
|
|
||||||
|
# the same with compressed states
|
||||||
|
run 0 ../modelcheck -z -dfalse -gm $srcdir/finite.pm.spins '"P_0.a < 10"' \
|
||||||
|
> stdout
|
||||||
|
test `grep ' -> ' stdout | wc -l` = 19
|
||||||
|
test `grep 'P_0.a=' stdout | wc -l` = 15
|
||||||
|
|
||||||
|
run 0 ../modelcheck -ddead -E $srcdir/finite.pm.spins \
|
||||||
|
'!(G(dead -> ("P_0.a==3" | "P_0.b==3")))'
|
||||||
|
|
||||||
|
run 0 ../modelcheck -ddead -e $srcdir/finite.pm.spins \
|
||||||
|
'!(G(dead -> ("P_0.a==2" | "P_0.b==3")))'
|
||||||
|
|
||||||
|
run 0 ../modelcheck -gp $srcdir/finite.pm.spins true
|
||||||
|
|
@ -33,10 +33,10 @@ fi
|
||||||
|
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
run 0 ../dve2check -gK ${srcdir}/finite.dve 'F("P.a > 5")' > output
|
run 0 ../modelcheck -gK ${srcdir}/finite.dve 'F("P.a > 5")' > output
|
||||||
run 0 ${top_builddir}/src/kripketest/parse_print output | tr -d '"' > output2
|
run 0 ${top_builddir}/src/kripketest/parse_print output | tr -d '"' > output2
|
||||||
tr -d '"' < output >outputF
|
tr -d '"' < output >outputF
|
||||||
cmp outputF output2
|
cmp outputF output2
|
||||||
|
|
||||||
../dve2check -gK $srcdir/beem-peterson.4.dve '!G("pos[1] < 3")' > outputP
|
../modelcheck -gK $srcdir/beem-peterson.4.dve '!G("pos[1] < 3")' > outputP
|
||||||
${top_builddir}/src/tgbatest/ltl2tgba -e -KPoutputP '!G("pos[1] < 3")'
|
${top_builddir}/src/tgbatest/ltl2tgba -e -KPoutputP '!G("pos[1] < 3")'
|
||||||
|
|
@ -30,21 +30,20 @@
|
||||||
# define WEXITSTATUS(x) ((x) & 0xff)
|
# define WEXITSTATUS(x) ((x) & 0xff)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "dve2.hh"
|
#include "ltsmin.hh"
|
||||||
#include "misc/hashfunc.hh"
|
#include "misc/hashfunc.hh"
|
||||||
#include "misc/fixpool.hh"
|
#include "misc/fixpool.hh"
|
||||||
#include "misc/mspool.hh"
|
#include "misc/mspool.hh"
|
||||||
#include "misc/intvcomp.hh"
|
#include "misc/intvcomp.hh"
|
||||||
#include "misc/intvcmp2.hh"
|
#include "misc/intvcmp2.hh"
|
||||||
|
|
||||||
|
|
||||||
namespace spot
|
namespace spot
|
||||||
{
|
{
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
// DVE2 --ltsmin interface
|
// spins interface
|
||||||
|
|
||||||
typedef struct transition_info {
|
typedef struct transition_info {
|
||||||
int* labels; // edge labels, NULL, or pointer to the edge label(s)
|
int* labels; // edge labels, NULL, or pointer to the edge label(s)
|
||||||
|
|
@ -55,29 +54,27 @@ namespace spot
|
||||||
transition_info_t *transition_info,
|
transition_info_t *transition_info,
|
||||||
int *dst);
|
int *dst);
|
||||||
|
|
||||||
struct dve2_interface
|
struct spins_interface
|
||||||
{
|
{
|
||||||
lt_dlhandle handle; // handle to the dynamic library
|
lt_dlhandle handle; // handle to the dynamic library
|
||||||
void (*get_initial_state)(void *to);
|
void (*get_initial_state)(void *to);
|
||||||
int (*have_property)();
|
int (*have_property)();
|
||||||
int (*get_successors)(void* m, int *in, TransitionCB, void *arg);
|
int (*get_successors)(void* m, int *in, TransitionCB, void *arg);
|
||||||
|
int (*get_state_size)();
|
||||||
int (*get_state_variable_count)();
|
|
||||||
const char* (*get_state_variable_name)(int var);
|
const char* (*get_state_variable_name)(int var);
|
||||||
int (*get_state_variable_type)(int var);
|
int (*get_state_variable_type)(int var);
|
||||||
int (*get_state_variable_type_count)();
|
int (*get_type_count)();
|
||||||
const char* (*get_state_variable_type_name)(int type);
|
const char* (*get_type_name)(int type);
|
||||||
int (*get_state_variable_type_value_count)(int type);
|
int (*get_type_value_count)(int type);
|
||||||
const char* (*get_state_variable_type_value)(int type, int value);
|
const char* (*get_type_value_name)(int type, int value);
|
||||||
int (*get_transition_count)();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
// STATE
|
// STATE
|
||||||
|
|
||||||
struct dve2_state: public state
|
struct spins_state: public state
|
||||||
{
|
{
|
||||||
dve2_state(int s, fixed_size_pool* p)
|
spins_state(int s, fixed_size_pool* p)
|
||||||
: pool(p), size(s), count(1)
|
: pool(p), size(s), count(1)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -89,10 +86,10 @@ namespace spot
|
||||||
hash_value = wang32_hash(hash_value ^ vars[i]);
|
hash_value = wang32_hash(hash_value ^ vars[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
dve2_state* clone() const
|
spins_state* clone() const
|
||||||
{
|
{
|
||||||
++count;
|
++count;
|
||||||
return const_cast<dve2_state*>(this);
|
return const_cast<spins_state*>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroy() const
|
void destroy() const
|
||||||
|
|
@ -111,7 +108,7 @@ namespace spot
|
||||||
{
|
{
|
||||||
if (this == other)
|
if (this == other)
|
||||||
return 0;
|
return 0;
|
||||||
const dve2_state* o = down_cast<const dve2_state*>(other);
|
const spins_state* o = down_cast<const spins_state*>(other);
|
||||||
assert(o);
|
assert(o);
|
||||||
if (hash_value < o->hash_value)
|
if (hash_value < o->hash_value)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -122,7 +119,7 @@ namespace spot
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
~dve2_state()
|
~spins_state()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -134,9 +131,9 @@ namespace spot
|
||||||
int vars[0];
|
int vars[0];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dve2_compressed_state: public state
|
struct spins_compressed_state: public state
|
||||||
{
|
{
|
||||||
dve2_compressed_state(int s, multiple_size_pool* p)
|
spins_compressed_state(int s, multiple_size_pool* p)
|
||||||
: pool(p), size(s), count(1)
|
: pool(p), size(s), count(1)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
@ -148,10 +145,10 @@ namespace spot
|
||||||
hash_value = wang32_hash(hash_value ^ vars[i]);
|
hash_value = wang32_hash(hash_value ^ vars[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
dve2_compressed_state* clone() const
|
spins_compressed_state* clone() const
|
||||||
{
|
{
|
||||||
++count;
|
++count;
|
||||||
return const_cast<dve2_compressed_state*>(this);
|
return const_cast<spins_compressed_state*>(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
void destroy() const
|
void destroy() const
|
||||||
|
|
@ -170,8 +167,8 @@ namespace spot
|
||||||
{
|
{
|
||||||
if (this == other)
|
if (this == other)
|
||||||
return 0;
|
return 0;
|
||||||
const dve2_compressed_state* o =
|
const spins_compressed_state* o =
|
||||||
down_cast<const dve2_compressed_state*>(other);
|
down_cast<const spins_compressed_state*>(other);
|
||||||
assert(o);
|
assert(o);
|
||||||
if (hash_value < o->hash_value)
|
if (hash_value < o->hash_value)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
@ -188,7 +185,7 @@ namespace spot
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
~dve2_compressed_state()
|
~spins_compressed_state()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -223,8 +220,8 @@ namespace spot
|
||||||
{
|
{
|
||||||
callback_context* ctx = static_cast<callback_context*>(arg);
|
callback_context* ctx = static_cast<callback_context*>(arg);
|
||||||
fixed_size_pool* p = static_cast<fixed_size_pool*>(ctx->pool);
|
fixed_size_pool* p = static_cast<fixed_size_pool*>(ctx->pool);
|
||||||
dve2_state* out =
|
spins_state* out =
|
||||||
new(p->allocate()) dve2_state(ctx->state_size, p);
|
new(p->allocate()) spins_state(ctx->state_size, p);
|
||||||
memcpy(out->vars, dst, ctx->state_size * sizeof(int));
|
memcpy(out->vars, dst, ctx->state_size * sizeof(int));
|
||||||
out->compute_hash();
|
out->compute_hash();
|
||||||
ctx->transitions.push_back(out);
|
ctx->transitions.push_back(out);
|
||||||
|
|
@ -238,9 +235,9 @@ namespace spot
|
||||||
size_t csize = ctx->state_size * 2;
|
size_t csize = ctx->state_size * 2;
|
||||||
ctx->compress(dst, ctx->state_size, ctx->compressed, csize);
|
ctx->compress(dst, ctx->state_size, ctx->compressed, csize);
|
||||||
|
|
||||||
void* mem = p->allocate(sizeof(dve2_compressed_state)
|
void* mem = p->allocate(sizeof(spins_compressed_state)
|
||||||
+ sizeof(int) * csize);
|
+ sizeof(int) * csize);
|
||||||
dve2_compressed_state* out = new(mem) dve2_compressed_state(csize, p);
|
spins_compressed_state* out = new(mem) spins_compressed_state(csize, p);
|
||||||
memcpy(out->vars, ctx->compressed, csize * sizeof(int));
|
memcpy(out->vars, ctx->compressed, csize * sizeof(int));
|
||||||
out->compute_hash();
|
out->compute_hash();
|
||||||
ctx->transitions.push_back(out);
|
ctx->transitions.push_back(out);
|
||||||
|
|
@ -249,11 +246,11 @@ namespace spot
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
// SUCC_ITERATOR
|
// SUCC_ITERATOR
|
||||||
|
|
||||||
class dve2_succ_iterator: public kripke_succ_iterator
|
class spins_succ_iterator: public kripke_succ_iterator
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
dve2_succ_iterator(const callback_context* cc,
|
spins_succ_iterator(const callback_context* cc,
|
||||||
bdd cond)
|
bdd cond)
|
||||||
: kripke_succ_iterator(cond), cc_(cc)
|
: kripke_succ_iterator(cond), cc_(cc)
|
||||||
{
|
{
|
||||||
|
|
@ -266,7 +263,7 @@ namespace spot
|
||||||
kripke_succ_iterator::recycle(cond);
|
kripke_succ_iterator::recycle(cond);
|
||||||
}
|
}
|
||||||
|
|
||||||
~dve2_succ_iterator()
|
~spins_succ_iterator()
|
||||||
{
|
{
|
||||||
delete cc_;
|
delete cc_;
|
||||||
}
|
}
|
||||||
|
|
@ -327,14 +324,14 @@ namespace spot
|
||||||
|
|
||||||
int
|
int
|
||||||
convert_aps(const ltl::atomic_prop_set* aps,
|
convert_aps(const ltl::atomic_prop_set* aps,
|
||||||
const dve2_interface* d,
|
const spins_interface* d,
|
||||||
bdd_dict_ptr dict,
|
bdd_dict_ptr dict,
|
||||||
const ltl::formula* dead,
|
const ltl::formula* dead,
|
||||||
prop_set& out)
|
prop_set& out)
|
||||||
{
|
{
|
||||||
int errors = 0;
|
int errors = 0;
|
||||||
|
|
||||||
int state_size = d->get_state_variable_count();
|
int state_size = d->get_state_size();
|
||||||
typedef std::map<std::string, var_info> val_map_t;
|
typedef std::map<std::string, var_info> val_map_t;
|
||||||
val_map_t val_map;
|
val_map_t val_map;
|
||||||
|
|
||||||
|
|
@ -346,14 +343,14 @@ namespace spot
|
||||||
val_map[name] = v;
|
val_map[name] = v;
|
||||||
}
|
}
|
||||||
|
|
||||||
int type_count = d->get_state_variable_type_count();
|
int type_count = d->get_type_count();
|
||||||
typedef std::map<std::string, int> enum_map_t;
|
typedef std::map<std::string, int> enum_map_t;
|
||||||
std::vector<enum_map_t> enum_map(type_count);
|
std::vector<enum_map_t> enum_map(type_count);
|
||||||
for (int i = 0; i < type_count; ++i)
|
for (int i = 0; i < type_count; ++i)
|
||||||
{
|
{
|
||||||
int enum_count = d->get_state_variable_type_value_count(i);
|
int enum_count = d->get_type_value_count(i);
|
||||||
for (int j = 0; j < enum_count; ++j)
|
for (int j = 0; j < enum_count; ++j)
|
||||||
enum_map[i].emplace(d->get_state_variable_type_value(i, j), j);
|
enum_map[i].emplace(d->get_type_value_name(i, j), j);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ltl::atomic_prop_set::const_iterator ap = aps->begin();
|
for (ltl::atomic_prop_set::const_iterator ap = aps->begin();
|
||||||
|
|
@ -600,15 +597,15 @@ namespace spot
|
||||||
////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////
|
||||||
// KRIPKE
|
// KRIPKE
|
||||||
|
|
||||||
class dve2_kripke: public kripke
|
class spins_kripke: public kripke
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
dve2_kripke(const dve2_interface* d, const bdd_dict_ptr& dict,
|
spins_kripke(const spins_interface* d, const bdd_dict_ptr& dict,
|
||||||
const prop_set* ps, const ltl::formula* dead, int compress)
|
const prop_set* ps, const ltl::formula* dead, int compress)
|
||||||
: kripke(dict),
|
: kripke(dict),
|
||||||
d_(d),
|
d_(d),
|
||||||
state_size_(d_->get_state_variable_count()),
|
state_size_(d_->get_state_size()),
|
||||||
dict_(dict), ps_(ps),
|
dict_(dict), ps_(ps),
|
||||||
compress_(compress == 0 ? 0
|
compress_(compress == 0 ? 0
|
||||||
: compress == 1 ? int_array_array_compress
|
: compress == 1 ? int_array_array_compress
|
||||||
|
|
@ -618,8 +615,8 @@ namespace spot
|
||||||
: int_array_array_decompress2),
|
: int_array_array_decompress2),
|
||||||
uncompressed_(compress ? new int[state_size_ + 30] : 0),
|
uncompressed_(compress ? new int[state_size_ + 30] : 0),
|
||||||
compressed_(compress ? new int[state_size_ * 2] : 0),
|
compressed_(compress ? new int[state_size_ * 2] : 0),
|
||||||
statepool_(compress ? sizeof(dve2_compressed_state) :
|
statepool_(compress ? sizeof(spins_compressed_state) :
|
||||||
(sizeof(dve2_state) + state_size_ * sizeof(int))),
|
(sizeof(spins_state) + state_size_ * sizeof(int))),
|
||||||
state_condition_last_state_(0), state_condition_last_cc_(0)
|
state_condition_last_state_(0), state_condition_last_cc_(0)
|
||||||
{
|
{
|
||||||
vname_ = new const char*[state_size_];
|
vname_ = new const char*[state_size_];
|
||||||
|
|
@ -632,7 +629,7 @@ namespace spot
|
||||||
// output.
|
// output.
|
||||||
int type = d->get_state_variable_type(i);
|
int type = d->get_state_variable_type(i);
|
||||||
format_filter_[i] =
|
format_filter_[i] =
|
||||||
(d->get_state_variable_type_value_count(type) != 1);
|
(d->get_type_value_count(type) != 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register the "dead" proposition. There are three cases to
|
// Register the "dead" proposition. There are three cases to
|
||||||
|
|
@ -666,7 +663,7 @@ namespace spot
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
~dve2_kripke()
|
~spins_kripke()
|
||||||
{
|
{
|
||||||
if (iter_cache_)
|
if (iter_cache_)
|
||||||
{
|
{
|
||||||
|
|
@ -704,10 +701,10 @@ namespace spot
|
||||||
|
|
||||||
multiple_size_pool* p =
|
multiple_size_pool* p =
|
||||||
const_cast<multiple_size_pool*>(&compstatepool_);
|
const_cast<multiple_size_pool*>(&compstatepool_);
|
||||||
void* mem = p->allocate(sizeof(dve2_compressed_state)
|
void* mem = p->allocate(sizeof(spins_compressed_state)
|
||||||
+ sizeof(int) * csize);
|
+ sizeof(int) * csize);
|
||||||
dve2_compressed_state* res = new(mem)
|
spins_compressed_state* res = new(mem)
|
||||||
dve2_compressed_state(csize, p);
|
spins_compressed_state(csize, p);
|
||||||
memcpy(res->vars, compressed_, csize * sizeof(int));
|
memcpy(res->vars, compressed_, csize * sizeof(int));
|
||||||
res->compute_hash();
|
res->compute_hash();
|
||||||
return res;
|
return res;
|
||||||
|
|
@ -715,7 +712,7 @@ namespace spot
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
fixed_size_pool* p = const_cast<fixed_size_pool*>(&statepool_);
|
fixed_size_pool* p = const_cast<fixed_size_pool*>(&statepool_);
|
||||||
dve2_state* res = new(p->allocate()) dve2_state(state_size_, p);
|
spins_state* res = new(p->allocate()) spins_state(state_size_, p);
|
||||||
d_->get_initial_state(res->vars);
|
d_->get_initial_state(res->vars);
|
||||||
res->compute_hash();
|
res->compute_hash();
|
||||||
return res;
|
return res;
|
||||||
|
|
@ -828,8 +825,8 @@ namespace spot
|
||||||
const int* vars;
|
const int* vars;
|
||||||
if (compress_)
|
if (compress_)
|
||||||
{
|
{
|
||||||
const dve2_compressed_state* s =
|
const spins_compressed_state* s =
|
||||||
down_cast<const dve2_compressed_state*>(st);
|
down_cast<const spins_compressed_state*>(st);
|
||||||
assert(s);
|
assert(s);
|
||||||
|
|
||||||
decompress_(s->vars, s->size, uncompressed_, state_size_);
|
decompress_(s->vars, s->size, uncompressed_, state_size_);
|
||||||
|
|
@ -837,7 +834,7 @@ namespace spot
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
const dve2_state* s = down_cast<const dve2_state*>(st);
|
const spins_state* s = down_cast<const spins_state*>(st);
|
||||||
assert(s);
|
assert(s);
|
||||||
vars = s->vars;
|
vars = s->vars;
|
||||||
}
|
}
|
||||||
|
|
@ -846,7 +843,7 @@ namespace spot
|
||||||
|
|
||||||
|
|
||||||
virtual
|
virtual
|
||||||
dve2_succ_iterator*
|
spins_succ_iterator*
|
||||||
succ_iter(const state* st) const
|
succ_iter(const state* st) const
|
||||||
{
|
{
|
||||||
// This may also compute successors in state_condition_last_cc
|
// This may also compute successors in state_condition_last_cc
|
||||||
|
|
@ -870,13 +867,13 @@ namespace spot
|
||||||
|
|
||||||
if (iter_cache_)
|
if (iter_cache_)
|
||||||
{
|
{
|
||||||
dve2_succ_iterator* it =
|
spins_succ_iterator* it =
|
||||||
down_cast<dve2_succ_iterator*>(iter_cache_);
|
down_cast<spins_succ_iterator*>(iter_cache_);
|
||||||
it->recycle(cc, scond);
|
it->recycle(cc, scond);
|
||||||
iter_cache_ = nullptr;
|
iter_cache_ = nullptr;
|
||||||
return it;
|
return it;
|
||||||
}
|
}
|
||||||
return new dve2_succ_iterator(cc, scond);
|
return new spins_succ_iterator(cc, scond);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual
|
virtual
|
||||||
|
|
@ -920,7 +917,7 @@ namespace spot
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const dve2_interface* d_;
|
const spins_interface* d_;
|
||||||
int state_size_;
|
int state_size_;
|
||||||
bdd_dict_ptr dict_;
|
bdd_dict_ptr dict_;
|
||||||
const char** vname_;
|
const char** vname_;
|
||||||
|
|
@ -952,13 +949,32 @@ namespace spot
|
||||||
// LOADER
|
// LOADER
|
||||||
|
|
||||||
|
|
||||||
// Call divine to compile "foo.dve" as "foo.dve2C" if the latter
|
// Call spins to compile "foo.prom" as "foo.prom.spins" if the latter
|
||||||
// does not exist already or is older.
|
// does not exist already or is older.
|
||||||
bool
|
bool
|
||||||
compile_dve2(std::string& filename, bool verbose)
|
compile_model(std::string& filename, std::string& ext, bool verbose)
|
||||||
{
|
{
|
||||||
|
std::string command;
|
||||||
|
std::string compiled_ext;
|
||||||
|
|
||||||
std::string command = "divine compile --ltsmin " + filename;
|
if (ext == ".prom" || ext == ".pm" || ext == ".pml")
|
||||||
|
{
|
||||||
|
command = "spins " + filename;
|
||||||
|
compiled_ext = ".spins";
|
||||||
|
}
|
||||||
|
else if (ext == ".dve")
|
||||||
|
{
|
||||||
|
command = "divine compile --ltsmin " + filename;
|
||||||
|
compiled_ext = "2C";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (verbose)
|
||||||
|
std::cerr << "Unknown extension `" << ext
|
||||||
|
<< "'. Use `.prom', `.pm', `.pml', `.dve', `.dve2C' or"\
|
||||||
|
"`.prom.spins'." << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
struct stat s;
|
struct stat s;
|
||||||
if (stat(filename.c_str(), &s) != 0)
|
if (stat(filename.c_str(), &s) != 0)
|
||||||
|
|
@ -971,7 +987,7 @@ namespace spot
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string old = filename;
|
std::string old = filename;
|
||||||
filename += "2C";
|
filename += compiled_ext;
|
||||||
|
|
||||||
// Remove any directory, because the new file will
|
// Remove any directory, because the new file will
|
||||||
// be compiled in the current directory.
|
// be compiled in the current directory.
|
||||||
|
|
@ -982,7 +998,7 @@ namespace spot
|
||||||
struct stat d;
|
struct stat d;
|
||||||
if (stat(filename.c_str(), &d) == 0)
|
if (stat(filename.c_str(), &d) == 0)
|
||||||
if (s.st_mtime < d.st_mtime)
|
if (s.st_mtime < d.st_mtime)
|
||||||
// The dve2C is up-to-date, no need to recompile it.
|
// The .prom.spins is up-to-date, no need to recompile it.
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
int res = system(command.c_str());
|
int res = system(command.c_str());
|
||||||
|
|
@ -997,9 +1013,8 @@ namespace spot
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
kripke_ptr
|
kripke_ptr
|
||||||
load_dve2(const std::string& file_arg, const bdd_dict_ptr& dict,
|
load_model(const std::string& file_arg, const bdd_dict_ptr& dict,
|
||||||
const ltl::atomic_prop_set* to_observe,
|
const ltl::atomic_prop_set* to_observe,
|
||||||
const ltl::formula* dead,
|
const ltl::formula* dead,
|
||||||
int compress,
|
int compress,
|
||||||
|
|
@ -1012,22 +1027,15 @@ namespace spot
|
||||||
file = "./" + file_arg;
|
file = "./" + file_arg;
|
||||||
|
|
||||||
std::string ext = file.substr(file.find_last_of("."));
|
std::string ext = file.substr(file.find_last_of("."));
|
||||||
if (ext == ".dve")
|
if (ext != ".spins" && ext != ".dve2C")
|
||||||
{
|
{
|
||||||
if (compile_dve2(file, verbose))
|
if (compile_model(file, ext, verbose))
|
||||||
{
|
{
|
||||||
if (verbose)
|
if (verbose)
|
||||||
std::cerr << "Failed to compile `" << file_arg
|
std::cerr << "Failed to compile `" << file_arg
|
||||||
<< "'." << std::endl;
|
<< "'." << std::endl;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else if (ext != ".dve2C")
|
|
||||||
{
|
|
||||||
if (verbose)
|
|
||||||
std::cerr << "Unknown extension `" << ext
|
|
||||||
<< "'. Use `.dve' or `.dve2C'." << std::endl;
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lt_dlinit())
|
if (lt_dlinit())
|
||||||
|
|
@ -1046,43 +1054,66 @@ namespace spot
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
dve2_interface* d = new dve2_interface;
|
spins_interface* d = new spins_interface;
|
||||||
d->handle = h;
|
d->handle = h;
|
||||||
|
|
||||||
d->get_initial_state = (void (*)(void*))
|
// SpinS interface.
|
||||||
lt_dlsym(h, "get_initial_state");
|
if ((d->get_initial_state = (void (*)(void*))
|
||||||
d->have_property = (int (*)())
|
lt_dlsym(h, "spins_get_initial_state")))
|
||||||
lt_dlsym(h, "have_property");
|
{
|
||||||
d->get_successors = (int (*)(void*, int*, TransitionCB, void*))
|
d->have_property = nullptr;
|
||||||
lt_dlsym(h, "get_successors");
|
d->get_successors = (int (*)(void*, int*, TransitionCB, void*))
|
||||||
d->get_state_variable_count = (int (*)())
|
lt_dlsym(h, "spins_get_successor_all");
|
||||||
lt_dlsym(h, "get_state_variable_count");
|
d->get_state_size = (int (*)())
|
||||||
d->get_state_variable_name = (const char* (*)(int))
|
lt_dlsym(h, "spins_get_state_size");
|
||||||
lt_dlsym(h, "get_state_variable_name");
|
d->get_state_variable_name = (const char* (*)(int))
|
||||||
d->get_state_variable_type = (int (*)(int))
|
lt_dlsym(h, "spins_get_state_variable_name");
|
||||||
lt_dlsym(h, "get_state_variable_type");
|
d->get_state_variable_type = (int (*)(int))
|
||||||
d->get_state_variable_type_count = (int (*)())
|
lt_dlsym(h, "spins_get_state_variable_type");
|
||||||
lt_dlsym(h, "get_state_variable_type_count");
|
d->get_type_count = (int (*)())
|
||||||
d->get_state_variable_type_name = (const char* (*)(int))
|
lt_dlsym(h, "spins_get_type_count");
|
||||||
lt_dlsym(h, "get_state_variable_type_name");
|
d->get_type_name = (const char* (*)(int))
|
||||||
d->get_state_variable_type_value_count = (int (*)(int))
|
lt_dlsym(h, "spins_get_type_name");
|
||||||
lt_dlsym(h, "get_state_variable_type_value_count");
|
d->get_type_value_count = (int (*)(int))
|
||||||
d->get_state_variable_type_value = (const char* (*)(int, int))
|
lt_dlsym(h, "spins_get_type_value_count");
|
||||||
lt_dlsym(h, "get_state_variable_type_value");
|
d->get_type_value_name = (const char* (*)(int, int))
|
||||||
d->get_transition_count = (int (*)())
|
lt_dlsym(h, "spins_get_type_value_name");
|
||||||
lt_dlsym(h, "get_transition_count");
|
}
|
||||||
|
// dve2 interface.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
d->get_initial_state = (void (*)(void*))
|
||||||
|
lt_dlsym(h, "get_initial_state");
|
||||||
|
d->have_property = (int (*)())
|
||||||
|
lt_dlsym(h, "have_property");
|
||||||
|
d->get_successors = (int (*)(void*, int*, TransitionCB, void*))
|
||||||
|
lt_dlsym(h, "get_successors");
|
||||||
|
d->get_state_size = (int (*)())
|
||||||
|
lt_dlsym(h, "get_state_variable_count");
|
||||||
|
d->get_state_variable_name = (const char* (*)(int))
|
||||||
|
lt_dlsym(h, "get_state_variable_name");
|
||||||
|
d->get_state_variable_type = (int (*)(int))
|
||||||
|
lt_dlsym(h, "get_state_variable_type");
|
||||||
|
d->get_type_count = (int (*)())
|
||||||
|
lt_dlsym(h, "get_state_variable_type_count");
|
||||||
|
d->get_type_name = (const char* (*)(int))
|
||||||
|
lt_dlsym(h, "get_state_variable_type_name");
|
||||||
|
d->get_type_value_count = (int (*)(int))
|
||||||
|
lt_dlsym(h, "get_state_variable_type_value_count");
|
||||||
|
d->get_type_value_name = (const char* (*)(int, int))
|
||||||
|
lt_dlsym(h, "get_state_variable_type_value");
|
||||||
|
}
|
||||||
|
|
||||||
if (!(d->get_initial_state
|
if (!(
|
||||||
&& d->have_property
|
d->get_initial_state
|
||||||
&& d->get_successors
|
&& d->get_successors
|
||||||
&& d->get_state_variable_count
|
&& d->get_state_size
|
||||||
&& d->get_state_variable_name
|
&& d->get_state_variable_name
|
||||||
&& d->get_state_variable_type
|
&& d->get_state_variable_type
|
||||||
&& d->get_state_variable_type_count
|
&& d->get_type_count
|
||||||
&& d->get_state_variable_type_name
|
&& d->get_type_name
|
||||||
&& d->get_state_variable_type_value_count
|
&& d->get_type_value_count
|
||||||
&& d->get_state_variable_type_value
|
&& d->get_type_value_name))
|
||||||
&& d->get_transition_count))
|
|
||||||
{
|
{
|
||||||
if (verbose)
|
if (verbose)
|
||||||
std::cerr << "Failed to resolve some symbol while loading `"
|
std::cerr << "Failed to resolve some symbol while loading `"
|
||||||
|
|
@ -1092,14 +1123,14 @@ namespace spot
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d->have_property())
|
if (d->have_property && d->have_property())
|
||||||
{
|
{
|
||||||
if (verbose)
|
if (verbose)
|
||||||
std::cerr << "Model with an embedded property are not supported."
|
std::cerr << "Model with an embedded property are not supported."
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
delete d;
|
delete d;
|
||||||
lt_dlexit();
|
lt_dlexit();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
prop_set* ps = new prop_set;
|
prop_set* ps = new prop_set;
|
||||||
|
|
@ -1113,6 +1144,6 @@ namespace spot
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return std::make_shared<dve2_kripke>(d, dict, ps, dead, compress);
|
return std::make_shared<spins_kripke>(d, dict, ps, dead, compress);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -17,8 +17,8 @@
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#ifndef SPOT_IFACE_DVE2_DVE2_HH
|
#ifndef SPOT_IFACE_PROMELA_PROMELA_HH
|
||||||
# define SPOT_IFACE_DVE2_DVE2_HH
|
# define SPOT_IFACE_PROMELA_PROMELA_HH
|
||||||
|
|
||||||
#include "kripke/kripke.hh"
|
#include "kripke/kripke.hh"
|
||||||
#include "ltlvisit/apcollect.hh"
|
#include "ltlvisit/apcollect.hh"
|
||||||
|
|
@ -28,11 +28,11 @@
|
||||||
namespace spot
|
namespace spot
|
||||||
{
|
{
|
||||||
|
|
||||||
// \brief Load a DVE model.
|
// \brief Load a PROMELA model.
|
||||||
//
|
//
|
||||||
// The filename given can be either a *.dve source or a *.dve2C
|
// The filename given can be either a *.prom source or a *.spins
|
||||||
// dynamic library compiled with "divine compile --ltsmin file".
|
// dynamic library compiled with "spins file".
|
||||||
// When the *.dve source is supplied, the *.dve2C will be updated
|
// When the *.prom source is supplied, the *.spins will be updated
|
||||||
// only if it is not newer.
|
// only if it is not newer.
|
||||||
//
|
//
|
||||||
// The dead parameter is used to control the behavior of the model
|
// The dead parameter is used to control the behavior of the model
|
||||||
|
|
@ -48,8 +48,7 @@ namespace spot
|
||||||
//
|
//
|
||||||
// This function returns 0 on error.
|
// This function returns 0 on error.
|
||||||
//
|
//
|
||||||
// \a file the name of the *.dve source file or of the *.dve2C
|
// \a file the name of the *.prom source file or the dynamic library
|
||||||
// dynamic library
|
|
||||||
// \a to_observe the list of atomic propositions that should be observed
|
// \a to_observe the list of atomic propositions that should be observed
|
||||||
// in the model
|
// in the model
|
||||||
// \a dict the BDD dictionary to use
|
// \a dict the BDD dictionary to use
|
||||||
|
|
@ -57,10 +56,10 @@ namespace spot
|
||||||
// dead states
|
// dead states
|
||||||
// \a verbose whether to output verbose messages
|
// \a verbose whether to output verbose messages
|
||||||
SPOT_API kripke_ptr
|
SPOT_API kripke_ptr
|
||||||
load_dve2(const std::string& file, const bdd_dict_ptr& dict,
|
load_model(const std::string& file, const bdd_dict_ptr& dict,
|
||||||
const ltl::atomic_prop_set* to_observe,
|
const ltl::atomic_prop_set* to_observe,
|
||||||
const ltl::formula* dead = ltl::constant::true_instance(),
|
const ltl::formula* dead = ltl::constant::true_instance(),
|
||||||
int compress = 0, bool verbose = true);
|
int compress = 0, bool verbose = true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // SPOT_IFACE_DVE2_DVE2_HH
|
#endif // SPOT_IFACE_PROMELA_PROMELA_HH
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#include "dve2.hh"
|
#include "ltsmin.hh"
|
||||||
#include "tgbaalgos/dotty.hh"
|
#include "tgbaalgos/dotty.hh"
|
||||||
#include "ltlenv/defaultenv.hh"
|
#include "ltlenv/defaultenv.hh"
|
||||||
#include "ltlast/allnodes.hh"
|
#include "ltlast/allnodes.hh"
|
||||||
|
|
@ -217,9 +217,10 @@ checked_main(int argc, char **argv)
|
||||||
|
|
||||||
if (output != DotFormula)
|
if (output != DotFormula)
|
||||||
{
|
{
|
||||||
tm.start("loading dve2");
|
tm.start("loading spins");
|
||||||
model = spot::load_dve2(argv[1], dict, &ap, deadf, compress_states, true);
|
model = spot::load_model(argv[1], dict, &ap, deadf,
|
||||||
tm.stop("loading dve2");
|
compress_states, true);
|
||||||
|
tm.stop("loading spins");
|
||||||
|
|
||||||
if (!model)
|
if (!model)
|
||||||
{
|
{
|
||||||
Loading…
Add table
Add a link
Reference in a new issue