|
| |||||
13.5 Using the tool |
The RSL-SAL translator works on different operative systems. In particular, it is possible to use Linux and Windows platforms.
For using the tool on Windows platform it is necessary to:
(ftp://ftp.iist.unu.edu/pub/RAISE/rsltc/windows/)
(http://www.cygwin.com)
In "Cygwin Setup" select "Interpreters Packages" and install "m4".
For using the tool on Linux platform it is necessary to:
(ftp://ftp.iist.unu.edu/pub/RAISE/rsltc/linux/)
Install the Unix macro processor"m4" (from the Linux distribution)
The translator's activation is through the Emacs editor, so for using the RSL-SAL translator
When the "Translate to SAL" option is executed, the tool generate some files (they are in the same folder where .rsl file is). Some of these files are:
IT_AN : CONTEXT = BEGIN Int_: TYPE = [SAL_GLOBAL!DefaultIntLow .. SAL_GLOBAL!DefaultIntHigh]; END
L_BUILTIN : CONTEXT = BEGIN Not_a_value_type: TYPE = DATATYPE ... END; Bool__cc: TYPE = DATATYPE Bool__cc(Bool__val: BT_AN!Bool_), Bool__nav(Bool__nav_val: Not_a_value_type) END; Int__cc: TYPE = DATATYPE Int__cc(Int__val: IT_AN!Int_), Int__nav(Int__nav_val: Not_a_value_type) END; END
L_BUILTIN_simple : CONTEXT = BEGIN Not_a_value_type: TYPE = DATATYPE nav END; Bool__cc: TYPE = DATATYPE Bool__cc(Bool__val: BT_AN!Bool_), Bool__nav(Bool__nav_val: Not_a_value_type) END; Int__cc: TYPE = DATATYPE Int__cc(Int__val: IT_AN!Int_), Int__nav(Int__nav_val: Not_a_value_type) END; END
NT_AN : CONTEXT = BEGIN Nat_: TYPE = [0 .. SAL_GLOBAL!DefaultNatHigh]; END
BT_AN : CONTEXT = BEGIN Bool_: TYPE = BOOLEAN; END
- <NameType>_<Type>_OPS.sal
- <NameType>_<Type>_cc_OPS.sal
- <NameType>_<Type>_cc_OPS_simple.sal
where <NameType> is the name in the declaration and <Type> is Map or Set. In these files there are functions such as "emptySet"function and "add" function (of Set type) used to translate RSL expressions to SAL (see section 13.2.5).
Once the "Translate to SAL" option has been executed, it is possible to check if the specification resulting from the translation is well formed. This one is activated in the Emacs editor, selecting the "RSL" option and the "Run SAL well-formed checker" option. This step also generates some .sal files from some .m4 files and so is essential.
After executing the "Run SAL well-formed checker" option, other utilities provided for the tool are enabled. Also they are activated using the Emacs editor. In this case, it is necessary to select the "RSL" option and some one of the following,
Run SAL deadlock checker Base CC Simple CC Run SAL model checker Base CC Simple CC
In the next subsection an example is used to show how the tool works in more detail.
The following code is in a file named "TOKENS.rsl",
scheme TOKENS = | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
class | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
type | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Token == a | b | c | d | e | f, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
State :: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
S1 : Token-set ↔ re_S1 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
S2 : Token-set ↔ re_S2 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
value | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
init : State = | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
mk_State({a, b, c}, {d, e, f}), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
give21 : Token × State → State | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
give21(t, s) ≡ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
re_S1({t} ∪ S1(s), re_S2(S2(s) \ {t}, s)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
give12 : Token × State → State | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
give12(t, s) ≡ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
re_S2({t} ∪ S2(s), re_S1(S1(s) \ {t}, s)), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
transition_system | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[sys] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
local state : State := init | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
in | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
([] tok : Token • | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[give21] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tok ∈ S2(state) ⇒ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
state′ = give21(tok, state)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
([] tok : Token • | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[give12] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
tok ∈ S1(state) ⇒ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
state′ = give12(tok, state)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
ltl_assertion | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[consistent] sys G(S1(state) ∩ S2(state) = {}), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[no_loss] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
sys | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
G(S1(state) ∪ S2(state) = {a, b, c, d, e, f}), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[empty_S1_reachable] sys G(S1(state) ≠ {}), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[empty_S2_reachable] sys G(S2(state) ≠ {}) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
end |
If the "TOKENS.rsl" file is opened using the Emacs editor and the "Translate to SAL" option is executed, the tool will generate these files,
Bool__cc_OPS.m4 Bool__cc_OPS_simple.m4 BT_AN.sal Int__cc_OPS.m4 Int__cc_OPS_simple.m4 Int__OPS.m4 IT_AN.sal L_BUILTIN.sal L_BUILTIN_simple.sal NT_AN.sal SAL_GLOBAL.sal SAL_TYPES.sal SAL_TYPES_cc.sal SAL_TYPES_cc_simple.sal State_cc_OPS.m4 State_cc_OPS_simple.m4 Token_cc_OPS.m4 Token_cc_OPS_simple.m4 Token_set_cc_OPS.m4 Token_set_cc_OPS_simple.m4 Token_set_OPS.m4 TOKENS.sal TOKENS_cc.sal TOKENS_cc_simple.sal
Now, it is possible to check if "TOKENS.sal", "TOKENS_cc.sal" and "TOKENS_cc_simple.sal" are well formed. For that, the tool first copies prelude files, and later it generates .sal files from .m4 files.
The well formed checking is enabled selecting the "Run SAL
well-formed checker" option. So, the compilation buffer shows,
sal_wfc_check TOKENS sal-wfc TOKENS Ok. sal-wfc TOKENS_cc Ok. sal-wfc TOKENS_cc_simple Ok. Compilation finished at ...
And the following files are generated:
Bool__cc_OPS.sal Bool__cc_OPS_simple.sal Bool_cc_prelude cc_type_prelude Int__cc_OPS.sal Int__cc_OPS_simple.sal Int__OPS.sal int_cc_prelude int_prelude map_cc_prelude map_prelude set_cc_prelude set_prelude State_cc_OPS.sal State_cc_OPS_simple.sal Token_cc_OPS.sal Token_cc_OPS_simple.sal Token_set_cc_OPS.sal Token_set_cc_OPS_simple.sal Token_set_OPS.sal
SAL model checking is only valid if there are no deadlock states. The tool allows one to check for no deadlock states, selecting the "Run SAL deadlock checker" option. Next, it is necessary to choose between "base", "CC", or "simple_CC" options. In all these cases, the Emacs minibuffer shows,
Transition system identifier:
Then it is necessary to specify a transition system identifier (in the TOKEN example its name is "sys"),
Transition system identifier: sys
So, if previously the "base" option was selected, the compilation buffer will show,
sal-deadlock-checker TOKENS sys
ok (module does NOT contain deadlock states).
The tool allows one to run the SAL model checker, selecting the "Run SAL model checker" option. Next, it is necessary to choose between "base", "CC", or "simple_CC" options. In all these cases, the Emacs minibuffer shows,
Assertion identifier (default all assertions):
If an assertion identifier is specified (for example, "consistent"),
and previously the "base" option was selected, the compilation buffer will show,
sal-smc TOKENS consistent
proved.
But if no particular assertion identifier is specified, by default all assertions are checked. In this case, the result is
sal-smc TOKEN2 Counterexample for 'empty_S1_reachable' located at [Context: TOKEN2, line(49), column(0)]: ======================== Path ======================== Step 0: --- System Variables (assignments) --- state = mk_State((LAMBDA (arg!9 : Token): (arg!9 /= f) and (arg!9 /= e) and (arg!9 /= d)), (LAMBDA (arg!10 : Token): (arg!10 = f) or (arg!10 = e) or (arg!10 = d))) ------------------------ Transition Information: (module instance at [Context: TOKEN2, line(47), column(21)] (with tok = a at [Context: TOKEN2, line(40), column(0)] (label give12 transition at [Context: TOKEN2, line(42), column(4)]))) ------------------------ Step 1: --- System Variables (assignments) --- state = mk_State((LAMBDA (arg!11 : Token): (arg!11 /= f) and (arg!11 /= e) and (arg!11 /= d) and ((arg!11 = c) or (arg!11 = b))), (LAMBDA (arg!12 : Token): (arg!12 = f) or (arg!12 = e) or (arg!12 = d) or (arg!12 /= c) and (arg!12 /= b))) ------------------------ Transition Information: (module instance at [Context: TOKEN2, line(47), column(21)] (with tok = c at [Context: TOKEN2, line(40), column(0)] (label give12 transition at [Context: TOKEN2, line(42), column(4)]))) ------------------------ Step 2: --- System Variables (assignments) --- state = mk_State((LAMBDA (arg!13 : Token): (arg!13 /= f) and (arg!13 /= e) and (arg!13 /= d) and (arg!13 /= c) and (arg!13 = b)), (LAMBDA (arg!14 : Token): (arg!14 = f) or (arg!14 = e) or (arg!14 = d) or (arg!14 = c) or (arg!14 /= b))) ------------------------ Transition Information: (module instance at [Context: TOKEN2, line(47), column(21)] (with tok = b at [Context: TOKEN2, line(40), column(0)] (label give12 transition at [Context: TOKEN2, line(42), column(4)]))) ------------------------ Step 3: --- System Variables (assignments) --- state = mk_State((LAMBDA (arg!15 : Token): false), (LAMBDA (arg!16 : Token): true)) Counterexample for 'empty_S2_reachable' located at [Context: TOKEN2, line(50), column(0)]: ======================== Path ======================== Step 0: --- System Variables (assignments) --- state = mk_State((LAMBDA (arg!17 : Token): (arg!17 /= f) and (arg!17 /= e) and (arg!17 /= d)), (LAMBDA (arg!18 : Token): (arg!18 = f) or (arg!18 = e) or (arg!18 = d))) ------------------------ Transition Information: (module instance at [Context: TOKEN2, line(47), column(21)] (with tok = d at [Context: TOKEN2, line(34), column(0)] (label give21 transition at [Context: TOKEN2, line(36), column(4)]))) ------------------------ Step 1: --- System Variables (assignments) --- state = mk_State((LAMBDA (arg!19 : Token): (arg!19 /= f) and (arg!19 /= e)), (LAMBDA (arg!20 : Token): (arg!20 = f) or (arg!20 = e))) ------------------------ Transition Information: (module instance at [Context: TOKEN2, line(47), column(21)] (with tok = f at [Context: TOKEN2, line(34), column(0)] (label give21 transition at [Context: TOKEN2, line(36), column(4)]))) ------------------------ Step 2: --- System Variables (assignments) --- state = mk_State((LAMBDA (arg!21 : Token): (arg!21 = f) or (arg!21 /= e)), (LAMBDA (arg!22 : Token): (arg!22 /= f) and (arg!22 = e))) ------------------------ Transition Information: (module instance at [Context: TOKEN2, line(47), column(21)] (with tok = e at [Context: TOKEN2, line(34), column(0)] (label give21 transition at [Context: TOKEN2, line(36), column(4)]))) ------------------------ Step 3: --- System Variables (assignments) --- state = mk_State((LAMBDA (arg!23 : Token): true), (LAMBDA (arg!24 : Token): false)) Summary: The assertion 'consistent' located at [Context: TOKEN2, line(47), column(0)] is valid. The assertion 'no_loss' located at [Context: TOKEN2, line(48), column(0)] is valid. The assertion 'empty_S1_reachable' located at [Context: TOKEN2, line(49), column(0)] is invalid. The assertion 'empty_S2_reachable' located at [Context: TOKEN2, line(50), column(0)] is invalid. Compilation finished ...
SAL is only sound when there are no deadlocks. So you have to check for deadlocks in the CC version as well as the basic one.
To illustrate this, and show how to get information from the CC version, we use the lift example from section 13.3.4. Suppose we change, in the BUTTONS module, the definition of "required_beyond" to
-- wrong version | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
required_beyond : T.Direction × T.Floor × Buttons → Bool | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
required_beyond(d, f, bs) ≡ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let f′ = T.next_floor(d, f) in | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
required_here(d, f′, bs) \/ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
T.is_next_floor(d, f′) /\ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
let f′′ = T.next_floor(d, f′) in | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
required_here(d, f′′, bs) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
end | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
end /\ T.is_next_floor(d, f) |
Note that we gave moved the conjunct T.is_next_floor(d, f) from the beginning to the end. This looks logically equivalent to the original, because /\ is normally commutative. But we have to remember RSL's left-to-right evaluation rule, and also recall that T.is_next_floor(d, f) is a precondition of T.next_floor(d, f). In the original version, if T.is_next_floor(d, f) is false, then T.next_floor(d, f) is not evaluated. In the new version, this is not so and we can get a precondition violation.
If we make this change to required_beyond, recompile to SAL, check well-formedness, and model check the CC version it reports all is well. But if we remember to also run the deadlock checker on the CC version it reports a deadlock:
Total number of deadlock states: 1.0 Deadlock states: State 1 --- System Variables (assignments) --- lift = Lift_cc(mk_Lift_(mk_Cage_(up, halted, 0), mk_Doors_(open, shut, shut), mk_Buttons_(lit, lit, lit, lit, lit, lit, lit)))
This tells us that the "no errors" report from the CC model check cannot be trusted, but otherwise is not very helpful, because no Nav value is reported. We might notice that the buttons have all become lit, which means that the press transition is not enabled. The other transition must also not be enabled (since we have a deadlock), which means that can_next(lift) must not be true. In fact can_next contains a Nav. We can investigate what is happening by adding a variable to the system so that we can see the value of can_next:
cn′ = can_next(lift′) |
Now we get the result that the check on the variables is invalid: cn contains a Nav:
Step 1: --- System Variables (assignments) --- lift = Lift_cc(mk_Lift_(mk_Cage_(up, halted, 0), mk_Doors_(open, shut, shut), mk_Buttons_(clear, lit, clear, clear, clear, clear, clear))) cn = Bool__nav(Precondition_of_function_T_next_floor_not_satisfied) Summary: The assertion 'LIFT_max_floor_cc_check' located at [Context: LIFT_cc, line(180), column(0)] is valid. The assertion 'LIFT_min_floor_cc_check' located at [Context: LIFT_cc, line(181), column(0)] is valid. The assertion 'LIFT_L_cc_check' located at [Context: LIFT_cc, line(209), column(0)] is invalid.
and we see that T.next_floor is the function whose precondition is violated. We can proceed in the same way if necessary, adding more variables to show how the values of particular expressions change in this run, until we find the error.
13.5 Using the tool | ||||||
|
|