3. 数据准备与库文件解析:LEF、DEF、Liberty、TLU+ 文件格式详解

做后端布局,说白了就是跟一堆库文件打交道。很多新手一上来就被 LEF、DEF、Liberty、TLU+ 这些缩写搞晕了。我刚开始接触时也差不多,对着文件夹里几十个 .lib、.lef 文件发愣——它们到底是干嘛的?

今天咱们就把这些文件一个一个拆开看。你搞懂了它们,后端流程就通了三分之一。

3.1 LEF 文件:物理库的“骨架”

LEF(Library Exchange Format)描述的是芯片的物理信息。它不关心电路怎么工作,只关心“长什么样、占多大地方”。

我个人习惯把 LEF 分成两类:

  • 技术 LEF:定义工艺规则,比如金属层数、最小线宽、间距、通孔类型。这些是工艺厂给的,一般不能改。
  • 单元 LEF:定义每个标准单元、宏单元的物理尺寸、端口位置、障碍层。比如一个 NAND2 门,LEF 里会写它宽 0.5μm、高 1.0μm,A/B 输入端口在左边,输出 Y 在右边。

关键点:LEF 只包含 外形 和 端口位置,不包含逻辑功能。功能在 Liberty 里。

举个例子,一个简单的 INV 单元 LEF 片段长这样:

MACRO INV
  CLASS CORE ;
  ORIGIN 0 0 ;
  SIZE 0.5 BY 1.0 ;
  PIN A
    DIRECTION INPUT ;
    PORT
      LAYER M1 ;
      RECT 0.1 0.4 0.3 0.6 ;
    END
  END A
  PIN Y
    DIRECTION OUTPUT ;
    PORT
      LAYER M1 ;
      RECT 0.2 0.4 0.4 0.6 ;
    END
  END Y
  OBS
    LAYER M1 ;
    RECT 0 0 0.5 1.0 ;
  END
END INV

你看,它只说了这个单元占 0.5×1.0 的面积,A 和 Y 端口在 M1 层上的坐标,以及 M1 层哪些区域不能走线(OBS)。

我的经验:导入 LEF 时最容易踩的坑是 技术 LEF 和单元 LEF 版本不匹配。我曾经遇到过技术 LEF 定义了 8 层金属,但单元 LEF 里某个宏单元用了第 9 层——工具直接报错。所以导入前一定要检查层数一致性。

3.2 DEF 文件:设计的“蓝图”

DEF(Design Exchange Format)描述的是你的 具体设计。如果说 LEF 是乐高积木的说明书,那 DEF 就是你用这些积木搭出来的模型。

DEF 里包含:

  • 芯片的尺寸(DIEAREA)
  • 所有单元的位置(COMPONENTS)
  • 端口的位置(PINS)
  • 走线信息(NETS)
  • 障碍、区域约束等

一个典型的 DEF 片段:

DESIGN my_chip ;
  DIEAREA ( 0 0 ) ( 1000 1000 ) ;
  COMPONENTS 3 ;
    - U1 INV + PLACED ( 100 200 ) N ;
    - U2 NAND2 + PLACED ( 300 200 ) N ;
    - U3 DFF + PLACED ( 500 200 ) N ;
  END COMPONENTS
  PINS 4 ;
    - clk + NET clk + DIRECTION INPUT + LAYER M3 ( 50 50 ) ;
    - data + NET data + DIRECTION INPUT + LAYER M3 ( 50 100 ) ;
    - out + NET out + DIRECTION OUTPUT + LAYER M3 ( 950 50 ) ;
  END PINS
  NETS 3 ;
    - net1 ( U1 Y ) ( U2 A ) ;
    - net2 ( U2 Y ) ( U3 D ) ;
    - net3 ( clk ) ( U3 CK ) ;
  END NETS
END DESIGN

DEF 是后端流程中 最常读写 的文件。布局完成后写 DEF,布线完成后写 DEF,ECO 修改后也写 DEF。我一般会养成习惯:每做完一个步骤就 dump 一份 DEF 出来,方便回溯。

注意:DEF 的坐标单位是 微米(μm) 还是 数据库单位(DBU),取决于你在 LEF 里定义的精度。我见过有人把单位搞混,结果单元飞到芯片外面去了。导入后第一件事:用工具画一下 floorplan,看看单元是不是在合理位置。

3.3 Liberty 文件:时序的“灵魂”

Liberty(.lib)文件描述的是每个单元的 时序和功耗特性。它告诉你:

  • 输入到输出的延迟(cell rise/fall)
  • 建立时间、保持时间(setup/hold)
  • 输出驱动能力
  • 输入电容
  • 漏电功耗、动态功耗

这些数据是通过 查表(NLDM) 或 电流源模型(CCS) 给出的。查表维度通常是输入转换时间(slew)和输出负载电容(load)。

