前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >[十五]Cracking Digital VLSI Verification Interview

[十五]Cracking Digital VLSI Verification Interview

作者头像
空白的贝塔
发布2020-06-24 16:25:58
1.1K0
发布2020-06-24 16:25:58
举报
文章被收录于专栏:摸鱼范式摸鱼范式

[281] sequencer有哪些仲裁机制?

多个sequence可以与同一个接口的driver并发交互。sequencer支持多种仲裁机制,以确保在任何时间点只有一个sequence可以访问driver。哪个sequence可以发送sequence_item取决于用户选择的仲裁机制。在UVM中实现了五种内置的仲裁机制。还有一个附加的回调函数可以实现用户定义的算法。sequencer具有一种称为set_arbitration()的方法,可以调用该方法来选择sequencer应使用哪种算法进行仲裁。可以选择的六种算法如下:

1.SEQ_ARB_FIFO(默认值)。如果指定了此仲裁模式,那么sequencer将使用一个FIFO选择sequence。例如:如果seq1,seq2和seq3在sequencer上运行,它将首先从seq1中选择一个item,然后从seq2中选择一个item,然后从seq3中选择一个item(如果可用),然后继续。2.SEQ_ARB_WEIGHTED:如果选择此仲裁模式,则始终首先选择优先级最高的sequence,直到没有可用为止,然后再选择下一个优先级sequence,依此类推。如果两个sequence具有相同的优先级,则以随机顺序从中选择它们。3.SEQ_ARB_RANDOM:如果选择此仲裁模式,忽略所有优先级以随机顺序选择sequence。4.SEQ_ARB_STRICT_FIFO:与SEQ_ARB_WEIGHTED相似,不同之处在于,如果两个sequence具有相同的优先级,则来自这些sequence的项顺序是按FIFO顺序而不是随机顺序选择的。5.SEQ_ARB_STRICT_RANDOM:与SEQ_ARB_RANDOM相似,只是不忽略优先级。首先从优先级最高的序列中随机选择sequence,然后依次选择下一个和最高顺序。6.SEQ_ARB_USER:此算法允许用户定义用于sequence之间仲裁的自定义算法。这是通过扩展uvm_sequencer类并覆盖user_priority_arbitration()方法来完成的。[282] 在sequencer上启动sequence时,如何指定其优先级?

通过将参数传递给序列的start()方法来指定优先级。根据为权重来确定优先级。例如:第三个参数指定sequence的优先级。

代码语言:javascript
复制
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 three sequences

[283] sequence如何才能独占sequencer的访问权限?

当在sequencer上运行多个sequence时,sequencer进行仲裁并授予sequence的访问权限。有时,一个sequence可能希望独占sequencer的访问权限,直到将其所有sequence_item送到driver为止(例如:如果您希望在不中断的情况下激发确定性模式)。有两种机制允许sequence获得对sequencer的独占访问权。

1.使用lock()和unlock():sequence可以调用在其上运行的sequencer的lock方法。当sequence通过sequencer仲裁机制获得下一个访问权限时,将授予该sequence对driver的独占访问权限。如果还有其他标记为更高优先级的sequence,则此序列需要等待,直到获得授权。权限锁定后,其他sequence将无法访问driver,直到该序列在sequencer上调用unlock()后,权限将被释放。lock方法是一个阻塞方法,直到授予锁后才返回。2.使用grab()和ungrab():grab方法类似于lock方法,可以在需要独占访问时由sequence调用。grab和lock之间的区别在于,调用grab()时,它将立即生效,并且该sequence将100%获得下一个sequencer的授权机会,从而高于所有当前的sequence优先级。阻止sequence通过grab独占sequencer的唯一方法是sequencer上已经存在的lock()或grab()。

[284] sequencer上的lock和grab有什么区别?

在sequencer上运行的sequence使用sequencer的grab()和lock()方法来获得对该序列器的独占访问权,直到调用了相应的unlock()或ungrab()。grab和lock之间的区别在于,当调用sequencer上的某个grab()时,它将立即生效,并且该sequence将获得下一个sequencer的授权,从而高于所有当前的sequence优先级。但是,对lock()的调用将需要等待,直到sequence根据设置的优先级和仲裁机制获得其下一个授权为止。在用法方面,可以使用lock来对优先级中断进行建模,并使用grab来对不可屏蔽的中断进行建模,在别的建模场景中也很有用。

