4.5 Symbolic SOS Transition Rules: The Control Flow Predicates
4.5.3 Computing the Data Flow
In the previous section, we have shown how the guarded actions of a state- ment S can be computed in terms of its surface actions ActSurf~(st, S)and its depth actions ActDepth (S). For the initial computation, we use the start signal or location st as precondition of the surfaces and the zero incarnation level function ~0that maps all variables to incarnation level 0. The guarded
actions of a statement S are therefore ActSurf~0(st, S) ∪ ActDepth (S). The guarded actions are the essential information that we need to define the data flow of the program, which is explained in this section. The mean- ing of a guarded action (γ, C) is that whenever γ holds, then C is executed. Executing an immediate assignment x=τ has the effect that immediately the equation x==τ holds, while the execution of a delayed assignment means that the value of x at the next point of time is equal to the current value of τ . As- sumptions and assertions do not contribute to the data flow. Instead, they are used for the construction of specifications as described in the next subsection. For the following, we therefore only consider the guarded actions that are assignments. Moreover, we partition them according the left hand side variables (expressions). For example, assume that for a variable x, we have obtained the guarded actions (γ1, x=τ1),. . . ,(γp, x=τp)with immediate assign-
ments, and the guarded actions (χ1, next(x)=π1), . . . , (χq, next(x)=πq)with
delayed assignments. Then, the following formulas must hold at every point of time: p ^ i=1 (γi→ (x = τi)) ! ∧ q ^ i=1 (χi → (next(x) = πi)) !
Note that this formula can become false if there are write conflicts on the variable x. We can essentially distinguish three kinds of write conflicts: • If two immediate assignments x=τiand x=τjare enabled at the same time,
then the formula is false unless we have τi= τj at that point of time.
• If two delayed assignments next(x)=πi and next(x)=πj are enabled at
the same time, then the formula is false unless we have πi = πj at that
point of time.
• If a delayed assignment next(x)=πi is enabled at the current point of
time, and an immediate assignment x=τi is enabled at the next point of
time, then the formula is false at the next point of time unless πi of the
current point of time is the same value as τiat the next point of time.
Hence, write conflicts can reduce the entire data flow formula to false. Check- ing for write conflicts is however not simple for the data flow transition rela- tion that is developed in this section. We consider the analysis of write con- flicts in more detail in Chapter8.
The above formula for the data flow of the variable x is not yet complete. It only determines the value of x at a point of time t when an immediate
assignment is executed at time t or a delayed assignment has been executed at time t−1. However, if neither is the case, then we must also determine a value for x which is done by the reaction-to-absence that has already been described in Figure4.8. In this case, x takes its default value Default(x) which is defined for memorized variables as the previous value of x, and for event variables as the default value of the type of x (which is 0 for numbers and false for booleans). A precise definition of the data flow is given in Figure4.10.
Figure4.10considers thereby the more general case where x is a locally declared variable that has some reincarnations. The case of global output variables is a special case of local variables where no reincarnations have to be considered.
To describe this formally, assume we have computed for a local variable x and its d reincarnations x1,. . . ,xdthe following guarded actions (note that
there are no delayed actions on the reincarnations), where xd is assumed to
be the outermost reincarnation of x:
(χ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)
Reincarnations xi do always have event storage mode, since they only exist
for one point of time. Note further that we have no delayed actions on rein- carnated variables, since the renamings due to the incarnation level function ~ have not been applied on the left hand sides of delayed assignments. For this reason, the transition relation of a reincarnated variable xi is defined as the
invariant Invarxi in Figure4.10that has to hold at every point of time. This
invariant simply states that whenever the trigger condition γi,j holds, then
the corresponding equation xi = τi,j must also hold. If no trigger condition
γi,jholds, then it is required that xiequals to the default value Default(x).
The initial condition Initx of the variable x is constructed analogously to Invarxi which indicates that the semantics of reincarnated variables corre-
sponds with an initialization of a variable. The explanations for the construc- tion of Initx are the same as for Invarxi.
The transition relation of x is more difficult: We have to distinguish be- tween event and memorized variables x for the reaction to absence. In any case, the equation x = τj must hold if the trigger condition γj holds. More-
over, if the trigger condition χjof a delayed assignment next(x) = πj holds,
then x must have the value πj at the next point of time (note that πjis evalu-
ated with the current variables to determine the value of x for the next point of time).
If neither a trigger condition γj of an immediate assignment nor a trig-
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)
Transition Relation of Reincarnated Variable xi:
Invarxi :≡ pi ^ j=1 (γi,j→ xi= τi,j) ! ∧ pi ^ j=1 ¬γi,j ! → xi= Default(x) !
Initial Condition of Event/Memorized Variable x:
Initx :≡ p ^ j=1 (γj→ x = τj) ! ∧ p ^ j=1 ¬γj ! → x = Default(x) ! !
Transition Relation of Variable x:
Transx :≡ p ^ j=1 (γj→ x = τj) ! ∧ q ^ j=1 (χj→ next(x) = πj) ! ∧ next( p ^ j=1 ¬γj) ∧ q ^ j=1 ¬χj ! → next(x) = Initialize(x) ! ,
where the expression Initialize(x) is defined as follows:
Initialize(x) :≡
Default(x) : if x is an event variable case god: xd; .. . go1: x1; else x : if x is a memorized variable
Fig. 4.10. Transition Relation to Define the Data Flow of Local Event/Memorized Vari-
the reaction-to-absence: The value of an event variable x is the default value Default(x) associated with the type of x.
The reaction-to-absence for memorized variables is more difficult. Clearly, if an immediate or delayed assignment is executed, we have the same effect as for event variables, and therefore the first two conjuncts of Transx are the same for event and memorized variables. The reaction-to-absence is however more difficult for memorized variables, since there may be an interference of reincarnated variables and the original memorized variable x: It may be the case that there is neither a delayed assignment to x in the surface of the local declaration nor an immediate assignment right after this point of time. In this case, x has to capture the value of that reincarnated variable xi that
corresponds with the surface that has been executed most recently.
Hence, we have to determine the ‘most recently executed surface’ in order to capture the value of the most recently reincarnated variable. This is the reason why the preconditions of each surface that has been generated by a loop has been stored in the variable Ξ during the computation of the depth actions. Using these preconditions, we are able to check one after the other (in the ordering of their nestings) to determine the most recently activated surface. Note that this selection is done dynamically and the formulas we generate therefore have to cover all possible cases.
Hence, assume that goi is the precondition of a loop surface where the
local variable x has been reincarnated to xi(hence,Wpj=1i γi,j → goimust be
valid, but the converse may not hold). The transition relation for x is then determined by the expression Initialize(x) in Figure4.10. With the case con- struct, we check the preconditions goione after the other. Note that if goi is
the first one that holds, then all goj with j < i do also hold, which means
that goirefers to the outermost surface whose reincarnated variable has to be
referred to. Finally, if no precondition goiholds, then the control flow moved
from somewhere inside the scope of x to somewhere inside the scope of x without leaving the scope in between. Hence, we simply store the previous value of x, which is the default case of the case construct in the expression Initialize(x).
Again, it is possible that write conflicts can appear in the transition re- lations Transx and Transx. Note that it is no problem if several surfaces are executed and if the local variable is assigned different values in each of these surfaces. We consider the issue of write conflicts in Chapter8in more detail.