☰
VCS 2021.09安装配置与IC设计仿真环境避坑指南
2026/11/4 12:31:55 网站建设 项目流程

简介:《VCS User Guide》为Synopsys VCS官方用户手册(S-2021.09版),面向IC设计、验证工程师及电子信息相关专业学习者,用于系统了解VCS仿真验证工具的安装配置、环境搭建、库管理与日常使用。压缩包内共1个PDF文件,大小约11.36MB,正文涵盖许可证获取、synopsys_sim.setup创建、库概念与名称映射、仿真器设置、技术支持等章节,并涉及命令行与图形界面配置、日志查看和调试排错等内容,便于按目录查阅完整流程。已有4339人学习或下载,具有较高参考热度。手册可作为查阅型资料,帮助读者熟悉数字、模拟及混合信号IC验证中的基础操作与关键概念,在搭建仿真环境、定位配置问题和规范工具使用流程时提供依据,也可用于快速检索术语、流程说明与常见问题,减少摸索时间,适合IC验证入门者与日常工程实践参考。

1. 一份 VCS 2021.09 装在 IC 设计服务器上:先对齐 license 和 timescale 再谈编译

IC 设计 的仿真环境里,VCS 属于那种「装一次能用三年,装错一次折腾三天」的工具。我见过最常见的场景:新服务器到位,目录结构照抄老机器,vlogan能跑,simv一起来就卡在 license;或者更玄学的——编译全过、波形全 X,最后发现两台机器的 timescale 精度不一样。

S-2021.09 这个版本的文档随安装包放在$VCS_HOME/doc下,很多人拿到 PDF 先翻参数表,其实前三章才是重点:环境变量、setup 文件、库映射。装不好不会立刻报错,而是让你在回归跑到一半时才发现结果对不上,那种时候排错的成本是安装阶段的十倍。这篇笔记按「先清点环境 → 再建库 → 再编译 → 最后验证」走一遍,适合第一次独立在服务器上搭 VCS 的人,也适合接手别人半成品环境的人。

2. 装机前的环境清点:VCS 2021.09 的目录、变量和 license 三件套

装 VCS 这件事,安装包本身反而是最简单的部分,展开就能用;真正决定成败的是安装前那半小时的清点工作。我一般会把它拆成三块:机器能不能跑、license 拿不拿得到、路径变量有没有写对。这三块任何一块出问题,表现出来的现象都长得很像——工具启动失败或者跑一半挂住,新手很容易误判成安装包损坏,然后重装三遍,白折腾。

2.1 系统、编译器与内核参数自检

VCS 是纯 64 位工具链,而且编译 DPI、PLI 那类 C 代码时要调用本机 gcc。先把这几项打出来看一眼:

uname -srm # 内核与架构,必须是 x86_64 getconf LONG_BIT # 输出 64 gcc --version | head -1 # 编译 DPI/PLI 用 ulimit -s # 栈大小,单位 KB df -h /opt /tmp # 安装目录与临时目录空间

-full64这个参数基本是所有命令的标配,但机器本身是 32 位的话加了也没用,所以先看getconf LONG_BIT。

gcc 版本是个隐性坑。新版发行版自带 gcc 往往偏新,而工具链自带的头文件是按老编译器写的,编译 DPI 时会出现一堆error: unknown type name。常见做法是单独装一个 4.8 或 7.3 的 gcc,然后在环境脚本里把CC、CXX指过去,别动系统默认的。

ulimit -s默认一般是 8192,小设计够用,几十万门以上的设计做 elaborate 时容易直接段错误退出,日志里还看不出原因。我一般会在环境脚本里加一句ulimit -s unlimited,或者至少提到 65536。

/tmp空间同样容易忽略。vcs 在细化阶段会往csrc目录和临时目录写大量中间文件,一个稍大的设计占十几 GB 很正常,/tmp单独分区只有 20G 的话,跑到一半报「No space left on device」就很常见了。

2.2 license 与环境变量:先确认拿得到再动手

安装之前先确认 license 服务可达,这一步能省掉后面 80% 的疑似安装故障。

# 指向 license 服务器,端口和主机名按实际环境替换 export LM_LICENSE_FILE=27020@lic-srv # 查看该服务上有哪些特性被占用、还有多少空闲 lmstat -a -c $LM_LICENSE_FILE | grep -i -E "vcs|Users of"