[285] 流水线和非流水线sequencer-driver模型有什么区别?

根据需要如何通过interface发送激励,在UVM driver类中可以实现两种模式。

1.非流水线模型:如果driver一次仅对一个事务进行建模,则称为非流水线模型。在这种情况下,sequence可以将一个事务发送给driver,并且driver可能需要几个周期(基于接口协议)才能完成驱动该事务。只有在那之后,驱动程序才会接受sequencer的新事务.

代码语言:javascript
复制
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

1.流水线模型:如果driver一次建模多个活动事务,则称为流水线模型。在这种情况下,sequence可以继续向driver发送新事务,而无需等待driver完成之前的事务。在这种情况下,对于从该sequence发送的每个事务,driver都会派生一个单独的进程来基于该事务驱动接口信号,不会等到它完成后再接受新事务。如果我们要在接口上回送请求而不等待设计的响应,应该采用这种建模。

代码语言:javascript
复制
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 to DUT which can take more clocks
                //separate thread that doesn't block sequence
                //driver can accept more items without waiting
            end
            join_none
            item_done(); // ** Unblocks finish_item() in sequence
        end
    endtask: run_phase
endclass: pipeline_driver

[286] 如何确保在sequencer-driver上运行多个sequnce时,响应会从driver发送回正确的sequence?

如果从driver返回了几个序列之一的响应,则sequencer将sequence中的sequenceID字段用于将响应路由回正确的sequence。driver中的响应处理代码应调用set_id_info(),以确保任何响应项都具有与其原始请求相同的sequenceID。下面是driver中的一个示例代码,该代码获取sequencer_item的id并发送回响应(请注意,这是用于说明的参考伪代码,并且假定某些功能在其他地方进行了编码)

代码语言:javascript
复制
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
            itemrsp_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

[287] 什么是m_sequencer句柄?

启动sequence时,它始终与启动sequencer相关联。m_sequencer句柄指向了当前sequence挂载的sequencer。使用此句柄,序列可以访问UVM组件层次结构中的任何信息和其他资源句柄。

[288] m_sequencer和p_sequencer有什么区别?

UVM sequence是寿命有限的对象,与sequencer,driver或monitor不同,后者是UVM的组件,并且在整个仿真时间内都存在。因此,如果需要从测试平台层次结构(组件层次结构)访问任何成员或句柄,sequence需要sequencer的句柄。m_sequencer是uvm_sequencer_base类型的句柄,默认情况下在uvm_sequence中可用。但是,要访问在其上运行sequence的真实sequencer,我们需要将m_sequencer转换为真实sequencer,通常称为p_sequencer(可以自定义为任何名字,不仅仅是p_sequencer)。下面是一个简单的示例,其中sequence要访问clock monitor组件的句柄,该组件可在sequencer中用作句柄。

代码语言:javascript
复制
//clock monitor component which is available as a handle in the sequencer.

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

[289] 生成sequence时,早期随机化和后期随机化有什么区别?

在早期随机化中,首先使用randomize()对sequence进行随机化,然后使用start_item()来请求对sequencer的访问,这是一个阻塞调用,根据sequencer的繁忙程度可能会花费一些时间。下面的示例显示一个对象(req)首先被随机化,然后sequence等待仲裁。

代码语言:javascript
复制
task body()
    assert(req.randomize());
    start_item(req); //Can consume time based on sequencer arbitration
    finish_item(req);
endtask

在后期随机化中,sequence首先调用start_item(),等待直到sequencer批准仲裁,然后在将事务发送给sequencer/driver之前,调用randomize。这样做的好处是,可以将item及时地随机化,并且可以在将item发送给driver之前使用来自设计或其他组件的任何反馈。以下代码中使用的就是后期随机化(req)

代码语言:javascript
复制
task body()
    start_item(req); //Can consume time based on sequencer arbitration
    assert(req.randomize());
    finish_item(req);
endtask

[290] 什么是subsequence?

subsequence是从另一个sequence开始的sequence。从sequence的body()中,如果调用了另一个sequence的start(),则通常将其称为subsequence。

[291] UVM driver中的get_next_item()和try_next_item()有什么不同?

get_next_item是一个阻塞方法(driver-sequencer API的一部分),阻塞直到sequence_item可供driver处理为止,并返回指向sequence_item的指针。try_next_item是非阻塞版本,如果没有sequence_item可用于driver处理,则它将返回空指针。

