跳到主要内容

02 - 单芯片内部详解:一条指令从取指到执行完成

概述 -- 一条指令的完整旅程

在 TPUPerf 中,一条指令从外部进入到最终执行完毕,经历的完整链路可以概括为:

IfeMaster (指令源)
| TXI/AXI 接口
v
IFE (指令取指引擎)
| pack -> pre_decode -> async -> decode -> check -> issue
v
+-----------+ +-----------+
| TIU 引擎 | | GDMA 引擎 |
| (计算指令) | | (搬运指令) |
+-----------+ +-----------+
| |
| DPC 5 级流水 | ~22 个 SC_THREAD
| DES->GEN->ISSUE->ARB | 流水线阶段
| ->COMPUTE |
v v
LMEM (本地 SRAM) <----> DDR (全局内存)
^ ^
| |
+---- WDC 存储控制层 ------+
(Fabric 路由 + CAM + X2X + UMC/DRAM)

关键时钟域:IFE 使用 clk_i_(系统时钟)和 clk_ife_(IFE 专用时钟),TIU 使用 tiu_clock_,GDMA/LMEM 使用 dma_clk_,WDC 内部使用 clk2G_(2GHz)、clk800M_(800MHz)、clk400M_(400MHz)三级时钟。

两大执行通道:TIU 指令和 GDMA 指令在 IFE 中被分别解码并分发到独立引擎,通过 tiu_sync_id_ / tdma_sync_id_ 信号对实现跨引擎依赖同步(详见 01-system-architecture.md)。


IFE 指令取指引擎

IFE(Instruction Fetch Engine)是指令进入单核子系统的入口。源码位于 ip/include/ife/ife.hip/src/ife/ife.cpp

指令输入接口

IFE 支持两种指令输入模式,由 IfeMaster::TXI_MODE 属性决定:

  • TXI 模式:通过 txi_req_data1_(256-bit rs1)、txi_req_data2_(256-bit rs2)、req_inst_(32-bit)三组信号传入,txi_req_valid_/txi_req_ready_ 握手
  • AXI 模式:通过 axi_pkg_sc_fifo<RvtiAxiCmd>,深度 8)传入 AXI 命令包,axi_aw_valid_/axi_aw_ready_ 握手,AXI 响应延迟 axi_slv_rsp_delay_ = 3

IfeSignalBus 类(ife_signal_bus.h)封装了 IfeMasterIFE 之间的所有信号连接,包括 TXI 数据信号、AXI 命令 FIFO、响应通道。

IFE 内部流水线

IFE 内部是一条多级流水线,每级之间通过 std::deque FIFO 缓冲。从 ife.cpp 构造函数中注册的 SystemC 进程可以还原完整流水:

TXI/AXI 输入
|
v
[pre_decode_input_txi] SC_CTHREAD(clk_i_) -- 从 TXI 接收,打包到 cm_fifo_
| 容量: CM_FIFO_LENGTH = 8
v
[pre_decode_output] SC_THREAD(clk_i_) -- 预解码,输出到 vcix_predecode_output_fifo_
| 容量: PRE_DECODE_OUTPUT_FIFO_LENGTH = 4
v
[async_deal1] SC_CTHREAD(clk_i_) -- 跨时钟域缓冲 (clk_i_ -> clk_ife_)
| 容量: ASYNC_INPUT_FIFO_LENGTH = 8
v
[async_deal2] SC_CTHREAD(clk_ife_) -- 跨时钟域缓冲下游
| 容量: ASYNC_OUTPUT_FIFO_LENGTH = 8
v
[decode] SC_THREAD(clk_ife_) -- 指令解码 -> decode_fifo_
|
v
[check] SC_THREAD(clk_ife_) -- 依赖检查 -> check_fifo_
|
v
[issue] SC_THREAD(clk_ife_) -- 分发到 TIU 或 GDMA
|
+---> tiu_fifo_request_ (深度 2) --[pe_ife_tiu_main_th]--> TIU 引擎
|
+---> gdma_fifo_request_ (深度 2) --[pe_ife_gdma_main_th]--> GDMA 引擎
|
+---> mv_fifo_request_ (深度 MV_FIFO_REQ_LENGTH=2) --> MoveModule

