Fast Hardware Simulation
Purpose: Validate RTL correctness faster than Vitis cosimulation using TAPA's fast cosim.
When to use this: After tapa compile produces a .xo file, before the multi-hour v++ --link step. Fast cosim catches logic bugs in generated RTL in seconds rather than the ten-plus minutes Vitis cosimulation requires.
What you need
- A
.xokernel object fromtapa compile(or a.zipfor thexilinx-hlstarget) - One of:
- xsim: Requires a Vivado installation. Linux only.
- verilator: Open-source. Works on Linux and macOS. No Vivado required.
Commands
Basic run
Pass the .xo file as the --bitstream argument:
./vadd --bitstream VecAdd.xo 1000
For the xilinx-hls target, a .zip file also works:
./vadd --bitstream VecAdd.zip 1000
Choosing a simulator backend
The default backend is xsim. To switch to Verilator:
./vadd --bitstream VecAdd.xo -cosim_simulator verilator 1000
Saving waveforms
Specify a persistent work directory and enable waveform saving:
./vadd --bitstream VecAdd.xo \
-cosim_work_dir ./cosim_work \
-xsim_save_waveform \
1000
Strongly recommended: pair -xsim_save_waveform with -cosim_work_dir. Without a persistent work directory, fast cosim uses a temporary directory that is deleted at exit, removing any saved waveforms with it.
Setup-only and resume workflow
When you want to inspect the generated simulation environment before committing to a full run:
# Step 1: set up the simulation environment and stop before running
./vadd --bitstream VecAdd.xo \
-cosim_work_dir ./cosim_work \
-cosim_setup_only \
1000
# Step 2: after inspecting, run post-simulation checks without re-simulating
./vadd --bitstream VecAdd.xo \
-cosim_work_dir ./cosim_work \
-cosim_resume_from_post_sim \
1000
Parallel runs
When a host application calls tapa::invoke more than once — for example, a pipeline split into separate kernels each compiled to its own .xo file — TAPA launches all cosim instances concurrently. Each kernel is compiled independently and its .xo path is passed to its own tapa::invoke call via a separate bitstream flag:
// Host code: two separate kernels, each with its own bitstream flag
DEFINE_string(producer_bitstream, "", "XO for Producer kernel");
DEFINE_string(consumer_bitstream, "", "XO for Consumer kernel");
tapa::invoke(Producer, FLAGS_producer_bitstream, ...);
tapa::invoke(Consumer, FLAGS_consumer_bitstream, ...);
./app --producer_bitstream=producer.xo --consumer_bitstream=consumer.xo
If all instances share the same -cosim_work_dir, their simulation environments collide. Pass -cosim_work_dir_parallel to give each instance its own uniquely named subdirectory:
./app \
--producer_bitstream=producer.xo \
--consumer_bitstream=consumer.xo \
-cosim_work_dir ./cosim_work \
-cosim_work_dir_parallel
TAPA creates ./cosim_work/XXXXXX/ (a unique name per instance) so that the simulations run without interfering with each other's build artifacts.
Runtime flags reference
The following flags control fast cosim behavior when passed to the host executable. The canonical reference is Runtime Flags.
| Flag | Description |
|---|---|
-cosim_executable <path> | Deprecated. Fast cosim now runs in-process via libfrt; this flag is ignored. |
-xsim_part_num <part> | Target FPGA part number for simulation (e.g., xcu280-fsvh2892-2L-e). |
-cosim_work_dir <dir> | Persistent working directory for simulation artifacts. Without this, a temporary directory is used and deleted after the run. |
-xsim_save_waveform | Save simulation waveforms to a .wdb file in the work directory. Requires -cosim_work_dir. |
-xsim_start_gui | Open the Vivado GUI for interactive debugging during simulation. |
-cosim_simulator <backend> | Simulator backend: xsim (default, Linux only) or verilator (cross-platform). |
-cosim_setup_only | Run simulation setup only, then stop before executing the simulation. |
-cosim_resume_from_post_sim | Skip re-running the simulation; jump directly to post-simulation checks. |
-cosim_work_dir_parallel | Create a unique subdirectory per instance when running concurrent simulations. |
Expected output
Fast cosim completes in seconds for simple designs. A successful run prints the application's correctness result (e.g., PASS!) after the simulation finishes.
Debugging frozen simulations
If the simulation becomes unresponsive:
- Run with
-cosim_work_dirto persist intermediate files. - Abort the simulation with Ctrl-C.
- Locate
[work-dir]/output/run/run_cosim.tcl. - Open Vivado in GUI mode and source the script:
vivado -mode gui -source [work-dir]/output/run/run_cosim.tcl
This allows real-time observation and waveform analysis of the frozen state.
Cross-channel access for HBM is not currently supported in fast cosimulation. Each AXI interface can only access one HBM channel.
If something goes wrong
See Cosimulation Issues for diagnosis steps covering xsim hangs, Verilator build errors, and waveform debugging.
Next step: Vitis Cosimulation