第六章 UVM中的sequence
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第六章 UVM中的sequence相关的知识,希望对你有一定的参考价值。
参考技术A(1)通过 uvm_do_pri 和 uvm_do_pri_with 改变所产生的transaction的优先级:
"my_case0.sv"
class sequence0 extends uvm_sequence #(my_transaction);
...
virtual task body();
`uvm_do_pri(m_trans, 100)
or
`uvm_do_pri_with(m_trans, 200, m_trans.pload.size < 500;)
第二个参数是优先级,这个数必须是一个大于等于-1的整数,数字越大,优先级越高。
(2)sequencer的仲裁算法:
SEQ_ARB_FIFO(默认仲裁算法,遵循先入先出,不考虑优先级)
SEQ_ARB_WEIGHTED(加权的仲裁)
SEQ_ARB_RANDOM(完全随机选择)
SEQ_ARB_STRICT_FIFO(严格按照优先级,当有多个同一优先级的sequence时,按照先入先出的顺序选择)
SEQ_ARB_STRICT_RANDOM(严格按照优先级,当有多个同一优先级的sequence时,随即从最高优先级中选择)
SEQ_ARB_USER (用户自定义的仲裁算法)
若想要优先级起作用,应该设置仲裁算法为SEQ_ARB_STRICT或者SEQ_ARB_STRICT_RANDOM:
env.i_agt.sqr.set_arbitration(SEQ_ARB_STRICT_FIFO);
fork
seq0.start(env.i_agt_sqr);
seq1.start(env.i_agt_sqr);
join
(3)lock 操作
grab 操作(比lock优先级更高,放入sequencer仲裁队列的最前面)
is_relevent() 函数(1说明此sequence有效,否则无效)
wait_for_relevent() 函数
(1)uvm_do系列
(2)uvm_create 与 uvm_send
(3)uvm_rand_send,与uvm_send类似,唯一区别是它会对transaction进行随机化
m_trans = new("m_trans");
`uvm_rand_send(m_trans);
(4)`uvm_do系列宏其实是将下述动作封装在了一个宏中:
tr = new("tr");
start_item(tr);
assert(tr.randomize() with tr.pload.size() == 200;);
finish_item(tr);
(5)pre_do (task), mid_do (function), post_do (function)
(1)嵌套的sequence:在一个sequence的body中,除了可以使用uvm_do宏产生transaction外,该可以启动其他的sequence,直接在新的sequence的body中调用定义好的sequence。
(2)uvm_do, uvm_send, uvm_rand_send, uvm_create宏,其第一个参数除了可以是transaction的指针外,还可以是sequence的指针。start_item & finish_item,这两个任务的参数必须是transaction的指针。
(3)sequence与transaction都可以调用randomize进行随机话,都可以由rand修饰符的成员变量。在sequence中定义的rand类型变量以向产生的transaction传递约束时,变量的名字一定要与transaction中相应字段的名字不同。
(4)`uvm_declare_p_sequencer(my_sequencer) == (my_sequencer p_sequencer);这个过程在pre_body()之前就完成了,因此在sequence中可以直接使用成员变量p_sequencer来访问sequencer中的成员变量。
(1)实现sequence之间同步最好的方式就是使用virtual sequence。virtual sequence不发送transaction,它只是控制其他的sequence,起统一调度的作用。为了使用virtual sequence,一般需要一个virtual sequencer,其里面包含指向其他真实sequencer的指针。
(2)一般来说。只在最顶层的virtual sequence中控制objection。
(1)在sequence中获取参数
sequence的路径:uvm_test_top.env.i_agt.sqr.case0_sequence
【uvm_config_db#(int)::set(this, "env.i_agt.sqr.*", "count", 9);】
因为sequence在实例化时名字一般是不固定的,而且有时时未知的(比如使用default_sequence启动的sequence的名字就是未知的),所i使用通配符。
uvm_config_db#(int)::get(null, get_full_name(), "count", count));
在get函数原型中,第一个参数必须是component,而sequence不是一个component,所以这里不能使用this指针,只能使用null或uvm_root::get()。
(2)在sequence中设置参数
uvm_config_db#(bit)::set(uvm_root::get(), "uvm_test_top.env0.scb", "cmp_en", 0);
uvm_config_db#(bit)::set(uvm_root::get(), "uvm_test_top.v_sqr.*", "first_start", 0);
(3)一个sequence是在task phase中运行的,当其设置一个参数的时候,起事件往往是不固定的。针对这种不固定的设置参数的方式,UVM提供了wait_modified任务。当它检测当第三个参数的值被更新过后,它就返回,否则一直等待在那里:
uvm_config_db#(bit)::wait_modified(this, "", "cmp_en");
(1)在driver中,
rsp = new("rsp");
rsp.set_id_info(req);
seq_item_port.put_response(rsp);
seq_item_port.item_done();
or
rsp = new("rsp");
rsp.set_id_info(req);
seq_item_port.item_done(rsp);
在sequence中,
virtual task body();
...
get_response(rsp);
(1)随机选择sequence
class simple_seq_library extends uvm_sequence_library #(my_transaction);
function new(string name = "simple_seq_library");
supre.new(name);
init_sequence_library();
endfunction
`uvm_object_utils(simple_seq_library)
`uvm_sequence_library_utils(simple_seq_library);
endclass
一个sequence在定义时使用宏uvm_add_to_seq_lib(seq0, simple_seq_library)来将其加入某个sequence library中。一个sequence可以加入多个sequence library中。
(2)控制选择算法
typedef enum UVM_SEQ_LIB_RAND, UVM_SEQ_LIB_RANDC, UVM_SEQ_LIB_ITEM, UVM_SEQ_LIB_USER uvm_sequence_lib_mode;
UVM_SEQ_LIB_RAND:完全随机。
UVM_SEQ_LIB_RANDC:将加入其中的sequence随机排一个顺序,然后按照此顺序执行,可以保证每个sequence执行一遍。配置方式:
uvm_config_db#(uvm_sequence_lib_mode)::set(this, "env.i_agt.sqr.main_phase", "default_sequence.selection_mode", UVM_SEQ_LIB_RANDC);
UVM_SEQ_LIB_ITEM:sequence library并不执行其sequence队列中的sequence,而是自己产生transaction。
UVM_SEQ_LIB_USER:用户自定义选择的算法。此时需要用户重载select_sequence参数:
virtual function int unsigned select_sequence(int unsigned max);
...
endfunction
(3)控制执行次数
min_random_count, max_random_count
(4)UVM提供了一个类uvm_sequence_library_cfg来对sequence library进行配置:
uvm_sequence_library_cfg cfg;
super.build_phase(phase);
cfg = new("cfg", UVM_SEQ_LIB_RANDC, 5, 20);
uvm_config_db#(uvm_object_wrapper)::set(this, "env.i_agt.sqr.main_phase", "default_sequence", simple_seq_library::type_id::get());
uvm_config_db#(uvm_sequence_library_cfg)::set(this. "env.i_agt.sqr.main_phase", "default_sequence.config", cfg);
or
simple_seq_library seq_lib;
super.build_phase(phase);
seq_lib = new("seq_lib");
seq_lib.selection_mode = UVM_SEQ_LIB_RANDC;
seq_lib.min_random_count = 10;
seq_lib.max_random_count = 15;
uvm_config_db#(uvm_sequence_base)::set(this, "env.i_agt.sqr.main_phase", "default_sequence", seq_lib);
以上是关于第六章 UVM中的sequence的主要内容,如果未能解决你的问题,请参考以下文章