Programming language

System, method and article of manufacture for signal constructs in a programming language capable of programming hardware architectures

6691301

Abstract

A system, method and article of manufacture are provided for using a dynamic object in a programming language. In general, an object is defined with an associated first value and second value. The first value is used in association with the object during a predetermined clock cycle. The second value is used in association with the object before or after the predetermined clock cycle.


Claims

What is claimed is:

1. A method for using a dynamic object in a programming language, comprising the steps of:

(a) defining an object with an associated first value and second value;

(b) using the first value in association with the object during a predetermined clock cycle; and

(c) using the second value in association with the object before or after the predetermined clock cycle.

2. A method as recited in claim 1, wherein the object is used to split up an expression into sub-expressions.

3. A method as recited in claim 2, wherein the sub-expressions are reused.

4. A method as recited in claim 1, wherein the first value is assigned to and read from the object during the predetermined clock cycle.

5. A method as recited in claim 1, wherein the programming language is adapted for programming a gate array.

6. A method as recited in claim 1, wherein the programming language includes Handel-C.

7. A computer program product for using a dynamic object in a programming language, comprising:

(a) computer code for defining an object with an associated first value and second value;

(b) computer code for using the first value in association with the object during a predetermined clock cycle; and

(c) computer code for using the second value in association with the object before or after the predetermined clock cycle.

8. A computer program product as recited in claim 7, wherein the object is used to split up an expression into sub-expressions.

9. A computer program product as recited in claim 8, wherein the sub-expressions are reused.

10. A computer program product as recited in claim 7, wherein the first value is assigned to and read from the object during the predetermined clock cycle.

11. A computer program product as recited in claim 7, wherein the programming language is adapted for programming a gate array.

12. A computer program product as recited in claim 7, wherein the programming language includes Handel-C.

13. A system for using a dynamic object in a programming language, comprising:

(a) logic for defining an object with an associated first value and second value;

(b) logic for using the first value in association with the object during a predetermined clock cycle; and

(c) logic for using the second value in association with the object before or after the predetermined clock cycle.

14. A system as recited in claim 13, wherein the object is used to split up an expression into sub-expressions.

15. A system as recited in claim 14, wherein the sub-expressions are reused.

16. A system as recited in claim 13, wherein the first value is assigned to and read from the object during the predetermined clock cycle.

17. A system as recited in claim 13, wherein the programming language is adapted for programming a gate array.

18. A system as recited in claim 13, wherein the programming language includes Handel-C.


Description

FIELD OF THE INVENTION