AXI 模式的额外前处理:AXI 数据包先经过 axi_slv_req_mth(SC_METHOD)接收,再由 split_buf640split_buf320(SC_THREAD)将 640-bit / 320-bit 缓冲拆分为 160-bit 指令粒度(axi_data_to_instr()),最终进入 instr_fifo_(深度 INSTR_FIFO_LENGTH=2)。

指令类型识别

IFE 内部的 Instruction 类(framework/include/instruction.h)封装了指令的完整元数据:

  • instr_type_:枚举 {NONE_TYPE, CONFIG, TIU, GDMA, MOVE}
  • TIU 指令由 tiu_desc_parse.h 中的 get_tiu_instr_type() 通过掩码匹配识别(支持 CONV、MM、POOL、AR、SFU、LIN、CMP、SG、RQDQ 等数十种指令类型)
  • GDMA 指令由 gdma_desc_parse.h 中的 get_dma_instr_type() 识别(支持 LD/ST/CP/MLD/MST/HGATHER/HSCATTER/CMPR/DECMPR 等 20+ 种搬运操作)
  • MOVE 指令由 MoveModule 处理,走独立的 mv_fifo_request_/mv_fifo_response_ 通路

依赖 ID 计算

IFE::calc_dep_id() 是 IFE 的核心逻辑之一,负责计算每条指令的依赖 ID(cmd_id_dep),确定它需要等待对端引擎的哪些指令完成。

两种依赖模式(由 CSR 寄存器 CSR_CTRL_0_DIS_AUTO_DEP_ID 控制):

  1. 自动依赖模式DIS_AUTO_DEP_ID = 1):

    • 非 parallel 模式:GDMA 指令依赖当前 tiu_id_counter_,TIU 指令依赖当前 gdma_id_counter_
    • parallel 模式:使用保存的 saved_tiu_cmd_id_ / saved_gdma_cmd_id_
  2. Bitmap 依赖模式DIS_AUTO_DEP_ID = 0):

    • 基于 chunk 粒度的 Read-After-Write / Write-After-Read / Write-After-Write 依赖分析
    • chunk_last_r_id_[]chunk_last_w_id_[] 数组(大小 = Utility::get_chunk_num())记录每个 chunk 最后一次读/写的指令 ID
    • 通过 get_read_bitmap() / get_write_bitmap() 获取指令的 chunk 访问 bitmap
    • 最终 dep_id 取所有冲突 chunk 的 max

IFE 到引擎的传输

IFE 通过 SimplePeInitiator TLM 接口将指令发送到 TIU 和 GDMA:

  • pe_ife_tiu_ini_:IFE -> TIU,pending 计数 pe_ife_tiu_ini_cmd_pend_,最大目标容量 pe_ife_tiu_tgt_cmd_max_ = 1
  • pe_ife_gdma_ini_:IFE -> GDMA,同样的流控

反压机制:当下游引擎的命令 FIFO 满时(TIU: is_tiu_cmd_list_full(),GDMA: is_gdma_cmd_list_full()),IFE 的 issue 阶段会阻塞等待。GDMA 命令 FIFO 容量为 GDMA_CMD_FIFO_LENGTH = 8192 Byte,TIU 的命令 FIFO 容量为 TIU_FIFO_LENGTH = 32768 Byte

Profiling 时间戳

Instruction 对象在流水线每一级记录时间戳(单位 ns),最终输出到 CSV:

  • txi_acq_cycle_:TXI 接收时刻
  • pack_cycle_:打包时刻
  • decode_cycle_:解码完成时刻
  • check_cycle_:依赖检查完成时刻
  • issue_cycle_:发射时刻

TIU 计算流水线

TIU 内部实现了两条独立的 DPC(Data Path Controller)流水线:向量引擎TiuModuleTop)和 Cube 引擎TiuModuleCubeTop)。两者共享相同的 5 级结构,但地址生成和仲裁逻辑不同。

向量引擎流水线(TiuModuleTop)

task_ ──> [DpcDes] ──> [DpcGen] ──> [DpcIssue] ──> [DpcArb] ──> [ComputeUnit]
(2 clk) (1 clk) (1 clk) (bank arb) (计算完成)
| | | | |
vld/rdy 6 bus 6 bus 3 bus last_done_
handshake (opd0~3, (r0,r1,w0) (r0,r1,w0)
res0~1)

