文章目录
前言
2023.2.25开启学习的一天~
一、phase机制
1、phase分类
(1)function phase
:除run_phase以外的其他phase
task phase
:消耗仿真时间($time打印出来的时间,区别于CPU的运行时间),run_phase
。
(2)run_phase和其他12个小的phase并行运行
这12个小的phase成为run-time phase
(动态运行的phase),通过细分实现了对DUT的精确控制。
主要:reset、configure、main、shutdown四个,模拟DUT的正常工作方式
reset
:复位、初始化操作等
configure
:进行DUT的配置
main
:DUT的运行
shutdown
:DUT断电操作等
2、phase的执行顺序
这里说的是空间顺序,上面说的是时间顺序,时间顺序就是按照自上至下。
(1)自上至下:build_phase
。
build_phase是做实例化工作的,driver和monitor都是agent的成员变量,所以它们的实例化都是在agent的build_phase中执行。如果在agent的build_phase之前执行driver的build_phase,此时driver还根本没有实例化,所以调用driver.build_phase只会引发错误。
如果是是uvm_object
的实例化,则可以在任何phase完成,当然也包括build_phase。
(2)自下至上:除build_phase之外的其他function phase
上下关系的component
:按照自下至上运行
同级关系的component(兄弟关系)
:按照实例化名字的字典序
。不是看谁先被实例化,而是看实例化名字的字母顺序,这种顺序是UVM1.1d代码定义的,如果要改变也是可以修改代码的。
叔侄关系的component(例如scoreboard和agent里面的driver)
:UVM按照深度优先
的原则,agent的build_phase先执行,再去执行driver、monitor、sequencer的build_phase;执行完毕再去执行scoreboard的build_phase。(也就是先执行完agent这个uvm树的小分支,再去执行同级的uvm树杈)
(3)自下至上:run_phase
这种task phase消耗时间,它不是等下面的phase全部运行完再执行上面的phase,而是通过fork..join_none
的形式全部启动,准确的说是自下至上顺序全部启动,然后再同时运行。
这张图的意思是不同component的phase执行完毕的时间不一定会相等,先完成的component要等待其他component的phase执行完毕后再一起进入下一个phase,保证系统的phase是按照时间先后顺序进行的。
此外,同一个component的run_phase
和post_shutdown_phase
要并行都全部完成
后才会一起进入extract_phase。
3、super.phase
在build_phase中一般会出现super.build_phase()
,如果不用configdb这个功能,可以不加super.build_phase()。
其他phase一般没啥功能,可以不加super。
4、phase之间可以相互跳转(高级功能)
5、phase的调试
命令行参数 UVM_PHASE_TRACE
来调试
6、超时退出
(1)在base_test的build_phase
第一个参数是设置的退出时间,第二个参数是是否允许后面的settime设置进行覆盖
uvm_top.set_timeout(500ns,0);
(2)命令行参数设置,一般默认是9200s
+ UVM_TIMEOUT = "300ns YES"
7、验证平台的运行(重要)
理解0时刻前、0时刻、0时刻后三个阶段
二、objection机制
1、objection和task phase
(1)在进入到某一phase时,UVM会收集此phase提出的所有objection,并且实时监测所有objection是否已经被撤销了,当发现所有都已经撤销后,那么就会关闭此phase,开始进入下一个phase。当所有的phase都执行完毕后,就会调用$finish
来将整个的验证平台关掉。
如果此phase没有提起任何的objection,那么会直接跳到下一个phase。
(2)run-time phase
:12个动态运行的phase,如果想要执行一些消耗时间的代码,就需要在此phase下的任意一个component里面至少提起一次objection。
(3)run_phase有两种情况可以运行代码:
其他动态运行的phase有objection被提起
:run_phase的运行时间受其控制
run_phase有objection被提起
:运行时间由自己决定。此时如果其他动态运行的phase没有objection的话也就不会执行代码了。
2、phase参数
目的:解决何时结束仿真的问题
(也可以放在function phase里面,不会报错,但主要是面对task phase
)
好处:在任意component的main_phase中都可以raise_objection
3、objection的最佳位置
driver和monitor一般都是无限循环,进去了就退不出来了,所以一般不放在这
(1)scoreboard
scoreboard的main_phase也是一个无限循环。如果要在scoreboard中控制objection,则需要去除这个无限循环,通过config_db::set的方式设置收集到的transaction的数量pkt_num,当收集到足够数量的transaction后跳出循环。
task my_scoreboard::main_phase(uvm_phase phase);
phase.raise_objection(this);
fork
while(1) begin
exp_port.get(get_expect);
expect_queue.push_back(get_expect);
end
for(int i=0;i<pkt_num;i++) begin
act_port.get(get_actual);
...
end
join_any //之前这里是join,现在第二个for循环结束后,就会退出
phase.drop_objection(this);
endtask
(2)在sequence中提起sequencer的objection,当sequence完成后,再撤销此objection,推荐该方式。
在sequence中raise objection,再在testcase的build_phase
里面去设置default sequence
class case0_sequence extends uvm_sequence #(my_transaction);
my_transaction m_trans;
function new(string name= "case0_sequence");
super.new(name);
endfunction
virtual task body();
if(starting_phase != null)
starting_phase.raise_objection(this);
repeat (10) begin
`uvm_do(m_trans)
end
#100; //等待sequence完全被接收
if(starting_phase != null)
starting_phase.drop_objection(this);
endtask
`uvm_object_utils(case0_sequence)
endclass
class my_case0 extends base_test;
function new(string name = "my_case0", uvm_component parent = null);
super.new(name,parent);
endfunction
extern virtual function void build_phase(uvm_phase phase);
`uvm_component_utils(my_case0)
endclass
function void my_case0::build_phase(uvm_phase phase);
super.build_phase(phase);
uvm_config_db#(uvm_object_wrapper)::set(this,
"env.i_agt.sqr.main_phase",
"default_sequence",
case0_sequence::type_id::get());
endfunction
4、set_drain_time
一般来说,发送完sequence之后不会立马drop objection,因为dut接收处理这些sequence需要一定的时间,所以在上述代码中设置了100ns延时,但是这样在每个sequence立马去设置延时比较麻烦,还得估计这个sequence接收完毕的时间。
phase_done
:uvm_phase里面预定义的成员变量,是uvm_objection类型
一个phase对应一个drain_time,不是共用的。
一般在drop_objection之后,会去看有没有设置这个时间,有就延时,没有就下一个phase。
task base_test::main_phase(uvm_phase phase)
phase.phase_done.set_drain_time(this,200);
endtask
5、objection的调试
命令行参数:+UVM_OBJECTION_TRACE
6、domain
(1)用于组织不同组件,比如希望DUT中的两个部分独立运行,隔开了两个时钟域,但是仅限于12个动态运行的phase
,其他的phase还是同步的(如run_phase和其他function phase)