• No results found

Causality Analysis with Higher Data Types

4.6 Symbolic SOS Reaction Rules

4.6.1 Causality Analysis with Higher Data Types

In Figure4.11on Page134, we have shown how the transition for the data flow of a local/output variable x is determined. However, this transition rela- tion is given at the granularity of macro steps, and does therefore not respect the SOS reaction rules that determine the constructive reaction of a program. To analyze the constructiveness of a program, we have to formulate the data flow at the finer level of micro steps. To this end, we have to model the progress of information since the values of the local/output variables are determined step by step in terms of micro steps. To this end, we formally have to add an explicit unknown value ⊥ to every data type, so that we can express that the value of a variable is not yet known at a particular micro step. These ‘ternary’ environments have already been used in Section4.1to describe the constructive operational semantics of Quartz by means of the SOS reaction rules.

Hence, we have to deal with ternary environments. However, we wish to derive a boolean transition relation for the micro step behavior of a Quartz program that can be analyzed by state of the art verification techniques. For this reason, we embed the unknown value ⊥ explicity as follows: For every

local, reincarnated local, and output variable x, we add a boolean-typed vari- able x⊥that holds iff the value of x is known. Hence, the pair (x⊥, x) encodes the actual value of the variable x: if xholds, then the value of x is known and is contained in x, otherwise the value of x is not yet known and we have to ignore the content of x.

Using the variables x⊥, we can explicitly model the progress of the in-

formation flow that is obtained by evaluating the program expression step by step until either assignments can be executed that determine the current value of a variable or until it becomes clear that no assignment will modify the current value of a variable so that the reaction to absence will determine it.

This progress of the information flow also makes use of lazy evaluation as explained in Figure4.1that has to be encoded in the transition relation at the micro step level. To this end, we formally define a function that maps a pro- gram expression σ of arbitrary type to a boolean formula k(σ) such that k(σ) holds iff the expression σ can be evaluated to a known value. Formally, the formula k(σ) follows the rules of Figure4.1and is defined as shown below:

Definition 4.17 (Known Status of Expressions). For every expression σ, we

define a formula k(σ) recursively as follows:

for variables and constants, we define

k(x) := true : if x is an input or location variable

x⊥ : if x is a local, reincarnated, or output variable

k(c) := c

for tuple constructor and selector, we define k((τn−1, . . . , τ0)) := k(τn−1) ∧ . . . ∧ k(τ0) k(τ.π) := k(τ ) ∧ k(π)

for array access, we define k(x[τ ]) := k(x) ∧ k(π) • for bitvector operators, we define:

k(ϕ @ ψ) := k(ϕ) ∧ k(ψ) k(ϕ{π1}) := k(ϕ) ∧ k(π1) k(ϕ{π1: π2}) := k(ϕ) ∧ k(π1) ∧ k(π2) k(ϕ{π1:}) := k(ϕ) ∧ k(π1) k(ϕ{: π2}) := k(ϕ) ∧ k(π2) k(fromArray(x)) := k(x) k(reverse(ϕ)) := k(ϕ) k({τ :: n}) := k(τ ) k(sizeOf(ϕ)) := true

for (bitwise) boolean operators, we define:

k(!ϕ) := k(ϕ)

k(ϕ & ψ) := k(ϕ) ∧ k(ψ) ∨ k(ϕ) ∧ ϕ = {true::sizeOf(ϕ)} ∨ k(ψ) ∧ ψ = {true::sizeOf(ψ)}

k(ϕ | ψ) := k(ϕ)∧k(ψ)∨k(ϕ)∧ϕ = {false::sizeOf(ϕ)}∨k(ψ)∧ψ =

k(ϕ -> ψ) := k(!ϕ | ψ)

k(ϕ <-> ψ) := k(!ϕ | ψ) ∧ k(!ψ | ϕ)

k(ϕ xor ψ) := k(!(ϕ <-> ψ)) • for explicit type converters, we define

k(int2bv(τ )) := k(τ )

k(nat2bv(τ )) := k(τ )

k(bv2int(τ )) := k(τ )

k(bv2nat(τ )) := k(τ )

for arithmetic operators, we define: k(−τ ) := k(τ ) k(abs(τ )) := k(τ ) k(τ + π) := k(τ ) ∧ k(π) k(τ - π) := k(τ ) ∧ k(π) k(τ * π) := k(τ ) ∧ k(π) ∨ k(τ ) ∧ τ = 0 ∨ k(π) ∧ π = 0 k(τ / π) := k(τ ) ∧ k(π) k(τ % π) := k(τ ) ∧ k(π) k(exp2(τ )) := k(τ ) k(log2(τ )) := k(τ ) for k(sat<n>(τ )) := k(τ )

for arithmetic relations, we define

k(τ <= π) := k(τ ) ∧ (τ = 0 ∨ k(π) ∧ τ ≤ π) : if τ and π are of some type nat<n>

k(τ ) ∧ k(π) : otherwise

