Vengineerの戯言

人生は短いけど、長いです。人生を楽しみましょう!

Xilinx Vitis の中を調べる(その8)

はじめに

Xilinx Vitis の中を調べるのその7。

UVM関連のファイルを調べるです。

multi_apuint.autotb.v

これがトップテストベンチで、下記のような構造になっているっぽいです。

Random Stall が OFF の時のトップテストベンチの構造が下記のようなので、ファイルの入出力が無くなった代わりに、sv_module_top モジュールの svtb_top というインスタンスが追加されたっぽいです。

test_multi_apuint_test_lib

まずは、xsim コマンドのログから、test_multi_apuint_test_lib と出ています。

UVM_INFO /mnt/usb/XILINX/Vivado/2022.1/Vivado/2022.1/data/system_verilog/uvm_1.2/xlnx_uvm_package.sv(18648) @ 0: reporter [NO_DPI_TSTNAME] UVM_NO_DPI defined--getting UVM_TESTNAME directly, without DPI
UVM_INFO @ 0: reporter [RNTST] Running test multi_apuint_test_lib...
UVM_INFO ./svtb/multi_apuint_test_lib.sv(30) @ 0: uvm_test_top [uvm_test_top] build_phase done

これは、xsim コマンドへの引数として渡した「-testplusarg "UVM_TESTNAME=multi_apuint_test_lib"」の UVM_TESTNAME に対応するものです。

xsim -testplusarg "UVM_VERBOSITY=UVM_LOW" -testplusarg "UVM_TESTNAME=multi_apuint_test_lib" -testplusarg "UVM_TIMEOUT=20000000000000" --noieeewarnings multi_apuint -tclbatch multi_apuint.tcl

multi_apuint_test_lib はどこ?

multi_apuint_test_lib は、下記のsvtb/multi_apuint_test_lib.sv になります。

//==============================================================
//Vitis HLS - High-Level Synthesis from C, C++ and OpenCL v2022.1 (64-bit)
//Tool Version Limit: 2022.04
//Copyright 1986-2022 Xilinx, Inc. All Rights Reserved.
//==============================================================
`ifndef MULTI_APUINT_TEST_LIB__SV
    `define MULTI_APUINT_TEST_LIB__SV

    `include "uvm_macros.svh"

    class multi_apuint_test_lib extends uvm_test;

        multi_apuint_env top_env;

        `uvm_component_utils(multi_apuint_test_lib)

        function new (string name, uvm_component parent = null);
            super.new(name, parent);
        endfunction

        virtual function void build_phase(uvm_phase phase);
            super.build_phase(phase);
            top_env = multi_apuint_subsystem_pkg::multi_apuint_env::type_id::create("top_env", this);
            uvm_config_db#(uvm_object_wrapper)::set(
                    this,
                    "top_env.multi_apuint_virtual_sqr.run_phase",
                    "default_sequence",
                    multi_apuint_subsys_test_sequence_lib::type_id::get()
                );
            `uvm_info(this.get_full_name(), "build_phase done", UVM_LOW)
        endfunction
        virtual function void end_of_elaboration_phase(uvm_phase phase);
            uvm_root top = uvm_root::get();
            top.print_topology();
        endfunction
    endclass

xsim.log ファイルを再度見ると、Running test multi_apuint_test_lib の後に、./svtb/multi_apuint_test_lib.sv(30)で、build_phase done というメッセージが表示されます。これは、./svtb/multi_apuint_test_lib.sv の 下記の build_phase が実行されたということを示しています。

UVM_INFO /mnt/usb/XILINX/Vivado/2022.1/Vivado/2022.1/data/system_verilog/uvm_1.2/xlnx_uvm_package.sv(18648) @ 0: reporter [NO_DPI_TSTNAME] UVM_NO_DPI defined--getting UVM_TESTNAME directly, without DPI
UVM_INFO @ 0: reporter [RNTST] Running test multi_apuint_test_lib...
UVM_INFO ./svtb/multi_apuint_test_lib.sv(30) @ 0: uvm_test_top [uvm_test_top] build_phase done

build_phase の中では、下記のように、

  • top_env を生成
  • top_env.multi_apuint_virtual_sqr.run_phase に、default_sequence を設定しています。
        virtual function void build_phase(uvm_phase phase);
            super.build_phase(phase);
            top_env = multi_apuint_subsystem_pkg::multi_apuint_env::type_id::create("top_env", this);
            uvm_config_db#(uvm_object_wrapper)::set(
                    this,
                    "top_env.multi_apuint_virtual_sqr.run_phase",
                    "default_sequence",
                    multi_apuint_subsys_test_sequence_lib::type_id::get()
                );
            `uvm_info(this.get_full_name(), "build_phase done", UVM_LOW)
        endfunction

