• Aucun résultat trouvé

7.3 Semantic Preserving Transformations

The transformations presented in this section preserve the semantics of theHPIOMsystem considered. This means the set of possible executions will be the same for the transformed system and the original one. An immediate consequence is that all properties are preserved.

7.3.1 Abstract Addresses Expansion

7.3.1.1 Abstract Addresses inLUSSY

In section5.3.2, we presented an encoding for an abstraction of the address space inHPIOM. This abstrac-tion uses a dedicated construct inHPIOMin the translation from SystemC toHPIOM, that we will transform into a pure Boolean encoding.

7.3.1.2 Expanding Abstract Address Into Arrays of Booleans

AnHPIOMvariable or signal of type abstract address will be replaced by an array of Boolean, of size the number of intervals in the address range. This transformation is implemented using a transformation visitor (see section5.5.2.2.2).

Abstract address literals are encoded straightforwardly: theithBoolean value is given directly by the value for theith interval in the abstract address literal. Abstract address manipulators are a bit harder to implement, but the algorithms for the constructs we have implemented are derived straightforwardly from their specifications (sections5.3.2.3and5.3.2.4).

7.3.1.3 Alternative Approach

This transformation could have been done on-the-fly: instead of returning a dedicatedHPIOM construct, the abstract address operators could have returned the encoding directly in terms of Boolean encoding.

Our approach is more flexible since we can do other treatment on the abstract addresses before expanding them into Boolean. It is on the other hand more intrusive inHPIOM: if we considerHPIOMas a generic intermediate format for several tools, it would not be acceptable for each tool to add its own “home made”

constructs like we did for abstract addresses.

7.3.2 Non-Deterministic Choices Expansion

When, in anHPIOM automaton, a control point has several outgoing edges, and if the conditions on the edges can not be guaranteed to be mutually exclusive, the ambiguity has to be removed with a non-deterministic choice. TheHPIOMAPI automatically adds it for each control point when necessary, unless specified otherwise (withset choice safe()).

A non-deterministic choice is anHPIOM condition. A non-deterministic link is attached to a control point, and can link several non-deterministic choices together. The semantics says that one and only one of the choices can be true at a time.

BIRTHcan transform this construct into a Boolean encoding: For a choice betweennpossibilities, it will use⌈log2(n)⌉Boolean unknown values. This transformation is not mandatory since theSMVback-end can do a better encoding usingSMVenumerated types.

7.3.3 Reducing the Number of Variables and Inputs

The number of variables in the system to verify is known to be important in particular for symbolic model-checking. It has a direct influence on the size of the BDDs manipulated. The same applies for the number of inputs.

Matthieu Moy Ph.D Thesis 115/190

Chapter 7. BIRTH: Back-end Independent Reduction and Transformations ofHPIOM

7.3.3.1 Live Variables Analysis

Minimizing the number of variables of a program is a very general problem. Any decent compiler will try to minimize the memory footprint of the generated executable, and will therefore try to reuse the unused memory as much as possible. To minimize the amount of memory necessary to store the local variables of a function, the usual approach is to perform a live variable analysis to know where each variable may be useful, and in a second pass, decide which register and which memory byte will be allocated for each variable at which point in the code. The general algorithm is presented for example in [BFG99,ASU86].

We use a slightly modified version of the traditional algorithm. The computation of live variables didn’t change much, but had to be adapted to our model with assignments and guards on automata edges (as opposed to instructions on nodes of a control-flow graph). The optimization resulting from this analysis is a bit different from what we see in compilers, since we have no notion of register.

7.3.3.1.1 Live Variable Computation.

Definitions. Intuitively, for a given edge, alive variableis a variable that holds a value that may be used in the future. This means that the variable may have been assigned a value, and that this value may be used before the next access to this variable.

The definition of live variables is based on some other definitions. First of all, we define the set of incoming edges to an edge as the set of incoming edges to the source control point. Similarly, the set of outgoing edges from an edge is the set of outgoing edges from the target control point.

Each of the following definitions apply for each edge of the automaton:

Defined Variables are variables that appear in the left-hand side of an assignment on an incoming edge to the current edge. We notedef(t)the set of defined variables for edget.

Used Variables are variables that appear either in the right-hand side of an assignment, in the guard, or in a valued signal emission in an outgoing edge from the current edge. We noteuse(t)the set of used variables for edget.

Live-In Variables are variables live on an incoming edge to the current edge. We note in(t)the set of live-in variables for edget.

