作者Darren H. Chen方向Backend Flow / 后端实现流程 / EDA 工具工程 / Tcl 脚本工程demoLAY-BE-12_collection_property_filter标签Backend Flow、EDA、Tcl、Collection、Property、Filter、Design Object Model、后端实现在前面的文章里我们已经讨论了一个基础问题Backend 工具真正理解设计之后内部看到的不是 Verilog 文本而是一组可被查询、可被筛选、可被操作的设计对象。这些对象包括cell net pin port module clock site row shape violation property但是仅仅知道有这些对象还不够。真正进入工程阶段后最关键的问题会变成如何从几十万、几百万甚至上千万个对象中稳定地找到你要处理的那一小部分这就引出了 Backend Tcl 脚本里最重要的三类能力Collection Property Filter它们看起来只是对象查询接口的一部分但从底层架构看它们决定的是工具数据库如何把“海量设计对象”转化成“可控工程操作集合”。本文不讨论某个具体命令怎么背而是从系统模型角度讲清楚为什么 Collection / Property / Filter 是 Backend 脚本工程的核心能力。一、对象查询为什么不能只靠名字匹配很多人最开始写 Tcl 脚本时会习惯这样想我要找某个 cell就按名字找 我要找某个 net就按名字找 我要找某个 pin就按名字找。例如get_cells U123 get_nets clk get_pins U123/A这当然是必要能力但远远不够。因为真实设计中很多工程问题不是“找一个名字”而是“找一类对象”。例如找所有未放置的 cell 找所有 fixed macro 找所有 clock net 找所有 high fanout net 找所有属于某个 hierarchy 的 instance 找所有没有物理 shape 的 pin 找所有 timing critical path 上的 cell 找所有 power/ground port 找所有某个 property 满足条件的对象。这类问题如果只靠名字匹配会很快失控。因为名字只是对象的一种外部标识而 Backend 工程真正关心的是对象的状态、属性、关系和上下文。所以Backend Tcl 查询的核心不是字符串处理而是在设计数据库中构造对象集合并在集合上进行属性判断和关系筛选。二、Collection 是什么可以把 Collection 理解成一组被工具数据库识别的对象引用。它不是普通字符串列表。普通字符串列表只是文本U1 U2 U3而 Collection 背后通常对应数据库对象cell object handle net object handle pin object handle port object handle这意味着 Collection 至少有三个重要特点。1. 它有对象类型一个 Collection 可能是cell collection net collection pin collection port collection shape collection violation collection不同类型的 Collection 能被不同命令消费。2. 它有数据库身份对象不只是名字。一个 cell 的名字可能显示为U123但在工具内部它还可能有object id hierarchical path master cell location orientation fixed status physical status propertiesCollection 保存的是对象引用而不只是名字文本。3. 它可以继续被操作Collection 的价值不在于“查出来”而在于它可以继续作为后续命令的输入。查询对象 ↓ 筛选对象 ↓ 读取属性 ↓ 生成报告 ↓ 修改状态 ↓ 再次查询这就是 Backend Tcl 脚本和普通文本脚本的根本差异。三、Property 是什么如果 Collection 回答的是有哪些对象那么 Property 回答的是这些对象是什么状态一个 cell 可能有属性name ref_name is_fixed is_placed location orientation area is_macro is_sequential is_clock_cell dont_touch一个 net 可能有属性name usage fanout is_clock is_power is_ground total_capacitance driver loads一个 pin 可能有属性name direction net cell is_clock_pin capacitance location layerProperty 是对象模型的可观测层。没有 PropertyCollection 只是一堆对象。有了 Property脚本才知道这些对象有什么差异哪些该被处理哪些不该被处理。四、Filter 是什么Filter 可以理解成基于对象属性和关系条件对 Collection 进行选择。例如从所有 cell 中筛出 macro 从所有 net 中筛出 clock net 从所有 pin 中筛出 input pin 从所有 cell 中筛出未放置对象 从所有 object 中筛出某个 property 为 true 的对象。Filter 的本质是谓词判断对象是否满足某个条件用系统模型表示FilteredCollection Filter(Collection, Predicate(Property, Relation, Context))也就是说输入一组对象 条件属性 / 关系 / 上下文判断 输出一组更小、更准确的对象这就是 Collection / Property / Filter 的完整闭环。五、对象查询流水线Backend 脚本中的对象查询通常不是单条命令而是一条流水线。Design Databaseget_* 查询对象Collectionget_property / list_propertyFilter PredicateFiltered CollectionReport / Check / Modify这条流水线的核心思想是先得到对象集合 再观察对象属性 再根据条件筛选 最后执行报告、检查或状态修改。所以一个成熟的 Backend 脚本不应该是大量硬编码名字堆起来的文本而应该是对象查询 属性判断 集合变换 阶段动作六、为什么对象查询能力决定脚本工程上限因为 Backend 工程问题的规模通常不是单点问题。它处理的是大规模对象集合。例如不是改一个 cell而是处理某类 cell 不是查一个 net而是查一批 high fanout net 不是看一个 pin而是看某类 pin 的物理可达性 不是读一条 timing path而是分析一组 critical path 的共性。如果查询能力弱脚本就只能写成手工列名字 手工改路径 手工判断类型 手工排除例外 手工生成局部报告这种脚本短期能用但很难维护。相反如果 Collection / Property / Filter 能力强脚本可以变成根据对象状态构造处理集合 根据属性决定处理策略 根据报告反馈更新筛选条件 根据阶段上下文控制命令边界。这里说的不是让工具替代工程师判断而是让脚本从“文本拼接”升级为“数据库对象操作”。这就是脚本工程上限的来源。七、名字、对象和属性三者不能混淆Backend Tcl 中最常见的错误之一就是把名字、对象和属性混在一起。概念本质示例风险name文本标识U123可能重名、转义、层次路径变化object数据库对象cell handle依赖当前 session 和数据库状态property对象状态is_fixed需要对象类型和上下文支持例如set cells [get_cells *]这里cells不应该简单理解成字符串列表而应该理解成 cell 对象集合。再比如get_property $cells ref_name这里读取的是对象属性而不是从名字中解析字符串。一旦把对象当字符串处理很多脚本就会出现隐性问题hierarchy 分隔符处理错误 bus name 转义错误 对象已经不存在但名字仍在 名字匹配过宽或过窄 同名对象在不同 scope 下混淆。所以Backend 脚本的第一原则是能用对象集合解决的问题不要退回到纯字符串处理。八、Filter 的底层思想把经验变成条件工程师的经验通常是这样表达的这些 macro 不要动 clock net 不应该当普通 signal net 处理 fixed cell 不能随便移动 critical path 上的 cell 要重点看 power/ground net 不参与普通信号逻辑判断 hierarchy A 下面的对象要单独报告。这些经验如果停留在脑子里只能靠人操作。如果写进脚本就要变成 filter 条件is_macro true usage clock is_fixed true slack threshold usage power || usage ground full_name matches hierarchy patternFilter 的真正价值是把工程经验转换成可执行的对象选择条件。一个团队对 Flow 的理解越深入往往不是脚本越长而是 filter 条件越清楚、越可解释。九、为什么 list_property 很重要很多人只知道get_property却忽略list_property。但从工程角度看list_property很关键。因为它回答的是某类对象到底有哪些可观察状态如果不知道有哪些 property就无法写出稳定 filter。例如你想筛选 fixed object但不知道工具里属性叫is_fixed fixed place_status status这时就不能靠猜。正确方式是先查询对象 再列出属性 再确认属性语义 最后写 filter。十、空集合意识与类型意识对象查询要区分三种状态命令失败 命令成功但集合为空 命令成功且集合非空。这三个状态不能混在一起。例如设计中没有 macro 时查询 macro collection 为空这不应该被当作错误。但如果get_cells命令本身失败那就是另一类问题。同时不同对象类型的属性不同cell 有 ref_name net 有 fanout pin 有 direction port 有 input/output shape 有 layer violation 有 rule_name。所以一个可靠脚本必须在关键入口检查对象类型避免对 net 读取 cell 属性对 pin 读取 net 属性。十一、对象关系比单个对象更重要Backend 设计数据库不是一堆孤立对象而是一张关系图。典型关系包括cell owns pin pin connects net net connects driver/load pins cell instantiates lib cell pin belongs to port or instance object has physical location object belongs to hierarchy clock traverses timing graph所以Collection / Property / Filter 的高级用法不只是筛对象而是沿关系图走。例如从 critical path 找 cell 从 cell 找 input/output pins 从 pin 找 net 从 net 找 fanout 从 fanout 找 downstream cell 从 cell 找 placement location。这时脚本处理的就不再是平面集合而是对象关系网络。十二、一个推荐的对象查询分层为了让脚本可维护可以把对象查询分为四层。基础查询层 属性封装层 过滤条件层 业务动作层1. 基础查询层负责调用工具原生命令get_cells get_nets get_pins get_ports2. 属性封装层负责统一读取属性get_object_name get_object_type get_object_property3. 过滤条件层负责定义选择规则is_macro_cell is_clock_net is_fixed_object is_io_port4. 业务动作层负责真正做报告或检查report_macro_summary check_unplaced_cells report_clock_net_summary这种分层可以避免脚本到处散落复杂 filter。十三、一个简化的对象查询模板下面是一个抽象模板不绑定具体工具语法。set all_cells [get_cells *] set all_nets [get_nets *] set all_ports [get_ports *] list_property $all_cells list_property $all_nets list_property $all_ports foreach_in_collection cell $all_cells { set name [get_property $cell name] set ref [get_property $cell ref_name] puts CELL $name REF $ref } set macro_cells [filter_collection $all_cells is_macro true] if {[sizeof_collection $macro_cells] 0} { puts No macro cells found. Skip macro report. } else { report_property $macro_cells }这个模板的重点不是具体命令名而是流程查询 观察 筛选 检查空集合 再执行动作十四、Demo 应该验证什么本篇对应的 demo 不需要做完整后端流程。它应该验证对象查询机制本身是否能读取 cell/net/pin/port 是否能列出 property 是否能对对象读取关键属性 是否能处理空集合 是否能输出对象关系报告 是否能把查询结果写入 report。建议输出object_inventory.rpt cell_property_summary.rpt net_property_summary.rpt pin_property_summary.rpt filter_result_summary.rpt empty_collection_check.rptDemo 的重点不是做 placement而是验证对象查询层是否可靠。十五、总结Collection 让脚本可以操作对象集合。Property 让脚本可以观察对象状态。Filter 让脚本可以把工程经验转换成对象选择条件。三者组合起来才形成真正可靠的对象查询能力。它们解决的是从海量设计对象中稳定、可解释、可复查地找到目标对象。一个 Backend Flow 能不能长期维护往往不取决于命令写得多不多而取决于对象查询层是否清楚、稳定、可扩展。结尾一句话Backend 脚本真正成熟的标志不是能执行很多命令而是能准确回答我正在操作哪些对象为什么是这些对象它们的状态是什么结果能不能被复查Collection / Property / Filter就是回答这些问题的基础。