sv_module_top

svtb/sv_module_top.sv は、下記のようになっています。

//==============================================================
//Vitis HLS - High-Level Synthesis from C, C++ and OpenCL v2022.1 (64-bit)
//Tool Version Limit: 2022.04
//Copyright 1986-2022 Xilinx, Inc. All Rights Reserved.
//==============================================================

`ifndef SV_MODULE_TOP_SV
`define SV_MODULE_TOP_SV


`timescale 1ns/1ps


`include "uvm_macros.svh"
import uvm_pkg::*;
import file_agent_pkg::*;
import svr_pkg::*;
import multi_apuint_subsystem_pkg::*;
`include "multi_apuint_subsys_test_sequence_lib.sv"
`include "multi_apuint_test_lib.sv"


module sv_module_top;


    misc_interface              misc_if ( .clock(apatb_multi_apuint_top.AESL_clock), .reset(apatb_multi_apuint_top.AESL_
reset) );
    assign apatb_multi_apuint_top.ap_start = misc_if.tb2dut_ap_start;
    assign misc_if.dut2tb_ap_done = apatb_multi_apuint_top.ap_done;
    assign misc_if.dut2tb_ap_ready = apatb_multi_apuint_top.ap_ready;
    initial begin
        uvm_config_db #(virtual misc_interface)::set(null, "uvm_test_top.top_env.*", "misc_if", misc_if);
    end


    svr_if #(8)  svr_multi_in0_if    (.clk  (apatb_multi_apuint_top.AESL_clock), .rst(apatb_multi_apuint_top.AESL_reset)
);
    assign apatb_multi_apuint_top.multi_in0_ap_vld = svr_multi_in0_if.valid;
    assign svr_multi_in0_if.ready = apatb_multi_apuint_top.multi_in0_ap_ack;
    assign apatb_multi_apuint_top.multi_in0 = svr_multi_in0_if.data[7:0];
    initial begin
        uvm_config_db #( virtual svr_if#(8) )::set(null, "uvm_test_top.top_env.env_master_svr_multi_in0.*", "vif", svr_m
ulti_in0_if);
    end


    svr_if #(8)  svr_multi_in1_if    (.clk  (apatb_multi_apuint_top.AESL_clock), .rst(apatb_multi_apuint_top.AESL_reset)
);
    assign apatb_multi_apuint_top.multi_in1_ap_vld = svr_multi_in1_if.valid;
    assign svr_multi_in1_if.ready = apatb_multi_apuint_top.multi_in1_ap_ack;
    assign apatb_multi_apuint_top.multi_in1 = svr_multi_in1_if.data[7:0];
    initial begin
        uvm_config_db #( virtual svr_if#(8) )::set(null, "uvm_test_top.top_env.env_master_svr_multi_in1.*", "vif", svr_m
ulti_in1_if);
    end


    svr_if #(16)  svr_multi_out_if    (.clk  (apatb_multi_apuint_top.AESL_clock), .rst(apatb_multi_apuint_top.AESL_reset
));
    assign svr_multi_out_if.valid = apatb_multi_apuint_top.multi_out_ap_vld;
    assign apatb_multi_apuint_top.multi_out_ap_ack = svr_multi_out_if.ready;
    assign svr_multi_out_if.data[15:0] = apatb_multi_apuint_top.multi_out;
    initial begin
        uvm_config_db #( virtual svr_if#(16) )::set(null, "uvm_test_top.top_env.env_slave_svr_multi_out.*", "vif", svr_m
