Electronic Notes in Theoretical Computer Science 65 No. 2 (2002) URL: http://www.elsevier.nl/locate/entcs/volume65.html pages

Geometric Model Checking: An Automatic Verification Technique for Loop and Data Reuse Transformations K.C. Shashidhar a,b,1 Maurice Bruynooghe b,2 Francky Catthoor a,c,1 Gerda Janssens b,2 a

DESICS Division, IMEC vzw, Kapeldreef 75, B-3001 Heverlee, Belgium b

c

Department of Computer Science, Katholieke Universiteit Leuven, Celestijnenlaan 200A, B-3001 Heverlee, Belgium

Department of Electrical Engineering, Katholieke Universiteit Leuven, Kasteelpark Arenberg 10, B-3001 Heverlee, Belgium

Abstract Optimizing programs by applying source-to-source transformations is a prevalent practice among programmers. Particularly so, in the framework of methodology based embedded systems design, where the initial program is subject to a series of transformations to optimize computation and communication. In the context of parallelization and custom memory design, such transformations are applied on the loop structures and index expressions of array variables in the program, more often manually than with a tool, leading to the non-trivial problem of checking their correctness. Applied transformations are semantics preserving if the transformed program is functionally equivalent to the initial program from the input-output point of view. In this work we present an automatic technique based on geometrical program modeling to formally check the functional equivalence of initial and transformed programs under loop and data reuse transformations. Our technique also provides very useful diagnostics to locate the detected errors.

1

Introduction

The design of embedded systems for the consumer market, particularly for multimedia signal processing applications is a complex task. The demands on the optimality of design in terms of performance, area, power and cost are high. Typically, an initial design is assembled by a straightforward implementation 1 2

Email: {kodambal,catthoor}@imec.be Email: {maurice,gerda}@cs.kuleuven.ac.be

c °2002 Published by Elsevier Science B. V.

Shashidhar et al I: Initial Program

... for ( i = 0; i < 10; i++ ) 1: B[i][0] = 0; for ( i = 0; i < 10; i++ ) for ( k = 0; k < 8; k++ ) 2: B[i][k+1] = B[i][k] + A[i*4+k]; ...

T: Transformed Program

1’: 2’:

3’: 4’: 5’:

... for ( i = 0; i < 10; i++ ) B[i][0] = 0; for ( j = 0; j < 4; j++ ) buf[0][j] = A[j]; for ( i = 9; i >= 0; i-- ){ for ( j = 0; j < 4; j++ ) buf[10-i][j] = A[4*(10-i)+j]; for ( k = 0; k < 4; k++ ) B[9-i][k+1] = B[9-i][k] + buf[9-i][k]; for ( k = 7; k > 3; k-- ) B[9-i][12-k] = B[9-i][11-k] + buf[10-i][7-k]; } ...

Fig. 1. An example of program transformation

of the specification in a high-level programming language. This initial design, if naively implemented, often leads to an unacceptably sub-optimal system. This has motivated development of methodical design frameworks. Design exploration and optimization is done at various levels of abstractions, leading to a more optimal mapping of the software onto the custom made platform. An important design rule is that higher abstraction levels lead to greater gains in optimization. As a result, the initial source code serves as the first basis for a systematic exploration by applying source-to-source transformations. For example, in the context of parallelization [3,25] and custom memory design [5], transformations that modify the loop structure of the program [2] and/or introduce caches to reduce the cost of data transfers are very common, as they have been shown to be the most useful for optimization. Application of such global transformations are still not within the scope of the current optimizing compilers [10]. In practice, designers manually apply complex transformations, relying on a combination of application know-how, experience and ingenuity, and supported by some analysis tools. The problem of ensuring an error-free implementation of today’s complex specification under time-to-market pressure is difficult enough and is further exacerbated by the hand-applied transformations. As a result, a dire need exists to supplement/replace testing with automatic verification tools. Also, in general, it has become necessary to scale up verification and testing techniques, to meet the present challenge [7]. Assuming that the initial source code is correct, in this work, we address the problem of automatically checking the functional equivalence of the transformed program with the initial. In other words, we verify that the transformations do not introduce any subtle bugs. Figure 1 shows a toy example of initial and transformed programs which are functionally equivalent from the input-output point of view, i.e., the sequence of values assigned to B[][] are the same in both the programs for a given input A[]. Since the equivalence checking problem for programs is, in general, undecidable [23], an automated tool has to be based on a decidable condition that is sufficient for equivalence between initial and transformed programs. If the condition holds, the 2

Shashidhar et al source-to-source transformations Initial program

Transformed program

equivalence Geometrical model

Geometrical model checking

O.K.

Not O.K. + error diagnostics

Fig. 2. Transformation verification scheme

