UVM Sequencer 深度解析:FIFO 深度、req/rsp 应答模型与高频面试坑

一、Sequencer 内部FIFO深度

1. 两个核心FIFO(很多人混淆!)

uvm_sequencer 内部维护两套FIFO,不是一个:

  1. request FIFO(req_fifo):存放sequence发过来的transaction(req),给driver拉取。
  2. response FIFO(rsp_fifo):存放driver回传的response事务,给sequence取回。

默认:两个FIFO默认深度都是1 !

uvm_sequencer_base里宏定义默认深度 UVM_SEQUENCER_DEFAULT_FIFO_DEPTH = 1

含义:

req_fifo深度=1:sequencer最多缓存1个还没有被driver取走的req。

  • 场景:driver正在处理第1笔item;sequence发第2笔item,此时req_fifo满,finish_item()阻塞。
  • 所以默认情况下,sequencer不会预存一大堆激励,基本是一进一出的流水线。

修改FIFO深度

systemverilog 复制代码
// 在test/env的build_phase,修改sequencer的FIFO深度
seqr.set_depth(8);  // req_fifo和rsp_fifo同时改成深度8

注意:set_depth(N) 同时修改 req_fifo 和 rsp_fifo。

只改rsp_fifo:seqr.set_rsp_depth(N)

什么时候调大FIFO深度?

  1. Driver处理item很慢,DUT处理时延很长,想让sequence提前产生多笔激励预存在sequencer,提高仿真效率;
  2. 做burst连续激励,避免sequence频繁阻塞等待driver;

⚠️ 坑:

FIFO深度只是缓存上限,不改变握手规则 。

就算FIFO深度设为8,driver调用get_next_item拿到item之后,必须item_done才能取下一笔。FIFO只是"仓库",不是跳过握手。

一句话记忆:

FIFO是缓存,默认深度1;set_depth同时改req和rsp,set_rsp_depth只改响应FIFO。


二、req/rsp 应答模型(两种模式)

两种工作模式

  1. NO_RSP 无应答模式(前面我们示例代码用的)
    sequence只发req,driver处理完item直接item_done(),不返回response 。
    item_done()不带参数。

    systemverilog 复制代码
    seq_item_port.item_done(); //无rsp
  2. WITH_RSP 带应答模式(req/rsp完整模型)
    driver处理完DUT事务,构造response事务,回传给sequencer,sequence接收rsp 。

    systemverilog 复制代码
    seq_item_port.item_done(rsp); //把rsp传给sequencer

适用场景:读操作!DUT返回读数据、返回状态、error标志。

req:我要读地址0x10;rsp:地址0x10读出的数据=0x55,status=ok。
底层端口:

driver除了 seq_item_port(pull req),内部自带response通路:put_response(put端口,push模型,driver推rsp回sequencer的rsp_fifo)。

三、response返回通路:put_response / get_response

1. driver侧:put_response()

两种写法等价:

systemverilog 复制代码
//写法1:item_done带rsp(推荐,简洁)
my_item rsp;
rsp = my_item::type_id::create("rsp");
rsp.data = read_data_from_dut;
rsp.status = 1'b1;
seq_item_port.item_done(rsp); 
//内部自动调用 put_response(rsp);
systemverilog 复制代码
//写法2:手动put_response,再调用不带参数item_done
seq_item_port.put_response(rsp);
seq_item_port.item_done();

⚠️ 重点:不要同时写item_done(rsp) + put_response,会重复发送两份response,引发报错!

2. sequence侧:get_response() 接收应答

sequence发送完finish_item(req)之后,可以调用get_response(rsp)阻塞等待driver返回的rsp。

get_response(rsp):阻塞任务,直到rsp_fifo收到对应response才返回。

完整sequence示例(带rsp):

