3 6 、 生成 sequence 时, early randomization 和 late randomization 有什么区别?
在early randomization中,先调用randomize()方法对sequence对象进行随机化,然后再使用start_item()来请求对sequencer的访问,如下例所示:
task body()
assert(req.randomize());
start_item(req);
//Can consume time based on sequencer arbitration
finish_item(req);
endtask
在 late randomization 中,先调用 start_item (),直到从 sequencer 授予仲裁,然后在将事务发送到 sequencer/driver 之前调用 randomize 。
task body()
start_item(req);
//Can consume time based on sequencer arbitration
assert(req.randomize());
finish_item(req);
endtask
37、什么是subsequence?
从sequence的body()任务中,如果调用了另一个sequence的start(),则通常将其称为subsequence。
38、get_next_item()和try_next_item()有什么区别
get_next_item() 是一个阻塞调用,直到存在可供驱动的sequence item为止,并返回指向sequence item的指针。 try_next_item() 是非阻塞调用,如果没有可供驱动的sequence item,则返回空指针。
39、UVM driver类中的get_next_item()和get()方法之间有什么区别?
get_next_item() 是一个阻塞调用,用于从sequencer FIFO获取sequence item。driver驱动完sequence item后需要先使用item_done()完成握手,然后再使用get_next_item()请求新的sequence item。
get() 也是一个阻塞调用,同样用于从sequencer FIFO获取sequence item。但是在使用get()时,由于get()方法隐式完成了握手,因此无需显式调用item_done()。
40、driver中带和不带有参数的item_done()调用有什么区别?
item_done()方法是driver中的一种非阻塞方法,用于在get_next_item()或try_next_item()成功之后与sequencer完成握手。如果不需要发回响应,则调用不带参数的item_done()。如果需要发回响应,则将指向sequence_item的指针作为item_done()参数。
41、以下哪个driver类方法是阻塞调用哪些是非阻塞调用?
-
get()
-
get_next_item()
-
item_done()
-
put()
-
try_next_item()
-
peek()
get(),get_next_item(), peek() 是阻塞调用;
try_next_item(),item_done()和put() 非阻塞调用
42、在UVM driver类中,以下哪个代码是错误的?
1)
function get_drive_req();
forever begin
req = get();
req = get();
end
endfunction
2)
function get_drive_req();
forever begin
req =get_next_item();
req =get_next_item();
item_done();
end
endfunction
3)
function get_drive_req();
forever begin
req = peek();
req = peek();
item_done();
req = get();
end
endfunction
2)错误,因为不能在调用item_done()之前两次调用get_next_item(), 无法完成与sequencer的握手。
43、如何停止在sequencer上运行的所有sequences?
sequencer具有 stop_sequences() 方法,可用于停止所有sequences。但是此方法不检查driver当前是否正在驱动任何sequence_items,如果driver调用item_done()或put(),则可能会出现Fatal Error,因为sequences指针可能无效。
44、调用sequence.print()方法时,应该调用sequence中的哪个方法?
convert2string(): 建议实现此函数,该函数返回对象的字符串形式(其数据成员的值),这对于将调试信息打印到仿真器界面或日志文件很有用。
45、找出UVM sequence的以下部分代码中的任何潜在问题
task body();
seq_item_c req;
start_item(req);
#10 ns;
assert(req.randomize());
finish_item(req);
endtask
应该避免在 start_item 和 finish_item 之间添加延迟。 start_item 返回后,该 sequence 将赢得仲裁并可以访问 sequencer/driver 。 从那时起直到 finish_item 的任何延迟都将使得 sequencer/driver 暂停 ,不能被其他 sequence 使用 。
46、什么是virtual sequence,在哪里使用?有什么好处?
virtual sequence是控制多个sequencers中激励生成的sequence。由于sequences,sequencers和drivers都只针对单个接口,几乎所有测试平台都需要virtual sequence来 协调 不同接口之间的激励。
Virtual sequences在子系统或系统级测试平台上也很有用,可以使模块级的sequence协调地运行。
47、使用new()和create()方法创建对象有什么区别?
UVM推荐使用内置方法 :: type_id :: create() ,而不是直接调用构造函数new()创建组件或事务对象。
create方法在内部调用factory机制以查找所请求创建的类型,然后调用构造函数new()以实际创建一个对象而 无需 更改 任何代码 。
48、我们如何注册uvm_component类和uvm_sequence类?
uvm_sequence类使用 uvm_object_utils() 宏在factory中注册,并将类名作为参数传递:
class test_seq_c extends uvm_sequence;
`uvm_object_utils(test_seq_c)
uvm_component类使用 uvm_component_utils() 宏在factory中注册,并将类名作为参数传递:
class test_driver_c extends uvm_component;
`uvm_component_utils(test_driver_c)
49、我们为什么要在factory中注册类?
factory是UVM中使用的 特殊查找表 ,用于创建component 或者transaction类型的对象。使用factory创建对象的好处是,测试平台可以在 运行仿真时 决定创建哪种类型的对象。
一个类可以用另一个派生类替换,而无需更改任何代码。 为确保此功能,建议所有类都在factory中注册。 如果不向factory注册类,则将无法使用factory方法:: type_id :: create()构造对象。
50、instance override和type override之间有什么区别?
顾名思义, type override 适用于该组件类型所在层次结构中的所有实例, instance override 仅覆盖类的特定实例,即该组件在UVM组件层次结构中的位置。 由于只有UVM 组件类具有层次结构,因此只有组件类能进行instance override,而sequen ces (UVM objects)只能进行type overridden。
51 、什么是 objections 概念,用在什么地方?
uvm_objection类提供了一种在多个components和sequences之间共享计数器的方法。每个component/sequence可能会异步地“raise”和“drop” objections,这会增加或减少计数值。当计数值达到零(从非零值开始)时,则称发生“all dropped”条件。
objection机制最常用于UVM phase机制中 ,以协调每个run-time phase的结束。在用户进程开始时raises an objection,在用户进程结束 时 drops the objection。当一个phase中的所有用户进程都drops objection时,该phase的objections计数将变为零。这种“all dropped” 条件向phase机制表明,每个用户进程都同意结束该phase。
下面是一个示例说明如何在sequencer(my_sequencer)上启动sequence(my_test_sequence),并在sequence执行完成之后drops objection。
task main_phase( uvm_phase phase);
phase.raise_objection(this);
my_test_sequence.start(my_sequencer);
phase.drop_objection(this );
endtask
52、我们如何在UVM中实现仿真超时机制(simulation timeout mechanism)?
如果由于某些错误导致超出最大仿真时间, 仿真超时机制 可以帮助停止仿真。 在UVM中有一个很方便的函数 set_global_timeout(timeout) 用于将 uvm_top.phase_timeout 变量设置为超时值。 如果run()phase 在该超时值之前没有结束,则仿真将停止并报告错误。
module test;
initial begin
set_global_timeout(1000ns);
end
initial begin
run_test();
end
endmodule
53、UVM方法学中phase的概念是什么?
不同于基于module的验证测试平台(所有module静态地存在于层次结构中),基于class的验证测试平台需要 管理不同对象的创建和其方法的执行 。
Phase使得验证平台具有一致的执行流程。测试的执行可以分为以下任务-配置**( configuration ),创建验证平台组件( creation ),运行激励( stimulus )和测试检查结束( end of test checks )**。
54、UVM组件有哪些不同的phases?UVM run_phase()的subphases是什么?
UVM使用标准phases来排序仿真过程中的主要步骤,有三组phases,按以下顺序执行。
1、Build phases –在构建phases 配置和构建测试平台,它具有以下子phases ,这些子phases 都在uvm_component基类中作为virtual方法实现。
1)build_phase()
2)connect_phase()
3)end_of_elaboration()
2、Run time phases – 这些phases 会消耗时间,这是大多数测试执行的地方。
-
start_of_simulation()
-
run_phase(),进一步分为12个子phases:
-
pre_reset
-
reset
-
post_reset
-
pre_configure
-
configure
-
post_configure
-
pre_main
-
main
-
post_main
-
pre_shutdown
-
shutdown
-
post_shutdown
3、Clean up phase – 该清理阶段在测试结束后执行,用于收集并报告测试的结果和统计信息,包括以下子phase:
1)extract()
-
check()
-
report()
-
final()
55、uvm_component类中的phase_ready_to_end()方法有什么用途?
phase_ready_to_end(uvm_phase phase) 是component类中的 回调(callback) 方法,当该phase的所有objections均被drop之后调用该方法。component类可以使用此回调方法来定义phase即将结束时需要执行的功能。
如果某个组件希望在objections被drop之后将phase结束延迟到某个条件,可以使用此回调方法来完成。