transformation is safe, ensuring the equivalence; otherwise, nothing can be concluded. In the latter case, to be useful, an automated tool should be able to pinpoint a reasonably small program fragment that is at the origin of the failure to prove equivalence. In the above explained context, it is practical to restrict transformation verification to checking the equivalence of computation of program statements under the loop structures in the initial and transformed programs. These program statements usually involve indexed variables (arrays) and transforming the loop structures usually also results in the transformation of index expressions. It is required to check that the use of the definition and operand variables in the computation under the loop structures of the transformed program is in one-to-one correspondence with that of the initial program. In our approach, this very information about the addressing order and the bounds of the indices of the variables under the loop iterators is extracted from the program and represented as geometric models. Once these models are available, it suffices to check the necessary and sufficient equivalence conditions on the corresponding models of initial and transformed programs. Figure 2 puts our scheme in a nutshell. The technique we present in this paper is applicable for loop and data reuse transformations on sequential programs in dynamic single-assignment form [9]. Outline of the paper. Section 2 discusses related work and contrasts the work presented in this paper with respect to it. Section 3 explains in brief the geometric model that we use in our verification technique. Section 4 describes the transformations that are targeted in this work. Section 5 presents the technique that we propose to verify the correctness of these transformations.

2

Related Work

An often suggested approach to ensure correctness is the a priori method of allowing only a predefined set of transformations to be applied, which are proven to be semantics preserving. If these transformations are applied by a formally verified tool, the transformed program is correct by construction [1,12,20,26]. 3

Shashidhar et al [Transformation Tool Verification] Is the transformation correct? designer guided program transformation tool

source program

transformed source program

manual transformations compiler

Is the transformed source program a correct transformation of the source? [Transformation Verification]

Is the target code a correct translation of the source? [Translation Validation]

Is the compiler correct? [Compiler Verification]

target code

Fig. 3. Contrasting with related work

But, a clear practical problem exists with this theoretically elegant approach. Often a customized program transformation tool is not available for the given context. Even if the tool is available, allowing only a predefined set of transformations is very restrictive. The designers desire the flexibility of applying a transformation that is not in the set when they see a clear gain in applying it. They usually also lack the skill required to add new transformations to the existing set with the required formal proofs. In practice, applying program transformations is as natural and manual an activity as programming itself, thereby warranting the need for a posteriori methods. The front line formal verification techniques, model checking and theorem proving, are not suited to the problem that we are addressing. Model checking is not suitable because we are dealing with sequential data dominated programs which are not amenable to be represented as state transition systems. Symbolic model checking of infinite state systems has been presented in [4] for verifying temporal properties, which is not the focus of our work. But, we do use a similar framework in addressing our problem. Theorem proving is unattractive to the designer because of the often quoted requirement of skill. Also, techniques applied for verification of equivalence of implementation to the behavioral specification [6,24] and others, are suited for checking arithmetic and logic expressions, but not for loop constructs on indexed variables in the source code. A solution proposed often is to completely unroll the loop, but this is clearly infeasible given that the loops are nested and the bounds are quite large in real programs, especially in embedded multimedia applications. In particular, SFG-Tracing [6] provides proof of equivalence of loop constructs based on induction with the restriction that ordering be preserved. But, automation has only been possible for non-loop transformations. The relatively recent work on translation validation [15,13,16], with motivation that props our own, addresses a very related problem of a posteriori 4

Shashidhar et al

validating whether the target code produced by a compiler is a correct translation of the source program, providing an alternative to the verification of translators/compilers. In this technique, a trade-off exists between the class of transformations that can be checked and the extent of compiler instrumentation that is required to provide enough information to the validator about the transformations applied. In contrast to translation, our concern is on the murkier source-to-source transformations. More importantly, the problem is compounded by the fact that usually transformations are made manually in the context of methodical system-level co-design frameworks and it is desirable to have first a verification at the level of the source code before getting down to compilation and synthesis. Our attempt here is to provide a transformation oblivious verification infrastructure which is complementary to translation validation. In Figure 3 the line in bold delineates the problem that we are addressing in contrast to other related problems. With an altogether different goal, approximate equivalence checking methods have been proposed based on program representation graphs and program slicing in the context of program integration [27,19]. But, their method is restricted to a language subset which omits indexed variables and hence is not suited to address our problem. In prior work, at Imec, the feasibility of the approach in handling pure loop transformations has been demonstrated [21] and also, a heuristic to handle bigger problem sizes has been proposed [8]. The work presented in this paper significantly improves the model and extends the approach to also handle data reuse transformations.

3

Geometrical Program Modeling

The novelty of our approach lies in the geometric model on which our technique is based. Geometrical models have in the past been quite extensively used to model and analyse execution of program statements, in the parallel compiler and regular array synthesis domain [9,17,18]. Though the model itself is quite simple, it concisely represents most of the necessary information about the data and control flow in the program. We use formulas that encode affine constraints on integer variables, logical connectives and quantifiers, also called Presburger formulas, to symbolically represent the domain spaces and mapping between them. The geometrical model is explained at length in [5], but here, we intend to give only the definitions that are required to present our technique. We use the following notation, for a given program P : variables read = P oper V ; variables defined = P Vdef ; variables read in statement i = Pi Voper ; variables defined in statement i = Pi Vdef . The following elements of the model are extracted by static analysis of the given program: •

