2020年7月24日金曜日

Vivado SimulatorでUVMを試してみた話その2

Vivado 2019.2でUVMが使えるようになっていたので試してみた話その2。 ここの サンプルをUVM1.2向けにしながら動作を確認しました。

環境

Ubuntu 18.04 Vivado 2019.2 UVM 1.2

テストベンチ

ひとまず波形の出力とログの確認ができたので一度終了。 後で続きやりたくなるかもしれないのでアップ。

`timescale 1ns/1ps
interface sample_if(input logic clk, rstz);
    logic[7:0] addr,data;
    logic valid;
endinterface


module tb_uvm_test;
    `include "uvm_macros.svh"
    import uvm_pkg::*;

    class sample_seq_item extends uvm_sequence_item;
      rand logic [7:0] addr, data;
      `uvm_object_utils_begin(sample_seq_item)
        `uvm_field_int (addr, UVM_DEFAULT)
        `uvm_field_int (data, UVM_DEFAULT)
      `uvm_object_utils_end
      function new (string name = "sample_seq_item_inst");
        super.new(name);
      endfunction : new
    endclass

    class sample_sequencer extends uvm_sequencer #(sample_seq_item);
        `uvm_component_utils(sample_sequencer)
        `uvm_new_func
        task run_phase(uvm_phase phase);
            uvm_report_info("SEQR","Hi I am Sequencer");
        endtask
    endclass

    class sample_driver extends uvm_driver #(sample_seq_item);
        `uvm_component_utils(sample_driver)
        virtual sample_if vif;
        function new (string name ="sample_driver", uvm_component parent);
            super.new(name, parent);
        endfunction

        function void build_phase(uvm_phase phase);
            super.build_phase(phase);
            if(!uvm_config_db#(virtual sample_if)::get(this, "", "vif", vif))
                `uvm_fatal("NOVIF",{"virtual interface must be set for: ",get_full_name(),".vif"});
        endfunction: build_phase

        task run_phase(uvm_phase phase);
            sample_seq_item trans_item;
            vif.valid = 1'b0;
            uvm_report_info("DRIVER", "Hi! I am sample_driver");
            @(posedge vif.rstz);// wait negate reset
            forever begin
                seq_item_port.get_next_item(trans_item);
                // get several value from trans_item and drive
                // signals, receive signals via virtual interface
                @(posedge vif.clk);
                vif.valid <= 1'b1;
                vif.addr  <= trans_item.addr;
                vif.data  <= trans_item.data;
                @(posedge vif.clk) vif.valid <= 1'b0;
                seq_item_port.item_done();
            end
        endtask
    endclass

    class sample_monitor extends uvm_monitor;
        `uvm_component_utils(sample_monitor)
        virtual sample_if vif;
        function new(string name="sample_monitor", uvm_component parent);
            super.new(name, parent);
        endfunction
        function void build_phase(uvm_phase phase);
            super.build_phase(phase);
            if(!uvm_config_db#(virtual sample_if)::get(this, "", "vif", vif))
                `uvm_fatal("NOVIF",{"virtual interface must be set for:", get_full_name(), ".vif"});
        endfunction: build_phase
        task run_phase(uvm_phase phase);
            uvm_report_info("MONITOR","Hi! I am sample_monitor");
            fork
                //check_clock;
                check_trans;
            join
        endtask
        task check_trans;
            forever begin
                @(posedge vif.valid) uvm_report_info("MON", $sformatf("addr=%02Xh, data=%02Xh", vif.addr, vif.data));
            end
        endtask;
        task check_clock;
            forever begin
                wait(vif.clk===1'b0);
                uvm_report_info("MON", "fall clock");
                wait(vif.clk===1'b1);
                uvm_report_info("MON", "rise clock");
            end
        endtask
    endclass
    class sample_agent extends uvm_agent;
        `uvm_component_utils(sample_agent)
        `uvm_new_func
        sample_driver       driver;
        sample_sequencer    sequencer;
        sample_monitor      monitor;
        function void build_phase(uvm_phase phase);
            driver = sample_driver::type_id::create("driver",this);
            sequencer = sample_sequencer::type_id::create("sequencer",this);
            monitor = sample_monitor::type_id::create("monitor",this);
        endfunction
        function void connect_phase(uvm_phase phase);
            if(get_is_active() == UVM_ACTIVE) begin
                driver.seq_item_port.connect(sequencer.seq_item_export);
            end
        endfunction
        task run_phase(uvm_phase phase);
            uvm_report_info("AGENT", "Hi! I am Agent");
        endtask
    endclass
    class sample_env extends uvm_env;
        `uvm_component_utils(sample_env)
        `uvm_new_func
        sample_agent agent;
        function void build_phase(uvm_phase phase);
            super.build_phase(phase);
            agent = sample_agent::type_id::create("agent",this);
        endfunction
    endclass
    virtual class sample_base_sequence extends uvm_sequence #(sample_seq_item);
        function new(string name="sample_base_seq");
            super.new(name);
        endfunction
        virtual task pre_body();
            if(starting_phase != null) begin
                `uvm_info(get_type_name(),
                          $sformatf("%s pre_body() raising %s objection",
                          starting_phase.get_name()), UVM_MEDIUM);
                starting_phase.raise_objection(this);
            end
        endtask
        // Drop the objection in the post_body so the objection is removed when
        // the root sequence is complete.
        virtual task post_body();
            if(starting_phase != null) begin
                `uvm_info(get_type_name(),
                          $sformatf("%s post_bodu() dropping %s objection",
                                    get_sequence_path(),
                                    starting_phase.get_name()), UVM_MEDIUM);
            starting_phase.drop_objection(this);
            end
        endtask
    endclass
    class issue_one_trans_seq extends sample_base_sequence;
        `uvm_object_utils(issue_one_trans_seq)
        function new(string name="issue_one_trans_seq");
            super.new(name);
        endfunction
      virtual task body();
        sample_seq_item trans_item;
        $display("I am issue_one_trans_seq");
        `uvm_create(trans_item)
        trans_item.addr = 8'h00;
        trans_item.data = 8'h10;
        `uvm_send(trans_item)
        #1000;
      endtask
   endclass
   class test extends uvm_test;
        `uvm_component_utils(test)
        `uvm_new_func
        sample_env env;
        virtual function void build_phase(uvm_phase phase);
           env=sample_env::type_id::create("env",this);
            super.build_phase(phase);
        endfunction

        task run_phase(uvm_phase phase);
            issue_one_trans_seq seq = issue_one_trans_seq::type_id::create("seq");
            uvm_report_info("TEST", "Hello World from class test");
            phase.raise_objection(this);
            seq.start(env.agent.sequencer);
            phase.drop_objection(this);
        endtask
    endclass
    class sample_test extends uvm_test;
        `uvm_component_utils(sample_test)
        sample_env env;
        function new (string name="sample_test", uvm_component parent=null);
            super.new(name,parent);
        endfunction
        function void build_phase(uvm_phase phase);
            super.build_phase(phase);
            env = sample_env::type_id::create("env",this);
        endfunction
        task run_phase(uvm_phase phase);
            uvm_report_info("TEST", "Hello World from sample_test");
        endtask
    endclass

    logic clk, rstz;
    sample_if sif(clk, rstz);// interface
    initial begin
        fork
            begin
                clk = 1'b1;
                #100;
                forever #50 clk = ~clk;
            end
            begin
                rstz = 1'b0;
                #100;
                rstz = 1'b1;
            end
        join
    end
    initial begin
        `uvm_info("info", "Hello World from initial block", UVM_LOW)
        uvm_config_db#(virtual sample_if)::set(uvm_root::get(), "*", "vif", sif);
        run_test("test");
    end
endmodule

実行結果

$ ninja open_tb_uvm_test
[1/4] Generating sim/work/xsim/compile_tb_uvm_test.timestamp
tb_uvm_test.sh - Script generated by export_simulation (Vivado v2019.2 (64-bit)-id)

INFO: [VRFC 10-2263] Analyzing SystemVerilog file "/home/akira/work/hls/ICS_IF/test/src/tb_uvm_test.sv" into library xil_defaultlib
INFO: [VRFC 10-311] analyzing module tb_uvm_test
INFO: [VRFC 10-2263] Analyzing Verilog file "/home/akira/work/hls/ICS_IF/build/sim/work/tb_uvm_test/xsim/glbl.v" into library xil_defaultlib
INFO: [VRFC 10-311] analyzing module glbl
[2/4] Generating sim/work/xsim/elaborate_tb_uvm_test.timestamp
tb_uvm_test.sh - Script generated by export_simulation (Vivado v2019.2 (64-bit)-id)

Vivado Simulator 2019.2
Copyright 1986-1999, 2001-2019 Xilinx, Inc. All Rights Reserved.
Running: /opt/Xilinx/Vivado/2019.2/bin/unwrapped/lnx64.o/xelab --relax -L uvm --debug typical --mt auto -L xil_defaultlib -L xilinx_vip -L unisims_ver -L unimacro_ver -L secureip -L xpm --snapshot tb_uvm_test xil_defaultlib.tb_uvm_test xil_defaultlib.glbl -log tb_uvm_test_elaborate.log
Multi-threading is on. Using 2 slave threads.
Starting static elaboration
Pass Through NonSizing Optimizer
WARNING: [VRFC 10-3522] missing or empty argument against format specification for 'sformatf' [/home/akira/work/hls/ICS_IF/test/src/tb_uvm_test.sv:132]
Completed static elaboration
Starting simulation data flow analysis
WARNING: [XSIM 43-4100] "/home/akira/work/hls/ICS_IF/test/src/tb_uvm_test.sv" Line 8. Module tb_uvm_test has a timescale but at least one module in design doesn't have timescale.
WARNING: [XSIM 43-4100] "/home/akira/work/hls/ICS_IF/test/src/tb_uvm_test.sv" Line 2. Module sample_if has a timescale but at least one module in design doesn't have timescale.
WARNING: [XSIM 43-4100] "/home/akira/work/hls/ICS_IF/build/sim/work/tb_uvm_test/xsim/glbl.v" Line 6. Module glbl has a timescale but at least one module in design doesn't have timescale.
Completed simulation data flow analysis
Time Resolution for simulation is 1ps
Compiling package uvm.uvm_pkg
Compiling package std.std
Compiling module xil_defaultlib.sample_if
Compiling module xil_defaultlib.tb_uvm_test
Compiling module xil_defaultlib.glbl
Built simulation snapshot tb_uvm_test
[3/4] Generating sim/work/xsim/tb_uvm_test.wdb
tb_uvm_test.sh - Script generated by export_simulation (Vivado v2019.2 (64-bit)-id)


****** xsim v2019.2 (64-bit)
  **** SW Build 2708876 on Wed Nov  6 21:39:14 MST 2019
  **** IP Build 2700528 on Thu Nov  7 00:09:20 MST 2019
    ** Copyright 1986-2019 Xilinx, Inc. All Rights Reserved.

source xsim.dir/tb_uvm_test/xsim_script.tcl
# xsim {tb_uvm_test} -autoloadwcfg -tclbatch {cmd.tcl} -key {Behavioral:sim_1:Functional:tb_uvm_test} -protoinst {protoinst_files/ics_if.protoinst} -protoinst {protoinst_files/ics_if.protoinst} -protoinst {protoinst_files/sim_ics_if.protoinst}
Vivado Simulator 2019.2
INFO: [Wavedata 42-565] Reading protoinst file protoinst_files/ics_if.protoinst
WARNING: [Wavedata 42-558] Couldn't load one or more protocol instances from protoinst file protoinst_files/ics_if.protoinst for the following reason(s):
There are no instances of module "ics_if" in the design.

INFO: [Wavedata 42-565] Reading protoinst file protoinst_files/ics_if.protoinst
WARNING: [Wavedata 42-558] Couldn't load one or more protocol instances from protoinst file protoinst_files/ics_if.protoinst for the following reason(s):
There are no instances of module "ics_if" in the design.

INFO: [Wavedata 42-565] Reading protoinst file protoinst_files/sim_ics_if.protoinst
WARNING: [Wavedata 42-558] Couldn't load one or more protocol instances from protoinst file protoinst_files/sim_ics_if.protoinst for the following reason(s):
There are no instances of module "sim_ics_if" in the design.

Time resolution is 1 ps
source cmd.tcl
## set curr_wave [current_wave_config]
## if { [string length $curr_wave] == 0 } {
##   if { [llength [get_objects]] > 0} {
##     add_wave /
##     set_property needs_save false [current_wave_config]
##   } else {
##      send_msg_id Add_Wave-1 WARNING "No top level signals found. Simulator will start without a wave window. If you want to open a wave window go to 'File->New Waveform Configuration' or type 'create_wave_config' in the TCL console."
##   }
## }
## log_wave -r /
WARNING: [Simtcl 6-197] One or more HDL objects could not be logged because of object type or size limitations.  To see details please rerun the command with -verbose (-v).
## run -all
UVM_INFO /proj/xbuilds/SWIP/2019.2_0924_1936/installs/lin64/Vivado/2019.2/data/system_verilog/uvm_1.2/xlnx_uvm_package.sv(18601) @ 0: reporter [UVM/RELNOTES]
      (Specify +UVM_NO_RELNOTES to turn off this notice)
  with `UVM_OBJECT_DO_NOT_NEED_CONSTRUCTOR undefined.

  You are using a version of the UVM library that has been compiled
  with `UVM_NO_DEPRECATED undefined.

  You are using a version of the UVM library that has been compiled

  ***********       IMPORTANT RELEASE NOTES         ************
----------------------------------------------------------------
(C) 2013-2014 NVIDIA Corporation
(C) 2011-2013 Cypress Semiconductor Corp.
(C) 2006-2014 Synopsys, Inc.
(C) 2007-2014 Cadence Design Systems, Inc.
(C) 2007-2014 Mentor Graphics Corporation


----------------------------------------------------------------

UVM_INFO /home/akira/work/hls/ICS_IF/test/src/tb_uvm_test.sv(212) @ 0: reporter [info] Hello World from initial block
UVM_INFO @ 0: reporter [RNTST] Running test test...
UVM_INFO /proj/xbuilds/SWIP/2019.2_0924_1936/installs/lin64/Vivado/2019.2/data/system_verilog/uvm_1.2/xlnx_uvm_package.sv(20867) @ 0: reporter [UVM/COMP/NAMECHECK] This implementation of the component name checks requires DPI to be enabled
UVM_INFO @ 0: uvm_test_top [TEST] Hello World from class test
UVM_INFO @ 0: uvm_test_top.env.agent [AGENT] Hi! I am Agent
UVM_INFO @ 0: uvm_test_top.env.agent.sequencer [SEQR] Hi I am Sequencer
UVM_INFO @ 0: uvm_test_top.env.agent.monitor [MONITOR] Hi! I am sample_monitor
UVM_INFO @ 0: uvm_test_top.env.agent.driver [DRIVER] Hi! I am sample_driver
I am issue_one_trans_seq
UVM_INFO @ 200000: uvm_test_top.env.agent.monitor [MON] addr=00h, data=10h
UVM_INFO /proj/xbuilds/SWIP/2019.2_0924_1936/installs/lin64/Vivado/2019.2/data/system_verilog/uvm_1.2/xlnx_uvm_package.sv(19968) @ 1300000: reporter [TEST_DONE] 'run' phase is ready to proceed to the 'extract' phase
UVM_INFO /proj/xbuilds/SWIP/2019.2_0924_1936/installs/lin64/Vivado/2019.2/data/system_verilog/uvm_1.2/xlnx_uvm_package.sv(13673) @ 1300000: reporter [UVM/REPORT/SERVER] [info]     1
[UVM/RELNOTES]     1
[UVM/COMP/NAMECHECK]     1
[TEST_DONE]     1
[TEST]     1
[SEQR]     1
[RNTST]     1
[MONITOR]     1
[MON]     1
[DRIVER]     1
[AGENT]     1
** Report counts by id
UVM_FATAL :    0
UVM_ERROR :    0
UVM_WARNING :    0
UVM_INFO :   11
** Report counts by severity

--- UVM Report Summary ---


$finish called at time : 1300 ns : File "/proj/xbuilds/SWIP/2019.2_0924_1936/installs/lin64/Vivado/2019.2/data/system_verilog/uvm_1.2/xlnx_uvm_package.sv" Line 18699
## quit
INFO: [Common 17-206] Exiting xsim at Fri Jul 24 07:02:17 2020...
[4/4] cd /home/akira/work/hls/ICS_IF/build && /opt/Xilinx/Vivado/2019.2/bin/v....tcl -tclargs /home/akira/work/hls/ICS_IF/build/sim/work/xsim/tb_uvm_test.wdb

****** Vivado v2019.2 (64-bit)
  **** SW Build 2708876 on Wed Nov  6 21:39:14 MST 2019
  **** IP Build 2700528 on Thu Nov  7 00:09:20 MST 2019
    ** Copyright 1986-2019 Xilinx, Inc. All Rights Reserved.

source /home/akira/work/vivado_cmake_helper/vivado_open_wdb.tcl
# set wdbfile_name   [lindex $argv  0]
# start_gui
INFO: [Common 17-206] Exiting Vivado at Fri Jul 24 07:02:55 2020...

波形


参考ページ

https://sites.google.com/site/playsystemverilog/uvm/uvm-introduction-for-10days https://www.accellera.org/images/downloads/standards/uvm/uvm_users_guide_1.2.pdf

2020年7月23日木曜日

VIvado SimulatorでUVMを試してみた話

Vivado 2019.2でUVMが使えるようになっていたので試してみた話。 各種サンプルに記載があるuvm_config_dbにvirtual interfaceを指定するようなテストベンチを実行しようとするとxelabがsegmentation faultを起こす模様。

環境

Ubuntu 18.04 Vivado 2019.2 UVM 1.2

テストベンチ

色々確認した後があって汚いけど以下の通り

`timescale 1ns/1ps
module tb_uvm_test;
    `include "uvm_macros.svh"
    import uvm_pkg::*;

    class sample_seq_item extends uvm_sequence_item;
      rand logic [7:0] addr, data;
      `uvm_object_utils_begin(sample_seq_item)
        `uvm_field_int (addr, UVM_DEFAULT)
        `uvm_field_int (data, UVM_DEFAULT)
      `uvm_object_utils_end
      function new (string name = "sample_seq_item_inst");
        super.new(name);
      endfunction : new
    endclass

    class sample_sequencer extends uvm_sequencer #(sample_seq_item);
        `uvm_component_utils(sample_sequencer)
        `uvm_new_func
        task run_phase(uvm_phase phase);
            uvm_report_info("SEQR","Hi I am Sequencer");
        endtask
    endclass

    interface sample_if(input logic clk, rstz);
        logic[7:0] addr,data;
        logic valid;
    endinterface

    class sample_driver extends uvm_driver #(sample_seq_item);
        `uvm_component_utils(sample_driver)
//        virtual sample_if vif;
        function new (string name ="sample_driver", uvm_component parent);
            super.new(name, parent);
        endfunction
//        function void build_phase(uvm_phase phase);
//            super.build_phase(phase);
//            if(!uvm_config_db#(virtual sample_if)::get(this, "", "vif", vif))
//                `uvm_fatal("NOVIF",{"virtual interface must be set for: ",get_full_name(),".vif"});
//        endfunction: build_phase
        task run_phase(uvm_phase phase);
            uvm_report_info("DRIVER", "Hi! I am sample_driver");
//            sample_seq_item trans_item;
//            vif.valid = 1'b0;
//            @(posedge cif.rstz);// wait negate reset
//            forever begin
//                seq_item_port.get_next_item(trans_item);
//                // get several value from trans_item and drive
//                // signals, receive signals via virtual interface
//                @(posedge vif.clk);
//                vif.valid <= 1'b1;
//                vif.addr  <= trans_item.addr;
//                vif.data  <= trans_item.data;
//                @(posedge vif.clk) vif.valid <= 1'b0;
//                seq_item_port.item_done();
//            end
        endtask
    endclass

    class sample_monitor extends uvm_monitor;
        `uvm_component_utils(sample_monitor)
//        virtual sample_if vif;
        function new(string name="sample_monitor", uvm_component parent);
            super.new(name, parent);
        endfunction
//        function void build_phase(uvm_phase phase);
//            super.build_phase(phase);
//            if(!uvm_config_db#(virtual sample_if)::get(this, "", "vif", vif))
//                `uvm_fatal("NOVIF",{"virtual interface must be set for:", get_full_name(), ".vif"});
//        endfunction: build_phase
        task run_phase(uvm_phase phase);
            uvm_report_info("MONITOR","Hi! I am sample_monitor");
//            fork
//                //check_clock;
//                check_trans;
//            join
        endtask
//        task check_trans;
//            forever begin
//                @(posedge vif.valid) uvm_report_info("MON", $sformatf("addr=%02Xh, data=%02Xh", vif.addr, vif.data));
//            end
//        endtask;
//        task check_clock;
//            forever begin
//                wait(vif.clk===1'b0);
//                uvm_report_info("MON", "fall clock");
//                wait(vif.clk===1'b1);
//                uvm_report_info("MON", "rise clock");
//            end
//        endtask
    endclass
    class sample_agent extends uvm_agent;
        `uvm_component_utils(sample_agent)
        `uvm_new_func
        sample_driver       driver;
        sample_sequencer    sequencer;
        sample_monitor      monitor;
        function void build_phase(uvm_phase phase);
            driver = sample_driver::type_id::create("driver",this);
            sequencer = sample_sequencer::type_id::create("sequencer",this);
            monitor = sample_monitor::type_id::create("monitor",this);
        endfunction
        function void connect_phase(uvm_phase phase);
            if(get_is_active() == UVM_ACTIVE) begin
                driver.seq_item_port.connect(sequencer.seq_item_export);
            end
        endfunction
        task run_phase(uvm_phase phase);
            uvm_report_info("AGENT", "Hi! I am Agent");
        endtask
    endclass
    class sample_env extends uvm_env;
        `uvm_component_utils(sample_env)
        `uvm_new_func
        sample_agent agent;
        function void build_phase(uvm_phase phase);
            super.build_phase(phase);
            agent = sample_agent::type_id::create("agent",this);
        endfunction
    endclass
//    virtual class sample_base_sequence extends uvm_sequence #(sample_seq_item);
//        function new(string name="sample_base_seq");
//            super.new(name);
//        endfunction
//        virtual task pre_body();
//            if(starting_phase != null) begin
//                `uvm_info(get_type_name(),
//                          $sformatf("%s pre_body() raising %s objection",
//                          starting_phase.get_name()), UVM_MEDIUM);
//                starting_phase.raise_objection(this);
//            end
//        endtask
//        // Drop the objection in the post_body so the objection is removed when
//        // the root sequence is complete.
//        virtual task post_body();
//            if(starting_phase != null) begin
//                `uvm_info(get_type_name(),
//                          $sformatf("%s post_bodu() dropping %s objection",
//                                    get_sequence_path(),
//                                    starting_phase.get_name()), UVM_MEDIUM);
//            starting_phase.drop_objection(this);
//            end
//        endtask
//    endclass
//    class issue_one_trans_seq extends sample_base_sequence;
//        function new(string name="issue_one_trans_seq", uvm_component parent);
//            super.new(name,parent);
//        endfunction
//        `uvm_object_utils(issue_one_trans_seq)
//        virtual task body();
//            sample_seq_item trans_item;
//            $display("I am issue_one_trans_seq");
//            `uvm_create(trans_item)
//            trans_item.addr = 8'h00;
//            trans_item.data = 8'h10;
//            `uvm_send(trans_item)
//            #1000 ns;
//        endtask
//    endclass
//    class test extends uvm_test;
//        `uvm_component_utils(test)
//        `uvm_new_func
//        sample_env env;
//        virtual function void build_phase(uvm_phase phase);
//            uvm_config_db#(uvm_object_wrapper)::set(this,
//                "env.agent.sequener.run_phase", "default_sequence",
//                issue_one_trans_seq::type_id::get());
//            env=sample_env::type_id::create("env",this);
//            super.build_phase(phase);
//        endfunction
//    endclass
    class sample_test extends uvm_test;
        `uvm_component_utils(sample_test)
        sample_env env;
        function new (string name="sample_test", uvm_component parent=null);
            super.new(name,parent);
        endfunction
        function void build_phase(uvm_phase phase);
            super.build_phase(phase);
            env = sample_env::type_id::create("env",this);
        endfunction
        task run_phase(uvm_phase phase);
            uvm_report_info("TEST", "Hello World from sample_test");
        endtask
    endclass

    logic clk, rstz;
    sample_if sif(clk, rstz);// interface
    initial begin
        fork
            begin
                clk = 1'b1;
                #100;
                forever #50 clk = ~clk;
            end
            begin
                rstz = 1'b0;
                #100;
                rstz = 1'b1;
            end
        join
    end
    class my_class;
        function new();
        endfunction
    endclass
    initial begin
        my_class mc = new;
        `uvm_info("info", "Hello World from initial block", UVM_LOW)
        uvm_config_db #(virtual sample_if)::set(uvm_root::get(), "*.env.*", "vif", sif);//xelab segmentation fault.
        run_test("sample_test");
    end
endmodule

実行メッセージ

[1/3] Generating sim/work/xsim/compile_tb_uvm_test.timestamp
tb_uvm_test.sh - Script generated by export_simulation (Vivado v2019.2 (64-bit)-id)

INFO: [VRFC 10-2263] Analyzing SystemVerilog file "/home/akira/work/hls/ICS_IF/test/src/tb_uvm_test.sv" into library xil_defaultlib
INFO: [VRFC 10-311] analyzing module tb_uvm_test
WARNING: [VRFC 10-3824] variable 'mc' must explicitly be declared as automatic or static [/home/akira/work/hls/ICS_IF/test/src/tb_uvm_test.sv:208]
INFO: [VRFC 10-2263] Analyzing Verilog file "/home/akira/work/hls/ICS_IF/build/sim/work/tb_uvm_test/xsim/glbl.v" into library xil_defaultlib
INFO: [VRFC 10-311] analyzing module glbl
[2/3] Generating sim/work/xsim/elaborate_tb_uvm_test.timestamp
FAILED: sim/work/xsim/elaborate_tb_uvm_test.timestamp
cd /home/akira/work/hls/ICS_IF/build/sim/work/xsim && source ./elaborate_tb_uvm_test.sh -noclean_files && /opt/Xilinx/Vitis/2019.2/tps/lnx64/cmake-3.3.2/bin/cmake -E touch elaborate_tb_uvm_test.timestamp
tb_uvm_test.sh - Script generated by export_simulation (Vivado v2019.2 (64-bit)-id)

Vivado Simulator 2019.2
Copyright 1986-1999, 2001-2019 Xilinx, Inc. All Rights Reserved.
Running: /opt/Xilinx/Vivado/2019.2/bin/unwrapped/lnx64.o/xelab --relax -L uvm --debug typical --mt auto -L xil_defaultlib -L xilinx_vip -L unisims_ver -L unimacro_ver -L secureip -L xpm --snapshot tb_uvm_test xil_defaultlib.tb_uvm_test xil_defaultlib.glbl -log tb_uvm_test_elaborate.log
Multi-threading is on. Using 2 slave threads.
Starting static elaboration
Pass Through NonSizing Optimizer
/opt/Xilinx/Vivado/2019.2/bin/loader: line 280:  1102 Segmentation fault      (core dumped) "$RDI_PROG" "$@"
ninja: build stopped: subcommand failed.

回避策

このままだとconnect_phaseでインターフェースの接続ができないので、検討中。 独自クラスのインスタンスは渡せてるっぽいのでこれを使えばインターフェースの受け渡しも可能か? 素直にバージョンアップ待つのが賢明な気もするけど。

interfaceをmodule内で定義しているのがどうもだめだった模様。 モジュールの外側で定義したら問題なく動いた。 この例が動いたので差分チェックして見つけた。

参考ページ

https://sites.google.com/site/playsystemverilog/uvm/uvm-introduction-for-10days https://www.accellera.org/images/downloads/standards/uvm/uvm_users_guide_1.2.pdf https://forums.xilinx.com/t5/Simulation-and-Verification/XELAB-2019-2-elaboration-fails-for-simple-UVM-example-design/m-p/1113039

2020年7月12日日曜日

VIvado_HLSとVivadoのBlockDesignをCMakeでビルドしてみた

Vivado_HLSとVivadoのBlockDesignをCMAKEでパッケージしてみた話です。 使っているヘルパースクリプトはgithubのリポジトリにて公開しています。 使用方法もgithubのリポジトリで公開しています。 また、CMakeLists.txtの例をヘルパースクリプトのリポジトリのexampleフォルダーに保存しています。

環境

Vivado 2019.2
Vivado_HLS 2019.2
CMake 3.10.2

事前準備

VIVADO_CMAKE_HELPER環境変数にリポジトリパスを登録します。 次のスクリプトを動かしてください。

source <path-to-repository>/setup.sh

使い方

vivado_hls

ディレクトリ構造

サンプルは以下に示すディレクトリ構造を想定しています。

project_top
├── CMakeLists.txt:リポジトリ同梱のCMakeLists.txt.hls_example
├── directives.tcl
├── include:ヘッダ置き場
├── src:ソース置き場
└── test:テストベンチ置き場
    ├── include:テストベンチ用ヘッダ置き場
    └── src:テストベンチ用ソース置き場

CMakeLists.txtの編集方法

ヘッダの保存パスをCFLAGS及びCFLAGS_TESTBENCHにリストとして追加してください。
ソースをSRC_FILESやTESTBENCH_FILESにリストとして追加してください。
リストは区切りの";"を":"に置き換えてください。(そうしないと誤動作する)
その後vivado_hls_export.cmakeをインポートしてください。
これはビルドに必要なcustom_commandとcustom_targetを追加します.
加えて、インストール設定も追加します。archive zipファイルを除き生成結果のipフォルダーをCMAKE_INSTALL_PREFIX/${project_name}にコピーします。

インストール

インストールは以下コマンドで実行できます。<>でくくった部分は環境に合わせて設定してください。

source <path_to_vivado>/setup.sh
source <path_to_this_repository>/setup.sh
mkdir build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX=<path_to_user_ip_repository>
cmake --build .
make install

vivado ip packager(ipx)

ディレクトリ構造

サンプルは以下に示すディレクトリ構造を想定しています。

project_top
├── CMakeLists.txt:リポジトリ同梱のCMakeLists.txt.ipx_example
├── scripts:blockdesign.tclが保存されることを期待
├── src:rtlモジュール置き場
└── test:テストベンチ置き場
    └── src:テストベンチ用ソース置き場

CMakeLists.txtの編集方法

blockdesign.tclはvivadoのwrite_bd_tclコマンドを使用して作成してください。
design_nameとCMakeLists.txtの編集方法project_nameが同じになるようにしてください。
(または生成されたblockdesign.tclを修正してdesign_nameを変更してください)
必要に応じてrtl moduleとtestbenchをそれぞれSRC_FILES、TESTBENCH_FILESに追加してください。
リストは区切りの";"を":"に置き換えてください。(vivado_hls同様)
その後vivado_ipx_export.cmakeをincludeしてください。
これはビルドに必要なcustom_commandとcustom_targetを追加します。
また、インストール設定を行います。archive zipファイルを除き生成結果のipフォルダーをCMAKE_INSTALL_PREFIX/${project_name}にコピーします。

インストール

インストールは以下コマンドで実行できます。<>でくくった部分は環境に合わせて設定してください。

source <path_to_vivado>/setup.sh
source <path_to_this_repository>/setup.sh
mkdir build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX=<path_to_user_ip_repository>
cmake --build .
make install

プロジェクトのネスト

プロジェクトがネストしていても動作します。ICS_IFに例があります。
add_subdirectory(modules)で追加し、各々ビルドできるようにCMakeLists.txtを作成してください。