【IC验证】UVM实验lab01

1. 工厂的注册、创建和覆盖

1.1 注册

object组件使用宏'uvm_obeject_ultis(string name)来创建,component组件使用'uvm_object_ultis(string name, parent)来创建

	class trans extends uvm_object;/*定义*/
		bit[31:0] data;
		'uvm_object_ultis(trans)/*注册*/
		function new(string name = "trans");/*构建*/
			super.new(name);
			'uvm_info("CREATE", $sformatf("trans type [%s] created", name),UVM_LOW)
			/*使用宏来进行消息管理。'uvm_info(ID, message,verbosity)*/
		endfunction
	endclass

1.2 创建

	class object_create extends top;
		trans t1, t2, t3, t4;
		'uvm_component_ultis(object_create)
		function new(string name = "object_create", uvm_component parent = null);
			super.new(name, parent);
		endfunction
		
		function void build_phase (uvm_phase phase);
			uvm_factory f = uvm_factory::get();/*创建uvm_factory实例*/
			super.build_phase(phase);
			/*对象的创建*/
			/*方法1,使用new函数来做*/
			t1 = new("t1");
			/*方法2,使用create*/
			/*string name = comp_type::type_id::create("string name", uvm_component parent = null)*/
			t2 = trans::type_id::create("t2", this);//trans是uvm_object类型的,为什么用component的来创建?
			/*方法3,使用uvm_factory的函数来做*/
			/*get_full_name()用于返回当前对象的完整层次名称 
			create_object_by_name (string requested_type_name,string parent_inst_path = "",string name = "")*/
			void'($cast(t3, f.create_object_by_type(trans::get_type(), get_full_name(), "t3")));
			/*方法4,使用create_object方法*/
			void'($cast(t4, create_object("trans", "t4")));//为什么要使用cast来实现类型转换
			/*因为 create_object_by_type 返回的是通用类型 uvm_object,为了使用对象的特定方法和属性,
			需要将其转换为具体的类型。这是通过 $cast 语句完成的*/
		endfunction		
	endclass

1.3 覆盖

	class object_override extends object_create;
		'uvm_component_ultis(object_override)
		function new(string name = "object_override", uvm_component parent = null);
			super.new(name, parent);
		endfunction	

		function void build_phase(uvm_pahse phase);
			set_type_override_by_type(trans, bad_trans, bit replace = 1);
			trans::type_id::set_type_override(bad_trans::get_type());//这种创建方法是不是也可以
			super.build_phase(phase);
		endfunction
	endclass

1.4 问题

为何对t1,t2,t3,t4报告名称不对

仿真器的原因,VCS可以。Questa Sim对于component组件可以传递进去name,但是object不行

2. 域的自动化与uvm_object常用方法

2.1 域的自动化

		'uvm_object_utils_begin(trans)
			'uvm_field_int(addr, UVM_ALL_ON)
			'uvm_field_int(data, UVM_DEFAULT)
			'uvm_field_enum(op_t, op, UVM_ALL_ON)
			/*`uvm_field_enum(T, ARG,FLAG=UVM_DEFAULT),
			T is an enumerated type, ARG is an instance of that type*/
			'uvm_field_string(name, UVM_DEFAULT)
		'uvm_objectr_utils_end

2.2 compare()

do_compare是compare的回调函数,在调用compare时,会默认执行do_compare

		function bit do_compare(uvm_object rhs, uvm_comparer comparer);//第二个参数也可以不要
			trans t;
			do_compare = 1;
			'void($cast(t,rhs));
			if(addr != t.addr)begin
				do_compare = 0;
				'uvm_warnning("CREATE", $sformatf(addr %8x != %8x, addr, t.addr))
			end
			if(data != t.data)begin
				do_compare = 0;
				'uvm_warnning("CREATE", $sformatf(addr %8x != %8x, data, t.data))
			end	
			if(op != t.op)begin
				do_compare = 0;
				'uvm_warnning("CREATE", $sformatf(addr %8x != %8x, op, t.op))
			end				
			if(name != t.name)begin
				do_compare = 0;
				'uvm_warnning("CREATE", $sformatf(addr %8x != %8x, name, t.name))
			end					
		endfunction
			is_equal = t1.compare(t2);
			uvm_default_compare.show_max = 10;
			/*uvm_default_compare 是一个默认的比较对象,用于控制比较时的显示行为。
			show_max 是它的一个属性,表示在比较时最多显示多少个不匹配项*/
			if(!is_equal)
				'uvm_warning("COMPARE", "t1 is not equal to t2")
			else
				'uvm_info("COMPARE", "t1 is equal to t2")

