UVM中add_typewide_sequence和add_sequence的区别

我们在用uvm_sequence_library的时候,会遇到三种方式往uvm_sequence_library添加sequence,分别是:
function void add_sequence(uvm_object_wrapper seq_type);function void add_typewide_sequence(uvm_object_wrapper seq_type);function void add_typewide_sequences(uvm_object_wrapper seq_types[$]);第2和第3种方式类似,第3种是一下子添加多个sequence,它内部原理就是调用第2种的函数,因此在本质上,只有第1和第2种这两类区别。第1种方式是往sequences队列里push sequences。第2种方式是往m_typewide_sequences队列里push sequences。sequences和m_typewide_sequences的定义如下,它们都是uvm_object_wrapper类型,因此sequence在push的时候,要采用sequence_name::get_type()的方式加入。
protected uvm_object_wrapper sequences[$];static protected uvm_object_wrapper m_typewide_sequences[$];下面分别说下两种push有何不同。
1. add_sequence(uvm_object_wrapper seq_type)
它的代码如下:
function void add_sequence(uvm_object_wrapper seq_type); if (m_dyn_check(seq_type)) sequences.push_back(seq_type);endfunction可以看出add_sequence(xxx)函数很简单,就是往sequences队列里push sequence的uvm_object_wrapper类型。
在m_dyn_check(xxx)函数里会检查push进来的sequence不能是非uvm_sequence_base类型的,且不能重复。只有都不满足以上两者条件,才能被push进sequences队列里。而且我们根据sequences队列的定义可以看出,它没有带static修饰,也就是说,uvm_sequence_library例化多份instance的话,它也会跟着被例化多份,多个instance里的sequences队列互不共享。这一点是和m_typewide_sequences队列有着本质区别的。
function bit m_dyn_check(uvm_object_wrapper seq_type); if (!m_check(seq_type,this)) return 0; foreach (sequences[i]) if (sequences[i] == seq_type) return 0; return 1;endfunctionm_check(xxx)函数定义如下,它就是单纯的判断seq_type,如果seq_type是uvm_sequence_base类型的,就返回1,否则返回0。
function bit m_check(uvm_object_wrapper seq_type, this_type lib); uvm_object obj; uvm_sequence_base seq; uvm_root top; string name; string typ; obj = seq_type.create_object(); name = (lib == null) ? type_name : lib.get_full_name(); typ = (lib == null) ? type_name : lib.get_type_name(); top = uvm_root::get(); if (!$cast(seq, obj)) begin `uvm_error_context(seqlib/bad_seq_type, {object ',obj.get_type_name(), ' is not a sequence. cannot add to sequence library ',name, '},top) return 0; end return 1;endfunction2. add_typewide_sequence(uvm_object_wrapper seq_type)
它的代码如下:
static function void add_typewide_sequence(uvm_object_wrapper seq_type); if (m_static_check(seq_type)) m_typewide_sequences.push_back(seq_type);endfunction可以看出add_typewide_sequence(xxx)函数也很简单,就是往m_typewide_sequences队列里push sequence的uvm_object_wrapper类型。
m_static_check(xxx)函数和m_dyn_check(xxx)函数类似,这里面会检查push进来的sequence不能是非uvm_sequence_base类型的,且不能重复。只有都不满足以上两者条件,才能被push进m_typewide_sequences队列里。
function bit m_static_check(uvm_object_wrapper seq_type); if (!m_check(seq_type,null)) return 0; foreach (m_typewide_sequences[i]) if (m_typewide_sequences[i] == seq_type) return 0; return 1;endfunction从m_typewide_sequences队列和add_typewide_sequence(xxx)函数的定义我们可以看出,它们都是static类型的,也就是就算uvm_sequence_library有多份不同的instances,m_typewide_sequences在它们之间是共享的。因此,放在m_typewide_sequences队列里的sequences是打算被多个uvm_sequence_library(包含从它扩展出的子类libraries)共享的话,就可以用add_typewide_sequence(xxx)函数把它们加入到m_typewide_sequences队列里。如果要被某个uvm_sequence_library私自独享的话,就需要用add_sequence(xxx)函数把它们加入到sequences队列中。
3. 注意事项
在uvm_sequence_library调用new(xxx)函数例化的时候,会自动调用init_sequence_library()函数,这个函数的定义如下:
function void init_sequence_library(); foreach (this_type::m_typewide_sequences[i]) sequences.push_back(this_type::m_typewide_sequences[i]);endfunctioninit_sequence_library()函数会自动把m_typewide_sequences队列里的内容复制到sequences队列里,因为uvm_sequence_library随机选择sequence时看的是sequences队列里的sequence。
因此大家要注意的是,如果在uvm_sequence_library例化之前,通过uvm_sequence_library::add_typewide_sequence(xxx)方式放到m_typewide_sequences队列里的sequences会自动也复制到sequences队列里。但如果是在uvm_sequence_library例化之后,才调用add_typewide_sequence(xxx)方式放到m_typewide_sequences队列里的sequences,需要自己再调用下init_sequence_library()函数。
下面是一段uvm的例子,selection_mode为uvm_seq_lib_rand,它会按平均权重随机在sequences队列挑出sequence。
uvm_seq_lib_rand: begin valid_rand_selection.constraint_mode(1); valid_sequence_count.constraint_mode(0); for (int i=1; i<=sequence_count; i++) begin if (!randomize(select_rand)) begin `uvm_error(seqlib/rand_fail, random sequence selection failed) break; end else begin wrap = sequences[select_rand]; end execute(wrap); end valid_rand_selection.constraint_mode(0); valid_sequence_count.constraint_mode(1); end下面是另一段uvm的例子,selection_mode为uvm_seq_lib_user,也是用户可以自动的方式。因此用户需要select_sequence(xxx)函数来完成自己挑选算法。
uvm_seq_lib_user: begin for (int i=1; i= sequences.size()) begin `uvm_error(seqlib/user_fail, user sequence selection out of range) wrap = req::get_type(); end else begin wrap = sequences[user_selection]; end execute(wrap); end endselect_sequence(xxx)函数定义如下,用户用systemverilog语法的virtual override就可以实现自定义挑选sequence的算法了。
function int unsigned select_sequence(int unsigned max); static int unsigned counter; select_sequence = counter; counter++; if (counter >= max) counter = 0;endfunction

亚太地区驱动全球市场增长,小米表现最为亮眼
疫情之后,特斯拉超级充电桩使用量下降了70%
微捷码QCP提取器通过台积电28纳米设计质量检验
2GB内存台式机用什么系统好
选购音响器材的技巧有哪些
UVM中add_typewide_sequence和add_sequence的区别
测试设备Zulu 3与Bose A20相比如何?
LED在工业通信应用中主要拥有哪些优势
变频器提供的控制方式有哪些?
曝华为将联手深度推出PC新系统 且预计出货至少60万台国产PC
CD4026芯片如何驱动共阳极数码管
2018全球Top 1000 计算机科学家,29位中国科学家上榜
飞思卡尔多摄像头全景泊车辅助系统与ADAS产品
工控机主板应该如何来选型
捕食者C无人机杀伤力大 被广泛应用于打击恐怖主义的操作中去
6颗白光LED灯珠的点亮方法
小米推Mi便携式无线鼠标:重量仅为56g,电池寿命长达12个月
PCBA开路为什么会导致电路板失效
蓄电池在线监测系统(蓄电池巡检系统)技术方案
高通芯片设计收入大幅增加的因素分析