电力电子转战数字IC20220722day55——sequence相关

目录

继承关系

sequence和item

uvm_sequence_item

uvm_sequence

flat sequence

hierarchical sequence

sequencer和driver

通信时序


 

类比:sequence=道路,seuqence item=货车,sequencer=目的地收费站,driver=卸货地点。item从sequence一端出发经过sequencer最终到达driver。

  • driver陆续拿到多个随机化的item,经过数据解析,按照与dut的物理接口协议将数据写入到接口上,对dut形成激励
  • 有必要时,driver解析完一个item回返回最后的状态信息给item对象并回到出发点(互动)

继承关系

 

 

  • item和sequence可以在任何phase创建
  • 无法通过uvm环境结构或phase机制来识别sequence的运行阶段
  • 顶层配置时无法按照层次关系直接配置到sequence中,因为item和sequence不在uvm结构中
  • sequence活动起来必须挂在attach到一个sequencer上,间接通过sequencer来获取顶层的配置和信息
  • sequence只负责生成item的内容,driver负责驱动激励时序,最终的接口驱动时序由driver和sequencer共同决定
  • sequencer:作为一个组件可以通过tlm端口与driver传送tiem对象;面向多个并行sequence有仲裁机制来合理分配和传送item
  • 数据传送机制采用get模式:driver从sequencer获取item

sequence和item

  • 分别是uvm_sequence类和uvm_sequence_item类
  • sequence编织激励生成和场景控制;对于激励所需要的的具体数据和控制要求,是从itme的成员数据得来的

uvm_sequence_item

  • item基于uvm_object类,具备uvm核心基类的数据操作方法:copy,clone, compare,record
  • item具备的数据成员:
    • 控制类(总线协议上的读写模式、数据长度、传送模式),
    • 负载类(数据总线上的数据包),
    • 配置类(控制driver的驱动行为)
    • 调试类(标记信息以方便调试,id、time)
class bus_trans extends uvm_sequence_item;
rand bit write;
rand int data;
rand int addr;
rand int delay;
static int id_num;
`uvm_object_utils_begin()
	`uvm_field_int()
	...
`uvm_object_utils_end
...endclass

class test1 extends uvm_test;
`uvm_component_utils()
...
task run_phase(u p);
	bus_trans t1, t2;
	phase.raise_objection(p);
	#100ns;
	t1=new("t1");
	t1.print();
	#200ns;
	t2=new("t2");
	void'(t2.randomize());
	t2.print();
	phase.drop_objection(p);
	endtask
endclass
  • 如果数据域属于需要用来做驱动,应该考虑定义为rand,按照驱动协议给出合适的约束constraint
  • 域的自动化不要忘记,便于使用uvm_object的基本数据方法
  • uvm要求item的创建和随机化都要发生在sequence的body()任务中
  • item生命周期:产生于sequence的body(),经历随机化,穿越sequencer,到达driver,被消化

uvm_sequence

  • 由于item在创建后需要被随机化,sequence在声明时也需要预留一些可供外部随机化的变量,部分用来通过层级传递约束最终控制item对象的随机变量,部分用来对item对象之间加以组织和时序控制
  • 分类
    • flat sequence扁平类:用来组织更小的粒度,即item实例构成的组织
    • hierarchical sequence层次类:由更高层的sequence用来组织底层的sequence,按照一定顺序或并行,挂载到同一个sequencer
    • virtual sequence虚拟类:最终控制整个测试场景的方式,针对多种类型的sequencer协调顶层的测试场景,该sequence不会固定挂载在某种sequencer上,而是将其内部不同类型sequence最终挂载到不同的目标sequencer上

flat sequence

往往由sequence item群落构成

  • 包含的信息:
    • itme以及相关的constraint,用来关联生成的item之间的关系;
    • 给定各个item之间的时序信息,也就是pkg_idle
    • 响应具体时间从而创建对应的item并发送出去,比如等待monitor的信号后与driver读操作
class bus_trans extends uvm_sequence_item;
rand bit write;
rand int data;
rand int addr;
rand int delay;
static int id_num;
//注册和域的自动化
...
endclass

class test1 extends uvm_test;
//注册
...//new
task run_phase(u p);
	flat_seq seq;
	phase.raise_objection(p);
	seq=new();
	seq.randomize() with {addr=='h200;
												length==		};
	seq.body();
	phase.drop_objection(p);
