ARTICLE DETAIL

资讯详情

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

tiny-gpu 代码质量提升实战:3 处改造让 Verilog 源码更好读

tiny-gpu 代码质量提升实战:3 处改造让 Verilog 源码更好读 tiny-gpu 代码质量提升实战3 处改造让 Verilog 源码更好读【免费下载链接】tiny-gpuA minimal GPU design in Verilog to learn how GPUs work from the ground up项目地址: https://gitcode.com/GitHub_Trending/ti/tiny-gputiny-gpu 是用 Verilog 实现的微型 GPU12 个源文件覆盖 GPU 架构与 SIMD 线程。读完你能完成 3 处代码质量改造拆薄顶层、替换状态机魔法数字、补齐命名与测试每处附改前改后对照。一、先给代码做体检4 个维度判断 Verilog 质量动手前先把仓库拉到本地本仓库只读改代码在你自己的副本里git clone https://gitcode.com/GitHub_Trending/ti/tiny-gpu判断这份源码值不值得继续读看 4 个维度。每个维度都给你一条好/差的划线标准维度什么算好什么算差职责一个文件干一类活打开就知道管什么顶层文件实例化、搬运、调度全干可读性状态常量定义一次全仓按名字用二进制魔法数字要翻别的文件查编码注释注释头与架构图对得上无拼写错误复制粘贴残留单词拼错可验证性改动后有测试回归、有逐周期执行轨迹只有功能测试边界路径没人管对照 src/ 下的 12 个 .sv 文件过一遍你会在 src/gpu.sv、src/fetcher.sv、src/lsu.sv 里找到对应的短板。下面三处实战改造每处都按看到什么 → 为什么是问题 → 怎么改 → 怎么确认走一遍。二、实战① 模块职责拆分把 217 行的顶层文件拆薄你会看到gpu.sv 一边实例化一边当信号搬运工gpu.sv是全仓最长的文件217 行。它在顶层干了四件事实例化设备控制寄存器、两个内存控制器、调度器以及 N 个计算核心。第四件不太显眼在 generate 循环里它还写了一段逐位搬运代码把每个 core 的 LSU 信号按i*THREADS_PER_BLOCK j的索引翻到全局总线信号上。// src/gpu.sv顶层文件里混入的信号中继 localparam lsu_index i * THREADS_PER_BLOCK j; always (posedge clk) begin lsu_read_valid[lsu_index] core_lsu_read_valid[j]; lsu_read_address[lsu_index] core_lsu_read_address[j]; lsu_write_valid[lsu_index] core_lsu_write_valid[j]; lsu_write_address[lsu_index] core_lsu_write_address[j]; lsu_write_data[lsu_index] core_lsu_write_data[j]; core_lsu_read_ready[j] lsu_read_ready[lsu_index]; core_lsu_read_data[j] lsu_read_data[lsu_index]; core_lsu_write_ready[j] lsu_write_ready[lsu_index]; end为什么是问题217 行里混着 16 行搬信号的代码这段逻辑没有一行 GPU 行为纯做索引映射却占了约 16 行。类比一下这栋楼的门房既接待来访、又分拣快递、还代收代转包裹。代码注释说清了缘由——OpenLane 流程要求 Verilog 2005顶层不能切片信号所以额外声明了一组信号。但信号必须存在和搬运逻辑必须写在顶层是两回事。怎么改把索引映射搬进独立模块信号组保留EDA 要求搬运逻辑抽成小模块。逐位赋值其实可以整根向量一次搬完// lsu_map.sv中继逻辑独立成模块 module lsu_map #( parameter THREADS_PER_BLOCK 4 ) ( input wire [THREADS_PER_BLOCK-1:0] core_read_valid, output reg [THREADS_PER_BLOCK-1:0] global_read_valid // address/data/ready 各一组同型端口 ); always (posedge clk) global_read_valid core_read_valid; // 整根向量一次搬完 endmodule改完后 src/gpu.sv 只剩实例化和接线回归组装本职。src/core.sv 那 18 个端口不用动它管核心内部职责本来就干净。改完怎么确认编译等价 两个 kernel 回归用 Makefile 里的现成流程make compile走 sv2v iverilog编译通过再跑make test_matadd和make test_matmul两个 kernel 的最终矩阵结果不变。逻辑等价拆分才算安全。图 1tiny-gpu 核心内每个线程的执行路径拆分时各模块边界要与此图一一对应三、实战② 控制流可读性GPU 状态机魔法数字怎么换掉你会看到core_state 的编码只有一处文件说得清scheduler定义了 7 个核心状态IDLE到DONE每个都起了名字。但其他模块引用这个状态时用的全是裸二进制。数一下grepcore_state 3b有 12 行加上 fetcher/lsu 的状态比较共 14 行散在 7 个文件里。// src/fetcher.sv:42 —— 3b001 是什么文件里没说 if (core_state 3b001) begin // src/alu.sv:36 —— 3b101继续猜 if (core_state 3b101) begin // src/lsu.sv:55 —— 011 又是哪个阶段 if (core_state 3b011) begin为什么是问题状态是跨 7 个模块的导线常量却藏在 1 处core_state从 src/scheduler.sv 出发一路被 fetcher、decoder、alu、lsu、pc、registers 读取。这像公司内部群发编号电报只有发报那间办公室留着编号对照表其他人收到3b101只能翻到 scheduler 里对表。对表一次没感觉改一次状态编码就是全仓事故。怎么改建一张全模块共享的状态常量表把状态定义挪进共享文件各模块改按名字引用// core_state.svh —— 全模块共享的状态常量 localparam FETCH 3b001, // 取指 DECODE 3b010, // 译码 REQUEST 3b011, // 发起访存 WAIT 3b100, // 等内存响应 EXECUTE 3b101, // 执行 ALU 与 PC UPDATE 3b110; // 回写寄存器 // src/fetcher.sv 改后 if (core_state FETCH) beginMakefile 的sv2v -I src/*会把 src 目录当 include 路径.svh用include引入即可构建不用改。改完怎么确认grep 归零仿真结果不变验收命令一条grep -rn core_state 3b src/14 处裸比较全部改名后应返回 0 行。再跑make test_matadd与make test_matmul逐周期轨迹与之前一致。状态机改造最省事的定位法就是先 grep 魔法数字数清几处再逐处替换。四、实战③ 命名、注释与验证体系从拼写错误到边界测试你会看到注释头很规范但藏着 1 处拼写错误这份代码的注释头值得表扬。每个文件开头都是模块名 三行职责说明的格式src/decoder.sv 的操作码常量表NOP 4b0000 … RET 4b1111与 ISA 表一一对应就是文档图在源码里的版本图 2tiny-gpu 的 11 条指令与 4 位操作码编码decoder.sv 的 localparam 与此表逐项对应但 src/lsu.sv 第 16 行留了个真问题// 改前src/lsu.sv:16Signals 拼成了 Sgiansl // Memory Control Sgiansl注释拼错一个词像门店招牌打错字。客户不会因此少但印象分先掉了。改后就是// Memory Control Signals一行搞定。为什么是问题好注释是资产测试却是只查最终答案命名与注释的短板只有这一处真正薄的是验证体系。test/test_matmul.py 和 test/test_matadd.py 是仅有的两个 cocotb【免费下载链接】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),仅供参考
返回列表