3
Ruby as a basis for hardware/software codesign Mary Sheeran (Chalmers Technical University, Sweden) Satnam Singh (Glasgow University, Scotland) Ruby is a language of relations and functions intended for use in the design of hardware by refinement. An initial formal specification (written in Ruby) describes the required behaviour as a relation on streams of data values. The streams rep- resent signals or sequences of values over time, so that behaviour over time can be described. A refinement step transforms the specification into another Ruby program representing a network of components, each of which can later be refined separately. The ways in which components are connected together are represented by special structuring functions or combinators, some of which are shown in figure 1. So Ruby describes both structure and behaviour at the same time. -"- -El- -++ Figure 1: R; S and [R, SI and col3 T The combinators obey algebraic laws which allow programs to be transformed without affecting the overall behaviour. Space-time tradeoffs can, for instance, be explored in this way. After a refinement step, the new program is externally behaviourally equivalent to the old, but details of data representation or timing behaviour may have been added. An abstract number in the specification might be refined to a bit-serial least- significant-bit-first binary number. This choice must be precisely documented by introducing the corresponding abstraction relation into the program (which can then manipulate the concrete values). We are convinced that such abstraction relations must be able to capture timing information, so it makes sense to describe them in Ruby too. Then, they can be manipulated, transformed and 'pushed around' in Ruby programs, just like any other component. In the context of signal processing, we have found that much of design revolves around this combined data and timing abstraction. It is the ease of dealing with abstraction that has convinced US to continue to use relational rather than functional circuit descriptions. The refinement process stops when each component has a direct implementation in hardware. In this approach, verification and design are done simultaneously; only verified transformations are applied, so there is no need for a post-hoc check that the final design meets its specification. We have long argued that if formal methods are to be used in practice, they must be incorporated early in the design process. A transformation assistant for Ruby has been developed at the Danish Technical University and Luk and others have developed tools to support the use of Ruby in

