UVM——sequence机制(数据激励的产生、配置方式)

UVM——sequence机制(数据激励的产⽣、配置⽅式)
⽂章⽬录
⼀、sequence的执⾏流程
uvm_sequence_item(包装数据):只能对数据进⾏封装,不存在⾃动执⾏的函数;
uvm_sequence(⽣产数据):具有可⾃动执⾏的函数,可通过body()函数进⾏可执⾏操作,产⽣数据激励;
uvm_sequencer(发送数据):将数据发送给driver;
  sequence item是每⼀次driver与DUT互动的最⼩粒度内容,在sequence与driver之间起到桥梁作⽤的是sequencer,sequencer与driver均是component组件,它们之间的通信也是通过TLM端⼝实现的。UVM序列的连接传送如下图所⽰:深圳市龙岗区至诚社会工作服务中心
1. sequence对象⾃⾝会产⽣⽬标数量的sequence item对象。借助于SV的随机化和sequence item对随机化的⽀持,使得产⽣的每个
sequence item对象中的数据内容都不相同。
2. 产⽣的sequence item会经过sequencer再流向driver。
3. driver得到了每⼀个sequence item,经过数据解析,再将数据按照与DUT的物理接⼝协议写⼊到接⼝上,对DUT形成有效激励。
4. 必要时,driver在每解析并且消化完⼀个sequence item,也会将最后的状态信息同sequence item对象本⾝再度返回给
sequencer,最终抵达sequence对象⼀侧。这么做的⽬的在于,有的时候sequence需要得知driver与DUT互动的状态,这就需要driver仍然有⼀个回路再将处理了的sequence item对象和状态信息写回到sequence⼀侧。
⼆、sequence的启动⽅式——start()/default_sequence
  UVM中sequence的启动分为显⽰启动和隐式启动两种⽅式。
江阴城南小学
显式启动(直接启动)——调⽤start()⽅法启动。
隐式启动 ——使⽤uvm_config_db机制配置default_sequence启动。
//sequence的显式启动
//该⽅法提起和落下objection,通过phase.raise_objection(this)/phase.drop_objection(this)
my_sequence  seq = my_sequence::type_id::create("seq");
phase.raise_objection(this);
seq.start(sequencer);
phase.drop_objection(this)
//sequence的隐式启动
//该⽅法可以在sequence中使⽤starting_phase提起和撤销objection
uvm_config_db#(uvm_object_wrapper)::set(this,"env.i_agt.sqr.main_phase",
"default_sequence",
case0_sequence::get_type());
//在my_sequence中的body任务中
virtual task body;
if(starting_phase != null)
starting_phase.raise_objection(this);
repeat(10)begin
`uvm_do(req);
end
if(starting_phase != null)
starting_phase.drop_objection(this);
endtask
⼆、sequence⽣产数据——body( )
  当⼀个sequence启动后,会⾃动执⾏body()函数⽣产数据,sequencer会将数据发送给driver,完成数据的发送。sequencer与driver 的通信也是通过TLM端⼝实现的,TLM端⼝在例化中需要对通信参数进⾏指定,这⾥的通信参数即sequence item种类。
class tr_sequence extends uvm_sequence#(transaction);
...
virtual task body();
if(starting_phase != null)
starting_phase.raise_objection(this,"starting");//1.启动仿真,⽣产数据
`uvm_do(req);//2.通过宏`uvm_do⾃动随机化产⽣数据
if(starting_phase != null)
starting_phase.drop_objection(this,"done");//3.结束仿真
endtask
endclass
class driver extends uvm_driver#(transaction);
...
virtual task run_phase(uvm_phase phase);
forever begin
seq__next_item(req);//4.driver申请数据
send(req);//5.按照物理时序处理接收到的数据
seq_item_port.item_done();//6.数据传输完毕
end
工效挂钩管理办法粟裕战争回忆录
endtask
endclass
加粗样式在sequence中,通过objection机制控制仿真时的数据⽣产;
在driver的run_phase阶段,利⽤TLM端⼝seq_item_port的get_next_item()和item_done()⽅法控制数据包的传输;
2.1.宏`uvm_do( )的功能
  当⼀个sequence启动后,会⾃动执⾏sequence中的body任务,在body任务中可以调⽤`uvm_do系列宏来⽣产数据。
  当同⼀个sequencer上启动多个sequence时,由于sequencer会依据何种选择启⽤哪⼀个sequence的transaction存疑,故引⼊仲裁机制。使⽤仲裁机制的相关系列宏如下所指⽰:(默认仲裁算法是SEQ_ARB_FIFO,遵循先⼊先出,不考虑优先级)
