UVM-sequence,sequencer,driver

package pack1; //pack1头
	import uvm_pkg::*; //+UVM
  	`include "uvm_macros.svh"//+工厂
	
	class item extends uvm_sequence_item;
		rand int data_auto;
		rand int data_noauto;
					//声明两个data,一个加入自动化域,一个
					//不加入
		`uvm_object_utils_begin(item)
			`uvm_field_int(data_auto,UVM_ALL_ON)
		`uvm_object_utils_end
		function new(string name = "item");
			super.new(name);
		endfunction
	endclass
	
	class seq extends uvm_sequence;
		`uvm_object_utils(seq)
		function new(string name = "seq");
			super.new(name);
		endfunction
		task body();
			uvm_sequence_item temp;
			item req,rsp;
			temp = create_item(item::get_type(),m_sequencer,"req");
				//create_item:能够实例化一个继承于uvm_sequence_item类的类
				//返回值:uvm_sequence_item句柄
				//参数1:指明要例化的继承于uvm_sequence_item类的类
				//参数2:指明这个对象即将挂载到哪个sequencer上
				//       (m_sequencer是uvm_sequence类的一个属
				//       性,当m_sequencer被挂载到某个
				//       sequencer上时,m_sequencer会自动指向
				//       这个sequencer)
				//参数3:这个对象的名字
			void'($cast(req,temp));
				//在上一句话中由于使用create_item方法,导致
				//父类句柄指向子类对象
				//(uvm_sequence_item句柄) --> (item对象)
				//做个转化使子类对象重新被子类句柄指向
			start_item(req);
				void'(req.randomize with{data_auto == 50;
							 data_noauto == 50;});
				`uvm_info("sequence","sequence request to send item", UVM_LOW)
				`uvm_info("data_auto",$sformatf("%d",req.data_auto), UVM_LOW)
				`uvm_info("data_noauto",$sformatf("%d",req.data_noauto), UVM_LOW)
				req.print();
			finish_item(req);
				//
				//seq发起start告知seqr,我要向driver发送item
				//(start会立即返回,然后执行下面的语句)
				//seqr判断此时的driver是否已经get_next_item,
				//若否,则继续等待。若是,那么driver收到完item
				//后会执行item_done,收到item_done后,
				//finish_item的阻塞结束
				//

			get_response(temp);  //get_response返回的uvm_sequence_item是句柄,
					     //需要做个中间转化
			void'($cast(rsp,temp));
			`uvm_info("sequence","sequence already recive item", UVM_LOW)
			`uvm_info("data_auto",$sformatf("%d",rsp.data_auto), UVM_LOW)
			`uvm_info("data_noauto",$sformatf("%d",rsp.data_noauto), UVM_LOW)
			req.print();
		endtask
	endclass

			
	class seqr extends uvm_sequencer;
		`uvm_component_utils(seqr)
		function new(string name = "seqr", uvm_component parent = null);
			super.new(name, parent);
		endfunction
	endclass

	class dri extends uvm_driver;
		`uvm_component_utils(dri)
		function new(string name = "dri", uvm_component parent = null);
			super.new(name, parent);
		endfunction
		
		task run_phase(uvm_phase phase);
			uvm_sequence_item temp ;
			uvm_object temp1;
			item req,rsp;
			phase.raise_objection(this);//进入run_phase需要先举手

			seq_item_port.get_next_item(temp);
			void'($cast(req,temp));
			`uvm_info("driver","driver already recive item", UVM_LOW)
			`uvm_info("data_auto",$sformatf("%d",req.data_auto), UVM_LOW)
			`uvm_info("data_noauto",$sformatf("%d",req.data_noauto), UVM_LOW)
			req.print();
			//driver使用自带的TLM端口,向seqr的TLM端口使用get_next_item
			//来获取一个对象,(get_next_item返回的是uvm_sequence_item
			//句柄需要类型转换)

			#1us;
			//---------------------------------------------
			//--此处省略driver解析item并向interface进行驱动
			//---------------------------------------------
			
		
			temp1 = req.clone();
			void'($cast(rsp,temp1));
			`uvm_info("clone:data_auto",$sformatf("%d",rsp.data_auto), UVM_LOW)
			`uvm_info("clone:data_noauto",$sformatf("%d",rsp.data_noauto), UVM_LOW)
			//克隆一个上一步接收到的对象
			//(clone返回的居然是uvm_object的句柄,需要类型转换)
			//!!clone只会克隆已经加入自动化域的属性的值,
			//data_noauto不在自动化域内,在克隆时候,类声明时候的
			//默认值0,而不是req的对象值50
			//同样‘req’的sequence_id也不会被克隆,克隆时候得到的也
			//是类中的声明初始值


			rsp.set_sequence_id(req.get_sequence_id());
			rsp.data_auto = rsp.data_auto + 100;
			rsp.data_noauto = rsp.data_noauto + 100;
			seq_item_port.item_done(rsp);
			//get_sequence_id用于获取‘req’这个item所在sequence的id好
			//然后使用set_sequence_id把id号交给‘rsp’这个item
			//这样item_done这个方法就知道要把‘rsp’这个item发送给谁
			//了
			//细节来说,item_done这个方法的作用有两个
			//1是:告知seq的finish_item,你别在那阻塞了,我都消化
			//     掉了
			//2是:向seqr的rspfifo中传递rsp这个对象
			//     这样sequence里的get_response才能得到对象
			//     要不然是得不到对象的
			`uvm_info("driver","driver already send item", UVM_LOW)
			`uvm_info("data_auto",$sformatf("%d",rsp.data_auto), UVM_LOW)
			`uvm_info("data_noauto",$sformatf("%d",rsp.data_noauto), UVM_LOW)

			phase.drop_objection(this);//退出run_phase需要先落手
		endtask

	endclass

	class env extends uvm_env;
		seqr seqr0;
		dri dri0;
		`uvm_component_utils(env)
		function new(string name="env" ,uvm_component parent = null);
			super.new(name,parent);
		endfunction
		//buildphase中例化sequencer 和 driver
		function void build_phase(uvm_phase phase);
			seqr0 = seqr::type_id::create("seqr0",this);		
			dri0 = dri::type_id::create("dri0",this);		
		endfunction
		//connect_phase中连接sequencer和driver自带的一组TLM端口
		function void connect_phase(uvm_phase phase);
			dri0.seq_item_port.connect(seqr0.seq_item_export);
		endfunction
		
	endclass


	class test1 extends uvm_test;
		env env0;
		`uvm_component_utils(test1)
		function new(string name = "test1", uvm_component parent = null);
			super.new(name, parent);
		endfunction

		function void build_phase(uvm_phase phase);
			super.build_phase(phase);
			env0 = env::type_id::create("env0",this);
			`uvm_info("test1",$sformatf("build"), UVM_LOW)
		endfunction

		task run_phase(uvm_phase phase);
			seq seq0;
			phase.raise_objection(this);//进入run_phase需要先举手
			
			`uvm_info("test1",$sformatf("run"), UVM_LOW)
			seq0 = new();
			seq0.start(env0.seqr0);
			//将seq0挂载到 env0的seqr0上
			//一旦seq被挂载到了seqr上,那么这个seq就知道了他的m_seqencer是谁
			//他的body任务也会自动执行
			
			phase.drop_objection(this);//退出run_phase需要先落手
		endtask
	endclass

endpackage

//--------------------------------------module---------------------------------
module hardware1;
	import pack1::*;
	import uvm_pkg::*; //+UVM

	
	initial begin
		run_test("test1"); 	
	end
		
endmodule

上一篇:【uvm】uvm_event同步


下一篇:协方差 cov以及协方差矩阵基础知识