第二章:版本控制(Git)在RTL项目中的使用
版本控制这事儿,很多做RTL的兄弟一开始不太当回事。我刚开始带项目的时候,见过有人用final.v、final_v2.v、final_really_final.v这种命名法……嗯,后来仿真出问题查了三天,才发现是版本搞混了。
说白了,Git就是你的后悔药和时光机。在CI流水线里,它更是整个自动化的起点。没有规范的Git管理,流水线跑得再快也是乱的。
仓库结构怎么搭
我建议一个RTL项目对应一个Git仓库。别把几十个IP核塞到一个仓库里,后期CI跑起来你会哭的。
典型的RTL仓库结构长这样:
project_name/
├── rtl/ # 设计源代码
│ ├── top/
│ ├── module_a/
│ └── module_b/
├── sim/ # 仿真相关
│ ├── tests/ # 测试用例
│ ├── tb/ # testbench
│ └── waves/ # 波形(一般不提交)
├── scripts/ # 编译、仿真、综合脚本
├── constraints/ # SDC约束文件
├── doc/ # 设计文档
├── .gitignore
└── README.md
这里有个坑。我曾经见过一个团队把sim/waves/下的vcd波形文件全部commit了,仓库活生生撑到2个G。每次clone都要等半天。
.gitignore配置——绕不开的学问
一个设计良好的.gitignore文件,能帮你省很多烦心事。我习惯从一开始就配置好,免得后面有人不小心把中间文件推上去。
RTL项目常用的忽略规则:
# 仿真生成文件
*.vcd
*.vpd
*.fsdb
*.wlft*
*.log
*.dump
# 综合/实现产物
*.ddc
*.mdd
*.sdc.out
*.vg # 网表
*.svf # 形式验证文件
*.syn*
# 编译中间文件
*.o
*.obj
work/ # ModelSim/VCS工作库
xsim.dir/ # Vivado仿真目录
.cache/
# IDE临时文件
*.swp
*.swo
.DS_Store
Thumbs.db
你想想看,要是一不小心把综合出来的网表提交了,review时大家对着几千行的gate-level代码看差异……那画面太美我不敢看。
git rm --cached手动处理。
分支策略——选对路子,少走弯路
在CI流水线里,分支策略决定了自动化触发的时机。我推荐基于Trunk-based或Git Flow的变体,适合RTL项目。核心原则就一条:main分支永远是可流片/可发布的。
常用的分支角色:
| 分支类型 | 命名示例 | 谁来用 | CI触发什么 |
|---|---|---|---|
| 功能开发 | feature/spi-master | 设计师 | Lint + 基本仿真 |
| Bug修复 | fix/timing-violation | 设计师 | 回归测试 |
| 发布准备 | release/v2.1 | 项目组 | 全量回归 + 综合 |
| 紧急修复 | hotfix/reset-glitch | 资深工程师 | 快速Lint + 全量仿真 |
我个人习惯用develop作为日常集成分支。每个feature分支开发完后,向develop发起Pull Request。PR通过后,CI自动触发回归测试。main分支只接受release或hotfix的合并。
有一次项目赶工期,有人直接往main上push了未验证的代码。流水线一跑,Lint报了两百多个warning,仿真直接挂掉。从那以后,我强制开启了main分支的protected规则——没有review和CI通过,谁都别想合并。
代码提交规范——写commit也是一门手艺
很多RTL工程师写commit message写得很随意,比如fix bug、update。过两个月回来看,根本不知道改了啥。在CI流水线的上下文里,好的commit message能帮助自动生成变更日志,甚至影响自动化工具的决策。
我推荐使用Conventional Commits规范,稍作调整适配RTL场景:
类型(范围): 一句话描述
详细说明(可选,包括为什么改、怎么改、影响哪些模块)
Closes #123
类型可以用这些:
feat—— 新功能模块fix—— Bug修复perf—— 时序/面积优化refactor—— 代码重构,功能不变test—— 增加测试doc—— 文档更新ci—— CI配置变更
举个例子:
feat(axi_slave): 实现AXI4-Lite从设备接口
- 添加读写通道FSM
- 支持burst长度1~16
- 增加地址对齐检查
Closes #45
为什么要这么写?因为在CI流水线里,工具可以自动解析commit message,决定是否触发特定环节。比如commit类型是feat,就触发全量回归;类型是doc,就只同步文档到wiki。
嗯,最后说一点。Git不是存代码的仓库,它更是团队的沟通工具。好的分支策略和commit规范,能让CI流水线跑得更聪明,也能让合作更顺畅。