☰
用Makefile自动化VCS+Verdi仿真流程:数字IC验证效率提升实战
2026/10/2 22:31:06 网站建设 项目流程

跑验证的第一天,我就被反复敲命令这事折磨得够呛。每改一次RTL,就得重新敲一遍VCS编译命令,跑完了再敲一遍Verdi打开波形,中间夹杂着各种路径切换和参数调整。后来带我的前辈瞟了一眼我的终端历史记录,丢下一句"这玩意儿不该靠人肉重复",然后给我演示了一个Makefile脚本怎么把编译、仿真、看波形全部串起来。从那时起,我才真正意识到Makefile在数字IC验证流程里的分量。今天这篇就围绕"Makefile脚本启动VCS+Verdi"这个主题,把我在实际项目中验证过、踩过坑之后沉淀下来的完整做法分享出来。

这篇文章适合刚接触数字IC验证、想规范化自己仿真流程的初级工程师,也适合已经在用VCS和Verdi但还在手动敲命令、想提高效率的验证同学。你会看到一套完整的Makefile设计方案,包括变量怎么规划、编译仿真目标怎么拆、fsdb波形怎么自动生成、Verdi怎么一键启动,以及我在实际使用中遇到的那些"没人告诉你"的坑。

1. Makefile + VCS + Verdi 这套组合到底解决了什么问题

1.1 验证工程师的日常真的不应该耗在敲命令上

很多刚入门验证的同学,包括当年的我,会理所当然地认为跑仿真的流程就是"敲命令"—编译、跑仿真、打开Verdi,完事。但当你面对的是一个真实的项目,一个DUT动辄几千行代码,testbench分层结构复杂,还经常需要在不同测试用例之间切换时,手动敲命令的方式会迅速变成灾难。

首先是命令行长度失控。VCS编译一条命令往往要带十几个选项,包括-sverilog、-debug_access+all、-timescale=1ns/1ps、-f filelist.f、-o simv等等,手一抖敲错一个字母,编译失败,重来。其次是参数不一致的问题。今天你顺手加了一个+acc+1,明天别人跑的时候忘了加,编译出来的仿真器行为可能就有差异,波形里看不到内部信号,排查半天发现是编译选项少了。再一个是文件清单管理的问题。RTL文件新增、删除、换路径,如果每个文件都在命令行里手写,每次变动都要去改那行命令,错一个文件,整个编译就挂了。

这套流程跑下来你会发现,真正有产出价值的不是"敲命令"这个动作,而是分析波形、定位bug、收敛覆盖率。Makefile脚本的价值,恰恰是把前面那些机械、重复、容易出错的部分抽象成几个固定目标,把你从命令行里解放出来。

1.2 为什么是Makefile而不是Shell脚本

有人可能会问,写个Shell脚本不也能做到吗?为什么非得用Makefile?

我自己的体会是,Shell脚本当然能做,但它缺少Makefile最核心的一个能力——依赖关系管理。Makefile天然支持目标之间的依赖,比如sim这个目标依赖compile,你只需要make sim,它会先检查编译产物是否存在、源码有没有更新,如果源码比仿真器新,它会自动重新编译,再启动仿真。这个"增量构建"的判断逻辑,用Shell脚本写起来很繁琐,而Makefile是内置的能力。

此外,Makefile的变量机制非常适合工程化管理。工具路径、编译选项、文件列表、波形文件名,全部收敛到文件顶部的变量区。改东西只改一处,不用满脚本去翻去替换。而且Makefile本身的语法足够简单,还能通过make -n预览要执行的命令,通过make -j并行跑多任务,这些都是Shell脚本用起来没那么顺手的地方。

当然,Shell脚本在复杂逻辑处理上也有它的优势,比如循环、条件判断更灵活。但针对VCS+Verdi这个固定的仿真流程,Makefile的简洁和确定性是更合适的。我的建议是把Makefile作为主入口,某些复杂的检查逻辑再单独抽一个Shell脚本让Makefile去调用,各司其职。

1.3 方案选型背后的几条关键考量

在敲定这套方案之前,我还考虑了另外几个点,分享给正在做方案选型的同学参考。

第一点是可移植性。公司里的EDA环境和本地可能不一样,工具安装目录、license配置、库文件路径都有差异。所以在Makefile里把工具路径和关键目录抽成变量,团队内共享时,每个人只需要改机器相关的几行,而不是全文替换。这也是我在后面详细展开变量的原因之一。