LM_LICENSE_FILE是通用变量名,多数工具链都认;有些环境还会额外用厂商自己的专用变量,两个都设上不冲突,反而是保险做法。lmstat的输出重点看两处:Users of ...后面括号里的数字是「已用/总数」,如果已用已经等于总数,那不是你装错了,是排队问题。

提示:批处理作业系统(LSF、Slurm 之类)提交时不一定继承登录 shell 的环境变量,很多人本地跑得好好的,一进队列就报 license 错,原因就在这里。环境脚本要在作业脚本开头重新 source 一次。

编译和运行时都建议加上+vcs+lic+wait,作用是在 license 全被占用时排队等待而不是直接失败。回归夜里跑几百个 case,没有这个参数的话,前几个把 license 占满,后面全部瞬间失败,早上一看日志一片红,以为是设计问题。

还有一点:license 里的版本号要和安装的版本对得上。S-2021.09 需要服务端有对应版本的特性行,版本太老的 license 文件即使能 checkout,也可能在细化阶段报版本不匹配。

2.3 安装目录规划与环境变量脚本

目录我一般这样分:工具装/opt/eda/,工程放/proj/,中间产物放本地盘或者高速盘。工具目录装完就只读,别往里写东西,不然下次升级会很难受。

# /opt/eda/env/vcs.sh —— 每次开新 shell 都 source 一次 export VCS_HOME=/opt/eda/vcs/S-2021.09 export PATH=$VCS_HOME/bin:$PATH export LD_LIBRARY_PATH=$VCS_HOME/linux64/lib:$LD_LIBRARY_PATH export LM_LICENSE_FILE=27020@lic-srv ulimit -s unlimited # 检查关键可执行文件是否都在 ls $VCS_HOME/bin | grep -E "^(vcs|vlogan|vhdlan|vdir)$" which vcs vlogan vhdlan

PATH一定要放在最前面,别用PATH=$PATH:$VCS_HOME/bin这种追加写法。机器上装了两三个版本的时候,追加写法会让老版本优先命中,vcs -ID查出来是哪个版本会发现根本不是你以为的那个,这种坑排查起来非常费时间。

LD_LIBRARY_PATH指向linux64/lib,缺了它最典型的报错是启动时提示找不到某个.so。有些机器上还会遇到架构判断错误,这时候才需要加VCS_ARCH_OVERRIDE=linux64强制指定,平时不用设。

变量典型值作用写错的后果
VCS_HOME/opt/eda/vcs/S-2021.09工具根目录文档、库路径全部找不到
PATH$VCS_HOME/bin:$PATH命令查找命中老版本或 command not found
LD_LIBRARY_PATH$VCS_HOME/linux64/lib运行时库启动报.so缺失
LM_LICENSE_FILE27020@lic-srvlicense 服务编译/仿真卡在 checkout
SYNOPSYS_SIM_SETUP工程内 setup 文件绝对路径指定库映射读到 home 里的旧配置

3. 库与 setup 文件:synopsys_sim.setup 的映射规则和查找顺序

VCS 里「库(library)」的概念和软件工程里的库不太一样,它更像一个存放已分析设计单元的容器:vlogan或vhdlan把源码分析进某个库,细化阶段再从库里按名字找模块。库到物理目录的对应关系,全靠synopsys_sim.setup这个文本文件描述。这份文件写错,报错信息往往只有一句「module not found」,看不出任何线索。

3.1 两段式还是三段式:先定流程再建库

流程选错,后面所有脚本都得重写,所以第一步先把这件事定下来。

流程命令序列适用场景增量能力
两段式vcs→simv纯 Verilog / SystemVerilog 工程加-Mupdate可增量编译
三段式vhdlan/vlogan→vcs→simv含 VHDL、混合语言、需要分库管理改一个文件只重新分析该文件

判断标准很简单:工程里有.vhd文件,就必须走三段式,因为vcs单条命令不能直接吃 VHDL。就算全是 Verilog,如果设计规模大、编译一次要十几分钟,也建议走三段式,因为分析阶段是文件粒度的,改一个文件只重分析一个,细化阶段可以靠-Mupdate增量,整体迭代速度能快好几倍。

混合语言工程还有个隐含要求:VHDL 和 Verilog 之间的层次引用,必须在细化阶段一次性解析完,所以三段式的第二步不能省。

3.2 setup 文件里到底写什么

一个能用的最小 setup 文件长这样,放在工程根目录:

# ./synopsys_sim.setup work : ./work rtl_lib : ./libs/rtl tb_lib : ./libs/tb gate_lib : ./libs/gate # 把站点级公共配置拆出去,避免每个工程抄一遍 INCLUDE /proj/common/site.setup

每行的格式是库名 : 物理路径,冒号两边空格随意,但库名不能带空格。work是默认库名,vlogan不给-work参数时就会往这里写。

路径写相对还是绝对,是这里最容易踩的坑:相对路径是相对于你敲命令时的当前目录,不是相对于 setup 文件所在目录。所以同一个 setup 文件,在工程根目录下跑和在sim/子目录下跑,指向的是两个不同的物理目录,表现就是「明明分析过了却说模块不存在」。我的习惯是库路径一律写绝对路径,或者用$ENV{变量}展开,宁可长一点。

注意:INCLUDE引入的文件里如果又定义了同名的库,后面的定义会覆盖前面的。站点级配置里放公共工艺库,工程级 setup 里放项目库,顺序别搞反。

手册第 1 章的 Library Name Mapping 一节讲的是库名别名映射:设计代码里如果写死了某个库名,迁移环境时不用改代码,在 setup 里加一行别名指向真实库就行。这一行在换机器、换目录的时候能省掉大量改动量。

3.3 setup 文件的查找顺序与 SYNOPSYS_SIM_SETUP

工具找 setup 文件是按顺序来的,找到第一个就停:

  1. 当前工作目录下的synopsys_sim.setup
  2. 环境变量SYNOPSYS_SIM_SETUP指向的文件
  3. 用户 home 目录下的synopsys_sim.setup

这个「三级兜底」是最隐蔽的坑。新人接手环境时,经常在工程目录下建好了 setup,跑起来却还是报模块找不到,查半天发现 home 目录里躺着一个几年前留下的旧 setup,里面把work映射到了另一个路径——只要当前目录没有 setup 文件,就会命中它。

# 明确指定,避免读到 home 里的历史配置 export SYNOPSYS_SIM_SETUP=$PROJ/vcs/synopsys_sim.setup

SYNOPSYS_SIM_SETUP我一般直接指向工程内文件的绝对路径,这样不管在哪个子目录下敲命令,读到的都是同一份配置。代价是同一台机器上同时做两个项目时,切项目必须重新 source,所以项目切换脚本里要带上这一句。

分析完之后怎么确认库里有东西?用vdir:

# 列出 work 库里已分析的设计单元 vdir -lib work # 只看某个单元的接口信息 vdir -lib work -type entity | head -20

vdir输出为空基本就三种原因:分析阶段其实失败了(去看vlogan.log)、-work指定的库名和 setup 里对不上、或者 setup 文件根本没被读到。按这个顺序查,比盲改参数快得多。

4. 编译与细化:vlogan、vhdlan 到 vcs 的参数怎么取舍

环境搭好、库建好,接下来是每天都要敲的那几条命令。这里我把三段式的完整链路写一遍,参数按「必给」和「看情况给」分开说,能直接抄。

4.1 分析阶段:vlogan 的必给参数

vlogan -full64 -sverilog -ntb_opts uvm-1.2 \ -timescale=1ns/1ps \ -work rtl_lib \ +incdir+./rtl/include+./tb/include \ -f rtl.f \ -l vlogan_rtl.log

逐条说明:

-full64走 64 位模式,大设计必须加,不加会在内存到 4G 附近直接崩。

-sverilog打开 SystemVerilog 支持。工程里用了logic、always_ff、interface这些,不加这个参数会报一堆莫名其妙的语法错。

-ntb_opts uvm-1.2使用工具自带的 UVM 库。这里有个选择:自己下载一份 UVM 源码加进文件列表,还是用自带的。我一般用自带的,因为自带版本和工具的补丁是配套的,自己那份很容易在 phase 执行顺序上和工具打架,报出来的错还特别难定位。要用 UVM 1.1d 就把参数改成uvm-1.1d。

