简介面向集成电路设计自动化领域的 Cadence SKILL 语言中文使用指南基于产品版本 6.1.62014 年 11 月翻译整理适合英语阅读较吃力但具备一定 C 语言基础的技术人员、版图与验证工程师入门查阅。内容从 SKILL 与 Lisp 的渊源讲起先交代语法约定、数据类型标识符写法与节名含义再依次说明安装步骤、环境变量配置与编译器选择并延伸到编程指南中的实用技巧文末还给出官方文档、社区论坛与技术支持的获取途径便于读者按主题快速定位。压缩包内为 1 个 PDF 文件体积约 68.23MB目录层级清晰支持关键词检索也方便打印成册随时翻阅。目前已有 527 人学习下载可作为中文环境下系统了解 SKILL 语言、编写定制化设计工具与排查环境问题的常备参考。1. 先弄明白一件事SKILL 语言到底是给谁用的脚本很多人第一次听到 SKILL 语言是在招聘要求或者部门内部培训通知里看到「熟悉 SKILL 语言者优先」几个字然后一头雾水这又是什么编程语言名字都没听过零基础还学得会吗说白了它是一种跑在集成电路设计工具里的脚本语言专门用来指挥那些画版图、做验证、跑仿真的大型软件干活。你不用拿它写网站、写 App你要做的是把重复几十遍的鼠标点击换成一句能反复执行的命令。这份中文使用指南把官方英文手册翻译成了中文让英语一般的新手也能从头看懂语法、跑通第一个例子这也是它最实在的价值。2. 为什么值得学SKILL 在芯片设计流程里到底管什么刚接触这个领域的人最容易犯的错是把它当成一门「要单独学的编程语言」于是搬来一本讲变量和循环的通用教材从头啃啃了两周发现和自己的工作完全对不上兴趣就没了。更省力的做法是先搞清楚它在整个流程里站哪个位置知道它替谁干活、解决哪类麻烦再回头看语法你会发现每一行代码都能对上具体场景。2.1 它不写业务系统它给设计工具装上「遥控器」芯片设计工程师日常面对的是版图编辑器、电路仿真器、规则检查工具这一类大型软件。这些软件出厂时功能是通用的可每家公司的流程都不一样有人习惯把某类器件按固定间距摆成一排有人要在导出数据前统一改一遍命名有人每天要检查几十个单元里有没有漏连的线。软件厂商不可能替每家客户把这些活都做进去于是留了一套脚本接口SKILL 语言就是操作这套接口的通用语言。用生活里的东西打比方会更好懂。你买回家的微波炉面板上只有几个固定按钮可你真正想要的是「中火三分钟再解冻两分钟」那就得有办法把这些按钮自己组合起来。SKILL 就是这个组合按钮的东西而且它比「录制宏」强得多它有变量、有条件判断、有循环、能定义函数可以写成真正的程序。再换一个更贴近的例子Excel 里的 VBA。SKILL 之于设计工具就相当于 VBA 之于 Excel、AutoLISP 之于某些绘图软件。它们的套路一模一样——宿主软件提供对象脚本语言负责批量读写这些对象。你只要理解过一次这种「宿主 脚本」的关系以后再遇到别的工具上手会快很多。所以第一层认知要立住它是工具的一部分不是独立的应用开发语言。学它的目的不是造一个新软件而是让手上这套软件按你的习惯干活。这个定位想明白了后面的语法就不会学得那么飘。2.2 和 Lisp 的血缘关系为什么满屏都是括号打开任何一份 SKILL 代码第一眼看到的都是括号一层套一层新手的本能反应是「这玩意儿能读吗」。它是 Lisp 家族的方言而 Lisp 这种语言最核心的想法叫「代码即数据」所有东西都是列表列表用括号包起来括号里第一个位置写动作后面写材料。; 括号里第一个词是函数名后面的都是参数 ( 1 2) ; 结果是 3 (list 1 2 3) ; 结果是 (1 2 3) (car (9 8 7)) ; 取第一个结果是 9这种写法叫前缀表达式。好处是语法极少没有运算符优先级要背没有一堆关键字要记加两个参数和加十个参数写法完全一样读代码时一眼就能看出谁在调用谁。坏处也很直接第一次看像天书括号多到眼花少写一个右括号整段就跑不起来。新手只要记住一条口诀就够用了括号里第一个词是动作后面的都是材料。「动作」就是函数「材料」就是参数。看到(printf hello\n)你就读成「执行 printf 这个动作材料是这串文字」看到(setq width 10)就读成「执行 setq 这个动作材料是变量名 width 和数值 10」。用这个读法去扫代码哪怕语法还不熟也能猜出七八成意思。顺带说一句SKILL 在 Lisp 基础上做了不少贴合设计场景的改造比如它支持中缀写法也内置了大量直接操作图形对象的函数。手册前言里专门有一节讲它和 Lisp 的关系第一遍读不懂没关系等你在窗口里敲过几十行再回头看那节会变得非常清楚。2.3 学会之后能干的四类活很多人学着学着就放弃是因为不知道学完能干嘛。按实际工作场景归归类SKILL 用得最多的是这四类事。第一类是参数化单元。同一个器件栅宽改一下图形就得跟着重画靠手动画既慢又容易错。写成参数化单元之后只需要改一个数值图形自动重算这是用得最广、也最值得先学的一块。第二类是批量修改。比如选中两百个对象统一把某一层改成另一层或者统一给命名加个前缀。手工点两百次一定会出错脚本一遍过还能重复用。第三类是自动化检查。跑一遍自己的规则把不合规的项收集成一张表打印出来比人眼一个个找靠谱得多这种脚本写一次能用一整年。第四类是数据导出与整理。把设计里的尺寸、坐标、属性导成文本或表格交给别人做分析。工具自带的导出往往不贴合你要的格式脚本能按你要的样子排。2.4 零基础该有的心理预期手册前言里提到这份文档面向的是「有一定 C 语言基础」的读者。看到这句别慌它的意思只是希望你听过变量、函数、返回值这些概念不是要你会写 C。真的一点编程经验都没有也能学只是前面两三章要多花点时间。还有一件事要提前打好预防针SKILL 是「遥控器」你得先知道电视在哪。也就是说你至少要熟悉手上那套设计工具的基本操作——知道单元在哪、图形怎么选、属性在哪看。完全不熟悉工具的人先花一周把工具用熟再回来学脚本效率反而高。时间上给个参考每天抽一小时两三周能看懂别人写的简单脚本一个月能照着改两三个月能独立写小工具。这个节奏对零基础的人是现实的别信「三天精通」那种话。至于这份中文手册怎么读我的建议是别从头读到尾。第一遍只看目录加前三章建立整体印象之后带着具体问题回去查比如「怎么判断两个数大小」就翻控制流程那章「怎么把结果写进文件」就翻文件输入输出那章。手册是工具书不是小说。3. 第一步怎么迈第一行 SKILL 代码怎么敲、怎么看结果前面讲的都是概念这一章开始动手。我要先说明一点下面所有例子都跑在工具自带的交互式命令行窗口里不同版本的窗口名字可能叫控制台、解释器或者 SKILL 命令行界面长得也不完全一样但「你敲一句、它回一句」这个模式是一样的。看到你手上的窗口和截图有差别不要怀疑自己这是版本差异。3.1 打开那个能对话的窗口在工具菜单里找到命令行入口点开之后会看到一个提示符光标在后面闪。这个窗口的本质是一个「读入—求值—打印」的循环行业里简称 REPL你输入一段代码它立刻算出结果再把结果打印出来然后等你输入下一段。它最大的好处是即时反馈写错立刻报错不用编译、不用保存、不用重启。新手最该做的第一件事不是去读语法章节而是在这个窗口里乱敲十分钟。敲错了顶多出一行报错不会把工具弄坏也不会影响你打开的设计数据。把这个心理负担卸掉后面才敢试。我第一次接触这类窗口的时候光是反复敲加减法就玩了一晚上那种「我说什么它就做什么」的感觉比看十页文档建立信心快得多。需要提醒的是在窗口里敲的代码默认只存在于当前会话关掉窗口就没了。所以真正有用的代码后面要存成文件。这一章先玩窗口下一章再学存文件。3.2 第一个例子让工具回你一句话把下面这行敲进去然后回车。; println 是输出函数双引号里是任意一段文字 (println Hello, SKILL)敲完回车窗口下面应该出现一行Hello, SKILL紧接着可能还会冒出一个返回值。逐项拆开看最外层的一对括号表示「这里要执行一个动作」println是动作的名字意思是打印一行双引号里的内容是要打印的材料字符串必须用双引号包住中文、英文、符号都行。如果你敲完没反应或者弹出一行红字先别急着重敲看三件事左右括号是不是成对、双引号是不是英文半角、println 有没有拼错。这三件事能解决新手九成以上的报错。3.3 第二个例子算个数、存进变量只会打印一句话没什么用接着让工具算点东西。; setq 是赋值函数第一个参数是变量名第二个是它的值 (setq width 10) (setq height 5) ; * 是乘法函数可以接两个以上的参数 (setq area (* width height)) ; 把结果打印出来 (println area)一行一行读第一行把 10 存进名叫width的变量第二行把 5 存进height。第三行先算括号里的(* width height)得到 50再把这个 50 存进area。第四行打印area窗口回你一个 50。这里的setq值得多说两句。它是赋值函数第一个参数写变量名注意不加引号这一点和后面讲列表时会形成对比第二个参数写值。SKILL 里变量不需要提前声明类型你把一个数存进去它就是数把一段文字存进去它就是字符串这一点比 C 语言宽松对新手很友好。再补一个更实用的写法。如果想把结果拼进一句话里打印用printf; %d 是整数占位符\n 表示换行 (printf area %d\n area)printf的第一个参数是格式串里面的%d会被后面的area替换掉\n是换行符。这种写法在实际脚本里出现频率极高因为日志要让人看懂光打印一个数字没法定位是哪一步出的问题。3.4 报错了先看这三处第一次动手必然会遇到报错这很正常不用觉得自己不适合学。SKILL 的报错信息通常以*Error*开头后面跟着一段英文说明比如「函数未定义」「参数个数不对」。看不懂那段英文也没关系按顺序排查这三处大部分问题当场就能解决。第一处是括号。SKILL 里括号是唯一的语法结构少一个右括号工具会一直以为你还没写完光标停在那里等多一个右括号直接报语法错误。排查办法是从最内层往外数一层一层配对。第二处是引号。字符串必须用英文半角双引号包住中文全角引号看起来几乎一样但工具不认。这种事在抄别人代码时特别容易发生翻车过一次之后你就会记住。第三处是函数名和参数个数。函数名拼错一个字母工具就找不到它参数给多了给少了也会报错。手册里每个函数都有固定的参数说明遇到不确定的就回去查那一节别凭感觉猜。4. 基础动作练四样数字、字符串、列表、判断窗口玩熟了接下来要把基本功打扎实。SKILL 的数据类型看着不少但对新手来说真正每天要打交道的就四样数字、字符串、列表、判断与循环。把这四样练到不用查手册你就能读懂大部分简单脚本了。这里我会把每一段代码都拆开讲清楚参数和返回值你照着敲一遍比看十遍强。4.1 数字和字符串最不容易出错的热身数字分整数和小数写法跟日常一样。加减乘除对应、-、*、/都是前缀式而且都支持两个以上参数( 1 2 3)直接得 6不用写成两次加法。( 1 2) ; 3 (* 2 3 4) ; 24乘法可以接多个参数 (/ 10 3) ; 整数相除结果可能被截断成 3 (/ 10.0 3) ; 其中一个写成小数结果就是 3.333...最后两行是个小坑值得单独记一下整数和整数相除很多版本会直接截断小数部分。你要精确结果就把其中一个数写成带小数点的形式。这个差别在做尺寸换算的时候会突然冒出来让人怀疑工具算错了。字符串用双引号包住拼接用strcat取长度用strlen。; strcat 把多段字符串接成一段 (setq name (strcat cell_ 001)) (println name) ; 输出 cell_001 ; strlen 返回字符个数 (println (strlen name)) ; 输出 8strcat的参数个数不固定想接几段接几段这一点在拼接命名规则时特别方便。需要注意它只能接字符串你硬塞一个数字进去会报错得先用格式化的方式把数字转成文字。4.2 列表SKILL 里最核心的一坨数据列表是这门语言的心脏。为什么这么说因为你调用工具的函数去查东西返回的几乎都是列表查一个单元里所有器件回来的是一个器件列表查一个图形的所有顶点回来的是一个坐标列表。不会处理列表就等于不会用这门语言。造一个列表有三种常见写法。第一种用list函数现场拼第二种用单引号直接写出来这叫引用意思是「原样当成数据别当代码执行」第三种用cons往已有列表前面接一个元素。(list 1 2 3) ; 得到 (1 2 3) (1 2 3) ; 同样得到 (1 2 3)单引号表示原样对待 (cons 0 (1 2 3)) ; 得到 (0 1 2 3)把 0 接到最前面单引号这个符号是新手第一个大坑后面避坑章会专门讲这里先记住一句话不加引号的列表会被当成代码去执行加了引号才是数据。你写(1 2 3)工具会以为你要调用一个叫 1 的函数直接报错写成(1 2 3)才是你想要的那个列表。取值用car和cdr这一对是 Lisp 家族的传统名字第一次见会觉得很怪用两次就顺了。car取第一个元素cdr取除了第一个之外剩下的部分。(setq nums (10 20 30)) (car nums) ; 10 (cdr nums) ; (20 30) (length nums) ; 3元素个数把car和cdr套起来用就能取到任意位置的元素比如(car (cdr nums))得到 20。套得太深不好读实际写代码时更常用nth(nth 1 nums)同样得到 20注意它从 0 开始数。4.3 判断和循环让脚本自己跑起来只会顺序执行的脚本价值有限真正省时间的是「按条件做不同的事」和「对一堆东西重复做同一件事」。条件判断最常用的是if三个参数条件、条件成立时做什么、不成立时做什么。(setq w 12) (if ( w 10) (printf too wide\n) (printf ok\n) )是大于比较返回成立或不成立。if的返回值就是被选中的那一支的结果这个特性在赋值时会用到。当只有「成立才做」而没有「不成立做什么」时用when更省事反过来「不成立才做」用unless。这两个函数身上省掉的括号写多了你会感谢它们。; 只有条件成立才执行不成立就跳过 (when ( w 10) (printf wide: %L\n w) )循环里最常用的是foreach它遍历一个列表对每个元素执行一次。这个函数你几乎每天都会用到因为工具返回的东西都是列表。(setq widths (1.0 2.0 3.5)) (foreach w widths (when ( w 3) (printf big one: %L\n w) ) )这段的意思是从widths里逐个取出元素每次叫它w如果w大于 3就打印一行。%L是格式化占位符能打印任意类型的值调试的时候用它最省心不用管当前是数字还是列表。如果只是想按次数循环用for(for i 1 5 (println i))从 1 数到 5每次打印。这个写法在「重复执行固定次数」时比foreach直观。4.4 把它存成文件再加载从敲一行到有一个自己的库窗口里敲的代码关掉就没了所以真正的脚本要存成文件。SKILL 脚本文件一般用.il后缀用任何纯文本编辑器都能写注意别用会插入格式的富文本编辑器。写好的文件用load加载; 加载一个脚本文件路径用双引号包住 (load /home/user/mytools/area.il)路径建议一开始就写绝对路径相对路径在不同工作目录下会找不到文件这是新手最常见的翻车点之一。文件里可以只放一堆函数定义加载之后这些函数就能在窗口里直接调用。定义一个函数用procedure; 定义函数 rectArea接收两个参数 w 和 h (procedure (rectArea w h) (let ((a (* w h))) ; let 声明局部变量 a只在这个函数里有效 (printf area %L\n a) a ; 函数最后一句的值就是返回值 ) )拆开看procedure后面第一对括号里第一个词是函数名后面是参数名函数体里用let声明了一个局部变量a它的作用域只在这个函数内部函数执行完就消失不会污染外面的同名变量最后一行单独写了个a它的值就是这个函数的返回值。存好文件、加载、然后在窗口里敲(rectArea 10 5)应该看到输出area 50同时返回值也是 50。这一步跑通你就算是真正迈过门槛了——从「敲一行算一行」变成「有一个自己的小工具库」。5. 避坑与常见问题新手最容易翻车的五个地方这一章单独拿出来讲是因为下面这几件事几乎每个新手都会遇到而且它们每次出现时都显得特别莫名其妙。我把现象、原因、解决按顺序写清楚你对号入座就行。5.1 敲完回车没反应光标一直等现象输完一行回车工具不报错也不返回结果光标就停在那里等下一行。原因括号没配平通常是少了一个右括号。SKILL 靠括号判断一段代码有没有写完它认为你还在输入自然不会执行。解决把光标移到这段代码上从最内层括号开始往外数看看每一层是不是都有对应的右括号。用带括号配对的编辑器写脚本能省掉大量这种麻烦。实在找不到就把这段代码单独粘到窗口逐行回车哪一行之后还在等问题就出在哪一行。5.2 变量明明赋过值用的时候却是空的现象前面刚setq过后面打印出来却是空值或者报「未定义」。原因多半是加载文件的顺序问题或者变量名拼写不一致。还有一种情况是用let声明的局部变量出了函数体就失效了你在外面用当然取不到。解决先确认赋值那一行确实执行过在它后面立刻加一句打印做验证。变量名统一风格别一会儿大写一会儿小写混着拼。需要跨函数共用的话就得用全局变量别用let。5.3 列表一写就报错说函数不存在现象写(1 2 3)想表达一个列表结果工具报错说找不到叫 1 的函数。原因没加引号。不加引号的列表会被当成函数调用括号里第一个位置会被当成函数名1当然不是函数。解决想表达「这就是一份数据」前面加单引号写成(1 2 3)。或者干脆用(list 1 2 3)语义更明确不容易被自己看错。5.4 函数改了跑起来还是老结果现象明明改了文件里的函数体重新执行还是旧的行为。原因文件改了但没重新加载工具内存里跑的还是旧定义。解决改完文件必须再load一次。想确认当前到底加载了哪个版本可以在函数里加一句打印版本号一跑就知道是不是新的。这个习惯看着笨但排查问题时能省下大量时间。5.5 拿翻译文档当唯一标准术语对不上现象手册里写的函数名或者说法和你实际敲的不一样或者你按手册的术语去搜索什么都搜不到。原因这份文档是中文译本术语翻译可能和社区里的常见叫法有出入个别地方还带着机器翻译的痕迹另外手册对应的是特定版本不同版本之间函数行为可能有细微差别。解决遇到关键函数把中文说法和括号里的英文原名一起记住搜索时用英文原名。和实际行为对不上时直接在窗口里敲一遍验证以运行结果为准不要和文档较劲。6. 下一步学什么从会写一行到能做出一个小工具走到这里你已经能在窗口里算数、处理列表、写循环、把函数存成文件加载。接下来最忌讳的是回头把手册从第一页读到最后一页那样很容易读一半就停了。更有效的路子是带着一个具体的小需求往前推。6.1 按这个顺序往下学阶段学什么大概花多久检验标准第一阶段函数参数写法rest、optional、key三天能写出参数可省略的函数第二阶段文件读写把结果写进文本、再从文本读回来一周能导出一份自己的报表第三阶段命名规范与源码维护函数前缀、注释、拆分文件一周别人能看懂你的脚本第四阶段操作图形对象选中、改属性、批量处理两到三周能写一个批量改名工具optional这一组参数写法是我认为性价比最高的一个知识点。学会之后你写的函数就能带默认值调用的人少传一个参数也不会报错给别人用的工具立刻规范起来。6.2 一个能立刻用上的技巧调试脚本时别指望一次性写对。我的习惯是每写三五行就单独执行一次把中间结果打印出来看看形状对不对; 调试时随手打印中间结果确认数据形状 (setq items (1 2 3)) (printf count %L\n (length items)) (printf first %L\n (car items))两行打印能让你立刻知道拿到的到底是列表还是单个值是空表还是有内容。很多所谓的「玄学 bug」其实就是数据类型和你想的不一样。6.3 给自己定一个小目标不要以「学完手册」为目标那玩意没有终点。给自己定一个具体的小工具比如「把选中图形的名字统一加前缀」两周做出来你就彻底入门了。做出来的东西哪怕只有二十行也比看完十章强。我第一次写这类脚本的时候图省事跳过了验证那一步直接把一个改了属性的函数跑在整份设计数据上结果把一批不该动的对象也改了花了半天回滚。从那以后我每次写完改数据的脚本都强制先在一个小单元上跑一遍确认输出和预期一致再放大到整份数据。这个习惯看着慢其实是唯一能让你不返工的办法。希望帮到你。本文还有配套的精品资源点击获取