第二点是标准化和可继承性。验证环境不是一个人的事,新同学加入团队,不需要从头理解"编译该怎么敲、Verdi怎么连",而是直接make compile、make verdi,看懂了Makefile顶部的变量注释,基本就理解了整个仿真流程。这让环境交接变得非常顺畅。

第三点是和回归测试的衔接。有了Makefile之后,跑回归不是挨个去跑每个test,而是可以定义regress目标,遍历测试用例目录,逐个调用编译好的仿真器,收集结果。这些在手动敲命令的场景下,成本高到没人愿意去做,但在Makefile体系下,只是增加一个目标的事。

2. 动手之前先把Makefile的变量规划和目录结构理清楚

2.1 顶层变量怎么设计才不容易翻车

很多新手写Makefile最大的问题是把路径写死在规则里,改一次路径要大动干戈。我习惯在文件顶部用一个清晰的区域把所有可变项收敛起来,关键变量用:=直接赋值,这样每一行都在定义时就确定下来,后面引用时不会出现递归展开的意外。

我当前项目里的一段变量定义大致是这样:

# 工具路径 VCS := /tools/synopsys/vcs/O-2018.09/bin/vcs VERDI := /tools/synopsys/verdi/V-2020.01/bin/verdi SIMV := ./simv # 仿真参数 VCS_OPTS := -sverilog +v2k +acc+1 -debug_access+all -timescale=1ns/1ps VCS_OPTS += -f filelist.f -o simv -l compile.log VCS_OPTS += -full64 # 运行选项 SIM_OPTS := +fsdb+autoflush +fsdb+dumpfile+$(DUMP_DIR)/wave.fsdb SIM_OPTS += -l sim.log

用:=而不是=,是因为我在定义SIM_OPTS时引用了后面的DUMP_DIR,如果不是展开时立即取值,变量的值在不同位置引用可能得到不一样的结果,排起错来非常头大。另外,工具路径这一项,建议在MAKEFILE里加一个检查,避免在工具链没配置好的机器上跑make,报出来的错误让人摸不着头脑:

$(info 编译工具: $(VCS)) ifeq ($(wildcard $(VCS)),) $(error 未找到VCS工具,请检查VCS路径: $(VCS)) endif

这段代码用wildcard判断文件是否存在,不存在则直接报错退出,早发现早解决,比等到编译阶段报"command not found"要友好得多。

2.2 目录结构怎么规划才能支撑多目录源码编译

关于目录结构,我踩过不少坑,尤其是"多目录源码编译"这个场景。一个中等规模的验证环境,RTL代码通常按模块放在不同目录下,testbench又在另一处,公共VIP包又可能分散在不同地方。如果不做规划,filelist.f就会变成一个巨型文件,维护成本陡增。

我的做法是分层维护文件清单:

. ├── Makefile ├── filelist.f ├── rtl/ │ ├── module_a/ │ │ ├── a_top.v │ │ └── a_sub.v │ └── module_b/ │ └── b_top.v ├── tb/ │ ├── tb_top.sv │ ├── testcase/ │ │ ├── test_basic.sv │ │ └── test_reg.sv │ └── vip/ └── dump/

在这种结构下,filelist.f里用相对路径或绝对路径把要编译的源文件按功能块组织,并加上注释说明每个区块是干啥的:

// RTL 模块 rtl/module_a/a_top.v rtl/module_a/a_sub.v rtl/module_b/b_top.v // Testbench tb/tb_top.sv tb/testcase/test_basic.sv // VIP 组件 tb/vip/ahb_master.sv

针对VCS的库文件处理,如果用到的是编译好的加密IP或者单元库,可以在filelist.f里用-v和-y选项引用,VCS会按指定路径去搜索这些库。这种做法在多目录、多IP的项目里几乎必不可少,Makefile里只需要固定引用filelist.f,内部的组织由维护者按约定维护即可。

2.3 目标设计:compile、sim、verdi、clean各司其职

Makefile的目标设计直接决定你日常使用是"丝滑"还是"别扭"。我的经验是,按验证流程的语义切分目标,不要贪多,也不要太少。

基础目标是这四个:

  • compile:执行VCS编译,产出仿真器可执行文件simv。
  • sim:运行编译好的simv,执行仿真,产出波形文件。
  • verdi:启动Verdi,加载fsdb波形,打开调试界面。
  • clean:清理编译产物和仿真中间文件。

