## c4Hardware Overview

The following serves as an overview of the capabilities of the c4Hardware library and of the flexibility that it offers.

This page is a work in progress. Please check back for further updates.

On this page:

- Initialisation - A few simple steps needed to add c4Hardware to a program

- Math and Linear Algebra - How data is manipulated in c4Hardware

- Interfacing with MATLAB - writing MEX with c4Hardware

- Debugging Features

- Statistics Counting

- Testbench data generation

- Custom Numeric Types - creating your own numeric types

- Overriding Numeric Functions

### Initialisation

A c4Hardware program is a normal c++ program, or MATLAB Mex function, that calls upon special libraries to handle the linear algebra and bit-accurate emulation functions of your algorithm. Initialisation involves calling a configuration class with a set of parameters :
c4hardware = new c4HardwareConfiguration();

c4HDLRealFloatHandler::registerNumberSystem(c4hardware);

int systemID = c4hardware->createSystem("c4HDLRealFloat","mantissa=6,exponent=6");

c4HDLRealFloatHandler::registerNumberSystem(c4hardware);

int systemID = c4hardware->createSystem("c4HDLRealFloat","mantissa=6,exponent=6");

The systemID is a identifier for the numeric system in use - you are able to use multiple number systems in the same project. Furthermore, <b>in most projects, reconfiguring your number system is simply a case of adjusting the parameters</b> on the above line.

To create a scalar value, vector, or matrix, the following commands are used :

SimValue* scalar = c4hardware->newSimValue(systemID);

SimValueVector* vector = c4hardware->newVector(systemID, rows);

SimValueMatrix* matrix = c4hardware->newMatrix(systemID, rows, cols);

SimValueVector* vector = c4hardware->newVector(systemID, rows);

SimValueMatrix* matrix = c4hardware->newMatrix(systemID, rows, cols);

[Top]

### Maths and Linear Algebra

For simple programming, many of the standard operators may be used to manipulate your data:
scalar1 = scalar2 + scalar3;

vec1 = vec2 * scalar1;

vec1 = vec2 * scalar1;

Alteratively, specific functions are provided to allow data to be passed by implicit reference, or as explicit pointers, to allow for more efficient programming. (This avoids creating and destroying objects, as happens when calling operators)

Pval.setWithMultiply(&beta, &alpmod2squared);

The availability of additional procedures also provides the programmer with powerful functions to more closely emulate the behaviour of hardware. For example, to perform a multiplication with carry-save results, add an offset of value one, and then resolve to a normal number, the following may be used :

Pval.setWithMultiplyAndOffset(&beta, &alpmod2squared,1);

[Top]

### Interfacing with MATLAB

A typical workflow may involve translating a generic MATLAB or similiar high level model.In particular, a programmer may wish to write their c4Hardware code as a MEX function to interface with a high level simulation script. c4Hardware provides functionality to allow this to be done with ease.

[Top]

### Statistics Counting

c4Hardware provides for the tracking of statistics via the plug-in of custom modules. These allow you to track things like maximum and minimum values, frequency of occurance of values, etc.[Top]

### Debugging Features

Perhaps the most time consuming part of algorithm modelling is finding and debugging mismatches between the original model and the reduced precision model. For that reason, c4Hardware provides a number of logging features to simplify the task :- Logging of data in formats that can be compared to MATLAB data dumps

- Logging of tracking points to follow the flow of an algorithm

An exception handling system is also available, with an exception stack trace allowing the developer to quickly pinpoint errors. For example, this code :

c = 0;

try {

*a = *b / c;

} catch (ExceptionSystem* e) {

e->dumpData();

delete e;

}

try {

*a = *b / c;

} catch (ExceptionSystem* e) {

e->dumpData();

delete e;

}

produces :

Exception EX_DivideByZero @

SimRealFloat, doDivide(const SimRealFloat& a) :

c : [Components = 0.00000000000000000000,

SimValue, doDivide(const SimNumericType& a)

c : [Components = 0.00000000000000000000,

SimValue, operator /(SimValue&)

c : [Components = 0.00000000000000000000,

SimRealFloat, doDivide(const SimRealFloat& a) :

c : [Components = 0.00000000000000000000,

SimValue, doDivide(const SimNumericType& a)

c : [Components = 0.00000000000000000000,

SimValue, operator /(SimValue&)

c : [Components = 0.00000000000000000000,

[Top]

### Testbench Vector Generation

c4Hardware is designed to provide a bit-accurate emulation environment, which can ultimately be used to generate test vector sets for input to an HDL testbench. As such, a testbench interface is provided.
testbench->logUnsignedInteger(RmodInverse->numCols(),"real size of rmi");

RmodInverse->writeToTestbench("");

RmodInverse->writeToTestbench("");

The above code will generate testbench data such as the following :

000704|035|0001| real size of rmi|3

000000|000|0000|RModInverse

000705|035|0048|RModInverse(:,1) | 1111111-0-11000 0000000-0-00000 0000000-0-00000

000706|035|0048|RModInverse(:,2) | 1111001-0-10110 1111111-0-10001 0000000-0-00000

000707|035|0048|RModInverse(:,3) | 1111010-0-10101 1111010-0-11001 0000000-0-10010

000000|000|0000|RModInverse

000705|035|0048|RModInverse(:,1) | 1111111-0-11000 0000000-0-00000 0000000-0-00000

000706|035|0048|RModInverse(:,2) | 1111001-0-10110 1111111-0-10001 0000000-0-00000

000707|035|0048|RModInverse(:,3) | 1111010-0-10101 1111010-0-11001 0000000-0-10010

A consistant format is used, to allow parsing by a testbench derived from the c4Hardware Testbench Template.

[Top]

### Custom Numeric Tyes

While the c4Hardware Library, and the companion c4HDL library, provide example floating and fixed point data types, there may be circumstances where the programmer may wish to either implement a different number system, or modify the way that an existing one behaves. This can be achieved by creating new base numeric types that match the provided class interface. They can then be seamlessly integrated into the c4Hardware system and used the same as the provided numeric types.

[Top]

### Overriding Numeric Operations

While a numeric system may suit most needs, there may be circumstances where the behaviour of a specific operation needs to be changed. For example, a suboptimal division operation that uses a limited number or iterations, or a multiplier that simplifies the rounding of results. c4Hardware allows this by providing a mechanism for overriding certain operations :

QPMultiplyCalculator multunit;

c4hardware->overrides(systemID)->setMultiplier(&multunit);

c4hardware->overrides(systemID)->setMultiplier(&multunit);