2.3 print() 与copy()

			'uvm_info("COPY", "Before uvm_object copy() taken", UVM_LOW)
			t1.print();
			uvm_default_printer = uvm_default_line_printer;/*修改打印的默认格式*/
			t2.print(();
			'uvm_info("COPY", "After uvm_object copy() taken", UVM_LOW)
			t1.copy(t2);/*将t2拷贝给t1*/
			uvm_default_printer = uvm_default_tree_printer;			
			t1.print();
			uvm_default_printer = uvm_default_line_printer;/*修改打印的默认格式*/
			t2.print(();	

3. phase机制

9个phase之间顺序执行,只有run_phase耗时因此采用task。run_phase必须有挂起和落下机制,否则该phase不被执行。run_phase与之对应的有12个并列的子Phase,12个子phase是顺序执行,但是和run_phase是并行执行。一般不建议在有run_phase的情况下采用其子phase   

  3.1 代码

	class comp2 extends uvm_component
		'uvm_component ultis(comp2)
		function new(string name = "comp2", uvm_component parent = null);
			super.new(name, parent);
			'uvm_info("CREATE", $sformatf("unit type [%s] create", name), UVM_LOW)
		endfunction
		
		function void build_phase(uvm_phase phase);
			super.build_phase(phase);
			'uvm_info("BUILD", "comp2 build_phase completed", UVM_LOW)
		endfunction
		
		function void connect_phase(uvm_phase phase);
			super.connect_phase(phase);
			'uvm_info("CONNECT", "comp2 connect_phase completed", UVM_LOW)
		endfunction

		task run_phase(uvm_phase phase);
			super.run_phase(phase);
			'uvm_info("RUN", "comp2 run_phase completed", UVM_LOW)
		endtask				

		function void report_phase(uvm_phase phase);
			super.report_phase(phase);
			'uvm_info("REPORT", "comp2 report_phase completed", UVM_LOW)
		endfunction		
	endclass
	
	class comp3 extends uvm_component
		'uvm_component ultis(comp3)
		function new(string name = "comp3", uvm_component parent = null);
			super.new(name, parent);
			'uvm_info("CREATE", $sformatf("unit type [%s] create", name), UVM_LOW)
		endfunction	
		
		function void build_phase(uvm_phase phase);
			super.build_phase(phase);
			'uvm_info("BUILD", "comp1 build_phase completed", UVM_LOW)
		endfunction
		
		function void connect_phase(uvm_phase phase);
			super.connect_phase(phase);
			'uvm_info("CONNECT", "comp1 connect_phase completed", UVM_LOW)
		endfunction

		task run_phase(uvm_phase phase);
			super.run_phase(phase);
			'uvm_info("RUN", "comp1 run_phase completed", UVM_LOW)
		endtask				

		function void report_phase(uvm_phase phase);
			super.report_phase(phase);
			'uvm_info("REPORT", "comp1 report_phase completed", UVM_LOW)
		endfunction		
	endclass	
	
	class comp1 extends uvm_component
		comp2 c2;
		comp3 c3;
		'uvm_component ultis(comp1)
		function new(string name = "comp1", uvm_component parent = null);
			super.new(name, parent);
			'uvm_info("CREATE", $sformatf("unit type [%s] create", name), UVM_LOW)
		endfunction	
		
		function void build_phase(uvm_phase phase);
			super.build_phase(phase);
			'uvm_info("BUILD", "comp1 build phase begin", UVM_LOW)
				c2 = comp2::type_id::create("c2", this);
				c3 = comp3::type_id::create("c3", this);				
			'uvm_info("BUILD", "comp1 build phase end", UVM_LOW)
		endfunction
		
		function void connect_phase(uvm_phase phase);
			super.connect_phase(phase);
			'uvm_info("CONNECT", "comp1 connect_phase completed", UVM_LOW)
		endfunction

		task run_phase(uvm_phase phase);
			super.run_phase(phase);
			'uvm_info("RUN", "comp1 run_phase completed", UVM_LOW)
		endtask				

		function void report_phase(uvm_phase phase);
			super.report_phase(phase);
			'uvm_info("REPORT", "comp1 report_phase completed", UVM_LOW)
		endfunction		
	endclass	
	
	class phase_order_test extends uvm_test
		comp1 c1;
		function new(string name = "phase_order_test", uvm_component parent = null);
			super.new(name, parent);
		endfunction
		
		function void build_phase(uvm_phase phase);
			super.build_phase(phase);
			'uvm_info("BUILD", "phase_order_test build phase begin", UVM_LOW)
				c1 = comp2::type_id::create("c2", this);				
			'uvm_info("BUILD", "phase_order_test build phase end", UVM_LOW)
		endfunction
		
		function void connect_phase(uvm_phase phase);
			super.connect_phase(phase);
			'uvm_info("CONNECT", "phase_order_test connect_phase completed", UVM_LOW)
		endfunction

		task run_phase(uvm_phase phase);
			super.run_phase(phase);
			'uvm_info("BUILD", "phase_order_test task begin", UVM_LOW)
				phase.raise_objection(this);
					#1us;
				phase.drop_objection(this);
			'uvm_info("BUILD", "phase_order_test task end", UVM_LOW)
		endtask	

		task reset_phase(uvm_phase phase);
			'uvm_info("RESET", "reset_phase  begin", UVM_LOW)
				phase.raise_objection(this);
					#1us;
				phase.drop_objection(this);
			'uvm_info("RESET", "reset_phase  end", UVM_LOW)
		endtask				

		task main_phase(uvm_phase phase);
			'uvm_info("MAIN", "main_phase  begin", UVM_LOW)
				phase.main_objection(this);
					#1us;
				phase.main_objection(this);
			'uvm_info("MAIN", "main_phase  end", UVM_LOW)
		endtask	
	endclass

   3.2 仿真结果

从仿真结果可以看出来,run_phase和main_phase, reset_phase都是在1us的时候仿真结束。

3.3 问题

为什么是在c1关于run_phase所有的信息被打印完了以后才去打印c2和c3的run_phase相关信息呢?

因为一旦进入c1的run_phase,就必须得要等到执行完毕退出以后才能去执行其他的,而c1的run_phase是有时延的。在每个 run_phase 和子phase方法中,如果包含了延迟或等待语句(如 #1us),那么仿真时间会在该方法中停留,直到延迟结束后才会继续执行下一个组件的 run_phase。但是各个组件的其他phase可以并行执行

4. config机制

4.1 代码

package uvm_config_pkg;
	import uvm_pkg::*;
	'include "uvm_macros.svh"
	
	class config_obj extends uvm_object;
		int comp1_var;
		int comp2_var;
		'uvm_object_utils(config_obj)
		function new(string name = "config_obj");
			super.new(name);
			'uvm_info("CREATE", $sformatf("config_obj type [%s] has been created", name), UVM_LOW)
		endfunction
	endclass
	
	class comp2 extends uvm_component;
		int var2;
		virtual uvm_config_if vif;
		config_obj cfg;
		'uvm_object_utils(comp2)
		function new(string name = "comp2", uvm_component parent = null);
			super.new(name, parent);
			var2 = 200;
			'uvm_info("CREATE", $sformatf("unit type [%s] has been created", name), UVM_LOW)
		endfunction	
	
		function void build_phase(uvm_phase phase);
			super.build_phase(phase);
			'uvm_info("BUILD", "comp2 build phase entered", UVM_LOW)
			if(!uvm_config_db#(virtual uvm_config_if)::get(this, "", "vif", vif))
				'uvm_error("GET VIF", "no virtual interface is assigned")
		
			'uvm_info("GET INT", $sformatf("before config get, var2 = %0d", var2), UVM_LOW)
			uvm_config_db#(int)::get(this, "", "var2", var2);
			'uvm_info("GET INT", $sformatf("after config get, var2 = %0d", var2), UVM_LOW)	

			uvm_config_db#(config_obj)::get(this, "", "cfg", cfg);
			'uvm_info("GET OBJ", $sformatf("after config get, cfg.comp2_var = %0d", cfg.comp2_var), UVM_LOW)				
		
			'uvm_info("BUILD", "comp2 build phase exited", UVM_LOW)
		endfunction
	endclass
	
	class config_obj extends uvm_object;
		int comp1_var;
		int comp2_var;
		'uvm_object_utils(config_obj)
		function new(string name = "config_obj");
			super.new(name);
			'uvm_info("CREATE", $sformatf("config_obj type [%s] has been created", name), UVM_LOW)
		endfunction
	endclass
	
	class comp1 extends uvm_component;
		int var1;
		virtual uvm_config_if vif;
		config_obj cfg;
		comp2 c2;
		'uvm_object_utils(comp1)
		function new(string name = "comp2", uvm_component parent = null);
			super.new(name, parent);
			var1 = 100;
			'uvm_info("CREATE", $sformatf("unit type [%s] has been created", name), UVM_LOW)
		endfunction	
	
		function void build_phase(uvm_phase phase);
			super.build_phase(phase);
			'uvm_info("BUILD", "comp1 build phase entered", UVM_LOW)
			if(!uvm_config_db#(virtual uvm_config_if)::get(this, "", "vif", vif))/*得到接口信号*/
				'uvm_error("GET VIF", "no virtual interface is assigned")
		
			'uvm_info("GET INT", $sformatf("before config get, var1 = %0d", var1), UVM_LOW)
			uvm_config_db#(int)::get(this, "", "var1", var1);
			'uvm_info("GET INT", $sformatf("after config get, var1 = %0d", var1), UVM_LOW)	

			uvm_config_db#(config_obj)::get(this, "", "cfg", cfg);
			'uvm_info("GET OBJ", $sformatf("after config get, cfg.comp1_var = %0d", cfg.comp1_var), UVM_LOW)				
		
			'uvm_info("BUILD", "comp1 build phase exited", UVM_LOW)
		endfunction
	endclass	
	
	class uvm_config_test extends uvm_test;
		comp1 c1;
		config_obj cfg;
		'uvm_component_utils(uvm_config_test)
		function new(string name = "uvm_config_test", uvm_component parent = null);
			super.new(name, parent);
		endfunction
		
		function void build_phase(uvm_phase phase)
			super.build_phase(phase);
			'uvm_info("BUILD", "uvm_config_test build_phase entered", UVM_LOW)
			
			cfg = config_obj::type_id::create("cfg");
			cfg.comp1_var = 100;
			cfg_comp2_var = 200;
			uvm_config_db#(config_obj)::set(this, "*", "cfg", cfg);
			
			uvm_config_db#(int)::set(this, "c1", "var1", 10);
			uvm_config_db#(int)::set(this, "c1.c2", "var2", 20);		

			c1 = comp1::type_id::create("c1", this);
			'uvm_info("BUILD", "uvm_config_test build_phase exited", UVM_LOW)
		endfunction
		
		task run_phase(uvm_phase phase)
			super.run_phase(phase)
			'uvm_info("RUN", "uvm_config_test run_phase entered", UVM_LOW)
				phase.raise_objection(this);
					#1us;
				phase.drop_objection(this);
			'uvm_info("RUN", "uvm_config_test run_phase exited", UVM_LOW)			
		endtask
	endclass
endpackage

4.2 仿真结果

5. 消息管理

set_report_verbosity_level_hier(UVM_NONE);/*冗余度高于UVM_NONE的都不会被打印出来*/
set_report_id_verbosity_hier("BUILD", UVM_NONE);/*只对BUILD ID做限制*/
uvm_root::get().set_report_id_verbosity_hier("BUILD", UVM_NONE);/*从顶层做配置*/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值