systemverilog 复制代码
virtual task body();
  my_item req, rsp;
  req = my_item::type_id::create("req");
  start_item(req);
  req.is_read = 1;
  req.addr = 16'h0010;
  finish_item(req);  //发送读请求,阻塞等待driver处理
  get_response(rsp); //【等待driver返回response】阻塞!
  `uvm_info("SEQ",$sformatf("read data = %0h, status=%0b",rsp.data,rsp.status),UVM_MEDIUM)
endtask

3. req和rsp如何配对?(uvm_sequence_item::transaction_id)

核心:依靠 transaction_id 事务ID匹配req和rsp!

  • sequence发送req时,UVM自动给req分配唯一transaction_id
  • driver构造rsp的时候,必须把rsp.transaction_id = req.transaction_id

如果用 item_done(rsp),UVM底层自动帮你拷贝transaction_id,不用手动赋值。

sequencer收到rsp,根据transaction_id找到对应的等待中的sequence,把rsp交给它。

坑:

如果手动put_response,忘记拷贝transaction_id → rsp无法匹配,rsp留在rsp_fifo,get_response永久阻塞卡死。

4. 非阻塞版本:try_get_response()

和try_get_next_item思路一致,function,不阻塞:

systemverilog 复制代码
if(!this.try_get_response(rsp)) begin
  //暂时没有rsp,可以做别的事情
end

5. 两个重要开关:set_response_handler / disable_item_done_response_auto

  • p_sequencer.set_response_handler(callback_func)

    注册回调函数,sequencer收到rsp自动调用回调,不用sequence主动调用get_response(异步回调方式)。适合需要异步接收rsp场景。

  • use_sequence_item_response:控制是否开启rsp通路。默认开启。

四、完整带RSP的握手时序图(Mermaid)

DUT driver sequencer sequence DUT driver sequencer sequence #mermaid-svg-mnR6K5cv89O613dk{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-mnR6K5cv89O613dk .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-mnR6K5cv89O613dk .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-mnR6K5cv89O613dk .error-icon{fill:#552222;}#mermaid-svg-mnR6K5cv89O613dk .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-mnR6K5cv89O613dk .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-mnR6K5cv89O613dk .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-mnR6K5cv89O613dk .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-mnR6K5cv89O613dk .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-mnR6K5cv89O613dk .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-mnR6K5cv89O613dk .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-mnR6K5cv89O613dk .marker{fill:#333333;stroke:#333333;}#mermaid-svg-mnR6K5cv89O613dk .marker.cross{stroke:#333333;}#mermaid-svg-mnR6K5cv89O613dk svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-mnR6K5cv89O613dk p{margin:0;}#mermaid-svg-mnR6K5cv89O613dk .actor{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-mnR6K5cv89O613dk text.actor>tspan{fill:black;stroke:none;}#mermaid-svg-mnR6K5cv89O613dk .actor-line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-mnR6K5cv89O613dk .innerArc{stroke-width:1.5;stroke-dasharray:none;}#mermaid-svg-mnR6K5cv89O613dk .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333;}#mermaid-svg-mnR6K5cv89O613dk .messageLine1{stroke-width:1.5;stroke-dasharray:2,2;stroke:#333;}#mermaid-svg-mnR6K5cv89O613dk #arrowhead path{fill:#333;stroke:#333;}#mermaid-svg-mnR6K5cv89O613dk .sequenceNumber{fill:white;}#mermaid-svg-mnR6K5cv89O613dk #sequencenumber{fill:#333;}#mermaid-svg-mnR6K5cv89O613dk #crosshead path{fill:#333;stroke:#333;}#mermaid-svg-mnR6K5cv89O613dk .messageText{fill:#333;stroke:none;}#mermaid-svg-mnR6K5cv89O613dk .labelBox{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-mnR6K5cv89O613dk .labelText,#mermaid-svg-mnR6K5cv89O613dk .labelText>tspan{fill:black;stroke:none;}#mermaid-svg-mnR6K5cv89O613dk .loopText,#mermaid-svg-mnR6K5cv89O613dk .loopText>tspan{fill:black;stroke:none;}#mermaid-svg-mnR6K5cv89O613dk .loopLine{stroke-width:2px;stroke-dasharray:2,2;stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);}#mermaid-svg-mnR6K5cv89O613dk .note{stroke:#aaaa33;fill:#fff5ad;}#mermaid-svg-mnR6K5cv89O613dk .noteText,#mermaid-svg-mnR6K5cv89O613dk .noteText>tspan{fill:black;stroke:none;}#mermaid-svg-mnR6K5cv89O613dk .activation0{fill:#f4f4f4;stroke:#666;}#mermaid-svg-mnR6K5cv89O613dk .activation1{fill:#f4f4f4;stroke:#666;}#mermaid-svg-mnR6K5cv89O613dk .activation2{fill:#f4f4f4;stroke:#666;}#mermaid-svg-mnR6K5cv89O613dk .actorPopupMenu{position:absolute;}#mermaid-svg-mnR6K5cv89O613dk .actorPopupMenuPanel{position:absolute;fill:#ECECFF;box-shadow:0px 8px 16px 0px rgba(0,0,0,0.2);filter:drop-shadow(3px 5px 2px rgb(0 0 0 / 0.4));}#mermaid-svg-mnR6K5cv89O613dk .actor-man line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;}#mermaid-svg-mnR6K5cv89O613dk .actor-man circle,#mermaid-svg-mnR6K5cv89O613dk line{stroke:hsl(259.6261682243, 59.7765363128%, 87.9019607843%);fill:#ECECFF;stroke-width:2px;}#mermaid-svg-mnR6K5cv89O613dk :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} rsp存入rsp_fifo,按transaction_id匹配SEQ 拿到rsp,校验数据 start_item(req)randomize reqfinish_item(req) 【SEQ阻塞】req送入req_fifoget_next_item(req)拿到请求驱动读命令、地址返回读数据创建rsp,填充数据,自动复制transaction_iditem_done(rsp) //内部put_response(rsp)finish_item 解除阻塞get_response(rsp) //拿应答返回rsp

五、两种rsp使用模式对比

模式 说明 使用场景
get_response 阻塞等待 finish_item之后调用get_response,同步等待rsp,一一对应 同步读写,发一个req等一个rsp(最常用)
response_handler回调 注册回调函数,rsp到达自动触发函数,不需要get_response 异步响应,rsp回来时间不确定

六、高频坑(面试必问)

  1. item_done(rsp) 等价于 put_response(rsp),二选一,不能两个一起写,否则会收到两份rsp,报匹配错误。
  2. transaction_id是req/rsp配对的钥匙;手动put_response必须手动赋值rsp.transaction_id = req.transaction_id。
  3. rsp_fifo满了的时候,driver调用put_response会阻塞。rsp_fifo深度独立可控 set_rsp_depth()。
  4. 一个req只能对应一个rsp,不能返回多个rsp;如果DUT返回多个应答,要设计成多个独立transaction。
  5. 不要在NO_RSP模式调用get_response → 永久阻塞卡死。

面试速记

  1. sequencer两个FIFO:req_fifo、rsp_fifo,默认深度都是1;set_depth同时修改两者,set_rsp_depth只修改rsp。
  2. rsp通路:driver用put_response或者item_done(rsp)把response推回sequencer的rsp_fifo。
  3. sequence通过get_response()阻塞获取应答,依靠transaction_id完成req-rsp配对。
  4. 两种rsp模式:同步get_response;异步response_handler回调。

继续往下我们可以讲:

  1. uvm_sequence_item的transaction_id、sequence_id、parent sequence
  2. uvm_sequencer#(REQ,RSP) 带两个参数的模板,REQ和RSP类型不同的场景
  3. 异常场景:rsp丢失、rsp乱序、transaction_id冲突仿真报错分析

如果需要请评论或私信~

相关推荐
用户6222884048191 小时前
站在JDK的角度理解线程池:从execute 到 getTask 一篇讲透
java·面试
考研保研资料分享1 小时前
生态学保研经验:从中央民族大学到上交,科研分工与多校考核(2025)
面试
studyForMokey3 小时前
【Android 面试】Paging3
android·面试·职场和发展
.道阻且长.3 小时前
Linux软件包管理器
linux·运维·ubuntu·职场和发展·centos
考研保研资料分享3 小时前
211英语专业跨保清华法学:2022年法学面试与口译考核复盘
面试·职场和发展
考研保研资料分享3 小时前
2024双非材料保研复旦:五校面试题与科研复盘
面试·职场和发展
救救孩子把12 小时前
AI面试八股文-21_21-多模态Agent面试题-Vision-Language-Agent
人工智能·面试·职场和发展·llava·多模态agent
ShineWinsu15 小时前
对于JavaScript:JavaScript基础语法的解析
开发语言·前端·javascript·面试·web·基础语法·循环
救救孩子把15 小时前
AI面试八股文-13_12-AI 框架与运维面试题
运维·人工智能·面试