
1. 为什么MBIST的Pattern Spec值得单独拿出来讲做DFT这行的朋友大多有个共识MBISTMemory Built-In Self-Test的插入本身不算最难的事真正让人头疼的是后续的Pattern Spec配置和Pattern生成。我见过不少项目MBIST电路插得漂漂亮亮结果卡在Pattern生成这一步要么仿真跑不通要么覆盖率上不去要么生成的Pattern体积大到测试机台吃不消。回头一查十有八九是Pattern Spec没配对。Tessent MemoryBIST这套工具链在业界用得相当广泛它的Pattern Spec本质上是一份告诉工具怎么生成测试向量的配置文件。你可以把它理解成一份菜谱内存的类型、数量、分组方式、测试算法、数据背景、地址顺序这些全都要在Spec里说清楚。Spec写得糙工具就按默认行为给你生成一套能用但不好用的PatternSpec写得细生成的Pattern才能既保证覆盖率又控制住体积和测试时间。这篇文章面向的是已经接触过Tessent MBIST基础流程、准备深入掌握Pattern Spec配置和生成的工程师。我会从Spec的核心结构讲起一步步拆到实际配置中的关键参数、常见陷阱、以及从Spec到最终Pattern的完整生成链路。不管你是刚接手MBIST Pattern生成的新人还是想系统梳理一遍流程的老手应该都能从中找到有用的东西。需要提前说明的是不同版本的Tessent工具在命令和参数上可能有细微差异我下面提到的配置方式和参数名以较新版本为基准你在实际使用时请对照手头的工具文档做确认。另外具体的Memory型号和项目约束各不相同我给出的示例参数是通用起点不是万能配方。2. Pattern Spec的文件结构与核心字段拆解2.1 Spec文件的整体骨架Tessent MBIST的Pattern Spec通常是一个以.spec为后缀的文本文件内部采用类似Tcl的语法结构。整个文件大致分为几个层次全局设置、控制器级设置、内存组设置、以及单个内存的个性化配置。这种层次化设计的逻辑很直观——全局设置管大方向控制器级管一组内存的共性行为内存组和单个内存则处理差异化需求。一个典型的Spec骨架长这样# 全局设置 set_pattern_spec_global -output_format verilog \ -pattern_type flat \ -serial_shift_clock 50 # 控制器级设置 set_pattern_spec_controller -controller_name MBIST_CTRL_0 \ -algorithm {March_SSA March_CU} \ -data_background {00 FF 55 AA} # 内存组设置 set_pattern_spec_memory_group -group_name SRAM_GROUP_0 \ -memories {SRAM_0 SRAM_1 SRAM_2} \ -address_order fast # 单个内存覆盖设置 set_pattern_spec_memory -memory_name SRAM_0 \ -algorithm March_SSA \ -data_background {00 FF}这个骨架里每一行都有讲究。output_format决定了生成的Pattern是Verilog格式还是其他格式pattern_type决定是扁平化输出还是层次化输出serial_shift_clock控制串行移位时钟的频率。这些参数看着简单但选错了后面会非常难受。2.2 全局设置里最容易踩坑的三个参数全局设置是Spec的基调一旦定下来后面所有控制器和内存都受影响。我重点说三个最容易出问题的参数。第一个是pattern_type。扁平化flat输出意味着所有Pattern打平成一个层次仿真时不需要逐层展开速度快但文件体积大。层次化hierarchical输出保留了设计的层次结构文件小但仿真时需要工具逐层解析速度慢。选哪个取决于你的仿真环境和Pattern用途。如果是给ATE机台用的最终Pattern通常选flat如果是给门级仿真做验证用的hierarchical更合适。我一般建议在开发阶段用hierarchical快速迭代最终交付前再切到flat。第二个是serial_shift_clock。这个参数控制的是串行移位操作的时钟周期数。设得太小移位不充分Pattern可能出错设得太大Pattern体积膨胀测试时间拉长。经验值是根据最长的那条扫描链长度来定一般取链长的1.2到1.5倍作为安全余量。比如最长链是40个触发器那serial_shift_clock设50到60比较稳妥。第三个是output_format。这个看似简单但如果你后续要对接不同的仿真器或ATE平台格式不匹配会直接导致Pattern无法使用。Verilog格式通用性最好但如果你的仿真环境是VHDL为主的那就得选VHDL格式。还有些项目需要STIL格式直接给ATE用那就要在Spec里指定STIL输出。2.3 控制器级配置算法选择是核心控制器级配置里最重要的就是算法选择。Tessent支持多种MBIST算法常用的有March_SSA、March_CU、March_CUD、Checkerboard、Walking_1_0等。不同算法针对的故障模型不一样覆盖率和测试时间也差很多。算法名称目标故障模型相对测试时间适用场景March_SSA固定型故障、跳变故障中等通用SRAM最常用March_CU耦合故障较长高密度SRAM对耦合敏感March_CUD耦合故障、地址解码故障长安全关键型内存Checkerboard固定型故障短快速筛查覆盖率要求不高Walking_1_0固定型故障、桥接故障很长小容量内存高覆盖率需求选算法不是越多越好。我见过有项目为了追求覆盖率把所有算法都堆上去结果Pattern体积翻了五倍测试时间从几十毫秒涨到几百毫秒ATE机台的测试成本直接爆表。合理的做法是根据内存的实际用途来选普通数据缓存用March_SSA就够了指令缓存或者安全相关的内存再加March_CU或March_CUD。data_background参数也值得多说一句。它定义的是测试时写入内存的数据背景模式。常见的背景有00、FF、55、AA这四种分别对应全0、全1、交替01、交替10。背景越多覆盖的故障类型越全但Pattern也会成比例增长。一般选两到四种背景就能覆盖绝大多数固定型故障和跳变故障。2.4 内存组配置分组策略直接影响效率内存组memory group的配置是很多人忽略的一环。Tessent允许你把多个内存归到一个组里共享同一套算法和背景设置。分组分得好Spec简洁Pattern生成快分得不好要么某些内存的测试不充分要么Pattern冗余严重。分组的基本原则是同类型、同容量、同端口数的内存放在一组。比如四个都是512x32的单端口SRAM那放一组用同一套算法没问题。但如果其中一个是双端口SRAM那最好单独拎出来因为双端口内存的测试算法和单端口不一样混在一起会导致工具按单端口的逻辑去处理双端口内存测试覆盖出现漏洞。address_order参数控制地址遍历顺序有fast和slow两个选项。fast模式按物理地址顺序快速遍历适合大多数情况slow模式会打乱地址顺序用于检测地址解码相关的故障。如果你的内存有地址解码器的可靠性担忧那slow模式值得加上代价是Pattern体积会增加大约30%到50%。3. 从Spec到Pattern生成流程的每一步在做什么3.1 生成前的环境检查清单在跑Pattern生成之前有几项检查必须做否则生成到一半报错排查起来很浪费时间。第一确认MBIST插入已经完成且没有DRC违规。Tessent的MBIST插入阶段会做一系列设计规则检查如果有未解决的违规Pattern生成阶段会直接失败或者生成无效Pattern。你可以在插入后的日志里搜DRC关键字确认没有ERROR级别的违规。第二确认Spec文件里的内存名称和设计中的实例名完全一致。大小写敏感一个字母对不上工具就找不到对应的内存。我习惯在写Spec之前先用工具命令导出一份内存列表然后直接从列表里复制名称到Spec里避免手打出错。第三确认仿真库和工艺库的路径配置正确。Pattern生成需要调用仿真模型来做验证如果库路径不对工具会在生成过程中报module not found之类的错误。第四检查磁盘空间。Pattern生成过程中会产生大量中间文件尤其是大容量内存或者多算法配置的情况下中间文件可能达到几个GB。提前确认磁盘有足够空间避免生成到90%的时候因为磁盘满而失败。3.2 生成命令的执行与日志解读环境检查通过后就可以执行Pattern生成命令了。Tessent通常提供命令行和图形界面两种方式我推荐用命令行因为可以脚本化方便重复执行和集成到CI流程里。tessent -shell -dft_config mbist_pattern_gen.tcl -log pattern_gen.log生成过程中日志文件是关键。日志里会按阶段输出进度信息你需要重点关注几个地方Spec解析阶段工具会逐条读取Spec里的配置如果有语法错误或者参数值不合法这里会报出来。常见的错误包括参数名拼写错误、值超出合法范围、引用的内存名不存在等。算法展开阶段工具根据你选的算法展开成具体的操作序列。这个阶段日志会显示每个内存用了哪些算法、生成了多少个操作步骤。如果某个内存的步骤数异常多或异常少可能意味着算法配置有问题。Pattern组装阶段把操作序列组装成最终的Pattern格式。这个阶段会显示生成的Pattern数量和总体积。仿真验证阶段如果开启了仿真验证工具会用生成的Pattern跑一遍仿真确认没有X态传播或者时序违规。这个阶段最耗时但也是最能发现问题的环节。日志里出现WARNING不一定都是问题但有几类WARNING必须重视关于内存覆盖率的WARNING、关于时序约束的WARNING、关于数据背景冲突的WARNING。这些往往预示着Pattern质量有隐患。3.3 生成结果的初步验证方法Pattern生成完成后不要急着交付先做几项快速验证。第一项是Pattern数量检查。对比一下生成前后的预期。如果你配了3种算法、4种数据背景、10个内存那Pattern数量大致应该是算法数乘以背景数再乘以内存数的一个量级。如果实际生成的数量远低于预期说明有些配置没生效远高于预期说明可能有冗余。第二项是覆盖率报告检查。Tessent会生成一份覆盖率报告列出每个内存的故障覆盖率。正常情况下March_SSA应该能达到95%以上的固定型故障覆盖率March_CU对耦合故障的覆盖率应该在90%以上。如果某个内存的覆盖率明显偏低回去检查它的算法配置和数据背景设置。第三项是仿真抽查。从生成的Pattern里随机抽几条手动跑一下仿真看看波形是否符合预期。重点看内存的读写时序、数据背景是否正确应用、地址遍历顺序是否和配置一致。这一步虽然费时间但能发现一些自动化检查覆盖不到的问题。4. 实际项目中那些Spec配置的坑与解法4.1 多时钟域内存的Spec处理多时钟域是MBIST Pattern Spec里最容易出问题的地方之一。当设计里有多个时钟域且每个时钟域里都有内存需要测试时Spec的配置就变得复杂了。核心问题在于不同时钟域的内存不能简单地放在同一个控制器下因为控制器的时钟是单一的。你需要为每个时钟域单独配置控制器或者在Spec里显式指定时钟域信息。# 时钟域A的控制器 set_pattern_spec_controller -controller_name MBIST_CTRL_A \ -clock_domain clk_a \ -algorithm March_SSA # 时钟域B的控制器 set_pattern_spec_controller -controller_name MBIST_CTRL_B \ -clock_domain clk_b \ -algorithm March_SSA如果两个时钟域的频率差异很大还要注意serial_shift_clock的设置。频率高的时钟域可以设小一点频率低的要设大一点确保移位操作在慢时钟域里也能完成。我遇到过因为没注意这一点导致慢时钟域的内存Pattern在仿真时出现时序违规的情况。另外跨时钟域的内存组不要混在一起。即使两个内存的型号完全一样只要它们在不同的时钟域就应该分到不同的组里。混在一起会导致工具在生成Pattern时无法正确处理时钟切换生成的Pattern在实际测试时可能失效。4.2 数据背景冲突的排查过程数据背景冲突是一个比较隐蔽的坑。表现是Pattern生成成功仿真也通过但实际测试时某些内存的故障检测率不达标。排查这类问题的思路是这样的首先确认Spec里每个内存的data_background设置是否和它的算法匹配。比如March_CU算法要求至少两种数据背景通常是00和FF如果你只配了一种覆盖率就会打折扣。其次检查是否有多个内存共享了同一个数据背景设置但它们的实际数据宽度不同。比如一个32位内存和一个16位内存如果共用背景设置16位内存的高16位可能一直是0导致某些故障无法被检测到。解决方法是给不同数据宽度的内存单独配置背景或者在背景设置里使用通配符模式让工具根据内存宽度自动扩展。Tessent支持用{00 FF 55 AA}这样的列表来指定多个背景也支持用repeat语法来按位重复某个模式。提示每次修改数据背景配置后务必重新生成覆盖率报告确认覆盖率没有下降。数据背景的改动对覆盖率的影响有时候是反直觉的。4.3 Pattern体积失控的优化手段Pattern体积失控是另一个常见问题。一个中等规模的SoC如果MBIST配置不当生成的Pattern体积可能达到几百MB甚至上GB给ATE机台的存储和加载带来很大压力。优化Pattern体积有几个方向。第一是精简算法组合。不是所有内存都需要全套算法根据内存的实际用途做取舍。第二是合并数据背景。如果两种背景对覆盖率的贡献重叠度很高可以只保留一种。第三是使用压缩选项。Tessent提供了Pattern压缩功能可以在Spec里开启。set_pattern_spec_global -compress on \ -compress_method run_length \ -compress_level 3压缩方法有run_length和statistical两种压缩级别从1到9。级别越高压缩率越好但解压时间也越长。一般设3到5就能在压缩率和解压时间之间取得不错的平衡。第四是合理设置地址顺序。fast模式比slow模式生成的Pattern体积小如果地址解码故障不是重点关注对象用fast模式就够了。我做过一个对比测试同一个设计优化前Pattern体积280MB经过算法精简、背景合并、开启压缩后降到45MB覆盖率只下降了不到1个百分点。这个代价是完全值得的。4.4 仿真验证阶段的常见报错与应对Pattern生成后的仿真验证阶段常见的报错有几类。X态传播是最常见的。原因是Pattern在某些内存上产生了不确定的读写操作导致仿真时出现X态。排查方法是定位到报X态的具体Pattern和内存检查该内存的Spec配置是否有遗漏比如是否缺少了初始化操作或者时序约束。时序违规通常和serial_shift_clock设置有关。如果移位时钟周期数不够数据还没稳定就被采样就会报时序违规。解决办法是增大serial_shift_clock的值或者检查时钟约束文件是否和Spec里的设置一致。内存模型不匹配是指仿真用的内存模型和实际设计中的内存行为不一致。这种情况通常发生在使用了第三方IP内存的时候仿真模型和实际电路的时序参数有差异。解决办法是确认使用的仿真模型版本和IP版本匹配必要时联系IP供应商获取正确的仿真模型。5. 让Pattern Spec配置可复用、可维护的工程化思路5.1 参数化模板的搭建方法每个项目都从头写Spec是不现实的效率低且容易出错。我的做法是搭建一套参数化的Spec模板把项目相关的变量抽出来用脚本生成最终的Spec文件。模板的核心思路是把Spec分成两部分不变部分和可变部分。不变部分是那些跨项目基本一致的配置比如输出格式、压缩选项、日志级别等。可变部分是项目相关的比如内存列表、控制器名称、算法选择等。# 模板文件 pattern_spec_template.tcl set_pattern_spec_global -output_format ${OUTPUT_FORMAT} \ -pattern_type ${PATTERN_TYPE} \ -serial_shift_clock ${SHIFT_CLOCK} foreach ctrl ${CONTROLLER_LIST} { set_pattern_spec_controller -controller_name ${ctrl} \ -algorithm ${ALGO_${ctrl}} \ -data_background ${BG_${ctrl}} }然后用一个简单的脚本读取项目配置文件替换模板里的变量生成最终的Spec。这样做的好处是模板经过多个项目验证稳定性有保障项目配置集中在一个文件里修改方便新人上手只需要理解项目配置文件不用啃整个Spec。5.2 版本管理与变更追踪Spec文件的版本管理经常被忽视但它对项目维护很重要。我建议把Spec文件纳入版本控制系统比如Git每次修改都提交并写清楚变更原因。变更追踪的关键是记录为什么改而不是改了什么。比如将SRAM_0的算法从March_SSA改为March_CU因为覆盖率报告显示耦合故障覆盖率不足就比修改了SRAM_0的算法配置有用得多。半年后回头看前者能让你快速理解当时的决策逻辑后者只会让你一头雾水。另外Spec文件和生成脚本、覆盖率报告应该关联管理。每次Spec变更后重新生成的Pattern和覆盖率报告应该和对应的Spec版本绑定存档。这样如果后续发现Pattern有问题可以快速回溯到是哪个版本的Spec导致的。5.3 跨项目复用的经验沉淀做了几个项目之后你会积累一些通用的配置经验和参数组合。把这些经验沉淀下来形成团队内部的配方库能大幅提升后续项目的效率。配方库可以按内存类型来组织SRAM配方、DRAM配方、ROM配方、双端口内存配方等。每个配方里记录推荐的算法组合、数据背景、地址顺序、压缩设置以及这些配置适用的场景和注意事项。比如SRAM的通用配方可能是March_SSA加March_CU数据背景00和FF地址顺序fast压缩级别3。这个配方在大多数SRAM上能提供95%以上的覆盖率Pattern体积可控。如果项目对覆盖率有更高要求再在此基础上加March_CUD和更多数据背景。配方库不是一成不变的每次项目结束后应该回顾一下哪些配方好用、哪些需要调整持续迭代。我自己的配方库经过五六个项目的打磨现在已经能覆盖80%以上的常见场景新项目启动时直接套用只需要针对特殊内存做微调。6. 一些实战中攒下来的零碎经验Spec里的注释不是可有可无的。我习惯在每条配置后面加一行注释说明这条配置的意图和依据。比如-algorithm March_SSA # 覆盖固定型故障参考覆盖率报告v2。这些注释在调试和交接时能省大量时间。生成Pattern之前先跑一次dry run。Tessent支持只解析Spec不实际生成Pattern的模式用这个模式快速检查Spec的语法和参数合法性比直接生成再报错要快得多。覆盖率报告不要只看总数。总数达标不代表每个内存都达标要逐个内存检查。我见过总数98%但某个小内存只有60%覆盖率的情况那个内存的故障在实际测试中很可能漏检。Pattern生成的时间通常比预期长。一个中等规模的设计从Spec解析到最终Pattern输出跑几个小时是正常的。建议把生成任务放在下班前启动第二天早上来看结果。如果支持分布式计算可以拆分成多个子任务并行跑。和ATE工程师的沟通要提前。Pattern的格式、体积、测试时间这些指标最终是ATE工程师在使用。在Spec配置阶段就和他们确认好需求比Pattern生成完了再返工要高效得多。最后说一个心态上的体会MBIST Pattern Spec的配置没有一次做对这回事。第一个版本能跑通就不错了后面通过覆盖率报告和仿真结果反复迭代才能逐步逼近最优配置。把每次迭代的配置和结果记录下来这些记录本身就是最有价值的项目资产。