ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

UPF2.1电源意图实战:Hard Macro与顶层端口的低功耗SoC设计要点

UPF2.1电源意图实战:Hard Macro与顶层端口的低功耗SoC设计要点 干过几个低功耗SoC项目后我最大的感受是UPF文件写得好不好往往不在那些花哨的isolation和level shifter策略上而在最容易忽略的两个地方——Hard Macro和Top-Level Port。这两个位置一不留神后面的形式验证、IR drop分析、甚至芯片回来点不亮都会找上门。这篇文章就围绕UPF2.1把处理Hard Macro和Top-Level Port电源意图的经验和坑完整梳理一遍。1. 为什么 Hard Macro 与 Top-Level Port 让工程师最头疼1.1 Hard Macro 的“黑盒”困境Hard Macro是经过版图固化、不能再做逻辑综合和布局优化的单元常见的有SRAM、ROM、PLL、ADC、高速接口PHY、第三方DSP硬核等。这类单元最大的特点在于你在时序库.lib和行为级网表.v里能看到VDD、VSS、VDDIO这些电源引脚但库文件不会主动告诉你宏内部有几个电压域、每个域的电压值是多少、域与域之间有没有内部电源开关、有没有retention单元。麻烦就麻烦在这里。UPF描述的是“电源意图”也就是你希望设计怎么供电、怎么断电、怎么保持但Hard Macro偏偏是一个已经固定死了的物理实现它内部的电源架构不会因为你外部UPF怎么写而改变。如果你把它当成普通标准单元随便连物理实现阶段很容易出现电源网络短路、supply net悬空如果你干脆不描述它功耗分析阶段又会漏掉宏单元的动态功耗和漏电功耗跑出来的结果跟实测能差出百分之二三十。我见过不少团队在Hard Macro上偷懒直接在顶层UPF里写一句connect_supply_net VDD -ports {mem0/VDD}就完事结果后端跑到电源完整性分析时发现SRAM宏内部还有独立的array电压和外围逻辑电压两个电压域根本没有在PSTPower State Table里表达带时序的功耗仿真直接挂掉。这类问题越晚发现越难改等到后端已经做完floorplan再回头补UPF代价往往是重新走一遍功耗验收流程。1.2 Top-Level Port 处于层级边界的特殊地位Top-Level Port是芯片与外部世界的接口电源意图在它身上的麻烦程度一点都不比Hard Macro低。核心问题在于端口名、端口方向、电压值必须同时被RTL、UPF、SDC物理约束、封装定义四套数据认可而这四套数据往往由不同的人维护。举个我实际遇到过的例子。RTL顶层有个端口叫VDD33库文件里的电源pad引脚叫vdd33_pad后端PDN里建的net叫VDD_3.3V封装工程师手里ball map上写的又是V33。四套名字互相不认UPF里create_supply_port VDD33之后后端工具找半天找不到对应的物理端口最后只能靠人工一一映射。这种问题在小型设计里还好在大型SoC里电源pad往往有几十上百个再加上功能端口横跨多个电压域只要命名或者上下层级映射错一处整个电源意图就断了一条链。Top-Level Port的另一重麻烦在于它不只是电源地pad还包括那些同时作为多个电源域输入输出的功能端口。比如芯片外面进来一个1.8V逻辑信号要送给内核1.8V域但同一根信号线还可能经过IO ring的3.3V域做输入保护。这种端口的电源意图需要明确告诉工具它属于哪个域、它的电压转换边界在哪里否则综合工具在优化时不知道该参考哪个供电电压后端做level shifter插入的时候也不知道该往哪个方向加。1.3 UPF2.1 相比老版本带来的关键改进UPF2.1对应IEEE Std 1801-2015标准相比早期UPF1.0和UPF2.0最大的进步是几个容易被忽视的能力。首先是supply set的抽象能力。UPF2.1允许你定义一组电源网络包括primary power、primary ground、备份电源、降级电源等为一个整体然后用这个整体去关联一个电源域或者一组端口。这个概念在处理Hard Macro和Top-Level Port时非常有用因为宏单元和顶层端口经常要表达“这一组引脚用的是同一个供电组合”而不是孤立地去描述某一根net的电压是多少。其次是Power State Table的描述能力增强。UPF2.1可以更精确地定义多个supply set在不同电压组合下的状态比如OFF、RETENTION、ACTIVE、IDLE并且支持多档电压的连续取值。这让Hard Macro内部多电压域的关系表达变得更贴近真实硬件。还有一个容易被忽略的点UPF2.1对externalsupply port的建模更友好允许你把顶层端口声明成芯片外部的供电来源并且通过create_power_domain和create_supply_port的组合来描述外部电源如何进入内部网络。这在老版本里经常要依靠工具私有的写法兼容性差换工具就得改一遍。2. Hard Macro 电源意图处理的“正确姿势”2.1 先给宏单元分类再决定处理策略拿到一个Hard Macro第一件事不是写UPF而是先去查它的资料包。我习惯先做一次分类不同类型的宏处理难度和策略完全不同。宏单元类型典型示例是否自带UPF模型处理难度推荐策略内存类SRAM、ROM、Register File有时附带UPF仿真模型中等外部建域连接VDD/VSS内部多电压用PST补充表达模拟类PLL、ADC、DAC、LDO通常不带UPF较高手动建模区分模拟电源和数字电源注意AGND处理高速接口PHYUSB PHY、PCIe PHY、SerDes自带UPF的概率低较高参考数据手册单独建域注意模拟域和数字域隔离内部复用硬核自家上一代芯片的模块大概率保留原UPF低核对命名映射必要时做supply net重命名分类之后你基本就知道这个宏是“可以直接连电源网络”还是要“额外写一段UPF stub模型”或者是“需要在宏外面包一层壳域把内部电源网络和外部隔离”。2.2 基础操作创建电源域与电源端口/网络以最常见的单电压域SRAM宏为例标准做法是先给宏单独建一个电源域再在该域下创建对应的供电端口和供电网络。create_power_domain PD_MEM0 -elements {mem0} create_supply_port VDD_MEM0 -domain PD_MEM0 -direction inout create_supply_net VDD_MEM0_NET -domain PD_MEM0 -reuse connect_supply_net VDD_MEM0_NET -ports {mem0/VDD} connect_supply_net VDD_MEM0_NET -ports {VDD_MEM0} create_supply_net VSS_NET -domain PD_MEM0 -reuse connect_supply_net VSS_NET -ports {mem0/VSS}这段代码里有几个细节值得说清楚。create_supply_port里的-direction inout是给外部接入口用的表示这个端口既可以受外部供电也可以向外供电大多数外部电源pad用inout不会错但如果这个电源只用于内部宏、不期望对外供电用-direction input更严谨。create_supply_net后面的-reuse的作用是如果该net已经存在于更高层级就直接复用而不是重复创建。这个参数在处理宏单元时尤其重要因为宏的VSS通常就是全局地不需要在宏域里重新造一根地线直接复用顶层的VSS_NET即可。2.3 闭合电源引脚连接connect_supply_net 的细节connect_supply_net是UPF里最常用也最容易被用错的命令。很多初学者以为它只是把两个名字连起来实际上它有明确的语义把supply net和端口、引脚、或者下一级网络进行电气连接。关键参数有三个-ports、-elements、-cell。-ports连接具体的端口或宏引脚-elements连接指定的module实例-cell用于把某个标准单元类型的全部电源引脚都连上。实际项目中连接宏单元引脚时有个常见错误直接写connect_supply_net VDD -ports {mem0/VDD}但如果宏的库模型里VDD引脚方向被定义为inout而UPF net同时连接了多个源工具会报multiple driver错误。处理办法是在宏外围再建一个内部net先连到VDD_MEM0_NET再通过-elements把宏实例挂到域上。create_supply_net VDD_MEM0_INT -domain PD_MEM0 connect_supply_net VDD_MEM0_INT -ports {mem0/VDD} connect_supply_net VDD_MEM0_NET -ports {VDD_MEM0_INT}我的经验是宏单元电源连接一定要养成“内外分离”的习惯外部网络统一走域级net内部引脚连接统一走宏内部net中间用connect_supply_net显式对接。这样后期做ECO或者换宏版本的时候只需要改一小段连接不用满世界找哪里引用了mem0/VDD。2.4 处理宏单元内部多电压域的特殊情况真正难的是宏单元内部有多个电压域。拿某个常见的SRAM Compiler生成的高密度SRAM举例外部有VDD逻辑电压和VDDM阵列电压两个电压在正常工作模式下可能都是0.8V但在低功耗模式下VDDM可以降到0.6V而VDD必须保持0.8V否则retention数据会丢。这种情况下如果只在宏外面建一个PD_SRAM把VDD和VDDM都连进去PST里就没有它们电压差异的信息后续做动态电压仿真时工具会认为两个net电压始终相同IR drop分析也会把VDDM的压降算成跟VDD一样结果明显偏乐观。正确的做法是给宏建两个电源域create_power_domain PD_SRAM_LOGIC -elements {mem0} create_power_domain PD_SRAM_ARRAY -elements {mem0} create_supply_net VDD_SRAM_LOGIC -domain PD_SRAM_LOGIC create_supply_net VDD_SRAM_ARRAY -domain PD_SRAM_ARRAY connect_supply_net VDD_SRAM_LOGIC -ports {mem0/VDD} connect_supply_net VDD_SRAM_ARRAY -ports {mem0/VDDM} set_domain_supply_net PD_SRAM_LOGIC -primary_power_net VDD_SRAM_LOGIC -primary_ground_net VSS_NET set_domain_supply_net PD_SRAM_ARRAY -primary_power_net VDD_SRAM_ARRAY -primary_ground_net VSS_NET注意两个power domain的-elements都是mem0本身这并不冲突因为UPF允许一个instance被多个domain引用只是需要在PST里定义清楚两个domains的供电状态组合。还有一种更极端的情况宏内部集成了LDO或者DC-DC核心电压在内部产生外部只输入一个较高的电压。比如某个USB2.0 PHY外部供电1.8V内部通过regulator生成1.0V逻辑电压。从UPF的角度看内部逻辑电压根本不存在于外部netlist的物理端口上但它真实存在且会影响功耗和时序分析。我的处理办法是在宏外面建一个“虚拟电源域”给它配一个虚拟的supply net然后通过create_supply_set把外部1.8V和内部1.0V的关系用PST描述出来。这样做不只是为了满足工具检查更重要的是在功耗分析时工具能把内部林林总总的漏电功率分配到一个真实的供电来源上否则IR drop分析里PHY内部就是空白一片。3. Top-Level Port 的电源意图建模3.1 从 top-level supply port 说起顶层端口处理的第一步是把芯片真正的供电入口声明出来。以一颗小型SoC为例外部通常有3.3V IO电源、1.8V模拟电源、0.8V核心电压和系统地在UPF里要分别建port和netcreate_supply_port VDD33_EXT -direction inout create_supply_port VDD18_EXT -direction inout create_supply_port VDD08_EXT -direction inout create_supply_port VSS_EXT -direction inout create_supply_net VDD33 -domain PD_TOP -reuse create_supply_net VDD18 -domain PD_TOP -reuse create_supply_net VDD08 -domain PD_TOP -reuse create_supply_net VSS -domain PD_TOP -reuse connect_supply_net VDD33 -ports {VDD33_EXT} connect_supply_net VDD18 -ports {VDD18_EXT} connect_supply_net VDD08 -ports {VDD08_EXT} connect_supply_net VSS -ports {VSS_EXT}这段代码看起来简单但我建议你养成一个习惯为每个外部电源端口加一个独立的supply port而不要把多个supply net直接对接在一个port上否则物理实现时同一块metal必须同时承载多个电压域的电流EM电迁移计算会非常痛苦。还有一个细节do not直接在顶层UPF里create_supply_net VDD33然后马上用connect_supply_net VDD33 -ports {VDD33_EXT}连接顶层port。你需要先确认VDD33这个net是不是已经在某个子模块里创建过如果有子模块升级后自己建了一根同名net顶层的连接就会变成平行世界里两堵墙谁也没连上谁。3.2 端口在多个电源域之间的“跨域”表达功能端口横跨多个电源域是常见需求尤其是有IO ring的设计。一个3.3V引脚输入信号经过IO cell内部的电平转换进入1.8V逻辑域再送到核心逻辑。这个端口从UPF角度看属于“跨域端口”需要在isolation和level shifter策略上明确处理。在UPF2.1里处理这类端口的第一步是告诉工具这个端口的供电来源。不同EDA工具给这个操作起了不同名字有的叫set_port_attributes有的叫set_related_supply_net核心思路是相同的把端口和它所在供电域绑定。set_port_attributes -ports {pad_in[31:0]} -related_power_net VDD33 -related_ground_net VSS set_port_attributes -ports {core_in[31:0]} -related_power_net VDD08 -related_ground_net VSS做完这一步工具在综合和物理实现时就能推断pad_in进来的信号是3.3V逻辑进入内核之前需要加level shifter。如果不写这个属性工具只能默认端口电压和它驱动的逻辑域一致插入level shifter的时候就会漏掉3.3V到0.8V的转换芯片实测时IO口直接烧逻辑。对于真正的双向端口或者同时被多个供电域驱动的端口我建议你在UPF里用一个辅助域去表达它然后再通过supply set描述它和两个真实域的关系不要试图在同一个port上绑两个related power net很多工具不支持这种写法。3.3 用 Power State Table 描述端口电压状态Power State TablePST是UPF2.1里表达多电压状态的核心工具。它的作用是声明整个设计在正常模式、睡眠模式、关断模式下各个supply set的电压值是什么。对于Top-Level Port来说PST还有个隐形作用它决定了外部系统比如板级PMIC需要给芯片供哪几个电压档位。看一个简化例子create_supply_set ss_vdd33 -function {power VDD33} create_supply_set ss_vdd18 -function {power VDD18} create_supply_set ss_vdd08 -function {power VDD08} create_supply_set ss_vss -function {ground VSS} add_power_state PS_ACTIVE -supply_expr {ss_vdd33 3.3 ss_vdd18 1.8 ss_vdd08 0.8} add_power_state PS_SLEEP -supply_expr {ss_vdd33 3.3 ss_vdd18 1.8 ss_vdd08 0.6} add_power_state PS_OFF -supply_expr {ss_vdd33 3.3 ss_vdd18 1.8 ss_vdd08 0} create_pst pst_top -supplies {ss_vdd33 ss_vdd18 ss_vdd08 ss_vss} add_pst_state ACTIVE -pst pst_top -state PS_ACTIVE add_pst_state SLEEP -pst pst_top -state PS_SLEEP add_pst_state OFF -pst pst_top -state PS_OFF在写PST时有几个易错点。一是所有supply set的电压值必须与库里的工作电压一致比如定义VDD08在ACTIVE是0.8V但标准单元库里对应电压档是0.75V工具做电压域一致性检查的时候会直接报错。二是PST里的状态名不要随意起要跟项目里功耗状态文档通常是PCS/PCG文档保持一致否则后端做动态电源分析时状态覆盖率统计会跟系统级模型对不上。另外我强烈建议你为每个顶层端口建立一个“端口电压状态表”这个表不完全是PST更像是一个跨团队的对齐文档。我通常用CSV维护格式大致是端口名、端口方向、在ACTIVE状态的电压、在SLEEP状态的电压、在OFF状态的电压、关联supply set、所属电源域。每次UPF评审时第一件事就是拿这个表跟PST逐行对照。3.4 顶层端口与芯片封装/PAD 的对齐问题顶层端口最终要落到物理PAD上而PAD的供电和连接方式与普通逻辑节点不同。PAD cell本身有模拟电路ESD保护结构、驱动管、施密特触发器它的电源引脚往往和普通逻辑单元一样需要连接到域级supply net但问题在于PAD cell的库模型比较复杂一个PAD cell里往往同时包含输入、输出、电源钳位、地钳位几部分电源引脚可能超过两个。为此UPF里需要明确一个处理原则PAD cell的供电引脚必须与它所在的IO电源域一致。如果某个PAD同时支持3.3V和1.8V两种电平而这个PAD又配了内部LDO做电平转换那你需要像处理Hard Macro内部电压域一样给PAD建一个独立域再把外部voltage source和内部LDO输出域在PST里表达出来。还有一个对齐问题是顶层端口名和物理库端口名的映射。RTL里叫VDD18物理库里对应PAD叫VDDPST18_0UPF里需要显式做一次映射connect_supply_net VDD18 -ports {VDDPST18_0/A VDDPST18_1/A}我踩过最深的坑是顶层有12个同电压PAD我在UPF里只连了第一个其他11个PAD靠工具自动匹配结果工具把剩下11个PAD默认接到了VSS上做LVS的时候爆出一堆电源短路错误。现在我的原则是所有外部电源PAD连接全部显式写出来一两百个端口虽然多但可以用脚本根据命名规则自动生成坚决不依赖工具的隐式匹配。4. 实战一个 12nm 项目中的 UPF2.1 处理流程4.1 三层芯片的 UPF 文件架构讲一个真实项目的UPF组织方式。芯片是三层的顶层TOP中间是数字逻辑DIGITAL底层挂着几个大宏包括2个SRAM、1个PLL、1个USB PHY。外部供电4组3.3V IO、1.8V模拟、0.8V核心、系统地。我习惯把UPF文件拆成4个top.upf定义外部supply port、顶层net、PST、全局isolation和level shifter策略。digital.upf数字逻辑域的电源树、时钟domain相关的电源策略。macro_sram.upf、macro_pll.upf、macro_usbphy.upf各自宏单元的电源模型和内部supply net连接。check.upf只包含检查脚本不写任何创建类命令用report_power_domain、report_supply_net、check_power_domain做最终验证。这个拆分方式的优点在于每个宏单元的UPF文件可以被单独复用。换一颗SRAM时只需要替换macro_sram.upf其他文件基本不用动。另外宏单元UPF由IP集成工程师维护顶层UPF由芯片leader维护边界清晰不会互相覆盖。4.2 自底向上处理 Hard Macro真实步骤自底向上的含义是先把每个宏单元自己的UPF写完再在父级把它们挂到顶层电源网络上。这样做的好处是宏单元的电源模型可以被验证、被复用而不是混在父级里一堆-elements连来连去。第一步拿到宏的资料后先写一个最简可用模型create_power_domain PD_USBPHY_DIG -elements {usbphy0} create_supply_net VDD18_PHY -domain PD_USBPHY_DIG create_supply_net VDD08_PHY -domain PD_USBPHY_DIG create_supply_net VSS_PHY -domain PD_USBPHY_DIG set_domain_supply_net PD_USBPHY_DIG -primary_power_net VDD08_PHY -primary_ground_net VSS_PHY第二步从.lib里提取pg_pin定义确认宏的电源引脚名称。这一步不能偷懒因为不同IP供应商的叫法差异很大同一个宏里VDD可能叫VDDC、VDDE、VDDIO好几个名字。第三步把宏的内部net和外部net连接起来connect_supply_net VDD08_PHY -ports {usbphy0/VDDC} connect_supply_net VDD18_PHY -ports {usbphy0/VDDE} connect_supply_net VSS_PHY -ports {usbphy0/VSS}第四步在父级digital.upf里把宏实现为子域的子域create_power_domain PD_DIGITAL -elements {.*} create_power_domain PD_USBPHY -elements {usbphy0} create_supply_net VDD08 -domain PD_DIGITAL connect_supply_net VDD08 -ports {PD_USBPHY/VDD08_PHY}这里的PD_USBPHY/VDD08_PHY意味着把子域内部net提升到父级。这种写法比直接在父级connect_supply_net VDD08 -ports {usbphy0/VDDC}更清晰后期工具在做供电域边界分析时也能正确识别宏是一个独立的供电域。处理Hard Macro时我还会在宏外围加一个边界策略块专门声明iso和level shifter的插入位置。虽然不是每个宏都需要但多写这一层可以避免后端工具“自作主张”把宏内部的逻辑和外部逻辑直接优化到一起破坏宏的物理边界。4.3 自顶向下处理 Top-Level Port真实步骤自顶向下的含义是先在顶层把所有外部端口和供电关系定死再让下层UPF遵循这个框架。第一步在top.upf里声明全部外部接口create_supply_port VDD33_EXT -direction inout create_supply_port VDD18_EXT -direction inout create_supply_port VDD08_EXT -direction inout create_supply_port VSS_EXT -direction inout create_supply_net VDD33 -domain PD_TOP -reuse create_supply_net VDD18 -domain PD_TOP -reuse create_supply_net VDD08 -domain PD_TOP -reuse create_supply_net VSS -domain PD_TOP -reuse第二步为每个外部功能端口设置供电关系set_port_attributes -ports {gpio_spi[0]} -related_power_net VDD33 -related_ground_net VSS set_port_attributes -ports {core_clk_in} -related_power_net VDD08 -related_ground_net VSS第三步建立PST并核对端口关系。这里有个我习以为常的检查流程把PST导出成文本再和芯片规格书里的power mode对照确保每个状态下所有端口都有明确的电压说明。第四步把顶层UPF和物理实现工具对接。这一步最容易被忽略——你在逻辑综合阶段写的UPF跟后端PR工具读入的UPF必须是同一个文件否则前端验证全部白做。实际操作中我会在顶层UPF末尾加一段“enforce”性质的约束比如set_voltage -object_list VDD08_EXT 0.8这样后端起跑时如果发现物理库电压档位和UPF不一致会直接报错而不是静默处理。4.4 一致性检查至少跑三遍UPF写出之后一致性检查绝不能省。我至少会跑三遍遍遍目的不同。第一遍是“语法和结构检查”。用工具自带的UPF parser跑check_power_domain确认supply net连接没有悬空、port定义没有重复、PST状态没有缺项。这一遍通常在写完UPF当天就做问题基本是命名拼写和括号不匹配。第二遍是“逻辑一致性检查”。这一步在综合后做工具会把UPF描述和综合后的netlist做比对确认每个instance的电源引脚都连上了、每个power domain的边界都正确。常见的报错是“supply net not found in design”通常原因是UPF里写了某个net但实际netlist里不存在这个名字。第三遍是“物理一致性检查”。在floorplan完成之后用物理实现工具读取UPF检查供电网络路由结果和UPF里的连接关系是否一致。这一步经常暴露出顶层端口方向问题和PAD对齐问题。我见过不少项目前面两遍检查都过了偏偏挂在第三遍。原因多半是顶层UPF里建了一根VDD18但物理库里的PAD引脚叫VDDPST18大小写都不同后端工具在匹配时默认不连。所以我的原则是物理一致性检查之前先写一个小脚本把顶层UPF里的所有supply port和物理库里所有pg pin列出来做交集比对提前把不一致项清掉。5. 常见问题与排查技巧实录5.1 问题速查表问题现象根本原因排查办法解决方案UPF报supply net not foundnet名与netlist中不一致report_supply_net对比统一命名规范或使用create_supply_net -reuse宏单元电源引脚连不上库模型中pg_pin名称与UPF写法不同查看.lib中pg_pin定义按库名称修正UPF端口名顶层端口电压和package不一致封装ball map与UPF端口定义脱节对照ball map表格维护端口电压对照表定期评审PST被工具忽略工具版本仅支持UPF2.0不识别部分2.1语法检查工具的支持版本升级工具或改用-pst兼容写法多层级UPF中supply net重名子模块UPF各自定义同层netreport_supply_net检查层级子模块net统一加前缀或使用域隔离端口ISO策略失效端口没有绑定related supply net检查set_port_attributes为所有跨域端口显式绑定供电关系这张表不是从帮助文档里抄的是从项目里一条条报错信息提炼出来的。尤其是最后一条“端口ISO策略失效”往往不是isolation cell选型问题而是端口根本没有和supply net绑定工具不知道它属于哪个域自然插不了ISO逻辑。5.2 排查方法从报错信息到根因分析排查UPF问题我习惯顺着报错信息往上游走。报错信息只能告诉你“哪里不对”不能告诉你“为什么不对”。我分享一个典型的排查路径。当工具报出supply net VDD08_PHY is not connected to any driver时不要急着去补connect_supply_net先回答三个问题这个net是顶层net还是宏内部net它应该由谁驱动如果它是一个中间net是不是还缺一层连接我的做法是打开宏的库文件搜pg_pin定义看它有没有把VDD08_PHY声明成输出电源引脚。很多宏的电源引脚默认不带driver属性因为宏内部电源由外部供电输入驱动宏的输出电源引脚在物理上只是电气连接点。此时你需要检查是否需要在该引脚上加-pg_type primary_power等属性。另一个常见问题的原因是UPF加载顺序。子模块的UPF和顶层UPF有依赖关系时如果先后顺序错了比如先加载顶层UPF、后面才加载子模块UPF工具在处理顶层里的connect_supply_net VDD08 -ports {PD_USBPHY/VDD08_PHY}时会发现PD_USBPHY还不存在直接报错。解决方案是把create_power_domain和后续引用操作分开到不同命令集里或者用UPF解析器的增量加载功能。5.3 我的几条独家避坑经验第一命名规范必须上升到“设计纪律”。我在项目启动时就会定一份电源命名规范明确顶层端口必须全大写、内部net用小写加模块前缀、宏内部net必须带宏名缩写。这个规范看起来简单但一份命名混乱的UPF会让所有下游工具链反复报错浪费的时间足够买一百个Licence。第二不要手改工具自动生成的UPF。综合工具或验证平台有时候会输出一份“净化的UPF”这份文件里会夹带很多内部生成的对象。你手改一行下次回归时就会跟自动生成版本冲突。我建议把自动生成文件和手工维护文件分目录存放两套文件通过脚本来做差异合并而不是直接改。第三在Hard Macro外面包一层“壳域”是我见过最能降低后期返工率的习惯。壳域的意思是宏单元本身建一个power domain然后在宏外面再建一个空壳的domain宏的域挂在这个壳域下。这样当你需要做电源域边界优化、IR drop分析或者给宏做电源开关时有壳域做缓冲不用动宏本身的UPF也不会影响宏IP的复用。第四每个阶段都要保留一个“供电快照”。我习惯在综合前、综合后、floorplan后、CTS后分别保存一份report_power_domain和report_supply_net的完整输出连同UPF文件一起提交到版本库。这样一旦后期出现问题可以快速定位是哪个阶段开始失配的而不是从头开始比对上千行UPF。第五如果项目允许尽量在顶层端口和宏端口上都加上“电源说明注释”。UPF支持#注释我会在每个supply port定义处写上它的电压来源、去向、对应库里的pg_pin名。这些注释不消耗任何芯片面积但能让接手的人少走很多弯路。回过头来处理Hard Macro和Top-Level Port的电源意图本质上就是在处理“信息茧房”问题。宏单元内部是一个信息孤岛顶层端口是芯片外部和内部的边界两个位置都需要你把零散的库文件、RTL端口定义、物理库信息整合成一个清晰、机器可读、团队可维护的供电模型。UPF2.1给了我们足够的命令和表达能力真正拉开距离的是是否愿意把每一个命名、每一层连接、每一个PST状态都当作严肃的工程产物来对待。
返回列表