
简介Cadence 官方发布的 LEF/DEF 5.8 语言参考手册是面向集成电路设计、电子设计自动化工具开发和物理实现工程师的权威技术文档。LEF 用于定义工艺技术层、单元模型与间距规则DEF 用于描述模块布局、网络连接和约束信息二者是物理综合、布局规划、验证及跨工具数据交换的标准格式。资源包含 1 个 PDF 文件大小 2.48MB为完整英文原版手册已有 2171 人浏览学习。手册内容涵盖技术层定义包括金属层、多晶硅层、接触层等及其电气特性、单元模型、间距规则、填充与隔离区域、宏模型以及模块布局、网络连接、通孔与多层互联、约束设置、物理分区和物理属性等核心语法附录中还提供 Whats New 和 Preface 章节方便读者快速定位 5.8 版本新增与变更内容。对需要编写或解析 LEF/DEF 文件、核对先进工艺节点下金属层、通孔与 site 定义的后端工程师及库建模人员而言这是一份可直接检索的案头参考。1. LEF/DEF 5.8 语言参考数字后端绕不开的交换格式字典在 lefdefeda 这条技术线里LEF/DEF 5.8 语言参考是绕不开的一本官方语法字典。它解决的是流程中最实际的问题工艺规则怎么从代工厂数据变成布局工具认得出来的 Layer 描述标准单元引脚和阻挡层怎么抽象成 Macro布局布线完成后实例位置、走线关系又怎么写成 DEF 交回给下游验证工具。LEF 管「工艺和单元库长什么样」DEF 管「这个设计具体怎么摆、怎么连」。刚接触后端的工程师照着它能把 netlist 到 GDS 之间的黑匣子逐段拆开熟手则拿它当边界参考遇到解析器不认的关键字翻回语法定义定位。适合所有写 PnR 脚本、读版图日志的人。2. LEF 技术文件从 UNITS 到 MACRO把工艺与单元库读进门手册的第一大部分是 LEF 语法内容围绕一件事把工艺与单元库描述成几何对象。拿到一份 LEF先看的不是某一条语句而是整体顺序和四个开头的全局字符约定。2.1 语法顺序与字符约定VERSION 到 NONDEFAULTRULELEF 文件里语句出现顺序有硬性规定不能想到什么写什么。手册在第一章直接给了 Order of LEF Statements顺序大致是 VERSION、BUSBITCHARS、DIVIDERCHAR、UNITS、MANUFACTURINGGRID、LAYER、SITE、MACRO、VIA、VIARULE、NONDEFAULTRULE、PROPERTYDEFINITIONS最后以 END LIBRARY 收尾。这个顺序不是装饰它决定了增量读入时的依赖关系单位没定义清楚后面的层和宏坐标就无从解释层没定义宏里的引脚引用层名就悬空。实际项目里我很少手写 LEF基本都是工具输出后做局部修改但每次改完都会按这个顺序核对一遍防止把新语句插错位置。几个全局字段值得单独说。VERSION 声明格式版本解析器用它决定按哪套规则解释后续语句版本写错比语法错更隐蔽因为它不报错只是行为不同。BUSBITCHARS 定义总线名的方括号字符默认是[和]像data[3]这种名字靠它识别。DIVIDERCHAR 定义层次分隔符默认是/层次化单元名靠它拼接。UNITS 段最实用LEF 里写成UNITS DATABASE MICRONS 1000 ;意思是数据库坐标值乘以 0.001 才是物理微米。不同工艺库这个系数可能差好几倍解析脚本第一步永远是读 UNITS 生成换算因子而不是先算坐标。还有两个通用约定语句以分号结束块状语句用 END 收尾。比如 LAYER 块以END layerName结束MACRO 块以END macroName结束END 后面的名字必须和开头一致。我见过最频繁的报错就是 END 抄错名字解析器直接提示块未闭合。VERSION 5.8 ; BUSBITCHARS [] ; DIVIDERCHAR / ; UNITS DATABASE MICRONS 1000 ; MANUFACTURINGGRID 0.005 ;这是一段最小 LEF 文件头的标准顺序。逻辑说明先声明版本再声明两个字符约定接着是单位和制造格点。MANUFACTURINGGRID 是工艺格点所有坐标理论上都是它的整数倍先进工艺下这个值通常是 0.001 或 0.005 这类小数换算后可以检查坐标合法性。参数说明DATABASE MICRONS 后面的 1000 不是固定值有的库用 2000有的用 4000解析时必须从文件里取而不是写死。BUSBITCHARS 和 DIVIDERCHAR 都有默认值但如果文件里显式声明了后续解析要按声明的来。2.2 Layer 段从 ROUTING 到 CUT 的参数地图Layer 是 LEF 里最常改的段落也是新人最容易看晕的段落。手册把层分成五类ROUTING、CUT、MASTERSLICE、IMPLANT、OVERLAP类型直接决定哪些关键字合法。ROUTING 层描述实际走线的金属层有 PITCH、WIDTH、SPACING、DIRECTION、RESISTANCE、CAPACITANCE先进工艺还要带 MAXWIDTH、MINWIDTH 和天线相关参数。CUT 层描述通孔切割层关心 WIDTH 和 SPACING通孔阵列尺寸靠它约束。IMPLANT 层只做注入区标示不参与布线。OVERLAP 层专门做单元重叠检查。MASTERSLICE 一般是基础层定义相对简单。LEF 层类型作用常见关键字ROUTING布线金属层、多晶硅层PITCH / WIDTH / SPACING / DIRECTION / RESISTANCE / CAPACITANCE / MAXWIDTH / MINWIDTH / ANTENNAAREAFACTORCUT通孔切割层WIDTH / SPACING / ENCLOSUREMASTERSLICE基础工艺层SPACING / PITCHIMPLANT注入区标记WIDTH / SPACINGOVERLAP重叠检查WIDTHROUTING 层的 PITCH 有讲究。规则一点的库会给两个方向的值比如 M1 的 x 方向 pitch 和 y 方向 pitch 不同因为横向纵向布线密度不一样。SPACING 更复杂可以只跟一个数值表示均匀间距也可以跟 RANGE 子句组成查表间距。查表间距在先进工艺里几乎必用宽金属的间距需求比窄金属大得多手册里对这种带 RANGE 的写法列得很细但自己写解析脚本时要注意SPACING 后面跟的数字不一定只有一个后面可能还挂着 RANGE 和 USEMINSPACING不能只取第一个浮点数就收工。我在实际项目里写过一个快速扫描脚本用来预检 LEF 的 layer 段有没有缺关键字段import re def scan_route_layer(lef_path, layer_name): layer_info {name: layer_name} with open(lef_path, r, encodingutf-8, errorsignore) as f: lines f.read().splitlines() in_block False for line in lines: if line.strip().startswith(LAYER) and layer_name in line: in_block True continue if in_block: if line.strip().startswith(END): break m re.match(r\s*(PITCH|WIDTH|SPACING|DIRECTION)\s([0-9.]|\w), line) if m: layer_info[m.group(1).lower()] m.group(2) elif SPACING in line and RANGE in line: layer_info[spacing_has_range] True return layer_info逻辑说明这段脚本逐行进 LAYER 块、出 LAYER 块只抓 PITCH、WIDTH、SPACING、DIRECTION 四个最常用的字段并单独标记 SPACING 是否带 RANGE。它不做完整解析目的是快速发现字段缺失。参数说明lef_path 是 LEF 文件路径layer_name 是要查的金属层名返回的 dict 里都是字符串具体数值要结合 UNITS 段换算。这个脚本只能做预检查真正的解析要处理注释行LEF 里 # 开头是注释、引号内特殊字符和层名大小写生产环境建议直接用现成解析库。2.3 Macro 与 Site标准单元抽象的核心Site 定义 row 的基本类型。后端工具摆放标准单元时每个单元都要落在某个 site 的 grid 上。Site 有 CORE、PAD 等类型有 CLASS有 SIZE还有 SYMMETRY。一个设计里通常有 core site 和 pad site 两种分别约束内核区域和 IO 区域。SIZE 决定了 row 的高度比如一个 site 高度等于标准单元高度宽度等于最小的单位宽度所有单元尺寸都是它的整数倍。Macro 是标准单元或宏模块的抽象描述包含 ORIGIN、SIZE、PIN、OBS 这些关键块。ORIGIN 定义单元在库里的坐标原点SIZE 定义外框尺寸PIN 定义每个引脚的金属层、几何形状和方向OBS 定义单元内部占据物理空间的多边形布局工具放单元时用 OBS 做间距检查。Macro 的 CLASS 字段很关键CORE、PAD、BUMP、BLOCK 分别对应不同的放置策略和检查规则。读 Macro 段时我一般会重点关注三处。第一是 FOREIGN 字段它把 LEF 里的单元名和 GDS 里的单元名做映射手工建库漏了这行会导致同名但坐标对不上版图。第二是 PIN 的方向和 USE 组合方向有 INPUT、OUTPUT、INOUTUSE 有 SIGNAL、POWER、GROUND、CLOCK这组组合是后端工具做时序和电源分析的重要依据。第三是 SYMMETRYX、Y、R90 三个值告诉工具这个单元能不能做镜像和旋转写错了工具宁可绕远路也不会用非法方向的单元。Macro 段在实际流程里不是人写的而是从单元库导出的真正是人写的是读这些数据的脚本。常见做法是把 SIZE、PIN 的 PORT 坐标、OBS 多边形解析出来画一个简化框图在 floorplan 早期评估摆几个单元会占多大面积。这份手册的价值就在这里语法定义清楚了脚本才不会靠猜。3. DEF 设计文件COMPONENTS、NETS 与 SPECIALNETS 的摆放互连解读LEF 描述的是类型DEF 描述的是实例。二者分工清楚LEF 里有一份 M1 层定义DEF 里才有具体一根 M1 走线。整份 DEF 文件开头段落固定中间最常碰的是 COMPONENTS、PINS、NETS、SPECIALNETS 四段本质上就是一张「摆放加连线」的清单。3.1 DEF 顶层与顺序DESIGN 到 DIEAREADEF 文件开头的段落结构在手册里也有固定顺序。全文从 VERSION 和 DESIGN 开始DESIGN 后面跟着设计名然后依次是 UNITS、TECHNOLOGY、DIEAREA再往后才是 ROWS、TRACKS、COMPONENTS、PINS、NETS、SPECIALNETS、BLOCKAGES、FILLS、REGIONS、GROUPS、SCANCHAINS、VIAS最后以 END DESIGN 收尾。DEF 语句作用VERSION声明 DEF 格式版本DESIGN设计名UNITS坐标单位写法与 LEF 不同TECHNOLOGY引用的技术库名DIEAREA芯片边界四角坐标ROWS / TRACKSrow 与布线轨道定义COMPONENTS实例列表PINS顶层端口NETS / SPECIALNETS信号与电源地走线BLOCKAGES / FILLS阻挡与填充REGIONS / GROUPS区域与分组SCANCHAINS / STYLES / VIAS扫描链、样式、通孔顺序在 DEF 里比 LEF 更敏感。做增量编辑时我尽量保持原有顺序只在对应位置追加因为某些工具对语句顺序有依赖乱插可能导致解析警告或静默忽略。UNITS 在 DEF 里写法和 LEF 不一样DEF 用UNITS DISTANCE MICRONS 100 ;这种形式DISTANCE 而不是 DATABASE这是两个格式最常被搞混的地方之一。DIEAREA 里的四个点描述芯片边界坐标这些值都是数据库坐标物理尺寸要除以 UNITS 里的数。单位换算的坑在第 5 章还会细讲这里先给个结论所有解析 DEF 的脚本第一件事都是把 UNITS 段读出来存成全局换算因子任何坐标输出前统一乘这个因子不要裸用原始值。同一个 DEF 里如果出现坐标数字看起来忽大忽小十有八九是单位处理出了问题而不是坐标本身错了。3.2 Components 与 Pins实例与端口的描述方式COMPONENTS 段是 DEF 里信息量最大的部分。它以COMPONENTS 数量 ;开头下面每行是一个实例格式大致是实例名、单元名、放置状态、坐标、方向。放置状态有 PLACED、FIXED、COVER、UNPLACED 四种。PLACED 和 FIXED 都会带坐标区别是 FIXED 表示位置锁定布局工具不能动UNPLACED 表示还没摆后面通常不跟坐标。COVER 是比较特殊的状态表示覆盖物比如 decap 电容不算普通逻辑单元。方向的写法也要习惯N、S、E、W 代表四个基本朝向FN、FS、FE、FW 带 F 前缀代表翻转。布局工具做镜像后写入 DEF 的方向就是这些枚举。读 Components 时最容易出的问题是不认识方向字符串尤其是自定义脚本里只处理了四个基本朝向遇到 FN 就直接抛异常。手册里把方向枚举列得非常全写解析器时对齐一下就能避免。顶层 Pins 段描述芯片的 IO 端口PIN 名对应的 NET 名、DIRECTION、USE以及 PORT 里的层与坐标。这里的坑是 DIRECTION 和 USE 的组合必须合法比如方向是 INPUT 但 USE 写成 POWER两边冲突会在物理验证阶段报端口类型不匹配。还有一个常见情况是 DEF 端口坐标和 LEF 里同名宏的引脚坐标不一致这通常发生在工程修改了单元库但 DEF 没有重新生成的时候。快速统计一下 DEF 实例数量和分布一般够我判断文件是否完整import re def count_components(def_path): comp_pat re.compile(r^\s*-\s(\S)\s(\S)\s(PLACED|FIXED|COVER|UNPLACED)) comps [] with open(def_path, r, encodingutf-8, errorsignore) as f: in_comp False for line in f: if line.strip().startswith(COMPONENTS): in_comp True continue if in_comp and line.strip().startswith(END COMPONENTS): break if not in_comp: continue m comp_pat.match(line) if m: comps.append((m.group(1), m.group(2), m.group(3))) return len(comps), comps[:5]逻辑说明脚本在 COMPONENTS 与 END COMPONENTS 之间逐行匹配以-开头的条目提取实例名、单元名、放置状态。只做到顶层统计不解析坐标因为坐标的列位置在不同工具输出里有差异用通用正则反而容易误判。参数说明返回的元组里第一个数是实例总数第二个是前五个样例。真正解析坐标时要在这条正则后面补坐标捕获组坐标和方向字段要按照文件实际列顺序调整。3.3 Nets 与 SpecialNets信号和电源地走线NETS 段描述信号连接关系。每条 net 以- netName开头后面跟一组引脚引用然后是 ROUTED 关键字和走线描述。ROUTED 后面是一系列 layer 名和坐标点比如一条 net 先在 M2 上走一段再通过 via 到 M3 上走另一段路径就把这几段按顺序写出来。SOURCE 字段标记 net 的来源常见值是 TIMING 或 NETLISTUSE 字段标记信号类型。WIREDLOGIC 是特殊场景用的表达线与逻辑平时很少遇到。SPECIALNETS 结构和 NETS 类似但专门描述电源地网络。差别在于 SPECIALNETS 里的 WIDTH 通常远大于信号线宽度还可能用 POLYGON 画形状而不是 PATH 画路径。电源地走线在物理实现里是宽的金属形状布线工具默认不去碰这些对象。读 SPECIALNETS 时要特别注意 WIDTH 后面的值它决定电源地网络的电阻估算值错了电压降分析会偏差很大。走线段落的坑多在 PATH 坐标点上。正常路径每个点由两个坐标组成但有些工具会把 pin 位置也写成点形成单点路径。这种 stub 在物理上可能合法但在某些检查器里会报悬空线段警告。我处理 DEF 时习惯先统计 PATH 后面坐标点的奇偶性和层切换次数数据异常就回头核对是不是工具做了特殊优化。解析器最容易翻车的地方正是这里语法合法但语义需要上下文判断。4. 落到真实流程增量 LEF、ALIAS 与天线参数怎么用前两章是语法层的读法这一章聊手册在实际流程里最常被调用的三块增量 LEF、ALIAS 扩展、天线效应相关字段。这三块是 5.8 版本里相对好用的东西也是项目里最容易踩到新问题的地方。4.1 增量 LEF不用全量重读的省事手段Incremental LEF 的思路很实用只把变化的 Layer 或 Macro 追加进一个新 LEF 文件工具基于已读入的 base LEF 做覆盖合并。手册里对增量文件有明确约束增量文件同样要写 VERSION被覆盖的定义必须保持同名同类型。这意味着增量文件不是一个完整的上下文而是一份「补丁」。实际场景里最典型的是 ECO。某标准单元改了 OBS或者多了一个引脚只发一个增量 LEF 给后端工具就能跑增量 PnR不用把整层库重新读一遍。这在工程时间上节省得很明显尤其是库特别大的时候全量读 LEF 可能要好几分钟。我维护脚本时习惯用 grep 快速看增量文件的结构grep -n -E ^(MACRO|LAYER|END ) incr.lef | head -80逻辑说明这条命令把增量 LEF 里出现的 MACRO、LAYER 以及对应的 END 行带行号打出来初看结构是否完整。参数说明head -80 只是限制输出行数实际文件大时需要看更多更可靠的做法是grep ^MACRO incr.lef | sort | uniq -c确认同一名字只出现一次。增量文件最常见的错误就是同一个 MACRO 被定义了两次工具不会报错但行为取决于实现可能用后一个覆盖前一个也可能直接拒绝。增量覆盖的语义还要注意一点覆盖同名对象时只有增量文件里出现的字段会更新没出现的字段保留旧值。这意味着如果只想清空 OBS必须显式写一个空的 OBS 定义而不是简单地不写 OBS 字段。4.2 ALIAS 语句总线名的简化写法ALIAS 是 5.8 手册里单独一章讲的内容作用是把带方括号的总线名映射成简单别名。比如把addr[0]映射成A0把data[7]映射成D7。这在实际操作里非常省事尤其是交互式命令行里敲 net 名方括号要转义很容易敲错。手册把 ALIAS 分成定义、示例、展开三块。定义语法就是ALIAS 别名 原始名字 ;展开规则处理的是带 bus bit 的名字如何递归替换。我在第三方 DEF 里经常看到 net 名带完整总线后缀手敲命令时用别名效率高很多。需要提醒的是 ALIAS 不会自动被所有工具展开如果发现 DEF 里 net 名和 LEF 里对不上先看文件头部有没有 ALIAS 段落别急着改数据。4.3 天线效应字段从 LEF 参数到验证链路附录 C 讲了完整的 Process Antenna 检查链路这是先进工艺绕不开的话题。核心问题是等离子体刻蚀过程中连接到栅极的金属面积过大会积累电荷损伤栅氧化层。LEF 侧在 ROUTING 层定义 ANTENNAAREAFACTOR 这类参数表示该层金属面积对天线效应的贡献因子DEF 侧则通过 net 的几何信息算各层暴露面积验证工具结合栅面积给出 antenna ratio超过阈值就报 violation。实际项目里最隐蔽的问题就是换工艺文件版本后天线参数丢了。我有一次在模拟项目X里跑签核前一天天线检查全绿第二天换了新 LEF 文件后突然全红排了半天发现新 LEF 的 ROUTING 层漏了 ANTENNAAREAFACTOR。坐标没错、连线没错只是物理参数没传到验证工具里。从那以后我把天线因子校验加进了例行检查换 LEF 必 grep 天线关键字。附录 B 的内容是优化 LEF Technology 文件对象是 place and route 工具的表现。它不教你语法教你写法routing pitch 怎么设、wide metal spacing 怎么配合、via 处 wire extension 给多少、默认 via 的枚举顺序。里面的核心经验是 via 列表顺序会影响布线器选择默认 via 要放在最前面否则布线器可能随机选到性能较差的 via。这些经验值不写进语法规则但对后端流程的收敛速度影响很大。5. 常见问题与避坑版本、单位、增量覆盖的五个实际教训这一章整理我实际踩过的坑每条都按「现象 → 原因 → 解决」来说值得存进自己的排错清单。5.1 现象用 5.8 语法写的 LEF解析器报 unexpected keyword原因文件头 VERSION 写的是 5.8但解析器实际只支持到 5.7或者 LAYER 段用了一个 5.8 新增的关键字旧版本工具不认。这类问题最迷惑人的地方在于关键字在手册里有、语法也对但工具就是不认。解决先确认工具版本对应的 LEF/DEF 支持级别再看手册 Whats New 章节里 5.8 的变更列表把新增关键字去掉或者升级工具。不要一上来怀疑语法写错先看版本宣言。提示VERSION 字段写高版本不会报错但行为可能完全不一样这是最阴的坑。5.2 现象从 DEF 算出的坐标和版图差 10 倍原因LEF 用 DATABASE MICRONSDEF 用 DISTANCE MICRONS两边数值可能不同或者同一个 DEF 里混用了不同单位基准的坐标脚本只取文件头单位就会读歪。解决脚本里做成「读 UNITS 段 → 生成换算因子 → 所有坐标过换算函数」的管线任何绝对坐标都不裸用原始值。我吃过一次 10 倍坐标错位的亏当时 pad 位置全乱了排查发现是单位系数写死成了 100实际文件里是 1000。5.3 现象PIN 方向为 INPUTUSE 却是 POWERDRC 报端口类型冲突原因LEF 里 Macro 的 PIN 定义和 DEF 顶层 PIN 定义不一致或者第三方 DEF 生成时方向与 USE 字段没有同步更新。解决先比对 LEF 同名宏的 PIN 方向和 DEF 里的引用方向再看 DEF 的 PinProperties 覆盖段。常规做法是把两侧 PIN 的 direction/use 拉出来做 diff问题定位很快不用肉眼一行行找。5.4 现象增量 LEF 读入后旧 Macro 的 OBS 还在原因增量 LEF 的覆盖语义是字段级覆盖不是对象级替换。增量文件里只写了 PIN 没写 OBSOBS 就保留旧值。如果基类里 OBS 很大而新单元已经改了外框布局工具会拿旧 OBS 做间距检查结果布局重叠。解决增量文件里被修改的 Macro 必须写全 SIZE 和 OBS只改 PIN 等于埋雷。我现在的增量脚本会强制检查凡是出现在增量文件里的 MacroOBS 字段必须非空。5.5 现象天线检查从全绿到全红只换了一个 LEF原因新 LEF 的 ROUTING 层没有携带天线因子或者因子值被导出工具重置为默认。原因不在 DEF是工艺参数没有传到验证链路。解决换工艺文件版本后把天线因子校验纳入例行检查。用 grep 抓每个 ROUTING 层的 ANTENNAAREAFACTOR 和其他天线关键字确认非空再往下跑。不要假设工具会自动继承旧值先进工艺下这个假设非常危险。6. 验证技巧最小可读文件与手册检索两步走接触新工具或者新版本的 LEF/DEF 解析器时我习惯先做一个最小可读文件验证。所谓最小就是只写必要的头部语句没有真实单元没有走线喂给解析器确认它认这个版本。这一步能把版本兼容问题挡在真正数据之前。VERSION 5.8 ; BUSBITCHARS [] ; DIVIDERCHAR / ; UNITS DATABASE MICRONS 1000 ; END LIBRARYVERSION 5.8 ; DESIGN demo ; UNITS DISTANCE MICRONS 1000 ; END DESIGN第一个是最小 LEF第二个是最小 DEF两个都能被解析器正常读入说明版本链路是通的。逻辑说明最小文件不包含真实内容只验证头部语法和版本声明。参数说明BUSBITCHARS 和 DIVIDERCHAR 的写法要和真实数据文件保持一致UNITS 系数用目标工艺的典型值即可因为这里只测解析不测坐标。做完最小验证第二步是把手册变成可检索的字典。原始 PDF 用命令行工具转成纯文本之后所有报错都能按关键字反查pdftotext lefdefref-5.8.pdf lefdefref.txt grep -n ANTENNAAREAFACTOR lefdefref.txt | head -20 grep -n NONDEFAULTRULE\|SPECIALNETS lefdefref.txt | head -40逻辑说明pdftotext 把 PDF 转成文本grep 按关键字定位语法定义出现的章节。参数说明head -20 限制输出条数多条关键字用\|分隔做或匹配。报错信息里出现的陌生关键字先在这里搜索再顺着行号翻上下文比从头翻手册快得多。从那以后我每次拿到新库或者新 DEF都强制先跑一遍最小文件验证加关键字检索确认版本和字段完整性再动手写解析脚本。这个习惯救过我很多次尤其是换工艺节点的时候。希望帮到你。本文还有配套的精品资源点击获取