• No results found

Can and Must-Guarded Actions

4.6 Symbolic SOS Reaction Rules

4.6.2 Can and Must-Guarded Actions

Recall that the SOS reaction rules have been primarily used to compute the sets Dmust and Dcanof immediate assignments that must be and can be exe-

cuted in the current reaction step. To this end, we had also to estimate the instantaneity of the statements by the boolean values tmustand tcanas defined

in Section4.3.

A symbolic version of the SOS reaction rules can be obtained by computing the guarded actions that must be and can be executed in the current reaction. The surprising fact is that there is nothing we have to compute for this pur- pose. Instead, all we have to do is to interpret the guards of ActSurf~(true, S) in a three-valued setting as explained in Section4.1. However, this is not suf- ficient, since we also have to incorporate the reaction-to-absence.

For this reason, the symbolic causality analysis is in principle a symbolic execution of the interpreter function given in Section 4.4. However, we are not yet ready to describe such a symbolic execution, since the symbolic ver- sions of the control and data flow that we have derived in this section are not executable. ‘Executable’ means here that we only have formulas that can check the satisfiability of given assignments, but we can not determine the as- signment in an incremental fashion as done by the interpreter function given in Section4.4. We will see in the next chapter that we can refine the symbolic control and data flow presentation developed in this Chapter so that a sym- bolic execution as required by the symbolic causality analysis will be possible. Hence, we have to postpone the symbolic version of the SOS reaction rules to the following Chapter, where it is then shown that it is equivalent to the ternary simulation of hardware circuits.

For this reason, the symbolic causality analysis is in principle a symbolic execution of the interpreter function given in Section 4.4. However, we are not yet ready to describe such a symbolic execution, since the symbolic ver- sions of the control and data flow that we have derived in this section are not executable. ‘Executable’ means here that we only have formulas that can check the satisfiability of given assignments, but we can not determine the as- signment in an incremental fashion as done by the interpreter function given in Section4.4. We will see in the next chapter that we can refine the symbolic control and data flow presentation developed in this Chapter so that a sym- bolic execution as required by the symbolic causality analysis will be possible. Hence, we have to postpone the symbolic version of the SOS reaction rules to the following Chapter, where it is then shown that it is equivalent to the ternary simulation of hardware circuits.

To formally reason about a symbolic causality analysis, we have to deal with incomplete environments E as defined in Section 4.1. In particular, we consider the following sets of actions:

Definition 4.18 (Symbolic Causality Analysis). For a given Quartz statement

• CanAct(E,~)(S) := {α | ∃γ.(γ, α) ∈ ActSurf~(true, S) ∧Jγ K~

E 6= false}

• MustAct(E,~)(S) := {α | ∃γ.(γ, α) ∈ ActSurf~(true, S) ∧Jγ K~

E = true}

Since the environment (E, ~) is incomplete, the evaluationJγ K

~

E may be either

one of {⊥, true, false}. Therefore, the set CanAct(E,~)(S)contains those actions with unclear precondition γ, so that there is still some hope that γ could become finally true. In contrast, MustAct(E,~)(S)contains only those actions where the precondition γ can not become false, so there is no risk that γ could become finally false.

Since the environments are monotonically updated with respect to the partial order of the environments E as defined in Definition4.3on page88, we can alternatively use the following ‘characterizations’ of the above sets:

Lemma 4.19 (Symbolic Causality Analysis). For every Quartz statement S,

and every incomplete environment (E, ~), we have the following inclusions:

• CanAct(E,~)(S) ⊇ {α | ∃γ.∃E0.(γ, α) ∈ ActSurf ~(true, S) ∧ (E , ~) v (E0, ~) ∧Jγ K ~ E0 = true} • MustAct(E,~)(S)

⊆ {α | ∃γ.∀E0.(γ, α) ∈ ActSurf~(true, S) ∧ (E , ~) v (E0, ~) ∧Jγ K~

E0 = true}

Proof. The evaluation of expression is monotonic. Therefore, we have for all

(E , ~) v (E0, ~) the following implications: • Jγ K~ E = trueimpliesJγ K ~0 E0 = true • Jγ K~ E = falseimpliesJγ K ~0 E0 = false • Jγ K~ E = ⊥impliesJγ K ~0 E0 ∈ {⊥, false, true} • Jγ K~0 E0 = trueimpliesJγ K~ 0 E0 6= false • Jγ K ~0 E0 = falseimpliesJγ K ~0 E0 6= true • Jγ K ~ E = ⊥impliesJγ K ~0 E0 = ⊥

