When considering the design of an expression unit, a number of design decisions must be considered as discussed in Section 2.1.5. The choice of a static or dynamic configuration can be considered first. A static configuration is defined at compilation time of the processor. A number of static configurations could be defined for expression shapes. A dynamic configuration is defined at soft- ware compilation time. For example, the compiler would emit instructions for a basic expression unit configuration for a set of common/basic expressions. However, it may then change the con- figuration of the expression unit to benefit the execution of more tailored expressions. These are likely to be domain or application specific. A dynamic configuration would naturally incur a higher hardware cost. This thesis limits considerations to a statically configured tree. More advanced approaches should be considered as additional work.
Another important design decision is the choice of operators to include and how they should be grouped together. Any arbitrary source base contains many expressions consisting of many shapes. However, when designing a static expression engine the aim is to find a configuration that is able to process as many expressions as possible in a single pass through the tree. Another conflicting
aim is to find a configuration that minimises node wastage in order to fully utilise the expression encoding and instruction stream. The choice of expression engine design is unlimited and finding an optimal configuration is NP-hard. The design could be done ad-hoc or it could be influenced empirically after collecting expression information for representative software that is likely to be executed on the processor. The middle ground is to analyse a source base to assist with an initial design.
To understand the operators needed in an expression tree, a compiler such as GCC could be instrumented. The output from the GCC parser is a tree-based intermediate representation called GENERIC. The purpose of GENERIC is to provide a language-independent way of representing an entire function [50]. This includes declarations, types, statements and expressions. If the out- put is appropriately instrumented, it will realise information about how expressions are composed; in particular, how operators are grouped. However, it is likely that for real-world applications the results obtained would contain many operator combinations, with a large range of frequen- cies. Analysis of expression usage therefore requires more structured future research. This should consider developing an appropriate analysis tool to extrapolate the operator usage at the source language level. In this thesis, an ad-hoc approach was taken for the expression tree design.
From a simplistic viewpoint, an expression tree can be constructed using logical grouping of arithmetic and logical operators. For example, addition and subtraction, multiplication and divi- sion. The nodes of the expression unit can be organised to support the precedence and associativity of C-based languages. For example, in C-based languages, the multiplication operator has higher precedence than the addition operator. It would therefore be sensible to have the multiplica- tion operator nearer the leaf nodes and the addition operator closer to the root node so that the multiplication is completed before the addition.
If the expression engine is designed as a binary tree, it certainly makes it easy to calculate various properties of the tree. With this scheme, a tree with a height of 2 would have 7 processing nodes. However, each leaf node is required to take 2 inputs rvalues and produce a single output result; this cannot be classified as a complete or full binary tree. The design of the Expression Engine is illustrated in Figure 4.2. It can be observed in Figure 4.2 that it can be more accurately described as an n-array tree and it requires fewer bits than the binary tree. This is because each input node has 2 input rvalues and some nodes only require a single configuration bit. The expression tree is influenced by Audsley and Ward’s expression tree illustrated in Figure 2.12, which is based on a dataflow model.
Since each node is capable of multiple operations, control bits are used to configure each node. The expression engine uses 8 bits for addressing an rvalue/lvalue in the memory subsystem. Therefore the expression engine imposes a memory-memory architecture as described by Hennessey and Paterson [8]. There are no explicit registers available, all operations are performed directly on storage elements.
It should be noted that an 8-bit address width for operands (rvalues and lvalues) places severe limitations on the addressing capabilities of the expression engine. This limitation means that currently, only 256 bytes can be accessed. Future work will need to focus on reducing this limitation whilst keeping the encoding length of an expression to a minimum.
Figure 4.2: Expression Engine
In order to evaluate an expression, the following information is required to configure each node in layers 1 - 2 (see Figure 4.2):
• The operators (C0 , C1, C6, C7)
• The input operands (R0 - R5). These refer to rvalues. • How the rvalues should be addressed (Rp0 - Rp5) For the level 3 output node:
• The operator (C2 - C5) • The output operand (lval)