每级之间通过 valid/ready 握手协议 实现流控,任何一级的 FIFO 满都会向上游反压。

Stage 1 - DpcDes(描述符加载)

  • 延迟:DPC_DES_DELAY_CYCLE = 2
  • 缓冲区大小:DPC_DES_BUFFER_SIZE = 1
  • 功能:接收 task(tiu_reg_t,即 shared_ptr<TpuCmd>),经过 2 拍延迟后输出到 DpcGen
  • start_in_ 信号控制是否接受新任务,已接收的任务不受影响继续流动

Stage 2 - DpcGen(地址生成)

  • 延迟:DPC_GEN_DELAY_CYCLE = 1
  • 6 个独立地址总线:opd0~opd3(4 个源操作数)、res0~res1(2 个目标操作数)
  • 每条总线宽度 = lane_num 个 64-bit 地址(典型值 16 lanes)
  • 每条总线有独立的 FIFO(深度 = DPC_GEN_DELAY_CYCLE + 5)和独立的 valid/ready 握手
  • 根据指令类型分派到不同的地址生成函数(如 dpc_gen_ar_copydpc_gen_sfu_normaldpc_gen_pool_max 等约 20 个 spec 函数)

Stage 3 - DpcIssue(发射/调度)

  • 延迟:DPC_ISSUE_DELAY_CYCLE = 1
  • 缓冲区:DPC_ISSUE_BUFFER_SIZE = DPC_ISSUE_DELAY_CYCLE + 15 = 16
  • 将 6 路输入总线合并为 3 路输出(r0=opd0, r1=opd1, w0=res0),存入 bus_fifo_BusFifoEntry 结构)
  • 处理不同指令类型的操作数映射(约 20 个 spec 函数,如 dpc_issue_ar_copydpc_issue_sfu_taylor_4x 等)

Stage 4 - DpcArb(Bank 仲裁)

  • calculate_flow_buffer_ 大小 = 32,每个单元包含 BANK_NUM = 16 个 bank 的 busy 标志
  • 检测 r0、r1、w0 三路地址是否访问同一 bank,产生冲突时插入气泡
  • 根据指令类型计算 compute_cycle_(计算流水线延迟,详见 3.3)

Stage 5 - ComputeUnit(计算单元)

  • 接收仲裁后的地址数据(r0_bus, r1_bus, w0_bus)
  • 收到 last_flag_in_ 时输出 last_done_ 信号,标记整条指令执行完成

Cube 引擎流水线(TiuModuleCubeTop)

Cube 引擎处理矩阵乘法(MM/CONV),流水线结构与向量引擎类似但参数不同:

task_ ──> [DpcDes] ──> [DpcGenCube] ──> [DpcIssueCube] ──> [DpcArbCube] ──> [ComputeUnit]
(2 clk) (12 clk) (5 clk) (5 clk) (计算完成)

关键差异

参数向量引擎Cube 引擎
GEN 延迟1 拍DPC_GEN_CUBE_DELAY_CYCLE = 12
ISSUE 延迟1 拍DPC_ISSUE_CUBE_DELAY_CYCLE = 5
ISSUE 缓冲区16DPC_ISSUE_CUBE_BUFFER_SIZE = 8
ARB 延迟动态DPC_ARB_CUBE_DELAY_CYCLE = 5
ARB 缓冲区32DPC_ARB_CUBE_BUFFER_SIZE = 8
地址总线opd03, res01 (6路)opa, opb, w0 (3路)
地址类型uint64_tCubeAddrEntry (含 addr_flag_, psum_add_flag_)

Cube 引擎的地址使用 CubeAddrEntry 结构体:

  • addr_:64-bit 物理地址
  • addr_flag_:标记是否 LMEM 访问或 buffer 命中(命中时跳过实际内存访问)
  • psum_add_flag_:标记是否与上一拍做部分和累加

DpcIssueCube 额外维护了 opa/opb 的 buffer 命中检测逻辑,通过 process_hit_detection()calculate_access_cycles() 判断当前数据是否在内部 buffer 中,命中时减少访存延迟。opa_reuse_ / opb_reuse_ 标记操作数复用。

DpcGenCube 支持两种地址生成模式:dpc_gen_conv(卷积)和 dpc_gen_mm2(矩阵乘法),作为 friend 函数访问 DpcGenCube 内部状态。

计算延迟表(compute_cycle_)