Consider now the must-actions: If alreadyJγ K~

E = trueholds, then we must

also have Jγ K

~

E0 = true for every environment (E0, ~0) with (E, ~) v (E0, ~).

The converse may however not be true, since the evaluation ofJγ K~

E may not

consider ‘global’ effects in the evaluation of γ: Consider, e.g., γ = (x+y)-x<=y, which is true for all values of x and y. However, when one of these value is not yet known, then the result of the evaluation is ⊥.

Analogously, ifJγ K~

E0 = trueholds, then we also haveJγ K~E 6= false for all

(E , ~) with (E, ~) v (E0, ~). Hence, the mentioned inclusion holds, and the converse is not the case for the same reason as mentioned in the case of the

must-actions. ut

Hence, our definitions are actually a bit too strong and can be liberated as given by the ‘alternative characterizations’ of the above lemma (that are however more difficult to check). Nevertheless, we can derive some interest- ing facts that will lead to further discussions. In particular, we can derive the

• CanAct(E,~)(x=τ ) = {x=τ }

• CanAct(E,~)(next(x)=τ ) = {next(x)=τ }

• CanAct(E,~)(assume(σ)) = {assume(σ)} • CanAct(E,~)(assert(σ)) = {assert(σ)}

• CanAct(E,~)(nothing) = {} • CanAct(E,~)(`:pause) = {}

• CanAct(E,~)(if(σ S1 else S2)

=  

CanAct(E,~)(S1) : if JσK~E= true

CanAct(E,~)(S2) : if JσK

~ E= false

CanAct(E,~)(S1) ∪ CanAct(E,~)(S2): if JσK~E= ⊥

• CanAct(E,~)({S1; S2})

=CanAct(E,~)(S1) : if Jinst~(S1)K~E = false

CanAct(E,~)(S1) ∪ CanAct(E,~)(S2): otherwise

• CanAct(E,~)({S1k S2}) = CanAct(E,~)(S1) ∪ CanAct(E,~)(S2)

• CanAct(E,~)(do S while(σ)) = CanAct(E,~)(S)

• CanAct(E,~)(while(σ) S) =

 {} : if JσK

~ E= false

CanAct(E,~)(S): otherwise

• CanAct(E,~)(abort S when(σ)) = CanAct(E,~)(S) • CanAct(E,~)([weak] abort S when(σ)) = CanAct(E,~)(S)

• CanAct(E,~)(weak immediate abort S when(σ)) = CanAct(E,~)(S)

• CanAct(E,~)(immediate abort S when(σ))

= {} : if JσK ~ E= true CanAct(E,~)(S): if JσK ~ E∈ {⊥, false}

• CanAct(E,~)(suspend S when(σ)) = CanAct(E,~)(S)

• CanAct(E,~)([weak] suspend S when(σ)) = CanAct(E,~)(S)

• CanAct(E,~)(weak immediate suspend S when(σ)) = CanAct(E,~)(S)

• CanAct(E,~)(immediate suspend S when(σ))

= {} : if JσK ~ E= true CanAct(E,~)(S): if JσK ~ E∈ {⊥, false}

Fig. 4.13. Possibly Executed Actions

recursive laws for the computation of CanAct(E,~)(S)and MustAct(E,~)(S)as given in the Figures4.13and4.14.

There is an asymmetry for the definition of the actions of the if-statements: While the can-actions take the union of the can-actions of the two substate- ments, the must-actions (which are supposed to be dual) do not take the intersections. The reason for this behavior is as follows:

• MustAct(E,~)(x=τ ) = {x=τ }

• MustAct(E,~)(next(x)=τ ) = {next(x)=τ }

• MustAct(E,~)(assume(σ)) = {assume(σ)} • MustAct(E,~)(assert(σ)) = {assert(σ)}

• MustAct(E,~)(nothing) = {} • MustAct(E,~)(`:pause) = {}

• MustAct(E,~)(if(σ) S1 else S2) =

   MustAct(E,~)(S1): if JσK ~ E= true

MustAct(E,~)(S2): if JσK~E= false

{} : if JσK~

