ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

tiny-gpu Verilog 重构实录:3 个关键手法提升硬件代码可读性

tiny-gpu Verilog 重构实录:3 个关键手法提升硬件代码可读性 tiny-gpu Verilog 重构实录3 个关键手法提升硬件代码可读性【免费下载链接】tiny-gpuA minimal GPU design in Verilog to learn how GPUs work from the ground up项目地址: https://gitcode.com/GitHub_Trending/ti/tiny-gpu想象这样的场景你只想改计算核心里的一处状态跳转却发现 6 个文件里有 12 处裸二进制比较要逐一核对而这些比特的“名字”只存在于 src/scheduler.sv 里一行 localparam 中。tiny-gpu 是一个用 Verilog 从零实现的微型 GPU用来理解 GPU 硬件如何工作。这篇文章复盘我们为它做 Verilog 代码质量重构的完整过程问题出在哪里、按什么顺序改、以及怎么借助现有仿真体系证明没改坏。图1tiny-gpu 整体架构顶层 gpu 模块下挂多个计算核心与数据/程序两组内存控制器现状盘点三处让人不敢下手的代码气味本章结论重构清单来自文件级证据而不是凭感觉——下面三个问题都能直接打开文件定位。状态语义一处定义、别处按编码识别。src/scheduler.sv 用具名常量定义了核心的 8 个状态IDLE 到 DONE但 src/alu.sv、src/fetcher.sv、src/lsu.sv、src/decoder.sv、src/pc.sv、src/registers.sv 全靠core_state 3b101这类裸编码识别状态grep 统计共 12 处。改一次编码、加一个状态就要翻 6 个文件。核心模块是总装车间。src/core.sv 约 212 行自行声明 14 个decoded_*控制信号再逐线分发给 decoder、scheduler 和每线程的 ALU/LSU/寄存器堆/PC顶层 src/gpu.sv 也有 217 行。每加一个控制位声明处和所有端口列表要同时动。测试只跑 happy path。test/ 下两个 kernel 测试分别仿真 1x8 矩阵加法和 2x2 矩阵乘法线程数为 8 和 4恰好都是每块容量 4src/gpu.sv 的THREADS_PER_BLOCK参数的整数倍“块不满、部分 ALU 停用”的路径从未被触发Makefile 里的 VCD 波形目标还挂着 TODO。重构路线先定边界再动内部本章结论不追求一次重写按三步推进每步都能用make test独立验证。先明确一个原则保留现有的三层结构。src/gpu.sv负责芯片级集成设备控制寄存器、线程分发、内存控制器src/core.sv是计算核心每线程的 ALU/LSU/PC/寄存器堆是叶子模块。这个边界拆分本身是合理的坏掉的是模块内部的耦合方式而不是模块边界所以重构不该以文件数量为目标。路线由此清晰集中状态语义把 12 处裸编码改为对共享具名常量的引用机械改动最多、风险最低可读性收益也最直接核心接口瘦身把 14 条分散的控制信号束成一个结构体以后加控制位只动一处定义补上回归保护在现有 cocotb iverilog sv2v 仿真流程上补边界用例让前面每一步改动都必须先通过两个 kernel 的仿真。图2tiny-gpu 单个计算核心的内部结构每线程一套执行资源由统一调度器驱动为什么是这个顺序状态机常量是耦合最密的点先改端口结构而不改常量新结构体里装的还是同样的 3 位魔法值收益会打对折测试回归放在最后是因为它要在前两步完成时立刻提供行为等价性的判定依据。环境按 README.md 准备好 iverilog、cocotb 与 sv2v 后make test_matadd/make test_matmul即可复现文中所有仿真。关键手法三个可落地的改法 ️本章结论三个手法一一对应上面的三个问题均给出前后代码对照“重构后”是基于仓库现状的改进示范。状态机怎么写得可读用共享常量替换裸编码仓库里其实已经有正确示范内存控制器 src/controller.sv 用 localparam 定义 5 个通道状态、case 里按名字判断——核心子模块缺的只是同样做法。把常量从 scheduler 的私有 localparam 挪进共享定义SystemVerilog 可用 package 或 include 头文件// 重构前src/alu.sv 实际代码靠裸编码认出 EXECUTE if (core_state 3b101) begin // ADD/SUB/MUL/DIV 在此执行 alu_out_reg rs rt; end // 重构后常量移入共享定义后比较对象是名字 // package core_pkg; localparam [2:0] EXECUTE 3b101, ...; endpackage if (core_state EXECUTE) begin alu_out_reg rs rt; end改动的本质不是重命名而是让状态语义有了单一归属以后加状态、调编码只动 packagescheduler 里lsu_state[i] 2b01这类裸比较照方抓药读代码的人不再需要翻编码对照表。图3tiny-gpu 每个线程的执行资源与数据通路状态机的推进就发生在这些资源之间给 core.sv 接口瘦身控制信号束成结构体14 个decoded_*信号目前在 core.sv 中逐个声明每个子模块的端口列表再各自挑子集接线光一个 ALU 实例就要连十几根线。束成结构体后整体传递// 重构前src/core.sv 实际代码逐个声明逐线连接 reg [3:0] decoded_rd_address; reg [3:0] decoded_rs_address; reg [7:0] decoded_immediate; reg [1:0] decoded_alu_arithmetic_mux; // ... 其余 10 个信号再向每个子模块端口逐一挂线 // 重构后一个结构体整体传递 typedef struct packed { logic [3:0] rd, rs, rt; logic [7:0] imm; logic [2:0] nzp; logic [1:0] alu_op, reg_mux; logic reg_we, mem_re, mem_we, nzp_we, out_mux, pc_mux, ret; } ctrl_t;本质是把“点对点布线”收敛成“总线式传递”新增控制位时只改结构体定义和 decoder子模块端口列表不必再动顶层例化的连线宽度也一并压缩后面看波形时接口一目了然。测试安全网用现有仿真体系补边界现有测试底子不差test/test_matmul.py 跑完整 2x2 矩阵乘法并逐元素断言仿真每一周期由format_cycle落盘日志本身就是最好的回归材料。缺口在边界两个 kernel 的线程数都不是“块不满”的数字。沿同一套 cocotb 流程补一个最小用例# 重构前现有测试的通用写法线程数总是块容量 4 的整数倍 for i, exp in enumerate(expected): assert data_memory.memory[i 8] exp # 重构后matadd 程序跑 3 线程只断言前 3 个元素 threads 3 # 触发 enable (i thread_count) 的路径 await setup(dut, program_memory, program, data_memory, data, threads) assert data_memory.memory[0:3] expected[:3]补这个测试的本质不是“能抓到 bug”而是让enable (i thread_count)这条路径第一次有了负责人——matmul 每个线程产出一个输出元素必须保持 4 线程matadd 的逐元素加法恰好适合 3 线程场景。图4tiny-gpu 的仿真执行追踪输出重构前后用同一份日志即可比对行为是否一致效果验证与后续方向 ✅本章结论文中每项改进都能对照仓库核实不编造百分比收益。可核实的数字先说清楚示范重构完成后12 处裸二进制状态比较降为 0grep 前后各统计一次core.sv 中 14 个分散的控制信号声明收敛为 1 个结构体定义make test_matadd与make test_matmul继续通过执行追踪日志结构不变行为等价成立。至于“排查耗时缩短多少”没有精确测量从读码和对照注释的体验看是明显提升这里就不写数字。后续优化方向有三个接上波形Makefile 的show_%目标已预留 gtkwave 接入VCD 转储还是 TODO启用后状态跳转可直接在屏幕上观察是状态机调试闭环的最后一块补边界矩阵块不满用例之后再加除数为零的边界DIV 指令目前没有保护两者都能复用现有 Memory 与 setup 流程接住下一项特性README 的 Next Steps 列了流水线、分支发散、内存合并与 Tiny Tapeout 7 适配每一项都会给重构后的模块结构施压这正是把接口留干净的回报。下一篇我们从 scheduler 的 WAIT 状态切入讲如何在这套干净的结构上引入流水线与 warp 调度。【免费下载链接】tiny-gpuA minimal GPU design in Verilog to learn how GPUs work from the ground up项目地址: https://gitcode.com/GitHub_Trending/ti/tiny-gpu创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表