• No results found

Validation of Action Sequences

A schedule is always described with respect to a context (closure or signa- ture) which for a CAL actor is a subset of the state variables, the FSM state, and the contents of the input queues. Naturally, this set only needs to con- tain variables and input ports which are reachable from a guard expression of one of the actions in the schedule. The schedule is fired based on evaluat- ing the guard of the first action of the sequence, while the other guards are expected to always evaluate to true once the schedule has been chosen for execution. Now, the variables of the guard expression of the action enabling the schedule, may not define the context uniquely enough for the sequence to always follow that specific guard. The guard may not restrict one variable enough or it may even ignore that variable; the sets of variables related to

scheduling can be seen as: Guard⊆ Context ⊆ ActorState.

The schedules generated according to the approach described above, was scheduled with a correct but arbitrary context with respect to the state variables. The generated schedule can certainly describe a correct action sequence for that particular state, but, the guard may not be strong enough to decide if the context exactly corresponds to that schedule. The approach taken here is not to strengthen the guard, but instead to shorten the sched- ules such that the context corresponds to the guards. This is done by insert- ing new choice states when a state is found where the guards of the outgoing transitions are too weakly described in the guard enabling the schedule. To find these states, the schedules are simulated with respect to how the actions access and modify the state variables.

For each action, what we are interested in is, mainly, the instructions storing a value to a state variable. A store instruction, in the IR (Inter- mediate Representation) we are working with, stores a value based on an expression, composed of constant values and local variables, to a state vari- able. By using the variable dependency graph, based on the instructions of the specific action only, a store instruction can be described as a modifica- tion of a state variable, from a set of state variables (and input ports). When repeating this for every store instruction, a schedule becomes a sequence of action firings which modify the state variables from other state variables. Some of the modifications are completely based on constants, which mean that the state variable is reset with a constant value. Other variables are modified based on some other variables or in some cases themselves. When

a variable is updated from variables, the variable inherits the state of the variable, which at a specific moment either is known or unknown. Figure 4.5, shows an example of how a store instruction is described from the program description.

Figure 4.5: Read/write analysis.

With this information, it is possible to, for each action, 1) give a set of variables that are reset, that is, gets updated with a constant value, 2) give a set of variables that are updated, including from which variables they are updated. By stepping through the sequence of actions, it is therefore possible to keep track of which variables has a known value and which does not. In the simplest type of analysis, we start with considering the variables in the context of the schedule to be unknown (or dirty). Then, for each action, if a variable is updated from known (or clean) values, where a constant always is known, then the variable itself becomes known. At the point where a variable is used in a guard, it can only be allowed to be based on known variables, else the state with that guard must be considered a choice state. In order to verify that a scheduler is complete, each of the schedules is run with this check to find out if there is a guard in one of the schedules which uses a variable with a potentially unknown value. If this check holds, we can be sure that the schedules are unique and are eligible when the action with the enabling guard is eligible; but, of course, only if sufficient input for the whole schedule is available.

A variable does not always need to start out as unknown. If every path to the state where a schedule starts resets the variable to a specific value, such that the variable always has the same value in the initial state of a schedule, the variable can be seen as known from the start, when that schedule is analyzed. To find these variables, two properties are checked for each variable belonging to the context of a schedule. First, a variable can only be known if it can be proved to always have a constant value in the state where the schedule begins. To prove this property, each path to that state must reset the variable such that it is clean when the state of interest

Figure 4.6: Validation of uniqueness of schedules.

is reached; this can be resolved with the same analysis as presented above. The second property is that each path to that state should end with the variable having the same value, including the initialization of the variable if it corresponds to the initial state. To achieve this, the interpreter producing the schedules records a snapshot of the state variables after each schedule it has executed. The set of variables that are both clean when reaching the scheduling state and have an identical value, no matter which path was taken to the state, is considered to be clean from the start of the analysis. Also, if the guard of the schedule is strict, the variable might be more or less known during the schedule. This, however, might quickly become complex when the variables are modified, and have not been utilized in this work.

In many cases, for example with a variable used to iterate a loop, a schedule either resets the variable before it starts looping or afterwards. In both cases, the variable is reset before it reaches a guard; in the case when it is reset before it is used, the analysis finds the variable to be known when the schedule is checked, in the other case, the variable should be marked as clean in the context of the schedule, if it can be shown to always have the same value in that FSM state. A simple example of how the bookkeeping of state variables works is given in Figure 4.6, which shows a schedule with three actions, each containing one instruction modifying the a state variable. The first instruction updates variable j from an constant which makes j known. At the potential choice state, variables j and k are known while i is unknown. If the guards of the potential choice state does not use i, the choice of the next action to fire is a static scheduling decision, else it is not.

This analysis can be improved by describing more carefully the relation- ships between guards and variables, and states and variables, however, it must be conservative in that sense that a schedule is only considered static when it can be proved to be. Consequently, a static schedule may be split

into several schedules, because it could not be proven to be unique. The resulting scheduler, after this step, describes the behavior of an actor with a simplified scheduler where the scheduling decisions that can be resolved at compile-time have been removed and replaced with sequences action firings. If the action sequences are composed in to bigger actions (super actions), the new scheduler causes the actor to work on larger chunks of data, which may cause problems especially if the program includes feedback loops. This is similar to the known problem that deadlock-freedom, for models such as SDF, is not closed under composition. Instead, composing two adjacent actors may introduce deadlock, and deadlock-freedom needs to be proved according to composition conditions such as those presented in [105].

The conclusion from this is that while the schedules are correct, for a composition to be deadlock-free, it may be unavoidable to interleave actions of two schedules from two different actions. This is exactly what the compo- sition presented in the next chapter is about, and the composition presented there does guarantee that a composition is deadlock-free, however, it does not guarantee the program to be deadlock-free globally.