附:
IC面试常考题
以下内容搬运自 数字芯片实验室 公众号,安利一波良心博主
(本人已为知识付费,只是搬运学习用作整理,希望大家也去付费支持一波)
原博文链接
- 1、什么是UVM?它的优势是什么?
- 2、uvm_component和uvm_object有什么区别?
- 3、为什么需要phase机制,不同的phase有什么区别?
- 4、哪些phase是top-down phase、bottom-up phase和parallel phase?
- 5、为什么build_phase是top-down phase,而connect_phase是bottom-up phase?
- 6、uvm phase仿真是怎么开始启动的?
- 7、VCS中通过什么方式执行对应的test case?
- 8、uvm_config_db和uvm_resource_db有什么区别?
- 9、什么是factory automation?
- 10、当前类的super class是什么?
- 11、什么是事物级建模(Transaction Level Modelling)?
- 12、什么是TLM ports和exports?
- 13、什么是TLM FIFOs?
- 14、TLM上的get()和peek()操作之间有什么区别?
- 15、TLM fifo上的get()和try_get()操作之间有什么区别?
- 16、analysisports和TLM ports之间有什么区别?analysisFIFOs和TLM FIFO有什么区别?analysis ports/ FIFO在哪里使用?
- 17、sequence和sequence item有什么区别?
- 18、uvm_transaction和uvm_sequence_item有什么区别?
- 19、copy()、clone()和create()方法之间有什么区别?
- 20、解释UVM方法学中的Agent概念。
- 21、get_name()和get_full_name()有什么区别
- 22、ACTIVE agent与PASSIVE agent有何不同?
- 23、Agent如何配置为“ACTIVE”或“PASSIVE”?
- 24、什么是driver和sequencer,为什么需要它们?
- 25、UVM中的monitor和scoreboard有什么区别?
- 26、哪个方法可以激活UVM验证平台,如何调用它?
- 27、运行sequence需要什么步骤?
- 28、解释sequencer和driver之间的握手协议?
- 29、sequence中的pre_body()和post_body()函数是什么?它们总是被调用么?
- 30、Sequencer有哪些不同的仲裁机制可用于?
- 31、在sequencer上启动sequence时,如何指定sequence的优先级?
- 32、sequence如何才能独占访问sequencer?
- 33、流水线和非流水线sequence-driver模式有什么区别?
- 34、我们如何确保在driver驱动多个sequences 时,则driver的响应会发送给正确的sequences ?
- 35、什么是m_sequencer句柄?
- 36、什么是p_sequencer句柄,与m_sequencer相比有什么不同?
- 36、生成sequence时,early randomization和late randomization有什么区别?
- 37、什么是subsequence?
- 38、get_next_item()和try_next_item()有什么区别
- 39、UVM driver类中的get_next_item()和get()方法之间有什么区别?
- 40、driver中带和不带有参数的item_done()调用有什么区别?
- 41、以下哪个driver类方法是阻塞调用哪些是非阻塞调用?
- 42、在UVM driver类中,以下哪个代码是错误的?
- 43、如何停止在sequencer上运行的所有sequences?
- 44、调用sequence.print()方法时,应该调用sequence中的哪个方法?
- 45、找出UVM sequence的以下部分代码中的任何潜在问题
- 46、什么是virtual sequence,在哪里使用?有什么好处?
- 47、使用new()和create()方法创建对象有什么区别?
- 48、我们如何注册uvm component类和uvm sequence类?
- 49、我们为什么要在factory中注册类?
- 50、instance override和type override之间有什么区别?
- 51、什么是objections概念,用在什么地方?
- 52、我们如何在UVM中实现仿真超时机制(simulation timeout mechanism)?
- 53、UVM方法学中phase的概念是什么?
- 54、UVM组件有哪些不同的phases?UVM run-phase()的subphases是什么?
- 55、uvm——component类中的phase _ready_to_end()方法有什么用途?
- 56、什么是uvm_config_db?它的作用是什么?
- 57、我们如何使用uvm_config_db的get()和set()方法?
- 58、验证平台中较低层次结构的组件是否可以使用get/setconfig方法将句柄传递给较高层次结构中的组件?
- 59、在UVM方法学中仿真如何结束?
- 60、什么是UVM RAL(UVM Register Abstraction Layer)?
- 61、什么是UVM Call back?
- 62、什么是uvm root类?
- 63、uvm_test的父类是什么?
- 64、为异步Fifo编写uvm_sequence_item
- 65、UVM是否独立于SystemVerilog?
- 66、什么是virtual sequence和virtual sequencer?
- 67、uvm_do和`uvm_send有什么区别?
- 68、我们可以在UVM中自定义phase么?
- 69、RAL backdoor和frontdoor访问有什么区别?
- 70、set_config_*和uvm_config_db有什么不同?
- 71、如何在component或者sequence中访问DUT中的信号?
- 72、如何调试UVM中config db的名称或者路径不匹配的问题?
- 73、如何连接monitor和scoreboard,driver和sequencer?
- 74、类中的静态属性和动态属性有什么区别?
- 75、sequence通常包含什么?
- 76、实现AHB-Lite driver的伪代码?
- 78、什么是UVM drain time?
- 79、仿真器需要设置UVM HOME才能仿真uvm test么?
- 80、什么是p-sequencer句柄,与m_sequencer相比有什么不同?
1、什么是UVM?它的优势是什么?
**UVM(Universal Verification Methodology)**是一个标准化的用于验证设计的方法学。其优势包括:
重用性、VIP即插即用、通用性、独立于仿真器、支持CDV(coverage driven verification)、支持CRV(constraint random verification)等等
2、uvm_component和uvm_object有什么区别?
- uvm_component: 在build_phase之后就一直存在于整个仿真周期。通过interface连接到DUT或者通过TLM port连接到其他uvm_component。通过configure机制和phase机制控制uvm_component的层次结构和仿真行为。
- uvm_object: 从一个uvm_component生成,然后传递到另一个uvm_component之后就会消失。不会连接到任何组件,也不存在phase机制
3、为什么需要phase机制,不同的phase有什么区别?
- hase机制用来控制和同步不同uvm_component的仿真行为。
- 可以根据是否消耗仿真时间区分为function phase和task phase
4、哪些phase是top-down phase、bottom-up phase和parallel phase?
build_phase是top-down phase,run phase等task phase是 parallel phase, 其他都是bottom-up phase。
5、为什么build_phase是top-down phase,而connect_phase是bottom-up phase?
- build_phase需要验证平台根据高层次组件的配置来决定建立低层次的组件,所以其是top-down phase。
- connect_phase需要在build_phase之后完成验证组件之间TLM连接
6、uvm phase仿真是怎么开始启动的?
通过在顶层调用run_test,run_test任务会首先创建test top,然后调用所有的phase,开始仿真。
7、VCS中通过什么方式执行对应的test case?
在顶层调用run_test(),在仿真选项中使用
+UVM_TESTNAME = testname
8、uvm_config_db和uvm_resource_db有什么区别?
- uvm_config_db和uvm_resource_db都是参数化的类,用于配置验证组件中不同类型的参数。
- 相比于uvm_resource_db,uvm_config_db增加了层次关系。
- 对于最后配置的参数值,uvm_resource_db是“last write wins”, uvm_config_db是“parent wins”
9、什么是factory automation?
factory是一种在验证环境中实例化组件或生成激励时提供更大灵活性的机制。factory机制允许在不修改原始源代码的条件下覆盖现有验证代码创建的对象类型。
10、当前类的super class是什么?
super class是当前类所**“扩展(extends)”**的类。例如,my_test的super class是uvm_test
11、什么是事物级建模(Transaction Level Modelling)?
- 事务级别建模(TLM)是一种在较高抽象级别上对系统设计或模块设计进行建模的方法,抽象出所有底层实现细节。
- 这是验证方法学中用于提高模块化和重用性的关键概念之一。即使DUT的实际接口由信号级别表示,但大多数验证任务(如生成激励,功能检查,收集覆盖率数据等)都可以在事务级别上更好地完成。这有助于验证组件在项目内部和项目之间重用和维护。
12、什么是TLM ports和exports?
在事务级别建模中,不同的组件或模块使用事务对象进行通信。TLM port定义了用于连接的一组方法(API),而这些方法的具体实现称为TLM exports。
TLM port和export之间的连接建立了两个组件之间的通信机制。producer可以创建事务并将其“put”到TLM端口,而“put”方法实现(也称为TLM export)将在consumer中读取producer创建的事务,从而建立通信渠道。
13、什么是TLM FIFOs?
如果producer组件和consumer组件需要独立运行,则可以使用TLM FIFO进行事务通信。在这种情况下,producer组件生成事务并将其“puts”到FIFO,而consumer组件一次从FIFO获取一个事务并对其进行处理。
14、TLM上的get()和peek()操作之间有什么区别?
- get()操作将从TLM FIFO返回一个事务(如果存在的话),并且还会从FIFO中删除该事务。如果FIFO中没有可用的事务,它将阻塞并等待,直到FIFO至少有一个事务。
- peek()操作将从TLM FIFO返回事务(如果存在的话),而无需从FIFO中删除该事务。这也是一个阻塞调用,如果FIFO没有可用事务,它将等待。
15、TLM fifo上的get()和try_get()操作之间有什么区别?
- get() 是从TLM FIFO获取事务的阻塞调用。因此如果FIFO中没有可用的事务,则任务get()将等待。
- try_get() 是一个非阻塞调用,即使FIFO中没有可用的事务,也会立即返回。try_get()的返回值指示是否返回有效事务项。
16、analysisports和TLM ports之间有什么区别?analysisFIFOs和TLM FIFO有什么区别?analysis ports/ FIFO在哪里使用?
- TLM ports/ FIFO用于两个组件之间的事务级别通信,这两个组件具有使用put/get方法建立的通信通道。Analysis ports/FIFOs是另一种事务通信通道,用于组件将事务广播到多个组件。
- TLM ports / FIFO用于driver和sequencer之间的连接,而analysis ports/FIFOs用于monitor将接收的事务广播到scoreboard或reference model
17、sequence和sequence item有什么区别?
sequence item是一个对象,其建模了两个验证组件之间传输的信息(有时也可以称为事务(transaction))。例如:读操作和写操作中的地址和数据信息。
sequence是由driver驱动的sequence item序列模式,由其body()方法实现。例如:连续读取10次事务。
18、uvm_transaction和uvm_sequence_item有什么区别?
- uvm_transaction是从uvm_object派生的用于对事务进行建模的基类。
- sequence item是在uvm_transaction的基础上还添加了一些其他信息的类,例如:sequence id。建议使用uvm_sequence_item实现基于sequence的激励。
19、copy()、clone()和create()方法之间有什么区别?
- create()方法用于构造一个对象。
- copy()方法用于将一个对象复制到另一个对象。
- clone()方法同时完成对象的创建和复制。
20、解释UVM方法学中的Agent概念。
UVM agent集合了围绕DUT的其他uvm_components。大多数DUT具有多个interfaces,并且一个Agent用于组合driver、sequencer和monitor。使用此层次结构有助于在不同验证环境和项目之间重用Agent。
21、get_name()和get_full_name()有什么区别
- get_name() 函数 返回对象的名称,该对象的名称由new构造函数或set_name()方法提供。
- get_full_name() 返回对象的完整层次结构名称。对于uvm_components,这在打印语句中使用时很有用,因为它显示了组件的完整层次结构。对于没有层次结构的sequence或配置对象,与get_name()打印相同的值
22、ACTIVE agent与PASSIVE agent有何不同?
ACTIVE agent是可以在其操作的接口上生成激励,其包含driver和sequencer。
PASSIVE agent不生成激励,只能监视接口,这意味着在PASSIVE agent中将不会创建driver和sequencer。
23、Agent如何配置为“ACTIVE”或“PASSIVE”?
-
UVM agents具有类型为uvm_active_passive_enum的变量,该变量定义agents是否是active (UVM_ACTIVE)(构建了sequencer和driver)或者passive(UVM_PASSIVE) (不构建sequencer和driver)。
-
此参数默认情况下设置为UVM_ACTIVE,在environment类中创建agents时,可以使用**set_config_int()**进行更改。然后,agent的build phase阶段应具有以下代码以选择性地构建driver和sequencer。
function void build_phase(uvm_phase phase);
if(m_cfg.active == UVM_ACTIVE) begin
//create driver, sequencer
end
endfunction
24、什么是driver和sequencer,为什么需要它们?
-
Driver是根据接口协议将事务转换为一组信号级切换的组件。Sequencer是一个将事务(sequence items)从sequence发送到Driver,并将Driver的响应反馈给sequence的组件。
-
sequencer也会对同时尝试访问Driver以激励设计接口的多个sequences进行仲裁。sequence和sequencer在事务级抽象,Driver在信号级对设计接口进行驱动,即单一设计模式。
25、UVM中的monitor和scoreboard有什么区别?
monitor是一个监测引脚级别的信号活动并将其转换为事务或sequence_items的组件。monitor还通过analysis port将这些事务发送到其他组件。
scoreboard用于检查DUT的行为是否正确。
26、哪个方法可以激活UVM验证平台,如何调用它?
**run_test()方法(静态方法)**用来激活UVM验证平台。通常在顶层的“ initial begin…end”块中调用,并且它使用一个参数指定要运行的test case。run_test()方法在build_phase()中执行test class的构造函数,并进一步构造层次化的Env / Agent / Driver / Sequencer对象。
27、运行sequence需要什么步骤?
启动sequence需要执行三个步骤,如下所示:
- 创建一个序列。使用工厂创建方法创建一个序列:
my_sequence_c seq;
seq = my_sequence_c ::type_id :: create(“ my_seq”)
- 配置或随机化序列。
seq.randomize()
- 开始一个sequence。使用sequence.start()方法启动序列。start方法需要输入一个指向sequencer的参数。关于sequence的启动,UVM进一步做了封装。
28、解释sequencer和driver之间的握手协议?
UVM将sequence item从sequence传输到driver并收集来自driver的响应。
在sequence端:
- **start_item():**请求sequencer访问driver
- **finish_item():**使driver接收sequence item,这是阻塞调用,在driver调用item_done()方法后才返回。
在driver端:
- **get_next_item(req):**这是driver中的一个阻塞方法,直到接收到sequence item,driver可以将其转换为引脚级协议信号。
- **item_done(req):**向sequencer发出信号,表明它可以接受新的sequence请求,使得sequence解除对finish_item()方法的阻塞。
29、sequence中的pre_body()和post_body()函数是什么?它们总是被调用么?
- **pre_body()是sequence类中的方法,该方法在body()方法之前调用,然后调用post_body()**方法。
- uvm_sequence:: start()有一个可选参数,如果将其设置为0,将不调用这些方法。以下是sequence中start()方法的参数:
virtual task start (
uvm_sequencer_base sequencer, // Pointer to sequencer
uvm_sequence_base parent_sequencer = null, // parent sequencer
integer this_priority = 100, // Priority on the sequencer
bit call_pre_post = 1); // pre_body and post_body called
30、Sequencer有哪些不同的仲裁机制可用于?
多个sequences可以同时连接到单个接口的driver上。Sequencer支持仲裁机制,以确保在任何时间点只有一个sequences可以访问driver。哪个sequence_item可以发送取决于用户选择的Sequencer仲裁算法。
在UVM中实现了五种内置的Sequencer仲裁机制,也可以实现用户自定义的仲裁算法。Sequencer有一个set_arbitration()的方法,调用该方法可以选择使用哪种算法进行仲裁。可以选择的六种算法如下:
- SEQ_ARB_FIFO(Default if none specified)
- SEQ_ARB_WEIGHTED
- SEQ_ARB_RANDOM
- SEQ_ARB_STRICT_FIFO
- SEQ_ARB_STRICT_RANDOM
- SEQ_ARB_USER
31、在sequencer上启动sequence时,如何指定sequence的优先级?
通过将优先级相对值参数传递给sequence的start()方法来指定优先级,第三个参数指定优先级。
seq_1.start(m_sequencer, this, 500); //Highest priority
seq_2.start(m_sequencer, this, 300); //Next Highest priority
seq_3.start(m_sequencer, this, 100); //Lowest priority among threesequences
32、sequence如何才能独占访问sequencer?
当在sequencer上运行多个sequence时,sequencer对sequence中的每个sequence item 的访问权限进行仲裁。有时一个sequence可能希望独占访问sequencer,直到将其所有的sequence item都发送完毕为止(例如:你希望施加一个定向的激励,在此过程中不被打断)。
有两种机制允许sequence获得对sequencer的独占访问权。
-
lock()和unlock( ): sequence可以调用sequencer的lock方法,以通过sequencer的仲裁机制获得对driver的独占访问权限。如果还有其他标记为更高优先级的sequences,则此sequences需要等待。授予lock权限后,其他sequences将无法访问driver,直到该sequences在sequencer上调用unlock()方法。lock方法是阻塞调用,直到获得lock权限才返回。
-
grab()和ungrab():grab()方法类似于lock()方法,用于申请独占访问。grab()和lock()之间的区别在于,调用grab()时将立即生效,不考虑其他sequences的优先级,除非已经存在sequences调用了lock()或grab()。
33、流水线和非流水线sequence-driver模式有什么区别?
根据设计接口如何激励,可以分为两种sequence-driver模式:
- 非流水线模式:如果driver一次仅对驱动一个事务,则称为非流水线模型。在这种情况下,sequence可以将一个事务发送给driver,并且driver可能需要几个周期(基于接口协议)才能完成驱动该事务。只有在该事务完成驱动之后,driver才会接受sequencer的新事务
class nonpipe_driver extends uvm_driver #(req_c);
task run_phase(uvm_phase phase);
req_c req;
forever begin
get_next_item(req); // Item from sequence via sequencer
// drive request to DUT which can take more clocks
// Sequence is blocked to send new items til then
item_done(); // ** Unblocks finish_item() in sequence
end
endtask: run_phase
endclass: nonpipe_driver
- 流水线模式: 如果driver一次驱动多个事务,则称为流水线模式。在这种情况下,sequence可以继续向driver持续发送新事务,而无需等待driver完成之前事务的驱动。在这种情况下,对于从该sequence发送的每个事务,driver中都会有一个单独的进程来驱动该事务,而不用等到它完成上一次事务的驱动之后再接受新事务。如果我们不需要等待设计的响应,则此模式很有用。
class pipeline_driver extends uvm_driver #(req_c);
task run_phase(uvm_phase phase);
req_c req;
forever begin
get_next_item(req);// Item from sequence via sequencer
fork
begin
//drive request toDUT which can take more clocks
//separate threadthat doesn’t block sequence
//driver can acceptmore items without waiting
end
join_none
item_done(); // **Unblocks finish_item() in sequence
end
endtask: run_phase
endclass:pipeline_driver
34、我们如何确保在driver驱动多个sequences 时,则driver的响应会发送给正确的sequences ?
- 如果从driver返回了几个sequences 之一的响应,则sequencer利用sequence中的sequence ID字段将响应返回给正确的sequence。driver中的响应处理代码应调用set_id_info(),以确保任何响应都具有与其原始请求相同的sequence ID。下面的代码driver的参考伪代码说明上述问题。
class my_driver extends uvm_driver;
//function that gets item from sequence port and
//drives response back
function drive_and_send_response();
forever begin
seq_item_port.get(req_item);
//function that takes req_item and drives pins
drive_req(req_item);
//create a new response item
rsp_item = new();
//some function that monitors response signals from dut
rsp_item.data = m_vif.get_data();
//copy id from req back to response
rsp.set_id_info(req_item);
//write response on rsp port
rsp_port.write(rsp_item);
end
endfunction
endclass
35、什么是m_sequencer句柄?
启动sequence时,它始终与启动sequencer相关联。m_sequencer句柄包含该sequencer的引用。使用此句柄,sequence可以访问UVM组件层次结构中的信息
36、什么是p_sequencer句柄,与m_sequencer相比有什么不同?
-
与sequencer,driver或monitor等UVM组件在整个仿真周期内都存在不同,UVM sequence是生命周期有限的对象。因此,如果在sequence从测试平台层次结构(组件层次结构)访问任何成员或句柄,则需要运行该sequence的sequencer的句柄。
-
m_sequencer是uvm_sequencer_base类型的句柄,默认情况下在uvm_sequence中可用。但是要访问在真实的sequencer,我们需要对m_sequencer进行转换(typecast),通常称为p_sequencer。下面是一个简单的示例,其中sequence要访问clock monitor组件的句柄。
class test_sequence_c extends uvm_sequence;
test_sequencer_c p_sequencer;
clock_monitor_c my_clock_monitor;
task pre_body();
if(!$cast(p_sequencer, m_sequencer)) begin
`uvm_fatal(“Sequencer Type Mismatch:”, ” Wrong Sequencer”);
end
my_clock_monitor = p_sequencer.clk_monitor;
endtask
endclass
class test_Sequencer_c extends uvm_sequencer;
clock_monitor_c clk_monitor;
endclass
36、生成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,而sequences(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 testsequence),并在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(100ons);
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,按以下顺序执行。
- Build Phases-这些子phases都在uvm_component基类中作为virtual方法实现。
1)build_phase()
2)connect_phase()
3)end of elaboration().
- Run time phases-这些phases会消耗时间,这是大多数测试执行的地方。
1. start_of_simulation()
2. run-phase(),进一步分为12个子phases:
1. pre_reset
2. reset
3. post reset
4. pre_configure
5. configure
6. post_configure
7. pre_main
8. main
9. post_main
10. pre _shutdown
11. shutdown
12. post_shutdown
- Clean_up_phase-该清理阶段在测试结束后执行,用于收集并报告测试的结果和统计信息,包括以下子phase:
1)extract()
2)check()
3)report()
4)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结束延迟到某个条件,可以使用此回调方法来完成
56、什么是uvm_config_db?它的作用是什么?
- UVM configure机制使用uvm_config_db配置数据支持在不同的测试平台组件之间共享配置参数。任何测试平台组件都可以配置参数,其他组件可以从配置数据库访问这些参数,而无需知道其在层次结构中的位置。
- 例如,测试平台顶层可以通过uvm_config_db存储virtual interface句柄。然后任何uvm_driver或uvm_monitor组件都可以查询uvm config_db以获取此virtual_interface的句柄,并将其用于获取实际接口信号。
57、我们如何使用uvm_config_db的get()和set()方法?
- get()和set()是用于使用uvm_config_db配置或检索信息的主要方法。任何验证组件都可以使用set()方法为config_db配置一些信息,还可以控制其他组件对该信息的可见性。可以将其设置为全局可见性,或者仅对一个或多个特定测试平台组件可见。
- get()函数从数据库中匹配配置参数。get()和set()方法的语法如下:
uvm_config_db#(<type>)::set (uvm_componentcontext, string inst_name, string field_name, <type> value)
uvm config_db#(<type>)::get(uvm_componentcontext, string inst_name, string field_name, ref value).
context指定调用get/set的当前类或组件。
inst_name是调用get/set的组件实例的名称。
field_name是在config-db中get/set的参数的名称。
****标识get/set的配置信息的类型。
58、验证平台中较低层次结构的组件是否可以使用get/setconfig方法将句柄传递给较高层次结构中的组件?
- 建议不要以这种方式在UVM中传递配置对象。通常,较高级别的组件设置配置数据而较低级别的组件使用get/set方法获取它们。
59、在UVM方法学中仿真如何结束?
- UVM具有分阶段(phase)执行,该执行由一组构建阶段,运行阶段和检查阶段组成。
- 在运行阶段执行实际的仿真,并且在此阶段中每个组件都可以在开始时raise objection并保留该objection直到完成其仿真行为为止。一旦所有组件都drops objection则运行阶段完成,然后所有组件的check()阶段执行,最后测试结束。
- 这是正常仿真结束的方式,但是如果某些组件由于设计或测试平台中的错误而挂起,仿真超时(timeouts)也可以控制仿真结束。
60、什么是UVM RAL(UVM Register Abstraction Layer)?
- **UVM RAL(寄存器抽象层)**是UVM支持的功能,有助于使用抽象寄存器模型来验证设计中的寄存器以及DUT的配置。UVM寄存器模型寄存器抽象模型反映了寄存器设计的结构规范,提供了一种跟踪DUT寄存器内容和位置的方式。这是硬件和软件工程师的共同参考。RAL的其他一些功能包括支持寄存器的front door和backdoor初始化以及内置的功能覆盖率支持。
61、什么是UVM Call back?
- uvm-callback类是用于实现回调(callbacks)的基类,这些回调用于在不更改组件类代码的情况下修改组件的行为。
- 一种常见用法是在driver将激励发送到DUT之前将错误注入到生成的数据包中。以下伪代码显示了如何实现Call back.
class Packet_c;
byte[4] src addr, dst addr;
byte[] data;
byte[4] crc;
endclass
//Userdefined callback class extended from base class
class PktDriver_Cb extends uvm_callback:
function new (string name = "pktDriver cb");
super. new(name);
endfunction
virtual task corrupt_packet (Packet_c pkt);
//Implement how to corrupt packet
//example -flip one bit of byte o in CRC
pkt.crc[0][0] = ~pkt. crc[0][0]
endtask
endclass: PktDriver_Cb
//Main Driver class
class PktDriver extends uvm_component;
`uvm_component_utils(pktDriver)
//Register callback class with driver
`uvm_register_cb(PktDriver, PktDriver_Cb)
function new (string name, uvm_component parent=null);
super. new(name, parent);
endfunction
virtual task run();
forever begin
seq_item_port. get_next_item(pkt);
`uvm do callbacks(PktDriver, PktDriver cb, corrupt_packet(pkt))
//other code to derive to DUT etc
end
endtask
endclass
1)定义数据包packet类
2)定义从sequence中接收此数据包并将其发送到DUT的driver类
3)定义一个从uvm_callback基类派生的driver callback类,并添加一个虚拟方法,该方法可用于注入错误或翻转数据包中的某个位。
4)使用`uvm_register_cb()宏注册callback类
5)在driver类的run()方法中接收数据包并将其发送到DUT
62、什么是uvm root类?
uvm_root类充当所有UVM组件的隐式顶层和phase控制器。用户不直接实例化uvm_-root,UVM自动创建一个uvm_root实例,用户可以通过全局实例变量uvm_top访问。
63、uvm_test的父类是什么?
uvm_test类是用户可以实现的顶层类,并且没有提到显式父类。但是,UVM有一个称为uvmtop的特殊组件,它被指定为test类的父类。
64、为异步Fifo编写uvm_sequence_item
class seqItem extends uvm_sequence_item;
`uvm_object_utils(seqItem)
logic [8-1:0] rdata;
logic wfull;
logic rempty;
rand logic [8-1:0] wdata;
logic winc, wrst_n;
logic rinc, rrst_n;
function new (string name="seqItem");
super. new(name);
endfunction
endclass
65、UVM是否独立于SystemVerilog?
- UVM建立在SystemVerilog基础上,不支持SystemVerilog的工具也不会支持UVM.
66、什么是virtual sequence和virtual sequencer?
- virtual sequence是一个包含和执行多个子sequence的容器,virtual sequencer是包含其他sequencer的容器以使得virtual sequence中的每个子sequence都能在相应的sequencer上获得执行。
67、uvm_do和`uvm_send有什么区别?
`uvm_do自动地创建、随机化 和 发送 新的对象
`uvm_send用于发送已经完成创建和随机化之后的对象
68、我们可以在UVM中自定义phase么?
- 可以在UVM中自定义phase,然后插入到已有的phase之间,自定义phase继承自uvm task phase,需要实现其中的exec task和exec func方法。
69、RAL backdoor和frontdoor访问有什么区别?
backdoor访问:通过RTL信号路径访问,不消耗仿真时间
frontdoor访问:通过数据总线协议访问,消耗仿真时间
70、set_config_*和uvm_config_db有什么不同?
set_config_*可以映射到相应的uvm_ config_db:
set_config_int(...)=>uvm_config_db#(uvm_bit_stream_t) :: set(cntxt, ...)
set_config_string(..)>uvm_config_db#(string) :: set(cntxt,...)
set_config_object (..)>uvm_config_db#(uvm_object) :: set(cntxt,...)
71、如何在component或者sequence中访问DUT中的信号?
- 接口信号可以通过指向具体interface的virtual interface访问,DUT内部信号可以通过信号路径访问
72、如何调试UVM中config db的名称或者路径不匹配的问题?
- 使用+UVM_CONFIG_DB_TRACE获得set/get信息
73、如何连接monitor和scoreboard,driver和sequencer?
- 使用analysis_port在connect phase连接monitor和scoreboard,driver具有一个seq_item_port,可以在agent的connect phase中连接到sequencer的seq_item_export
74、类中的静态属性和动态属性有什么区别?
- SystemVerilog支持属于**类(class)而不属于特定实例(instance)**的静态属性。即使没有实例存在,也可以访问这些属性。例如可以使用静态属性来计算特定类的实例数,也可以调用可以访问静态属性的静态方法。静态方法无法访问非静态属性,因为这些属性可能不存在。
virtual class car;
static int counter =0; // shared by all instances
static local
function void increment counter();
counter ++
$display("creating item %od counter);
endfunction
function new();
increment counter(); // increment on construction
endfunction: new
endclass: car
75、sequence通常包含什么?
- 一个sequence通常包含一个body)任务,在其中生成施加到DUT的激励。
76、实现AHB-Lite driver的伪代码?
- 实现AHB driver的关键点是其流水线协议,需要在处理当前事务数据的同时处理下一事务的地址,这可以通过fork-join多个并行进程实现
class ahb_driver extends uvm_driver ;
semaphore sema ;
virtual task run_phase(uvm phasephase);
fork
drive_tx();
drive_tx();
join
endtask
virtual task drivetx();
//1. Gethold of a semaphore
//2. Gettransaction packet from sequencer
//3. Drivethe address phase
//4. Releasesemaphore
//5. Drive data phase
endtask
endclass
77、UVM源自哪种语言?
78、什么是UVM drain time?
- drain time是指设置的所有objection结束之后、仿真结束之前的时间
79、仿真器需要设置UVM HOME才能仿真uvm test么?
- 当前主流仿真器都支持UVM,可以不设置UVM_HOME,这时候仿真工具会选择默认的UVM版本
80、什么是p-sequencer句柄,与m_sequencer相比有什么不同?
- 与sequencer,driver或monitor等UVM组件在整个仿真周期内都存在不同,UVM sequence是生命周期有限的对象。因此,如果在sequence从测试平台层次结构(组件层次结构)访问任何成员或句柄,则需要运行该sequence的sequencer的句柄。
- m_sequencer是uvm_sequencer_base类型的句柄,默认情况下在uvm_sequence中可用。但是要访问在真实的sequencer,我们需要对msequencer进行转换(typecast),通常称为p_sequencer。
- 下面是一个简单的示例,其中sequence要访问clock monitor组件的句柄。
class test_sequence_c extends uvm_sequence;
test_sequencer_c p_sequencer;
clock_monitor_c my_clock_monitor;
task pre_body();
if(!$cast(p_sequencer, m_sequencer)) begin
`uvm_fatal ("Sequencer Type Mismatch:", "wrong sequencer");
end
my_clock_monitor = p_sequencer. clk_monitor;
endtask
endclass
class test_sequencer_c extends uvm_sequencer;
clock_monitor_c clk_monitor;
endclass