The present invention relates to programmable hardware architectures and more particularly to programming field programmable gate arrays (FPGA's).

BACKGROUND OF THE INVENTION

It is well known that software-controlled machines provide great flexibility in that they can be adapted to many different desired purposes by the use of suitable software. As well as being used in the familiar general purpose computers, software-controlled processors are now used in many products such as cars, telephones and other domestic products, where they are known as embedded systems.

However, for a given function, a software-controlled processor is usually slower than hardware dedicated to that function. A way of overcoming this problem is to use a special software-controlled processor such as a RISC processor which can be made to function more quickly for limited purposes by having its parameters (for instance size, instruction set etc.) tailored to the desired functionality.

Where hardware is used, though, although it increases the speed of operation, it lacks flexibility and, for instance, although it may be suitable for the task for which it was designed it may not be suitable for a modified version of that task which is desired later. It is now possible to form the hardware on reconfigurable logic circuits, such as Field Programmable Gate Arrays (FPGA's) which are logic circuits which can be repeatedly reconfigured in different ways. Thus they provide the speed advantages of dedicated hardware, with some degree of flexibility for later updating or multiple functionality.

In general, though, it can be seen that designers face a problem in finding the right balance between speed and generality. They can build versatile chips which will be software controlled and thus perform many different functions relatively slowly, or they can devise application-specific chips that do only a limited set of tasks but do them much more quickly.

SUMMARY OF THE INVENTION

A system, method and article of manufacture are provided for using a dynamic object in a programming language. In general, an object is defined with an associated first value and second value. The first value is used in association with the object during a predetermined clock cycle. The second value is used in association with the object before or after the predetermined clock cycle.

In an aspect of the present invention, the object may be used to split up an expression into sub-expressions. As an option, the sub-expressions may be reused. In another aspect, the first value may be assigned to and read from the object during the predetermined clock cycle. In a further aspect, the programming language may be adapted for programming a gate array. As an option, the programming language may include Handel-C.

BRIEF DESCRIPTION OF THE DRAWINGS

The invention may be better understood when consideration is given to the following detailed description thereof. Such description makes reference to the annexed drawings wherein:

FIG. 1 is a schematic diagram of a hardware implementation of one embodiment of the present invention;

FIG. 2 illustrates a design flow overview, in accordance with one embodiment of the present invention;

FIG. 3 illustrates the Handel-C development environment, in accordance with one embodiment of the present invention;

FIG. 4 illustrates a graphical user interface shown if one starts the program with an empty workspace;

FIG. 5 illustrates a graphical user interface used to create a project, in accordance with one embodiment of the present invention;

FIG. 6 illustrates the various types of new projects, in accordance with one embodiment of the present invention;

FIG. 7 illustrates a breakpoint, in accordance with one embodiment of the present invention;

FIG. 8 illustrates a project settings interface, in accordance with one embodiment of the present invention;

FIGS. 9A, 9B, and 9C illustrate available settings;

FIG. 10 illustrates a configurations graphical user interface, in accordance with one embodiment of the present invention;

FIG. 11 illustrates a file view interface, in accordance with one embodiment of the present invention;

FIG. 12 illustrates a file properties, in accordance with one embodiment of the present invention;

FIG. 13 illustrates a workspace interface and the associated icons, in accordance with one embodiment of the present invention;

FIG. 14 illustrates a version test interface, in accordance with one embodiment of the present invention;

FIG. 15 illustrate a browse and associated results interface, in accordance with one embodiment of the present invention;

FIGS. 16A and 16B illustrate browsing commands, in accordance with one embodiment of the present invention;

FIG. 17 is a table of editing commands, in accordance with one embodiment of the present invention;

FIG. 18 is a table of regular expressions, in accordance with one embodiment of the present invention;

FIG. 19 is a table of various project files, in accordance with one embodiment of the present invention;

FIG. 20 illustrates a GUI for customizing the interface, in accordance with one embodiment of the present invention;

FIG. 20A illustrates a method for compiling a computer program for programming a hardware device;

FIG. 21 illustrates a build interface, in accordance with one embodiment of the present invention;

FIG. 22 illustrates table showing a build menu, in accordance with one embodiment of the present invention;

FIG. 22A illustrates a method for debugging a computer program, in accordance with one embodiment of the present invention;

FIGS. 23A and 23B illustrate the various commands associated with the debug menu, in accordance with one embodiment of the present invention;

FIG. 24 illustrates a table showing the various windows associated with the debugger interface, in accordance with one embodiment of the present invention;

FIG. 25 illustrates a variables window interface, in accordance with one embodiment of the present invention;

FIG. 26 illustrates the current positioning function blib, and the related call stack window;

FIG. 27 illustrates a threads window interface, in accordance with one embodiment of the present invention;

FIG. 28 illustrates a variables window interface, in accordance with one embodiment of the present invention;

FIG. 29 illustrates a breakpoints window interface, in accordance with one embodiment of the present invention;

FIGS. 30 and 31 illustrate a table showing various differences between Handel-C and the conventional C programming language, in accordance with one embodiment of the present invention;

FIG. 32 illustrates a table of types, type operators and objects, in accordance with one embodiment of the present invention;

FIG. 33 illustrates a table of statements, in accordance with one embodiment of the present invention;

FIG. 34 illustrates a table of expressions, in accordance with one embodiment of the present invention;

FIG. 35 illustrates a net list reader settings display, in accordance with one embodiment of the present invention;

FIGS. 36 and 37 illustrate a tool settings display, in accordance with one embodiment of the present invention;

FIG. 38 illustrates the wires that would be produced when specifying floating wire names, in accordance with one embodiment of the present invention;

FIG. 39 illustrates an interface between Handel-C and VHDL for simulation, in accordance with one embodiment of the present invention;

FIGS. 40A and 40B illustrate a table of possible specifications, in accordance with one embodiment of the present invention;

FIG. 41 illustrates the use of various VHDL files, in accordance with one embodiment of the present invention;

FIG. 41A illustrates a method for equipping a simulator with plug-ins;

FIGS. 42A and 42B illustrate various function calls and the various uses thereof, in accordance with one embodiment of the present invention;

FIG. 43 illustrates a plurality of possible values and meanings associated with libraries of the present invention;

FIG. 44 shows how the synchronization works when single-stepping the two projects in simulation;

FIG. 44A illustrates a pair of simulators, in accordance with one embodiment of the present invention;

FIG. 44B illustrates a cosimulation arrangement including processes and DLLs;

FIG. 44C illustrates an example of a simulator reengagement, in accordance with one embodiment of the present invention;

FIG. 44D illustrates a schematic of exemplary cosimulation architecture;

FIGS. 45A and 45B summarize the options available on the compiler;

FIGS. 46A and 46B illustrate various commands and debugs, in accordance with one embodiment of the present invention;

FIGS. 47A through 47C illustrate various icons that may be utilized, in accordance with one embodiment of the present invention;

FIG. 48 illustrates the various raw file bit numbers and the corresponding color bits;

FIG. 49 illustrates the manner in which branches that complete early are forced to wait for the slowest branch before continuing;

FIG. 50 illustrates the link between parallel branches, in accordance with one embodiment of the present invention;

FIG. 51 illustrates the scope of variables, in accordance with one embodiment of the present invention

FIGS. 52, 53 and 54 illustrate a table of operators, statements, and macros respectively, along with alternate meanings thereof;

FIG. 55 illustrates a compiler, in accordance with one embodiment of the present invention;

FIG. 56 illustrates the various specifications for the interfaces of the present invention;

FIG. 57 illustrates a table showing the ROM entries, in accordance with one embodiment of the present invention;

FIG. 57A illustrates a method for using a dynamic object in a programming language;

FIG. 57A-1 illustrates a method for using extensions to execute commands in parallel;

FIG. 57A-2 illustrates a method for parameterized expressions, in accordance with various embodiments of the present invention;

FIGS. 58A and 58B illustrate a summary of statement timings, in accordance with one embodiment of the present invention;

FIG. 59 illustrates various I/O based on clock cycles, in accordance with one embodiment of the present invention;

FIG. 60 illustrates a table showing the various locations, in accordance with one embodiment of the present invention;

FIG. 61 illustrates the various family names, in accordance with one embodiment of the present invention;

FIG. 62 illustrates a timing diagram showing a signal, in accordance with one embodiment of the present invention;

FIG. 63 illustrates a timing diagram showing a SSRAM read and write, in accordance with one embodiment of the present invention;

FIG. 64 illustrates a timing diagram showing a SSRAM read cycle using generated RAMCLK, in accordance with one embodiment of the present invention;

FIG. 65 illustrates a timing diagram showing read-cycle from a flow-through SSRAM within a Handel-C design, in accordance with one embodiment of the present invention;

FIG. 66 illustrates a timing diagram showing complete write cycle, in accordance with one embodiment of the present invention;

FIG. 67 illustrates a timing diagram showing complete read cycle, in accordance with one embodiment of the present invention;

FIG. 68 illustrates a timing diagram showing complete cycle, in accordance with one embodiment of the present invention;

FIG. 69 illustrates a timing diagram showing a cycle for a write to external RAM, in accordance with one embodiment of the present invention;

FIG. 70 illustrates a timing diagram showing a cycle for a read from external RAM, in accordance with one embodiment of the present invention;

FIG. 71 illustrates a timing diagram showing a cycle for a write to external RAM, in accordance with one embodiment of the present invention;

FIG. 72 illustrates a timing diagram showing a cycle for a read from external RAM, in accordance with one embodiment of the present invention;

FIG. 73 illustrates a timing diagram showing a cycle for a write to external RAM, in accordance with one embodiment of the present invention;

FIG. 74 illustrates a timing diagram showing a cycle for a read from external RAM, in accordance with one embodiment of the present invention;

FIG. 75 is a table of pre-defined interface sorts, in accordance with one embodiment of the present invention;

FIG. 76 illustrates a timing diagram, in accordance with one embodiment of the present invention;

FIG. 76A is a flowchart showing a method for providing a versatile interface;

FIG. 77 illustrates the manner in which an interface is specified, in accordance with one embodiment of the present invention;

FIGS. 78A through 78C illustrate a table showing the specification of various keywords, in accordance with one embodiment of the present invention;

FIG. 78D illustrates the manner in which an pin outs are specified, in accordance with one embodiment of the present invention;

FIG. 79 illustrates the various signals employed by the present invention;

FIG. 80 illustrates a read waveform representative of a cycle, in accordance with one embodiment of the present invention;

FIG. 81 illustrates a waveform representative of a write cycle, in accordance with one embodiment of the present invention;

FIG. 82 illustrates a table that lists the most common types that may be associated with a variable, in accordance with one embodiment of the present invention;

FIG. 83 illustrates a table that lists all prefixes to the above types for different architectural object types, in accordance with one embodiment of the present invention;

FIG. 84 illustrates a table that lists all statements in the Handel-C language, in accordance with one embodiment of the present invention;

FIGS. 85A and 85B illustrate a table that lists all operators in the Handel-C language, in accordance with one embodiment of the present invention;

FIGS. 86A through 86E illustrate a table that lists keywords, in accordance with one embodiment of the present invention;

FIG. 87A illustrates escape codes and their associated meanings, in accordance with one embodiment of the present invention;

FIG. 87B illustrates a method for distributing cores, in accordance with one embodiment of the present invention;

FIG. 87C illustrates a method for using a library map during the design of cores, in accordance with one embodiment of the present invention;

FIG. 87D illustrates a method for providing polymorphism using pointers, in accordance with one embodiment of the present invention;

FIG. 87E illustrates a method for generating libraries utilizing pre-compiler macros, in accordance with one embodiment of the present invention;

FIG. 87F illustrates a method for mimicking object oriented programming utilizing pointers in a programmable hardware architecture, in accordance with one embodiment of the present invention;

FIG. 88 illustrates an application program interface, in accordance with one embodiment of the present invention, in accordance with one embodiment of the present invention;

FIG. 89 illustrates that the physical layer is divided into a further two sections, in accordance with one embodiment of the present invention;

FIG. 90 is a schematic diagram of the application layer, physical layer, and user domain, in accordance with one embodiment of the present invention;

FIG. 91 shows a typical execution flow for a function, in accordance with one embodiment of the present invention;

FIG. 92 shows a typical address packet, in accordance with one embodiment of the present invention;

FIG. 93 illustrates a Trace and Pattern window, in accordance with one embodiment of the present invention; and

FIG. 94 illustrates several toolbar icons and their functions, in accordance with one embodiment of the present invention.

DETAILED DESCRIPTION OF THE PREFERRED EMBODIMENTS

A preferred embodiment of a system in accordance with the present invention is preferably practiced in the context of a personal computer such as an IBM compatible personal computer, Apple Macintosh computer or UNIX based workstation. A representative hardware environment is depicted in FIG. 1, which illustrates a typical hardware configuration of a workstation in accordance with a preferred embodiment having a central processing unit 110, such as a microprocessor, and a number of other units interconnected via a system bus 112.

The workstation shown in FIG. 1 includes a Random Access Memory (RAM) 114, Read Only Memory (ROM) 116, an I/O adapter 118 for connecting peripheral devices such as disk storage units 120 to the bus 112, a user interface adapter 122 for connecting a keyboard 124, a mouse 126, a speaker 128, a microphone 132, and/or other user interface devices such as a touch screen (not shown) to the bus 112, communication adapter 134 for connecting the workstation to a communication network (e.g., a data processing network) and a display adapter 136 for connecting the bus 112 to a display device 138.

The workstation typically has resident thereon an operating system such as the Microsoft Windows NT or Windows/95 Operating System (OS), the IBM OS/2 operating system, the MAC OS, or UNIX operating system. Those skilled in the art may appreciate that the present invention may also be implemented on platforms and operating systems other than those mentioned.

In one embodiment, the hardware environment of FIG. 1 may include, at least in part, a field programmable gate array (FPGA) device. For example, the central processing unit 110 may be replaced or supplemented with an FPGA. Use of such device provides flexibility in functionality, while maintaining high processing speeds.

Examples of such FPGA devices include the XC2000.TM. and XC3000.TM. families of FPGA devices introduced by Xilinx, Inc. of San Jose, Calif. The architectures of these devices are exemplified in U.S. Pat. Nos. 4,642,487; 4,706,216; 4,713,557; and 4,758,985; each of which is originally assigned to Xilinx, Inc. and which are herein incorporated by reference for all purposes. It should be noted, however, that FPGA's of any type may be employed in the context of the present invention.

An FPGA device can be characterized as an integrated circuit that has four major features as follows.

(1) A user-accessible, configuration-defining memory means, such as SRAM, PROM, EPROM, EEPROM, anti-fused, fused, or other, is provided in the FPGA device so as to be at least once-programmable by device users for defining user-provided configuration instructions. Static Random Access Memory or SRAM is of course, a form of reprogrammable memory that can be differently programmed many times. Electrically Erasable and reprogrammable ROM or EEPROM is an example of nonvolatile reprogrammable memory. The configuration-defining memory of an FPGA device can be formed of mixture of different kinds of memory elements if desired (e.g., SRAM and EEPROM) although this is not a popular approach.

(2) Input/Output Blocks (IOB's) are provided for interconnecting other internal circuit components of the FPGA device with external circuitry. The IOB's' may have fixed configurations or they may be configurable in accordance with user-provided configuration instructions stored in the configuration-defining memory means.

(3) Configurable Logic Blocks (CLB's) are provided for carrying out user-programmed logic functions as defined by user-provided configuration instructions stored in the configuration-defining memory means.

Typically, each of the many CLB's of an FPGA has at least one lookup table (LUT) that is user-configurable to define any desired truth table,--to the extent allowed by the address space of the LUT. Each CLB may have other resources such as LUT input signal pre-processing resources and LUT output signal post-processing resources. Although the term `CLB` was adopted by early pioneers of FPGA technology, it is not uncommon to see other names being given to the repeated portion of the FPGA that carries out user-programmed logic functions. The term, `LAB` is used for example in U.S. Pat. No. 5,260,611 to refer to a repeated unit having a 4-input LUT.

(4) An interconnect network is provided for carrying signal traffic within the FPGA device between various CLB's and/or between various IOB's and/or between various IOB's and CLB's. At least part of the interconnect network is typically configurable so as to allow for programmably-defined routing of signals between various CLB's and/or IOB's in accordance with user-defined routing instructions stored in the configuration-defining memory means.

In some instances, FPGA devices may additionally include embedded volatile memory for serving as scratchpad memory for the CLB's or as FIFO or LIFO circuitry. The embedded volatile memory may be fairly sizable and can have 1 million or more storage bits in addition to the storage bits of the device's configuration memory.

Modern FPGA's tend to be fairly complex. They typically offer a large spectrum of user-configurable options with respect to how each of many CLB's should be configured, how each of many interconnect resources should be configured, and/or how each of many IOB's should be configured. This means that there can be thousands or millions of configurable bits that may need to be individually set or cleared during configuration of each FPGA device.

Rather than determining with pencil and paper how each of the configurable resources of an FPGA device should be programmed, it is common practice to employ a computer and appropriate FPGA-configuring software to automatically generate the configuration instruction signals that may be supplied to, and that may ultimately cause an unprogrammed FPGA to implement a specific design. (The configuration instruction signals may also define an initial state for the implemented design, that is, initial set and reset states for embedded flip flops and/or embedded scratchpad memory cells.)

The number of logic bits that are used for defining the configuration instructions of a given FPGA device tends to be fairly large (e.g., 1 Megabits or more) and usually grows with the size and complexity of the target FPGA. Time spent in loading configuration instructions and verifying that the instructions have been correctly loaded can become significant, particularly when such loading is carried out in the field.

For many reasons, it is often desirable to have in-system reprogramming capabilities so that reconfiguration of FPGA's can be carried out in the field.

FPGA devices that have configuration memories of the reprogrammable kind are, at least in theory, `in-system programmable` (ISP). This means no more than that a possibility exists for changing the configuration instructions within the FPGA device while the FPGA device is `in-system` because the configuration memory is inherently reprogrammable. The term, `in-system` as used herein indicates that the FPGA device remains connected to an application-specific printed circuit board or to another form of end-use system during reprogramming. The end-use system is of course, one which contains the FPGA device and for which the FPGA device is to be at least once configured to operate within in accordance with predefined, end-use or `in the field` application specifications.

The possibility of reconfiguring such inherently reprogrammable FPGA's does not mean that configuration changes can always be made with any end-use system. Nor does it mean that, where in-system reprogramming is possible, that reconfiguration of the FPGA can be made in timely fashion or convenient fashion from the perspective of the end-use system or its users. (Users of the end-use system can be located either locally or remotely relative to the end-use system.)

Although there may be many instances in which it is desirable to alter a pre-existing configuration of an `in the field` FPGA (with the alteration commands coming either from a remote site or from the local site of the FPGA), there are certain practical considerations that may make such in-system reprogrammability of FPGA's more difficult than first apparent (that is, when conventional techniques for FPGA reconfiguration are followed).

A popular class of FPGA integrated circuits (IC's) relies on volatile memory technologies such as SRAM (static random access memory) for implementing on-chip configuration memory cells. The popularity of such volatile memory technologies is owed primarily to the inherent reprogrammability of the memory over a device lifetime that can include an essentially unlimited number of reprogramming cycles.

There is a price to be paid for these advantageous features, however. The price is the inherent volatility of the configuration data as stored in the FPGA device. Each time power to the FPGA device is shut off, the volatile configuration memory cells lose their configuration data. Other events may also cause corruption or loss of data from volatile memory cells within the FPGA device.

Some form of configuration restoration means is needed to restore the lost data when power is shut off and then re-applied to the FPGA or when another like event calls for configuration restoration (e.g., corruption of state data within scratchpad memory).

The configuration restoration means can take many forms. If the FPGA device resides in a relatively large system that has a magnetic or optical or opto-magnetic form of nonvolatile memory (e.g., a hard magnetic disk)--and the latency of powering up such a optical/magnetic device and/or of loading configuration instructions from such an optical/magnetic form of nonvolatile memory can be tolerated--then the optical/magnetic memory device can be used as a nonvolatile configuration restoration means that redundantly stores the configuration data and is used to reload the same into the system's FPGA device(s) during power-up operations (and/or other restoration cycles).

On the other hand, if the FPGA device(s) resides in a relatively small system that does not have such optical/magnetic devices, and/or if the latency of loading configuration memory data from such an optical/magnetic device is not tolerable, then a smaller and/or faster configuration restoration means may be called for.

Many end-use systems such as cable-TV set tops, satellite receiver boxes, and communications switching boxes are constrained by prespecified design limitations on physical size and/or power-up timing and/or security provisions and/or other provisions such that they cannot rely on magnetic or optical technologies (or on network/satellite downloads) for performing configuration restoration. Their designs instead call for a relatively small and fast acting, non-volatile memory device (such as a securely-packaged EPROM IC), for performing the configuration restoration function. The small/fast device is expected to satisfy application-specific criteria such as: (1) being securely retained within the end-use system; (2) being able to store FPGA configuration data during prolonged power outage periods; and (3) being able to quickly and automatically re-load the configuration instructions back into the volatile configuration memory (SRAM) of the FPGA device each time power is turned back on or another event calls for configuration restoration.

The term `CROP device` may be used herein to refer in a general way to this form of compact, nonvolatile, and fast-acting device that performs `Configuration-Restoring On Power-up` services for an associated FPGA device.

Unlike its supported, volatilely reprogrammable FPGA device, the corresponding CROP device is not volatile, and it is generally not `in-system programmable`. Instead, the CROP device is generally of a completely nonprogrammable type such as exemplified by mask-programmed ROM IC's or by once-only programmable, fuse-based PROM IC's. Examples of such CROP devices include a product family that the Xilinx company provides under the designation `Serial Configuration PROMs` and under the trade name, XC1700D.TM. These serial CROP devices employ one-time programmable PROM (Programmable Read Only Memory) cells for storing configuration instructions in nonvolatile fashion.

A preferred embodiment is written using Handel-C. Handel-C is a programming language marketed by Celoxica Limited. Handel-C is a programming language that enables a software or hardware engineer to target directly FPGAs (Field Programmable Gate Arrays) in a similar fashion to classical microprocessor cross-compiler development tools, without recourse to a Hardware Description Language. This allows the designer to directly realize the raw real-time computing capability of the FPGA.

Handel-C allows one to use a high-level language to program FPGAs. It makes it easy to implement complex algorithms by using a software-based language rather than a hardware architecture-based language. One can use all the power of reconfigurable computing in FPGAs without needing to know the details of the FPGAs themselves. A program may be written in Handel-C to generate all required state machines, while one can specify storage requirements down to the bit level. A clock and clock speed may be assigned for working with the simple but explicit model of one clock cycle per assignment. A Handel-C macro library may be used for bit manipulation and arithmetic operations. The program may be compiled and then simulated and debugged on a PC similar to that in FIG. 1. This may be done while stepping through single or multiple clock cycles.

When one has designed their chip, the code can be compiled directly to a netlist, ready to be used by manufacturers' place and route tools for a variety of different chips.

As such, one can design hardware quickly because he or she can write high-level code instead of using a hardware description language. Handel-C optimizes code, and uses efficient algorithms to generate the logic hardware from the program. Because of the speed of development and the ease of maintaining well-commented high-level code, it allows one to use reconfigurable computing easily and efficiently.

Handel-C has the tight relationship between code and hardware generation required by hardware engineers, with the advantages of high-level language abstraction. Further features include:

C-like language allows one to program quickly

Architecture specifiers allow one to define RAMs, ROMs, buses and interfaces.

Parallelism allows one to optimize use of the FPGA

Close correspondence between the program and the hardware

Easy to understand timing model

Full simulation of owner hardware on the PC

Display the contents of registers every clock cycle during debug

Rapid prototyping

Convert existing C programs to hardware

Works with manufacturers' existing tools

Rapid reconfiguration

Logic estimation tool highlights code inefficiencies in colored Web pages

Device-independent programs

Generates EDIF and XNF formats (and XBLOX macros)

Handel-C is thus designed to enable the compilation of programs into synchronous hardware; it is aimed at compiling high level algorithms directly into gate level hardware. The Handel-C syntax is based on that of conventional C so programmers familiar with conventional C may recognize almost all the constructs in the Handel-C language. Sequential programs can be written in Handel-C just as in conventional C but to gain the most benefit in performance from the target hardware its inherent parallelism may be exploited. Handel-C includes parallel constructs that provide the means for the programmer to exploit this benefit in his applications. The compiler compiles and optimizes Handel-C source code into a file suitable for simulation or a net list which can be placed and routed on a real FPGA.

More information regarding the Handel-C programming language will now be set forth. For further information, reference may be made to "EMBEDDED SOLUTIONS Handel-C Language Reference Manual: Version 3," "EMBEDDED SOLUTIONS Handel-C User Manual: Version 3.0," "EMBEDDED SOLUTIONS Handel-C Interfacing to other language code blocks: Version 3.0," and "EMBEDDED SOLUTIONS Handel-C Preprocessor Reference Manual: Version 2.1," each authored by Rachel Ganz, and published by Embedded Solutions Limited, and which are each incorporated herein by reference in their entirety.

The present description is divided in a plurality of sections set forth under the headings:

HANDEL-C COMPILER AND SIMULATOR

HANDEL-C LANGUAGE

PREPROCESSOR

FPGA-BASED CO-PROCESSOR API

FIXED AND FLOATING POINT LIBRARY

WAVEFORM ANALYSIS

HANDEL-C COMPILER AND SIMULATOR

Conventions

A number of conventions are used throughout this description. These conventions are detailed below. Hexadecimal numbers appear throughout this description. The convention used is that of prefixing the number with `0x` in common with standard C syntax.

Sections of code or commands that one may type are given in typewriter font as follows:

"void main( );"

Information about a type of object one may specify is given in italics as follows:

"copy SourceFileName DestinationFileName"

Menu items appear in narrow bold text as follows:

"insert Project into Workspace"

Elements within a menu are separated from the menu name by a >so Edit>Find means the Find item in the Edit menu.

Introduction

Handel-C is a programming language designed to enable the compilation of programs into synchronous hardware. The Handel-C compiler and simulator will now be described. The Handel-C language may be described hereinafter in greater detail.

The present description contains:

Getting started

User interface overview

Compiler and simulator overview

Examples of compiler and simulator use

Notes on using Handel-C and porting C code to Handel-C

Description of interfacing with VHDL code

Guide to the API (Application Programmers Interface)

Descriptions of the bitmap to data conversion utilities used by the

examples.

Overview

Design Flow Overview

FIG. 2 illustrates a design flow overview 200, in accordance with one embodiment of the present invention. The dotted lines 202 show the extra steps 204 required if one wishes to integrate Handel-C with VHDL.

Getting Started.

Introduction

The present section gives a brief description of how to use the Handel-C compiler and simulator.

The Handel-C Development Environment

FIG. 3 illustrates the Handel-C development environment 300, in accordance with one embodiment of the present invention. The Handel-C development environment is a standard Windows development environment. It is in four main parts. The windows and toolbars are standard Windows dockable windows and customizable toolbars.

Expected Development Sequence

The normal development sequence for a single-chip project is as follows:

1. Create a new project.

2. Configure the project.

3. Add the empty source code files to the project.

4. Create source code.

5. Link to any required libraries.

6. Set up the files for debug.

7. Compile the project for debug.

8. Debug the project.

9. Compile the project for target chip.

10. Export the target file to a place and route tool.

11. Place and route.

There is not necessarily information on placing and routing within the Handel-C documentation.

The steps are described below.

Invoking the Environment.

One starts Handel-C by doing one of:

selecting Start>Programs>Handel-C>Handel-C

double-clicking on an existing Handel-C workspace file (files with the extension .hw)

double-clicking the Handel-C icon

FIG. 4 illustrates a graphical user interface 400 shown if one starts the program with an empty workspace.

Creating the Project

FIG. 5 illustrates a graphical user interface 500 used to create a project, in accordance with one embodiment of the present invention.

Select New from the File menu.

Select the Project tab in the dialog that appears.

One may be asked for the name and location (pathname for the directory that it is stored in) for the project. One can look for a directory by clicking the . . . button to the right of the Location box.

By default, a new workspace is created for the project in the same directory as the project. Workspace files have .hw extensions. Project files have .hp extensions. When one starts a new project, one may have to define its type. FIG. 6 illustrates the various types 600 of new projects, in accordance with one embodiment of the present invention.

Common pre-defined project types are supplied with Handel-C.

Select the appropriate project type from the types listed in the Project pane.

Click OK.

Configuring the Project

Once a person has created a project, one should configure its settings. These settings define what type of chip is targeted, and how the compiler, pre-processor and optimizer work. The default settings are correct for a new project that one wishes to debug.

Adding Files to the Project

Add a Handel-C source file to the new project. This may be one that a person has already written, or a new, empty one.

Creating a New File

Select File>New, and click the Source File tab.

Select whether it's a header file or a source file in the left-hand pane.

Select the project the file should belong to from the drop-down list of current projects.

Set the location (the directory path where the file is stored), either by typing the pathname in the box, or selecting a directory by clicking the . . . button.

The code editor window may open.

Adding an Existing File

Select Project>Add to Project>Files and browse the directory tree for the files one wishes to add.

One can add multiple files from a directory by selecting them all. OR

Right-click the mouse on the project, and select Add Files to Folder from the shortcut menu.

Removing Files from a Project

One can remove files from a project by selecting the file in the workspace window and pressing the Delete key or selecting Edit>Delete. This does not delete the file from the hard disk.

Opening an existing source code file does not add it to the project. It may not be built or compiled. One may explicitly add files to the project.

Writing Source Code

One may write Handel-C source code in the source code editor. Code is indented at the same level as the line above it and is syntax highlighted.

Having a file open in the source code editor does not mean that it is part of the project. The only files that may be compiled and built are those that may have been added to the project.

Setting up for Debug

There are several methods of coding Handel-C to help one debug a project.

They fall into two kinds:

Code which may automatically be discarded by the compiler if one does not compile a project for debug, e.g., the with {infile="file"} directive

Code where one supplies alternatives to be compiled for debug and release or target compilations. In these cases, one can use the #ifdef DEBUG, #ifdef NDEBUG and #ifdef SIMULATE directives.

By default, DEBUG and SIMULATE may be defined if one compiles for debug, and NDEBUG may be defined for all other compilations. For example:

.ifdef SIMULATE

sim_chan ? var; // Read from simulator .else

HardwareMacroRead(var); // Real HW interface .endif

Summary of coding techniques used for debug:

Substitute simulator channels for hardware interface channels

Use the assert directive to stop a compilation if a condition is untrue.

Substitute file input for external channel input

Export the contents of variables into files

Build and Compile for Debug

Debug is the default compilation target. It is unlikely that one would need to make any changes to the project settings at this stage. The compiler creates a file which is in turn compiled into native PC code using Microsoft Visual C++. This creates the chip simulation.

To build and compile the project, select Build from the Build menu. Messages from the compiler may appear in the Build tab of the output window

Debug and Simulation

Select Start debug from the Build menu. The Debug menu may replace the Build menu. A person can step through the code from execution point to execution point. Statements that are completed at the end of the current clock cycle are marked with an arrow.

The arrows are color coded as follows:

Yellow current point

White other points in this thread executed in this cycle

Grey points in other threads executed in this cycle

To set a breakpoint, click in the code editor on the line where one wishes to set the breakpoint and then click the breakpoint button . A red circle may appear at the beginning of that line. When the debugger reaches that line, it may stop. FIG. 7 illustrates a breakpoint 700, in accordance with one embodiment of the present invention.

Optimize Code as Necessary

One can examine the depth and speed of the code by compiling with the -e option selected in the Compiler tab of the Project Settings dialog. This creates:

an html file for the project, project.html

an html file for each file in the project files_c.html.

These files highlight the code according to the code area and timing. The project.html file has links to all the html files highlighting the source code. It also links to the 5 top areas and 5 top delays in the project. One can use this as a basis for optimizing the code. An example of progressive optimization is given later.

Compile for Release

When one is satisfied with the project, select Build>Set Active Configuration and choose the type of build required from the available configurations. Release allows one to simulate the project without the delays inherent in debug. It also allows one to compile Handel-C libraries without debug information to protect intellectual property. Target is one of VHDL and EDIF. These are files that are ready to be placed and routed. By default, most optimizations may be turned on.

Project Settings

FIG. 8 illustrates a project settings interface 800, in accordance with one embodiment of the present invention. Project settings define how projects are compiled and built. Select Project>Settings to see the Project settings dialog box. The different settings 802 are available via tabs 804. If one can't see the tab one want, then scroll the tabs by clicking on the arrows 806 at the end of the tabs. Note that some tabs are not available for an empty project. FIGS. 9A, 9B, and 9C illustrate available settings 900.

Independent Settings for Files

One can create independent settings for a file. A person might wish to do this if one wanted to change the optimization level for a particular file. Project settings for a file override the general project settings.

To create settings for a file, open the Project Settings dialog (either right-click the file in the File View and select Settings, or select Project>Settings).

Select the name of the file that one wishes to affect in the file pane of the Project Settings dialog.

Make the appropriate changes.

Configurations

There are three types of configuration that one can select from to build the application

Debug (default)

Release

Target (VHDL, EDIF etc.)

Debug is used to build a configuration that can be simulated and debugged on the PC. In debug mode, one can view the contents of registers and step through the program's source code.

Release mode is used to create Handel-C intellectual property (libraries). It creates compiled code that has no debug messages and can be used in another program. Release mode can also be used for high-speed simulation.

In target mode, one gets a list of gates, ready to be placed and routed on an FPGA.

Defining Configurations

FIG. 10 illustrates a configurations graphical user interface 1000, in accordance with one embodiment of the present invention. One can save a particular combination of settings as a project configuration using the Build>Configurations menu item. This user-defined configuration can only be used in the project. Handel-C comes with four default configurations: Build 1002, Debug 1004, VHDL 1006 and EDIF 1008. One can copy one of these configurations and then make changes to it.

Select Build>Configurations . . .

Click the Add button in the dialog that appears.

Enter a name for the new configuration, and select the configuration type that one wishes to use as a base in the Copy settings from box.

More Complex Configurations

If one knows that he or she is going to have multiple projects (perhaps one needs to have two independent circuits on the same chip), it is better to create a workspace first and then add the projects to it.

If one has an existing workspace set up, it may be opened. Otherwise, select New from the File menu. Create a new workspace to store the project(s). One may be asked for its name and location (pathname for the directory that it may be stored in). Either type the pathname in the Location box, or use the . . . button to browse for a directory. Workspace files have .hw extensions.

Adding an Existing Project to a Workspace

Select Insert Project into Workspace from the Project menu.

Creating a Complex Project

If a project is a board or system, it may contain subprojects. When one creates a new complex project type (by writing a new .cf file) a dialog box appears when one clicks OK. The New Project Components dialog box asks what projects one wishes to use for the components of the project. One can either create a new project or select one within the workspace from the drop-down list. If the project exists but is not in the workspace, one can add it using the Insert Project button.

To ensure that the subprojects are built when one builds the complex project, he or she can set up the subprojects as dependent. Select Project>Dependencies . . .

One may be offered a list of the projects in the workspace. Check the ones that are desired to be rebuilt when building the complex project.

Dependencies

Dependencies are used to ensure that files that are not part of the project are updated during a build. They also specify the order that files may be compiled and built.

There are three types of dependencies used in Handel-C:

Project dependencies

File dependencies

External dependencies

The only one that can be changed directly is Project Dependencies. The others show information calculated by the compiler.

Project Dependencies

The Project>Dependencies . . . dialog allows one to select other projects within the workspace that this project is dependent on. Projects listed here may be rebuilt as necessary when the project is rebuilt.

If one is building a complex project, such as a board or system that has several chips on it, he or she can create a separate project for each chip, and make the system project dependent upon them.

File Dependencies

File dependencies are listed in the file properties. They specify the user include files that are not included in the project which are needed to compile and build a selected file. They also specify what other files within the project may be compiled before this file.

These dependencies are generated when one compiles a file. One can examine them by selecting a file in the File View pane of the workspace window and typing Alt+Enter or right-clicking the file name and selecting Properties from the shortcut menu.

External Dependencies

The External Dependencies folder appears in the workspace window after a project has been built. It contains a list of the header files required by the project that are not included in the project.

User Interface

The Workspace Window

The workspace window contains workspaces and projects. A workspace is simply an area that one keeps projects in. It allows one to organize the files that one need for each project. One could generally use one workspace per system (a system is the configuration that one are targeting).

A project consists of everything one need to create one or more net list files ready to be placed and routed on an FPGA, together with the project settings. Project settings provide information about where the files for the project are stored, the target chip for the project, how the compilation may work, and optimization requirements. Projects can be libraries (compiled Handel-C that is not targeted for a particular output), cores (a piece of code, such as a function), complete net lists for a chip, boards (net lists for several chips in a specified configuration) or systems (a combination of boards etc.). In one embodiment, the core may optionally be compiled to a net list.

The workspace window has two views:

File view

Symbol view

File View

FIG. 11 illustrates a file view interface 1100, in accordance with one embodiment of the present invention. File view shows the workspace, its projects, and their source files and folders 1102. If there are multiple projects in a single workspace, the current project name 1104 may be in bold. The file view gives the structure of files in the project. It has no relationship to the way one has stored files on a hard disk. It allows one to set up dependencies (what files are needed for this project and what files or projects they depend upon) and manage the project by seeing which files are used within it.

One can adjust the space given to the Object and Info columns 1106 by dragging the edge of the column heading. Double-clicking on a source file opens it in the code editor. Double clicking on anything else expands or contracts that branch of the workspace tree. Right-clicking on a filename or directory gives one a list of commonly-used commands.

File Properties

FIG. 12 illustrates a file properties 1200, in accordance with one embodiment of the present invention. To operate, one may select a file or directory in the workspace window 1202, then select View>Properties. This displays:

Inputs The tools used and the source file pathname(s) that tool requires

Outputs The output files generated by the specified tool

Dependencies The header files (dependencies) this file requires.

Managing the Project Files

One can order the files within the project into folders. These folders are only used to organize the files. They do not exist as folders on the hard disk and have no effect on the directory structure.

Select Project>Add to Project>New Folder

Type the name of the folder in the dialog box that appears

Type the extension for the file types it should contain. One can leave the box blank.

Click OK

A new folder appears in the file view window.

Drag the files that are desired to be moved across to the folder.

Symbol View

FIG. 13 illustrates a workspace interface 1300 and the associated icons, in accordance with one embodiment of the present invention. A symbol is anything defined by the user (functions, variables, macros, typedefs, enums etc.). Symbol view allows one to see what one has in a project. It is empty before one builds a project. When one builds the project with the browse information enabled (set by default in the Debug configuration), a symbol table is created that allows one to examine the symbols defined and used in the project. Selecting the Symbol View tab 1302 of the workspace window then shows icons 1304 representing logic and architectural variables, functions and procedures.

Each icon is identified by its definition and use (references). External symbols (external variables and function names) appear in alphabetical order.

Double-clicking on a symbol expands it if it is expandable: if not, it opens the relevant source code file, with the appropriate line tagged Local symbols appear in alphabetical order within the function or procedure where they are defined.

FIG. 14 illustrates a version test interface 1400, in accordance with one embodiment of the present invention.

The Source Browser

FIG. 15 illustrate a browse and associated results interface 1500, in accordance with one embodiment of the present invention. One can browse for definitions and references 1502 without using symbol view. When one selects the Source Browser command from the Tool menu, one is given a Browse dialog box.

Enter the symbol being searched for, and a dialog box may be shown giving its definition and references to it.

Browse Commands

If one selects a symbol name in a source file, one can use the browse commands and buttons to find its definitions and references in all the files used in a project. FIGS. 16A and 16B illustrate browsing commands 1600, in accordance with one embodiment of the present invention.

Editing

The Code Editor

The code editor is a simple editor that resides in its own window. The syntax is color coded. One can change the color codes by selecting the Format tab from the Tools>Options dialog box. The default values are:

Comments green

Handel-C keywords blue

Number black

String black

Operator black

One can use standard editing commands within the code window. These are accessible from the Edit menu. FIG. 17 is a table of editing commands 1700, in accordance with one embodiment of the present invention. The Edit menu also has the Bookmarks and Browse sub-menus and the Breakpoints command.

Find Commands

Handel-C has simple Find and Replace commands that allow one to search for text in the current file, and the Find in Files command, which allows one to search for a string in all the files in a directory. The output from this command can be sent to two different window panes, allowing one to view the results of two searches. To choose which pane is selected check or uncheck the Output to pane 2 box in the Find in Files dialog.

These searches work line by line, which means that one cannot match text that spans more than one line. One can also search using regular expressions. To do this, check Regular expression in the Find and Find in Files dialog box. The regular expressions supported are listed below. FIG. 18 is a table of regular expressions 1800, in accordance with one embodiment of the present invention.

Bookmarks Submenu

The Bookmarks submenu allows one to set and clear bookmarks within the files. Once one has set bookmarks in the file, one can move through the bookmarks by selecting Next Bookmark (F2) or Previous Bookmark (Shift F2).

To Set a Bookmark

Select the line where one wishes to place the bookmark

Press the toggle bookmark button OR

Right-click the line and select Toggle bookmark from the shortcut menu that appears OR

Select Edit>Bookmarks>Toggle Bookmark (Ctrl F2).

To Move to a Bookmark

Select Edit>Bookmarks>Next Bookmark (F2) or press the next bookmark button to move forward through the bookmarks

Select Edit>Bookmarks>Previous Bookmark (Shift F2) or press the previous bookmark button to move backwards.

To Remove a Bookmark

Select the line where one wishes to clear the bookmark Press the toggle bookmark button OR

Right-click the line and select Toggle bookmark from the shortcut menu that appears OR

Select Edit>Bookmarks>Toggle Bookmark (Control F2).

To Remove All Bookmarks

Select Edit>Bookmarks>Clear All Bookmarks (Control Shift F2) or press the clear all bookmarks button to clear all bookmarks

Breakpoints Command

The Breakpoints command allows one to set, enable and disable breakpoints. Breakpoints are fully discussed hereinafter in greater detail.

Breakpoints Alt+F9 Display a dialogue box for editing the breakpoints list for this project.

Browse Submenu

The Browse submenu allows one to find definitions of and references to selected variables or other symbols. If one makes a change to a variable, this is a quick way of finding everywhere that the variable is used.

To Find the Definition of a Variable or other Symbol

Select the symbol name in an edit window.

Select Edit>Browse>Go to Definition or click the button

To Find the First Reference to a Variable or other Symbol

Select the symbol name in an edit window.

Select Edit>Browse>Go to Reference or click the button

To Move through the References to and Definitions of a Variable or other Symbol

Select the symbol name in an edit window.

To move forward, select Edit>Browse>Next Definition Reference or click the button

To move backward, select Edit>Browse>Previous Definition Reference or click the button

To Return to the Position before Starting Browsing

Select Edit>Browse>Pop Context or click the button

Saving Changes

If one has not saved changes to a file, an asterisk appears after the filename on the title bar. One may be asked if he or she wishes to save changes when a file is closed.

Files and Paths

The current directory is the directory containing the current project's .hp file. All relative pathnames are calculated from that current directory.

Project Files Generated

When one creates a workspace, a directory is created for that workspace. Projects within the workspace may be in the same directory or a sub-directory. When one builds a project, a directory is created for the build results. The default directory name is the name of the build type (Debug, Release, VHDL or EDIF). One can change this by setting the Output Directory values in the General tab of the Project Settings dialog.

These are the files built for a workspace prog.hw, containing a project example 1, consisting of one Handel-C file, prog.c that has been compiled for simulation. The files may all be stored in the Debug folder. FIG. 19 is a table of various project files 1900, in accordance with one embodiment of the present invention.

Search Paths

Code files that one has added to the project workspace may be compiled and built. Header files may only be found by the pre-processor if they exist on a known path.

The directories searched are in the following order:

1. Directory containing the Handel-C file that has the #include directive (if within quotes).

2. Directories listed in Project>Settings>Preprocessor>Additional include directories (in the order specified)

3. Directories listed in the Directories pane of the Tools>Options dialog (in the order specified)

4. Directories in the HANDELC_CPPFLAGS environment variable (in the order specified)

Windows and Toolbars

The Handel-C user interface has standard scrollable windows and customizable toolbars. One can customize:

The way the edit and build environment is laid out (position of workspace and output windows etc.)

The way document windows are laid out (this is specific to each workspace)

The debugger layout (the way windows look when you're in the debugger)

These layouts are stored. The edit and build and the debug layouts are kept for the copy of Handel-C. If one changes them, he or she changes them for every project. The document window layout is kept with the workspace, and can change whenever he or she changes the current workspace.

Window Types

Document windows are movable within the Handel-C window. One can resize them and drag them about. Docking windows can either be docked at one of the window margins, or can float above the other windows. When a window is docked it has no title-bar. If one has docked a code editor window, the file name appears in brackets after the project title in the Handel-C title bar. To float a docked window, double-click its border. To dock a floating window, either double-click its border, or drag its title bar to a docking position.

Splitting Windows

One can split text windows by dragging the small box immediately above the vertical scroll bar.

The Windows Menu

The windows menu allows one to control the size and display of editing windows. It has the following commands:

New window Create a copy of the current window

Split Split the window into two or four views.

Docking view Enable/disable docking view of selected dockable window

Close Close current window

Close All Close all windows

Next Move to next pane of a split window

Previous Move to previous pane of a split window

Cascade Cascade all open windows with title bars visible

Tile Horizontally Display all windows, splitting the viewing area horizontally

Tile Vertically Display all windows, splitting the viewing area vertically

Arrange Icons Arrange minimized window icons along bottom of viewing area

Windows . . . Open Windows dialog

Windows Dialog

The Windows dialog gives the names of all open edit windows. A person can make one of them the current window, or select a group of windows to be saved, closed or tiled.

Full Screen Display

The Full Screen command on the Edit menu displays the code editor pane at maximum size. The normal menu bars and toolbars are not visible. To return to a normal view, click the no full screen button.

Toolbars

When one starts Handel-C, toolbars appear under the menu bar. They are:

The standard toolbar

Build mini-bar

Browse mini-bar

Debug mini-bar

Bookmark mini-bar.

Standard Toolbar Buttons

The standard toolbar buttons are a frequently used subset from the File, Edit and View menus.

Changing Toolbars

The toolbars in Handel-C are dockable. They can be docked at one of the edges of the Handel-C window, or they can float. One can change a toolbar from docked to floating and back by double clicking on it. One can move them by dragging the title bar or the double bar.

The Status Bar

The status bar is visible at the bottom of the Handel-C window. It displays information about items when the mouse is over them.

The Tools Menu

The tools menu has the Source Browser command and commands to customize the copy of Handel-C.

The Source Browser Command

The Source Browser command allows one to search for names of variables and functions within the code. It directs one to their definition and lists references to them. Its use is more fully discussed hereinafter in greater detail.

Customizing the Interface

FIG. 20 illustrates a GUI 2000 for customizing the interface, in accordance with one embodiment of the present invention. The Customize . . . command brings up the Customize dialog. The Toolbar tab 2002 allows one to change the display of toolbars utilizing various options 2004, as shown. To use, one may check a toolbar in the toolbar pane to display it, uncheck it to hide it.

Show Tooltips Check this to popup the purpose of a button when the mouse cursor is over it.

Cool Look Check this to make the buttons appear two-dimensional

Large Buttons Check this to increase the button size

Large Icons Check this to have large icons on large buttons.

The Command tab allows one to add menus and buttons to the toolbar and menu bar. The right-hand pane displays the buttons and Menu commands available.

Select the button or menu that one wishes to add and drag it to the toolbar or menu bar. If one drags a menu command to a toolbar, it appears as a button. If one drags it to an empty area, it appears as a new floating window.

Removing Buttons and Menus

One can remove buttons from a toolbar by opening the Tools>Customize dialog and then dragging them off the toolbar. One can remove menus from the menu bar by opening the Tools>Customize dialog and dragging the menu name off the toolbar.

To restore a toolbar to its previous state, select the Toolbars tab of the Tools>Customize dialog. Select the toolbar (under the Toolbars tab) or the menu (under the Commands tab)

Options

The Tools>Options command allows one to set options:

Editor Set the window options for the editor. Define when files are saved.

Tabs Define how tabs are handled and whether Auto-Indent is used.

Debug Set the default base used to display numbers in the debug windows. This information is over-ruled by the Handel-C show specification.

Format Define the color and font of text and markers in windows.

Workspace Set the number of recently opened workspaces in the workspace list.

Directories Set the directories that may be searched for include and library files used in projects.

Editor

Vertical scroll bar Check to display vertical scroll-bar

Horizontal scroll bar Check to display horizontal scrollbar

Automatic window recycling Display files opened by the IDE (integrated development environment) in an existing window

Selection margin Use a selection margin in the editor window to enable one to select paragraphs, etc.

Drag and drop text editing Edit by selecting an area, and dragging it to a new position

Save before running tools Save files before running tools defined in the Tools menu

Prompt before saving files Ask before saving

Automatic reload of externally modified files If a file is open in Handel-C, and then modified by something outside Handel-C, load changes from disk automatically.

Tabs

File type Define settings for specified file types or define default settings.

Tab size Equivalent number of spaces per tab

Insert spaces/Keep tabs Select whether to use spaces or tabs in file

Auto indent Check to auto-indent text to above line's indent

Debug

Base for numbers Select default display base in debug windows

Format

Category Select window type(s) to modify

Font Select font to display text in

Size Select display font size

Colors Select text type to modify

Foreground: Set foreground color

Background: Set background color.

Sample Display sample text in selected settings

Reset All Return to default settings

Workspace

Default workspace list Set number of recent workspaces in the File>Recent Workspaces command

Directories

Show directories for: Select include path list or Library path list

Add or remove directory paths to search for include files or library files.

Compiler

FIG. 20A illustrates a method 2050 for a compiler capable of compiling a computer program for programming a hardware device. In general, in operation 2052, a first net list is created with a first format based on a computer program. Further, in operation 2054, a second net list is created with a second format based on the computer program. In an aspect of the present invention, the first format may include EDIF. As another aspect, the second format may include VDHL, XNF, etc. It should be noted, however, that any other formats may be employed per the desires of the user.

It is important to note that the first net list and the second net list are created utilizing a single compiler. Note operation 2056. As an option, the computer program from which the first net list was created may be the same as the computer program from which the second net list was created. More information regarding the compiler will now be set forth.

The Handel-C compiler compiles and optimizes Handel-C source code into a file suitable for simulation or a net list file which can be placed and routed on a real FPGA. The compiler is normally invoked automatically when the user selects an option from the Build menu.

Once the compile has completed, an estimate of the number of NAND gates estimate required to implement the design is displayed in the output window. The compiler uses the GNU preprocessor. Flags can be passed to the preprocessor using the Preprocessor tab of the Project>Settings dialog box. If one wishes to run the compiler from a command line, one may do so by using the command handelc. A complete list of the command line options is set forth hereinafter.

The Build Process

FIG. 21 illustrates a build interface 2100, in accordance with one embodiment of the present invention. A build happens when:

one click on the build button 2102.

one has uncompiled files and one select one of the Start Debug commands in the Build menu.

one selects Build or Rebuild All from the Build menu

This should:

preprocess header files and compile dependent header files

compile any files that have been added, changed and saved since the last compilation and also compile any files dependent upon them.

compile all dependent projects.

link the compiled files together

calculate the number of gates used

build a symbol table

generate a simulatable file or a net list.

If one changes the configuration for a project, he or she may need to compile all the files. Select the Build>Rebuild All command to ensure that all the files are recompiled.

The results of the compilation and build are displayed in the Build window. Double-clicking an error takes one to the appropriate line in the source file.

Checking Code Depth and Speed

One can examine the depth and speed of the code by compiling using the -e option. This creates:

an html file for the project, project.html

an html file for each file in the projectfiles_c.html. These highlight areas of code according to how much area or delay may be required to implement it.

One can look at these files by opening them in any Internet browser. project.html.

The project.html file has links to all the files_c.html files that highlight the source code. It also links to the 5 top areas and 5 top delays in the project.

file_c.html

The html versions of the source files show two versions of the source code. The first is colored according to the area required to implement the code; the second according to the amount of delay. Cool colors (blues and greens) indicate a small area or delay; hot colors (red and yellow) show where there are large areas or delays. There are full color tables at the end of each section. The five largest delays and areas are underlined and tagged with the number of gates or logic levels needed. These estimates are only a guide since full place and route is needed to get exact logic area and timing information.

The Build Menu

FIG. 22 illustrates table showing a build menu 2200, in accordance with one embodiment of the present invention.

Debugger and Simulator

FIG. 22A illustrates a method 2250 for debugging a computer program, in accordance with one embodiment of the present invention. In general, in operation 2252, a plurality of threads is identified in a computer program.

Selection of one of the threads is allowed in operation 2254. In another aspect, the thread may be selected by inserting a breakpoint in the computer program. As may soon become apparent, this or any other desired method may be used to carry out the selection. As such, the user can choose to jump between threads existing in the same clock cycle. Note use of the "follow" command hereinafter.

The selected thread is then debugged. See operation 2256. In one aspect of the present invention, a default thread may be initially debugged without user action (automatically). As an option, the default thread may be a thread that is first encountered in the computer program. In a further aspect, the debugging may utilize a clock associated with the selected thread.

The simulator thus allows one to test the program without using real hardware. It allows one to see the state of every variable (register) in the program at every clock cycle. One can select which variables are to be displayed by using the Watch and Variable windows. One can see the current threads running in the Threads window and the current clocks used in the Clocks window. A person can see the current function, and what functions were called to reach it, in the Call Stack window.

One can run the code in the simulator in several ways:

Run until the end (never ends on a continuous program loop)

Run until one reaches the current cursor position

Run until one reaches a user-defined breakpoint

Step through the code.

When one is using the debugger one can be running the simulation (run mode) or pausing the simulation (break mode). When the simulation has paused (in one of the ways given above or by using the Break command) one can easily examine variables, change window displays, or set breakpoints. When the simulation is in run mode, one can only observe.

When one starts the debugger, a Debug menu appears. FIGS. 23A and 23B illustrate the various commands 2200 associated with the debug menu, in accordance with one embodiment of the present invention.

One can also set breakpoints on valid code lines. When the debugger reaches a breakpoint it may pause until one requests it to continue.

The Debugger Interface

The debugger interface consists of a plurality of windows. FIG. 24 illustrates a table 2400 showing the various windows associated with the debugger interface, in accordance with one embodiment of the present invention.

Symbols in the Editor Window

The statements associated with the current clock tick are marked with arrows. All of these statements execute together. If there is a par statement in the code, the execution may split into separate threads, one for each branch of the par statement. The threads execute in parallel. When one is debugging, one can only follow one thread at a time. The current thread has arrows marked in yellow and white. White arrows show combinatorial code that may be executed on the next clock tick. A yellow arrow shows the current point.

The other threads have the points that may be executed on the current clock cycle in dark gray. If one single-steps through the Handel-C code, one may see the arrows move.

The Variables Window

FIG. 25 illustrates a variables window interface 2500, in accordance with one embodiment of the present invention. The Variables window always shows the current variables 2502. When their values change, the color changes from black to red. The window has two tabs 2504, Auto and Locals. The Auto tab shows variables that have been automatically selected. They are variables used in the current and previous statement in the current thread. It also displays return values when one comes out of or step overs a function.

The Locals tab shows the variables that are local to the current function or macro.

The Watch Windows

There are four watch windows. One can select variables to be displayed in each window, and look at their values at any breakpoint or as one step through the program.

One can add a variable to the watch window by typing its name. The watch window has an expression evaluator. If one types in an expression, the result may be evaluated.

The Call Stack Window

FIG. 26 illustrates the current positioning function blib 2600, and the related call stack window. The functions called on the way to the current function are displayed in the Call Stack window. This shows the current function at the top of the window, and the functions that have not yet completed beneath.

The current function in the current thread is marked with a yellow arrow. If multiple threads that are running different functions, the other current functions are marked with green arrows.

The Threads Window

FIG. 27 illustrates a threads window interface 2700, in accordance with one embodiment of the present invention. All threads 2702 are displayed in the Threads window.

The thread column shows the thread ID 2704 (how the simulator identifies the thread) The yellow arrow 2706 indicates the current thread. The grey arrows 2708 indicate threads with the same clock as the current thread. The Detail column gives an outline of the provenance of this thread. The picture shows four threads that are branches of the replicated par in queue.c. They are distinguished here by the par (i=XXX) detail. The Location column tells one the current line number of that thread in the code.

Right-click in the Threads window to see a menu:

Show Location shows one the source file and scrolls to the right position

Follow tells the debugger to follow that thread (make it the current thread)

The Clocks Window

FIG. 28 illustrates a variables window interface 2800, in accordance with one embodiment of the present invention. All clocks 2802 used are displayed in the Clocks window. The current clock is marked with a yellow arrow. It is identified by the full pathname of the file referencing it. The clock cycle count 2804 is also displayed in the Clocks window. Double-clicking a clock takes one to the clock definition.

Using the Debugger Commands

One can use the debugger commands to go through every line of the code, step over functions and macros, or the run the code until a breakpoint has been reached.

Single Stepping

The simulator steps through the program, one clock cycle at a time. Essentially, assignments, and reads and writes to channels take one clock cycle, everything else is `free`. In a sequential language, such as ISO-C, one can step through code one line at a time, and one stop at an execution point. Because Handel-C is a parallel language, there can be multiple execution points. Because parallel threads are implemented as separate pieces of logic, multiple statements may execute on the same clock tick.

Single stepping through the program does not mean stepping through it one line at a time, or one statement at a time.

One can choose to Step Into, Step Out of or Step Over functions and macros. If one wants to move forward a single line, rather than a complete clock cycle, one can use the Advance command.

Using Breakpoints

FIG. 29 illustrates a breakpoints window interface 2900, in accordance with one embodiment of the present invention. If a person does not wish to single-step through the code, one can run until he or she reaches a breakpoint.

Setting Breakpoints

Select the line of code where one wishes the simulator to pause. (Use Edit>Find to hunt for known names.)

Click the breakpoint button OR

Select Break from the Debug menu. OR

Right-click the mouse and select Insert Breakpoint

Disabling Breakpoints

Breakpoints can be active or inactive. If one wishes to keep a breakpoint but not to stop at it,

Find the line of code where the breakpoint is set; right-click the mouse and select Disable Breakpoint

All breakpoints are listed in the Edit>Breakpoints dialog box. One can also disable a breakpoint by unchecking its box in this dialog.

Removing Breakpoints

Find the line of code where the breakpoint is set.

Click the breakpoint button OR

Right-click the mouse and select Remove Breakpoint OR

Open the breakpoints dialog (Edit>Breakpoints), select the

breakpoint(s) to be removed and click Remove.

Breakpoints in Replicated Code

If one sets a breakpoint in replicated code, a breakpoint may be set in every copy of the code. When one steps through it, the arrows may not appear to advance, but one can see the thread changing in the Threads window.

Breakpoints in Macros and Inline Functions

One cannot set breakpoints in macro expressions. If a person sets a breakpoint in an inline function or a macro procedure, the breakpoint may occur every time that the code is used.

Following Threads

The default thread followed is the one that appears first in the code. One can follow another thread by:

Selecting the code to follow in the code editor, right-clicking the mouse and selecting Follow Thread OR

Opening the Threads window, selecting a thread, right-clicking and selecting Follow Thread OR

By setting a breakpoint within that thread.

Setting a breakpoint in a thread makes that the current thread when the breakpoint is reached.

Selecting Clocks

The clock used is the one associated with the current thread. One can change the clock domain followed by:

following a different thread

setting a breakpoint within the thread to be followed

All clocks used are displayed in the Clocks window. The current clock is marked with a yellow arrow. It is identified by the full pathname of the file referencing it.

The current clock cycle count is also displayed in the Clocks window.

Following Function Calls

The way a function has been called is displayed in the Call Stack window. This shows the current function at the top of the window, and the uncompleted functions that called it beneath. The current function in the current thread is marked with a yellow arrow. If multiple threads are running different functions, the other current functions are marked with green arrows. If a function has stopped at a breakpoint, the breakpoint marker is shown in the Call Stack window.

Examining Variables

There are two windows for examining variable values

Watch

Variables

By default variables are displayed in decimal. One can change the base by right-clicking within the window and selecting a new value from the pop-up menu. One can change the display base of an individual variable using the Handel-C specification with {base=n}. One can turn off the display of a variable by using the Handel-C specification with {show=0}.

Int 32 Pike with {Show=0};

Arrays and structures are displayed with a +button next to the name. Click on this button to display individual array elements or structure members.

Configuration

In debug mode, the project configuration for debug is set by default.

Debug Configuration

The settings specific to debug are:

Preprocessor defines the variables DEBUG and SIMULATE. This allows one to set up the code (see examples below) according to whether a person is using the simulator, e.g. use simulator channels instead of real interfaces.

Compiler Generate Debug and Generate warning boxes checked

Linker Output format set to Simulator; Save browse info box checked; Generate estimation information option (create html files) switched off.

Debugger Working directory for debugger set to current (.).

Optimizations High-level optimization switched on.

Hardware Embodiments

If one is approaching Handel-C from a hardware background, one should be aware of these points:

Handel-C is halfway between RTL and a behavioral HDL. It is a high-level language that requires one to think in algorithms rather than circuits.

Handel-C uses a zero-delay model and a synchronous design style.

Handel-C is implicitly sequential. Parallel processes may be specified.

All code in Handel-C (apart from the simulator chanin and chanout commands) can be synthesized. so one may ensure that he or she disables debug code when he or she compiles to target real hardware.

Signals in Handel-C are different from signals in VHDL; they are assigned to immediately, and only hold their value for one clock cycle.

Handel-C has abstract high-level concepts such as pointers.

Points of Difference

If one is an experienced C user, he or she may be caught unawares by some of the differences between C and Handel-C. The differences are summarized hereinafter.

FIGS. 30 and 31 illustrate a table showing various differences 3100 between Handel-C and the conventional C programming language, in accordance with one embodiment of the present invention.

Porting C to Handle-C

Introduction

This section illustrates the general process of porting an existing conventional C routine to Handel-C. The general issues are discussed first and then illustrated with the particular example of an edge detection routine. This example illustrates the whole conversion process from conventional C program to optimized Handel-C program and also shows how to map conventional C onto real hardware. There is also a section detailing the differences between conventional C and Handel-C.

General Porting Issues

In general, there are a number of stages to porting and mapping a conventional C program to hardware. These are:

1. Decide on how the software system maps onto the target hardware platform. For example, external RAM connected to the FPGA can be used to hold buffers used in the conventional C program. This mapping may also include partitioning the algorithm between multiple FPGAs and, hence, splitting the conventional C into multiple Handel-C programs.

2. Convert the conventional C program to Handel-C and use the simulator to check correctness. Remember that there may be optimizations that can be made to the algorithm given that a Handel-C program can use parallelism. For example, one can sort numbers more quickly in parallel by using a sorting network. This form of coarse grain parallelism can provide massive performance gains so time should be spent on this step.

3. Modify code to take advantage of extra operators available in Handel-C. For example, concatenation and bit selection can be used where conventional C programs may use shifts and masks. Simulate again to ensure program is still correct.

4. Add fine grain parallelism such as making parallel assignments or executing individual instructions in parallel to fine-tune performance. Again, simulate to ensure that the program still functions correctly.

5. Add the hardware interfaces necessary for the target architecture and map the simulator channel communications onto these interfaces. If possible, simulate to ensure mapping has been performed correctly.

6. Use the FPGA place and route tools to generate the FPGA image(s).

These steps are obviously guidelines only--some of the stages may not be relevant to the design or one may require extra stages if the design does not fit this example flow. This list provides a starting point and guidelines for how to approach the process of porting the code. A full example follows after the section comparing C and Handel-C.

One of the most important factors in selecting a good partitioning of a program between hardware and software is to take into account the cost of communicating data between the two halves of the partition. The communication link between the hardware and software is determined by a number of parameters particular to a given target. These parameters include bandwidth, latency, and (per-message) overhead.

For some languages, it is possible to determine exactly the amount of data that would be transferred by an operation such as a function call, since all the data is passed in one direction by the arguments, and in the other direction by the return value. However, many other languages (including C) pass data implicitly using pointers. For these languages static analysis techniques cannot yield usefully accurate results. It is in this situation that the techniques presented are applicable.

One technique relies on dynamic analysis of the source program. The source program is compiled to platform independent bytecode. A suitable bytecode interpreter is augmented such that accesses to memory (typically load and store instructions) can be traced. In this way the memory use behavior of each part of the source program can be examined by executing the program and analyzing the generated trace. A simplistic implementation of this technique suffers from the problem of generating a very large amount of profiling data. The present embodiment uses two alternative techniques to solve this problem:

1. During execution of a single function (or set of functions grouped as a domain) the present embodiment records a map of all the memory accessed. At the end of execution of the function outputs only a compressed version of this map (compressed using a technique such as run-length encoding). Since functions may typically tend to use blocks of memory in ranges, rather than a fully random access pattern, this results in significant savings in the size of the generated output. The output is then analyzed post-hoc to determine where memory transfers would have taken place between domains of a partitioned system.

2. Alternatively, some of the analysis can happen on-line during the execution of the program. In this case, a memory map of the program is kept which records which functions (or groups of functions) have valid copies of small ranges of memory (micropages). When a function reads for an area of memory, this map is checked to see which functions have a valid copy of the data. If the current function has a valid copy no further action is taken. If no function has a valid copy of the data then it is taken as coming from an external source function. Otherwise a transfer from one of the other functions to the current function is recorded, and the map records that the current function now has a valid copy of the micropage. When a write occurs, exactly the same action takes place except the ownership of the micropage becomes only the current function, no other functions now possess valid (up-to-date) copies of the data in the given page. The result of the execution of a program in this way is a 2-dimensional table recording data transfers from functions to functions. This data can then be further analyzed to give estimates for the performance of given partitions, be used to decide partitions, or be presented in a graphical form (such as a directed graph). It has been assumed in the above that the compiled code is executed within a virtual machine. It is possible via modification to the compiler to generate native code with appropriate traps on memory accesses and calls to functions implemented either of the above strategies. This results in an improvement in performance over the bytecode alternative.

Comparison between Conventional C and Handel-C

This section details the types, operators, and statements available in conventional C and Handel-C. The tables should be used to get an idea of which parts of the conventional C program need to be altered. Differences in implementation between Handel-C and ISO-C:

Functions may not be recursive.

Old-style function declarations are not necessarily supported.

Variable length parameter lists are not necessarily supported.

One may not necessarily change the width of a variable by casting

One cannot convert pointer types except to and from void, between signed and unsigned and between similar structs

Floating point is not necessarily supported, but may be supported (optionally) in some embodiments

Statements in Handel-C may not cause side-effects. This has the following consequences:

local initializations are not supported.

the initialization and iteration phases of for loops may be statements, not expressions.

shortcut assignments (e.g. +=) may appear as standalone statements.

Types, Type Operators and Objects

FIG. 32 illustrates a table of types, type operators and objects 3200, in accordance with one embodiment of the present invention.

Statements

FIG. 33 illustrates a table of statements 3300, in accordance with one embodiment of the present invention.

Expressions

FIG. 34 illustrates a table of expressions 3400, in accordance with one embodiment of the present invention.

In Both/in Conventional C Only/in Handel-C Only

The Edge Detector Example (C to Handel-C)

The edge detector consists of a number of versions of the same application that detail the process of porting a conventional C application to a Handel-C application. All but the final stage (targeting real hardware) are presented as complete examples that may be simulated with the Handel-C simulator. They are stored as separate projects within a single workspace.

The original C code is supplied in source and compiled versions. One can execute this code, and simulate the different versions of the ported code. Note that the examples use specific hard-coded filenames for the image data. The image data filenames may be exactly the same as those given in the examples, or the source code may be edited and recompiled.

The Original Program

The example used in this section to illustrate the porting process is that of a simple edge detector. Each of the stages outlined in the previous section is illustrated with complete code listings. The original conventional C program is given below.

#include <stdio.h>

#include <stdlib.h>

/*

*Define name of input/output files

*/

#define SourceFileName "../Data/source.raw"

#define DestFileName "../Data/dest.raw"

/*

*Define parameters of image and threshold for edges

*/

#define WIDTH 256

#define HEIGHT 256

#define THRESHOLD 16

/*

*Edge detector procedure

*/

void edge_detect(unsigned char *Source, unsigned char *Dest)

{

int x, y;.Targeting Hardware

/*

*Loop round for every pixel

*/

for (y=1; y<HEIGHT; y++)

for (x=1; x<WIDTH; x++)

{

/*

*Determine whether there is an edge here

*/

if (abs(Source[x+y*WIDTH]-

Source[x-1+y*WIDTH])>THRESHOLD .vertline..vertline.

abs(Source[x+y*WIDTH]-

Source[x+(y-1)*WIDTH])>THRESHOLD)

Dest[x+y*WIDTH]=0xFF;

else

Dest[x+y*WIDTH]=0;

}

}

/*

*Main program

*/

int main(void)

{

unsigned char *Source=malloc(WIDTH*HEIGHT);

unsigned char *Dest=malloc(WIDTH*HEIGHT);

FILE *FilePtr;

/*

*Read image from file

*/

FilePtr=fopen(SourceFileName, "rb");

fread(Source, sizeof(unsigned char), WIDTH*HEIGHT, FilePtr);

fclose(FilePtr);

/*

*Do edge detection

*/

edge_detect(Source, Dest);

/*

*Write results back to file

*/

FilePtr=fopen(DestFileName, "wb");

fwrite(Dest, sizeof(unsigned char), WIDTH*HEIGHT, FilePtr);

fclose(FilePtr);

return 0;

}

The file reads data from a raw data file into a buffer. The function edge_detect then performs a simple edge detection and stores the results in a second buffer which is stored in a second file. The edge detection is performed by subtracting the pixel values for adjacent horizontal and vertical pixels, taking the absolute values and thresholding the result. The source and destination images are both 8 bit per pixel greyscale images. The conventional C source file and a compiled version are provided along with an example image (source.bmp). One can run the program now to see the results. This is done using the following commands:

1. Convert the example BMP file to raw data with the bmp2raw utility.

bmp2raw-b source.bmp source.raw 8bppdest.rgb

2. Execute the conventional C edge detector.

edge_c

3. Convert the output from the edge detector back to a BMP file using the raw2bmp utility:

raw2bmp -b 256 dest.raw dest_c.bmp 8bppsrc.rgb

One can use the standard Windows 98 and NT Paint utility to display the source and destination BMP files to compare results.

First Attempt Handel-C Program

The first step is to port the conventional C to Handel-C with as few changes as possible to ensure that the resulting program works correctly. The file handling sections of the original program are modified to read data from a file and write data back to a file using the Handel-C simulator. The resulting program is given below.

The following points should be noted about the port:

1. The Source and Dest buffers have been replaced with two RAMs.

2. An abs ( ) macro expression provided in stdlib.h has been used to replace the standard C function.

3. The x and y variables have been given widths equal to the number of address lines required for the RAMs to simplify the index of the RAM. Without this, each variable would have to be padded with zeros in its MSBs to avoid a width conflict when accessing the RAM.

4. Temporary variables have been used for the three pixels read from RAM to avoid the restriction on only one access per RAM per clock cycle. Without these variables, the condition for the if statement would require multiple accesses to the Source RAM.

5. The pixel values may be extended by one bit to ensure the subtract does not underflow.

6. The Input and Output channels are declared to read from and write to files for simulation. The file name is given using the with specification, e.g. chanin unsigned Input with {infile="../Data/source.dat"};

To execute the Handel-C code:

1. Convert the example BMP file to text data with the bmp2raw utility by typing:

bmp2raw source.bmp source.dat 8bppdest.rgb

2. Open the Handel-C edge detector workspace (Examples/Handel-C/Examples/ExampleC/ExampleC.hw) by double-clicking on it. Build and run the project.

3. Convert the output from the edge detector back to a BMP file using the raw2bmp utility by typing:

raw2bmp 256 dest.dat dest .sub.13 v1.bmp 8bppsrc.rgb.

Example Code Version 1

/****************************************************************

*Description*

*Handel-C edge detector example program--First pass.*

**

*To test open the workspace file `ExampleC.hw`.*

**

*****************************************************************

/

*

*Define a clock

*/

set clock=external "P1";

/*

*Define parameters of image and threshold for edges

*/

#define LOG2_WIDTH 8

#define WIDTH 256

#define LOG2_HEIGHT 8

#define HEIGHT 256

#define THRESHOLD 16

/*

*Declare RAMs for source and destination images

*/

ram unsigned char Source[WIDTH*HEIGHT];

ram unsigned char Dest[WIDTH*HEIGHT];

/*

*Declare a macro for absolute value

*/

macro expr abs(a)=(a<0? -a: a);

/*

*Edge detector procedure

*/

void edge.sub.13 detect( )

{

unsigned (LOG2_WIDTH+LOG2_HEIGHT) x;

unsigned (LOG2_WIDTH+LOG2_HEIGHT) y;

int 9 Pixel1, Pixel2, Pixel3;

/*

*Loop round for every pixel

/*

for (y=1; y<HEIGHT; y++)

.gamma.

for (x=1; x<WIDTH; x++)

{

Pixel1=(int)(0 @ Source[x+y*WIDTH]);

Pixel2=(int)(0 @ Source[x-1+y*WIDTH]);

Pixel3=(int)(0 @ Source[x+(y-1)*WIDTH]);

/*

*Determine whether there is an edge here

*/

if (abs(Pixel1-Pixel2)>THRESHOLD .vertline..vertline.

abs(Pixel1-Pixel3)>THRESHOLD)

{

Dest[x+y*WIDTH]=0xFF;

}

else

{

Dest[x+y*WIDTH]=0;

}

}

}

}

/*

*Main program

*/

void main(void)

{

chanin unsigned Input with {infile="../Data/source.dat"};

chanout unsigned Output with {outfile="../Data/dest.dat"};

unsigned (LOG2_WIDTH+LOG2_HEIGHT) i;

unsigned (LOG2_WIDTH+LOG2_HEIGHT) j;

/*

*Read image from file

/*

for (i=0; i<HEIGHT; i++)

for (j=0; j<WIDTH; j++)

Input ? Source[j+i*WIDTH];

/*

*Do edge detection

*/

edge_detect( );

/*

*Write results back to file

*/

for (i=0; i<HEIGHT; i++)

for (j=0; j<WIDTH; j++)

Output ! Dest[j+i*WIDTH];

delay;

}

First Optimizations of the Handel-C Program

The next development stage is to change some of the operators familiar in C to operators more suitable for Handel-C. In the above example, every time the Source or Dest RAM is accessed, a multiplication is made by the constant WIDTH. The Handel-C optimizer simplifies this to a shift left by 8 bits but one could easily do this by hand to reflect the hardware more accurately and reduce compilation times. New macros may also be introduced to access the RAMs given x and y co-ordinates:

macro expr ReadRAM(a, b)=

((unsigned 1)0)@

Source[(0@a)+((0@b)<<8)];

macro proc WriteRAM(a, b, c)

Dest[(0@a)+((0@b)<<8)]=c;

Notice how the macros pad both the result and the co-ordinate expressions with zeros. This allows one to reduce the width of the x and y counters to 8 bits each and reduces clutter in the rest of the program. This width reduction does mean that the loop conditions may be altered because x and y are no longer wide enough to hold the constant 256. Instead, one could test against zero since the counters may wrap round to zero after 255.

The modified edge_detect function is shown below:

Example Code Version 2

void edge_detect( )

{

unsigned LOG2_WIDTH x;

unsigned LOG2_HEIGHT y;

int 9 Pixel1, Pixel2, Pixel3;

/*

*Loop round for every pixel

*/

for (y=1; y!=0; y++)

{

for (x=1; x!=0; x++)

{

Pixel1=(int)ReadRAM(x, y);

Pixel2=(int)ReadRAM(x-1, y);

Pixel3=(int)ReadRAM(x, y-1);

/*

*Determine whether there is an edge here

*/

if (abs(Pixel1-Pixel2)>THRESHOLD .vertline..vertline.

abs(Pixel1-Pixel3)>THRESHOLD)

WriteRAM(x, y, 0xFF);

else

WriteRAM (x, y, 0);

}

}

To execute this version of the Handel-C code:

1. Make the version 2 project current within the ExampleC workspace by selecting Project>Set Active Project>Edge_v2:

2. Build and run the project by selecting Build>Build Edge_v2 followed by F5.

3. Convert the output from the edge detector back to a BMP file using the raw2bmp utility by opening a Command Prompt or MS-DOS window. Change to the Version 2 project directory and type: raw2bmp 256 dest.dat dest_v2. bmp 8bppsrc.rgb

Adding Fine Grain Parallelism

There are two areas in this program that can be modified to improve performance. The first is to replace for loops with while loops and the second solves the problem of multiple accesses to external RAM in single clock cycles.

The for loop expands into a while loop inside the compiler in the following way:

for (Init; Test; Inc)

Body;

becomes:

{

Init;

while (Test)

{

Body;

Inc;

}

}

This is normally not efficient for hardware implementation because the Inc statement is executed sequentially after the loop body when in most cases it could be executed in parallel. The solution is to expand the for loops by hand and use the par statement to execute the increment in parallel with one of the statements in the loop body.

The second optimization concerns the three statements required to read the three pixels from external RAM. Without the restriction on multiple accesses to RAMs the loop body of the edge detector could be executed in a single cycle whereas our current program requires four cycles, three of which access the RAM. What is needed is a modification to eliminate as many of these RAM accesses as possible.

Since it is not possible to access the external RAM more than once in one clock cycle, the only way to improve this program is to access multiple RAMs in parallel. It should also be clear that the current program accesses most locations in the external RAM three times. For example, when x is 34 and y is 56 the three pixels read are at co-ordinates (34,55), (33,56) and (34,56).

The first of these is also read when x is 34 and y is 55 and when x is 35 and y is 55 whereas the second is also read when x is 33 and y is 56 and when x is 33 and y is 57. If one can devise a scheme whereby pixels are stored in two extra RAMs when they are read from the main external RAM for the first time then they could simply access these additional RAMs to get pixel values in the main loop.

The first step is to store the previous line of the image in an internal RAM on the FPGA. This allows the pixel above the current location to be read at the same time as the external RAM is accessed. The second step is to store the pixel to the left of the current location in a register. The loop body then looks something like this:

Pixel1=ReadRAM(x, y);

Pixel2=PixelLeft;

Pixel3=LineAbove[x];

LineAbove[x]=Pixel1;

PixelLeft=Pixel1;

At first glance, it looks like things have been worse by increasing the number of clock cycles but one can now add parallelism to make it look like this:

par

{

Pixel1=(int)ReadRAM(x, y);

Pixel2=PixelLeft;

Pixel3=(int)LineAbove[x];

}

par

}

LineAbove [x]=Pixel1;

PixelLeft=Pixel1;

}

Note the LineAbove RAM may be initialized at the start of the image to contain the first line of the image and the PixelLeft variable may be initialized at the start of each line with the left hand pixel on that line. Since the second of these par statements and the if statement are not dependent on each other they can be executed in parallel. Putting all these modifications together gives an edge_detect procedure shown below.

Notice that the increment of y has been moved from the end of the loop to the start and the start and end values have been adjusted accordingly. This allows the increment to be executed without additional clock cycles which would have been required if it were placed at the end of the loop.

To execute this version of the Handel-C code:

1. Make the version 3 project current within the ExampleC workspace by selecting Project>Set Active Project>Edge_v3;

2. Build and run the project by selecting Build>Build Edge_v3 followed by F5.

3. Convert the output from the edge detector back to a BMP file using the raw2bmp utility by opening a Command Prompt or MS-DOS window. Change to the Version 3 project directory and type: raw2bmp 256 dest.dat dest_v3.bmp 8bppsrc.rgb

Example Code Version 3

void edge_detect( )

{

unsigned LOG2_WIDTH x;

unsigned LOG2_HEIGHT y;

int 9 Pixel1, Pixel2, Pixel3, PixelLeft;

ram LineAbove[ ];

/*

*Initialise the LineAbove RAM

*/

x=1;

while (x!=0)

{

par

{

LineAbove [x]=ReadRAM(x, (unsigned LOG2_HEIGHT)0);

x++;

}

}

/*

*Loop for every line

*/

y=0;

while (y!=255)

{

/*

*Initialise the PixelLeft register

*/

par

{

x=1;

PixelLeft=(int)ReadRAM((unsigned LOG2_WIDTH)0, y+1);

y++;

}

/*

*Loop for every column

/*

while (x!=0)

{

/*

*Update pixel registers

*/

par

{

Pixel1=(int)ReadRAM(x, y);

Pixel2=PixelLeft;

Pixel3=(int)LineAbove[x];

}

/*

*Determine whether there is an edge here

*/

par

{

LineAbove[x]=(unsigned)Pixel1;

PixelLeft=Pixel1;

if (abs(Pixel1-Pixel2)>THRESHOLD

abs(Pixel1-Pixel3)>THRESHOLD)

WriteRAM(x, y, 0XFF);

else

WriteRAM(x, y, 0);

x++;

}

}

Further Fine Grain Parallelism

The core loop body has now been reduced from five clock cycles (including the loop increment) to 2 clock cycles. One can even do better because one should be able to access the two off-chip banks of RAM in parallel. Thus, the two parallel statements in the loop body could be executed simultaneously if one could organize the data flow correctly.

The program has been modified because the LineAbove internal RAM is accessed in both clock cycles. Paralleling the two statements is not permitted because it would involve two accesses to the same internal RAM in a single clock cycle. The solution is to increase the number of internal RAMs. The current line can be copied into one internal RAM while the previous line is read from a second internal RAM. The two internal RAM banks can then be swapped for the next line.

By also removing the Pixel1, Pixel2 and Pixel3 intermediate variables, the two statements in the loop body can be rolled into one. A person may use the LSB of the y coordinate to determine which line buffer to read from and which line buffer to write to. The external RAM read is done using a shared expression (RAMPixel) since one needs the value from the RAM in multiple places but only want to perform the actual read once.

The new version of the edge detector is shown below. The core loop is now only one clock cycle long and is executed 255 times per line. One extra clock cycle is required per line for the initialization of variables and 255 lines are processed. In addition, 255 cycles are required to initialize the on-chip RAM and one extra clock cycle per frame is required for variable initialization. This gives a grand total of 65536 clock cycles per frame or an average of exactly one pixel per clock cycle. Since there is no way of getting the image into or the results out from the FPGA any faster than this one can conclude that the fastest possible solution to our problem has been reached.

Example Code Version 4

void edge_detect( )

{

unsigned LOG2_WIDTH x;

unsigned LOG2_HEIGHT y;

int 9 PixelLeft;

ram unsigned char LineAbove0[ ], LineAbove1[ ];

unsigned 5 i;

/*

Initialise the x and y counters and the LineAbove RAM

*/

par

{

x=1;

y=0;

}

while (x!=0)

{

par

{

LineAbove0[x]=ReadRAM(x, (unsigned LOG2_HEIGHT)0)<-8;

x++;

}

}

/*

*Loop for every line

*/

while (y!=255)

{

/*

*Initialise the PixelLeft register

*/

par

{

x=1;

PixelLeft=(int)ReadRAM((unsigned LOG2_WIDTH)0, y+1);

Y++;

}

/*

*Loop for every column

*/

while (x !=0)

{

par

{

shared expr RAMPixel=(int)ReadRAM(x, y);

shared expr PixelAbove=(int)(y[0]==0 ? 0@LineAbove0[x]

0@LineAbove1[x]);

macro expr abs(a)=(a<0? -a: a);

/*

*Update pixel registers

*/

if (y[0]==1)

LineAbove0[x]=(unsigned)(RAMPixel<-8);

else

LineAbove1[x]=(unsigned)(RAMPixel<-8);

PixelLeft=RAMPixel;

/*

*Determine whether there is an edge here

*/

if (abs(RAMPixel-PixelLeft)>THRESHOLD .vertline..vertline.

abs (RAMPixel-PixelAbove)>THRESHOLD)

WriteRAM(x, y, 0xFF);

else

WriteRAM(x, y, 0);

x++;

}

}

}

}

To execute this version of the Handel-C code:

1. Make the version 4 project current within the ExampleC workspace by selecting Project>Set Active Project>Edge_v4:

2. Build and run the project by selecting Build>Build Edge_v4 followed by F5

3. Convert the output from the edge detector back to a BMP file using the raw2bmp utility by opening a Command Prompt or MS-DOS window. Change to the Version 4 project directory and type: raw2bmp 256 dest.dat dest_v4.bmp 8bppsrc.rgb

Adding the Hardware Interfaces

Once the program has been simulated correctly one may add the necessary hardware interfaces. The interface with the host requires the same signals and timings as the example set out hereinafter. The code will now be taken from that example and used to produce two macro procedures--one to read a word from the host and one to write a word to the host. (These could also be implemented as functions) The suitably modified code looks like this:

// Read word from host

macro proc ReadWord(Reg)

{

while (ReadReady==0);

Read=1; // Set the read strobe

par

{

Reg=dataB.in; // Read the bus

Read=0; // Clear the read strobe

}

}

// Write one word back to host

macro proc Writeword (Expr)

{

par

{

while (WriteReady==0);

dataBOut=Expr;

}

par

{

En=1; // Drive the bus

Write=1; // Set the write strobe

}

Write=0; // Clear the write strobe

En=0; // Stop driving the bus

}

One also needs to define the pins for the external RAMs and remove the RAM declarations added to simulate the RAMs. The main program also needs to be modified to include the code to synchronies the frame grabber with the edge detector. The project settings need to be changed in the GUI. Set the configuration to VHDL or EDIF. This code is not designed for a specific device. One would need to know the appropriate pins for the device one are targeting. The pin definitions given are examples only and do not reflect the actual pins available on any particular device. The code excluding the edge detection and host interface macros is given below.

#define LOG2_WIDTH 8

#define WIDTH 256

#define LOG2_HEIGHT 8

#define HEIGHT 256

set clock=external "P1";

unsigned 8 Threshold;

// External RAM definitions/declarations

ram unsigned 8 Source[65536] with {

offchip=1,

data={"P1", "P2", "P3", "p4",

"P5", "P6", "P7", "p8"},

addr={"P9", "P10", "P11", "P12",

"P13", "P14", "P15", "P16",

"P17", "P18", "P19", "P20",

"P21", "P22", "P23", "P24"},

we={"P25"}, oe={"P26"}, cs={"P27"}};

ram unsigned 8 Dest[65536] with {

offchip=1,

data={"P28", "P29", "P30", "P31",

"P32", "P33", "P34", "P35"},

addr={"P36", "P37", "P38", "P39",

"P40", "P41", "P41", "P43",

"P44", "P45", "P46", "P47",

"P48", "P49", "P50", "P51"},

we={"P52"}, oe={"P53"}, cs={"54"}};

macro expr ReadRAM(a, b)=

((unsigned 1)0) @ Source[(0@a)+((0@b) <<8)];

macro proc WriteRAM(a, b, c) Dest[(0@a)+((0@b)<<8)]=c;

#ifndef SIMULATE

// Host bus definitions/declarations

unsigned 8 dataBOut;

int 1 En=0;

interface bus_ts_clock_in(int 4) dataB(dataBOut, En==1) with

{data={"P55", "P56", "P57", "P58"}};

int 1 Write=0;

interface bus_out( ) writeB(Write) with

{data={"P59"}};

int 1 Read=0;

interface bus_out ( ) readB(Read) with

{data={"P60"}};

interface bus_clock_in(int 1) WriteReady( ) with

{data={"P61"}};

interface bus_clock_in(int 1) ReadReady( ) with

{data={"P62"}};

#endif

Insert edge_detect, ReadWord and WriteWord function and macro

definitions here

void main(void)

{

ReadWord(Threshold);

while(1)

{

unsigned Dummy;

ReadWord(Dummy);

edge_detect( );

WriteWord (Dummy);

}

SUMMARY

The aim of this section has been to show the development of a real Handel-C program from conventional C to a full program targeted at hardware. Is has also shown the performance benefits of the Handel-C approach by demonstrating a real time application executing with a great deal of parallelism.

Targeting Hardware

Targeting Hardware via VHDL

If one is integrating Handel-C code with raw VHDL code, one would compile the Handel-C for debug, and use ModelSim to compile the VHDL for simulation. One could then compile the Handel-C to VHDL and use Simplify LeonardoSpectrum or FPGA Express to synthesize the code. One would then use Xilinx or Altera tools to place and route it.

Linking to the Handel-C VHDL Library

The HandelC.vhdl file may be supplied which supports all Handel-C VHDL files. To use Handel-C VHDL, one may compile the HandelC.vhdl file into a library called HandelC. (Consult the documentation for the synthesis or simulation tool on compiling library files.) A person also needs to compile the supplied file ROC.vhdl into the work library for simulation.

Connecting Handel-C EDIF to VHDL

If one compiles a Handel-C file to EDIF and wish to connect it to a VHDL, he or she may be aware that the ports in EDIF and VHDL are different. EDIF ports consist of a collection of single wires. VHDL ports are normally described as n-bit wide cables. To ensure that the generated EDIF can connect to the VHDL, the VHDL ports may be listed as single-bit wires.

VHDL Component Within Handel-C Project

Handel-C code

set clock=external "D17";

unsigned 4 x;

interface vhdl_component(unsigned 4 return_val)

vhdl_component_instance(unsigned 1 clk=_clock,

unsigned 4 sent_value=x);

etc . . .

unsigned 4 y;

y=vhdl_component_instance; // Read from VHDL component

x=y; // Write to VHDL component

VHDL Code

The VHDL entity may need an interface like this to be compatible with the Handel-C.

entity vhdl_component is

port (

clk: in std_logic;

sent_value.sub.-- 0: in std_logic;

sent_value.sub.-- 1: in std_logic;

sent_value.sub.-- 2: in std_logic;

sent_value.sub.-- 3: in std_logic;

return_val.sub.-- 0: out std_logic;

return_val.sub.-- 1: out std_logic;

return_val.sub.-- 2: out std_logic;

return_val.sub.-- 3: out std_logic

);

end;

Note that all the ports are 1-bit wide, standard_logic types. This is because when the Handel-C is compiled to EDIF, this is how the expanded interface appears. (EDIF cannot represent n-bit wide cables, only single wires).

Handel-C Component within VHDL Project

The Handel-C needs to have ports to its top level, so that the VHDL can connect to them.

unsigned 4 x;

interface port_in(unsigned 1 clk) ClockPort( );

interface port_in(unsigned 4 sent_value) InPort( );

interface port_out( ) OutPort(unsigned 4 return_value=x);

set clock=internal ClockPort.clk;

etc . . .

unsigned 4 y;

y=InPort.sent_value; // Read from top-level VHDL

x=y; // Write to top-level VHDL

VHDL code

The top level VHDL may need to instantiate the Handel-C like

this:

component handelc_component

port (

clk: out std_logic;

clk: in std_logic;

sent_value.sub.-- 0: in std_logic;

sent_value.sub.-- 1: in std_logic;

sent_value.sub.-- 2: in std_logic;

sent_value.sub.-- 3: in std_logic;

return_val.sub.-- 0: out std_logic;

return_val.sub.-- 1: out std_logic;

return_val.sub.-- 2: out std_logic;

return_val.sub.-- 3: out std_logic

);

end component;.

Targeting Hardware via EDIF

To target hardware via EDIF, one may set up the project to target EDIF using the Build>Set Active Configuration command. This compiles directly to an .edf file which can be passed to the place and route tools.

Port Renaming for Debug

To aid in debugging the generated EDIF, one can rename the EDIF nets within the net list such that the Handel-C declaration name appears before the EDIF unique identifier.

To do so, select the Project>Settings . . . command. In the Project Settings dialog that opens, ensure that the EDIF is the type of settings that is being edited.

In the Compiler tab, check the Generate debug information box.

Setting up Place and Route Tools

FIG. 35 illustrates a net list reader settings display 3500, in accordance with one embodiment of the present invention. The Altera EDIF compiler requires a library mapping file. This is supplied as handelc.lmf.

Setting up MaxPlus II to use handelc.lmf

Start MaxPlus II

Open MaxPlus II>Compiler

With the compiler selected, select Interfaces>EDIF Net list Reader Settings.

In the dialog box, specify Vendor as Custom.

Click the Customize>>button (3502)

Select the LMF #1 radio button (3504). Set up the pathname (3506) for the handelc.lmf file.

(Installed in Handel-C installation root.backslash.lmf.)

Setting up Quartus 2000 to use handelc.lmf

FIGS. 36 and 37 illustrates a tool settings display 3600 and 3700, in accordance with one embodiment of the present invention.

Start Quartus.

Select the Project>EDA Tool Settings menu command.

In the dialog box, use the pull-down list to set Custom as the Design entry/synthesis tool.

Click Settings. (3602) (Note FIG. 37.)

Set the File name 3702 for the Library Mapping File, click the . . . button to browse for handelc.lmf. (Installed in Handel-C installation root.backslash.lmf.)

Setting up Wire Nam