DpcArb::get_compute_cycle() 根据 tsk_typeu_typ 返回不同指令的计算流水线延迟(单位:clock cycle):

tsk_typ指令类型eu_typ延迟 (cycles)
0Convolution-5
1Depthwise/Pooling03
1Depthwise/Poolingothers5
2Matrix Multiply (MM/MM2)-3
3Arithmetic (AR)12 (mul_satu)5
3Arithmetic (AR)131
3Arithmetic (AR)others3
4RQDQ DQ_0-8
5TRANS/BC0 (CW trans)28
5TRANS/BC1 (WC trans)18
5TRANS/BC2 (BC lane copy)12
5TRANS/BC4 (BC static broad)0
5TRANS/BC5 (BC static dist)0
9SFU-3
10LIN (AddSqr)-11
11(未命名)-10
12(未命名)-9
13CMP (Compare)-4
15SYS85
15SYS313

TIU 地址生成与 Bank 冲突

NCHW 地址计算

DpcGen::nchw_to_address() 是向量引擎的核心地址计算函数。它将 NCHW 张量坐标转换为 LMEM 物理地址:

address = base_addr + (n * n_stride +
(c + start_lane)/16 * c_stride +
h * h_stride +
w * w_stride) * precision_bits
  • per_lane_lmem_size = lmem_size / lane_num(典型值:4MB / 16 = 256KB per lane)
  • start_lane = (base_addr / per_lane_lmem_size) % lane_num:从基址中提取 lane 索引
  • precision_bitscalculate_stride_bits() 根据数据类型返回(INT4=4, INT8/FP8=8, FP16/BFP16=16, FP32/TF32=32)

地址最终通过 align_256bit() 对齐到 eu_num_vec / 2 字节边界(典型值 eu_num_vec = 64,对齐到 32 字节)。

calculateEU_NUM() 根据精度返回每个 EU 处理的元素数:INT4=64, INT8/FP8=32, FP16/BFP16=16, FP32/TF32=8。

Bank 冲突检测

DpcArb::address_to_bank() 从物理地址提取 bank ID:

int bank_id = (address >> 14) % 16;   // 右移 14 位后取模 16

即 LMEM 的 bank 交织粒度为 16KB(2^14),共 BANK_NUM = 16 个 bank。

冲突检测机制calculate_flow_buffer_ 是一个 32 深度的 ring buffer,每个 entry 记录 16 个 bank 的 busy 状态。当 r0、r1、w0 三路中有两路或以上访问同一 bank 时,DpcArb 插入等待周期。

Cube 引擎的 DpcArbCube::bank_conflict_check() 对 opa 和 opb 两组向量地址做成对冲突检测,产生的冲突计数 bank_cflt_num_ 作为额外延迟。

FIFO 管理

DpcGen 为每个操作数维护独立的地址 FIFO:

向量引擎: opd0_fifo_, opd1_fifo_, opd2_fifo_, opd3_fifo_, res0_fifo_, res1_fifo_
每个 FIFO 存储 FifoEntry = {num, addresses[lane_num], write_time}
最大深度: DPC_GEN_DELAY_CYCLE + 5 = 6

Cube 引擎: opa_addr_fifo_, opb_addr_fifo_, w0_addr_fifo_, gen_addr_fifo_
存储 CubeGenEntry = {vector<CubeAddrEntry>, write_time}

DpcIssue 额外维护 bus_fifo_BusFifoEntry),将多路输入合并为 r0/r1/w0 三路输出。


WDC 存储控制层次

WDC(Write/Data Controller)是连接 GDMA 和物理 DDR 之间的多级存储控制子系统。源码位于 ip/include/wdc/wdc.h

总体拓扑

GDMA gmem_external_socket_
|
v
[AuxFab<1024,2> fab1t2_] -- 1-to-2 Fabric, clk2G_ (2GHz)
|
+----+----+
| |
v v
[ItlvDemux<1024>] x2 -- 地址交织解复用, clk800M_
| |
+--+ +--+
| | | |
v v v v
[private] [shared_fab1] -- 私有 / 共享 Fabric, clk800M_
AuxFab AuxFabSplit
<1024,8> <1024,1024,2>
| |
| +----+----+
| | |
| v v
| [shared_fab2] x2 -- 二级共享 Fabric, clk800M_
| AuxFabSplit
| <1024,1024,4>
| |
+--+---+ (每 channel 汇合)
|
v
[Fab2t1<1024,1024,1024>] x16 -- 2-to-1 Fabric, clk800M_
|
v
[AuxCam<1024>] x16 -- CAM 调度器, clk800M_
|
v
[X2x<1024,256>] x16 -- 频率/位宽转换, 800M->400M, 1024->256 bit
|
v
[UMC<256> / DramUnit] x16 -- DDR 时序模型, clk400M_