Live-Out Variables are variables live on an outgoing edge from the current edge. We noteout(t)the set of live-out variables for the edget.

Live Variables in a control point are then variables live-out in an incoming edge of the current control point.

The definition of a live variable is based on the propagation of the notions of used and defined variables along the edges. Intuitively, defined variables will propagate forward, and used variables will propagate backward, stopping when encountering an assignment. Live variables are the ones in the intersection of the result of the propagation for used and defined.

Formally, we definein(t)andout(t)the smallest fixed point of:

in(t) = use(t)∪(out(t)−def(t))

out(t) = [

tsucc(t) in(t)

Iterative Algorithm. The unoptimized algorithm is rather straightforward from the definition. The following sequence can be proved to be increasing, and therefore converging to their fixed point defined above.

116/190 Verimag/STMicroelectronics — 9 d´ecembre 2005 Matthieu Moy

7.3. Semantic Preserving Transformations

This algorithm can be optimized in many ways. An obvious optimization is to group the edges between two branching control points, and consider basic blocks instead ofHPIOMcontrol points and edges. On a typical automaton obtained from imperative code, this considerably reduces the size of the automaton to consider. Another common optimization is to order the control points to minimize the number of iterations.

Starting from the final control point and iterating backwards is usually considered as a good heuristic.

Also, using optimized data-structures like bit vectors to represent control points would clearly speed up the process (we currently use the STL’s set operators).

7.3.3.1.2 Optimization of the Number of Variables. Our problem is a slight variant from the usual problem compilers solve with live variable analysis. The usual problem is: given a number of registers, find the way to allocate registers to variables that will minimize the number of variables not allocated to a register, or better, minimize the number of access to variables that are not allocated to registers.

We can represent the problem by a graph in which each variable is represented by a node, and then, add one edge between two nodes whenever both of the corresponding variables are live in the same control point. This is called theconflicts graph. Then, the problem is reduced to the one of graph coloring, which is a well-known and NP-complete problem. [Cha82] describes some techniques to optimize the register allocation based on graph coloring algorithms. [Mue93] is a review of the existing algorithms.

Our problem is a bit different: we do not have to do the distinction between registers and memory. The problem is only to minimize the number of variables.

We use a simple greedy algorithm, that seem to be a good heuristic in practice. The goal is to compute a set of replacement variablesVrep and a mapR : V → Vrep(note: the size of Vrep is not known yet, but we can consider an infinite ordered setVrep : we will allocate its first variables in priority. Then, at the end of computation, Vrep will be the set of assigned variables inVrep . Concretely, this means that Vrep is allocated on demand during the execution of the algorithm). We will use two temporary maps A : Vrep ×S → {assigned,unassigned} andU : S → 2V. A represents the role of the variables in each control point, which are initially assigned to unassigned in each control point.U is the set of original variables that have not yet been assigned. The algorithm is then as follows:

fors∈Sloop forv∈U(s)loop

vrep:=smallest variable for which

∀s∈set of control points wherevis live,A(vrep, s) =unassigned forsaset of control points wherevis liveloop

A(vrep, sa) :=assigned U(s) :=U(s)−v R(v) :=vrep

end loop end loop end loop

Matthieu Moy Ph.D Thesis 117/190

Chapter 7. BIRTH: Back-end Independent Reduction and Transformations ofHPIOM

Remark:

We perform this optimization type-by-type, which means that a variable used to store an array of Boolean, for example, may not be used to store some scalar Boolean variable in other points of the program. To take full advantage of this optimization, we should encode as many types of variables as possible into individual Boolean variables, before performing the live variables analysis.

7.3.3.1.3 Other Optimizations Made Possible by Live Variable Analysis. Live variable analysis also allows some other optimizations. The first one is based on the fact that the initial value for a variable is never used if this variable is not active in the initial control point. We can therefore replace non-deterministic initial values by arbitrary values in this case. This reduces the number of initial global states for the prover, and also reduces the number of inputs in the case of the LUSTREback-end.

The second optimization is to remove assignments for variables not live-out on the edge on which the assignment is performed. This simplifies the transition relation of the automaton.

Another potential optimization, which hasn’t been implemented, would be to reset the variables (assign them a constant value chosen once and for all) when they leave their live scope. This way, the proof wouldn’t have to carry different values for the variables when they go out of scope. In Figure7.1, ifxisn’t used in the rest of the automaton, then it goes out of its live scope after being tested. Without the proposed optimization, the value ofxwould not be the same at the end of the upper branch and the end of the lower branch of the automaton. The resulting BDD would therefore include a condition ofx. Our optimization would consist in adding the assignmentx:=trueto the edges wherexis tested and therefore goes out of scope. The value ofxin the joining control point would then always betrue.

x := true

[ x == true ]

x := false

[ x == false ]

...

x := true

Figure 7.1: Illustration of the Reset Optimization

7.3.3.1.4 Practical Results. On the HPIOM generated for the EASY platform, the total number of boolean variables (we don’t consider non-boolean variables since they will be abstracted before the proof in our case) is decreased from 1,105 to 793. In other words, the number of variables is decreased by 28%.

The number of unknown values is also reduced from 293 to 206 (because we eliminated unused initial val-ues). On the example platform, the number decreased from 51 to 43 (the gain is 17% in this case), which changes the time taken for the proofs:

SMVtime: 0.47s (used to be 0.48s)

SMVBDD nodes allocated: 70,564 (used to be 71,595)

• LESARtime: 1.242s (used to be 5.039s)

We can guess from the results thatSMValready did the same kind of optimization (but not exactly the same, since the number of BDD node slightly decreased). On the other hand, the speedup using LESARis impressive.

118/190 Verimag/STMicroelectronics — 9 d´ecembre 2005 Matthieu Moy

7.3. Semantic Preserving Transformations

7.3.3.2.1 The Algorithm. We implemented another trivial but interesting optimization, to minimize the number of inputs the system needs to modelHPIOMunknown values. The idea is that unknown values will typically be used once only in the automaton, but will, in the unoptimized version, require one input per unknown value. If two unknown values are not used at the same time, then we can use the same unknown value for both.

The problem is similar to the minimization of the number of variables described above, but there is one important difference: since unknown values do not keep a value from one instant to the other, we can compute the replacement control point per control point, which allows us to compute the optimal solution (not a heuristic) easily: we keep a list of unknown values used as replacement, globally for the automaton (initially empty, and filled-in on demand). For each control point, we compute the list of unknown values used on each outgoing edge and assign them replacements.

7.3.3.2.2 Practical Results. On the EASY platform, this optimization allowed us to reduce the number of boolean unknown from 293 to 211 (28% gain). On the example platform, the number is decreased only from 13 to 12, and we get the following performance results:

SMVtime: 0.48s (used to be 0.48s)

SMVBDD nodes allocated: 71,577 (used to be 71,595)

• LESARtime: 4.8s (used to be 5.039s)

Once again, LESARbenefited of the optimization noticeably, but the results withSMVdid not change much. We can guess thatSMValready has a well optimized management of non-deterministic values.

7.3.4 Reduce the Number of States by Parallelizing Transitions

7.3.4.1 The Algorithm

The main problem with model-checking is the state explosion. Any optimization able to reduce the state-space is therefore appreciable.

We implemented a transformation able to reduce the number of control points and edges in anHPIOM

automaton, by parallelizing independent transitions that would have been executed in sequence. Note that this transformation does not preserve the semantic of anHPIOMautomaton in the general case: since

HPIOMhas a synchronous semantics, doing in one step something that should have been done in two does matter. For processes automata, however, the number of transitions doesn’t matter because of the non preemptiveness of the scheduler. Reducing the number of transitions is a kind of automatic parallelization.

When a control point has only one outgoing edge, targeting a control point with only one incoming edge, if the edge emits no signal, then we can merge the control point and its successor. Figure7.2illustrates this transformation.

Matthieu Moy Ph.D Thesis 119/190

Chapter 7. BIRTH: Back-end Independent Reduction and Transformations ofHPIOM

The algorithm is as follows: letT be the edge considered,S its source control point, andD its des-tination control point. Actions ofT are “propagated” onto each outgoing edgeOTi ofD: we copy each assignment ofT onOTi, and the left value is substituted in all existing expressions inOTi. SandDare

“merged” (incoming edges toSare redirected toDandSis deleted).

7.3.4.2 Practical Results

On the EASY platform, applying this algorithm reduces the number of edges from 1,789 to 1,747 (a gain of 42, i.e. 2.3%), and the number of control points from 1,074 to 1,032 (3.9% gained). On the example, the optimization were not applicable on any edge (the source code doesn’t contain sequential, independent actions).

Those results are a bit disappointing. It would be interesting to refine the condition of application of the transformation and see if we can get better results.

7.4 An Approximation Conservative for Safety Properties: