ARTICLE DETAIL

资讯详情

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

Cadence门级数模混仿SDF反标全流程与排错

Cadence门级数模混仿SDF反标全流程与排错 门级数模混仿这件事最磨人的往往不是写激励而是SDF反标那一步。日志里刷出几百行 warning仿真跑起来数字侧却像没延时一样模拟侧又被拖得几乎不动一个晚上就这么过去了。我在cadence这套流程里前前后后交了不少学费从SDF 2.1和3.0的格式差异到AMS Designer里连接模块的选型再到反标日志里那些看不懂的Failed to find基本每一样都踩过。这篇就把在cadence中进行SDF文件的反标并进行数模混仿整条链路拆开讲反标到底在反什么、需要提前备好哪些文件、命令怎么下、日志怎么读、混合信号接口怎么连、跑不动的时候先从哪查。内容偏向门级网表加模拟块的混仿场景无论你是刚接手一个带数字后端的混合信号模块还是已经在调时序却总对不上数都能直接拿去用。1. 先搞清楚SDF反标到底在干什么1.1 从RTL到门级时序信息为什么要回填RTL级的仿真里数字逻辑是理想化的信号从输入端到输出端仿真时间轴上一分一秒都不花顶多是零延时或者加个单位延时。这在功能验证阶段完全够用但一旦进入门级尤其是要和模拟电路放在一起跑这个假设就崩了。门级网表描述的是标准单元和它们之间的连线网表本身只告诉你谁连谁不告诉你信号在这条路上走多久。真正的延时数据来自综合工具或静态时序分析工具它们根据工艺库里的单元延时表、输出负载、输入转换时间算出一堆数值最后导成一份文本文件就是SDFStandard Delay Format。反标annotation这个动作说白了就是把SDF里的延时数值按层次路径塞回门级网表的每一个单元、每一条连线上。做完之后仿真器算的不再是理想传播而是带着真实门延时和线延时的波形。我个人的体会是只要你的数字部分要和模拟块交互而且交互涉及时序窗口——比如DAC的建立时间、ADC采样沿和数字控制信号的先后关系、复位释放和模拟上电的配合——那就必须反标。不反标跑出来的波形看着挺漂亮可能和流片结果差十万八千里。1.2 SDF文件里到底装了哪些东西很多人第一次打开SDF会懵觉得像天书。其实结构很规整主要就那么几类延时和时序检查。我整理了一个对照表看懂了这几行日志里的告警基本就能对号入座。SDF关键字含义典型来源反标失败的常见原因IOPATH单元输入到输出的路径延时工艺库时序表单元实例名或引脚名对不上INTERCONNECT连线延时含RC布局布线后提取网表未保留层次或提取未做SETUP / HOLD建立、保持检查时序库缺neg_tchk或负值被裁掉RECOVERY / REMOVAL异步复位释放检查时序库异步端口被识别成普通输入WIDTH / PERIOD脉冲宽度、时钟周期检查时序库时钟定义和SDF不一致PATHPULSE路径脉冲宽度传播库STA多数仿真器默认不打开还有一点特别容易被忽略SDF里的延时经常写成min:typ:max三元组比如(0.08:0.12:0.21)。这三个值分别对应快速、典型、慢速工艺角。反标的时候必须明确告诉仿真器用哪一档不同档跑出来的结果可能差两倍以上。1.3 数模混仿到底解决什么问题纯数字仿真器跑不动模拟行为纯模拟仿真器SPICE类也扛不住一个几万门的数字模块。混合信号仿真的思路是分而治之数字部分交给事件驱动的数字求解器模拟部分交给基于方程求解的模拟引擎两边在特定的时间点上同步、交换数据。落到Cadence这套工具链上通常就是Xcelium原来的ncsim/irun Virtuoso模拟求解器的组合界面层用AMS Designer或者直接在命令行跑。数字侧用门级网表加SDF反标模拟侧用schematic或提取后的网表两边通过连接模块connect module对接。这种组合的价值在于你能在一次仿真里看到完整的因果链模拟块的输出经过连接模块变成数字域的电平数字逻辑带着门延时做出响应再通过连接模块回到模拟域驱动下一级。中间任何一处时序不对波形上立刻能看出来。2. 环境与文件准备把该齐的东西先凑齐2.1 工具链与版本的匹配关系这一步听起来像是废话但确实是翻车最多的地方。几个硬性匹配关系必须先确认SDF格式版本和仿真器支持的版本要对上。SDF 1.0/2.1/3.0/4.0差异不小尤其是2.1和3.0在CELL、INSTANCE结构上有区别。Cadence的工具普遍吃3.0最顺综合或STA导出时优先选3.0。工艺库版本要和网表来源一致。用A版本库综合出的网表反标时却挂了B版本的仿真库引脚名或单元名对不上反标必然大面积失败。模拟侧的模型库和仿真器版本。AMS Designer对Spectre版本有要求混仿的connectLib也要跟着工具版本走不要从别的项目直接拷一个老版本的connect rules文件过来用。我的习惯是在项目目录里放一个env.md或者直接写在README里把每个工具的版本号、库路径记下来。下次换环境或者交接给别人能省掉半天的排查。2.2 SDF是怎么产生的参数怎么选SDF通常有两条产生路径你按自己的流程挑一条。第一条是综合工具导出。数字综合完成后工具已经有时序模型可以顺手write_sdf出来。这条路径的优点是快缺点是综合阶段的连线负载是估算的通常用wire load model精度一般适合早期功能联调。第二条是静态时序分析工具导出。用布局布线后的寄生参数做STA再write_sdf。精度高尤其带INTERCONNECT的情况下更接近真实。代价是流程长而且要保证STA用的库角、约束和网表是同一套。导出时几个参数值得留意# 以STA工具为例示意写法具体命令名按你的工具手册 write_sdf -max -min -typical \ -interconnect \ -precision 4 \ -format 3.0 \ -output ./sdf/dut_max.sdf-max/-min/-typical三个角都写进去之后仿真时用哪个再挑避免反复生成。-interconnect要不要带连线延时。后仿阶段建议带上前仿阶段网表里没这些信息加了也是空的。-precision小数位数4位够了写太细只会把文件撑大。-formatSDF版本前面说过优先3.0。提示如果STA工具报出一堆未约束路径先别急着导SDF。未约束的路径在SDF里可能是默认值或者干脆缺失反标日志会告诉你哪些实例没拿到延时。2.3 目录组织与配置视图的准备混仿项目的目录如果一开始不规划好后面找文件会疯。我一般按下面这个结构摆proj/ ├── rtl/ # RTL源码混仿时通常不用 ├── syn/ │ ├── netlist/dut.v # 门级网表 │ └── sdf/dut_max.sdf # 导出的SDF ├── analog/ │ ├── schematic/ # 模拟原理图库形式 │ └── spectre/ # 提取后的模拟网表 ├── tb/ │ ├── tb_top.vams # 顶层测试台 │ └── config_ams # 混合信号配置视图 └── sim/ # 仿真运行目录日志全放这里配置视图config view是AMS流程的核心概念本质是一张表告诉工具每个实例该用哪个视图去展开。数字模块指向网表视图模拟模块指向schematic或symbol视图顶层测试台指向你写的混合源码视图。在Hierarchy Editor里配的时候有两个细节容易被忘掉一是视图列表的顺序工具是从上往下找的把netlist排在schematic前面避免数字模块被误当成模拟块展开二是全局绑定global bindings库名变更或者模块名带参数化时靠全局绑定兜底更省事。3. SDF反标的完整操作流程3.1 两种反标方式的取舍Cadence的仿真器支持两种反标入口各有各的适用场景。**方式一网表/测试台里写系统任务。**在Verilog里直接调用$sdf_annotate路径和选项都写在代码里。initial begin $sdf_annotate(../syn/sdf/dut_max.sdf, tb.u_dut, , ../sim/dut_max.sdf.log, MAXIMUM, 1.0, FROM_MTM); end这种写法适合流程固定、只跑一个角的场景。缺点是换角要改代码重新编译灵活性差。测试台里最好加个判断用$test$plusargs之类控制避免每次都重新编。**方式二命令行选项。**不用改代码跑仿真时通过选项把SDF喂进去。# 示意写法选项名以你手上版本的xrun/ncsim手册为准 xrun -ams \ -config tb.config_ams \ -sdf max:tb.u_dut:../syn/sdf/dut_max.sdf \ -sdf_verbose \ -timescale 1ns/1ps \ -access rwc \ tb_top.vams我推荐早期调试用方式一日志集中、好定位后期跑多角回归用方式二脚本一改就能扫min/typ/max。两种方式的日志格式会有细微差别看日志的时候留意一下。3.2 反标选项逐条拆解$sdf_annotate的参数顺序容易记混我按最常见的形式列一遍顺便说说每个坑在哪。位置参数说明踩坑点1sdf_fileSDF路径相对路径是相对于仿真运行目录不是源文件目录2module_instance反标的目标实例必须是层次路径写错就整体失败3config_file配置文件一般留空串用命令行更灵活4log_file反标日志路径强烈建议显式指定默认日志可能混在大日志里找不到5mtm_specMINIMUM / TYPICAL / MAXIMUM建立时间检查跑max保持时间检查跑min6scale_factors缩放系数单位和精度不对时用的正常填1.07scale_type缩放方式用SDF自带值还是按mtm取这里最容易写反第三个参数很多人会填个东西进去其实留空加上命令行覆盖更省事。第五个参数mtm_spec是重点如果你在做建立时间相关的检查跑MAXIMUM做保持时间相关的跑MINIMUM。这不是玄学是因为最坏建立和最坏保持发生在不同的工艺角上混仿里如果只有一个SDF就得根据你关注的时序类型选边站。第六、七个参数是保险丝。多数情况下单位和精度都是对的但如果你发现波形上的延时要不大十倍要不小十倍先查timescale和SDF头部的TIMESCALE行是否一致再查这两个参数。3.3 反标日志怎么读才算读懂了日志这东西不看等于没反标。一份典型的SDF反标日志会包含这些信息Reading SDF file: ../syn/sdf/dut_max.sdf SDF version: 3.0, timescale: 1ns Annotating instance: tb.u_dut IOPATH annotations applied: 12876 IOPATH annotations failed: 43 SETUP/HOLD annotations applied: 3204 SETUP/HOLD annotations failed: 7 Instances not found: 2 Total cells in design: 4521 Cells annotated: 4502读的时候抓三个数就够了失败数量、失败率、没找到的实例。失败率低于千分之一一般可以接受但要把失败的类型分类看——如果失败集中在某一种单元上基本是库引脚名不匹配如果均匀散布可能是层次路径有偏差。几个经验判据IOPATH annotations failed突然几百条第一反应查是不是选错了mtm档SDF里只有typ值但你却要max。Instances not found有值直接去看这些实例在网表里叫什么名字通常是被工具改过名比如加了_0、_1后缀。日志里如果出现Instance ... not annotated, no timing specification in library说明库里那个单元本来就没时序信息属于正常情况不用管。最要命的是零失败有时候日志干干净净但波形上一点延时都没有。这种情况一般是反标打到了错误的层次或者网表被展开了flattenSDF里的层次结构和实际设计对不上。注意反标日志一定要和仿真日志分开存。混在几万行的仿真输出里出问题的时候你根本找不到那几十行关键信息。3.4 怎么确认反标真的生效了别只看日志做两个小实验验证。第一个实验挑一条确定的路径在仿真里打时间戳。比如某个D触发器从时钟上升到Q输出翻转实测延时应该和SDF里对应的IOPATH数值在同一量级。如果实测是0说明没反标上。第二个实验跑两个角对比。同样激励max角和min角跑出来的总延时应该有明显差异常见十几到几十个百分点。如果两边波形完全重合八成是mtm_spec没生效或者SDF里三个值本来就相同。4. 数模混仿的连接与跑通4.1 连接模块数字和模拟之间的翻译官数字域是离散的0/1加逻辑强度模拟域是连续电压电流。中间必须有东西做转换这个东西就是连接模块connect moduleCadence的ConnectLib库里给了一整套。常用的几种E2Lelectrical to logic模拟电压转成数字逻辑值靠阈值判断还能带上上升下降时间。L2Elogic to electrical数字逻辑值转成模拟电压源需要指定高低电平电压、输出阻抗、上升下降时间。E2R / R2E和实际电阻值打交道的场景比如某些总线的上拉下拉建模。参数选不对波形会非常难看。我见过最典型的两个问题L2E的上升时间设成0结果模拟侧看到的是理想阶跃导致后级电路出现不真实的过冲和振铃E2L的阈值设成电源电压的一半但实际数字输入是1.8V域模拟侧只有1.2V摆幅结果逻辑一直判成0。选参数的思路很直接照着数字单元的实际输入输出特性设。输出高低电平填数据手册的VOH/VOL上升下降时间填数据手册的转换时间阈值填VIH/VIL的中间值。别偷懒用默认值。4.2 连接规则文件怎么写连接规则connect rules文件给工具一张映射表哪些模拟网络和哪些数字网络对接时用哪个连接模块。示意写法如下具体关键字以你库里connectLib的实际内容为准。// 示意非可直接运行文件 connectrules MyAmsRules; connect E2L(electrical, logic) ConnectLib.E2L; connect L2E(logic, electrical) ConnectLib.L2E; // 单比特和多比特分开指定 connect E2L(electrical, wreal) ConnectLib.E2W; // 指定不同电压域用不同的转换参数 connect L2E(logic, electrical) ConnectLib.L2E_1v8; endconnectrules写的时候三个原则按电压域分组。1.2V域、1.8V域、3.3V域的参数完全不同混在一个规则里会出事。分开写每个域一套参数。多比特信号单独处理。总线信号两边宽度的解释方式要对齐特别是模拟侧用wreal数组表示的时候位序容易搞反。规则文件放版本控制里。这东西改一次影响全局务必记清楚哪次改动对应哪次仿真结果。4.3 时间精度与事件同步混仿里最容易出现数字跑太快把模拟甩在后面或者模拟步长太细跑不动这两极。几个关键设置全局精度。数字侧timescale 1ns/1ps模拟侧tran的maxstep和errpreset要匹配。数字最小步长1ps模拟的时间步长如果设成10ns中间的所有数字事件都会被漏掉。errpreset选择。conservative最慢最准moderate是常用折中liberal快但可能丢细节。混仿里带开关电容或锁相环的模块建议先用moderate跑通再谈提速。同步点密度。连接模块本身会引入额外的求解事件接口线越多同步开销越大。如果一个宽总线两边都用逐位连接模块性能会很惨考虑用wreal数组一把过。我在一个带ADC的混仿项目上做过对比同样是10微秒的仿真时长接口用逐位连接模块要跑40分钟改成多比特wreal之后降到9分钟波形基本一致。接口建模方式对性能的影响比想象中大得多。4.4 配置视图与网表生成AMS Designer的流程里配置视图决定了整个设计的展开方式。配置好之后工具会做一次网表生成把模拟部分转成Spectre网表数字部分转成仿真器能吃的形式两边在顶层粘起来。这一步常见的坑模拟块被展开成了晶体管级。如果你只想跑schematic级的行为模型检查视图列表里schematic的位置别让spectre或cdl排在前面。数字网表被当成模拟块处理。反过来如果看到数字侧在跑SPICE求解就是因为视图顺序反了。参数化模块的参数没传下去。混合层次里如果有参数化模块生成网表时参数传递容易断链跑之前抽查几个关键实例的参数值。生成完网表后别急着跑长仿真。先跑个几百纳秒的短仿真看看波形有没有基本的逻辑跳变。这一步花两分钟能省掉后面两小时。5. 常见问题与排查技巧实录5.1 反标类问题速查表现象可能原因排查动作日志全部反标失败SDF层次路径和网表不匹配对比SDF里的INSTANCE和网表顶层实例名只失败一部分单元引脚名大小写或后缀不一致抽查失败单元的库引脚名反标成功但波形无延时网表被flatten或反标打错层次检查$sdf_annotate的第二个参数延时数值大十倍或小十倍timescale不一致核对SDF头部TIMESCALE和编译选项SETUP/HOLD全失败缺少负时序检查支持加neg_tchk之类的选项min/max跑出来一样mtm_spec没生效或SDF只有单一值打开日志确认取的哪一档INTERCONNECT全失败网表没有层次或未提取寄生确认是否后仿网表5.2 排查反标问题的三个实用手法第一先做单实例实验。别一上来就全设计反标。挑一个小的子模块单独导一份SDF跑通了再往上加。层次路径的问题在小模块上暴露得最快。第二用工具自带的报告功能。多数仿真器支持把反标结果导成一份列表列出每个实例每个引脚实际反标到了什么值。拿这份列表和SDF原文对照差异一目了然比看日志猜快得多。第三打开详细模式。-sdf_verbose这类选项会把每一次反标尝试都打出来。日志会变得很长但配合grep定位问题的速度反而更快。我一般这么用grep -i failed\|not found\|error dut_max.sdf.log | sort | uniq -c | sort -rn | head -30先把失败模式按出现次数排序最常见的那个八成就是根因。5.3 混仿跑不动怎么办混仿慢是常态但慢到不可接受就有问题。按这个顺序查先看数字侧是不是在空转。数字求解器在没有事件的时候几乎不耗时间如果它一直在跳说明时钟或复位有问题比如复位没释放导致电路一直在翻转。再看模拟侧的步长。在Spectre日志里看平均步长和总步数。步长被压到皮秒级通常是有节点在剧烈振荡或者有高阻节点没加初始条件。前者查电路后者加.ic或初始条件。然后看接口。接口数量、连接模块的复杂度、两侧的同步频率这三样都直接决定开销。能合并的总线就合并能用理想源的别用带阻抗的模型。最后看输出。波形保存是全量还是抽样全量保存几万个节点的波形光写盘就能拖垮仿真。只存你真正要看的信号或者设置抽样间隔。提示混仿调试阶段可以先关掉SDF反标跑一遍确认功能对了再打开反标。这样能把功能问题和时序问题分开不然两个问题缠在一起排查效率极低。5.4 几个血泪教训别在反标没验证的情况下跑长仿真。我吃过一次亏SDF反标日志有几百条失败当时想着不影响主体结果跑了一整夜的仿真第二天发现关键路径上的延时全是默认值时序结论完全无效。现在我的规矩是反标日志当天必须清干净。把日志留在运行目录里别覆盖。每次仿真生成带时间戳的日志目录出了回归差异能直接对比。见过太多人为了目录干净每次覆盖最后想回溯的时候什么都没有。模拟侧的初始条件要写全。混仿里模拟块的初始状态如果靠自动DC求解可能收敛到非预期的解导致数字侧收到错误的初始电平。关键节点的初始电压手动指定能省掉大量莫名其妙的启动异常。版本升级后重新验证反标。换个仿真器版本反标行为可能有细微变化尤其是负时序检查和脉冲宽度传播的处理。别默认以前能跑现在也能跑跑一个短用例确认一下。5.5 关于性能与精度的取舍心得混仿里精度和速度永远是矛盾。我的做法是分阶段功能联调阶段SDF只反标IOPATH不带INTERCONNECT模拟侧用行为级模型errpreset用liberal。这个阶段目标是逻辑对不对几十分钟能跑完一毫秒。时序验证阶段SDF带上INTERCONNECT模拟侧换成带寄生参数的后仿网表errpreset用moderate或conservative。这个阶段只跑关键场景几百纳秒的量级可能要跑几个小时。这两个阶段的用例、网表、SDF最好完全分开存放。混在一起最典型的后果是跑功能用例时忘了切回简化配置白白等了一整天。我个人在实际操作中的体会是反标和混仿这两件事八成的坑都在文件对齐上——SDF和网表的层次对齐、库版本对齐、时间单位对齐、连接规则和电压域对齐。工具本身的用法反而是最简单的那部分。所以每次新项目开坑我会花半天时间专门做一轮对齐检查把这四样东西逐个验证一遍后面能省下的时间远不止半天。
返回列表