ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

3. UVM -- factory机制与平台组件构建

2022-07-17 17:40:27  阅读:247  来源: 互联网

标签:name -- my0 factory uvm type phase my UVM


3. UVM -- factory机制与平台组件构建

3.1. 什么是factory机制

  • UVM工厂机制可以使用户在不更改代码的情况下实现不同对象的替换;
  • 工厂是UVM的一种数据结构。它的作用范围是整个平台空间,它有且仅有一个实例化对象 (即单实例类)。它是一个 多态构造器,可仅仅使用一个函数让用户实例化很多不同类型的对象。
  • 为了使用一个函数而可以返回多种对象,这些对象必须从一个基类扩展而来。

3.2. uvm factory机制的原理及使用

  

3.2.1 factory机制的运作步骤

(1). factory注册:一般使用宏

注册
`uvm object utils() 对 uvm object类 进行注册
`uvm_component_utils() 对 uvm_component类 进行注册
`uvm object param utils() 对 object参数化类 进行注册
`uvm component param utils() 对 component参数化类 进行注册

宏的作用如下:

  • 为注册的类创建一个代理类:type_id

    • 这个类在注册类的内部,起到间接实例化对象的代理作用
    • 创建一个注册类的对象并将该对象向factory注册
    • type_id内建create函数,该函数的任务是根据替换表创建指定类的对象
  • 创建一个静态函数get_type()

  • 创建一个函数get_object_type(),非静态

(2). 实例化对象:要使用 静态方法 class_name:type_id:create() 来代替new实例化对象;

