3. UVM -- factory机制与平台组件构建
作者:互联网
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机制需要注意的几点:
- 用户需要向注册表注册。
- 用户需要向替换表添加项目。
- 被替换对象的类型是替换对象类型的基类。
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