Iteration domain of statement i; Pi Diter : Domain in which each point with integral coordinates represents exactly one execution of the statement 5

Shashidhar et al

i. The domain will be a k-dimensional linearly bounded lattice (LBL) [22] if the execution of the statement is controlled by k iterator variables. For example: the iteration domain of statement 2 in the initial program I in Figure 1 is as given below: I iter 2D

:= { [i, k] | 0 ≤ i ≤ 9 ∧ 0 ≤ k ≤ 7 ∧ [i, k] ∈ Z2 }

The if-then-else constructs, if present, introduce additional constraints on the domain with their branch conditions. •

P oper Definition/operand domain of a variable v in statement i; Pi Ddef : v , i Dv The definition (or operand) domain of a variable defined (or read) in a statement i describes which elements of the variable are accessed during all possible executions of the statement. Each point with integral coordinates in these domains corresponds to exactly one element of the variable that is being written (in the definition domain) or read (in the operand domain). For a d-dimensional array variable, the definition and operand domains will be LBLs of the same dimension. For example: the definition domain of B[][] and operand domain of A[] in statement 2 of I is: I def := { [a1 , a2 ] | a1 = i ∧ a2 2 DB I oper := { [a3 ] | a3 = i ∗ 4 2 DA



= k + 1 ∧ [i, k] ∈ I2 Diter } + k ∧ [i, k] ∈ I2 Diter }

Dependency mapping between the defined variable vd and the k th operand variable vo in a statement i; Pi Mvd (vo ,k) : The dependency mapping is an integer tuple relation describing the complete information about which elements of the defined variable depends on which elements of the operand variable during all possible executions of the statement. Each tuple in the relation corresponds to exactly one dependency mapping between the elements of the defined and operand variables. For example: the dependency mapping between the defined variable B[][] and the second operand variable A[] in statement 2 of I is: I 2 MB (A,2)

:= { [a1 , a2 ] → [a3 ] | a1 = i ∧ a2 = k + 1 ∧ a3 = i ∗ 4 + k ∧ [i, k] ∈ I2 Diter }

The dependency mapping M : Ddef → Doper , as evident from the definition, is a partial function from an integral definition domain to an integral operand domain which is neither surjective nor injective. The model of [5] includes other definitions that capture data flow information like dependency distance vector, direction vector etc. But they are relevant for equivalence checking only to the extent that they provide information about the DEF-USE ordering between elements of indexed variables. An important point to make here is that the above model can be extracted from programs written in any programming language that provides loops and indexed variables. This makes the equivalence checking independent of the particular programming language in which the initial and the transformed programs have been written. Also, we would like to add that the notation explained was kept simple to maintain clarity. Mere sophistication of notation 6

Shashidhar et al

suffices if more than one variable is defined in a statement. Assumptions. The transformation verification technique to follow requires that the transformations change only the loop structure and the index expressions and nothing else. This requirement is reasonably justified given the particular problem that is being addressed. The assumptions enumerated below make the requirements explicit. •

In many program transformation frameworks, it is common to transform the program first to the dynamic single-assignment form, where, each variable (array element) is written only once [9]. This gives much more freedom in applying optimizing transformations. Hence, we require that programs are in single-assignment form and also that they are free from pointers. We assume that a preprocessing stage, partly described in [5], has correctly transformed the source code to the required form.



The index expressions and the expressions giving the bounds of the iterators are affine functions of only the surrounding iterator variables.



Only vector variables are verified. The data flow involving scalars, without loop constructs and indexed variables, can be handled with other techniques that deal with arithmetic and logic expressions mentioned in Section 2. The integration with other techniques is straightforward if the source code is organized into two layers, wherein, the loop constructs and indexed variables are sorted into one and the scalars into another. This in fact is essential to facilitate manual transformations on the former, while leaving the optimization of the latter to the compiler [5].



The transformations do not change the variable names and their types in the program.



We assume that transformations only involve (1) the introduction of buffer arrays (caches), that are written by copying other array elements and (2) reorganization of the loop structure that preserves the functions applied on the data elements in the right hand side of write statements i.e., only modification of index expressions and replacement of an array being read by a buffer are supported by our analysis.



We assume that it has been verified that the data flow is correct in the initial and the transformed program, i.e., each array element is DEFined before being USEd.

4

Optimizing Transformations

4.1 Loop Transformations Loop transformations play a crucial role in program optimization when the goal is to increase parallelism and to make efficient use of memory hierar7

Shashidhar et al

