1. 仿真脚本基础
大家好,我是你们这门课的老朋友。今天咱们聊聊仿真脚本的入门知识。说实话,我刚入行那会儿,对脚本这东西也是又爱又恨。爱的是它能帮我省不少力气,恨的是刚开始总写不对。但后来我发现,搞懂这三个问题,脚本这事儿就通了:它到底是什么?为啥要批量跑?用什么语言写?
1.1 什么是仿真脚本?
说白了,仿真脚本就是一段“自动化指挥代码”。你想想看,平时我们跑一个仿真,是不是得敲一堆命令?比如启动仿真器、加载设计文件、设置波形、跑测试用例、最后看结果……这些步骤要是每次都手动来一遍,手都得抽筋。
仿真脚本的作用,就是把这一连串操作打包成一个“一键执行”的流程。 我习惯把它比作一个“机器人助理”——你告诉它今天要跑哪些测试,它自己就去挨个执行,跑完了还给你整理报告。
举个例子,一个最简单的仿真脚本可能长这样:
#!/bin/bash
# 一个简单的仿真脚本示例
vlog -work work *.sv # 编译所有SystemVerilog文件
vsim -c -do "run -all; quit" work.top_tb # 跑仿真并退出
嗯,这里要注意:脚本本身不改变仿真器的行为,它只是把你要做的事情“自动化”了。我在项目中遇到过不少新人,以为脚本能“优化”仿真速度,其实不是的——它优化的是你的操作效率。
1.2 为什么需要批量运行?
这个问题,我当年也问过自己。单个测试用例跑得好好的,干嘛非要批量跑?
原因其实很简单:一个芯片设计,少说几十个测试用例,多则上千个。 你一个个手动跑,不仅慢,还容易出错。我印象最深的一次,是手动漏跑了一个边界条件的测试,结果流片回来芯片在低温下直接罢工……从那以后,我再也不敢手动跑了。
批量运行的好处,我总结为三点:
- 省时间:晚上下班前点一下批量运行,第二天早上结果就出来了。你想想看,这省了多少盯着屏幕的时间。
- 防遗漏:脚本会按照你设定的列表,一个不落地跑完所有用例。不会出现“哎呀,那个用例我忘了跑”的情况。
- 好追溯:每次批量运行都会生成日志和报告,哪个用例过了、哪个挂了、挂在哪一步,一目了然。我习惯把这些日志按日期归档,出了问题随时翻旧账。
1.3 脚本语言选型:Python vs Shell
好,到了大家最纠结的地方了——到底用 Python 还是 Shell?我两个都用过,踩过不少坑,今天把经验分享给你。
先看一张对比图,帮你快速建立认知:
我个人习惯是:能用 Shell 搞定的,绝不写 Python;一旦逻辑复杂了,果断切 Python。 为什么?因为 Shell 脚本写起来快,但维护起来真让人头大。我见过一个同事用 Shell 写了 500 行的仿真调度脚本,里面全是 if-else 嵌套,改一个参数得找半天。
来看两个实际例子,你就明白了:
场景一:简单编译+运行(Shell 更合适)
#!/bin/bash
# 编译所有文件
vlog -f filelist.f
# 跑三个测试用例
for test in test_a test_b test_c; do
vsim -c -do "run -all; quit" work.top_tb -gTEST_NAME=$test
done
这种场景,Shell 一行顶 Python 十行。我在项目中遇到这种需求,基本 5 分钟就写完了。
场景二:带参数解析、日志分析、结果汇总(Python 更合适)
import subprocess
import json
import os
def run_simulation(test_name, seed):
"""运行单个仿真用例"""
cmd = f"vsim -c -do 'run -all; quit' work.top_tb -gTEST_NAME={test_name} -sv_seed {seed}"
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
return result.returncode
def batch_run(test_list, seed_list):
"""批量运行并汇总结果"""
results = {}
for test in test_list:
for seed in seed_list:
key = f"{test}_seed{seed}"
ret = run_simulation(test, seed)
results[key] = "PASS" if ret == 0 else "FAIL"
print(f"{key}: {results[key]}")
# 生成报告
with open("report.json", "w") as f:
json.dump(results, f, indent=2)
print("报告已生成:report.json")
# 调用示例
batch_run(["test_a", "test_b"], [1, 42, 100])
小结
这一章我们聊了三件事:
- 仿真脚本就是自动化执行仿真流程的“机器人助理”
- 批量运行是为了省时间、防遗漏、好追溯
- 语言选型上,Shell 适合简单任务,Python 适合复杂逻辑