2. 核心接口:put/get、transport、nb_transport 与时序模型

好,咱们今天聊聊 TLM 通信里最核心的几个接口。说实话,我刚接触 TLM 那会儿,也被这些接口搞得有点晕——put/get、transport、nb_transport,还有阻塞非阻塞,到底什么时候该用哪个?

我个人的习惯是,先别急着背接口定义,而是想清楚一件事:你的模型到底要模拟什么样的通信行为? 是简单的数据搬运,还是带时序的精确交互?想清楚这个,接口选择就顺理成章了。

2.1 put/get 接口:最简单的数据搬运

put/get 接口,说白了就是两个操作:放数据取数据。它是最基础的 TLM 通信方式,适合那些不需要关心时序细节的场景。

核心特点:

  • put():发起方把数据塞给接收方
  • get():发起方从接收方把数据拿过来
  • 两者都是阻塞调用——调用没返回,你就等着

我在项目中遇到过这样一个场景:一个简单的 FIFO 模型,只需要把事务从一个模块搬到另一个模块。用 put/get 就足够了,代码写起来也清爽。

// 一个简单的 put/get 示例
class producer extends uvm_component;
  uvm_blocking_put_port #(my_transaction) put_port;
  
  virtual task run_phase(uvm_phase phase);
    my_transaction tr;
    // 创建事务,然后发出去
    tr = my_transaction::type_id::create("tr");
    put_port.put(tr);  // 阻塞在这里,直到对方取走
  endtask
endclass

class consumer extends uvm_component;
  uvm_blocking_get_port #(my_transaction) get_port;
  
  virtual task run_phase(uvm_phase phase);
    my_transaction tr;
    get_port.get(tr);  // 阻塞在这里,直到有数据来
    // 处理 tr...
  endtask
endclass

嗯,这里要注意:put/get 接口默认是阻塞的。如果你想要非阻塞版本,可以用 try_put()try_get(),它们会立即返回一个状态值告诉你成功还是失败。

我的小建议: 如果你的模型只是做功能验证,不关心精确时序,put/get 是最省事的。但如果你要做性能分析,就得考虑 transport 接口了。

2.2 transport 接口:带往返的通信

transport 接口,你可以把它理解成一次完整的请求-响应交互。它把 put 和 get 合并成了一个操作——你发一个请求出去,然后等着响应回来。

为什么会需要这个?你想想看,很多总线协议(比如 AXI)都是请求和响应分开的。你用 put 发请求,再用 get 收响应,中间还得自己维护关联关系,多麻烦。transport 直接帮你搞定。

transport 接口有两种形式:

  • transport():阻塞版本,发完请求后一直等到响应回来
  • nb_transport():非阻塞版本,发完请求就返回,响应通过回调通知
// 阻塞 transport 示例
class master extends uvm_component;
  uvm_blocking_transport_port #(req_t, rsp_t) trans_port;
  
  virtual task run_phase(uvm_phase phase);
    req_t req;
    rsp_t rsp;
    req.addr = 32'h1000;
    req.data = 32'hDEAD_BEEF;
    trans_port.transport(req, rsp);  // 发请求,等响应
    // 此时 rsp 里已经有结果了
  endtask
endclass

我曾经在一个 DDR 控制器模型里用过 transport 接口。当时需要模拟一次读操作——先发地址,再等数据回来。用 transport 接口,一行代码就搞定了请求和响应的配对,省了不少事。

注意: transport 接口是原子操作,也就是说,在 transport 返回之前,发起方不能做其他事。如果你的模型需要并发处理多个事务,就得考虑非阻塞版本了。

2.3 nb_transport 接口:非阻塞的时序交互

nb_transport 接口,全称是 non-blocking transport。它和 transport 最大的区别在于:调用立即返回,不等待

你可能会问:「那响应怎么回来?」嗯,这就是 nb_transport 的精髓了——它通过回调机制来处理响应。具体来说,nb_transport 会返回一个状态值,告诉调用方「我收下了,你忙你的」,然后等处理完了再通过另一个方向的通知把结果送回来。