[292] UVM driver中的get_next_item()和get()有什么不同?

get_next_item是一个阻塞调用,用于从sequencer FIFO获取sequence_item以供driver处理。driver处理完sequence_item后,需要先使用item_done完成握手,然后再使用get_next_item()请求新的sequence_item。

get()也是一个阻塞调用,它从sequencer FIFO获取sequence_item以供driver处理。但是,在使用get()时,由于get()方法隐式完成了握手,因此无需显式调用item_done()。

[294] UVM driver中的peek()和get()有什么不同?

driver的get()方法是一个阻塞调用,从sequencer FIFO获取sequence_item以供driver处理。一旦有sequence_item可用,它就会解锁,并与sequencer完成握手。peek()方法类似于get(),并阻塞直到sequence_item可用为止。但是,它不会从sequencer FIFO中删除sequence。因此,多次调用peek()将在driver中返回相同的sequence_item。

[295] 带有和不带有参数调用时,driver-sequencer API的item_done()方法有什么区别?

item_done()方法是driver中的一种非阻塞方法,用于在get_next_item()或try_next_item()成功之后与sequencer完成握手。如果不需要发回响应,则不带参数调用item_done(),它将完成握手,而无需在sequencer响应FIFO中放置任何内容。如果希望将响应发送回去,则将item_done()与指向响应sequence_item的句柄作为参数一起传递。该响应句柄将放置在sequencer响应FIFO中,sequence通过这种方式进行响应。

[296] 下面哪些方法是阻塞的,哪些是非阻塞的?

1.get()2.get_next_item()3.item_done()4.put()5.try_next_item()6.peek()

get(), get_next_item(), peek() 是阻塞的

try_next_item(), item_done(), and put() 是非阻塞的

[297] UVM driver中,下面哪些代码是错误的?

代码语言:javascript
复制
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的握手。

[298] 如何停止sequencer上的所有sequence?

sequencer具有stop_sequences()方法,可用于停止所有sequence。但是,此方法不检查driver当前是否正在处理任何sequence_items。因此,如果driver调用item_done()或put(),则可能会出现致命错误,因为sequence指针可能无效。因此,用户需要注意,一旦调用stop_sequence(),就禁用了sequencer线程(如果在fork中启动)。

[299] 用户调用sequence.print()方法时,将调用sequence中的哪个方法?

convert2string():建议实现此函数,该函数返回对象的字符串表示形式(其数据成员的值)。这对于将调试信息打印到模拟器脚本或日志文件很有用。

[300] 找出UVM sequence的以下代码部分中的所有潜在问题

代码语言:javascript
复制
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将赢得仲裁并可以访问driver-sequencer。从那时起直到finish_item的任何延迟都将阻塞driver-sequencer,并且使得任何其他sequence都不能访问driver-sequencer。如果在一个接口上运行多个sequence,并且延迟很大,设计接口上有很多空闲时,这会造成很大的麻烦。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-05-21,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 摸鱼范式 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • [281] sequencer有哪些仲裁机制?
  • [283] sequence如何才能独占sequencer的访问权限?
  • [284] sequencer上的lock和grab有什么区别?
  • [285] 流水线和非流水线sequencer-driver模型有什么区别?
  • [286] 如何确保在sequencer-driver上运行多个sequnce时,响应会从driver发送回正确的sequence?
  • [287] 什么是m_sequencer句柄?
  • [288] m_sequencer和p_sequencer有什么区别?
  • [289] 生成sequence时,早期随机化和后期随机化有什么区别?
  • [290] 什么是subsequence?
  • [291] UVM driver中的get_next_item()和try_next_item()有什么不同?
  • [292] UVM driver中的get_next_item()和get()有什么不同?
  • [294] UVM driver中的peek()和get()有什么不同?
  • [295] 带有和不带有参数调用时,driver-sequencer API的item_done()方法有什么区别?
  • [296] 下面哪些方法是阻塞的,哪些是非阻塞的?
  • [297] UVM driver中,下面哪些代码是错误的?
  • [298] 如何停止sequencer上的所有sequence?
  • [299] 用户调用sequence.print()方法时,将调用sequence中的哪个方法?
  • [300] 找出UVM sequence的以下代码部分中的所有潜在问题
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档