1.2 Our approach to compilation
1.2.4 The semantics of the reasoning language
We have already mentioned that the correctness results from the algebraic compilation technique may be invalidated by the introduction of an incorrect axiom in the set of algebraic laws the compiler is based on. In this thesis we address this possible problem by means of providing a denotational semantics model for the reasoning language that we use to prove the validity and consistency of the axioms used in the compiler.
The goal is to provide a semantic framework in which it is possible to reason about synchro- nous, parallel programs with shared-variables. As there are several existing hardware description languages with most or all the features required, our initial intention was to try to apply the same mathematical domain used in their semantics as the semantic framework for our work. Perhaps the most widely used hardware description language is VHDL [Ashenden 1999]. There are several operational [Goossens 1995; Nicola and Hennessy 1984; De Nicola and Pugliese 1994], denota- tional [Breuer et al. 1994b;a] and logical [Breuer et al. 1995] semantic models for it. The standard defining VHDL [IEEE 1993] informally describes the meaning of all the language’s constructs by means of the effect they have over an interpreter (i.e., the standard describes the simulation semantics for the language). Unfortunately, all the semantic models mentioned above follow this interpreter-based approach, making all of them unsuitable for proving the kind of algebraic laws needed for our compiler. Furthermore, VHDL is a language meant to give the designer a great deal of control over the hardware being generated. From the language perspective, this means the constructs tend to reflect the hardware structure rather than the kind of high-level program- ming features we are interested in our input and reasoning languages (e.g. selection, assignment, sequential composition, iteration, etc.).
Occam [Barrett 1992] is a higher-level language that can be used to generate hardware. Deno- tational semantics based on the failures-divergences model [Roscoe 1997] have been proposed for the language [Roscoe 1985; Roscoe et al. 1993]. In addition to these, an axiomatic characterisation of the language was proposed in [Roscoe and Hoare 1988], together with a proof of equivalence between this and its denotational semantics. Even though this semantic approach seems to be more in line with our needs, there are two main drawbacks if we were to use this denotational model as the foundation for our reasoning language: (a) the lack of explicit representation of time; and (b) the fact that variables cannot be shared among parallel processes. Furthermore, a direct consequence of observation (b) is that there is no need for synchronisation as a mechanism to keep variables consistent among parallel processes.
Handel-C, on the other hand, presents all the features we are interested in, and its underlying synchronicity forces any semantic model for the language to account for the clock-cycle-based timing structure of all constructs. Several operational [Butterfield 2001; Butterfield and Woodcock 2002; 2005b] and denotational [Butterfield and Woodcock 2005a; Butterfield 2007; Butterfield et al. 2007; Perna and Woodcock 2007] semantic models have been proposed for Handel-C. In all of these works, the semantics are represented in terms of sequences indexed by clock-cycle where each element in the sequence is a collection of sub-atomic events describing the steps the hardware carries out to compute and store results. Unfortunately, this “operational” nature of the semantics
incorporates too many implementation details, hindering the possibility of performing any of the proofs about the reasoning language we intend to conduct.
Given the fact that the existing semantics for HDLs did not provide us with the kind of semantic domain we need for our work, we considered two additional formalisms as possible semantic domains: Higher-Order Logic (HOL) [Gordon and Melham 1993] and the weakest precondition (wp) calculus [Dijkstra 1975; 1976]. In the case of HOL, it has been extensively used in the specification, generation and verification of hardware components [Melham 1993; Iyoda 2007; Berghofer and Strecker 2003; Klein and Nipkow 2003], and in the verification of HDLs themselves [Boulton et al. 1993; Perna and Woodcock 2008]. However, HOL only offers very basic direct support for programming constructs [Norrish and Slind 2007, Chapter 2] like the ones required in our context and this will force us to define a whole theory of programming within HOL. This is not a good choice for us as there are other alternatives where there is existing support for most of the programming constructs we want to include in our framework.
On the other hand, our reason for considering the wp-calculus lies in the fact that it was used as the semantic foundation for an algebraic compiler for an object-oriented language [Cavalcanti and Naumann 2000; Duran et al. 2001]. The main limitation we observe over the wp-calculus as the semantic framework for our work is its poor integration with other theories within the same semantic domain. For example, one of the possible extensions of our work is to include pointers in our input language. In these regards, we would like to have a way of linking our semantics with a theory of pointers rather than having to re-formulate the entire semantic framework.
In the light of the observations and weaknesses with all the approaches mentioned above, we selected the Unifying Theories of Programming (UTP) [Hoare and He 1998] as the semantic domain for our reasoning language. Our choice for the UTP is mainly based in two factors. Firstly, the UTP provides definitions for all the operators needed in our work. In this way, theories in the UTP do not need to re-define them: they only need to show the operators are closed in the theory (i.e., the result of combining constructs in the theory is itself within the theory). This means that even if we define a new theory for our context (as we do in Chapter 3), we only need to analyse how the programming operators behave under the conditions imposed by the new theory. Secondly, all programming constructs are defined as predicates and a single notion of refinement is used across all theories (i.e., reverse logical implication under universal closure over all known variables). This makes each of the UTP theories a lattice [Davey and Priestley 2002] and it is possible to establish links among them by means of Galois connections [Erne et al. 1992]. This is one of the key aspects of the UTP as it allows an easy integration and exchange of results between different theories and programming paradigms.
Within the UTP, our initial intention was to use the theory of designs (see Chapter 2) as the semantic domain for our reasoning framework since it contains all the features required in our context together with a comprehensive set of algebraic laws that are of great advantage for our reasoning language. While trying to prove additional laws needed in our context, we discovered a series of limitations that hindered the usability of the design theory as the semantic foundation for our reasoning framework. This is mainly related with assertional reasoning after clock-cycle boundaries. We solve this and other problems by restricting the theory of designs with additional
conditions that allow the kind of assertional reasoning we need for synchronous, parallel programs with shared variables. We use this new theory of synchronous designs (see Chapter 3) not only as the semantic domain to prove the laws in the reasoning language, but also to give semantics to Handel-C (described in Chapter 4) which is in line with the needs of our work.