一、Sequencer 内部FIFO深度
1. 两个核心FIFO(很多人混淆!)
uvm_sequencer 内部维护两套FIFO,不是一个:
- request FIFO(req_fifo):存放sequence发过来的transaction(req),给driver拉取。
- 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深度?
- Driver处理item很慢,DUT处理时延很长,想让sequence提前产生多笔激励预存在sequencer,提高仿真效率;
- 做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 应答模型(两种模式)
两种工作模式
-
NO_RSP 无应答模式(前面我们示例代码用的)
sequence只发req,driver处理完item直接item_done(),不返回response 。
item_done()不带参数。systemverilogseq_item_port.item_done(); //无rsp -
WITH_RSP 带应答模式(req/rsp完整模型)
driver处理完DUT事务,构造response事务,回传给sequencer,sequence接收rsp 。systemverilogseq_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回来时间不确定 |
六、高频坑(面试必问)
- item_done(rsp) 等价于 put_response(rsp),二选一,不能两个一起写,否则会收到两份rsp,报匹配错误。
- transaction_id是req/rsp配对的钥匙;手动put_response必须手动赋值rsp.transaction_id = req.transaction_id。
- rsp_fifo满了的时候,driver调用put_response会阻塞。rsp_fifo深度独立可控
set_rsp_depth()。 - 一个req只能对应一个rsp,不能返回多个rsp;如果DUT返回多个应答,要设计成多个独立transaction。
- 不要在NO_RSP模式调用get_response → 永久阻塞卡死。
面试速记
- sequencer两个FIFO:req_fifo、rsp_fifo,默认深度都是1;set_depth同时修改两者,set_rsp_depth只修改rsp。
- rsp通路:driver用put_response或者item_done(rsp)把response推回sequencer的rsp_fifo。
- sequence通过get_response()阻塞获取应答,依靠transaction_id完成req-rsp配对。
- 两种rsp模式:同步get_response;异步response_handler回调。
继续往下我们可以讲:
- uvm_sequence_item的transaction_id、sequence_id、parent sequence
uvm_sequencer#(REQ,RSP)带两个参数的模板,REQ和RSP类型不同的场景- 异常场景:rsp丢失、rsp乱序、transaction_id冲突仿真报错分析
如果需要请评论或私信~