endtask 
endclass

class flat_seq extends uvm_sequence;
rand int length;
rand int addr;
rand int data[];//1个trans只有1个data,1个sequence有多个data
rand bit write;
rand int delay;
constraint cstr {
data.size()==length;
foreach(data[i]) soft data[i]==i;
soft addr=='h100;
soft write==1;
delay inside{[1:5]};
};
//注册
...
task body();
	bus_trans tmp;
	foreach(data[i]) begin
	tmp=new();
	tmp.randomize() with {
		data==local::data[i];
		addr==local::addr+i<<2;
		write==local::write;
		delay==local::delay;
												};
	tmp.print();
	end
endtask
endclass
class bus_trans extends uvm_sequence_item;
rand bit write;
rand int data;
rand int addr;
rand int delay;
static int id_num;

constraint cstr {
data.size()==length;
foreach(data[i]) soft data[i]==i;
soft addr=='h100;
soft write==1;
delay inside{[1:5]};
};
//注册和域的自动化
....endclass

class flat_seq extends uvm_sequence;
rand int length;//其他成员变量下放到trans
rand int addr;
`uvm_object_utils()
...
task body();
	bus_trans tmp;
	tmp=new();
	tmp.randomize() with{ length==local::length;
												addr==local::addr;
																							};
	tmp.print();
endtask
endclass

class test1 extends uvm_test;
//注册utils
...
task run_phase(u p);
	flat_seq seq;
	phase.raise_objection(p);
	seq=new();
	seq.randomize() with {addr=='h200; length==3;};
	seq.body();//body在挂载后会自动执行,这里只是刻意而为之
	phase.drop_objection(p);
endtask
endclass

hierarchical sequence

  • 可以使用其他sequence以及item,创建更丰富的激励场景
  • 具体地,通过层次嵌套关系,hs可以使用其他hs、flat seq和item
  • 如果底层的fs和item的粒度得当,则可以充分复用这些来构成形式更多样的hs
class hier_seq extends uvm_sequence;
`uvm_object_utils(hier_seq)
function new(string name ="hier_seq");
	super.new(name);
endfunction

task body();
	bus_trans t1, t2;
	flat_seq  s1, s2;
	`uvm_do_with(t1, {length==2;})//一个宏完成seq或者item的创建、随机化、传送
	fork
		`uvm_do_with(s1, {length==5;})
		`uvm_do_with(s2, {length==8;})
	join
	`uvm_do_with(t2, {length==3;})
endtask
endclass
  • sequence复用:通过高层的sequence来嵌套底层的sequence或者item,最后创建期望的场景
  • 上述例子既有串行也有并行的激励关系,还可以考虑加入事件的同步,延迟,来构成seq或者item之间的时序关系

sequencer和driver

  • uvm定义了匹配的tlm端口供这两位使用
    • uvm_seq_item_pull_port#(type REQ=int, type RSP=REQ)
    • uvm_seq_item_pull_export#(type REQ=int, type RSP=REQ)
    • uvm_seq_item_pull_imp#(type REQ=int, type RSP=REQ, type imp=int)
  • 作为initiator的driver,例化了两个端口
    • uvm_seq_item_pull_port#(REQ,RSP) seq_item_port
    • uvm_analysis_port#(RSP) rsp_port
  • 作为responser的sequencer,例化了两个端口
    • uvm_seq_item_pull_imp#(REQ, RSP, this_type) seq_item_port
    • uvm_analysis_export #(RSP) rsp_export
  • 一次完整的传送,driver::seq_itme_port和sequencer::seq_item_export,连接driver::seq_item_port.connect(sequencer::seq_item_export)

 

 

  • 都是参数化的类
    • uvm_sequencer #(type REQ= uvm_sequence_item, RSP=REQ)
    • uvm_driver #(type REQ=uvm_sequence_item, RSP=REQ)
    • driver得到req对象在进行下一步处理时,需要进行动态类型转换,将req转换成uvm_sequence_item的子类型
    • 或者自定义时标明其传递的具体item类型
  • req和rsp的类型尽量保持一致,便于统一处理方便item的操作
  • driver消化完当前的req后可以通过item_done(input RSP rsp_arg = null)告知sequence此次传输已经结束,参数中的rsp可以填入,返回相应的状态值
  • driver可以通过put_response()或者put()单独发送rsp,这可以通过成对的uvm_driver::rsp_port和uvm_driver::rsp_export端口来完成,方法为uvm_driver::rsp_port::write(RSP)