这之外可以按需增加regress(回归)、lint(代码检查)、synth等目标,但核心流程,我建议始终围绕上述四个目标来组织,保持简单可预期。

另外,一定要声明.PHONY。不声明的话,如果目录下恰好存在一个叫clean的同名文件,make clean会被判定为"无需执行"。这是老生常谈,但我见过不止一个同事因为这个诡异问题浪费了半天时间。

.PHONY: compile sim verdi clean regress

3. 完整Makefile脚本实现与VCS/Verdi联合仿真配置

3.1 编译目标:把一次性命令改成可持续复用的资产

先看核心的编译目标。这一步本质上是把VCS的常用编译选项收敛到Makefile变量中,并让后续的仿真目标依赖它的产物。

compile: mkdir -p $(DUMP_DIR) $(VCS) $(VCS_OPTS)

VCS_OPTS里面包含的选项,每个都有它的针对性:

  • -sverilog:启用SystemVerilog语法支持。
  • +v2k:兼容Verilog-2001语法。
  • +acc+1:允许PLI/probe访问,配合Verdi调试时经常需要。
  • -debug_access+all:生成绩效和波形调试所需的完整调试信息,不加的话Verdi打开后的信号可见性会受限,很多内部信号看不到。
  • -full64:以64位模式编译仿真器,处理大规模设计和长仿真时间更稳,尤其是在内存超过4GB的场景。
  • -timescale=1ns/1ps:统一时间精度,避免各文件精度不统一导致仿真时间异常。

编译阶段我会习惯性地加上-l compile.log,把日志写到文件里。编译报错时直接打开log搜索Error关键字,配合编辑器跳转到代码行号,比在终端里翻输出高效得多。

一个实用的小技巧是,在Makefile里定义COVERAGE_OPTS和DEBUG_OPTS两组可选项,通过在命令行用make compile DEBUG=1切换,而不是把所有选项永远堆在一起:

DEBUG ?= 0 ifeq ($(DEBUG),1) VCS_OPTS += -debug_access+all else VCS_OPTS += -debug_access+pp endif

这里?=表示如果命令行没有传入DEBUG变量,就使用默认值0;ifeq做条件判断,按需加入不同的调试信息级别。这样一来,快速跑冒烟测试时可以去掉重调试选项,仿真速度能快不少。

3.2 仿真目标:仿真器运行与fsdb波形自动生成的关键写法

编译完之后就是仿真。仿真的本质是运行./simv,但关键在于波形文件怎么产生,以及Makefile怎么组织才能让整个流程自动化。

关于波形生成,我遇到过两类场景。一是验证代码里已经通过$fsdbDumpfile和$fsdbDumpvars系统任务主动控制波形导出,这种情况下仿真目标里不需要额外干预。二是代码里没有写dump逻辑,尤其是一个通用的testbench要跑多个用例时,我更倾向于不修改仿真代码,而是通过仿真器的命令行参数来控制波形生成,让Makefile来统一处理:

sim: compile $(SIMV) $(SIM_OPTS)

其中SIM_OPTS包含了:

SIM_OPTS := +fsdb+autoflush +fsdb+dumpfile+$(DUMP_DIR)/wave.fsdb SIM_OPTS += +ntb_random_seed=1 -l sim.log

+fsdb+autoflush让仿真边跑边往fsdb文件里刷数据,避免仿真中途崩溃导致波形全部丢失,这个在长仿真里非常重要。+fsdb+dumpfile+指定路径可以在不改testbench的情况下,把波形文件导出到指定目录并指定文件名。这两个参数配合起来,即使代码里一行$fsdbDumpfile都没写,照样能产出波形,非常实用。

如果你在testbench里用initial块主动控制波形层次,那写法通常是:

initial begin $fsdbDumpfile("$(DUMP_DIR)/wave.fsdb"); $fsdbDumpvars(0, tb_top); end

注意$fsdbDumpvars的第一个参数是层级数:0表示dump当前模块以下所有层级的信号,1只dump当前层级,2dump下一层。全开最省心,但文件体积会大很多,这个取舍后面在问题部分细讲。

仿真跑完,别急着关终端。先看sim.log里面有没有Error、Failure之类的关键词,确认没挂再进入下一步。这个检查动作也可以自动化,比如在Makefile里加一个check目标:

check: @grep -E "Error|Failure" sim.log || echo "日志检查通过"

我实际用的时候,还会顺手把pass/fail状态统计出来。UVM的log默认自带UVM_INFO、UVM_ERROR这些标签,用grep过滤一下UVM_ERROR : 0就能判断用例是否通过,做成Makefile里的一个check_log目标,回归的时候非常省事。

3.3 Verdi启动目标:波形加载与快捷键一个都不能少

仿真跑完,到了看波形的环节。在Makefile里把Verdi的启动也固化下来,好处是打开的命令永远是同一套参数,不会因为某次敲错路径而加载不到波形。

verdi: $(VERDI) -f filelist.f -ssf $(DUMP_DIR)/wave.fsdb -top tb_top &

-f filelist.f让Verdi加载所有源码文件;-ssf指定要打开的fsdb波形文件;-top tb_top指定hierarchy顶层。每次执行make verdi,就能直接看到源码和波形同时加载好的调试界面。这里用&把Verdi放到后台启动,避免终端卡在前台进程里,退出Verdi之前无法继续敲命令。

如果仿真还没有跑,也可以启动Verdi先看代码结构、检查fsdb文件是否生成,此时不带-ssf参数即可:

verdi_source: $(VERDI) -f filelist.f -top tb_top &

当Verdi打开之后,几个高频操作我得单独提一下。n和N键是波形窗口里跳转下一个/上一个上升沿,非常常用;在源文件窗口里直接选中信号然后按Ctrl+W可以快速添加波形;按h键可以测光标间的时间差,算时序延迟的时候特别方便。这些快捷键看着小,实际用起来对手感和效率影响巨大,属于"知道的人觉得理所应当、不知道的人手动点半天"的那类知识。

Verdi界面打开后,如果发现有些信号显示为x或者根本找不到,十有八九是编译时的调试信息级别不够。解决方法是回到compile目标,确认VCS_OPTS里带了-debug_access+all或者至少-debug_access+pp,重新编译一次再仿真。

3.4 clean目标与多目标联动的最终整合

最后把clean目标补上,整个基础流程就闭环了:

clean: rm -rf simv simv.daidir csrc verdiLog *.log $(DUMP_DIR) *.fsdb clobber: clean rm -rf *.vpd ucli.key

注意我们在clean里加了*.log和$(DUMP_DIR),确保日志和波形这类体积大的中间产物能被彻底清掉,否则几次迭代跑下来,硬盘很容易被堆满。

然后你日常的使用流程就非常简洁:

make compile # 编译,生成 simv make sim # 仿真,生成 wave.fsdb make verdi # 打开 Verdi,加载源码和波形 make clean # 清理中间文件

调试完一轮修改RTL之后,直接重新make sim,Makefile会发现源文件更新了,自动触发重编译,无需手动分两步执行。这是我的高频用法,也是增量构建最直观的收益。

如果需要一次跑完整个流程,可以把默认目标设置成all:

all: compile sim

然后直接make一把梭。不过我个人建议日常还是分开执行,编译和仿真分开能更早发现是哪一步出问题,日志也更好对。至于all目标,更适合自动化回归或CI场景。

完整脚本放出来,方便直接对照使用:

# ============================================================ # Makefile for VCS + Verdi verification flow # 用法: # make compile 编译RTL+TB,生成simv # make sim 运行仿真,生成fsdb波形 # make verdi 启动Verdi加载源码和波形 # make clean 清理中间文件 # ============================================================ # 工具路径 VCS := /tools/synopsys/vcs/O-2018.09/bin/vcs VERDI := /tools/synopsys/verdi/V-2020.01/bin/verdi SIMV := ./simv # 目录 DUMP_DIR := dump # 编译选项 VCS_OPTS := -sverilog +v2k +acc+1 -debug_access+all VCS_OPTS += -timescale=1ns/1ps -full64 VCS_OPTS += -f filelist.f -o simv -l compile.log # 仿真选项 SIM_OPTS := +fsdb+autoflush +fsdb+dumpfile+$(DUMP_DIR)/wave.fsdb SIM_OPTS += -l sim.log # 声明伪目标 .PHONY: all compile sim verdi clean # 默认目标 all: compile sim # VCS编译 compile: mkdir -p $(DUMP_DIR) $(VCS) $(VCS_OPTS) # 运行仿真 sim: compile $(SIMV) $(SIM_OPTS) # 启动Verdi并加载波形 verdi: $(VERDI) -f filelist.f -ssf $(DUMP_DIR)/wave.fsdb -top tb_top & # 清理编译仿真产物 clean: rm -rf simv simv.daidir csrc verdiLog *.log $(DUMP_DIR) *.fsdb