总计 2 个 channel,每 channel 8 个 UMC,共 16 个 DDR 控制器实例。

地址交织解复用(ItlvDemux)

ItlvDemux<1024> 继承自 AuxFab<BusWidth, 2>,重写了 decode() 函数。它根据 AXI 事务的 axi_region_extension 属性将流量分为两路:

  • Port 0:私有 Fabric(private_fab_[i]),8 个输出端口,直连 8 个 Fab2t1
  • Port 1:共享 Fabric(shared_fab1_[i]),2 个输出端口,每个再分为 4 路(shared_fab2_),总计 8 路

ItlvDemux 还检查 GDMA 扩展属性,对写操作判断是否启用 ARE(All-Reduce Engine):当 are_en_are_psum_op_ != 0,或 reduce_en_reduce_psum_op_ != 0 时,在事务上设置 "ARE" 用户属性。

Fabric 层级

AuxFab 是基础的 1-to-N 交叉开关,支持可配置的:

  • 总线宽度(模板参数,典型 1024-bit)
  • 目标端口数(模板参数 TargetNum
  • 读/写 outstanding 数(RD_OSTD_OUT/WR_OSTD_OUT
  • 地址交织位(itlv_bit_ = 12,即 4KB 交织粒度)

AuxFabSplit 是 AuxFab 的变体,支持主/从独立时钟域。共享 Fabric 的 outstanding 限制:

  • shared_fab1_: rd/wr outstanding = 128
  • shared_fab2_: rd/wr outstanding = 64

Fab2t1 是 2-to-1 合并节点(fab_2t1.h),将私有和共享两路流量合并到单个输出,outstanding = 32。

CAM 事务调度(AuxCam)

AuxCam<1024> 位于 Fab2t1 下游,负责 DDR 访问的页面级调度优化。内部包含:

  • read_table_CamTableSemiNested 类型,读请求调度表
  • write_table_CamTableSemiNested 类型,写请求调度表(构造时传入 read_table_ 作为嵌套引用)
  • ar_scheduler():读地址调度,SC_METHOD,每个 clock_.pos() 触发
  • aw_scheduler():写地址调度,SC_METHOD,每个 clock_.pos() 触发

CAM 表的作用是对同一 DDR page 的访问进行重排序,减少 page miss 带来的延迟惩罚。

跨时钟域转换(X2x)

X2x<1024, 256> 实现从 800MHz / 1024-bit 到 400MHz / 256-bit 的频率和位宽转换:

  • 主侧(master):mst_clock_ = clk800M_,1024-bit 接口
  • 从侧(slave):slv_clock_ = clk400M_,256-bit 接口
  • data_width_ratio_ = MstWidth / SlvWidth = 4(每个主侧 beat 拆分为 4 个从侧 beat)

内部 5 个 FIFO 缓冲各 AXI 通道:

  • ar_fifo_(深度 16)、r_fifo_(深度 16)
  • aw_fifo_(深度 16)、w_fifo_(深度 16)
  • b_fifo_(深度 4)

5 个 SC_METHOD 处理各通道:ar_process/aw_process/w_processslv_clock_.pos() 触发,r_process/b_processmst_clock_.pos() 触发。

DDR 时序模型(DramUnit)

DramUnitdram_unit.h)是最底层的 DDR 时序模型,通过 TLM nb_transport_fw 接口接收访问请求。核心参数:

  • open_page_cycle_:打开新页的延迟
  • read_close_page_cycle_ / write_close_page_cycle_:关闭页延迟
  • minimum_read_to_write_cycle_ / minimum_write_to_read_cycle_:读写切换延迟
  • minimal_read_cycle_:最小读周期
  • page_size_:页大小
  • data_width_:数据宽度

时序计算逻辑

  1. Page Hit + 同方向delay += data_beats * clock_period
  2. Page Hit + 写转读:先等待 minimum_write_to_read_cycle_,再加数据传输时间
  3. Page Hit + 读转写:先等待 minimum_read_to_write_cycle_,再加数据传输时间
  4. Page Missdelay += close_page_cycle + open_page_cycle + data_beats * clock_period

其中 data_beats = ceil(data_len / data_width_)。DramUnit 严格保序:sc_assert(sc_time_stamp() + delay >= last_cmd_.first)

UMC<256> 是 DramUnit 的封装:using UMC = DdrWrapper1c<UmcFtSocket<BusWidthBits>>


GDMA 数据通路

GDMA(Global DMA)的实现类是 Tdmac_model/include/sg2260/tdma.hc_model/src/sg2260/tdma.cc)。它使用约 22 个 SC_THREAD 建模一条深度流水线化的数据搬运通路。

