An article by Niklaus Wirth in IEEE Computer (June 1998) inspired me to write a simple hardware compiler. The compiler was written in August 1998. The program I designed is similar to the one described in the article by Niklaus Wirth. It takes a pascal/oberon like program as input and produces an XNF netlist as an output. The compiler has logic to generate all common operations: *, /, -, +, >=, <=, <, >, =.
Let's see some examples of HWCOMP in action. How do you express a divider in HWCOMP? Well that's easy, all it consists of is writing the following program:
module div const integer a const integer b var integer o begin o := a / b end
When presented with the above code, the compiler produces a divider. The output XNF file is expressed solely in terms of primitive gates OR, AND, NOT and D-type flip flops in order to make the XNF file as portable as possible. The size of the integer is dependent on the way the HWCOMP was compiled - one can vary the number of bits used to represent an integer. All integers in HWCOMP are unsigned - signed integers are not provided since they complicate division and multiplication.
When programming in HWCOMP, one should view each statement as taking a single cycle. However tests using "IF" or "WHILE" statements don't count as a cycle. For example the following code takes a single cycle:
module test2 const integer a const integer b var integer min var integer max begin if a < b then min := a, max := b else min := b, max := a end end
Note that the assignment to "max" and "min" are done in parallel as denoted by the comma operator.
As an example of more complex code, a logarithm function is presented below (Niklaus Wirth presented a logarithm function for his hardware compiler in his article):
module log const integer a const integer b var integer x var integer y begin x := 0, y := a while y >= b do x := x + 1, y := y / b end end
The result of the logarithm is output using signal "x". Signal "y" can be ignored. How many gates are needed to represent the logarithm function? This particular function requires 831 components. A component is one of :
HWCOMP performs some simple optimizations on the resulting network of gates. The optimizations are performed at the gate level using simple rules. For example:
Using the simple rules defined above, in the following code, HWCOMP realizes that the output never depends on "i" (the first bit of vector "i"):
module test5 const integer i var integer o begin o := i / 2 end
In fact the simple rules lead to reasonably effective optimisations. The above code uses only 63 components while a full scale divider would have used 674 components.
The HWCOMP source code.
Updated December 4, 2001