ulti_out_if);
    end


    initial begin
        run_test();
    end
endmodule
`endif

sv_module_top は、svtb/sv_module_top.sv です。下図のような構成になっています。sv_module_top モジュールには、下記の4つの interface を使って、トップテストベンチ内の信号に接続しています。

  • svr_if svr_multi_in0_if
  • svr_if svr_multi_in1_if
  • svr_if svr_multi_out_if
  • misc_interface misc_if

  • misc_interface は、ap_xxx 関連
  • svr_if #(8) svr_multi_in0_if は、入力信号 (multi_in0) 関連
  • svr_if #(8) svr_multi_in1_if は、入力信号 (multi_in1) 関連
  • svr_if #(16) svr_multi_out_if は、出力信号 (multi_out) 関連

です。

misc_interface は、svtb/misc_interface.sv です。下記のようなコードになっています。

//==============================================================
//Vitis HLS - High-Level Synthesis from C, C++ and OpenCL v2022.1 (64-bit)
//Tool Version Limit: 2022.04
//Copyright 1986-2022 Xilinx, Inc. All Rights Reserved.
//==============================================================
`ifndef MISC_INTERFACE__SV
`define MISC_INTERFACE__SV
`timescale 1ns/1ps
interface misc_interface (input clock, input reset);


    logic    dut2tb_ap_done   ;
    logic    dut2tb_ap_idle   ;
    logic    dut2tb_ap_ready  ;
    logic    tb2dut_ap_start  = 0;
    logic    tb2dut_ap_continue = 0;
    logic    ap_ready_for_nexttrans = 0;
    logic    ap_done_for_nexttrans = 0;
    logic    initialed = 0;
    logic    finished = 0;
    event    dut2tb_ap_ready_evt;
    event    dut2tb_ap_done_evt;
    event    initialed_evt;
    event    finished_evt;


    clocking pclk @(posedge clock);
        default input #0.1ns output #0.1ns;
    endclocking


    clocking nclk @(negedge clock);
        default input #0.1ns output #0.1ns;
    endclocking


endinterface
`endif

svr_if# は、svr/svr_if.sv です。下記のようなコードになっています。

//==============================================================
//Vitis HLS - High-Level Synthesis from C, C++ and OpenCL v2022.1 (64-bit)
//Tool Version Limit: 2022.04
//Copyright 1986-2022 Xilinx, Inc. All Rights Reserved.
//==============================================================
`ifndef SVR_IF__SV
    `define SVR_IF__SV

    interface svr_if#(int DATA_WIDTH = 32)(input clk, input rst);

        logic [DATA_WIDTH -1: 0] data ;
        logic                    valid;
        logic                    ready;

        property noxwhenh(logic x, logic y);
            disable iff(!rst)
                @(posedge clk)
                (x&y)===1'b0 | (x===1'b1 && (y===1'b0|y==='h1)) | (y==='b1 && (x===1'b0|x==='b1));
        endproperty

        property nodatax(logic x, logic y, logic [DATA_WIDTH - 1: 0] data);
            disable iff(!rst)
                @(posedge clk)
                (x&y)===1'b0 | ((x === 1'b1) && (y === 1'b1) && (|data === 1'b0) | (|data === 1'b1)) | (x === 1'bx) | (y
 === 1'bx);
        endproperty

        validh_readxy: assert property(noxwhenh(valid, ready))
            else $warning("invalid X state when valid/ready is asserted time:%0t  valid:%0d, ready:%0d", $time, valid, r
eady);

        validh_data: assert property(nodatax(valid, ready, data))
            else $warning("data is in X state when valid and ready are asserted time:%0t", $time);

        stable_when_valid: assert property(
                    @(posedge clk) disable iff(!rst)
                    ready===1'b0 && $rose(valid) | ($fell(ready) && valid===1'b1) | ($fell(ready) && $rose(valid)) |=>
                    ($stable(data) [*0:$] ##1 ready===1'b1 & $stable(data)) or (ready===1'b1 & $stable(data))
                )
            else $warning("data is not stable when valid is asserted time:%0t", $time);
    endinterface

`endif

おわりに

次回は、sv_module_top をみていきます。