chy. They have been well studied as matrix manipulations on index sets. The most primitive of loop transformations are: permutation/interchange, skewing, reversal and bumping on tightly nested loops. A large class of generally applied loop transformations can be derived through successive application of affine unimodular transformations of these primitive types [3]. Loop distribution/fission/splitting, merging/folding/fusion, strip-mining/tiling, unrolling are other important loop transformations that cannot be derived from the primitives above. Most of the loop transformations applied in practice belong to one of the above types. Also, some of these transformations are just enabling transformations for other loop transformations and do not result in any optimization by themselves. The loop transformations change only the execution ordering while the overall computation remains essentially the same. If the program is in singleassignment form and the DEF-USE order is preserved, the elements of the variables read and written, and the dependency between them should remain unaltered for the transformation to hold. As explained in Section 3, the geometrical model captures this information independent of the particular loop transformation that is applied, hence, enabling us to verify the whole set of structure preserving and structure modifying loop transformations that were mentioned above. The example in Figure 1 shows a simple loop distribution transformation on the inner loop and a loop reversal transformation on the outer loop and one of the inner loops, along with a to be explained data reuse transformation. Though the transformations applied in the example are trivial compared to transformations applied in multimedia applications for rigorous optimization, they illustrate the complexity involved in checking the correctness. 4.2 Data Reuse Transformations Efficient use of a customized memory hierarchy to exploit temporal locality in data accesses is very important for optimal design of embedded systems with less energy consumption in the memory system. Hardware controlled caches exploit this, but at a very significant energy cost. Hence there is an increased interest in software controlled caching. Compile time introduced data reuse transformations on the program enable this in a system-level design framework [5]. The data reuse transformation involves the introduction of a buffer variable to hold the data element that is accessed multiple times as shown in Figure 4. The introduction of buffer variables usually also requires that loop structure and index expressions of the array variables are transformed. Clearly this transformation is semantics preserving. But, a mistake made during application of such a transformation on non-trivial programs might introduce subtle bugs. The fairly simple initial and transformed program pair in Figure 1 demon8

Shashidhar et al initial

transformed

Fig. 4. The principle of data reuse transformation

strates the transformation. Here, the buf[][] variable is introduced to hold the reused elements of A[] 1 . The example shows data reuse with a single cache, but in practice, multi-level reuse is often required, making it very hard to check manually that the semantics is preserved.

5

Transformation Verification Technique

The transformation verification technique is an implementation of the scheme shown in Figure 2. Given the initial and transformed program pair (I, T ), the geometrical models are extracted from the two programs and necessary and sufficient equivalence condition checks are applied on the various domains and mappings in the models. If a condition does not hold the transformed program is debugged with the error diagnostics generated as a result of invalidity of the condition. The equivalence on integral domains and mappings is defined as below. Definition 5.1 Domain Equivalence: D = D0 iff (x ∈ D) ⇐⇒ (x ∈ D0 ). Mapping Equivalence: M = M0 iff ((x → y) ∈ M) ⇐⇒ ((x → y) ∈ M0 ). The above definitions are the same as saying that equivalence A = B holds when both A − B = φ and B − A = φ, where, A and B are both either integral domains or mappings. Performing an equivalence check with a tool such as Omega test [17] has to be done this way. Before we present the technique, we define two notions of equivalence of statements and some sets of statements: Definition 5.2 Let s1 : u[. . .] = f (u1 [. . .], . . . , um [. . .]) and s2 : v[. . .] = g(v1 [. . .], . . . , vm [. . .]) be program statements. Statements s1 and s2 are weakly equivalent if u = v and f = g (i.e., the statements define the same array and apply the same function). They are equivalent if they are weakly equivalent and for all 1 ≤ i ≤ m: ui = vi . 1

The buf[][] variable has the same number of elements as A[], this is because of the requirement of single-assignment form. Later transformation steps in the full transformation script remove these redundancies [5,18].

9

Shashidhar et al I: Initial Program

T: Transformed Program {

{ ....

h’:

buf[..] = u2[..]; ....

i:

v[..]= f(u1,u2,..,un); ....

i’:

j:

v[..]= g(u1,u2,..,um); ....

v[..]= f(u1,buf,..,un); ....

j’:

v[..]= f(u1,u2,..,un); .... }

v[..]= g(u1,buf,..,um); ....

k’:

v[..]= f(u1,u2,..,un); ....

k:

l’:

v[..]= f(u1,buf,..,un); }

Fig. 5. Example to explain statement classes. Each v[..] is a different element of v as the programs are in single-assignment form.

Definition 5.3 Let P be a program and P Sdef be the set of statements definv ing the array variable v in P . This set can be partitioned into statement classes, each class being a maximal subset of equivalent statements. We use P Rv (with an extra superscript if needed) to denote a statement class for variable v in P . For example, in the initial program I in Figure 5, with v being defined only in statements i, j and k, the sets defined above are as follows: I Sdef = {i, j, k}, v I def I 1 I 2 I 1 I 2 the partition π( Sv ) = { Rv , Rv }, where Rv = {i, k} and Rv = {j}. As programs are in single-assignment and have a correct data flow, the semantics of the initial program I is completely defined by the mappings I i Mv (w,k) to its arrays and the functions used in the statements defining the array elements. Indeed, for each array element, its mappings identify the array elements that serve as input to the function that computes the value, i.e., how each array element depends on other array elements (array dependency). Correctness is preserved if it can be shown that each mapping dependency in the initial program I also exists in the transformed program T . However, a mapping is not necessarily present in the transformed program due the introduction of buffers. This can be resolved by tracing the array dependencies back in the transformed program. Hence, to show correctness, we will check that each array dependency present in the initial program is also present in the transformed program. In addition, it is desirable that the transformed program does not perform superfluous computations, i.e., each defined element, except output arrays, is also used (implied by the data flow correctness) and that the output arrays in initial and transformed programs have the same number of defined elements. We formalize this in what follows. First we define a function τ as: τ (I Rv ) = {s | s ∈ T and s is weakly equivalent with the statements of I Rv }. An array element defined in I by a statement in I Rv must be defined in T by one of the statements of τ (I Rv ). For example, in the transformed program T in Figure 5, τ (I R1v ) = {i0 , k 0 , l0 }. Next we compute the array dependencies of defined-operand variable pairs 10