nb_transport 的返回值:

返回值 含义
TLM_ACCEPTED 请求被接受,但还没处理完
TLM_UPDATED 请求被接受,并且处理了一部分
TLM_COMPLETED 请求已经处理完成,响应可用
// nb_transport 示例
class slave extends uvm_component;
  uvm_nonblocking_transport_imp #(req_t, rsp_t, slave) imp;
  
  virtual function tlm_sync_state nb_transport_fw(req_t req, ref rsp_t rsp);
    // 立即接受请求
    if (can_accept(req)) begin
      // 把请求加入队列,稍后处理
      request_queue.push_back(req);
      return TLM_ACCEPTED;
    end else begin
      return TLM_INCOMPLETE;
    end
  endfunction
  
  // 处理完请求后,通过 nb_transport_bw 回调通知 master
  virtual function void process_requests();
    // ... 处理逻辑
    master.nb_transport_bw(rsp);
  endfunction
endclass

我个人觉得,nb_transport 是 TLM 里最强大但也最容易用错的接口。为什么?因为它引入了时序的概念——你不再只是「放数据」和「取数据」,而是在模拟一个带延迟的通信过程。

避坑指南: 我曾经在一个项目里把所有通信都用了 nb_transport,结果代码变得极其复杂,调试起来想哭。后来我学乖了:只有当你真的需要模拟时序延迟时,才用 nb_transport。否则,用阻塞接口更省心。

2.4 时序与阻塞/非阻塞模型

好,咱们来聊聊时序模型。说白了,TLM 的时序模型就两种:粗略时序精确时序

  • 粗略时序(Loosely Timed, LT):用阻塞接口,时间跳跃式前进。适合快速仿真和功能验证。
  • 精确时序(Approximately Timed, AT):用非阻塞接口,时间精确到时钟周期。适合性能分析和架构探索。

两种时序模型的对比:

特性 LT(粗略时序) AT(精确时序)
接口类型 阻塞(put/get, transport) 非阻塞(nb_transport)
时间精度 低,以事务为单位 高,以时钟周期为单位
仿真速度
适用场景 功能验证、软件调试 性能分析、架构优化

我个人的经验是:前期做功能验证时,用 LT 模型就够了。等到需要分析系统瓶颈、优化带宽时,再切换到 AT 模型。别一上来就搞精确时序,否则仿真跑一天都跑不完一个用例。

你想想看,一个 SoC 里有几十个 master 和 slave,如果每个通信都用 nb_transport 精确到时钟周期,那仿真速度会慢到什么程度?所以,选择合适的时序模型,本身就是一种性能调优

再强调一次: 阻塞接口(put/get, transport)适合 LT 模型,非阻塞接口(nb_transport)适合 AT 模型。混用的时候要小心,别在 LT 模型里用 nb_transport,那会白白增加复杂度。

2.5 本章知识体系

为了让你更直观地理解这些接口的关系,我画了一张图:

TLM 核心接口与时序模型 阻塞接口 非阻塞接口 时序模型 put() / get() transport() 阻塞等待,直到完成 nb_transport() try_put() / try_get() 立即返回,回调通知 LT(粗略时序) AT(精确时序) 时间精度 vs 仿真速度 阻塞接口 → LT 模型(快速仿真) 非阻塞接口 → AT 模型(精确分析) 选择建议 功能验证用 LT + 阻塞接口 | 性能分析用 AT + 非阻塞接口 别混用,别过度设计,够用就好

这张图把今天讲的内容串起来了。你从上往下看:先选接口类型(阻塞还是非阻塞),再选时序模型(LT 还是 AT),最后根据场景做取舍。说白了,没有最好的接口,只有最合适的。

好,这一章就到这里。记住我的一句话:接口是工具,不是目的。搞清楚你的模型要模拟什么行为,再去选接口,事半功倍。


专注资料整理