命令调度

cmd_list_ (sc_attribute<deque<gdma_des_t>>)
|
v
[cmd_dispatch_mth] SC_METHOD, 敏感于 reset_, transfer_done_, tiu_sync_id_, cmd_list_no_empty_
| 检查 cmd_id_dep <= tiu_sync_id_ 后发射
v
[cmd_collect_th] SC_THREAD, 等待命令完成, 更新 tdma_sync_id_

cmd_dispatch_mth 是 GDMA 的入口。它在以下信号变化时触发:

  • tiu_sync_id_:TIU 完成新指令,可能解除 GDMA 的依赖阻塞
  • transfer_done_:上一条 GDMA 传输完成
  • cmd_list_no_empty_:命令队列非空(check_cmd_list_no_empty 每个时钟上升沿检查)

读写分段流水线

GDMA 的核心流水线由以下 SC_THREAD 组成,通过 sc_fifo 连接:

命令分发
|
+---> [rd_cmd_segmentation_th] ---> rcmd_req_fifo_ ---> [rd_tensor_to_fab_th]
| |
| v
| rd_cmd_fifo_ / rd_fab_req_fifo_
| |
| v
+---> [wr_cmd_segmentation_th] ---> wcmd_req_fifo_ ---> [wr_tensor_to_fab_th]
|
v
wr_cmd_fifo_ / wr_fab_req_fifo_

+--- [rd_ca_mux_th] ---+
| |
ca_req_in_fifo_ <--------+ +-------> ca_req_out_fifo_
| |
+--- [wr_ca_mux_th] ---+
|
v
[ca_to_fab_mux_th]
|
+-----------------------------------+----------------------------+
| |
v v
[fab_rrsp_mux_th] [fab_wrsp_mux_th]
| |
v v
fab_rsp_fifo_ fab_rsp_fifo_
| |
v v
[ca_rsp_th] [ca_rsp_th]
| |
v v
rrsp_to_dp_fifo_ wrsp_to_dp_fifo_
| |
v v
[dp_update_rd_th] [dp_update_wr_th]
| |
v v
[fab_to_tensor_th] [transform_datapath_th]
| |
v v
rd_tensor_rsp_fifo_ wr_tensor_rsp_fifo_
| |
v v
[rd_rsp_th] [wr_rsp_th]
| |
+-------> read_path_done_ / write_path_done_ -------> transfer_done_

特殊搬运模式

GDMA 除了标准的读/写分段外,还为特殊数据模式提供专用线程对:

模式读线程写线程
Gathergather_rd_idx_cmd_seg_th + gather_rd_data_cmd_seg_th-
Scatterscatter_rd_idx_cmd_seg_th + scatter_rd_data_cmd_seg_thscatter_wr_cmd_seg_th
Randmaskrandmask_rd_cmd_seg_thrandmask_wr_cmd_seg_th
Reversereverse_rd_cmd_seg_threverse_wr_cmd_seg_th
Nonzerononzero_rd_cmd_seg_thnonzero_wr_cmd_seg_th
Masked Selectmasked_sel_rd_mask_cmd_seg_th + masked_sel_rd_data_cmd_seg_thmasked_sel_wr_cmd_seg_th

缓冲与 Outstanding 控制

