Suppose that you generate C++ code from Arx source file foo.arx
.
The result is a C++ class called foo
the description of which
is distributed across the files foo.h
and foo.cpp
. Hierarchy
that may have been present in the original Arx description is not
preserved. The execution model that has been chosen for simulation
requires the design to be flattened.
The class will contain four methods:
These methods should be called in an appropriate way from the testbench, as explained below.
The testbench can be as simple or sophisticated as the circumstances require as long as a few rules are observed.
The header file foo.h
as generated by Arx contains all information
about the class representing the hardware and should be included in
the testbench code.
#include "foo.h"
First, the object representing the hardware needs to be created by
means of the constructor. Assuming that the class is called foo
and the object hardware
, this amounts to the statement:
foo hardware;
To bring the hardware in its reset state as specified by the
reset values in the register declarations, the reset
method
should be called.
hardware.reset();
The reset
method should be called before performing the simulation
of clock cycles. If appropriate, the reset
method can be called
multiple times during a simulation.
Calling the run
method once amounts to simulating one clock cycle.
The arguments of run
correspond to the inputs and outputs of the
top-level component in Arx. The Arx C++ code generator takes care
of converting the output signals into reference arguments of
run
. So the calling environment should take care that the correct
inputs are passed to run
before each call and that the returned
outputs are appropriately processed after each call. So:
hardware.run(<io-first>, ..., <io-last>);
Of course, the arguments of run
should have the correct data type.
The C++ data type used by the Arx generator can be found in the
generated code (most likely a signed or unsigned integer of some
specific length).
As mentioned above, all Arx code residing in a single source file is flattened by the C++ code generator and translated into a single simulation model. It is possible to incorporate multiple of these models in one testbench. This is useful for large designs and especially for dealing with multiple clock domains and multirate systems.
In the current version of Arx, the generated code contains global variables corresponding to registers in the Arx code and to enumarations. When simulating multiple models, this may lead to conflicts. The workaround is to make sure that there are no name conflicts.
This workaround does not help when instantiating the same model multiple times in the testbench. If the models are needed in the same clock domain, the problem can be avoided by creating a new level of hierarchy in Arx and performing the instantiation in Arx.
A value-change dump (VCD) can be generated during a C++ simulation. This is achieved by setting the following pre-processor variable:
#define VCD_OUTPUT
When set, the waveforms for all signals in the simulation will be
dumped in a file called debug.vcd
. Using a suitable waveform
viewer, one can then analyze the waveforms.
The current version of Arx does not allow to dump only a subset of the
signals. One should be aware that for larger models and longer
simulations, turning on VCD-output generation considerably slows down
the simulation. In addition, one should be aware that the size of
debug.vcd
can grow large.
VCD generation does not work when multiple Arx models are instantiated in the testbench.