Skip to content
WIP: parts of this documentation are AI-generated and may contain factual errors.

Verification

Verification Overview

iDMA uses a SystemVerilog testbench driven by job files that describe transfer sequences. The testbench compares hardware behavior against a byte-accurate golden model. The full job-file testbenches run under Questa or VCS; Verilator is wired for elaboration/lint only. Job files live in jobs/backend_<variant>/.

For documentation quality checks, see Docs Verification Plan.

Testbench Architecture

Key Components

ComponentLocationDescription
idma_test packagetest/idma_test.svShared test infrastructure: job class, golden model, drivers
tb_idma_backend_*test/tpl/tb_idma_backend.sv.tpl (generated)Per-variant top-level testbench module
tb_tasks.svhtest/include/tb_tasks.svhProtocol-specific memory access tasks, job file parser

Golden Model

The testbench uses a golden model - a software reference implementation that predicts the expected memory state after each DMA transfer. By comparing the hardware’s actual memory writes against the model’s predictions, the testbench detects functional bugs without requiring hand-written expected values.

The idma_model class in idma_test.sv is a byte-addressed memory model that simulates DMA transfers at the byte granularity. It replicates the legalizer’s burst splitting logic (page boundaries, maximum burst lengths) and error handling behavior (continue/abort semantics). After each transfer, the testbench compares the hardware memory state against the model’s expected state to detect mismatches. The golden model uses the max_src_len and max_dst_len fields from the job file to configure burst splitting - these must match the protocol’s actual limits for comparisons to pass. If max_src_len/max_dst_len don’t match the protocol’s actual burst limits, the golden model will split bursts differently than the hardware legalizer, causing false mismatches.

Job File Format

Each job file contains one or more transfer descriptions, concatenated back-to-back. Each transfer is described by the following fields, one per line.

The most important fields are length, src_addr, dst_addr, and the two max_*_len fields (which must match your protocol’s actual burst limits). For a basic AXI test, set both protocols to 0, both max lengths to 256, and both decoupling flags to 0.

Fields

LineFormatFieldDescription
1%dlengthTransfer length in bytes
20x%xsrc_addrSource address (hex)
30x%xdst_addrDestination address (hex)
4%dsrc_protocolSource protocol enum (0=AXI, 1=OBI, …)
5%ddst_protocolDestination protocol enum
6%dmax_src_lenMax source burst length in beats
7%dmax_dst_lenMax destination burst length in beats
8%baw_decoupledAW decoupling flag (0 or 1)
9%brw_decoupledRW decoupling flag (0 or 1)
10%dnum_errorsNumber of injected errors (0 for clean transfers)
11+%c%c0x%herror specsOne line per error: r/w + c/a + hex address

Error spec format: first character is r (read) or w (write), second is c (continue) or a (abort), followed by the error address in hex.

Example

Annotated simple.txt (a single 2-byte transfer with no errors):

2 # length: 2 bytes
0x0 # src_addr: 0x000
0x3ff # dst_addr: 0x3ff
0 # src_protocol: AXI (0)
0 # dst_protocol: AXI (0)
256 # max_src_len: 256 beats
256 # max_dst_len: 256 beats
0 # aw_decoupled: no
0 # rw_decoupled: no
0 # num_errors: 0

Annotated error transfer (from error_simple.txt):

32 # length: 32 bytes
0x0 # src_addr
0x10000 # dst_addr
0 # AXI read
0 # AXI write
256 # max 256 beats
256 # max 256 beats
0 # aw_decoupled: no
0 # rw_decoupled: no
3 # 3 injected errors:
rc0x4 # read error at 0x4, action: continue
rc0x8 # read error at 0x8, action: continue
rc0xc # read error at 0xc, action: continue

Writing Custom Job Files

To create a custom test, write a text file following the format above. Each field is on its own line, with transfers concatenated back-to-back (no blank lines between them). The max_src_len and max_dst_len fields control burst splitting in the golden model - set to 256 for AXI (matching the protocol maximum) or 1 for single-beat protocols (OBI, INIT, AXI Stream).

Here is an example with two back-to-back transfers in a single job file (64 bytes followed by 128 bytes, no errors):

64
0x0
0x1000
0
0
256
256
0
0
0
128
0x100
0x2000
0
0
256
256
1
0
0

Available Test Suites

Each backend variant has its own set of job files under jobs/backend_<variant>/:

Basic - start here for bring-up and sanity checks:

Job FileDescription
simple.txtMinimal transfer (2 bytes), basic sanity check
small.txtA few short transfers
tiny.txtVery small (sub-word) transfers

Stress - increasing transfer sizes for throughput and boundary testing:

Job FileDescription
medium.txtMixed lengths, some with AW decoupling
large.txtLonger transfers approaching page boundaries
huge.txtLarge transfers spanning multiple pages

Pattern - specific address and access patterns:

Job FileDescription
linear.txtSequential address patterns
mixed.txtVaried source/destination alignments
same_dst.txtMultiple transfers to the same destination
zero_transfer.txtZero-length transfer (tests RejectZeroTransfers)

Error - error injection and handling:

Job FileDescription
error_simple.txtTransfers with injected read/write errors and continue/abort actions
error_mixed.txtComplex error scenarios with multiple error types

For initial bring-up, start with simple.txt on the rw_axi variant - it’s the smallest test on the most common backend.

Compute Testbenches

The on-the-fly compute engines have dedicated self-checking testbenches, checked byte-exact against DPI-C golden models (they are separate from the job-file backend flow):

Make targetDUTChecks
idma_sim_tb_idma_otf_transposeidma_otf_transpose standaloneTranspose engine over StrbWidth and FullDuplex sweeps, golden idma_transpose_dpi.c
idma_sim_tb_idma_transpose_ndND midend -> rw_axi -> axi_sim_memMulti-tile transpose end-to-end at DataWidth 32/64
idma_sim_tb_idma_transpose_b2bND midend -> rw_axiTwo back-to-back transposes to distinct destinations
idma_sim_tb_idma_mxquantrw_axi backend, COMPUTE_MXQUANT{,_FP16}FP32/FP16 -> MXFP8 33 B blocks, golden idma_mxquant_dpi.c; one run crosses a 4K page

These idma_sim_tb_* targets drive Questa directly (they source compile.tcl and run under vsim), so they are Questa-only; pass the tool binaries through the VSIM / VLOG / VLIB variables:

Terminal window
make idma_sim_tb_idma_mxquant VSIM="questa-2023.4 vsim" \
VLOG="questa-2023.4 vlog" VLIB="questa-2023.4 vlib"

Running Simulations

idma.mk wires three simulators. Questa and VCS run the full job-file testbenches; Verilator is wired for elaboration/lint only (it Verilates a chosen top with --cc, not a full behavioral run). Each flow takes its tool binaries as make variables, whose defaults are the bare vsim / vcs / verilator names; the Questa examples below use the questa-2023.4 SEPP wrapper.

Prerequisites

Generate the RTL (and, for Questa/VCS, the compile scripts) first:

Terminal window
make idma_hw_all # Generate RTL into target/rtl/
make idma_sim_all # Generate compile.tcl + start.tcl (Questa) and compile.sh (VCS)

Compile and Run

Compile with the generated compile.tcl, then run a job file with the +job_file plusarg:

Terminal window
cd target/sim/vsim
questa-2023.4 vsim -c -do "source compile.tcl; quit"
questa-2023.4 vsim -c -t 1ps -voptargs=+acc \
+job_file=../../../jobs/backend_rw_axi/simple.txt \
-logfile output.log \
tb_idma_backend_rw_axi \
-do "source start.tcl; run -all"

Replace backend_rw_axi and tb_idma_backend_rw_axi with the desired variant. The +job_file plusarg points to the job file describing the test sequence.

Debugging Failures

If a simulation fails, the testbench prints the first mismatching address and expected vs. actual values. To debug further, open the waveform in the Questa GUI by removing the -c flag from the vsim command.

Check the busy_o flags to identify which subunit stalled:

FlagStuck means
r_leg_busyLegalizer can’t split - check transfer parameters
r_dp_busyRead channel not getting responses - check memory slave
buffer_busyWrite channel not draining - check write backpressure
w_dp_busyWrite channel blocked - check destination memory
eh_fsm_busyError handler waiting for software action

Key signals to trace in waveforms: idma_req_i/req_valid_i/req_ready_o (request handshake), idma_rsp_o/rsp_valid_o (response), busy_o (subunit status), and the AXI AR/AW/R/W/B channels on the bus interface.

Source Files

  • test/idma_test.sv - Test package (job class, golden model, drivers)
  • test/tpl/tb_idma_backend.sv.tpl - Testbench template (generates per-variant TBs)
  • test/include/tb_tasks.svh - Memory tasks, job parser (read_jobs)
  • jobs/ - Job files organized by backend variant