GDMA 的关键缓冲区和流控参数:

  • 读 Outstandingrd_outstanding_(默认 128),通过 rd_ost_sema_map_ 信号量控制
  • 写 Outstandingwr_outstanding_(默认 128),通过 wr_ost_sema_map_ 信号量控制
  • 读缓冲rd_buf_ch_[4](4 个 Tensor1dChannel:dat/idx/meta/map)
  • 写缓冲wr_buf_ch_(1 个 Tensor1dChannel
  • CA 缓冲ca_req_in_fifo_ / ca_rsp_in_fifo_(深度 32)
  • Fabric 响应fab_rsp_fifo_(深度 = rd_outstanding + wr_outstanding

GDMA 通过两个 Agent 与外部存储交互:

  • lmem_agt_(LmemAgent):连接到 LMEM(本地 SRAM),1 端口
  • gmem_agt_(GmemAgent):连接到 DDR(通过 SimpleBus),可配置端口数
  • cache_(GsCache):DDR 访问前置缓存

关键数据结构

TIU 指令描述符(TpuCmd)

TpuCmdspec/base/include/tiu_dma_cmd.h)是所有 TIU 指令的基类:

TpuCmd : BaseCmd
|-- des_cmd_short : bool // 短指令标记 (bit 0)
|-- des_tsk_typ : uint8_t // 任务类型 (bit 41-44, 4 bits)
|-- des_tsk_eu_typ : uint8_t // EU 类型 (bit 45-49, 3~5 bits)
|-- des_cmd_id_dep : uint64_t // 依赖 ID (20 bits)
|-- des_dep_id_en_ : bool // 依赖 ID 使能
|-- cmd_id : uint32_t // 指令 ID (继承自 BaseCmd)
|-- start_time_ : sc_time // 执行开始时间
|-- end_time_ : sc_time // 执行结束时间
|-- alg_ops_ : u64 // 算法级运算量
|-- u_arch_ops_ : u64 // 微架构级运算量
|-- alg_cycle_ : u32 // 算法级 cycle
|-- u_rate_ : float // 利用率
+-- get_des_{res0,opd0,...}_{n,c,h,w}() // NCHW 维度访问器

GDMA 指令描述符(gdma_des_t)

gdma_des_t 定义在 include/gdma_reg_parse.h(由 reg_tdma.h 引用),主要字段包括:

  • cmd_type_:命令类型(GDMA_TENSOR / GDMA_LOSSY_COMPRESS / GDMA_LOSSY_DECOMPRESS 等)
  • cmd_id / cmd_id_dep_:指令 ID 和依赖 ID
  • reduce_en_ / reduce_psum_op_:Reduce 操作使能和操作类型
  • 源/目标地址、数据长度、stride 等搬运参数

TIU 模块配置(TiuModuleCfg)

TiuModuleCfgtiu_module_cfg.h)通过 sc_attribute 存储所有架构参数,在仿真启动时从 JSON 配置加载:

参数含义访问方法
lane_num_Lane 数量get_lane_num()
bank_num_per_lmem_每个 LMEM 的 Bank 数get_bank_num_per_lmem()
eu_num_vec_向量 EU 数量get_eu_num_vec()
eu_width_lmem_EU 宽度 (LMEM 侧)get_eu_width_lmem()
cube_ic_{4,8,16,32}bit_Cube IC 维度 (按精度)get_cube_ic_Xbit()
cube_ohow_{4,8,16,32}bit_Cube OHOW 维度 (按精度)get_cube_ohow_Xbit()
opa_reuse_num_OPA 复用次数get_opa_reuse_num()
psum_h_ / psum_w_部分和 H/W 维度get_psum_h/w()
lmem_size_LMEM 总大小 (字节)get_lmem_size()
is_mix_bank_size_是否混合 bank 大小get_is_mix_bank_size()
r0_buffer_switch_R0 buffer 开关get_r0_buffer_switch()
psum_add_delay_Psum 累加延迟get_psum_add_delay()

全局实例 g_tiu_cfg 被所有 DPC 子模块引用。

时钟周期获取

tiu_module_utils.h 中定义了 get_clock_period() 内联函数,通过 Utility::get_tiu_clock_period() 从运行时配置读取 TIU 时钟频率并转换为 sc_time。宏 CLOCK_PERIOD 是其别名。WDC 内部使用三个独立频率:fab1t2 运行在 clk2G_(2GHz),Fabric/CAM 运行在 clk800M_(800MHz),UMC/DramUnit 运行在 clk400M_(400MHz)。