ICode9

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

(23)UVM 层次化sequence构建方式(layering sequence)

2021-11-21 09:03:18  阅读:215  来源: 互联网

标签:层次化 layering layer sequence phy uvm sequencer phase


UVM 层次化sequence构建方式(layering sequence)

文章目录

layering sequence介绍

  • 如果我们在构建更加复杂的协议总线传输,例如PCIe,USB3.0等,那么通过一个单一的传输层级会对以后的激励复用、上层控制不那么友好。对于这种更深层次化的数据传输,在实际中无论是VIP还是自开发的环境,都倾向于通过若干抽象层次的sequence群落来模拟协议层次。
  • 通过层次化的sequence可以分别构建transaction layer、transport layer和physical layer等从高抽象级到低抽象级的transaction转换。这种层次化的sequence构建方式,我们称之为layering sequence。例如在进行寄存器级别的访问操作,其需要通过transport layer转换,最终映射为具体的总线传输。
  • 我们将通过一端简单的例码,来阐述layer sequence的核心,突出sequence层级转换的思想。
    在这里插入图片描述

layering sequence示例

在这里插入图片描述

typedef enum{CLKON,CLKOFF,RESET,WRREG,RDREG} phy_cmd_t;
typedef enum{FREG_LOW_TRANS,FREG_MED_TRANS,FREG_HIGH_TRANS}layer_cmd_t;
class bus_trans extends uvm_sequence_item;
	rand phy_cmd_t cmd;
	rand int addr;
	rand int data;
	constraint cstr{
		soft addr=='h0;
		soft data=='h0;
	};
	...
endclass

class packet_seq extends uvm_sequence;
	rand int len;
	rand int addr;
	rand int data[];
	rand phy_cmd_t cmd;
	constraint cstr{
		soft len inside {[30:50]};
		soft addr[31:26]=='hFF00;
		data.size()==len;
	};
	...
	task body();
		bus_trans req;
		foreach(data[i])
			`uvm_do_with{req,{cmd==local::cmd;
							addr==local::addr;
							data==local::data[i];}}
	endtask
endclass

class layer_trans extends uvm_sequence_item;
	rand layer_cmd_t layer_cmd;
	rand int pkt_len;
	rand int pkt_idle;
	constraint cstr{
	soft pkt_len inside{[10:20]};
	layer_cmd == FREQ_LOW_TRANS -> pkt_idle inside {[300:400]};
	layer_cmd == FREQ_MED_TRANS -> pkt_idle inside {[100:200]};
	layer_cmd == FREQ_HIGH_TRANS -> pkt_idle inside {[20:40]};
};
...
endclass

class adapter_sequence extends uvm_sequence;
	`uvm_object_utils(adapter_seq)
	`uvm_declare_p_sequencer(phy_master_sequencer)
	...
	task body();
		layer_trans trans;
		packet_seq pkt;
		forever begin
			p_sequencer.up_sqr.get_next_item(req);
			void'($cast(trans,req));
			repeat(trans.pkt_len)begin
				`uvm_do(pkt)
				delay(trans.pkt_idle);
			end
			p_sequencer.up_sqr.item_done();
		end
	endtask
	virtual task delay(int delay);
	...
	endtask
endclass

class top_seq extends uvm_sequence;
	...
	task body();
		layer_trans trans;
		`uvm_do_with(trans,{layer_cmd == FREQ_LOW_TRANS;})
		`uvm_do_with(trans,{layer_cmd == FREQ_HIGH_TRANS;})
	endtask
endclass

class layering_sequencer extends uvm_sequencer;
...
endclass

class phy_master_sequencer extends uvm_sequencer;
	layering_sequencer up_sqr;
	...
endclasss