E= ⊥

• MustAct(E,~)({S1;S2})

=MustAct(E,~)(S1) ∪ MustAct(E,~)(S2): if E(inst~(S1)) = true

MustAct(E,~)(S1) : if E(inst~(S1)) ∈ {⊥, false}

• MustAct(E,~)({S1k S2}) = MustAct(E,~)(S1) ∪ MustAct(E,~)(S2)

• MustAct(E,~)(do S while(σ)) = MustAct(E,~)(S) • MustAct(E,~)(while(σ) S) =

 MustAct(E,~)(S): if JσK~ E = true

{} : otherwise

• MustAct(E,~)(abort S when(σ)) = MustAct(E,~)(S)

• MustAct(E,~)([weak] abort S when(σ)) = MustAct(E,~)(S)

• MustAct(E,~)(weak immediate abort S when(σ)) = MustAct(E,~)(S)

• MustAct(E,~)(immediate abort S when(σ))

= MustAct(E,~)(S): if JσK

~ E= false

{} : if E(inst~(S1)) ∈ {⊥, true}

• MustAct(E,~)(suspend S when(σ)) = MustAct(E,~)(S) • MustAct(E,~)([weak] suspend S when(σ)) = MustAct(E,~)(S)

• MustAct(E,~)(weak immediate suspend S when(σ)) = MustAct(E,~)(S) • MustAct(E,~)(suspend immediate S when(σ))

= MustAct(E,~)(S): if JσK

~ E= false

{} : if E(inst~(S1)) ∈ {⊥, true} Fig. 4.14. Necessarily Executed Actions

MustAct(E,~)(if(σ) S1 else S2)

= {α | ∃γ.(γ, α) ∈ ActSurf~(true, if(σ) S1 else S2) ∧Jγ K

~ E = true} = {α | ∃γ.(γ, α) ∈ ActSurf~(σ, S1) ∪ ActSurf~(¬σ, S2) ∧Jγ K ~ E = true} = {α | ∃γ.(γ, α) ∈ ActSurf~(σ, S1) ∧Jγ K ~ E = true}∪ {α | ∃γ.(γ, α) ∈ ActSurf~(¬σ, S2) ∧Jγ K ~ E = true}

= {α | ∃γ.(γ, α) ∈ ActSurf~(true, S1) ∧ E (γ ∧ σ) = true}∪

{α | ∃γ.(γ, α) ∈ ActSurf~(true, S2) ∧ E (γ ∧ ¬σ) = true}

=      MustAct(E,~)(S1): if JσK ~ E = true MustAct(E,~)(S2): if JσK ~ E = false {} : if JσK ~ E = ⊥

The definition of causality depends on some subtle definitions that are from a logical point of view equivalent, and redundant. For example the following alternatives have been discussed in [229]:

• The instantaneity of if-statements can be defined as follows:

– inst~(if(σ) S1 else S2) = ~(σ) ∧ inst~(S1) ∨ ¬~(σ) ∧ inst~(S2)

– inst~(if(σ) S1 else S2) = ~(σ) ∧ inst~(S1) ∨ ¬~(σ) ∧ inst~(S2) ∨

inst~(S1) ∧ inst~(S2)

From a logical point of view, both expressions are equivalent, since the boolean formulas a ∧ b ∨ ¬a ∧ c and a ∧ b ∨ ¬a ∧ c ∨ b ∧ c are equivalent. The latter formula contains just the redundant prime implicant b ∧ c. Using either the one or the other definition, however, changes the set of construc- tion programs. For example, program P10 below becomes constructive:

module P10(event &o) { if(o) nothing; emit o;

}

Using the first variant, the guard of emit o is either o ∧ true ∨ !o ∧ true, hence, o ∨ !o, while the second variant yields o ∧ true ∨ !o ∧ true ∨ true ∧ true, hence, true. Therefore, adding the redundancy makes more programs constructive.

• In a similar way, we can also refine the definition of the surface actions. Here are the two alternatives:

– ActSurf~(ϕ, if(σ) S1 else S2)

:= ActSurf~(ϕ ∧ ~(σ), S1) ∪ ActSurf~(ϕ ∧ ¬~(σ), S2)

– ActSurf~(ϕ, if(σ) S1 else S2)