-timescale=1ns/1ps统一时间单位与精度。这条一定要在分析阶段给,而不是只在细化阶段给,否则每个文件的精度按各自\timescale` 走,混合精度仿真的结果会和你预期差一个数量级。全工程统一是省事做法,代价是某些 IP 内部需要更细精度时得单独处理。

-work rtl_lib指定分析进哪个库,必须和 setup 文件里定义的库名完全一致,大小写敏感。

+incdir+a+b是 include 搜索路径,多个用+连起来,不要重复写多个+incdir+(虽然也能识别,但可读性差)。路径里带+或者空格的目录趁早改掉,工具解析会出问题。

-f rtl.f从文件列表读源码。rtl.f里一行一个相对路径,支持-v指定库文件、-y指定库目录配+libext+.v自动搜索。文件列表建议按「包 → 接口 → 模块 → 顶层」顺序排,VCS 虽然会做依赖分析,但顺序写对了能少很多 iteration。

-l vlogan_rtl.log把日志落盘。不加这个参数,输出只在终端,作业跑完日志就没了,出问题想查都查不到。

如果后面要接波形调试工具,再加-kdb -lca,作用是生成知识库,否则细化阶段开了-debug_access也看不到某些信号。

VHDL 侧对应的是:

vhdlan -full64 -work rtl_lib \ -time 1ns/1ps \ -f vhdl.f \ -l vhdlan_rtl.log

-time对应-timescale,语义一样,单位写法是单位/精度。

4.2 细化阶段:-debug_access 的取舍与 -debug_region

分析完了,第二步把所有库里的顶层组装成可执行文件:

vcs -full64 -sverilog -ntb_opts uvm-1.2 \ -timescale=1ns/1ps \ -top tb_top \ -debug_access+all -debug_region+cell \ -cm line+cond+fsm+tgl+branch -cm_dir ./cov.vdb \ -Mupdate \ -o simv -l vcs_elab.log

-top tb_top指定顶层模块名。多顶层时写多个-top,或者用-top加配置文件。这个参数写错,细化阶段会直接报找不到 top。

-debug_access+all是调试能力总开关,代价很大:编译时间、内存占用、仿真速度三方面都会退化,实测下来带全量 debug 的仿真比不带慢三到五倍。手册第 4 章给了分层做法:+all是全部打开,+pp是后处理级(波形工具只能看、不能改值),+r是只读。日常回归推荐-debug_access+pp,出了问题要交互调试时再单独编一版+all的。

-debug_region+cell配合-debug_access用,把调试能力限制在某个范围里。设计里有大块第三方 IP 时特别有用,把 IP 区排除掉,能明显缩短编译时间。

-cm line+cond+fsm+tgl+branch开覆盖率采集,五个维度全开。-cm_dir ./cov.vdb指定数据库目录,后面用urg -dir ./cov.vdb出报告。覆盖率开关只在细化阶段给,运行时不用重复给(重复给也不报错,但没有任何意义)。

-Mupdate增量编译。第二次细化时只重编发生变化的模块,大设计上能把十几分钟压到两三分钟。第一次编译没区别。

-o simv指定输出可执行文件名。多人协作时建议带上场景名,比如-o simv_smoke、-o simv_regress,不然大家都是simv,前后跑两个 case 互相覆盖,波形对不上。

-lca是打开一些「限量可用」特性的开关,-kdb、部分-debug_access组合都需要它。加错不会报错,只是某些特性静默失效,所以建议固定写进脚本里。

4.3 运行阶段:simv 的常用参数与随机种子

./simv +ntb_random_seed=20210901 \ +vcs+initreg+random \ +vcs+lic+wait \ -cm line+cond+fsm+tgl+branch \ -cm_name smoke_0 \ -l sim_0.log

+ntb_random_seed=固定随机种子。验证中最重要的参数之一:复现问题必须把种子记下来,日志开头那行 seed 值要抄进缺陷单里,不然这个 case 再也跑不回同一个状态。

+vcs+initreg+random让寄存器随机初始化;要全零初始化就写+vcs+initreg+0。默认情况下寄存器是 X 态,X 会在逻辑里传播,很多「仿真结果全 X」的问题根源就在这。跑正常回归用 random,做寄存器复位验证时用 0,两种模式各跑一遍能覆盖不少遗漏。

+vcs+lic+wait前面提过,批处理必加。

-cm_name给这次运行的覆盖率数据打标签,同一个目录下多 case 数据不会互相覆盖。回归脚本里用case_$i这种命名,最后urg -dir ./cov.vdb -format both合并出一份报告。

交互调试模式用./simv -ucli或者加-gui,但交互模式只能人工手敲,回归必须走批处理。

5. 避坑记录:VCS 环境里最常见的五类翻车

5.1 现象:细化阶段报模块找不到,但分析日志明明是 success

原因:-work指定的库名和 setup 文件里的库名对不上,或者 setup 文件根本没被读到(读的是 home 目录里那份旧的)。还有一种情况是相对路径陷阱——在sim/子目录下执行细化,相对路径解析到了另一个目录。

解决:先echo $SYNOPSYS_SIM_SETUP确认读到哪个文件,再vdir -lib rtl_lib确认库里有东西,最后核对-work参数拼写。三分钟查完,比反复重编快多了。

5.2 现象:simv启动瞬间报无法 checkout license,lmstat显示还有空闲

原因:运行时的 license 变量在作业脚本里没生效,或者LM_LICENSE_FILE指向的是另一台服务器。批处理环境不继承登录 shell 变量是常态。

解决:在作业脚本开头显式source /opt/eda/env/vcs.sh,然后在同一脚本内跑一次lmstat -a -c $LM_LICENSE_FILE,把输出打进日志。以后翻日志能直接看到当时 license 服务是否可达。

5.3 现象:编译到一半报No space left on device

原因:csrc目录和/tmp被打满。带-debug_access+all时中间文件体积会翻好几倍,一个中等设计几十 GB 很常见。

解决:把-Mdir指到大容量盘,定期清csrc目录下的历史残留;/tmp空间小的机器用TMPDIR环境变量重定向到数据盘。回归脚本里加一个磁盘水位检查,超过 85% 就先告警再跑。

5.4 现象:同一份代码在老机器上跑得好好的,新机器上结果全 X

原因:-timescale只在细化阶段给了,分析阶段没给,各文件按各自的\timescale` 精度走,采样时刻错位。