class phy_master_driver extends uvm_driver;
	...
	task run_phase(uvm_phase phase);
		REQ tmp;
		bus_trans req;
		forever begin
			seq_item_port.get_next_item(tmp);
			void'($cast(req,tmp));
			`uvm_info("DRV",$sformatf("got a item \n %s",req.sprint()),UVM_LOW)
			seq_item_port.item_done();
		end
	endtask
endclass

class phy_master_agent extends uvm_agent;
	phy_master_driver drv;
	phy_master_sequencer sqr;
	...
	function void build_phase(uvm_phase phase);
		sqr=reg_master_sequencer::type_id::create("sqr",this);
		drv=reg_master_driver::type_id::create("drv",this);
	endfunction
	function void connect_phase(uvm_phase phase);
		drv.seq_item_port.connect(sqr.seq_item_export);
	endfunction
endclass

class test1 extends uvm_test;
	layering_sequencer layer_sqr;
	phy_master_agent phy_agt;
	...
	function void build_phae(uvm_phase phase);
		layer_sqr=layering_sequencer::type_id::create("layer_sqr",this);
		phy_agt=phy_master_agent::type_id::create("phy_agt",this);
	endfunction
	function void connect_phase(uvm_phase phase);
		phy_agt.sqr.up_sqr=layer_sqr;
	endfunction
	task run_phase(uvm_phase phase);
		top_seq seq;
		adapter_seq adapter;
		phase.raise_objection(phase);
		seq=new();
		adapter=new();
		fork
			adapter.start(phy_agt.sqr);
		join_none
		seq.start(layer_sqr);
		phase.drop_objection(phase);
	endtask
endclass

不是driver,可以调用get_next_item吗?也可以,因为get_next_item方法实际上是属于sqr的,那为什么driver可以直接通过port调用该方法呢?这是因为port与sqr的import相连。

我们可以得出一些关于如何实现sequencer layer协议转换的方法:

  • 无论有多少抽象层次的transaction类定义,都应该有对应的sequencer作为transaction的路由通道。例如layer_sequencer和phy_master_sequencer分别作为layer_trans和bus_trans的通道。
  • 在各个抽象级的sequence中,需要有相应的转换方法,将从高层次的transaction从高层次的sequencer获取,继而转换为低层次的transaction,最终通过低层次的sequencer发送出去。例如adapter_seq负责从layer_sequencer获取layer_trans,再将其转换为phy_master_sequencer一侧对应的sequence或者transaction,最后再将其从phy_master_sequencer发送出去。
  • 这些adaption sequence应该运行再低层次的sequencer一侧,作为"永动"的sequence时刻做好服务准备,从高层次的sequencer获取transaction,通过转换将其从低层次的sequencer一侧送出。例如上面在test1中,adapter sequence通过adapter.start(phy_agt.sqr)挂载到低层次的sequencer,做好转换transaction并将其发送的准备。
  • 至于需要定义多少个层次的transaction item类,上面的例子仅仅是为了说明layer sequence的一般方法,对于实际中的层次定义和transaction item定义,我们还需要具体问题具体处理。

layering sequence解析

我们可以看到各个sequence类别对应的sequencer,同时也有sequence item发送和转换的方法。经过转换,最终高层次的transaction内容可以落实到低层次的protocol agent和physical interface上面。

例码中没有给出读回路的处理,即从physical interface穿过physical agent,最终抵达layering sequencer的通信。在实际中我们可以通过monitor转换抽象级返回item的方式来实现。

也可以通过不同层次的monitor采集response transcation,最终通过monitor转换抽象级返回item的方式来实现。

至于选择哪一种反馈回路,这与底层agent反馈回路的实现方式有关,即如果原有方法通过driver一侧返回response,那么我们建议继续在该反馈链条上进行从低级transaction到高级transaction的转换,如果原有方式通过monitor一侧返回response,那么我们也建议创建对应的高层次monitor,抽线抽象层次转换。

关注作者

  • 自述
    作者是一位中科大数字设计专业的研究生,水平有限,如有错误,请大家指正,想要与大家一同进步。
  • 经历
    曾获得国家奖学金,“高教社杯”数学建模国家二等奖等
  • 陆续更新:
    1.与UVM验证相关的system verilog后续内容;
    2.与verilog数字设计相关的一些基础模块设计,例如FIFO,UART,I2C等的书写。
    3.保研与竞赛经历等
  • 微信公众号
    欢迎大家关注公众号“数字IC小白的日常修炼”,期待与大家一同仗剑遨游数字IC世界。

标签:层次化,layering,layer,sequence,phy,uvm,sequencer,phase
来源: https://blog.csdn.net/qq_42419590/article/details/121443652

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

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

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

ICode9版权所有