:= A1∪ A2∪ {(γ1∧ γ2, C) | (γ1, C) ∈ A1∧ (γ2, C) ∈ A2}, where A1:=

ActSurf~(ϕ ∧ ~(σ), S1)and A2:= ActSurf~(ϕ ∧ ¬~(σ), S2)

The idea of the latter definition is that actions C must be executed when this action has two guards γ1and γ2that stem from the different branches,

and both guards must be true. Again, this makes some programs construc- tive that would otherwise be not constructive. For example, the simple program P12 becomes constructive:

module P12(event &o) { if(o) emit o;

else emit o; }

In [53] and [229], some more alternatives have been discussed. From a logi- cal point of view, it is even known that there is a maximal notion of causality that is related to Eichelberger’s prime implicants theorem [94] to avoid haz- ards in asynchronous circuits.

We can also discuss the rules of Figures4.6and4.6in the light of the three- valued logic. To this end, it is convenient to encode the three logic values ⊥, true, and false by a pair of boolean values. There are many encodings that

could be used, however, the following negated dual-rail4 encoding has some convenient properties: x ∈ B2 (x) (false, true) ⊥ (false, false) 0 (true, true) 1 (true, false) > ∧ ⊥ 0 1 ⊥ ⊥ 0 ⊥ 0 0 0 0 1 ⊥ 0 1 ∨ ⊥ 0 1 ⊥ ⊥ ⊥ 1 0 ⊥ 0 1 1 1 1 1 x ¬x ⊥ ⊥ 0 1 1 0

For the above dual-rail encoding of true, false, and ⊥ by two boolean val- ues (b1, b2), and the three-valued boolean operations ∧, ∨, and ¬, we can

define the three-valued boolean operations ∧, ∨, and ¬ directly in terms of the boolean pairs that encode the three-valued truth values. It can be easily verified that the following holds:

• (a1, a2) ∧ (b1, b2) = (a1∧ b1, a2∧ b2)

• (a1, a2) ∨ (b1, b2) = (a1∨ b1, a2∨ b2)

• ¬(a1, a2) = (¬a2, ¬a1)

Now, consider the pair (tmust, tcan) of the boolean flags that have been used

in the definition of the SOS reaction rules. It is interesting to re-read the SOS reaction rules in terms of the three-valued interpretation of this pair.

For example, consider the conditional statement if(σ) S1 else S2 and

assume that i1and i2are the three-valued conditions for instantaneous exe-

cution of S1and S2, respectively. According to the rules given in Figure4.6,

we can easily check that they define the instantaneous execution of the condi- tional statement as σ ∧ i1∨ ¬σ ∧ i2∨ i1∧ i2. To see this, recall that we encode i1

and i2 by the pairs (t1must, t1can)and (t2must, t2can), respectively. For σ = (σ1, σ2),

we therefore obtain the following two rails: • σ1∧ t1must∨ ¬σ2∧ t2must∨ t1must∧ t2must

• σ2∧ t1can∨ ¬σ1∧ t2can∨ t1can∧ t2can

It is now easy to see that for the three cases (σ1, σ2) ∈ {(false, false), (false, true),

(true, true)}, we obtain exactly the definitions as stated in Figure4.6.

In case of sequences S1; S2, the condition for instantaneous execution is

i1∧ i2where i1 and i2 are the three-valued conditions for instantaneous ex-

ecution of S1 and S2, respectively. If these are again encoded by (t1must, t 1 can)

and (t2

must, t2can), respectively, we obtain the definitions as given in Figure4.6.

4The encoding we use here is related to the well-known dual-rail encoding. The

Compilation to Guarded Actions

In the previous section, we have defined an operational semantics in terms of SOS transition and reaction rules. This is not only necessary to define the semantics of the language in a precise way; it is also useful to implement a simulator or an interpreter for the language. However, it is inconvenient to handle all possible inputs at compile time which is necessary for a compiler. For this reason, we have already considered the symbolic form of the SOS rules that is given in terms of the symbolic control flow predicates and the guarded actions. While this symbolic form solves the problem to consider all possible inputs at once, it does not lead to an algorithm to compile the programs into executable code.