class bus_trans extends uvm_sequence_item;//item定义:就是个trans类
	rand int data;
	`uvm_object_utils_begin(bus_trans)//注册和域的自动化
		`uvm_field_int(data, UVM_ALL_ON)
	`uvm_object_utils_end
...endclass

class flat_seq extends uvm_sequence;//sequence定义
	`uvm_object_utils()//注册和例化
	...
task body();//sequence中不是run而是body
	uvm_sequence_item tmp;
	bus_trans req, rsp;
	tmp=create_item(bus_trans::get_type(), m_sequencer, "req");
	//创建req item对象(类型,被挂载目标m_sequencer,name)
	//如果没有指定挂载目标,在start_item时会默认挂载当前所在sequence挂载的sequencer
	void'($cast(req, tmp));//uvm_sequence_item类型的句柄转换成bus_trans型
	start_item(req);//准备发送,发送前做随机化
	req.randomize with {data==10;};//访问子类句柄的成员变量,需要句柄转换
	//如果是req.randomize();就可以,父类句柄做随机化会调用到子类里面的随机化
	`uvm_info("SEQ", "send a item")//sequence发出了item
	finish_item(req);//完成发送
	get_response(tmp);//必要的时候从driver处获取response item(可选)
	void'($cast(rsp, tmp));
	`uvm_info("SEQ", "got a item")//拿到item
endtask
endclass

class env extends uvm_env;
	sequencer sqr;
	driver drv;
	`uvm_component_utils(env)
	...
function void build_phase(u p);
	sqr=sequencer::type_id::create("sqr", this);
	drv=driver::type_id::create("drv", this);
endfunction

function void connect_phase(u p);//例化,连接driver到sequencer的tlm端口
	drv.seq_item_port.connect(sqr.seq_item_export);
endfunction
endclass

class sequencer extends uvm_sequencer;
`uvm_component_utils()
...endclass

class driver extends uvm_driver;
`uvm_component_utils()
...
task run_phase(u p);
	REQ tmp;
	bus_trans req, rsp;
	seq_item_port.get_next_item(tmp);//从sequencer获取有效的req item
	void'($cast(req, tmp));//从req item获取数据,产生数据激励
	`uvm_info("DRV", "got a item")
	void'($cast(rsp, req.clone()));//克隆生成新对象rsp item
	rsp.set_sequence_id(req.get_sequence_id());
	rsp.data +=100;//?????修改数据成员
	seq_item_port.item_done(rsp);//将rsp item对象返回给sequence(可选),成对操作
	`uvm_info("DRV", "sent a item")
endtask
endclass

通信时序

  • sequence和driver通话的对象都是sequencer(收费站,中间人)
  • 多个sequence要挂载到同一个sequencer上时,涉及sequencer的仲裁功能

 

 

  • 传递过程
    • sequence中由create_item产生一个item,start_item准备发送item时询问sequencer能不能发出,并randomization做随机化,在获得批准后finish_item开始发送item
    • item经过sequencer后到达driver,driver通过get_next_item获得这个item,将其解析后生成硬件dut的激励
    • driver通过item_done告诉sequence完成数据传送,至此为一次握手传输
    • 其中,driver可以选择将rsp作为状态返回值传回给sequence;sequence也可以调用get_response(RSP)主动等待从driver返回的数据对象
  • 注意
    • 每个item多应该有id信息表明从哪个sequence来的,在创建item时赋值
    • sequencer可以根据id信息发送respinse item返回到对应的sequence
    • 建议在driver中通过clone()单独创建rsp item,保证两个对象的独立性
    • 为了统一,用户可以不再定义sequence或者driver时指定item的类型,用默认类型REQ=uvm_sequence_item;在driver做类型转换:对get_next_item(REQ)的返回值REQ句柄做动态转换
    • 需要复用验证ip时,建议通过继承于原有sequence item的方式定义新的item子类,同时在顶层通过工厂覆盖的方式用新的item覆盖原有的item类型
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值