Shashidhar et al

for the statements in τ (I Rv ). As we are only interested in pairs that correspond to array dependencies in the statements of I Rv , we define a mapping 0 M that eliminates the chain of buffer variables for defined-operand variable pair (v, w) as follows: 0 Mv (w,k) := { [¯ a] → [¯b] | there exists a chain of dependencies Tsn Mcn (w,1) , T T T sn−1 Mcn−1 (cn ,1) ,... s1 Mc1 (c2 ,1) , sv Mv (c1 ,k) such that (1) sv ∈ τ (I Rv ) (2) ∀i such that 1 ≤ i ≤ n : si ∈ T Sdef ci , where, ci is a buffer and T T ¯ (3) [¯ a] → [b] ∈ sn Mcn (w,1) ◦ sn−1 Mcn−1 (cn ,1) ◦ · · · ◦ Ts1 Mc1 (c2 ,1) ◦ Tsv Mv (c1 ,k) }

T

Note that, for given arrays v and w, several chains of possibly different 0 lengths may exist. The mapping T Mv (w,k) is the union of the mappings defined by each separate chain. Also, the code is in single-assignment, hence each chain defines a distinct set of elements in the mapping. Now the verification condition can be stated as: each array dependency between a defined variable v and k th operand wk in a statement class I Rv must also occur in the array dependencies of the statements τ (I Rv ) of the transformed program. Formally, let ORv denote the number of operands and wk denote the k th operand of the (equivalent) statements in I Rv , then: ∀v ∈ I Vdef , ∀I Rv ∈ π(I Sdef v ), ∀k such that 1 ≤ k ≤ ORv it holds that:

[

∀i∈

I

I i Mv (wk ,k)



T

0

Mv (wk ,k)

Rv

Theorem 5.4 Let I and T be a pair of single assignment programs for which the verification condition holds. If array element z[i1 ] . . . [in ] is assigned a value v in I then it is assigned the same value v in T also. Proof Sketch. For each element z[i1 ] . . . [in ], the value v assigned to it in I is given by a function f (u1 [. . .], . . . , um [. . .]). The mapping I Mz ui identifies the element of ui [. . .] that serves as ith input to f . In T , the value v assigned to it 0 is given by f (u01 [. . .], . . . , u0m [. . .]). The mapping T Mz ui identifies the element ui [. . .] that is at the origin of the value of u0i [. . .] and hence serves as ith input to f in T . The verification condition ensures that it is the same element. As this holds for all arguments of f , the value computed by f is also the same.2 It is desirable to verify also that the transformed program does not define more array elements than the initial. An inexpensive check, that should be done before testing the above verification condition, is to verify that the definition domains in the initial and transformed program are the same for all arrays, i.e., ∀ v ∈ I Vdef : [ [ T def I def = D j Dv v i T def I def ∀ j ∈ Sv ∀ i ∈ Sv Example 5.5 To illustrate the technique, we verify in the example of Figure 1 11

Shashidhar et al

the defined-operand variable pair (B, A) of statement 2 in I. The iteration domain is: I2 Diter := { [i, k] | 0 ≤ i ≤ 9 ∧ 0 ≤ k ≤ 7 ∧ [i, k] ∈ Z2 } Let C0 := ( a4 = i ∧ a5 = k + 1 ∧ a3 = i ∗ 4 + k ∧ [i, k] ∈ I2 Diter ) The array dependency between B and A is given by: IM 2 B (A,2) := { [a4 , a5 ] → [a3 ] | C0 } The function τ maps statement 2 in I to the statements 40 and 50 of T . But, array A is replaced by buf, which is defined in statements 20 and 30 in T . Hence, the array dependency between buf and A in the statements 20 and 30 has to be used. Statement 20 of T has the iteration domain: T Diter := { [j] | 0 ≤ j ≤ 3 ∧ [j] ∈ Z} 20 The following constraint will be used in its dependency mapping: C2 := ( a1 = 0 ∧ a2 = j ∧ a3 = j ∧ [j] ∈ T20 Diter ) For statement 30 , iteration domain and the constraint are respectively: T Diter := { [i, j] | 0 ≤ i ≤ 9 ∧ 0 ≤ j ≤ 3 ∧ [i, j] ∈ Z2 } and 30 C3 := ( a1 = 10 − i ∧ a2 = j ∧ a3 = 4 ∗ (10 − i) + j ∧ [i, j] ∈ T30 Diter ) Resulting dependency mappings are: TM TM 20 30 buf (A,1) := { [a1 , a2 ] → [a3 ] | C2 }; buf (A,1) := { [a1 , a2 ] → [a3 ] | C3 } For statement 40 , iteration domain and the constraint are respectively: T Diter := { [i, k] | 0 ≤ i ≤ 9 ∧ 0 ≤ k ≤ 3 ∧ [i, k] ∈ Z2 } 40 C4 := ( a4 = 9 − i ∧ a5 = k + 1 ∧ a1 = 9 − i ∧ a2 = k ∧ [i, k] ∈ T40 Diter ) Finally, for statement 50 iteration domain and the constraint are respectively: T Diter := { [i, k] | 0 ≤ i ≤ 9 ∧ 4 ≤ k ≤ 7 ∧ [i, k] ∈ Z2 } 50 C5 := ( a4 = 9 − i ∧ a5 = 12 − k ∧ a1 = 10 − i ∧ a2 = 7 − k ∧ [i, k] ∈ T50 Diter ) Resulting dependency mappings are: TM TM 40 50 B (buf,2) := { [a4 , a5 ] → [a1 , a2 ] | C4 }; B (buf,2) := { [a4 , a5 ] → [a1 , a2 ] | C5 } We have that: TM T T buf (A,1) := 20 Mbuf (A,1) ∪ 30 Mbuf (A,1) := { [a1 , a2 ] → [a3 ] | C2 ∨ C3 } and T MB (buf,2) := T40 MB (buf,2) ∪ T50 MB (buf,2) := { [a4 , a5 ] → [a1 , a2 ] | C4 ∨ C5 } Hence the array dependencies in the transformed program are: T M0 T T B (A,2) := Mbuf (A,1) ◦ 50 MB (buf,2) := { [a4 , a5 ] → [a3 ] | (C2 ∨ C3 ) ∧ (C4 ∨ C5 ) } Define: C1 := ((C2 ∨ C3 ) ∧ (C4 ∨ C5 )) Now, the verification condition is satisfied when: IM 2 B (A,2)

0

− T MB (A,2) := { [a4 , a5 ] → [a3 ] | C0 ∧ ¬C1 } = φ

This can be verified with the Omega test framework [17].

Complexity and Experience. The condition checks as described above evaluates the validity of the constraints and the best known upper bound for determining validity in Prespn 22 burger arithmetic is 2 on the length of the formula [14], where p > 1 is some constant. The Omega test framework [17] based on Fourier-Motzkin variable elimination and a host of other heuristics provides an integer programming solver for the Presburger arithmetic which is very efficient in practice. 12

Shashidhar et al

This has prompted us to use the Omega calculator [11] to perform the condition checks on our domains and mappings. The mappings that we check are taken separately for each definition-operand variable pairs and hence, the length of the formula depends solely on the size of the statement classes and in all practical cases, the problem size remains reasonable. On implementations of real life multimedia applications viz., H.263 video decoder, Mpeg-4 motion estimation, voice coder etc., with many complex nested loops and multi-dimensional arrays, the checks on transformations have been shown to be possible within a matter of seconds in prior work. In the past, both testing and manual paper-and-pencil based checking had taken unreasonable amount of time and yet without guarantee of correctness. We are presently building a tool to integrate calls to the geometrical model extractor and the Omega calculator and coordinate all the checks and provide precise error location information to the user. Error Diagnosis. A successful verification implies that initial and final program are equivalent. Failure indicates either a genuine error or that the transformation is beyond the assumptions about the syntactical correspondence between initial and transformed program, e.g. that functions in right hand side of statements have been modified or that operations other than plain copy operations are used when filling the buffer arrays. If a condition does not hold it means that some points are missing in the domain or the mapping in question. Since our condition checks are made by calculating the differences of domains for each variable or mappings for each variable pair separately for each statement class, the resulting non-empty set of points gives enough information about the location of the errors. The variable or the variable pair in question and the missing range of index values is sufficient to direct the designer to the part of the code under an erroneous transformation. This is a very useful property of the presented technique.

6

Conclusions

Correctness checking is a complex problem which manifests itself in many contexts in varied forms eluding a general solution, hence it is important to explore every avenue of entry available to tackle the problem. In this paper, we have presented an approach that provides one such avenue. The main idea is to use static program analysis to extract the geometric model on which equivalence conditions can be checked for correctness of loop and data reuse transformations. In this sense, the approach presents a demonstrably useful geometric model checking technique. The equivalence checking technique has wide applicability in the context of source-to-source program transformations and in particular, has been very applicable in our inhouse system design activities. 13

Shashidhar et al

In future work, we will investigate the feasibility of the approach on benchmark applications, with respect to the assumptions that have been made. In general, the full theoretical power of the geometrical model in abstracting the program behavior and it’s ultimate limitations in solving transformation verification problems need to be studied. ˇ ak Acknowledgements. The authors thank Eddy De Greef and Miroslav Cup´ for useful discussions during the course of the presented work.

References [1] Angelo, C., Formal Hardware Verification in a Silicon Compilation Environment by means of Theorem Proving. PhD Thesis, KU Leuven, Belgium. 1994. [2] Banerjee, U., Loop Transformations for Restructuring Compilers: The Foundations. Kluwer Academic Publishers. 1993. [3] Banerjee, U., Loop Parallelization. Kluwer Academic Publishers. 1994. [4] Bultan, T., R. Gerber, and W. Pugh, Symbolic Model Checking of Infinite State Systems Using Presburger Arithmetic. Proc. 9th Intl. Conf. on Computer Aided Verification (CAV), Israel. Orna Grumberg, ed., pp. 400-411, LNCS 1254. Springer-Verlag. 1997. [5] Catthoor, F., S. Wuytack, E. de Greef, F. Balasa, L. Nachtergaele, and A. Vandecappelle, Custom Memory Management Methodology - Exploration of Memory Organization for Embedded Multimedia System Design. Kluwer Academic Publishers. 1998. [6] Claesen, L., M. Genoe, E. Verlind, F. Proesmans, and H. de Man. SFGTracing: A Methodology of Design for Verifiability. In Correct Hardware Design Methodologies, P. Prinetto and P. Camurati, eds., pp. 187-202, North-Holland. 1992. [7] Cousot, P., and R. Cousot, Verification of Embedded Software: Problems and Perspectives. Proc. of the 1st Intl. Workshop on Embedded Software (EMSOFT), USA. pp. 97-113, LNCS 2211. 2001. ˇ ak, M., F. Catthoor, and H. de Man, Efficient functional validation of [8] Cup´ system level loop transformations for multimedia applications. Proc. of 3rd Intl. Workshop on High Level Design Validation and Test (HLDVT), USA. pp. 72-79. 1998. [9] Feautrier, P., Dataflow analysis of array and scalar references. International Journal of Parallel Programming, 20(1):23-53. 1991. [10] Goos, G., Issues in Compiling. Journal of UCS, 7(5):410-419. Springer. 2001.

14

Shashidhar et al

[11] Kelly, W., V. Maslov, W. Pugh, E. Rosser, T. Shpeisman, D. Wonnacott, The Omega Calculator and Library, Version 1.1.0. 1996. Available from: url: http://www.cs.umd.edu/projects/omega [12] Middelhoek, P. F. A., and S. P. Rajan, From VHDL to efficient and first-timeright designs: a formal approach. ACM TODAES, 1(2):205 - 250. 1996. [13] Necula, G. C., Translation Validation for an Optimizing Compiler. Proc. of the ACM Conf. on Programming Language Design and Implementation (PLDI), Canada. pp. 83-95. 2000. 2pn

[14] Oppen, D., A 22 upper bound on the complexity of presburger arithmetic. Journal of Computer and System Sciences, 16(3):323-332. 1978. [15] Pnueli, A., M. Siegel, and O. Shtrichman, Translation Validation: From SIGNAL to C. In Correct System Design, E.-R. Olderog and B. Steffen, eds., pp. 231-255, LNCS 1710. Springer-Verlag. 1999. [16] Pandya, P., A. Pnueli, and L. Zuck, Translation Validation of Optimizing Compilers by Computational Induction. Tech. Rep., Courant Institute of Mathematical Sciences, New York University, USA. 2000. [17] Pugh, W., The Omega test: a fast and practical integer programming algorithm for dependence analysis. Communications of the ACM, 35(8):102-114. 1992. [18] Quiller´e, F., and S. Rajopadhye, Optimizing memory usage in the polyhedral model. ACM TOPLAS, 22(5):773-815. 2000. [19] Ramalingam, G., and T. Reps, Semantics of program representation graphs. Tech. Rep., TR-900, CS Dept., University of Wisconsin-Madison, USA. 1989. [20] Samsom, H., L. Claesen, and H. de Man, SynGuide: An environment for doing interactive correctness preserving transformations. In VLSI Signal Processing VI, L. Eggermont et. al., eds., pp. 269-277, IEEE Press. 1993. [21] Samsom, H., F. Franssen, F. Catthoor, and H. de Man, System level verification of video and image processing specifications. Proc. of the 8th Intl. Symp. on System Synthesis (ISSS), USA. pp. 144-149. 1995. [22] Thiele, L., and U. Arzt, On the synthesis of massively parallel architectures. International Journal of High Speed Electronics, 2(4):99-131. 1993. [23] Tsichritzis, D., The Equivalence Problem of Simple Programs. Journal of the ACM, 17(4):729-738. 1970. [24] van Aelten, F., J. Allen, and S. Devadas, Event-Based Verification of Synchronous, Globally Controlled, Logic Designs Against Signal Flow Graphs. IEEE Trans. on CAD of Integrated Circuits and Systems, 13(1):122-134. 1994. [25] Wolf, M. E., and M. S. Lam, A Loop Transformation Theory and an Algorithm to Maximize Parallelism. IEEE Trans. on Parallel and Distributed Systems, 2(4):452-471. 1991.

15

Shashidhar et al

[26] Wu, W., and A. Jantsch, A Survey of Design Transformation Techniques. Tech. Rep., Department of Electronics, Royal Institute of Technology, Sweden. 1999. [27] Yang, W., S. Horwitz, and T. Reps, Detecting program components with equivalent behaviors. Tech. Rep., TR-840, CS Dept., University of WisconsinMadison, USA. 1989.

16

Geometric Model Checking: An Automatic Verification ...

based embedded systems design, where the initial program is subject to a series of transformations to .... It is required to check that the use of the definition and operand variables in the ..... used when filling the buffer arrays. If a condition does ...

254KB Sizes 1 Downloads 300 Views

Recommend Documents

Model Checking
where v1, v2, . . . . v represents the current state and v., v, ..., v, represents the next state. By converting this ... one register is eventually equal to the sum of the values in two other registers. In such ... atomic proposition names. .... If

Regular Model Checking
sets of states and the transition relation are represented by regular sets. Major ... [C] Ahmed Bouajjani, Bengt Jonsson, Marcus Nilsson, and Tayssir Touili. Regu- lar model checking. In Proc. 12th Int. Conf. on Computer Aided Verification, ..... hav

An Automatic Verification Technique for Loop and Data ...
tion/fission/splitting, merging/folding/fusion, strip-mining/tiling, unrolling are other important ... information about the data and control flow in the program. We use ...

Model Checking-Based Genetic Programming with an Application to ...
ing for providing the fitness function has the advantage over testing that all the executions ...... In: Computer Performance Evaluation / TOOLS 2002, 200–204. 6.

Automatic Verification of Algebraic Transformations
restructuring transformations are called global data-flow transformations. In our earlier work [2], we have presented an intra- procedural method for showing the ...

automatic pronunciation verification - Research at Google
Further, a lexicon recorded by experts may not cover all the .... rently containing interested words are covered. 2. ... All other utterances can be safely discarded.

Functional Equivalence Checking for Verification of ...
for equivalence checking tools similar to the ones available for comparing digital circuits. ..... extracted data-flow can be represented in the form of an ar- ray data ...

Functional Equivalence Checking for Verification of ...
sis (RTL-level and below) has been very successfully addressed by equivalence checking methods. But to emulate this success in software synthesis, given that.

Parameterized Model Checking of Fine Grained Concurrency
implementation of multi-threaded programs. Their efficiency is achieved by using .... Unbounded threads: We show how concurrent list based set data structures.

Model Checking Hw-Hume
School of Mathematical and Computer Sciences ... thesis has not been submitted for any other degree. .... 4.6.2 Variable Declaration . ... 4.8.2 Output Streams . ...... PROMELA translator was also created at Heriot-Watt University the same year.

Model Checking Secondary Relations
be put to use to query mildly context-sensitive secondary relations with ... mally considered a powerful query language, is too weak to capture these phenom-.

A primer on model checking
Software systems for model checking have become a cornerstone of both ..... Aside from the standard features of an environment (file handling, editing and ...

Size Matters: Exhaustive Geometric Verification ... - Research at Google
large databases while extracting the data needed for geometric verification for all remaining .... identifier of the least-advanced posting lists and its index, but also how many ..... with applications to image analysis and automated cartography.

Verification of Model Processing Tools1
the consequences of their choices. Such tools include model-checking engines for verifying logical properties of the software, schedulability analysis tools that ...

Verification of Model Processing Tools1
three broad approaches are used: translator verification, translation validation and ... and by combining ideas from static/dynamic analysis and model-checking.

Verification of Model Processing Tools1
Each stage of software development de- mands different abstractions, and accordingly, MBD pro- vides different languages tailored for the idiosyncrasies.

Verification of Model Processing Tools1
plexity of software requires the use of methodologies such .... graph transformation rules, and techniques such as Clas- ..... Generating test data with enhanced.

8.1 Model building, verification, and validation - WordPress.com
UNIT – 8: VERIFICATION AND VALIDATION OF SIMULATION MODELS, OPTIMIZATION: Model building, verification and validation; Verification of simulation models; Calibration and validation ... D. The simulation can be temporarily suspended, or paused, not

efficient automatic verification of loop and data-flow ...
and transformations that is common in the domain of digital signal pro- cessing and ... check, it generates feedback on the possible locations of errors in the program. ...... statements and for-loops as the only available constructs to specify the.

Statistical Model Checking for Cyber-Physical Systems
The autopilot is a software which provides inputs to the aircraft's engines and flight control surfaces (e.g., ..... Therefore, instead of try- ing to come up with the optimal density, it may be preferable to search in a ..... optimization. Methodolo

Bayesian Statistical Model Checking with Application to ...
Jan 13, 2010 - discrete-time hybrid system models in Stateflow/Simulink: a fuel control system .... Formally, we start with a definition of a deterministic automaton. ...... demos.html?file=/products/demos/shipping/simulink/sldemo fuelsys.html .