作者Darren H. Chen方向Backend 工具开发 / 后端实现流程 / 工程化脚本 / 验证基础设施demoLAY-BE-11_design_object_model标签Backend Flow、EDA、Tcl、Design Object Model、Cell、Net、Pin、Port、后端实现、工程化流程在前面的文章中我们已经讨论了几个基础问题环境如何可复现 session 状态如何控制 Tcl 为什么是工具控制层 log / cmd.log 如何固化工程现场 脚本为什么要先验证再执行 命令帮助基线为什么是工程基准面 Project Library 如何建立工艺与单元库上下文 多种标准格式如何共同进入 Backend Flow Design Import 如何建立设计数据库 link_project 为什么决定设计是否真正被工具理解。当 design import 和 link 完成以后工具内部已经不再只是几份输入文件。它开始拥有一个可以查询、可以分析、可以修改、可以报告的设计数据库。这个数据库中最基础的单位不是文件也不是脚本而是一组对象cell net pin port如果不能理解这些对象之间的关系后面的 placement、timing、CTS、routing、ECO、report 都会变成一堆命令堆叠。如果能理解对象模型Backend Flow 就会变成一个围绕设计数据库逐步推进的工程系统。本文只讨论一个问题为什么 cell、net、pin、port 是 Backend Flow 工程化的基本单位一、Design Import 之后工具内部发生了什么从外部看设计输入可能只是几类文件Verilog netlist LEF Liberty DEF SDC UPF GDS / OASIS parasitic file但工具不会一直以“文本文件”的方式理解设计。真正进入 Backend 工具以后这些文件会被解析、关联、检查并转换成内部对象。例如Verilog instance - cell instance Verilog wire - net module port - port cell pin - pin Liberty cell - library cell LEF macro - physical master SDC clock - timing object DEF placement - physical location也就是说工具内部看到的不是一堆文本行而是一个对象网络。这个对象网络就是设计数据库的基本形态。二、为什么不能只把 netlist 当成文本很多人第一次处理 netlist 时会自然地把它看成文本。例如INVX1 U1 (.A(n1), .Y(n2)); NAND2X1 U2 (.A(n2), .B(n3), .Y(n4)); DFFQX1 U3 (.D(n4), .CK(clk), .Q(q));如果只是做简单文本处理你可以看到有几个 instance 每个 instance 用了什么 cell type 每个 pin 连到了哪个 net。但 Backend 工具需要理解的远不止这些。它还要知道U1 是一个 instance还是一个 hierarchy module INVX1 在 library 中是否存在 U1 的 pin A 在物理版图中在哪里 n2 是普通 signal net还是 clock net还是 power net U3 的 CK pin 是否属于 clock network q 是内部 net还是 top-level output port 这些对象是否已经被 placement、route、timing 分析使用这些问题不是文本搜索能可靠解决的。它们必须依赖工具内部的对象模型。三、对象模型的核心名字不是对象本身在 Backend Flow 中一个非常重要的概念是name 只是对象的标识方式之一不等于对象本身。例如U1 n2 clk q这些都是名字。但工具内部真正处理的是对象。一个 cell object 可能包含name master cell hierarchy path placement location orientation fixed status size area connected pins properties一个 net object 可能包含name net type driver loads connected pins routing status wire geometry capacitance clock / signal / power usage properties一个 pin object 可能包含name direction owner cell connected net physical pin shape timing arc role capacitance transition properties一个 port object 可能包含name direction top boundary relation connected net IO constraint input / output delay physical pin relation properties所以脚本层真正应该操作的是对象而不是单纯字符串。四、cell设计数据库中的实例化基本单位cell 是 Backend Flow 中最常被操作的对象之一。但这里要区分两个层次library cell / master cell instance celllibrary cell 描述的是“这个单元类型是什么”。例如INVX1 NAND2X1 DFFQX1 BUFX4 CLKBUF_X8它来自 standard cell library 或 macro library。instance cell 描述的是“这个设计中具体用了一个这样的单元”。例如U1 是一个 INVX1 instance U2 是一个 NAND2X1 instance U3 是一个 DFFQX1 instance。这两个概念不能混淆。1. library cell 关注能力library cell 通常回答这个 cell 能做什么逻辑功能 面积是多少 pin 有哪些 timing arc 如何 是否可以用于优化 是否可以用于 CTS 是否有 physical abstract2. instance cell 关注当前设计状态instance cell 通常回答这个 instance 放在哪里 连接到哪些 net 是否 fixed 是否属于某个 hierarchy 是否在 critical path 上 是否被替换、移动、buffer 或 resizeBackend Flow 的很多操作本质上都是围绕 instance cell 展开的。例如get_cells * get_property [get_cells U1] ref_name get_property [get_cells U1] is_fixed report_property [get_cells U1]这些命令的意义不是“查字符串”而是访问设计数据库中的 cell object。五、net连接关系与物理布线的承载对象net 是连接关系的基本单位。在逻辑层面net 连接 driver 和 load。在物理层面net 会逐步演变成真实的 wire、via、route shape。一个 net 通常经历多个状态逻辑连接存在 ↓ 被识别为 signal / clock / power / ground ↓ 被 timing 引擎分析 ↓ 被 placement 用于估算线长和拥塞 ↓ 被 global route 规划路径 ↓ 被 detail route 生成几何图形 ↓ 被 DRC / antenna / extraction / timing 更新使用所以 net 不是简单的一条线。它在 Backend Flow 中同时承担三类角色逻辑连接对象 时序传播对象 物理布线对象例如get_nets *clk* get_property [get_nets clk] net_type get_pins -of_objects [get_nets clk] report_property [get_nets clk]通过 net object可以进一步追踪谁驱动它 它连接到哪些 load 它是不是 clock net 它是否已经 route 它是否有异常 fanout 它是否属于高风险 timing path这就是为什么 net 是后端实现中非常核心的对象。六、pincell 与 net 之间的连接界面pin 是 cell 和 net 之间的连接点。从逻辑角度看pin 表示单元端口。从物理角度看pin 对应实际可接入的 pin shape。从时序角度看pin 是 timing path 的节点。例如U1/A U1/Y U3/D U3/CK U3/Q这些 pin 在不同视角下有不同意义。1. 逻辑视角pin direction input / output / inout function relation connected net2. 物理视角pin shape layer access point routing connection pin blockage relation3. 时序视角arrival time required time transition capacitance slack timing arc endpoint很多 Backend 问题最终都会落到 pin 上。例如为什么某条 path slack 差 为什么某个 load 太重 为什么 route 接不上 为什么 CTS 没有识别某个 clock sink 为什么 output delay 没有生效这些问题往往都需要查询 pin 对象。示例get_pins U3/CK get_property [get_pins U3/CK] direction get_property [get_pins U3/CK] net report_property [get_pins U3/CK]pin 是连接逻辑、物理和时序的交叉点。七、port设计边界上的接口对象port 是 top-level module 与外部世界之间的接口。例如clk rst_n scan_en data_in[0] data_out[0]port 和 pin 很容易混淆但它们所处层次不同。pin 通常属于 cell instance port 通常属于当前 design boundary。port 在 Backend Flow 中非常重要因为它直接关联IO constraint input delay output delay drive / load physical IO placement pad / bump connection top-level net connection例如get_ports * get_property [get_ports clk] direction get_nets -of_objects [get_ports clk] report_property [get_ports data_out]如果 port 没有被正确理解可能出现SDC 约束无法绑定 input / output delay 不生效 IO placement 无法对应 top-level connectivity 异常 export 后边界信息不完整。所以 port 是设计数据库和外部约束世界之间的入口。八、cell、net、pin、port 之间的关系这四类对象并不是孤立存在的。它们共同构成了一个连接图。可以用一个简化模型表示Top Port: clkNet: clkPin: U3/CKCell: U3 DFFQX1Cell: U1 INVX1Pin: U1/YNet: n2Pin: U2/ACell: U2 NAND2X1这个图说明port 连接到 net net 连接到 pin pin 属于 cell cell 通过 pin 和 net 与其他 cell 形成连接关系。Backend 工具所谓“理解设计”很大程度上就是建立、维护和查询这张对象关系图。九、对象查询不是 grep而是数据库访问很多脚本问题来自一个误区把对象查询当成名字匹配。例如get_cells *buf*这看起来像字符串匹配但真正返回的通常是一组 cell objects。这些对象可以继续作为后续命令输入set bufs [get_cells *buf*] report_property $bufs get_pins -of_objects $bufs这就是对象查询和文本 grep 的根本区别。文本 grep 得到的是字符串。对象查询得到的是设计数据库对象集合。对象集合可以继续参与属性查询 过滤 报告 高亮 选择 导出 检查 阶段控制所以Backend Tcl 脚本的质量很大程度上取决于是否正确使用对象查询。十、为什么 property 是理解对象的关键对象本身只是入口真正描述对象状态的是 property。例如一个 cell 可能有ref_name is_fixed is_macro is_sequential location orientation area一个 net 可能有net_type fanout is_clock is_power route_status capacitance一个 pin 可能有direction owner net capacitance arrival transition一个 port 可能有direction net input_delay output_delay location常见查询方式包括list_property [get_cells U1] get_property [get_cells U1] ref_name report_property [get_cells U1]从工程角度看property 的价值在于它把对象从“有名字的点”变成“有状态、有类型、有上下文的数据库实体”。没有 property 查询脚本很容易停留在浅层名字操作。有了 property 查询脚本才能根据对象状态做判断。十一、name_select 与 get_select_set 的工程意义在交互式调试中工程师经常会在 GUI 或 layout window 中选中某些对象。例如选中一个 cell 选中一条 net 选中一组 timing path 上的对象 选中某个 congestion 区域附近的 objects。如果这些选择只能停留在界面上它们很难进入脚本流程。而对象选择相关命令的价值在于把人工观察到的问题对象转化为可查询、可报告、可保存的对象集合。典型思路包括name_select U1 set sel [get_select_set] report_property $sel这类机制让交互式分析和脚本化处理之间有了桥梁。也就是说工程师在界面上发现的问题不必只靠截图和口头描述而可以转化为对象集合继续分析。十二、设计对象模型如何支撑后续 Flow一旦 cell、net、pin、port 的对象模型建立起来后续很多阶段都可以统一理解。1. PlacementPlacement 操作的核心对象是 cell。但它不能只看 cell还要看cell 连接到哪些 net net 的 fanout 和 timing 重要性 pin 的物理可接入性 port / IO 的位置约束。2. Timing AnalysisTiming path 通常由 pin、net、cell arc 共同构成。如果没有 pin 和 net 的对象模型timing report 就很难和设计数据库关联。3. CTS时钟网络不是普通字符串clk。它是由 clock source、clock net、clock pin、sink pin、buffer cell 共同组成的对象网络。4. RoutingRouting 不只是“把名字相同的 net 接起来”。它必须根据 net、pin shape、routing layer、blockage、via rule 等信息生成物理连接。5. ECOECO 往往会修改 cell、net、pin 连接关系。如果对象模型不清楚很容易出现逻辑改了、物理没改或者物理改了、时序没闭合的情况。所以设计对象模型不是某个单独阶段的知识而是贯穿整个 Backend Flow 的底层结构。十三、常见错误一把 hierarchical name 当成普通名字层次化设计中对象名字可能带有 hierarchy path。例如top/u_cpu/u_alu/U123这和简单 flat name 不同。脚本中如果直接写get_cells U123可能查不到对象或者查到错误对象。更稳妥的做法是明确当前作用域是什么 是否允许 hierarchical 查询 对象名字是否唯一 是否需要 full hierarchical name。这也是为什么 current_design、current_instance、current_scope 等上下文很重要。十四、常见错误二把 collection 当成普通字符串列表很多 Backend Tcl 命令返回的是 collection 或 object list。它看起来像列表但不一定等同于普通 Tcl list。例如set cells [get_cells *]这个cells变量可能代表一组对象句柄而不只是名字列表。如果直接用普通字符串方式处理可能出现对象丢失 层次信息丢失 属性无法继续查询 后续命令输入类型不匹配。因此处理对象集合时应该优先使用工具提供的对象迭代、过滤和属性查询命令。十五、常见错误三忽略 current context很多对象查询都依赖当前上下文。例如current design current instance current scope current view current project同一条命令在不同上下文下可能返回不同结果。例如get_cells *在 top design 下它可能返回 top 层对象。在某个 hierarchical instance 下它可能返回局部对象。如果脚本没有显式控制上下文就会出现本来想查全局却只查到局部 本来想处理某个模块却误处理 top 本来以为对象为空其实是 scope 不对。所以成熟脚本应该在关键查询前明确当前上下文。十六、一个推荐的 Design Object Model Demo 目录结构如果要做一个最小可验证 demo可以这样组织LAY-BE-11_design_object_model/ ├─ data/ │ ├─ netlist/ │ │ └─ demo_top.v │ ├─ lef/ │ │ └─ demo_stdcell.lef │ └─ liberty/ │ └─ demo_stdcell.lib ├─ scripts/ │ ├─ run_object_model.csh │ └─ clean.csh ├─ tcl/ │ ├─ 01_load_library.tcl │ ├─ 02_import_and_link.tcl │ ├─ 03_query_cells.tcl │ ├─ 04_query_nets.tcl │ ├─ 05_query_pins_ports.tcl │ └─ 06_report_object_summary.tcl ├─ logs/ │ ├─ object_model.log │ ├─ object_model.cmd.log │ └─ object_model.sum.log ├─ reports/ │ ├─ cell_summary.rpt │ ├─ net_summary.rpt │ ├─ pin_summary.rpt │ ├─ port_summary.rpt │ ├─ property_summary.rpt │ └─ object_relation_summary.rpt └─ README.md这个 demo 的目标不是做 placement 或 routing而是验证设计导入后是否能查询 cell cell 是否能关联到 library master net 是否能查到连接的 pins pin 是否能查到所属 cell 和 connected net port 是否能查到 direction 和 boundary relation 对象 property 是否能被统一报告。十七、一个简化的对象查询脚本骨架下面给一个抽象示例不绑定具体商业工具。# # 03_query_cells.tcl # set rpt_dir ./reports file mkdir $rpt_dir set fp [open $rpt_dir/cell_summary.rpt w] puts $fp Cell Summary puts $fp puts $fp set cells [get_cells *] foreach_in_collection c $cells { set name [get_object_name $c] set ref [get_property $c ref_name] puts $fp [format %-40s %-20s $name $ref] } close $fp查询 net# # 04_query_nets.tcl # set fp [open $rpt_dir/net_summary.rpt w] puts $fp Net Summary puts $fp puts $fp set nets [get_nets *] foreach_in_collection n $nets { set name [get_object_name $n] set pins [get_pins -of_objects $n] puts $fp NET: $name puts $fp PINS: [sizeof_collection $pins] } close $fp查询 port# # 05_query_pins_ports.tcl # set fp [open $rpt_dir/port_summary.rpt w] puts $fp Port Summary puts $fp puts $fp set ports [get_ports *] foreach_in_collection p $ports { set name [get_object_name $p] set dir [get_property $p direction] puts $fp [format %-40s %-10s $name $dir] } close $fp真实工具中的命令名称和 collection API 可能不同但工程思想是一致的先得到对象集合 再查询对象属性 再输出结构化报告。十八、对象模型报告应该包含什么一个好的对象模型 demo不应该只打印对象名字。建议至少输出以下报告报告内容cell_summary.rptcell 名称、master、hierarchy、数量统计net_summary.rptnet 名称、fanout、driver/load 数量、net 类型pin_summary.rptpin 名称、所属 cell、connected net、directionport_summary.rptport 名称、direction、connected netproperty_summary.rpt关键对象 property 列表object_relation_summary.rptcell-net-pin-port 关系摘要这些报告可以回答非常基础但很关键的问题设计中到底有哪些对象 对象之间是否能正确关联 对象 property 是否能被读取 设计是否已经从文本输入变成可查询数据库这就是第 11 篇 demo 的核心价值。十九、设计对象模型的工程价值设计对象模型的价值可以概括为四点。1. 把文本输入变成数据库对象Backend 工具真正处理的是对象而不是原始文本。2. 把连接关系变成可查询图结构cell、net、pin、port 共同构成连接图后续分析都建立在这张图之上。3. 把流程命令变成对象操作placement、routing、timing、ECO 等命令本质上都是对设计对象及其属性的读取或修改。4. 把经验判断变成可报告证据对象 summary 和 property report 可以让问题定位从口头经验变成工程证据。二十、总结回到题目cell、net、pin、port 为什么是 Backend Flow 工程化的基本单位因为 Backend 工具真正理解设计是从对象模型开始的。其中cell 表示设计中的实例化单元 net 表示连接关系和后续物理布线对象 pin 表示 cell 与 net 的连接界面也是时序路径节点 port 表示 top-level boundary 与外部约束入口。这四类对象共同构成设计数据库的基本连接图。后续所有阶段包括 placement、timing analysis、CTS、routing、ECO、report都需要围绕这张对象图展开。所以理解 Backend Flow不能只看脚本顺序也不能只看输入文件。更关键的是理解输入文件如何变成对象 对象如何形成连接图 属性如何描述对象状态 查询如何把对象转化为报告 命令如何基于对象推进流程。当这套对象模型清楚以后Backend Flow 才从“命令堆叠”变成真正可理解、可检查、可维护的工程流程。