k(τ < π) := k(!(π <= τ )

k(τ > π) := k(π < τ )

k(τ >= π) := k(π <= τ )

for equality and inequality operators, we define k(τ == π) := k(τ ) ∧ k(π) k(τ != π) := k(τ ) ∧ k(π) • finally, k((ϕ?τ : π)) :=   k(ϕ) ∧ ϕ ∧ τ ∨ k(ϕ) ∧ ¬ϕ ∧ π∨ k(τ ) ∧ k(π) ∧ τ = π   k(sizeOf(τ )) := k(τ )

Clearly, in the behavior of the program, we can only make use of an expres- sion if we know its value. For this reason, the entire execution of the actions is controlled by the data flow. In Chapter 6, we therefore consider the inter- pretation of Quartz programs in terms of data flow machines that completely correspond to the data flow computers that have been built in the eighties.

As the reaction of a program is determined in micro steps that are executed in several steps of a macro step, we have to explicitly distinguish between micro and macro steps of the execution. This distinction has also been made in the SOS transition rules, while the SOS reaction rules only refer to the current macro step. For this reason, we introduce a clock signal clock, that is

true whenever all variables have become known values2. If this happens, the

delayed assignments are executed, the location variables change their values according to the control flow, and the input variables are allowed to change their values in a nondeterministic way.

Macro steps are therefore defined in terms of occurrences of the clocksignal, and between two clock ticks, the micro steps of a macro step are executed: As long as clockis false, the immediate assignments to the variables are executed if the values of the guards and right hand side expressions are known, and the guard is true.

We therefore distinguish between the information flow and the data flow. The information flow of a variable x is determined by the corresponding vari- able k(x) = x⊥ that holds if and only if the value of x is already determined

in the current macro step.

The transition relation of the information flow can be formulated as an equation system as shown in Figure4.11that contains the following cases: • If there is no clock tick, the value of x remains known if it was already

known3.

• If there is no clock tick, the value of x becomes known if a guarded action (γj, x=τj)with an immediate assignment x=τjcan be fired. This is the case

if and only if the value of the guard γjis known to be true and if the value

of the right hand side expression τj is known.

• If there is no clock tick, and all guards γj are known to be false, the re-

action to absence determines the value of x: The formula of Figure4.11

simply demands that next(x)=x has to hold in this case, since x has been given the now desired value at the previous clock tick as a preliminary value.

• If there is a clock tick, then the values of all variables are known. There- fore, we can execute all enabled delayed actions. If one of the delayed actions can be fired, then the value of x is known for the following macro step.

• Otherwise, the value of x is not known.

The data flow of x is determined by the same cases as formalized in formula ValTransx given in Figure4.11:

• If there is no clock tick and a guarded action (γj, x=τj)with an immediate

assignment x=τjcan be fired, then x will receive the value of τjat the next

point of time. Note that if more than one guarded action can be fired with different values τi and τj, then there is no transition.

2Actually, we have to delay the clock signal by a further step, as will be described

later.

3Although a guarded action (γ

j, x=τj)that once fires in a macro step, remains en-

abled until the end of the macro step, we have to add this constraint, since the variable x may be known due to a delayed assignment of the previous macro step.

Computed Guarded Commands of x and its Reincarnations x1,. . . ,xd: (χ1, next(x) = π1), . . . , (χq, next(x) = πq) (γ1, x = τ1), . . . , (γp, x = τp), (γ1,1, x1 = τ1,1), . . . , (γ1,p1, x1= τ1,p1), .. . ... (γd,1, xd= τd,1), . . . , (γd,pd, xd= τd,pd)

Propagation of Knowledge During Clock Cycle:

KnownTransxi :≡     next(k(xi)) :⇔ ¬clock ∧     k(xi)∨  Wpi

j=1k(γi,j) ∧ γi,j∧ k(τi,j)

 ∨  Vpi j=1k(γi,j) ∧ ¬γi,j          KnownTransx :≡       next(k(x)) :⇔       ¬clock ∧ k(x)∨ ¬clock ∧Wp j=1k(γj) ∧ γj∧ k(τj)  ∨ ¬clock ∧Vp j=1k(γj) ∧ ¬γj  ∨ ¬clock ∧Wq j=1χj            

Micro Step Transition Relation of Reincarnated Variable xj:

ReincarTransxi :≡         ¬clock → pi ^ j=1

(k(γi,j) ∧ γi,j∧ k(τi,j) → next(xj) = τi,j)

!! ∧ ¬clock → ¬ pi _ j=1

k(γi,j) ∧ γi,j∧ k(τi,j)

!

→ next(xj) = Default(x)

!! ∧ (¬clock → next(xj) = Default(x))

       

Micro Step Transition Relation of Local/Output Variable x:

ValTransx :≡                  ¬clock → p ^ j=1 (k(γj) ∧ γj∧ k(τj) → next(x) = τj) !! ∧ ¬clock → ¬ p _ j=1 k(γj) ∧ γj∧ k(τj) ! → next(x) = x !! ∧ ¬clock → q ^ j=1 (χj→ next(x) = πj) !! ∧ ¬clock → ¬ q _ j=1 χj ! → next(x) = Initialize(x) !!                  ,

where Initialize(x) is defined as in Figure 4.10on Page126

Fig. 4.11. Micro Step Transition Relation to Define the Data Flow of a Local/Output

• If there is no clock tick and no immediate guarded action can be fired, then x will keep its value. This covers several cases: First, if the reaction- to-absence should take place, since all guards γj are known to be false,

then keeping the value of x is correct, since we already provided the de- sired value for x at the previous clock tick: Either there was a delayed assignment in the previous macro step that determined the current value of x, or x has been initialized according to Initialize(x).

• If there is a clock tick, then the values of all variables are known, and therefore, we can execute all enabled delayed actions. If one of the delayed actions can be fired, then the value of x is known for the following macro step. Note again, that there is no transition if several delayed guarded actions with different values πiand πj are fired.

• Finally, if there is a clock tick, but no delayed action can be fired, then x is initialized according to Initialize(x).

Note that reincarnated variables do always have event storage mode and no delayed actions, which simplifies their transition relation accordingly. Finally, note that the case distinctions as given by the left hand sides of the implica- tions of ValTransx and ReincarTransxi are complete; that is the disjunction of

the left hand sides of the implications is valid.

The formulas given in Figure4.11describe the micro step transition re- lation of a particular local/output variable x together with its potential rein- carnated variables. In addition to this, we also have to determine the flow of the input and location variables, and we have to define the clock signal. The latter is defined as follows:

ClockTrans :≡  next(clock) :⇔^ x k(x) ∧ d ^ j=1 k(xj)  

In principle, the new clock tick can arrive as soon as all values of the local and output variables become known. This suggest to define the clock signal simply as an abbreviation of the right hand side of the above transition equation. However, this would hide certain write conflicts: Assume that the value of a variable x becomes know in the last micro step of the macro step. Hence, after this point of time (in terms of micro steps), all variables have known values. Therefore, a so-far not known guard may now also become known and the execution of its assignment may lead to a write conflict to the already determined value of x. Hence, we have to add a further micro step before the clock tick so that all enabled guarded actions will fire at that point of time.

When the clock tick arrives, we perform the following actions to initiate the next macro step:

The values of the location variables ` can be computed in terms of the now known value of the inputs, outputs, and local variables. Hence, we add for every location variable ` with transition equation next(`) = ϕ` the

The input variables are read from the environment, which is done by al- lowing the input variables to change their values in a nondeterministic way. However, when clockis false, we have to make sure that the in- puts do not change any more. Therefore, we have to add the formula ¬clock → next(x) = x for every input variable x.

It is easily seen that the micro step behavior as formalized in Figure4.11and in the above additional explanations for the clock definition, the location vari- ables and the input variables describe the semantics of an asynchronous cir-

cuit. We consider the relationship to asynchronous hardware circuits in more

detail in Section??.

Moreover, the entire behavior is described in terms of conditional rewrite

rules, so that also term rewriting techniques are adequate for the analysis of

It is interesting to consider the classic case, i.e., the case where x is an event variable that only has immediate assignments with the right hand side true. In this case, the formulas of Figure 4.11reduce to the ones shown in Figure4.12.

Computed Guarded Commands of x and its Reincarnations x1,. . . ,xd:

(γ1, x=true), . . . , (γp, x=true),

(γ1,1, x1= true), . . . , (γ1,p1, x1= true),

..

. ...

(γd,1, xd= true), . . . , (γd,pd, xd= true)

Propagation of Knowledge During Clock Cycle:

KnownTransxi:≡  next(k(xi)) :⇔ ¬clock ∧    Wpi j=1k(γi,j) ∧ γi,j  ∨  Vpi j=1k(γi,j) ∧ ¬γi,j      KnownTransx :≡  next(k(x)) :⇔ ¬clock ∧    Wp j=1k(γj) ∧ γj  ∨  Vp j=1k(γj) ∧ ¬γj     

Micro Step Transition Relation of Reincarnated Variable xj:

ReincarTransxi :≡  next(xj) :⇔ ¬clock ∧  Vpi j=1(k(γi,j) ∧ γi,j) 

Micro Step Transition Relation of Local/Output Variable x:

ValTransx :≡next(x) :⇔ ¬clock ∧Vp

j=1(k(γj) ∧ γj)



Fig. 4.12. Micro Step Transition Relation for Event Variable x with only Immediate

Assignments x=true

As can be seen in Figure4.12, the transition relation can now be given in form of an equation system. The reason for this is that at every clock tick, the known values as well as the values themselves are reset to false, and during the clock cycle, the value of such an event signal becomes true if and only if one of the guards γj is known to be true. The known value becomes

additionally true if all guards γj are known to be false. As a consequence x

implies k(x).

The equational form given in Figure4.12is interesting because it gives a new insight in the causality analysis in terms of a fixpoint computation:

The reason why we can obtain an equational form is that there are by definition no write conflicts if we only have assignments of the form x=true. In principle, we can therefore also allow delayed assignments of the form next(x)=true, and we could still derive equation systems as it has been shown in [226]. However, this requires the introduction of new state-holding

variables since we have to store if a delayed assignment was enabled in the previous macro step.

In the general case, we have to consider the possibility that several assign- ments are enabled at the same point of time and that these assignments refer to different values.