解决:-timescale在vlogan、vhdlan、vcs三个阶段都显式给同一个值。这个参数写三遍看起来啰嗦,但它是这类玄学问题的唯一根治办法。

5.5 现象:带 debug 编译一次要四十分钟,回归根本跑不动

原因:-debug_access+all全量开启,编译期和仿真期都在为「可能要用到」的调试能力付代价。

解决:日常回归用-debug_access+pp -debug_region+cell,只在需要交互调试时单独编一版+all。另外开-Mupdate,改一个文件只重编那一个。这两条加起来,迭代速度能差出五到十倍。

6. 跑通验证:用一个十六行的小设计确认整套环境可用

环境装完,别急着上真设计。先用一个最小可跑通的设计把链路走一遍,出问题也好定位。准备两个文件:

// counter.v —— 4 位计数器,带异步复位 module counter(input clk, input rst_n, output reg [3:0] q); always @(posedge clk or negedge rst_n) if (!rst_n) q <= 4'd0; else q <= q + 4'd1; endmodule // tb.v —— 只做一件事:复位后跑 20 个周期并打印 module tb; reg clk = 0, rst_n = 0; wire [3:0] q; counter u_dut(.clk(clk), .rst_n(rst_n), .q(q)); always #5 clk = ~clk; initial begin #20 rst_n = 1; #200; $display("[CHECK] q=%0d at %0t", q, $time); $finish; end endmodule

三步走完:

vlogan -full64 -sverilog -timescale=1ns/1ps -work work counter.v tb.v -l a.log vcs -full64 -sverilog -timescale=1ns/1ps -top tb -debug_access+pp -o simv -l e.log ./simv +ntb_random_seed=1 +vcs+lic+wait -l s.log

判断标准我一般看四条,缺一条就说明环境有问题:

检查点期望结果异常时的方向
s.log尾部出现仿真时间和$finish提示没跑起来,查 license 和可执行文件
[CHECK]打印时间 220ns,q 为 4 位以内的值时间不对,查 timescale
vdir -lib work列出tb和counter两个单元查-work与 setup
simv目录生成simv可执行文件查细化日志前几行

最容易被跳过的是第二条。很多人看到[CHECK] q=3就觉得通了,其实$time打出 220000000 才是 timescale 没生效的信号,到真设计上会表现成采样时刻整体偏移。所以自检时要把时间也打出来,别只打数据。

提示:把这四步写成一个smoke.sh,每次升级工具版本或换机器都先跑一遍。五分钟的投入,能挡掉后面大部分「到底是环境问题还是设计问题」的争论。

从那以后我每次搭完环境,都会先跑这个十六行的小设计,$display里的时间戳必须和预期一致才继续往下走。工具版本升级、机器迁移、环境变量被人改过,这三件事发生的频率远比想象中高,而它们表现出来的现象惊人地相似。希望这套流程能帮到你,少在环境上耗几个晚上。

本文还有配套的精品资源,点击获取

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

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

立即咨询