4. 常见问题排查与避坑实录

4.1 波形打开后一片空白或信号全是x,问题出在哪

这是新手问得最多的问题之一,根源大多出在编译选项上。Verdi要显示内部信号值,依赖的是仿真时留下的调试信息,而VCS默认的编译选项并不会把所有的调试信息都留下来。我在前面反复强调的-debug_access+all,就是为这个场景准备的。

还有同学反馈,波形文件有,信号也在,但全是红色的x。这个通常不是Makefile的问题,而是testbench里没有做正确的复位。复位信号拉高/拉低之后,时序逻辑才会有确定的初值。如果复位逻辑本身写错了,或者复位序列没有在波形里体现,那信号自然是x。排查时先用Verdi的Get Signals功能把复位相关信号加进来,看复位时序是否和预期一致。

如果是加密模块或者第三方IP,信号是x还可能因为模型本身的抽象级别就不支持内部信号观测,这种只能靠IP厂商提供的接口和协议来调试,不是Makefile层面能解决的。

4.2 "make: 没有指明目标并且找不到makefile"是哪里没配置对

这个经典报错,本质是make在当前目录下找不到一个叫Makefile或makefile的文件。常见原因有这么几个:文件名拼错成了Makefiles或者MAKEFILE;当前工作目录不对,比如进了rtl/子目录但Makefile在上一级;或者Makefile被某种方式保护起来没权限读。

遇到这个报错,第一件事是ls -la看目录下到底有没有Makefile。如果没有,看是不是压根没创建,或者放在了其他目录。如果在子目录,可以make -C .. compile指定在父目录执行。如果Makefile存在但有权限问题,chmod +r Makefile解决。

这个看起来特别小白的问题,之所以值得拿出来讲,是因为它往往不是真的不懂Makefile,而是目录切换和路径管理习惯的问题。养成"每次都在项目根目录执行make"的习惯,能少踩很多坑。

4.3 fsdb文件过大,仿真跑了很久但dump阶段直接卡死

波形文件动辄几个GB甚至几十个GB,是长仿真的常见现象。fsdb文件过大的直接后果是Verdi打开极度卡顿,仿真结束前的dump阶段还会因为磁盘IO写入速度跟不上而拖慢整体时间。

我的解决方案是分层次dump。在Makefile里增加一个变量,控制dump的层级数:

DUMP_LEVEL ?= 0 ifeq ($(DUMP_LEVEL),0) SIM_OPTS += +fsdb+level+0 else SIM_OPTS += +fsdb+level+1 endif

跑全芯片级的大回归时,用make sim DUMP_LEVEL=1只dump顶层,快速确认整体行为;定位某个模块内部的bug时,再切回DUMP_LEVEL=0全量dump。这样既保证了调试能力,又不至于让每个用例的波形都大得吓人。

还有一个技巧是,如果你的验证环境里存在模拟模型或者PLL这类高频翻转信号,可以在$fsdbDumpvars之后使用$fsdbDumpvars的补充参数来排除特定模块,或者干脆在信号列表层面过滤。不过这个更细节一些,等真正被波形撑爆硬盘的时候再研究也不迟。

4.4 不同机器/不同VCS版本下Makefile行为不一致

团队协作时最头疼的莫过于"A机器上能跑,B机器上报错"。这种不一致大概率出在工具路径、VCS版本差异、库文件路径几方面。

工具路径的问题,通过把VCS、VERDI变量独立出来,并在文件顶部加上(wildcard)检查可以提前拦截,我在前面已经演示过。VCS版本的差异是最隐蔽的,不同版本对SystemVerilog新特性的支持程度不一样,同一个文件在VCS 2018版本能编译过,到2020版本可能因为某个语法检查更严格直接报错。

应对方法是在Makefile里增加一个版本声明变量和一个展示版本信息的目标:

VERSION_TAG := vcs_$(shell $(VCS) -ID | grep -i version | awk '{print $$4}')

然后在编译日志里记录这个变量,一旦后续仿真行为诡异,先对照编译时用的VCS版本和验证环境配置文件里要求的版本是否一致。别小看这一步,它能帮你避免大量"玄学"low-level的排查时间。