`uvm_do(SEQ_OR_ITEM)//1. 根据sequence_item实例,随机化产⽣数据
`uvm_do_with(SEQ_OR_ITEM, CONSTRAINTS)//2. 在随机化数据的基础上,添加约束
红领巾小五年规划
`uvm_do_pri(SEQ_OR_ITEM, PRIORITY)
`uvm_do_pri_with(SEQ_OR_ITEM, PRIORITY, CONSTRAINTS)
`uvm_do_on(SEQ_OR_ITEM, SEQR)//3. 随机化同时,显式的指定使⽤哪个sequencer来发送此transaction
`uvm_do_on_pri(SEQ_OR_ITEM, SEQR, PRIORITY)
`uvm_do_on_with(SEQ_OR_ITEM, SEQR, CONSTRAINTS)
`uvm_do_on_pri_with(SEQ_OR_ITEM, SEQR, PRIORITY, CONSTRAINTS)
`uvm_do系列宏其实是将下述动作封装在了⼀个宏中(start_item与finish_item运⽤)。在实际的代码编写中,⼯程师可以不使⽤宏uvm_do()处理数据,⽽是根据实际情况⼿动执⾏这些内嵌程序。
req = my_sequence::type_id::create("req");  \      1.创建item对象实例;
start_item(req);      \                  2.获取sequencer的授权许可;
assert(req.randomzie() with {req.data ==100;});//assert(req.ranomzie()); 3.**对item进⾏随机化处理**;
finish_item(req);    \                  4.将item发送⾄sequencer,进⽽完成与driver之间的交互
宏`uvm_do_with (item, { constraint })与 宏 ‘uvm_do( )⽆本质区别,只是多了约束条件;需要说明的是宏‘uvm_do( )不⽀持randc类型的随机变量。
2.2.sequence的嵌套启动
  嵌套sequence的启动可以通过start(m_sequencer)来完成,也可以通过uvm_do()系列宏来完成;
m_sequencer是base_sequencer启动时所使⽤的sequencer的指针,也就是说,嵌套的seq启动时所使⽤的sequencer同所在的sequence所使⽤的sequencer⼀致。
class base_sequence extends uvm_sequence#(transaction);
...
virtual task body();
crc_seq    cseq=crc_seq::type_id::create("cseq");
long_seq      lseq=long_seq:;type_id::create("lseq");
repeat(10)begin
cseq.start(m_sequencer);            //启动嵌套的seq
lseq.start(m_sequencer);
end
endtask
endclass
采⽤uvm_do宏启动嵌套的seq,更加简单;
class base_sequence extends uvm_sequence#(transaction);
...
virtual task body();
crc_seq    cseq;
long_seq      lseq;
repeat(10)begin
`uvm_do(cseq);            //启动嵌套seq
`uvm_do(lseq);
情迷巴塞罗那
end
endtask
endclass
2.3.sequence接收响应rsp
class tr_sequence extends uvm_sequence#(transaction);
...
virtual task body();
.
..
`uvm_do(req);
get_response(rsp);//3.接收响应信息rsp
endtask
endclass
class driver extends uvm_driver#(transaction);
...
virtual task run_phase(uvm_phase phase);
forever begin
seq__next_item(req);
send(req);
rsp = transaction::type_id::create("rsp");
rsp.set_id_info(req);//1. 创建并配置响应ID
seq.item.port.item_done(rsp);//2. driver返回响应rsp
end
endtask
endclass
三、config_db配置sequence
3.1.默认执⾏的sequence
  默认的测试⽤例(test_base)执⾏默认的default sequence,该sequence在验证环境中配置的;
class environment extends uvm_env;//在初始环境中配置默认的sequence
...
function void build_phase(uvm_phase phase);
...
uvm_config_db #(uvm_object_wrapper)::set(this,"*.seqr.main_phase","default_sequence",transaction_sequence::get_type());
...
endfunciton
endclass
  默认sequence在main_phase阶段执⾏,此时也可将null赋给default sequence,不产⽣数据。
3.2.配置sequence——get_full_name() / m_sequencer
通过get_full_name( )获取配置的路径名称,可以有效防⽌不同的sequence中有相同变量进⾏配置时产⽣的冲突。
get_full_name()在sequence中被调⽤时,打印的路径为:uvm_v.agt.seqr.seq;
需要说明的是,当sequence在virtual sequence中被启动,调⽤的get_full_name()⽅法打印的路径结果:uvm_test_top.v_seqr.*,这是由于virtual sequence不遵循UVM树的路径层次;
class tr_sequence extends base_sequence;//2.在底层组件捕获sequence配置
int item_count =10;
...
virtual task pre_start();
...
uvm_config_db #(int)::get(null,"_full_name()","item_count", item_count);//本地变量item_count = 20,配置成功//uvm_config_db #(int)::get(null, _full_name(), "item_count", item_count);  get_full_name() 不添加引号
//uvm_config_db #(int)::get(m_sequencer, “”, "item_count", item_count);  m_sequencer 指定路径
endfunciton
endclass
class test_20_items extends test_base;//1.在测试⽤例中启动sequence配置
...
function void build_phase(uvm_phase phase);
...
uvm_config_db #(int)::set(this,"env.agt.seqr.*","item_count",20);//item_count = 20 ,启动配置赋值
endfunciton
endclass
3.3.配置sequence——get_sequncer()
通过get_sequencer( )获取配置字段的sequencer,可以为sequencer下的所有sequence中的相同变量同时提供配置。class tr_sequence extends base_sequence;//2.在底层组件捕获sequence配置
int item_count =10;
...
virtual task pre_start();
...
uvm_config_db #(int)::_sequencer(),"","item_count",item_count);//本地变量item_count = 20,配置成功
endfunciton
endclass
class test_20_items extends test_base;//1.在测试⽤例中启动sequence配置
...
function void build_phase(uvm_phase phase);
...
uvm_config_db #(int)::set(this,"env.agt.seqr.*","item_count",20);//item_count = 20 ,启动配置赋值
endfunciton
endclass

本文发布于:2024-09-22 10:05:50,感谢您对本站的认可!

本文链接:https://www.17tex.com/xueshu/648619.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:数据   配置   对象   启动   需要
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议