This synthesis procedure is based on various prerequisites that have de- veloped in previous work. The starting point was the translation to hard- ware circuits given in [222] that has been formally verified using the HOL theorem prover. To this end, the control flow predicates have been defined [223,224,233] as a symbolic form of the operational semantics as described in the previous chapter. As schizophrenia problems have not been considered in these previous attempts, a generalization to handle all kinds of schizophre- nia has been developed in [227, 228]. To obtain a translation that runs in quadratic time, subterms that are generated during the translation have to be abbreviated by new variables. In the former version described in [227], we used two equation systems Esrfc and Edpth that contained the abbreviations

made for the surface and the depth, respectively.

This was necessary since the solution of schizophrenia problems requires to rename the locally declared variables in the surfaces of loops (see below). Hence, we had to split the equation systems of the abbreviations so that re- naming of only the surface part Esrfcbecame possible. This, however, changes

hash values, and moreover, allows one term to occur multiple times in differ- ent surfaces Esrfcwithout being renamed.

To circumvent this later renaming and hence, the necessity to use multiple hash tables, the solution of the revised journal version [228] works differ- ently: A function Renamings was used to compute all possible scopes before the

actual compilation and these substitutions are forwarded by the depth compi-

lation. The compile algorithms of this chapter are a further improvement in that the renaming is done during the depth compilation and the generated incarnation levels are forwarded to the subsequent surface compilations.

Finally, these compilation procedures have been extended to handle mod- ular (separate) compilation [54], which is essentially the compilation proce- dure described in this chapter.

In this section, we will solve this problem in that we transform the control and data flow to an equation system, so that the entire semantics is given in form of an equation system. For every location variable ` of the program, there is exactly one initial and one transition equation of the forms init(`) = srfc`

and next(`) = Ω`, respectively, where srfc` is a boolean constant, and Ω` is

an expression that only depends on the current values of the location, local, input, and output variables. As the control flow is given as such an equation system, it follows that the control flow is totally defined and deterministic: For all current values, we can evaluate the expressions Ω` to determine the

next value for `, so that we definitely can compute which of the locations are active at the next point of time.

For this reason, the results of this section additionally prove that the con- trol flow of every Quartz program is deterministic. As Quartz has however nondeterministic statements, we have to note that this only holds, when we view the controllable input variables as inputs, since these variables nonde- terministically choose their values.

The data flow will also be translated to an equation system where for every output and local variable (including their possible reincarnations), we gener- ate either an invariant equation of the form x = ϕ or also initial and transi- tion equations as described for the control flow. For memorized variables, and event variables with delayed actions, we must also define a so-called accom- panying carrier variable to store the previous values if these are required. In contrast to the control flow, the data flow equations can suffer from causality

cycles, since the dependency graph of the variables defined by the equations

can be cyclic.

We will define a causality analysis for the equation systems that are gener- ated from the Quartz statements. In principle, this causality analysis is a sym- bolic execution of the program that covers all possible inputs and all reachable states. Preliminarily unknown values are modeled with the special value ⊥ as already done in the previous chapter. We will outline the equivalence to the so-called ternary simulation of asynchronous circuits in Section??. We will see

that constructive programs are closely related to speed-independent circuits, in that a program is constructive if and only if the generated hardware circuit is speed-independent.

A major problem for the translation into hardware circuits are schizophrenic

statements, in particular schizophrenic local declarations [42,210,233]. Re- call that a statement is schizophrenic if some of its micro steps are executed more than once in a macro step. This may happen only if the statement be-

longs to a loop body that is left and (re)entered at the same time (in the same

macro step). If the scope of a local declaration is thereby left and (re)entered, then the compiler must carefully distinguish between different incarnations of local variables that exist at the same time, but in different scopes.

In the previous chapter, we already dealt with the reincarnations in that we used incarnation level functions h to map the local variables to their current incarnation level. This means that we generated for every reincarnation of a variable x a new variable of a different name ~(x), which is however known to be the i-th incarnation of x. In general, several copies may be necessary, which can (only) be achieved by nested abort and loop statements as shown by Gonthier’s example in Figure3.2on page60). We will use the same notation and the same incarnation level functions also in this chapter.

In this section, we therefore present an algorithm for the translation of Quartz programs to equation systems that can also be interpreted as hard- ware circuits. In a first step, we compute thereby directly the equation system of the control flow, while the data flow is computed in terms of guarded ac- tions as done in the previous chapter. In contrast to the previous chapter, we then construct equations of the guarded actions, to that the entire result is an equation system that covers both the control and data flow of the program.