4.5 增量编译不生效,每次都在漫长全量编译中煎熬

Makefile的依赖管理本质上是靠文件时间戳来判断的,但集成到VCS里有个特殊情况:VCS编译的源文件是在filelist.f里指定的,而Makefile的compile目标本身只依赖filelist.f的更新,不会感知到filelist.f里列出的文件是否更新。

也就是说,哪怕你改了一个.v文件,直接在命令行跑make compile,如果filelist.f的mtime没变,Makefile会认为不需要重编译,这是增量编译不生效的最常见原因。

解决方案有几种,但我用得最多的是让Makefile自动检测所有源文件:

SRC_FILES := $(shell cat filelist.f | grep -v '^//' | grep -v '^\s*$')

然后把compile目标的依赖改为$(SRC_FILES):

compile: $(SRC_FILES) $(VCS) $(VCS_OPTS)

这样任何一个源文件更新,make compile都会感知到并重新编译。如果想让VCS内部的增量编译也生效,编译选项里可以加上-Mupdate,让VCS自动维护文件依赖关系,重编译时只增量更新受影响的模块,速度提升非常明显。

4.6 调试大法:make -n和日志逐层定位

最后分享一个我个人最喜欢的排查思路。当Makefile行为不符合预期时,先用make -n compile看Makefile打算执行哪些命令,不要真的执行。这会把你从"猜它为什么这样"中解放出来,直接看它"准备干什么"。

如果命令本身没问题,再去看对应的日志。编译问题看compile.log,仿真问题看sim.log,Verdi加载问题看verdiLog/目录下的日志。分层定位,基本能覆盖90%的情况。

还有一个习惯,我会在Makefile里把调用的关键命令通过@echo打印出来:

compile: @echo "=== VCS Compile Start ===" $(VCS) $(VCS_OPTS) @echo "=== VCS Compile End ==="

这样每次执行的时候,屏幕上能清楚看到当前进行到哪一步,配合-l compile.log,什么时候挂的、在哪一步挂的,一目了然。等环境稳定了,再把@echo注释掉也不迟。

5. 把Makefile再往前推一步:参数化、回归与日常养成

前面对目标层级的讲解已经覆盖了标准的三目标流程,我看到很多团队其实止步于这里,但Makefile的能力远不止这些。我自己在用顺手之后,又增加了两个目标,把日常工作进一步简化。

第一个是test参数化。在验证工作里经常需要给仿真器传test name,比如UVM的+UVM_TESTNAME=test_basic。如果每次都在命令行手动写,麻烦且容易错。在Makefile里定义一个TEST变量,透传到SIM_OPTS里:

TEST ?= test_basic SIM_OPTS += +UVM_TESTNAME=$(TEST)

日常跑用例只需要:

make sim TEST=test_reg

第二个是回归目标。当用例多了之后,逐个执行显然不现实,我加了一个regress目标,遍历一个测试用例清单文件,逐个跑仿真:

regress: for test in `cat testlist.txt`; do \ $(SIMV) +UVM_TESTNAME=$$test +fsdb+autoflush -l log_$$test.log; \ done @echo "回归完成,请查看各 log 文件"

这里要注意,回归里如果还每个用例都dump fsdb,磁盘和耗时都受不了,我一般会在regress的仿真参数里不携带+fsdb+dumpfile+,只靠log做结果判别。需要追查失败用例时,再单独make sim TEST=xxx重新生成fsdb。

这种做法的意义在于,让Makefile的脚本能力随着验证环境的成长而成长。它不是一个写完就固定不变的脚本,而是一个可以持续增加目标来适配新需求的自动化入口。这也是Makefile和一次性Shell命令之间最本质的区别——前者是可持续积累的资产,后者只是临时工具。

回到开头那个问题:用Makefile启动VCS和Verdi,到底是为了什么?我认为核心是为了把人的注意力从机械命令里释放出来,让验证工程师把更多精力投入到真正有挑战性的调试和分析中去。当我看到新同事拿到这套脚本,不用问任何问题就能make compile && make sim && make verdi跑通第一个用例时,我觉得当初花时间把这些命令收敛成目标,是非常值得的。

以上是这套方案的全部内容。如果你在实际配置过程中遇到其他问题,尤其是和VCS版本、Verdi加载、多目录源码相关的坑,欢迎一起交流。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询