一个简化的 Liberty 条目:

cell (INV) {
  area : 0.5 ;
  pin (A) {
    direction : input ;
    capacitance : 0.002 ;
  }
  pin (Y) {
    direction : output ;
    function : "(!A)" ;
    timing () {
      related_pin : "A" ;
      timing_type : combinational ;
      cell_rise (delay_template_7x7) {
        index_1 ("0.01, 0.1, 0.5, 1.0, 2.0, 4.0, 8.0") ;
        index_2 ("0.01, 0.05, 0.1, 0.5, 1.0, 2.0, 4.0") ;
        values ( \
          "0.02, 0.04, 0.08, 0.15, 0.25, 0.40, 0.60", \
          "0.03, 0.06, 0.10, 0.18, 0.30, 0.45, 0.70", \
          ...
        ) ;
      }
    }
  }
}

这里 index_1 是输入 slew,index_2 是输出负载,values 是对应的延迟。工具通过 二维插值 算出实际工作条件下的延迟。

避坑指南:我曾经遇到一个项目,综合用的 .lib 是 slow 工艺角,后端导入的却是 fast 工艺角。结果时序分析全乱套了。所以导入 Liberty 时一定要确认 工艺角(PVT) 是否正确——温度、电压、工艺偏差这三个参数必须跟你的设计目标一致。

3.4 TLU+ 文件:互连线的“电阻电容”

TLU+(Technology LEF-based Unified parasitic format)是工艺厂提供的 寄生参数文件。它描述了每层金属的:

  • 单位长度电阻(R per μm)
  • 单位长度电容(C per μm)
  • 层间耦合电容
  • 通孔电阻

没有 TLU+,工具就不知道一根 100μm 长的 M2 走线到底有多大的 RC 延迟。说白了,TLU+ 是 时序精度的基石。

TLU+ 文件通常以 .tluplus 或 .itf 格式提供。导入时需要配合 映射文件(map file),把 LEF 里的层名映射到 TLU+ 里的层名。

举个例子:LEF 里叫 M1,TLU+ 里叫 METAL1。映射文件里写一行 M1 METAL1,工具才能对上号。

3.5 工艺库的导入与检查

好了,文件都认识了。那怎么导入?导入后怎么确认没问题?

我一般按这个流程走:

  1. 整理文件清单:确认拿到技术 LEF、单元 LEF、Liberty(所有工艺角)、TLU+、映射文件。
  2. 检查版本一致性:所有文件必须来自 同一工艺版本。混用不同版本的库是灾难。
  3. 导入工具:以 Innovus 为例,用 setTechLEF、setCellLEF、read_lib、set_tlu_plus 命令依次导入。
  4. 运行检查:工具一般有 check_library 或 verify_library 命令。跑一遍,看有没有 missing cell、missing pin、层名不匹配等问题。
  5. 可视化验证:打开 GUI,随机挑几个单元看看。形状对不对?端口位置合理吗?

下面这张图总结了四种文件的关系:

后端库文件体系与数据流 LEF 物理外形 + 端口 DEF 设计实例 + 位置 Liberty 时序 + 功耗 TLU+ 寄生 RC 后端工具(Innovus / ICC2) 布局 → 时钟树 → 布线 → 时序优化 GDS / Netlist / SDF 💡 关键理解: LEF 提供“积木块”,DEF 提供“搭建图纸”,Liberty 提供“积木性能”,TLU+ 提供“连接线参数”。 四者缺一不可,共同支撑后端工具完成布局布线与时序收敛。

3.6 导入后的检查清单

导入不是点一下按钮就完事了。我每次都会过一遍这个清单:

检查项 方法 常见问题
LEF 层数一致性 对比技术 LEF 和单元 LEF 的金属层定义 单元 LEF 用了未定义的层
Liberty 工艺角 确认 .lib 文件名或内部 PVT 条件 误用不同电压的库
TLU+ 映射 检查 map 文件是否覆盖所有 LEF 层 漏映射导致寄生提取失败
单元完整性 运行 check_library 或 report_library 缺少某些标准单元
端口对齐 GUI 中查看单元端口位置 端口在障碍区内

血的教训:我曾经在一个 28nm 项目里,导入 LEF 时没注意技术 LEF 里定义了 双重图案(DPT) 规则,但单元 LEF 没更新。结果布线时工具死活绕不过去,最后发现是 LEF 版本不匹配。从那以后,我每次导入都会用 diff 命令对比新旧 LEF 的层定义部分。

嗯,数据准备这一步看着琐碎,但真不能省。你想想看,如果库文件本身就有问题,后面做的所有工作都是白费。花半小时检查,能省后面好几天 debug 的时间。