拓冰建站拓冰建站
首页 / 资讯中心 / 正文

Cadence Virtuoso .cdsinit配置指南:从启动脚本到高效模拟IC设计

用了这么多年Cadence Virtuoso我有个挺深的体会很多人把大量精力花在画版图、调电路、跑仿真上却很少花十分钟去看一眼自己的.cdsinit启动文件。这个文件其实就是Virtuoso的“启动脚本”是每次打开工具时自动加载的SKILL代码地位相当于Linux用户熟悉的.bashrc。把它配置好了工具用起来会顺手一大截——启动完自动进入你想要的界面状态快捷键按自己的习惯来仿真默认值也提前设好。这篇文章就把我这些年攒下来的.cdsinit实用配置和有趣玩法一次性分享出来适合所有用Virtuoso做模拟IC设计、版图设计和混合信号验证的工程师参考。1. cdsinit的定位它和其他Cadence配置文件到底什么关系新手最容易搞混的就是.cdsinit、.cdsenv、.cds.lib、display.drf这几个文件到底分别管什么。我刚开始用的时候也糊涂经常把环境变量往.cdsinit里塞结果该生效的没生效不该报错的反而报错。这里先把这个关系理顺后面再讲具体配置就清晰了。1.1 启动时到底都加载了哪些文件Virtuoso启动时是一个“分级加载”的过程不是只读一个文件。按顺序大致是这样工具自带的初始化文件Cadence在安装目录下自带一套默认的启动配置比如cdsinit、cdsenv这是所有用户的基础默认值。CDS_INIT_DIR指定目录下的文件如果设置了CDS_INIT_DIR环境变量工具会优先到这个目录去找初始化文件。这对于公司在多台服务器上统一管理非常有价值。用户主目录下的.cdsinit这是个人配置的核心文件。.cdsenv这个文件存的是工具选项类设置比如原理图编辑器默认网格、仿真器默认参数等。它和.cdsinit有分工.cdsenv面向“选项参数”.cdsinit面向“代码逻辑”。.cds.lib库定义文件告诉工具你有哪些库、库文件放哪、哪个是技术库。display.drf显示资源文件工艺库自带的层颜色、线型、填充图案就是由它定义的。所以你可以把.cdsinit理解为“总指挥”里面除了写SKILL函数还可以通过load语句去加载其他配置文件或者用envSetVal去修改.cdsenv里的参数。它是一切的起点。1.2 找到你的.cdsinit看看里面默认有什么如果你从来没有自己创建过.cdsinit那工具主目录下是有一份模板的。常见的位置取决于版本和安装路径例如$CDS_ROOT/tools/dfII/samples/local/.cdsinit。建议把它拷贝一份到自己家目录再改cp $CDS_ROOT/tools/dfII/samples/local/.cdsinit ~/.cdsinit打开这份默认文件里面一般会做几件事加载一些基础SKILL库、设置滚动条和鼠标中键行为、加载env文件等。其中有一个很重要的变量叫envSetVal它可以在.cdsinit里直接写“键值对”来覆盖选项默认值。我遇到过不少同事改了半天.cdsinit不生效最后发现是文件权限问题——工具在读取时要是没有可读权限会直接跳过且不报错。还有一次是有个隐藏字符混进了文件头导致整个文件解析失败工具退回默认配置。所以如果你改了没反应第一步就是去CIW窗口Command Interpreter Window看启动日志里有没有SKILL报错信息。2. 先来点实在的编辑器、库路径和启动目录搞清楚了.cdsinit的定位接下来先聊几个每天都会影响到你的基础设置。这些配置不复杂但能解决很多“看着不舒服”的小问题。2.1 指定编辑器摆脱默认vi模拟工程师经常要在电路里查看或编辑文本文件——比如修改model文件、查看仿真日志、写个临时脚本。Virtuoso默认调用的文本编辑器是vi如果你平时不习惯vi的操作方式每次打开都会很痛苦。在.cdsinit里可以直接指定你用顺手的编辑器; 指定文本编辑器为geditLinux桌面环境 envSetVal(text editor string gedit) ; 或者使用gvim保留图形界面 envSetVal(text editor string gvim -f)注意这里有个小细节string表示这个参数的数据类型是字符串。envSetVal的通用语法是envSetVal(会话名 参数名 类型 值)类型不只是string还有int、boolean、float等。类型写错了设置不会生效而且不会报错特别容易让人抓狂。我自己一直用的是gvim -f其中-f参数是为了让Virtuoso等待这个编辑器进程关闭后再继续执行否则可能出现文件还没保存完工具就以为编辑结束了。这个坑我踩过好几次。2.2 默认库路径少跑冤枉路每次打开Virtuoso都要通过Library Manager去加载项目库吗其实可以在.cdsinit里把常用的库路径提前加进去省去反复浏览目录的操作。方法是用ddGetObj或直接操作.cds.lib但我更推荐直接在启动文件末尾调用; 把项目库目录加载到Library Manager let( (libPath) libPath /home/user/analog_project/cds.lib if( isFile( libPath ) then load( libPath ) else printf(Warning: %s not found\n libPath) ) )这里用printf打印一个警告是一个很好的习惯。因为如果你引用的库路径不存在至少能在CIW里看到提示而不是稀里糊涂地在Library Manager里找不到库。.cdsinit里还可以设置默认的工作目录让每次启动后自动进入项目目录; 启动后自动切换到项目目录 cd(/home/user/analog_project)如果你同时管理多个项目我建议不要在.cdsinit里写死路径而是用环境变量比如cd(getShellEnvVar(PROJECT_ROOT))这样换项目时只需要改环境变量不用改启动脚本。2.3 启动时的窗口标题和状态栏另一个很实用的配置是修改CIW窗口标题这样多开Virtuoso实例时一眼就能分辨哪个是哪个。比如; 把当前用户名和主机名显示在CIW标题上 hiSetWindowTitle( hiGetCIWindow() strcat( Virtuoso - getShellEnvVar(USER) getHostName( ) ) )还有状态栏显示的内容也可以通过hiSetStatusItem之类的函数自定义。不过这个功能不同版本接口差异较大我只建议在明确知道当前版本支持时才去碰它否则可能启动时报错。3. 快捷键Virtuoso里最该花时间的自定义如果说.cdsinit里什么设置最“有趣”我认为是快捷键绑定。两个工程师用同一个Virtuoso版本一个全靠鼠标点菜单一个全程键盘操作工作效率的差距很快就体现出来了。快捷键绑定的好处不只是省时间更重要的是手不需要在键盘和鼠标之间来回切换专注力能保持得更久。3.1 hiSetBindKey的语法没那么神秘快捷键绑定的核心函数是hiSetBindKey基本语法hiSetBindKey( 界面类别 按键组合 要执行的函数或命令 )界面类别是指这个快捷键在哪个环境下生效常见的有Layout版图编辑器Schematic原理图编辑器Simulation仿真环境General通用环境libraryManager库管理器按键组合的写法要注意是双引号内的字符串。比如按ShiftZ写ShiftKeyZ按CtrlE写CtrlKeyE按F9写KeyF9。多个修饰键就叠加比如CtrlShiftKeyP。你可以使用hiGetBindKey去查询当前某个功能绑定了什么按键这比翻文档快得多。3.2 原理图编辑器里我比较喜欢的快捷键这一节我给一些实际能用的示例。注意不同版本对命令名称的兼容性有差异如果你发现某条不生效先在CIW里用hiGetBindKey查一下命令是否存在。; 原理图中按ShiftZ缩放至全屏适配 hiSetBindKey( Schematic ShiftKeyZ zoomFitAll() ) ; CtrlE 打开属性编辑窗口 hiSetBindKey( Schematic CtrlKeyE hiOpenProperties() ) ; CtrlF 快速放置器件 hiSetBindKey( Schematic CtrlKeyF hiAddInstance() ) ; F4 复制选中的对象 hiSetBindKey( Schematic F4 hiCopy() ) ; Esc 取消当前操作 hiSetBindKey( Schematic Escape geCancel() )原理图编辑时我强烈建议把CtrlZ绑定撤销、CtrlY绑定重做因为默认情况下某些版本这两个操作没有绑定快捷键用起来特别别扭hiSetBindKey( Schematic CtrlKeyz hiUndo() ) hiSetBindKey( Schematic CtrlKeyy hiRedo() )3.3 版图编辑器里那些高频操作版图编辑器的操作频率比原理图高得多快捷键的价值也更明显。我平时的配置是这样的; 版图中ShiftZ缩放至当前视图全部 hiSetBindKey( Layout ShiftKeyZ zoomFitAll() ) ; 按F5 保存并检查 hiSetBindKey( Layout KeyF5 hiSaveDesign() ) ; 按F6 运行DRC hiSetBindKey( Layout KeyF6 lxGenDRC() ) ; 按F7 运行LVS hiSetBindKey( Layout KeyF7 lxGenLVS() ) ; CtrlD 快速删除跳过二次确认 hiSetBindKey( Layout CtrlKeyd leHiDelete() ) ; CtrlShiftA 全选当前层 hiSetBindKey( Layout CtrlShiftKeyA leHiSelectAll() )这里要特别提醒绑定CtrlD这类组合键要注意会不会和系统或输入法冲突尤其在中国大陆工程师常用的搜狗拼音或微软拼音输入法下如果不小心切到中文输入状态快捷键很可能会被输入法窗口拦截。我建议在.cdsinit里加一条防呆提醒启动时打印一句话“当前已加载快捷键配置请保持英文输入法状态。”这个细节看起来不起眼但真的能省去很多困惑。3.4 仿真窗口与通用快捷键仿真图形界面里也值得配几个快捷键。我最常用的是在波形窗口里“缩放到合适范围”和“光标测量”; 波形窗口F2 缩放到合适范围 hiSetBindKey( Waveform KeyF2 awvZoomFit() ) ; 波形窗口按X 启动光标测量 hiSetBindKey( Waveform x awvCursorCreate() )通用环境中我习惯把CtrlShiftL绑定到“锁定所有窗口”hiSetBindKey( General CtrlShiftKeyL hiLockAllWindow() )锁定窗口这个动作看着不起眼但实际项目评审时特别有用——防止不小心拖动了某个窗口布局。4. 显示、颜色与标注让工具用起来更顺眼Virtuoso默认的界面风格偏“老式Unix”黑底白字菜单和数据表格的配色也不够现代。好在.cdsinit可以调整很多视觉相关的内容。4.1 配色方案与背景色Cadence从IC6.1.8开始支持hiSetColorScheme可以直接换一套配色; 切换到暗色主题风格 hiSetColorScheme(dark)如果你不喜欢默认的黑色原理图背景也可以改成白色; 把原理图背景改成白色 envSetVal(schematic graphic string white)不过这里要小心如果团队里有其他人共用同一个显示资源文件display.drf你一个人把背景改成白色层颜色和背景的对比度可能就出问题了。我个人还是建议保留工艺库默认设置的背景色因为PDK厂商设计的层颜色都是以特定背景为前提的强改背景色会导致某些层次看不清。4.2 网格、坐标和缩放习惯每个人的画图习惯不一样有人喜欢开网格有人喜欢关。这个可以在.cdsinit里统一设置; 原理图默认开启网格显示 envSetVal(schematic gridSpacing float 0.125) envSetVal(schematic gridEnabled boolean t) ; 版图默认开启网格显示 envSetVal(layout gridSpacing float 0.005) envSetVal(layout gridEnabled boolean t)gridSpacing的单位取决于工艺库定义有的库是微米有的库是纳米。不要盲目照抄别人的数值——我在两个不同工艺之间切换时就因为这些数值不匹配导致网格看起来密密麻麻。更稳妥的办法是用envGetVal(schematic gridSpacing)先看当前值再决定改多少。4.3 文本和字体设置如果你觉得Virtuoso默认字体太小或太粗糙可以通过环境变量改字体。不同版本支持的字体机制不太一样比较通用的是设置hiSetFont。; 将标签文本设为指定字体和大小 hiSetFont( -adobe-courier-medium-r-normal--14-100-100-100-m-90-iso8859-1 )这一行在不同系统上的可用字体名不一样建议在Virtuoso的Tools - Font Options里先选择你想要的字体然后用它生成的对应用法或者干脆用hiGetFont查看当前字体名。直接硬编码一个不存在的字体名启动时会弹出字体警告虽然不影响功能但很烦人。还有个小技巧把CIW里显示的行数调多一点方便查看长时间运行的仿真日志。相关变量是hiSetIntVar里的maxLines; CIW窗口显示更多历史行 hiSetIntVar(hiGetCIWindow() maxLines 2000)这样大量日志输出时就不用来回复制了。5. 自动加载项目内容启动即进入状态.cdsinit真正“有趣”的地方在于它不仅是配置还可以写逻辑。很多人每天上班打开Virtuoso第一件事是手动展开库、找到上次的顶层原理图、双击打开再打开仿真状态文件。这些重复操作完全可以交给初始化脚本自动完成。5.1 启动后自动打开顶层原理图下面的脚本会根据环境变量PROJECT_TOP_CELL自动打开指定单元视图let( (topCell libName cellName viewName) topCell getShellEnvVar(PROJECT_TOP_CELL) if( topCell ! nil then ; 假设环境变量格式为 lib/cell/view libName nth(0 parseString(topCell /)) cellName nth(1 parseString(topCell /)) viewName nth(2 parseString(topCell /)) if( libName ! nil cellName ! nil viewName ! nil then dbOpenCellViewByType( libName cellName viewName nil r) hiOpenCellView( libName cellName viewName) printf(自动打开顶层单元: %s\n topCell) else printf(环境变量PROJECT_TOP_CELL格式错误应为lib/cell/view\n) ) ) )这段代码里我自己比较得意的是随时会打印状态信息。.cdsinit是启动脚本不是“黑盒”每段逻辑做了什么最好都打印出来方便排查问题。你想想看如果哪天启动后自动打开功能失灵了CIW里没有任何提示你从头到尾翻代码找bug效率多低。5.2 检查库文件完整性项目开发久了.cds.lib里可能引用了已经搬走或删除的库。启动时自动检查这些路径是否有效能提前发现问题; 检查.cds.lib中所有库路径是否存在 let( (libFile lines libPath) libFile ~/.cds.lib ; 或者使用项目实际的cds.lib when( isFile(libFile) lines readFileLines( libFile ) foreach( line lines when( rexMatchp(^DEFINE line) libPath nth(1 parseString(line )) when( isFile(libPath) nil printf(警告: 库路径不存在 - %s\n libPath) ) ) ) ) )这个脚本写得比较简洁原理就是逐行读取.cds.lib找到DEFINE开头的行再检查第二个字段指向的路径是否存在。如果发现缺失CIW里会打出警告这样你可以在Loading各个库之前就知道问题而不是等到画版图时才发现器件库没加载。5.3 启动时打印项目信息我习惯在.cdsinit里放一个“横幅打印”函数启动后显示当前用户、项目名、工艺名和仿真器路径等信息printf(\n\n) printf( 项目环境初始化完成\n) printf( 用户: %s\n getShellEnvVar(USER)) printf( 主机: %s\n getHostName()) printf( 工艺库: %s\n getShellEnvVar(TECH_LIB)) printf( 启动时间: %s\n getCurrentTime()) printf(\n\n)这个东西没什么技术含量但在团队协作时很有用——如果某台服务器上配置错了环境变量同事启动后一眼就能看到不用到处查。5.4 用启动脚本做“防呆”在模拟IC设计流程里最怕的是工艺角和仿真模型选错。我见过有人用错了工艺角仿真结果整整偏了一周才发现。可以在.cdsinit里写一个简单的检查函数启动时去环境里读取当前模型库设置如果发现模型路径包含可疑关键词直接弹警告let( (modelPath) modelPath getShellEnvVar(MODEL_PATH) when( modelPath ! nil when( rexMatchp(tt_27 modelPath) printf(提示: 当前模型为典型角tt若需要ff/ss角请检查环境变量\n) ) ) )6. 仿真工具链的默认值把ADE配置写进初始化对模拟设计来说.cdsinit除了管界面还可以管仿真。通过它设置仿真器默认值和环境能保证每次新建testbench时不需要反复去点选几个下拉菜单。6.1 指定仿真器和工艺角启动时直接指定仿真器类型确保ADE环境自动切换到目标仿真器; 设置仿真器为spectre envSetVal(ade simulator string spectre) ; 设置默认工艺角变量名根据工艺库不同而不同 envSetVal(spectre modelFiles string /home/user/pdk/models/spectre/xxx.scs)这里要特别注意spectre的模型文件路径千万别写死每个工艺节点、每个项目的model文件都不同。更好的做法是读取环境变量; 从环境变量读取模型库路径 let( (modelPath) modelPath getShellEnvVar(SPECTRE_MODEL) when( modelPath ! nil envSetVal(spectre modelFiles string modelPath) ) )6.2 常用envSetVal仿真参数ADE环境中很多选项值得在.cdsinit里预先设好。比如保存波形数据的数量限制、仿真精度默认值。下面是一些我长期在用的设置; 默认保存所有信号波形 envSetVal(directplot saveAll boolean t) ; 仿真结果的保存目录 envSetVal(ade saveDir string ./sim_results) ; 设置直流仿真默认温度 envSetVal(spectre temp string 27) ; 放宽仿真输出的日志滚动条数 envSetVal(spectre logLevel string info)关于directplot的saveAll这个设置要谨慎打开。如果你做的是大规模混合信号仿真所有节点都保存波形数据量会爆炸。我自己一般在小型模拟模块里才开全保存做系统级仿真时会手动关掉。6.3 波形窗口和输出设置ADC、PLL这种长时间跑瞬态仿真的设计波形数据动辄几个GB。.cdsinit里可以提前把波形数据库的压缩和格式选项配好; 仿真结果以psf格式保存并开启压缩 envSetVal(psf format string psf) envSetVal(psf compression boolean t) ; 波形窗口默认打开实部和虚部 envSetVal(waveform complexDisplay boolean t)这里有一个很重要的点仿真结果的可视化方式很大程度取决于psf格式版本。不同Cadence版本之间的psf格式有细微差异如果你用的是IC231或更新版本建议保留默认格式不要强行指定老格式否则可能无法正常打开仿真结果。7. 更高级的玩法自定义菜单与SKILL工具库当.cdsinit的配置积累到一定程度你就不仅仅是“配置工具”了而是在“二次开发工具”。这个阶段可以通过自定义菜单和使用SKILL函数库把日常工作里重复的操作固化成按钮。7.1 用hiAddMenuItem创建自定义菜单比如我想在原理图编辑器里加一个“一键检查”菜单点击就执行DRC、LVS快捷键hiAddMenuItem( hiGetEditMenu(schematic) Check DRC LVS lxGenDRC() lxGenLVS() )这个函数的参数在不同版本里略有不同但核心用法基本一致先获得当前编辑器的菜单对象再指定菜单项名称和回调函数。如果你在CIW里看到*Error* hiAddMenuItem: arg must be a menu这类错误多半是第一个参数写错了。7.2 挂载自己的SKILL函数库项目做久了每个人手里都会有一些自己写的SKILL函数。老是把几十个procedure写在.cdsinit里会让这个文件变得又臭又长而且改一处就可能导致整个启动失败。我建议把常用的函数统一放到一个目录比如/home/user/skilllib/然后在.cdsinit里批量加载; 批量加载自定义SKILL函数库 let( (skillDir skillFiles) skillDir /home/user/skilllib/ ; 获取目录下所有.il文件 skillFiles getDirFiles( skillDir *Skill*) foreach( file skillFiles when( rexMatchp(\.il$ file) load( strcat( skillDir file) ) printf(加载SKILL库: %s\n file) ) ) )这段代码里的getDirFiles函数用法随着版本不同会有差异如果你用的版本不支持可以退一步用ls配合parseString自己解析文件列表或者干脆写一行load语句逐个加载。稳定性优先不要为了炫技用了不符合当前版本的API。7.3 通过.env和shell脚本联动.cdsinit还能读取系统的环境变量这就给了我们很大的灵活性。比如在shell里定义了PDK_ROOT在.cdsinit里就能直接用它来引导加载对应的PDK初始化内容; 根据PDK_ROOT加载不同工艺的初始化脚本 let( (pdkRoot) pdkRoot getShellEnvVar(PDK_ROOT) when( pdkRoot ! nil let( (initFile) initFile strcat( pdkRoot /cdsinit) when( isFile( initFile) load( initFile ) printf(已加载PDK初始化: %s\n initFile) ) ) ) )这样换工艺时只需要在shell环境里修改PDK_ROOTVirtuoso启动后会自动把对应的PDK初始化脚本加载进来不需要改动个人.cdsinit。对于同时维护多个工艺项目的工程师来说这套联动方案真的能省不少事。8. 启动脚本的坑排错和版本差异最后这一章聊聊我踩过的坑和一些实用的排错思路。.cdsinit之所以让很多人不敢碰就是因为它一旦出问题启动就可能卡住或报一堆看不懂的SKILL错误。其实掌握了方法排错并不难。8.1 SKILL加载报错怎么排查最常见的报错有这么几类*Error* eval: undefined function调用了不存在的函数。多半是函数名写错或者当前版本不支持。*Error* parse error语法错误。SKILL是Lisp风格的语言括号配对特别容易出错。建议每次改完.cdsinit都先单独load一遍文件不要直接重启Virtuoso。*Error* cant open file加载了不存在的文件路径。这类错误最值得警惕因为你可能引用了别的机器上的路径拷贝到新机器后就会炸。排查思路很简单一条条注释法。把.cdsinit里新增的代码逐段注释掉哪段注释后启动就正常了问题就在哪段。千万不要一次性改很多内容再启动否则你根本定位不了问题。我自己还会用一个小技巧在.cdsinit开头加一个printf打印“开始加载cdsinit”。如果这个打印都没出现说明文件压根没被读取去检查文件名、位置和权限如果打印出现了但后面某段代码执行时挂掉错误信息会在CIW里显示出来。这个“日志探针”的思路适用于所有启动脚本排查。8.2 版本差异老版本到新版本迁移Cadence从IC6.1.8到IC23.1很多API发生了变化。我整理了一个简单的对照表方便你在迁移时排查问题功能IC6.1.8IC23.1缩放适配zoomFitAll()zoomFitAll()打开属性hiOpenProperties()hiOpenProperties()锁窗口hiLockAllWindow()hiLockAllWindow()颜色方案hiSetColorSchemehiSetColorScheme菜单添加hiAddMenuItemhiAddMenuItem或新版菜单接口多数命令是兼容的但部分高级API在IC23.1里被标记为deprecated或替换为axl风格的新接口。建议在迁移环境后逐条在CIW里手动执行一下.cdsinit中的关键函数看看有没有报deprecated警告。8.3 团队协作时的cdsinit管理最后聊团队协作。很多公司是多个工程师共用一台服务器跑仿真如果每个人都随心所欲改.cdsinit很容易出现“我这边正常你那边报错”的情况。我的建议是把.cdsinit放入版本管理Git或SVN每次修改都留记录。统一用CDS_INIT_DIR指向团队共享的初始化目录个人差异化配置放在~/.cdsinit里。.cdsinit顶部用一个大区块写明“团队公共配置请勿随意修改”下面才是“个人配置区”。加载团队共享配置时用load并加printf日志这样启动日志里能明确看到当前加载的是团队公版还是个人定制版。我个人的习惯是在团队共享配置中把快捷键统一管理一部分再把个人偏好留在自己目录。这样既不凌乱也能兼顾个性。还有一个细节很多PDK比如TSMC、SMIC的工艺库自带的初始化脚本里也包含快捷键定义它的加载顺序在用户.cdsinit之前还是之后会直接影响最终生效的快捷键。如果你发现某个快捷键被“抢”了优先考虑是不是PDK初始化脚本里覆盖了你的绑定。解决办法是把自己的绑定放在.cdsinit最后或者直接修改PDK的初始化脚本前提是你对这个修改有把握且不破坏工艺库功能。写在最后以上这些.cdsinit配置和玩法是我在多个工艺节点、多个项目里一点点积累出来的经验。坦白说没有一套配置能适合所有人甚至同一个工程师在不同项目里需求都会变化。但我始终认为花一个下午时间把启动脚本梳理好收益是非常可观的——每次打开Virtuoro时工具已经按照你的习惯准备好了一切那体验确实比从头点菜单舒服太多。我建议你现在就打开自己环境里的.cdsinit文件对照这篇文章挑两三个设置试一下比如加个快捷键、改一下启动日志。先从简单处入手等慢慢熟悉了SKILL语法再逐步添加自动加载和自定义菜单这些更进阶的玩法。如果你在配置过程中发现了一些我这篇文章里没有提到的有趣用法欢迎多交流我也很想知道大家各自环境里那些“隐藏”的启动技巧。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门