From 5813b38aafd276ad3f52ecaa832dcd2011977f3d Mon Sep 17 00:00:00 2001 From: Jorge Marques Date: Tue, 19 Nov 2024 18:42:16 -0300 Subject: [PATCH] dmac_flock: Test AXI DMAC Framelock feature Verify the framelock when the writer is faster than the reader and vice-versa. Test with delay and in AutoRun mode. Signed-off-by: Jorge Marques --- library/drivers/dmac/dma_trans.sv | 4 +- library/drivers/dmac/dmac_api.sv | 6 +- library/regmaps/adi_regmap_dmac_pkg.sv | 14 +- library/utilities/utils.svh | 2 +- testbenches/ip/dma_flock/Makefile | 63 +++ testbenches/ip/dma_flock/cfgs/cfg1.tcl | 65 +++ testbenches/ip/dma_flock/cfgs/cfg2_fsync.tcl | 66 +++ .../ip/dma_flock/cfgs/cfg3_fsync_autorun.tcl | 89 +++++ testbenches/ip/dma_flock/environment.sv | 164 ++++++++ testbenches/ip/dma_flock/scoreboard.sv | 125 ++++++ testbenches/ip/dma_flock/system_bd.tcl | 152 +++++++ testbenches/ip/dma_flock/system_project.tcl | 47 +++ testbenches/ip/dma_flock/system_tb.sv | 44 ++ .../ip/dma_flock/tests/test_program.sv | 322 +++++++++++++++ .../tests/test_program_frame_delay.sv | 376 ++++++++++++++++++ testbenches/ip/dma_flock/waves/cfg1.wcfg | 92 +++++ .../ip/dma_flock/waves/cfg2_fsync.wcfg | 92 +++++ .../dma_flock/waves/cfg3_fsync_autorun.wcfg | 92 +++++ 18 files changed, 1802 insertions(+), 13 deletions(-) create mode 100644 testbenches/ip/dma_flock/Makefile create mode 100644 testbenches/ip/dma_flock/cfgs/cfg1.tcl create mode 100644 testbenches/ip/dma_flock/cfgs/cfg2_fsync.tcl create mode 100644 testbenches/ip/dma_flock/cfgs/cfg3_fsync_autorun.tcl create mode 100644 testbenches/ip/dma_flock/environment.sv create mode 100644 testbenches/ip/dma_flock/scoreboard.sv create mode 100644 testbenches/ip/dma_flock/system_bd.tcl create mode 100644 testbenches/ip/dma_flock/system_project.tcl create mode 100644 testbenches/ip/dma_flock/system_tb.sv create mode 100644 testbenches/ip/dma_flock/tests/test_program.sv create mode 100644 testbenches/ip/dma_flock/tests/test_program_frame_delay.sv create mode 100644 testbenches/ip/dma_flock/waves/cfg1.wcfg create mode 100644 testbenches/ip/dma_flock/waves/cfg2_fsync.wcfg create mode 100644 testbenches/ip/dma_flock/waves/cfg3_fsync_autorun.wcfg diff --git a/library/drivers/dmac/dma_trans.sv b/library/drivers/dmac/dma_trans.sv index ba12dcec..9918d8b1 100644 --- a/library/drivers/dmac/dma_trans.sv +++ b/library/drivers/dmac/dma_trans.sv @@ -50,7 +50,7 @@ package dma_trans_pkg; int DMA_LENGTH_ALIGN; int MAX_BYTES_PER_BURST; int FRAMELOCK; - int MAX_NUM_FRAMES; + int MAX_NUM_FRAMES_WIDTH; int USE_EXT_SYNC; int HAS_AUTORUN; } axi_dmac_params_t; @@ -430,7 +430,7 @@ package dma_trans_pkg; ds.flock_wait_writer = flock_wait_writer; endfunction - constraint c_buf_num {flock_framenum < p.MAX_NUM_FRAMES;}; + constraint c_buf_num {flock_framenum < (p.MAX_NUM_FRAMES_WIDTH-1)**2;}; constraint c_frm_dist {flock_distance < flock_framenum;}; virtual function void print(); diff --git a/library/drivers/dmac/dmac_api.sv b/library/drivers/dmac/dmac_api.sv index d4d172f4..9fe258e4 100644 --- a/library/drivers/dmac/dmac_api.sv +++ b/library/drivers/dmac/dmac_api.sv @@ -75,7 +75,7 @@ package dmac_api_pkg; bpb_width_log2 = `GET_DMAC_INTERFACE_DESCRIPTION_1_BYTES_PER_BURST_WIDTH(val); p.MAX_BYTES_PER_BURST = 2**bpb_width_log2; p.DMA_2D_TLAST_MODE = `GET_DMAC_INTERFACE_DESCRIPTION_1_DMA_2D_TLAST_MODE(val); - p.MAX_NUM_FRAMES = `GET_DMAC_INTERFACE_DESCRIPTION_1_MAX_NUM_FRAMES(val); + p.MAX_NUM_FRAMES_WIDTH = $clog2(`GET_DMAC_INTERFACE_DESCRIPTION_1_MAX_NUM_FRAMES(val))+1; p.USE_EXT_SYNC = `GET_DMAC_INTERFACE_DESCRIPTION_1_USE_EXT_SYNC(val); p.HAS_AUTORUN = `GET_DMAC_INTERFACE_DESCRIPTION_1_HAS_AUTORUN(val); if (!p.HAS_AUTORUN) begin @@ -341,10 +341,10 @@ package dmac_api_pkg; if ($cast(t_fl_2d,t)) begin this.axi_write(GetAddrs(DMAC_FRAMELOCK_CONFIG), - `SET_DMAC_FRAMELOCK_CONFIG_FRAMENUM(t_fl_2d.flock_framenum) | `SET_DMAC_FRAMELOCK_CONFIG_MODE(t_fl_2d.flock_mode) | `SET_DMAC_FRAMELOCK_CONFIG_WAIT_WRITER(t_fl_2d.flock_wait_writer ) | - `SET_DMAC_FRAMELOCK_CONFIG_DISTANCE(t_fl_2d.flock_distance-1)); + `SET_DMAC_FRAMELOCK_CONFIG_FRAMENUM(t_fl_2d.flock_framenum) | + `SET_DMAC_FRAMELOCK_CONFIG_DISTANCE(t_fl_2d.flock_distance)); this.axi_write(GetAddrs(DMAC_FRAMELOCK_STRIDE), `SET_DMAC_FRAMELOCK_STRIDE_STRIDE(t_fl_2d.flock_stride)); end diff --git a/library/regmaps/adi_regmap_dmac_pkg.sv b/library/regmaps/adi_regmap_dmac_pkg.sv index 137fbca9..a893c0c2 100644 --- a/library/regmaps/adi_regmap_dmac_pkg.sv +++ b/library/regmaps/adi_regmap_dmac_pkg.sv @@ -359,13 +359,17 @@ package adi_regmap_dmac_pkg; const reg_t DMAC_FRAMELOCK_CONFIG = '{ 'h0458, "FRAMELOCK_CONFIG" , '{ "DISTANCE": '{ 23, 16, RW, 0 }, - "WAIT_WRITER": '{ 9, 9, RW, 0 }, - "MODE": '{ 8, 8, RW, 0 }, - "FRAMENUM": '{ 7, 0, RW, 0 }}}; + "FRAMENUM": '{ 15, 8, RW, 0 }, + "WAIT_WRITER": '{ 1, 1, RW, 0 }, + "MODE": '{ 0, 0, RW, 0 }}}; `define SET_DMAC_FRAMELOCK_CONFIG_DISTANCE(x) SetField(DMAC_FRAMELOCK_CONFIG,"DISTANCE",x) `define GET_DMAC_FRAMELOCK_CONFIG_DISTANCE(x) GetField(DMAC_FRAMELOCK_CONFIG,"DISTANCE",x) `define DEFAULT_DMAC_FRAMELOCK_CONFIG_DISTANCE GetResetValue(DMAC_FRAMELOCK_CONFIG,"DISTANCE") `define UPDATE_DMAC_FRAMELOCK_CONFIG_DISTANCE(x,y) UpdateField(DMAC_FRAMELOCK_CONFIG,"DISTANCE",x,y) + `define SET_DMAC_FRAMELOCK_CONFIG_FRAMENUM(x) SetField(DMAC_FRAMELOCK_CONFIG,"FRAMENUM",x) + `define GET_DMAC_FRAMELOCK_CONFIG_FRAMENUM(x) GetField(DMAC_FRAMELOCK_CONFIG,"FRAMENUM",x) + `define DEFAULT_DMAC_FRAMELOCK_CONFIG_FRAMENUM GetResetValue(DMAC_FRAMELOCK_CONFIG,"FRAMENUM") + `define UPDATE_DMAC_FRAMELOCK_CONFIG_FRAMENUM(x,y) UpdateField(DMAC_FRAMELOCK_CONFIG,"FRAMENUM",x,y) `define SET_DMAC_FRAMELOCK_CONFIG_WAIT_WRITER(x) SetField(DMAC_FRAMELOCK_CONFIG,"WAIT_WRITER",x) `define GET_DMAC_FRAMELOCK_CONFIG_WAIT_WRITER(x) GetField(DMAC_FRAMELOCK_CONFIG,"WAIT_WRITER",x) `define DEFAULT_DMAC_FRAMELOCK_CONFIG_WAIT_WRITER GetResetValue(DMAC_FRAMELOCK_CONFIG,"WAIT_WRITER") @@ -374,10 +378,6 @@ package adi_regmap_dmac_pkg; `define GET_DMAC_FRAMELOCK_CONFIG_MODE(x) GetField(DMAC_FRAMELOCK_CONFIG,"MODE",x) `define DEFAULT_DMAC_FRAMELOCK_CONFIG_MODE GetResetValue(DMAC_FRAMELOCK_CONFIG,"MODE") `define UPDATE_DMAC_FRAMELOCK_CONFIG_MODE(x,y) UpdateField(DMAC_FRAMELOCK_CONFIG,"MODE",x,y) - `define SET_DMAC_FRAMELOCK_CONFIG_FRAMENUM(x) SetField(DMAC_FRAMELOCK_CONFIG,"FRAMENUM",x) - `define GET_DMAC_FRAMELOCK_CONFIG_FRAMENUM(x) GetField(DMAC_FRAMELOCK_CONFIG,"FRAMENUM",x) - `define DEFAULT_DMAC_FRAMELOCK_CONFIG_FRAMENUM GetResetValue(DMAC_FRAMELOCK_CONFIG,"FRAMENUM") - `define UPDATE_DMAC_FRAMELOCK_CONFIG_FRAMENUM(x,y) UpdateField(DMAC_FRAMELOCK_CONFIG,"FRAMENUM",x,y) const reg_t DMAC_FRAMELOCK_STRIDE = '{ 'h045c, "FRAMELOCK_STRIDE" , '{ "STRIDE": '{ 31, 0, RW, 0 }}}; diff --git a/library/utilities/utils.svh b/library/utilities/utils.svh index 02478ba9..8186ad2d 100644 --- a/library/utilities/utils.svh +++ b/library/utilities/utils.svh @@ -73,7 +73,7 @@ th``_``vip``_0_DISABLE_DEBUG_REGISTERS, \ th``_``vip``_0_ENABLE_DIAGNOSTICS_IF, \ th``_``vip``_0_ENABLE_FRAME_LOCK, \ - th``_``vip``_0_MAX_NUM_FRAMES, \ + th``_``vip``_0_MAX_NUM_FRAMES_WIDTH, \ th``_``vip``_0_USE_EXT_SYNC, \ th``_``vip``_0_HAS_AUTORUN diff --git a/testbenches/ip/dma_flock/Makefile b/testbenches/ip/dma_flock/Makefile new file mode 100644 index 00000000..0d356da1 --- /dev/null +++ b/testbenches/ip/dma_flock/Makefile @@ -0,0 +1,63 @@ +#################################################################################### +#################################################################################### +## Copyright (C) 2024 Analog Devices, Inc. +#################################################################################### +#################################################################################### + +# All test-bench dependencies except test programs +SV_DEPS += ../../../library/utilities/utils.svh +SV_DEPS += ../../../library/drivers/dmac/dma_trans.sv +SV_DEPS += ../../../library/utilities/logger_pkg.sv +SV_DEPS += ../../../library/regmaps/reg_accessor.sv +SV_DEPS += ../../../library/vip/amd/m_axis_sequencer.sv +SV_DEPS += ../../../library/vip/amd/s_axis_sequencer.sv +SV_DEPS += ../../../library/vip/amd/m_axi_sequencer.sv +SV_DEPS += ../../../library/vip/amd/s_axi_sequencer.sv +SV_DEPS += ../../../library/drivers/dmac/dmac_api.sv +SV_DEPS += ../../../library/regmaps/adi_regmap_pkg.sv +SV_DEPS += ../../../library/regmaps/adi_regmap_dmac_pkg.sv +SV_DEPS += ../../../library/drivers/dmac/dma_trans.sv +SV_DEPS += ../../../library/utilities/test_harness_env.sv +SV_DEPS += ../../../library/regmaps/adi_peripheral_pkg.sv +SV_DEPS += environment.sv +SV_DEPS += scoreboard.sv +SV_DEPS += system_tb.sv + +ENV_DEPS += system_project.tcl +ENV_DEPS += system_bd.tcl +ENV_DEPS +=../../../scripts/adi_sim.tcl +ENV_DEPS +=../../../scripts/run_sim.tcl + +LIB_DEPS := axi_dmac +SIM_LIB_DEPS := io_vip + +# default test program +TP := test_program + +# config files should have the following format +# cfg__.tcl +CFG_FILES := $(notdir $(wildcard cfgs/cfg*.tcl)) +#$(warning $(CFG_FILES)) + +# List of tests and configuration combinations that has to be run +# Format is: : +#TESTS := $(foreach cfg, $(basename $(CFG_FILES)), $(cfg):$(TP)) +TESTS += cfg1:test_program +TESTS += cfg2_fsync:test_program +TESTS += cfg2_fsync:test_program_frame_delay +TESTS += cfg3_fsync_autorun:test_program_frame_delay + +include ../../../scripts/project-sim.mk + +# usage : +# +# run specific test on a specific configuration in gui mode +# make CFG=cfg2_fsync TST=test_program_frame_delay MODE=gui +# +# run all test from a configuration +# make cfg1_mm2mm_default + + + +#################################################################################### +#################################################################################### diff --git a/testbenches/ip/dma_flock/cfgs/cfg1.tcl b/testbenches/ip/dma_flock/cfgs/cfg1.tcl new file mode 100644 index 00000000..0142b379 --- /dev/null +++ b/testbenches/ip/dma_flock/cfgs/cfg1.tcl @@ -0,0 +1,65 @@ +set MAX_NUM_FRAMES_WIDTH 4 +set AUTORUN 0 +set USE_EXT_SYNC 0 +set TDATA_NUM_BYTES 8 + +set ad_project_params(M_DMA_CFG_MAX_NUM_FRAMES) $MAX_NUM_FRAMES_WIDTH +set ad_project_params(M_DMA_CFG_AUTORUN) $AUTORUN +set ad_project_params(S_DMA_CFG_AUTORUN) $AUTORUN +set ad_project_params(M_DMA_CFG_USE_EXT_SYNC) $USE_EXT_SYNC +set ad_project_params(S_DMA_CFG_USE_EXT_SYNC) $USE_EXT_SYNC +set ad_project_params(SRC_AXIS_VIP_CFG_TDATA_NUM_BYTES) $TDATA_NUM_BYTES +set ad_project_params(DST_AXIS_VIP_CFG_TDATA_NUM_BYTES) $TDATA_NUM_BYTES + +set m_dma_cfg [list \ + DMA_TYPE_SRC 1 \ + DMA_TYPE_DEST 0 \ + DMA_2D_TRANSFER 1 \ + SYNC_TRANSFER_START 0 \ + AXIS_TUSER_SYNC 0 \ + CYCLIC 1 \ + FRAMELOCK 1 \ + MAX_NUM_FRAMES_WIDTH $MAX_NUM_FRAMES_WIDTH \ + USE_EXT_SYNC $USE_EXT_SYNC \ + DMA_2D_TLAST_MODE 1 \ +] + +set s_dma_cfg [list \ + DMA_TYPE_SRC 0 \ + DMA_TYPE_DEST 1 \ + DMA_2D_TRANSFER 1 \ + SYNC_TRANSFER_START 0 \ + AXIS_TUSER_SYNC 0 \ + CYCLIC 1 \ + FRAMELOCK 1 \ + MAX_NUM_FRAMES_WIDTH $MAX_NUM_FRAMES_WIDTH \ + USE_EXT_SYNC $USE_EXT_SYNC \ + DMA_2D_TLAST_MODE 1 \ +] + +# VDMA config +set vdma_cfg [list \ + c_m_axis_mm2s_tdata_width {64} \ + c_num_fstores {3} \ + c_use_mm2s_fsync {0} \ + c_use_s2mm_fsync {0} \ + c_enable_vert_flip {0} \ + c_mm2s_genlock_mode {3} \ + c_s2mm_genlock_mode {2} \ + c_mm2s_linebuffer_depth {8192} \ + c_s2mm_linebuffer_depth {8192} \ +] + +# SRC AXIS +set src_axis_vip_cfg [list \ + INTERFACE_MODE {MASTER} \ + HAS_TLAST {1} \ + TDATA_NUM_BYTES $TDATA_NUM_BYTES \ + ] + +# DST AXIS +set dst_axis_vip_cfg [list \ + INTERFACE_MODE {SLAVE} \ + HAS_TLAST {1} \ + TDATA_NUM_BYTES $TDATA_NUM_BYTES \ +] diff --git a/testbenches/ip/dma_flock/cfgs/cfg2_fsync.tcl b/testbenches/ip/dma_flock/cfgs/cfg2_fsync.tcl new file mode 100644 index 00000000..2d4365ea --- /dev/null +++ b/testbenches/ip/dma_flock/cfgs/cfg2_fsync.tcl @@ -0,0 +1,66 @@ +set MAX_NUM_FRAMES_WIDTH 4 +set AUTORUN 0 +set M_USE_EXT_SYNC 0 +set S_USE_EXT_SYNC 1 +set TDATA_NUM_BYTES 8 + +set ad_project_params(M_DMA_CFG_MAX_NUM_FRAMES) $MAX_NUM_FRAMES_WIDTH +set ad_project_params(M_DMA_CFG_AUTORUN) $AUTORUN +set ad_project_params(S_DMA_CFG_AUTORUN) $AUTORUN +set ad_project_params(M_DMA_CFG_USE_EXT_SYNC) $M_USE_EXT_SYNC +set ad_project_params(S_DMA_CFG_USE_EXT_SYNC) $S_USE_EXT_SYNC +set ad_project_params(SRC_AXIS_VIP_CFG_TDATA_NUM_BYTES) $TDATA_NUM_BYTES +set ad_project_params(DST_AXIS_VIP_CFG_TDATA_NUM_BYTES) $TDATA_NUM_BYTES + +set m_dma_cfg [list \ + DMA_TYPE_SRC 1 \ + DMA_TYPE_DEST 0 \ + DMA_2D_TRANSFER 1 \ + SYNC_TRANSFER_START 0 \ + AXIS_TUSER_SYNC 0 \ + CYCLIC 1 \ + FRAMELOCK 1 \ + MAX_NUM_FRAMES_WIDTH $MAX_NUM_FRAMES_WIDTH \ + USE_EXT_SYNC $M_USE_EXT_SYNC \ + SYNC_TRANSFER_START 1 \ + DMA_2D_TLAST_MODE 1 \ +] + +set s_dma_cfg [list \ + DMA_TYPE_SRC {0} \ + DMA_TYPE_DEST {1} \ + DMA_2D_TRANSFER 1 \ + SYNC_TRANSFER_START 0 \ + AXIS_TUSER_SYNC 0 \ + CYCLIC 1 \ + FRAMELOCK 1 \ + MAX_NUM_FRAMES_WIDTH $MAX_NUM_FRAMES_WIDTH \ + USE_EXT_SYNC $S_USE_EXT_SYNC \ + DMA_2D_TLAST_MODE 1 \ +] + +# VDMA config +set vdma_cfg [list \ + c_m_axis_mm2s_tdata_width {64} \ + c_num_fstores {8} \ + c_use_mm2s_fsync {1} \ + c_use_s2mm_fsync {2} \ + c_enable_vert_flip {0} \ + c_mm2s_genlock_mode {1} \ + c_s2mm_genlock_mode {0} \ +] + +# SRC AXIS +set src_axis_vip_cfg [list \ + INTERFACE_MODE {MASTER} \ + HAS_TLAST {1} \ + TUSER_WIDTH {1} \ + TDATA_NUM_BYTES $TDATA_NUM_BYTES \ + ] + +# DST AXIS +set dst_axis_vip_cfg [list \ + INTERFACE_MODE {SLAVE} \ + HAS_TLAST {1} \ + TDATA_NUM_BYTES $TDATA_NUM_BYTES \ +] diff --git a/testbenches/ip/dma_flock/cfgs/cfg3_fsync_autorun.tcl b/testbenches/ip/dma_flock/cfgs/cfg3_fsync_autorun.tcl new file mode 100644 index 00000000..7e0ee90b --- /dev/null +++ b/testbenches/ip/dma_flock/cfgs/cfg3_fsync_autorun.tcl @@ -0,0 +1,89 @@ +set MAX_NUM_FRAMES_WIDTH 4 +set AUTORUN 1 +set M_USE_EXT_SYNC 0 +set S_USE_EXT_SYNC 1 +set TDATA_NUM_BYTES 8 + +set ad_project_params(M_DMA_CFG_MAX_NUM_FRAMES) $MAX_NUM_FRAMES_WIDTH +set ad_project_params(M_DMA_CFG_AUTORUN) $AUTORUN +set ad_project_params(S_DMA_CFG_AUTORUN) $AUTORUN +set ad_project_params(M_DMA_CFG_USE_EXT_SYNC) $M_USE_EXT_SYNC +set ad_project_params(S_DMA_CFG_USE_EXT_SYNC) $S_USE_EXT_SYNC +set ad_project_params(SRC_AXIS_VIP_CFG_TDATA_NUM_BYTES) $TDATA_NUM_BYTES +set ad_project_params(DST_AXIS_VIP_CFG_TDATA_NUM_BYTES) $TDATA_NUM_BYTES + +set m_dma_cfg [list \ + DMA_TYPE_SRC 1 \ + DMA_TYPE_DEST 0 \ + DMA_2D_TRANSFER 1 \ + SYNC_TRANSFER_START 0 \ + AXIS_TUSER_SYNC 0 \ + CYCLIC 1 \ + FRAMELOCK 1 \ + MAX_NUM_FRAMES_WIDTH $MAX_NUM_FRAMES_WIDTH \ + USE_EXT_SYNC $M_USE_EXT_SYNC \ + SYNC_TRANSFER_START 1 \ + DMA_2D_TLAST_MODE {1} \ + \ + AUTORUN $AUTORUN \ + AUTORUN_FLAGS {0x13} \ + AUTORUN_SRC_ADDR {0x00000000} \ + AUTORUN_DEST_ADDR {0x00001000} \ + AUTORUN_X_LENGTH {0x3FF} \ + AUTORUN_Y_LENGTH {0x7} \ + AUTORUN_SRC_STRIDE {0x000} \ + AUTORUN_DEST_STRIDE {0x400} \ + AUTORUN_FRAMELOCK_CONFIG {0x00303} \ + AUTORUN_FRAMELOCK_STRIDE {0x2000} \ +] + +set s_dma_cfg [list \ + DMA_TYPE_SRC {0} \ + DMA_TYPE_DEST {1} \ + DMA_2D_TRANSFER 1 \ + SYNC_TRANSFER_START 0 \ + AXIS_TUSER_SYNC 0 \ + CYCLIC 1 \ + FRAMELOCK 1 \ + MAX_NUM_FRAMES_WIDTH $MAX_NUM_FRAMES_WIDTH \ + USE_EXT_SYNC $S_USE_EXT_SYNC \ + DMA_2D_TLAST_MODE {1} \ + \ + AUTORUN $AUTORUN \ + AUTORUN_FLAGS {0x13} \ + AUTORUN_SRC_ADDR {0x00001000} \ + AUTORUN_DEST_ADDR {0x00000000} \ + AUTORUN_X_LENGTH {0x3FF} \ + AUTORUN_Y_LENGTH {0x7} \ + AUTORUN_SRC_STRIDE {0x000} \ + AUTORUN_DEST_STRIDE {0x400} \ + AUTORUN_FRAMELOCK_CONFIG {0x00303} \ + AUTORUN_FRAMELOCK_STRIDE {0x2000} \ +] + + +# VDMA config +set vdma_cfg [list \ + c_m_axis_mm2s_tdata_width {64} \ + c_num_fstores {8} \ + c_use_mm2s_fsync {1} \ + c_use_s2mm_fsync {2} \ + c_enable_vert_flip {0} \ + c_mm2s_genlock_mode {1} \ + c_s2mm_genlock_mode {0} \ +] + +# SRC AXIS +set src_axis_vip_cfg [list \ + INTERFACE_MODE {MASTER} \ + HAS_TLAST {1} \ + TUSER_WIDTH {1} \ + TDATA_NUM_BYTES $TDATA_NUM_BYTES \ + ] + +# DST AXIS +set dst_axis_vip_cfg [list \ + INTERFACE_MODE {SLAVE} \ + HAS_TLAST {1} \ + TDATA_NUM_BYTES $TDATA_NUM_BYTES \ +] diff --git a/testbenches/ip/dma_flock/environment.sv b/testbenches/ip/dma_flock/environment.sv new file mode 100644 index 00000000..2d581701 --- /dev/null +++ b/testbenches/ip/dma_flock/environment.sv @@ -0,0 +1,164 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2024 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsabilities that he or she has by using this source/core. +// +// This core is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +// A PARTICULAR PURPOSE. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/main/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`include "utils.svh" + +package environment_pkg; + + import axi_vip_pkg::*; + import scoreboard_pkg::*; + import axi4stream_vip_pkg::*; + import m_axi_sequencer_pkg::*; + import s_axi_sequencer_pkg::*; + import m_axis_sequencer_pkg::*; + import s_axis_sequencer_pkg::*; + import test_harness_env_pkg::*; + import dma_trans_pkg::*; + import `PKGIFY(test_harness, mng_axi_vip)::*; + import `PKGIFY(test_harness, ddr_axi_vip)::*; + import `PKGIFY(test_harness, src_axis_vip)::*; + import `PKGIFY(test_harness, dst_axis_vip)::*; + + class environment extends test_harness_env; + + // Agents + `AGENT(test_harness, src_axis_vip, mst_t) src_axis_agent; + `AGENT(test_harness, dst_axis_vip, slv_t) dst_axis_agent; + + // Sequencers + m_axis_sequencer #(`AGENT(test_harness, src_axis_vip, mst_t), + `AXIS_VIP_PARAMS(test_harness, src_axis_vip) + ) src_axis_seq; + s_axis_sequencer #(`AGENT(test_harness, dst_axis_vip, slv_t)) dst_axis_seq; + // Register accessors + + dma_transfer_group trans_q[$]; + + scoreboard scrb; + + //============================================================================ + // Constructor + //============================================================================ + function new( + virtual interface clk_vip_if #(.C_CLK_CLOCK_PERIOD(10)) sys_clk_vip_if, + virtual interface clk_vip_if #(.C_CLK_CLOCK_PERIOD(5)) dma_clk_vip_if, + virtual interface clk_vip_if #(.C_CLK_CLOCK_PERIOD(2.5)) ddr_clk_vip_if, + + virtual interface rst_vip_if #(.C_ASYNCHRONOUS(1), .C_RST_POLARITY(1)) sys_rst_vip_if, + + virtual interface axi_vip_if #(`AXI_VIP_IF_PARAMS(test_harness, mng_axi_vip)) mng_vip_if, + virtual interface axi_vip_if #(`AXI_VIP_IF_PARAMS(test_harness, ddr_axi_vip)) ddr_vip_if, + virtual interface axi4stream_vip_if #(`AXIS_VIP_IF_PARAMS(test_harness, src_axis_vip)) src_axis_vip_if, + virtual interface axi4stream_vip_if #(`AXIS_VIP_IF_PARAMS(test_harness, dst_axis_vip)) dst_axis_vip_if + ); + super.new(sys_clk_vip_if, + dma_clk_vip_if, + ddr_clk_vip_if, + sys_rst_vip_if, + mng_vip_if, + ddr_vip_if); + + // Creating the agents + src_axis_agent = new("Src AXI stream agent", src_axis_vip_if); + dst_axis_agent = new("Dest AXI stream agent", dst_axis_vip_if); + + // Creating the sequencers + src_axis_seq = new(src_axis_agent); + dst_axis_seq = new(dst_axis_agent); + + scrb = new; + + endfunction + + //============================================================================ + // Start environment + // - Connect all the agents to the scoreboard + // - Start the agents + //============================================================================ + task start(); + super.start(); + scrb.connect( + src_axis_agent.monitor.item_collected_port, + dst_axis_agent.monitor.item_collected_port + ); + + src_axis_agent.start_master(); + dst_axis_agent.start_slave(); + + endtask + + //============================================================================ + // Start the test + // - start the scoreboard + // - start the sequencers + //============================================================================ + task test(); + super.test(); + src_axis_seq.run(); + // DEST AXIS does not have to run, scoreboard connects and + // gathers packets from the agent + scrb.run(); + test_c_run(); + endtask + + //============================================================================ + // Post test subroutine + //============================================================================ + task post_test(); + super.post_test(); + // wait until done + scrb.shutdown(); + endtask + + //============================================================================ + // Run subroutine + //============================================================================ + task run; + test(); + post_test(); + endtask + + //============================================================================ + // Stop subroutine + //============================================================================ + task stop; + super.stop(); + src_axis_agent.stop_master(); + dst_axis_agent.stop_slave(); + endtask + + endclass + +endpackage diff --git a/testbenches/ip/dma_flock/scoreboard.sv b/testbenches/ip/dma_flock/scoreboard.sv new file mode 100644 index 00000000..44c1a63a --- /dev/null +++ b/testbenches/ip/dma_flock/scoreboard.sv @@ -0,0 +1,125 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2024 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsabilities that he or she has by using this source/core. +// +// This core is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +// A PARTICULAR PURPOSE. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/main/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`include "utils.svh" + +package scoreboard_pkg; + + import xil_common_vip_pkg::*; + import axi4stream_vip_pkg::*; + import axi_vip_pkg::*; + import logger_pkg::*; + + class scoreboard; + // List of analysis ports from the monitors + xil_analysis_port #(axi4stream_monitor_transaction) src_axis_ap; + xil_analysis_port #(axi4stream_monitor_transaction) dst_axis_ap; + + protected event shutdown_event; + + function new(); + endfunction: new + + function void connect( + xil_analysis_port #(axi4stream_monitor_transaction) src_axis_ap, + xil_analysis_port #(axi4stream_monitor_transaction) dst_axis_ap); + + this.src_axis_ap = src_axis_ap; + this.dst_axis_ap = dst_axis_ap; + endfunction: connect + + task run(); + fork begin + fork + run_src(); + run_dst(); + join_none + @shutdown_event; + disable fork; + end join_none + endtask: run + + task run_src(); + endtask : run_src + + task run_dst(); + axi4stream_monitor_transaction dst_axis_trans; + xil_axi4stream_data_beat data_beat; + int num_bytes; + xil_axi4stream_data_byte expected_byte; + xil_axi4stream_data_byte received_byte; + bit received_tuser; + bit received_tlast; + int frame_count,prev_frame_count = 0; + + forever begin + dst_axis_ap.get(dst_axis_trans); + // get TDATA + // Assumption is that all bytes from beat are valid + data_beat = dst_axis_trans.get_data_beat(); + num_bytes = dst_axis_trans.get_data_width()/8; + // Get TUSER[0] + received_tuser = dst_axis_trans.get_user_beat(); + // Get TLAST + received_tlast = dst_axis_trans.get_last(); + // TUSER marks the start of frame; set the current frame number based + // on first beat first pixel + if (received_tuser == 1) begin + frame_count = data_beat[7:0]; + if (frame_count < prev_frame_count) + `ERROR(("Frame count out of order. Expected at least: 0x%h ; Found : 0x%h", prev_frame_count, frame_count)); + else + `INFO(("Received frame 0x%0h ", frame_count)); + prev_frame_count = frame_count; + end + // Compare data against the frame counter; all pixels from frame + // should match the frame counter. + for (int i = 0; i < num_bytes; i++) begin + expected_byte = frame_count; + received_byte = data_beat[i*8+:8]; + if (expected_byte !== received_byte) + `ERROR(("Data mismatch. Expected : 0x%h ; Found : 0x%h", expected_byte, received_byte)); + else + `INFOV(("Received byte 0x%h ", received_byte), 99); + end + end + endtask : run_dst + task shutdown; + -> shutdown_event; + endtask: shutdown + + endclass: scoreboard + +endpackage diff --git a/testbenches/ip/dma_flock/system_bd.tcl b/testbenches/ip/dma_flock/system_bd.tcl new file mode 100644 index 00000000..3473a53e --- /dev/null +++ b/testbenches/ip/dma_flock/system_bd.tcl @@ -0,0 +1,152 @@ +# *************************************************************************** +# *************************************************************************** +# Copyright (C) 2024 Analog Devices, Inc. All rights reserved. +# +# In this HDL repository, there are many different and unique modules, consisting +# of various HDL (Verilog or VHDL) components. The individual modules are +# developed independently, and may be accompanied by separate and unique license +# terms. +# +# The user should read each of these license terms, and understand the +# freedoms and responsibilities that he or she has by using this source/core. +# +# This core is distributed in the hope that it will be useful, but WITHOUT ANY +# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +# A PARTICULAR PURPOSE. +# +# Redistribution and use of source or resulting binaries, with or without modification +# of this file, are permitted under one of the following two license terms: +# +# 1. The GNU General Public License version 2 as published by the +# Free Software Foundation, which can be found in the top level directory +# of this repository (LICENSE_GPL2), and also online at: +# +# +# OR +# +# 2. An ADI specific BSD license, which can be found in the top level directory +# of this repository (LICENSE_ADIBSD), and also on-line at: +# https://github.com/analogdevicesinc/hdl/blob/main/LICENSE_ADIBSD +# This will allow to generate bit files and not release the source code, +# as long as it attaches to an ADI device. +# +# *************************************************************************** +# *************************************************************************** + +source ../../../../scripts/adi_env.tcl + +global m_dma_cfg +global s_dma_cfg +global vdma_cfg +global src_axis_vip_cfg +global dst_axis_vip_cfg + +ad_ip_instance clk_vip src_clk_vip [list \ + INTERFACE_MODE {MASTER} \ + FREQ_HZ {100000000} \ +] +ad_ip_instance clk_vip dst_clk_vip [list \ + INTERFACE_MODE {MASTER} \ + FREQ_HZ {200000000} \ +] + +adi_sim_add_define "SRC_CLK=src_clk_vip" +adi_sim_add_define "DST_CLK=dst_clk_vip" + +# create data source and consumer +ad_ip_instance axi4stream_vip src_axis_vip $src_axis_vip_cfg +ad_ip_instance axi4stream_vip dst_axis_vip $dst_axis_vip_cfg + +adi_sim_add_define "SRC_AXIS=src_axis_vip" +adi_sim_add_define "DST_AXIS=dst_axis_vip" + +## connect clocks +ad_connect dst_clk_vip/clk_out dst_axis_vip/aclk +ad_connect src_clk_vip/clk_out src_axis_vip/aclk + +## connect resets +ad_connect $sys_dma_resetn src_axis_vip/aresetn +ad_connect $sys_dma_resetn dst_axis_vip/aresetn + +# create external syncs +if {[dict exists $m_dma_cfg USE_EXT_SYNC]} { + if {[dict get $m_dma_cfg USE_EXT_SYNC] == 1} { + ad_ip_instance io_vip src_sync_io_vip + adi_sim_add_define "SRC_SYNC_IO=src_sync_io_vip" + + ## connect clocks + ad_connect src_clk_vip/clk_out src_sync_io_vip/clk + } +} +if {[dict exists $s_dma_cfg USE_EXT_SYNC]} { + if {[dict get $s_dma_cfg USE_EXT_SYNC] == 1} { + ad_ip_instance io_vip dst_sync_io_vip + adi_sim_add_define "DST_SYNC_IO=dst_sync_io_vip" + + ## connect clocks + ad_connect dst_clk_vip/clk_out dst_sync_io_vip/clk + } +} + +# create DMAs +ad_ip_instance axi_dmac dut_tx_dma $m_dma_cfg +ad_ip_instance axi_dmac dut_rx_dma $s_dma_cfg + +adi_sim_add_define "DUT_TX_DMA=dut_tx_dma" +adi_sim_add_define "DUT_RX_DMA=dut_rx_dma" +ad_connect sys_dma_clk dut_rx_dma/m_src_axi_aclk +ad_connect sys_dma_clk dut_tx_dma/m_dest_axi_aclk + +## connect clocks +ad_connect dst_clk_vip/clk_out dut_rx_dma/m_axis_aclk +ad_connect src_clk_vip/clk_out dut_tx_dma/s_axis_aclk + +## connect resets +ad_connect $sys_dma_resetn dut_rx_dma/m_src_axi_aresetn +ad_connect $sys_dma_resetn dut_tx_dma/m_dest_axi_aresetn + +## connect data source and consumer +ad_connect dut_rx_dma/m_axis dst_axis_vip/S_AXIS +ad_connect src_axis_vip/M_AXIS dut_tx_dma/s_axis + +## connect external syncs +if {[dict exists $m_dma_cfg USE_EXT_SYNC]} { + if {[dict get $m_dma_cfg USE_EXT_SYNC] == 1} { + ad_connect src_sync_io_vip/out dut_tx_dma/src_ext_sync + } +} +if {[dict exists $s_dma_cfg USE_EXT_SYNC]} { + if {[dict get $s_dma_cfg USE_EXT_SYNC] == 1} { + ad_connect dst_sync_io_vip/out dut_rx_dma/dest_ext_sync + } +} + +## connect framelock +ad_connect dut_tx_dma/m_framelock dut_rx_dma/s_framelock + +## connect cpu + +set DUT_RX_DMA 0x7C420000 +set DUT_TX_DMA 0x7C430000 +ad_cpu_interconnect $DUT_RX_DMA dut_rx_dma +ad_cpu_interconnect $DUT_TX_DMA dut_tx_dma +adi_sim_add_define "DUT_RX_DMA_BA=[format "%d" ${DUT_RX_DMA}]" +adi_sim_add_define "DUT_TX_DMA_BA=[format "%d" ${DUT_TX_DMA}]" + +ad_mem_hp0_interconnect $sys_dma_clk dut_rx_dma/m_src_axi +ad_mem_hp0_interconnect $sys_dma_clk dut_tx_dma/m_dest_axi + +ad_cpu_interrupt ps-13 mb-12 dut_rx_dma/irq +ad_cpu_interrupt ps-12 mb-13 dut_tx_dma/irq + +set RX_DMA 0x7C420000 +set_property offset $RX_DMA [get_bd_addr_segs {mng_axi_vip/Master_AXI/SEG_data_dut_rx_dma}] +adi_sim_add_define "RX_DMA_BA=[format "%d" ${RX_DMA}]" + +set TX_DMA 0x7C430000 +set_property offset $TX_DMA [get_bd_addr_segs {mng_axi_vip/Master_AXI/SEG_data_dut_tx_dma}] +adi_sim_add_define "TX_DMA_BA=[format "%d" ${TX_DMA}]" + +set_property offset 0x0 [get_bd_addr_segs {dut_tx_dma/m_dest_axi/SEG_ddr_axi_vip_Reg}] +set_property offset 0x0 [get_bd_addr_segs {dut_rx_dma/m_src_axi/SEG_ddr_axi_vip_Reg}] + diff --git a/testbenches/ip/dma_flock/system_project.tcl b/testbenches/ip/dma_flock/system_project.tcl new file mode 100644 index 00000000..331c579b --- /dev/null +++ b/testbenches/ip/dma_flock/system_project.tcl @@ -0,0 +1,47 @@ +source ../../../scripts/adi_sim.tcl +source ../../../../scripts/adi_env.tcl +source $ad_hdl_dir/projects/scripts/adi_board.tcl + +if {$argc < 1} { + puts "Expecting at least one argument that specifies the test configuration" + exit 1 +} else { + set cfg_file [lindex $argv 0] +} + +# Read config file with cfg information +source "cfgs/${cfg_file}" + +# Set the project name +set project_name [file rootname $cfg_file] + +# Create the project +adi_sim_project_xilinx $project_name "xcvu9p-flga2104-2L-e" + +# Add test files to the project +adi_sim_project_files [list \ + "../../../library/utilities/utils.svh" \ + "../../../library/drivers/dmac/dma_trans.sv" \ + "../../../library/utilities/logger_pkg.sv" \ + "../../../library/regmaps/reg_accessor.sv" \ + "../../../library/vip/amd/m_axis_sequencer.sv" \ + "../../../library/vip/amd/s_axis_sequencer.sv" \ + "../../../library/vip/amd/m_axi_sequencer.sv" \ + "../../../library/vip/amd/s_axi_sequencer.sv" \ + "../../../library/drivers/dmac/dmac_api.sv" \ + "../../../library/regmaps/adi_regmap_pkg.sv" \ + "../../../library/regmaps/adi_regmap_dmac_pkg.sv" \ + "../../../library/drivers/dmac/dma_trans.sv" \ + "../../../library/utilities/test_harness_env.sv" \ + "../../../library/regmaps/adi_peripheral_pkg.sv" \ + "scoreboard.sv" \ + "environment.sv" \ + "tests/test_program.sv" \ + "tests/test_program_frame_delay.sv" \ + "system_tb.sv" \ +] + +#set a default test program +adi_sim_add_define "TEST_PROGRAM=test_program" + +adi_sim_generate $project_name diff --git a/testbenches/ip/dma_flock/system_tb.sv b/testbenches/ip/dma_flock/system_tb.sv new file mode 100644 index 00000000..8fb9ed2f --- /dev/null +++ b/testbenches/ip/dma_flock/system_tb.sv @@ -0,0 +1,44 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2024 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsabilities that he or she has by using this source/core. +// +// This core is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +// A PARTICULAR PURPOSE. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/main/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`include "utils.svh" + +module system_tb(); + + `TEST_PROGRAM test(); + + test_harness `TH (); + +endmodule diff --git a/testbenches/ip/dma_flock/tests/test_program.sv b/testbenches/ip/dma_flock/tests/test_program.sv new file mode 100644 index 00000000..7988d1eb --- /dev/null +++ b/testbenches/ip/dma_flock/tests/test_program.sv @@ -0,0 +1,322 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2024 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsabilities that he or she has by using this source/core. +// +// This core is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +// A PARTICULAR PURPOSE. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/main/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`include "utils.svh" + +import environment_pkg::*; +import axi_vip_pkg::*; +import axi4stream_vip_pkg::*; +import logger_pkg::*; +import adi_regmap_pkg::*; +import adi_regmap_dmac_pkg::*; +import dmac_api_pkg::*; +import dma_trans_pkg::*; + +program test_program; + + environment env; + // Register accessors + dmac_api m_dmac_api; + dmac_api s_dmac_api; + + int frame_count; + int has_sfsync; + int has_dfsync; + int sync_gen_en; + + initial begin + //creating environment + env = new(`TH.`SYS_CLK.inst.IF, + `TH.`DMA_CLK.inst.IF, + `TH.`DDR_CLK.inst.IF, + `TH.`SYS_RST.inst.IF, + `TH.`MNG_AXI.inst.IF, + `TH.`DDR_AXI.inst.IF, + `TH.`SRC_AXIS.inst.IF, + `TH.`DST_AXIS.inst.IF + ); + + #2ps; + + has_sfsync = `M_DMA_CFG_USE_EXT_SYNC; + has_dfsync = `S_DMA_CFG_USE_EXT_SYNC; + + setLoggerVerbosity(6); + env.start(); + start_clocks(); + env.sys_reset(); + env.run(); + + m_dmac_api = new("TX_DMA_BA", env.mng, `TX_DMA_BA); + m_dmac_api.probe(); + + s_dmac_api = new("RX_DMA_BA", env.mng, `RX_DMA_BA); + s_dmac_api.probe(); + + sanity_test; + + // Test synchronous (reader and writer at the same speed) + singleTest( + .frame_num(10), + .flock_framenum(3), + .flock_distance(0), + .src_clk(250000000), + .dst_clk(250000000) + ); + + // Test repeating (reader faster than writer) + singleTest( + .frame_num(5), + .flock_framenum(3), + .flock_distance(0), + .src_clk( 50000000), + .dst_clk(250000000) + ); + + // Test skipping (writer faster than reader) + singleTest( + .frame_num(10), + .flock_framenum(3), + .flock_distance(0), + .src_clk(250000000), + .dst_clk( 50000000) + ); + + stop_clocks(); + env.stop(); + + `INFO(("Testbench done!")); + $finish(); + + end + + task singleTest( + input int frame_num = 10, + input int flock_framenum = 3, + input int flock_distance = 1, + input int src_clk = 250000000, + input int dst_clk = 250000000 + ); + dma_flocked_2d_segment m_seg, s_seg; + int m_tid, s_tid; + automatic int rand_succ = 0; + + axi4stream_ready_gen tready_gen; + axi_ready_gen wready_gen; + + // Set no backpressure from AXIS destination + env.dst_axis_seq.set_mode(XIL_AXI4STREAM_READY_GEN_NO_BACKPRESSURE); + env.dst_axis_seq.user_gen_tready(); + + // Set no backpressure from DDR + wready_gen = env.ddr_axi_agent.wr_driver.create_ready("wready"); + wready_gen.set_ready_policy(XIL_AXI_READY_GEN_NO_BACKPRESSURE); + env.ddr_axi_agent.wr_driver.send_wready(wready_gen); + + m_seg = new(m_dmac_api.p); + rand_succ = m_seg.randomize() with { dst_addr == 0; + length == 1024; + ylength == 8; + dst_stride == length; }; + if (rand_succ == 0) `ERROR(("randomization failed")); + + m_seg.flock_framenum = flock_framenum; + m_seg.flock_distance = flock_distance; + m_seg.flock_mode = 0; + m_seg.flock_wait_writer = 1; + + s_seg = m_seg.toSlaveSeg(); + + env.src_axis_seq.set_stop_policy(m_axis_sequencer_pkg::STOP_POLICY_DESCRIPTOR_QUEUE); + env.src_axis_seq.set_data_gen_mode(m_axis_sequencer_pkg::DATA_GEN_MODE_TEST_DATA); + env.src_axis_seq.start(); + + m_dmac_api.set_control('b1001); + m_dmac_api.set_flags('b111); + + s_dmac_api.set_control('b1001); + s_dmac_api.set_flags('b111); + + // Submit transfers to DMACs + m_dmac_api.submit_transfer(m_seg, m_tid); + s_dmac_api.submit_transfer(s_seg, s_tid); + + // Set clock generators + set_src_clock(src_clk); + set_dst_clock(dst_clk); + + sync_gen_en = 1; + fork + // Generate external sync and data for SRC + begin + for (int i = 0; i < frame_num; i++) begin + if (sync_gen_en) begin + fork + gen_src_fsync(.clk_period(src_clk), + .bytes_to_transfer(m_seg.get_bytes_in_transfer)); + // Generate data + begin + for (int l = 0; l < m_seg.ylength; l++) begin + // update the AXIS generator command + env.src_axis_seq.add_xfer_descriptor(.bytes_to_generate(m_seg.length), + .gen_last(1), + .gen_sync(l==0)); + end + + // update the AXIS generator data + for (int j = 0; j < m_seg.get_bytes_in_transfer; j++) begin + // ADI DMA frames start from offset 0x00 + env.src_axis_seq.push_byte_for_stream(frame_count); + end + end + join + frame_count++; + end + end + end + + // Generate external syncs for DEST + begin + while (sync_gen_en) begin + gen_dst_fsync(.clk_period(dst_clk), + .bytes_to_transfer(m_seg.get_bytes_in_transfer)); + end + #10ns; + end + join_any + sync_gen_en = 0; + + // Stop triggers wait stop policy + env.src_axis_seq.stop(); + + // Shutdown DMACs + m_dmac_api.disable_dma(); + s_dmac_api.disable_dma(); + + endtask + + // This is a simple reg test to check the register access API + task sanity_test(); + xil_axi_ulong mtestWADDR; // Write ADDR + + bit [63:0] mtestWData; // Write Data + bit [31:0] rdData; + + env.mng.RegReadVerify32(`TX_DMA_BA + GetAddrs(DMAC_IDENTIFICATION), 'h44_4D_41_43); + + mtestWData = 0; + repeat (10) begin + env.mng.RegWrite32(`TX_DMA_BA + GetAddrs(DMAC_SCRATCH), mtestWData); + env.mng.RegReadVerify32(`TX_DMA_BA + GetAddrs(DMAC_SCRATCH), mtestWData); + mtestWData += 4; + end + + env.mng.RegReadVerify32(`RX_DMA_BA + GetAddrs(DMAC_IDENTIFICATION), 'h44_4D_41_43); + + endtask + + // Set the writer AXIS side clock frequency + task set_src_clock(input int freq); + `TH.`SRC_CLK.inst.IF.set_clk_frq(.user_frequency(freq)); + endtask + + // Set the reader AXIS side clock frequency + task set_dst_clock(input int freq); + `TH.`DST_CLK.inst.IF.set_clk_frq(.user_frequency(freq)); + endtask + + // Set the MM AXI side DDR clock frequency + task set_ddr_clock(input int freq); + `TH.`DDR_CLK.inst.IF.set_clk_frq(.user_frequency(freq)); + endtask + + // Start all clocks + task start_clocks(); + set_src_clock(100000000); + set_dst_clock(100000000); + set_ddr_clock(600000000); + + `TH.`SRC_CLK.inst.IF.start_clock; + `TH.`DST_CLK.inst.IF.start_clock; + #100ns; + endtask + + // Stop all clocks + task stop_clocks(); + `TH.`SRC_CLK.inst.IF.stop_clock; + `TH.`DST_CLK.inst.IF.stop_clock; + endtask + + // Assert external sync for one clock cycle + task assert_writer_ext_sync(); + `ifdef SRC_SYNC_IO + `TH.`SRC_SYNC_IO.inst.IF.setw_io(1); + `TH.`SRC_SYNC_IO.inst.IF.setw_io(0); + `endif + endtask + + // Assert external sync for one clock cycle + task assert_reader_ext_sync(); + `ifdef DST_SYNC_IO + `TH.`DST_SYNC_IO.inst.IF.setw_io(1); + `TH.`DST_SYNC_IO.inst.IF.setw_io(0); + `endif + endtask + + // Generate external sync pulse for input frames + task gen_src_fsync(input int clk_period, input int bytes_to_transfer); + real incycles,fperiod; + if (has_sfsync) begin + assert_writer_ext_sync(); + end + // Calculate and wait one input frame duration plus a margin + incycles = bytes_to_transfer / `SRC_AXIS_VIP_CFG_TDATA_NUM_BYTES * 1.5; + fperiod = (incycles*1000000000)/ clk_period; + #(fperiod*1ns); + endtask + + // Generate external sync pulse for output frames + task gen_dst_fsync(input int clk_period, input int bytes_to_transfer); + real incycles,fperiod; + if (has_dfsync) begin + assert_reader_ext_sync(); + end + // Calculate and wait one output frame duration plus a margin + incycles = bytes_to_transfer / `DST_AXIS_VIP_CFG_TDATA_NUM_BYTES * 1.5; + fperiod = (incycles*1000000000)/ clk_period; + #(fperiod*1ns); + endtask + +endprogram diff --git a/testbenches/ip/dma_flock/tests/test_program_frame_delay.sv b/testbenches/ip/dma_flock/tests/test_program_frame_delay.sv new file mode 100644 index 00000000..3e16f9f3 --- /dev/null +++ b/testbenches/ip/dma_flock/tests/test_program_frame_delay.sv @@ -0,0 +1,376 @@ +// *************************************************************************** +// *************************************************************************** +// Copyright 2024 (c) Analog Devices, Inc. All rights reserved. +// +// In this HDL repository, there are many different and unique modules, consisting +// of various HDL (Verilog or VHDL) components. The individual modules are +// developed independently, and may be accompanied by separate and unique license +// terms. +// +// The user should read each of these license terms, and understand the +// freedoms and responsabilities that he or she has by using this source/core. +// +// This core is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR +// A PARTICULAR PURPOSE. +// +// Redistribution and use of source or resulting binaries, with or without modification +// of this file, are permitted under one of the following two license terms: +// +// 1. The GNU General Public License version 2 as published by the +// Free Software Foundation, which can be found in the top level directory +// of this repository (LICENSE_GPL2), and also online at: +// +// +// OR +// +// 2. An ADI specific BSD license, which can be found in the top level directory +// of this repository (LICENSE_ADIBSD), and also on-line at: +// https://github.com/analogdevicesinc/hdl/blob/main/LICENSE_ADIBSD +// This will allow to generate bit files and not release the source code, +// as long as it attaches to an ADI device. +// +// *************************************************************************** +// *************************************************************************** + +`include "utils.svh" + +import environment_pkg::*; +import axi_vip_pkg::*; +import axi4stream_vip_pkg::*; +import logger_pkg::*; +import adi_regmap_pkg::*; +import adi_regmap_dmac_pkg::*; +import dmac_api_pkg::*; +import dma_trans_pkg::*; + +program test_program_frame_delay; + + environment env; + // Register accessors + dmac_api m_dmac_api; + dmac_api s_dmac_api; + + int frame_count; + int has_sfsync; + int has_dfsync; + int has_s_autorun; + int has_m_autorun; + int sync_gen_en; + + initial begin + //creating environment + env = new(`TH.`SYS_CLK.inst.IF, + `TH.`DMA_CLK.inst.IF, + `TH.`DDR_CLK.inst.IF, + `TH.`SYS_RST.inst.IF, + `TH.`MNG_AXI.inst.IF, + `TH.`DDR_AXI.inst.IF, + `TH.`SRC_AXIS.inst.IF, + `TH.`DST_AXIS.inst.IF + ); + + #2ps; + + has_sfsync = `M_DMA_CFG_USE_EXT_SYNC; + has_dfsync = `S_DMA_CFG_USE_EXT_SYNC; + has_m_autorun = `M_DMA_CFG_AUTORUN; + has_s_autorun = `S_DMA_CFG_AUTORUN; + + setLoggerVerbosity(6); + env.start(); + start_clocks(); + env.sys_reset(); + env.run(); + + m_dmac_api = new("TX_DMA_BA", env.mng, `TX_DMA_BA); + m_dmac_api.probe(); + + s_dmac_api = new("RX_DMA_BA", env.mng, `RX_DMA_BA); + s_dmac_api.probe(); + + + if (has_s_autorun + has_m_autorun == 0) begin + sanity_test; + end + + // Test non-autorun mode + if (has_s_autorun + has_m_autorun == 0) begin + singleTest( + .frame_num(10), + .flock_framenum(3), + .flock_distance(0), + .src_clk(250000000), + .dst_clk(250000000) + ); + + singleTest( + .frame_num(10), + .flock_framenum(3), + .flock_distance(0), + .src_clk(250000000), + .dst_clk(250000000) + ); + + singleTest( + .frame_num(10), + .flock_framenum(3), + .flock_distance(0), + .src_clk(250000000), + .dst_clk(250000000) + ); + end + + // Test autorun mode + if (has_s_autorun + has_m_autorun == 2) begin + int autorun_flock_framenum; + int autorun_flock_distance; + + // Get parameters + autorun_flock_framenum = `TH.`DUT_RX_DMA.inst.AUTORUN_FRAMELOCK_CONFIG & 'hFF; + autorun_flock_distance = (((`TH.`DUT_RX_DMA.inst.AUTORUN_FRAMELOCK_CONFIG) >> 16) & 'hFF) + 1; + + singleTest( + .frame_num(10), + .flock_framenum(autorun_flock_framenum), + .flock_distance(autorun_flock_distance), + .src_clk(250000000), + .dst_clk(250000000), + .has_autorun(1) + ); + end + if (has_s_autorun + has_m_autorun == 1) begin + `ERROR(("Both DMACs must be set in autorun mode.")); + end + + stop_clocks(); + env.stop(); + + `INFO(("Testbench done!")); + $finish(); + + end + + task singleTest( + input int frame_num = 10, + input int flock_framenum = 3, + input int flock_distance = 1, + input int src_clk = 250000000, + input int dst_clk = 250000000, + input int has_autorun = 0 + ); + dma_flocked_2d_segment m_seg, s_seg; + int m_tid, s_tid; + automatic int rand_succ = 0; + int x_length, y_length, baseaddress; + + axi4stream_ready_gen tready_gen; + axi_ready_gen wready_gen; + + // Set no backpressure from AXIS destination + env.dst_axis_seq.set_mode(XIL_AXI4STREAM_READY_GEN_NO_BACKPRESSURE); + env.dst_axis_seq.user_gen_tready(); + + // Set no backpressure from DDR + wready_gen = env.ddr_axi_agent.wr_driver.create_ready("wready"); + wready_gen.set_ready_policy(XIL_AXI_READY_GEN_NO_BACKPRESSURE); + env.ddr_axi_agent.wr_driver.send_wready(wready_gen); + + m_seg = new(m_dmac_api.p); + + baseaddress = 0; + x_length = 1024; + y_length = 8; + if (has_autorun) begin + // Get parameters + baseaddress = `TH.`DUT_TX_DMA.inst.AUTORUN_DEST_ADDR; + x_length = (`TH.`DUT_TX_DMA.inst.AUTORUN_X_LENGTH) + 1; + y_length = (`TH.`DUT_TX_DMA.inst.AUTORUN_Y_LENGTH) + 1; + end + + rand_succ = m_seg.randomize() with { dst_addr == baseaddress; + length == x_length; + ylength == y_length; + dst_stride == length; }; + if (rand_succ == 0) `ERROR(("randomization failed")); + + m_seg.flock_framenum = flock_framenum; + m_seg.flock_distance = flock_distance; + m_seg.flock_mode = 1; + m_seg.flock_wait_writer = 1; + + s_seg = m_seg.toSlaveSeg(); + + env.src_axis_seq.set_stop_policy(m_axis_sequencer_pkg::STOP_POLICY_DESCRIPTOR_QUEUE); + env.src_axis_seq.set_data_gen_mode(m_axis_sequencer_pkg::DATA_GEN_MODE_TEST_DATA); + env.src_axis_seq.start(); + + if (has_autorun == 0) begin + m_dmac_api.set_control('b1001); + m_dmac_api.set_flags('b111); + + s_dmac_api.set_control('b1001); + s_dmac_api.set_flags('b111); + end + + // Submit transfers to DMACs + if (has_autorun == 0) begin + m_dmac_api.submit_transfer(m_seg, m_tid); + s_dmac_api.submit_transfer(s_seg, s_tid); + end + + // Set clock generators + set_src_clock(src_clk); + set_dst_clock(dst_clk); + + sync_gen_en = 1; + fork + // Generate external sync and data for SRC + begin + #0.5us; + for (int i = 0; i < frame_num; i++) begin + if (sync_gen_en) begin + fork + gen_src_fsync(.clk_period(src_clk), + .bytes_to_transfer(m_seg.get_bytes_in_transfer)); + // Generate data + begin + for (int l = 0; l < m_seg.ylength; l++) begin + // update the AXIS generator command + env.src_axis_seq.add_xfer_descriptor(.bytes_to_generate(m_seg.length), + .gen_last(1), + .gen_sync(l==0)); + end + + // update the AXIS generator data + for (int j = 0; j < m_seg.get_bytes_in_transfer; j++) begin + // ADI DMA frames start from offset 0x00 + env.src_axis_seq.push_byte_for_stream(frame_count); + end + end + join + frame_count++; + end + end + end + + // Generate external syncs for DEST + begin + for (int i=0; i + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Framelock + label + + + m_frame_in[3:0] + m_frame_in[3:0] + + + m_frame_out[3:0] + m_frame_out[3:0] + + + Source + label + + + s_axi + s_axi + + + s_axis + s_axis + + + m_dest_axi + m_dest_axi + + + Destination + label + + + s_axi + s_axi + + + m_axis + m_axis + + + m_src_axi + m_src_axi + + diff --git a/testbenches/ip/dma_flock/waves/cfg2_fsync.wcfg b/testbenches/ip/dma_flock/waves/cfg2_fsync.wcfg new file mode 100644 index 00000000..f099716c --- /dev/null +++ b/testbenches/ip/dma_flock/waves/cfg2_fsync.wcfg @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Framelock + label + + + m_frame_in[3:0] + m_frame_in[3:0] + + + m_frame_out[3:0] + m_frame_out[3:0] + + + Source + label + + + s_axi + s_axi + + + s_axis + s_axis + + + m_dest_axi + m_dest_axi + + + Destination + label + + + s_axi + s_axi + + + m_axis + m_axis + + + m_src_axi + m_src_axi + + diff --git a/testbenches/ip/dma_flock/waves/cfg3_fsync_autorun.wcfg b/testbenches/ip/dma_flock/waves/cfg3_fsync_autorun.wcfg new file mode 100644 index 00000000..f099716c --- /dev/null +++ b/testbenches/ip/dma_flock/waves/cfg3_fsync_autorun.wcfg @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Framelock + label + + + m_frame_in[3:0] + m_frame_in[3:0] + + + m_frame_out[3:0] + m_frame_out[3:0] + + + Source + label + + + s_axi + s_axi + + + s_axis + s_axis + + + m_dest_axi + m_dest_axi + + + Destination + label + + + s_axi + s_axi + + + m_axis + m_axis + + + m_src_axi + m_src_axi + +