Simulation Guide for C++

Generated Code

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:

  • A constructor
  • A destructor
  • A reset method
  • A run method

These methods should be called in an appropriate way from the testbench, as explained below.

Embedding in Tesbench

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).

Simulation of Multiple Arx Models

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.

Known Issues

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.

VCD Generation

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.

Known Issue

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.

 
arx/cpp_sim.txt · Last modified: 2023/07/17 22:40 by 127.0.0.1