create()会按以下步骤执行:

  • 调用factory的get函数获取factory对象;
  • 以当前所要创建对象的类名为索引,在factory的替换列表中查询该类 该对象是否被替换;
  • 如果替换列表中没有相关条目,则调用当前类的new(0函数;如果有相关条目,则调用替换类的new()函数实例化对象。

(3). 根据具体要求向替换表添加替换条目,override;

(4). 在运行仿真时,UVM会根据这两张表自动的实现factory机制;

3.2.2. 使用factory机制需要注意的几点:

  1. 用户需要向注册表注册。
  2. 用户需要向替换表添加项目。
  3. 被替换对象的类型是替换对象类型的基类。

factory机制与override机制

  常用的override函数有两个:

set_type_override_by_type()

set_type_override_by_type(original_class_name::get_type(),target_class_name::get_type());

  

  这个函数的作用是将平台中 所有类型 为“original_.class_name”实例化的对象都被替换成类型为“target_class_name”的对象 -- 全部替换

set_inst_override_by_type()

set_inst_override_by_type("original_inst_path", original_class_name::get_type(), target_class_name:get_type());

  

  这个函数的作用是将平台中 指定路径 的类型为“original_class_name”实例化的对象被替换成类型为“target_class_name”的对象 -- 指定替换,路径越具体,替换越明确

  这两个函数存在于component中,并且一般需要在 build_phase() 中调用。

一个简单平台 -- 添加平台组件

  • 平台架构调试,可使用: uvm_top.print_topology;

  • Makefile

    #! all comp sim run clean
    .PHONY: all comp sim run clean
    
    TC       ?=my_base_test
    SEED     ?=1234
    TOP      ?=test_top
    FILELIST ?=../scripts/filelist.f
    
    COMP_OPTS += -sverilog +v2k -full64
    COMP_OPTS += -kdb -lca
    COMP_OPTS += +acc +vpi -debug_access+all
    COMP_OPTS += -timescale=1ns/1ps
    COMP_OPTS += -ntb_opts uvm-1.2
    COMP_OPTS += +libext+.v+.sv+.svh+.incl
    COMP_OPTS += +plusarg_save
    COMP_OPTS += -top $(TOP)
    COMP_OPTS += -F $(FILELIST)
    
    SIM_OPTS += +UVM_TESTNAME=$(TC)
    SIM_OPTS += +UVM_VERBOSITY=UVM_DEBUG##UVM_LOW
    SIM_OPTS += +UVM_DUMP_CMDLINE_ARGS
    SIM_OPTS += +UVM_CONFIG_DB_TRACE
    SIM_OPTS += +UVM_PHASE_TRACE
    SIM_OPTS += +UVM_OBJECTION_TRACE
    SIM_OPTS += +ntb_random_seed=$(SEED)
    SIM_OPTS += +notimingcheck
    SIM_OPTS += +nospecify
    SIM_OPTS += +delay_mode_zero
    
    COV_OPTS += -cm cond+line+fsm
    COV_OPTS += -cm_name $(TC) -cm_dir $(TC).vdb
    
    DUMP_OPTS += +fsdb+autoflush+all=on
    DUMP_OPTS += -ucli -i ../scripts/wave.tcl
    DUMP_OPTS += +fsdbfile+./wave/$(TC)_$(SEED).fsdb
    
    all: comp sim
    
    comp:
    	mkdir -p ./wave ./log & \
    	vcs $(COMP_OPTS) \
    	-l ./log/comp_$(TC)_$(SEED).log
    
    sim:
    	./simv $(SIM_OPTS) \
    	$(DUMP_OPTS) \
    	-l ./log/sim_$(TC)_$(SEED).log
    
    rpt_cg:
    	urg -dir *.vdb -report cg_report
    	@echo "coverage report generated in ./cg_report"
    
    verdi_cg:
    	verdi -cov -covdir *.vdb/ &
    
    verdi_db:
    	verdi -dbdir simv.daidir &
    
    verdi_f:
    	verdi -f filelist.f &
    
    verdi_wave:
    	verdi -ssf ./wave/*.fsdb &
    
    run:
    	vcs -R -sverilog $(TC)
    
    clean:
    	rm -rf *.log *.vdb *simv* *.h *.key cg_report csrc vdCovLog
    
    clean_all:
    	rm -rf *.log *.vdb *simv* *.h *.key cg_report csrc vdCovLog novas* ./log/* ./wave/* verdiLog
    
    
    
  • test_top

    //-----------------------------------------------
    //@ test_top
    //@ Version : V0.1
    //@ Wesley 2022.04.10
    //-----------------------------------------------
    
    module test_top;
        import uvm_pkg::*;
        `include "uvm_macros.svh"
    
        import my_test_pkg::*;
    
        logic clk     = 0;
        logic reset_n = 0;
    
        //interface
        my_intf vif();
    
        // DUT - a 16550 UART:
        dut DUT ( );
    
        // clock/reset
        always #5ns clk = ~clk;
    
        initial begin
            clk     = 0;
            reset_n = 0;
            repeat(10) @(posedge clk);
            reset_n = 1;
    	    `uvm_info (" TEST_TOP ", $sformatf("clk = 0x%h , resetn = 0x%h", clk, reset_n), UVM_MEDIUM)
        end
    
        // UVM virtual interface handling and run_test()
        initial begin
            // run
            run_test();
        end
    endmodule: test_top
    
    
  • my_base_test

    //-----------------------------------------------
    //@ my_base_test
    //@ Version : V0.1
    //@ Wesley 2022.04.10
    //-----------------------------------------------
    `ifndef my_base_test__SV
    `define my_base_test__SV
    
    class my_base_test extends uvm_test;
    
        `uvm_component_utils(my_base_test)
        my_env             m_env;
    
        extern function new(string name = "my_base_test", uvm_component parent = null);
        extern function void build_phase(uvm_phase phase);
        extern function void connect_phase(uvm_phase phase);
        extern function void end_of_elaboration_phase(uvm_phase phase);
        extern virtual task  run_phase(uvm_phase phase);
        extern function void report_phase(uvm_phase phase);
        extern function void final_phase(uvm_phase phase);
    endclass: my_base_test
    
    function my_base_test::new(string name = "my_base_test", uvm_component parent = null);
        super.new(name, parent);
        `uvm_info(get_type_name(), "< 000 > : new ", UVM_DEBUG)
    endfunction: new
    
    function void my_base_test::build_phase(uvm_phase phase);
        super.build_phase(phase);
        `uvm_info(get_type_name(), "< 001 > : build_phase ", UVM_DEBUG)
        m_env = my_env::type_id::create("m_env", this);
    endfunction: build_phase
    
    function void my_base_test::connect_phase(uvm_phase phase);
       super.connect_phase(phase);
    endfunction: connect_phase
    
    function void my_base_test::end_of_elaboration_phase(uvm_phase phase);
        uvm_top.print_topology;
        `uvm_info(get_type_name(), "< 003 > : end_of_elaboration_phase ", UVM_DEBUG)
    endfunction: end_of_elaboration_phase
    
    task my_base_test::run_phase(uvm_phase phase);
        super.run_phase(phase);
        phase.raise_objection(this);
        `uvm_info(get_type_name(), "< 005 > : run_phase ", UVM_DEBUG)
    
        #100ns;
        phase.get_objection().set_drain_time(this, 1000);
        phase.drop_objection(this);
    endtask: run_phase
    
    function void my_base_test::report_phase(uvm_phase phase);
        `uvm_info(get_type_name(), "< 008 > : report_phase ", UVM_DEBUG)
        `uvm_info(get_type_name(), "+-----------------------------------------------+", UVM_DEBUG)
        `uvm_info(get_type_name(), "+-           *** UVM TEST PASSED ***           -+", UVM_DEBUG)
        `uvm_info(get_type_name(), "+-----------------------------------------------+", UVM_DEBUG)
    
        `uvm_info(get_type_name(), "+-----------------------------------------------+", UVM_DEBUG)
        `uvm_info(get_type_name(), "+-           *** UVM TEST FAILED ***           -+", UVM_DEBUG)
        `uvm_info(get_type_name(), "+-----------------------------------------------+", UVM_DEBUG)
    
    endfunction: report_phase
    
    function void my_base_test::final_phase(uvm_phase phase);
        `uvm_info(get_type_name(), "< 009 > : final_phase ", UVM_DEBUG)
    endfunction: final_phase
    
    `endif // my_base_test__SV
    
    
  • env

    //-----------------------------------------------
    //@ my_env
    //@ Version : V0.1
    //@ Wesley 2022.04.10
    //-----------------------------------------------
    `ifndef my_env__SV
    `define my_env__SV
    
    class my_env extends uvm_env;
    
        `uvm_component_utils(my_env)
    
        my0_agent          m0_agent;
        my_scoreboard      m_scb;
        my_reference       m_ref;
    
        extern function new(string name = "my_env", uvm_component parent = null);
        extern function void build_phase(uvm_phase phase);
        extern function void connect_phase(uvm_phase phase);
    endclass: my_env
    
    function my_env::new(string name = "my_env", uvm_component parent = null);
        super.new(name, parent);
        `uvm_info(get_type_name(), "< 000 > : new ", UVM_DEBUG)
    endfunction: new
    
    function void my_env::build_phase(uvm_phase phase);
        super.build_phase(phase);
        `uvm_info(get_type_name(), "< 001 > : build_phase ", UVM_DEBUG)
    
        m0_agent = my0_agent::type_id::create("m0_agent", this);
        m_scb    = my_scoreboard::type_id::create("m_scb", this);
        m_ref    = my_reference::type_id::create("m_ref", this);
    
    endfunction: build_phase
    
    function void my_env::connect_phase(uvm_phase phase);
        `uvm_info(get_type_name(), "< 002 > : connect_phase ", UVM_DEBUG)
    endfunction: connect_phase
    
    `endif // my_env__SV
    
    
  • agent

    //-----------------------------------------------
    //@ my0_agent
    //@ Version : V0.1
    //@ Wesley 2022.04.10
    //-----------------------------------------------
    `ifndef my0_agent__SV
    `define my0_agent__SV
    
    class my0_agent extends uvm_agent;
    
        `uvm_component_utils(my0_agent)
    
        my0_driver        m0_drv;
        my0_monitor       m0_mon;
        my0_sequencer     m0_seqr;
    
        extern function new(string name = "my0_agent", uvm_component parent = null);
        extern function void build_phase(uvm_phase phase);
        extern function void connect_phase(uvm_phase phase);
    endclass: my0_agent
    
    function my0_agent::new(string name = "my0_agent", uvm_component parent = null);
        super.new(name, parent);
        `uvm_info(get_type_name(), "< 000 > : new ", UVM_DEBUG)
    endfunction: new
    
    function void my0_agent::build_phase(uvm_phase phase);
        super.build_phase(phase);
        `uvm_info(get_type_name(), "< 001 > : build_phase ", UVM_DEBUG)
    
        m0_drv  = my0_driver::type_id::create("m0_drv", this);
        m0_seqr = my0_sequencer::type_id::create("m0_seqr", this);
        m0_mon  = my0_monitor::type_id::create("m0_mon", this);
    endfunction: build_phase
    
    function void my0_agent::connect_phase(uvm_phase phase);
        `uvm_info(get_type_name(), "< 002 > : connect_phase ", UVM_DEBUG)
    endfunction: connect_phase
    
    `endif // my0_agent__SV
    
    
  • driver

    //-----------------------------------------------
    //@ my0_driver
    //@ Version : V0.1
    //@ Wesley 2022.04.10
    //-----------------------------------------------
    `ifndef my0_driver__SV
    `define my0_driver__SV
    
    class my0_driver extends uvm_driver#(my0_seq_item);
        `uvm_component_utils(my0_driver)
    
        extern function new(string name = "my0_driver", uvm_component parent = null);
        extern function void build_phase(uvm_phase phase);
        extern function void connect_phase(uvm_phase phase);
        extern task          run_phase(uvm_phase phase);
    
    endclass: my0_driver
    
    function my0_driver::new(string name = "my0_driver", uvm_component parent = null);
        super.new(name, parent);
        `uvm_info(get_type_name(), "< 000 > : new ", UVM_DEBUG)
    endfunction: new
    
    function void my0_driver::build_phase(uvm_phase phase);
        `uvm_info(get_type_name(), "< 001 > : build_phase ", UVM_DEBUG)
    endfunction: build_phase
    
    function void my0_driver::connect_phase(uvm_phase phase);
        `uvm_info(get_type_name(), "< 002 > : connect_phase ", UVM_DEBUG)
    endfunction: connect_phase
    
    task my0_driver::run_phase(uvm_phase phase);
        `uvm_info(get_type_name(), "< 005 > : run_phase ", UVM_DEBUG)
        super.run_phase(phase);
    endtask: run_phase
    
    `endif // my0_driver__SV
    
    
  • monitor

    //-----------------------------------------------
    //@ my0_monitor
    //@ Version : V0.1
    //@ Wesley 2022.04.10
    //-----------------------------------------------
    `ifndef my0_monitor__SV
    `define my0_monitor__SV
    
    class my0_monitor extends uvm_monitor;
    
        `uvm_component_utils(my0_monitor)
    
        extern function new(string name = "my0_monitor", uvm_component parent = null);
        extern function void build_phase(uvm_phase phase);
        extern function void connect_phase(uvm_phase phase);
        extern task          run_phase(uvm_phase phase);
    endclass: my0_monitor
    
    function my0_monitor::new(string name = "my0_monitor", uvm_component parent = null);
        super.new(name, parent);
        `uvm_info(get_type_name(), "< 000 > : new ", UVM_DEBUG)
    endfunction: new
    
    function void my0_monitor::build_phase(uvm_phase phase);
        `uvm_info(get_type_name(), "< 001 > : build_phase ", UVM_DEBUG)
    endfunction: build_phase
    
    function void my0_monitor::connect_phase(uvm_phase phase);
        `uvm_info(get_type_name(), "< 002 > : connect_phase ", UVM_DEBUG)
    endfunction: connect_phase
    
    task my0_monitor::run_phase(uvm_phase phase);
        `uvm_info(get_type_name(), "< 005 > : run_phase ", UVM_DEBUG)
    endtask: run_phase
    
    `endif // my0_monitor__SV
    
    
  • sequencer

    //-----------------------------------------------
    //@ my0_sequencer
    //@ Version : V0.1
    //@ Wesley 2022.04.10
    //-----------------------------------------------
    `ifndef my0_sequencer__SV
    `define my0_sequencer__SV
    
    class my0_sequencer extends uvm_sequencer #(my0_seq_item);
    
        `uvm_component_utils(my0_sequencer)
    
        function new(string name = "my0_sequencer", uvm_component parent = null);
            super.new(name, parent);
            `uvm_info(get_type_name(), "< 000 > : new ", UVM_DEBUG)
        endfunction: new
    
    endclass: my0_sequencer
    
    `endif // my0_sequencer__SV
    
    
    
  • reference

    //-----------------------------------------------
    //@ my_reference
    //@ Version : V0.1
    //@ Wesley 2022.04.10
    //-----------------------------------------------
    `ifndef my_reference__SV
    `define my_reference__SV
    
    // Step1 : Create a new class that extends from uvm_scoreboard
    class my_reference extends uvm_component;
    	`uvm_component_utils (my_reference)
    
    	// Step2a: Declare and create a TLM Analysis Port to receive data objects from other TB components
        uvm_blocking_get_port #(my0_seq_item) get_port;//exp_port;
        uvm_analysis_port #(my0_seq_item) ap;
        //uvm_analysis_export #(my0_seq_item) analysis_export;
    
    	function new (string name = "my_reference", uvm_component parent);
    		super.new (name, parent);
    	endfunction
    
    	// Step2b: Instantiate the analysis port, because afterall, its a class object
    	function void build_phase (uvm_phase phase);
    		//ap = new ("ap", this);
    		//get_port = new ("get_port", this);
    		//analysis_export = new ("analysis_export", this);
    	endfunction
    
    	// Step3: Define other functions and tasks that operate on the data and call them
    	// Remember, this is the main task that consumes simulation time in UVM
    	virtual task run_phase (uvm_phase phase);
            my0_seq_item tr;
    	endtask
    
    	// Step4: [Optional] Perform any remaining comparisons or checks before end of simulation
    	virtual function void check_phase (uvm_phase phase);
    		//...
    	endfunction
    endclass
    
    `endif // my_reference__SV
    
    
  • scoreboard

    //-----------------------------------------------
    //@ my_scoreboard
    //@ Version : V0.1
    //@ Wesley 2022.04.10
    //-----------------------------------------------
    `ifndef my_scoreboard__SV
    `define my_scoreboard__SV
    
    class my_scoreboard extends uvm_scoreboard;
    	`uvm_component_utils (my_scoreboard)
    
    	// Step2a: Declare and create a TLM Analysis Port to receive data objects from other TB components
        uvm_blocking_get_port #(my0_seq_item) get_port;
        //uvm_analysis_imp_monitor #(my0_seq_item, my_scoreboard) analysis_imp;
    
    	function new (string name = "my_scoreboard", uvm_component parent);
    		super.new (name, parent);
    	endfunction
    
    	// Step2b: Instantiate the analysis port, because afterall, its a class object
    	function void build_phase (uvm_phase phase);
    		//get_port = new ("get_port", this);
    		//analysis_imp = new ("analysis_imp", this);
    	endfunction
    
    	// Step3: Define other functions and tasks that operate on the data and call them
    	// Remember, this is the main task that consumes simulation time in UVM
    	virtual task run_phase (uvm_phase phase);
            my0_seq_item tr;
    	endtask
    
    	// Step4: [Optional] Perform any remaining comparisons or checks before end of simulation
    	virtual function void check_phase (uvm_phase phase);
    		//...
    	endfunction
    endclass
    
    `endif // my_scoreboard__SV
    
    

标签:name,--,my0,factory,uvm,type,phase,my,UVM
来源: https://www.cnblogs.com/thisway2014/p/16487814.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有