Today we'll talk about how spin works. Several times we've said "DFS!" and glossed over the details. What's really going on? We will discuss this for two primary reasons:
Q: There was a piazza question about the significance of whitespace
A: Whitespace mostly doesn't matter. There are a few cases in which
it does, due to the fact that spin invokes the C preprocessor. The most
notable case is in the expansion of macros, the most notable case of
which is select
.
Q: We've talked about nondeterministic branches, but how does spin actually choose among the branches?
A: During a simulation spin chooses randomly; however, during verification the search we'll talk about today is responsible for such choices.
Q: What does the "fair scheduling" option actually do?
A: There is a flag, -f
, which may be passed to pan
to enable "fair
scheduling". There is a technical definition of what this means. Roughly
speaking it is that, any process that is enabled infinitely often is
allowed to progress infinitely often. Essentially, this means that the
scheduler will not arbitrarily keep a process which is not otherwise
blocked paused forever. When the flag is passed, the graph search we'll
talk about today rules out "unfair" paths.
Q: How are do
and if
related and how do they differ?
A: do
and if
behave identically except that do
loops and if
does not.
Spin represents each state as a value of the state vector. The state vector is a representation of the complete state of the model, including:
For verification purposes, spin represents the model as a finite state automaton, but we're sort of going to ignore the accepting states.
This is a directed graph where the nodes are global system states and each edge represents some process taking a step forward. The edges are defined by the transition function.
Spin takes each line as a seperate state - here we're lumping things together a little bit for simplicity. We wrote a completely deterministic model, so there is one edge out of each state.
This is the complete set of reachable states in our model, but there are other states which may be represented but are ruled out by the model, for instance states like both lights being green.
Our state vector is ~5 bytes long. That's 40 bits, so we can represent 2^40 states, which is a lot! How does spin deal with so many states? The key is that most of them aren't reachable - here we have 2^40 states, but only six are reachable.
When checking safety properties (where a counterexample consists of a path to a state in which the property doesn't hold), search depth-first over the graph. This is what spin does, and it's called "finite-state model checking."
There's an entirely different approach in which this representation is digested into a SAT problem and passed to a SAT solver, which is called "symbolic model checking."
We've just seen how to find assertion violations, but we've actually also seen how to find deadlocks. A deadlock is any state with no outbound edges (think back to the state machines question on the Alloy3 assignment).
Q: Why DFS and not BFS?
A: There's a commandline switch to use BFS, DFS is the default because it typically performs well because system models tend to have high fanout. BFS is nice because it will produce the shortest trace to a bad state.
Q: So use DFS to find the problem and then BFS to find a nice trace?
A: Yes, but spin has a trace minimization option, use that
Q: How does DFS work on infinite processes?
A: The search detects the cycle in the FSA representation (by remembering visited states) and backtracks
We have only talked so far about saftey properties. What about liveness? There aren't single "bad state" counterexamples for liveness properties - counterexamples are infinite.
Spin produces a "monitor process"
We take the following as fact, but the underlying reasons are very interesting! "every LTL formula can be turned into an automoton which represents this monitor process"
But we're interested in infinite inputs to our automoton, which doesn't work with the typical definitions for finite state automata. These automata that can deal with infinite words are called Buchi automata. We say that a Buchi automaton accepts an infinite word iff while processing that word it passes through an accepting state infinitely many times.
Example: the LTL statement always x=0
can be transformed into a Buchi
automaton like the following one:
Here's a slightly more complicated example:
always eventually x=0
So spin builds this automoton, combines it with the model, and searches