[IEE IEE Colloquium on `Verification of Hardware Software Codesign' - London, UK (17 Oct. 1995)] IEE Colloquium on `Verification of Hardware Software Codesign' - Ruby as a basis for

  • Upload
    m

  • View
    212

  • Download
    0

Embed Size (px)

Citation preview

Page 1: [IEE IEE Colloquium on `Verification of Hardware Software Codesign' - London, UK (17 Oct. 1995)] IEE Colloquium on `Verification of Hardware Software Codesign' - Ruby as a basis for

Ruby as a basis for hardware/software codesign

Mary Sheeran (Chalmers Technical University, Sweden) Satnam Singh (Glasgow University, Scotland)

Ruby is a language of relations and functions intended for use in the design of hardware by refinement. An initial formal specification (written in Ruby) describes the required behaviour as a relation on streams of data values. The streams rep- resent signals or sequences of values over time, so that behaviour over time can be described. A refinement step transforms the specification into another Ruby program representing a network of components, each of which can later be refined separately. The ways in which components are connected together are represented by special structuring functions or combinators, some of which are shown in figure 1. So Ruby describes both structure and behaviour a t the same time.

-"- -El- -++ Figure 1: R; S and [R, SI and col3 T

The combinators obey algebraic laws which allow programs to be transformed without affecting the overall behaviour. Space-time tradeoffs can, for instance, be explored in this way.

After a refinement step, the new program is externally behaviourally equivalent to the old, but details of data representation or timing behaviour may have been added. An abstract number in the specification might be refined to a bit-serial least- significant-bit-first binary number. This choice must be precisely documented by introducing the corresponding abstraction relation into the program (which can then manipulate the concrete values). We are convinced that such abstraction relations must be able to capture timing information, so it makes sense to describe them in Ruby too. Then, they can be manipulated, transformed and 'pushed around' in Ruby programs, just like any other component. In the context of signal processing, we have found that much of design revolves around this combined data and timing abstraction. It is the ease of dealing with abstraction that has convinced US t o continue to use relational rather than functional circuit descriptions.

The refinement process stops when each component has a direct implementation in hardware. In this approach, verification and design are done simultaneously; only verified transformations are applied, so there is no need for a post-hoc check that the final design meets its specification. We have long argued that if formal methods are to be used in practice, they must be incorporated early in the design process. A transformation assistant for Ruby has been developed at the Danish Technical University and Luk and others have developed tools to support the use of Ruby in

Page 2: [IEE IEE Colloquium on `Verification of Hardware Software Codesign' - London, UK (17 Oct. 1995)] IEE Colloquium on `Verification of Hardware Software Codesign' - Ruby as a basis for

regular array design. We hope to interface the Ruby compiler described below to a designer’s assistant based on the Alf proof checker [l].

Ruby has been shown to be a successful hardware design language, particularly in the area of regular array circuits. Here, we consider using Ruby in the much wider field of hardwareJsoftware codesign. In codesign, the ability to describe behaviour at varying levels of abstraction and to refine behaviour and investigate the effects of that refinement is even more important than in straight hardware design. For this reason, we believe that a style of verification in which each refinement step is checked individually is most appropriate. It is important to capture errors as early as possible in the design and in any case post-hoc verification is likely to be unwieldy and time-consuming for the kinds of complex system that will be built as codesigns.

One must provide good support for partitioning a design into communicating components, for investigating a number of different partitions and for varying the choice of which components to implement in hardware and which in software. Ruby fits well with these requirements. 3 u t is i t sufficient to describe software, hardware, and the interfaces between them? Our answer to this is a tentative yes. To describe the software components, we use a limited form of (lazy) functional programming, in which programs are constructed from existing components using Ruby-style com- binators. (This is a form of functional programming that is advocated by Hughes and others at Chalmers [Z]). Ruby programs can be seen as static networks of func- tional components. To describe software, we must be able to cope with dynamically varying networks of functions, that is functional programs.

It is tempting to use an unconstrained Eunctional program as an initial speci- fication but we would like to investigate a more restrictive approach in which the initial specification is written in Ruby and so is more hardware-like. This would al- low us to use partitioning and abstraction in Ruby style. We are, as always, trading off simplicity and expressive power. Only experience with real designs will tell u5 where the best compromise lies. We shouId stress that this work is only beginning. The project to make a Postscript engine (described below) will be a good test of our ideas.

In functional programming, many interesting program analyses based on ab- stract and non-standard interpretation have already been developed. Analyses have been developed for symbolic evaluation, critical path analysis, and for producing testability information. These systematic analyses give important information that can be used to guide refinement steps and to perform space/time trade-offs for both hardware and software. Recent work on a novel type system for the analysis of functional programs should be directly relevant here [3].

We believe our system is particularly suitable for a special case of hardware- /software eo-design where the software executes on a personal computer and the hardware executes on a reconfigurable logic board connected to the main processor over a fast bus. The emergence of Field Programmable Gate Arrays (FPGAs) makes general purpose accelerator cards possible. Most FPGA chips contain a regular grid of cells which can be rapidly reprogrammed. In some architectures, each cell can be memory mapped into the address space of the processor, allowing very flexible communication between the software and hardware components. Several vendors offer such cards.

We have developed a compiler for our version of the Ruby language. The system currently targets the new Xilinx XC6200 FPGAs. The compiler preserves Ruby layout information, and so gives highly compact and regular layouts on FPGAs. Experience has shown that Ruby descriptions allow the limited resource available on FPGAs to be more aggressively exploited that by techniques based on behavioural synthesis of VHDL descriptions.

The compiler can also translate Ruby descriptions into VHDL or the lazy func-

5 / 2

Page 3: [IEE IEE Colloquium on `Verification of Hardware Software Codesign' - London, UK (17 Oct. 1995)] IEE Colloquium on `Verification of Hardware Software Codesign' - Ruby as a basis for

tional programming language Haskell. A C code generator is also planned. The objective is to allow a Ruby description to be partitioned into a hardware subset which is realised as an FPGA design and software subset (compiled Haskell or C programs). The FPGA designs will be programmed onto an FPGA card connected to the host system via a PCI bus. The Ruby system will also generate the code needed to communicate with a run-time system which manages the FPGA resource. This architecture is designed to support applications whose compute intensive por- tions (e.g. inner loops) can be programmed onto the FPGA hardware, whilst the remainder of the system executes in software.

Often when one wants to transfer some set of calculations from software to hardware, there is insufficient hardware resource available. This is especially true for FPGA chips, which typically have 64x64 cells. However, it is possible to draw inspiration from virtual memory techniques here. If the design can be partitioned into sub-circuits which are temporally cohesive, then they can be ‘swapped’ into the FPGA resource only when they are needed. The Postscript system that we describe is a good example of this. There are several circuits for rendering graphics e.g. line drawing and circle drawing circuits. However, at any given instant, there is probably only need for a t most one line drawing circuit or one circle drawing circuit to be actually present in the FPGA chips. The designs can be stored as programming information in the system’s main memory, or on a static RAM cache on the FPGA card. When a line needs to be drawn, the FPGA is rapidly reconfigured. The reconfiguration overhead is recovered if the circuit is executed hundreds of times (which is the case for graphics circuits). At a later stage, a circle may have to be drawn, in which case the the line circuit is ‘swapped out’ and the circle circuit is ‘swapped in’. We call this use of FPGAs virtual hardware.

Note We have not included references to Ruby papers in this summary. We refer the interested reader to the Ruby page on the World Wide Web: http://www.comla b.0x.ac.u k/oucl/users/geraint.jones/ruby/

References [I] Thierry Coquand et al, Type Theory and Programming, EATCS Bulletin, no.

52, February 1994.

[2] John Hughes, Why Functional Programming Matters, in The Computer Jour- nal, Vol. 32, Number 2, April 1989.

[3] John Hughes, Lars Pareto and Amr Sabry, Proving the Correctness of Re- active Systems using Sized Types, to appear in Int. Conf. on Principles of Programming Languages, 1996.

5/3