scalarset BIT 0..7;
scalarset INDEX 0..31;
typedef BYTE array BIT of boolean;
module main(){
/* the abstract model */
bytes : array INDEX of BYTE;
next(bytes) := bytes;
/* the input and output signals */
inp, out : struct{
valid : boolean;
idx : INDEX;
data : BYTE;
}
/* the refinement maps */
layer spec: {
if(inp.valid) inp.data := bytes[inp.idx];
if(out.valid) out.data := bytes[out.idx];
}
And let's use our original very trivial implementation:
init(out.valid) := 0; next(out) := inp; }That is, the output is just the input delayed by one time unit.
Note that our specification (layer spec) says that at all times the output value must be equal to the element of array bytes indicated by the index value out.idx. We would like to break this specification into cases and consider only one index value at a time. To do this, we add the following declaration:
forall (i in INDEX)
subcase spec_case[i] of out.data//spec for out.idx = i;
In this case, the property we are splitting into cases is out.data//spec, the assignment to out.data in layer spec. The resulting cases are out.data//spec_case[i]. Note, however, that in the subcase declaration, we only give a layer name for the new cases, since the signal name is redundant. This declaration is exactly as if we had written
forall (i in INDEX)
layer spec_case[i]:
if (out.idx = i)
out.data := bytes[out.idx];
except that SMV recognizes that if we prove out.data//spec_case[i]
for all i, we don't have to prove out.data//spec.
Run this example, and
look in the properties pane. You'll see that out.data//spec does
not appear, but instead we have out.data//spec_case[0]. Note
that only the case i = 0 appears, since INDEX is a scalarset
type, and SMV knows that all the other cases are symmetric to this
one. Now look in the cone pane. You'll notice that all of the elements
of the array bytes are in the cone. This is because the
definition of inp.data in layer spec references all of
them. However, all of them except element 0 are in the undefined
layer. This is a heuristic used by SMV: if a property references some
specific value or values of a given scalarset type, then only the
corresponding elements of arrays over that type are used. The rest are
given the undefined value. You might try clicking on element bytes[1] and choosing Abstraction|Explain Layer to get an
explanation of why this signal was left undefined. You can, of course,
override this heuristic by explicitly specifying a layer for the other
elements. In this case, however, the heuristic works, since property
out.data//spec_case[0] verifies correctly.