ARTICLE DETAIL

资讯详情

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

Tessent MBIST实战:从零搭建可复用参考脚本框架

Tessent MBIST实战:从零搭建可复用参考脚本框架 1. 从零理解Tessent MBIST为什么需要参考脚本1.1 MBIST在DFT体系中的位置做DFT这行的朋友都清楚芯片测试里最让人头疼的不是逻辑测试而是存储器测试。一颗SoC里面动辄几十上百个SRAM实例每个SRAM的地址位宽、数据位宽、深度、mux策略都不一样。如果靠人工去写测试向量那基本等于自己给自己挖坑。MBISTMemory Built-In Self-Test就是为解决这个问题而生的——在芯片内部集成一套自测试逻辑上电后自动对存储器进行读写遍历把故障覆盖率拉上去。Tessent是业界主流的DFT工具链之一它的MBIST流程覆盖了从memory model导入、BIST控制器插入、pattern生成到仿真验证的完整链路。但问题在于Tessent的文档虽然全却散落在各种User Guide和Reference Manual里新手拿到项目之后往往不知道从哪下手。这时候一套可复用的参考脚本就成了救命稻草。我见过太多团队在项目初期花两三周时间摸索Tessent MBIST的脚本框架最后发现其实核心逻辑就那么几十行。这篇内容就是把我自己踩过的坑和最终沉淀下来的脚本框架完整拆开让你能在最短时间内搭起一套能跑通的内存测试环境。1.2 谁适合看这份实战记录如果你属于以下几类人这篇内容应该能帮你省下不少时间刚接触DFT、第一次用Tessent做MBIST的工程师需要快速搭建memory测试环境、但不想从零啃文档的从业者想理解MBIST脚本背后逻辑、而不只是复制粘贴的验证人员需要维护多项目脚本框架、希望统一流程的团队负责人我假设你已经对Verilog和基本DFT概念有了解但不需要你精通Tessent。脚本部分我会从最基础的环境变量设置讲起每一步都解释为什么这么做。1.3 参考脚本的核心价值一套好的MBIST参考脚本本质上解决三个问题可复用、可调试、可扩展。可复用意味着换个项目只需要改配置参数不用重写流程可调试意味着出问题的时候能快速定位是memory model的问题、controller配置的问题还是pattern生成的问题可扩展意味着后续要加新的memory类型或者新的test algorithm时框架不用大改。我下面要拆解的这套脚本框架核心思路是“配置与流程分离”——把所有跟具体memory相关的参数抽到一个配置文件里主流程脚本只负责调用Tessent的命令。这样做的直接好处是当你手上有五个项目并行的时候你不需要维护五套脚本只需要维护五份配置。2. 环境准备与目录结构设计2.1 Tessent环境的关键设置在跑任何脚本之前环境必须先通。Tessent的环境设置主要涉及几个部分工具安装路径、license配置、工艺库路径。我习惯在项目根目录下放一个env_setup.sh把所有环境变量集中管理。#!/bin/bash # env_setup.sh - Tessent环境初始化 export TESSENT_HOME/tools/tessent/2023.1 export PATH$TESSENT_HOME/bin:$PATH export TESSENT_LICENSE_FILE27020license_server export STD_CELL_LIB/projects/libs/tsmc28/stdcell export MEM_LIB/projects/libs/tsmc28/memory这里有个细节值得说TESSENT_LICENSE_FILE的格式取决于你们公司的license服务器配置有的是porthost有的是直接指向license文件。这个一定要跟IT确认清楚否则工具启动就卡住了。注意环境变量设置完之后一定要用which tessent确认工具路径正确再用tessent -version验证license能正常获取。我遇到过好几次环境变量看着没问题、但license端口被防火墙挡了的情况。2.2 推荐的目录结构脚本要跑得顺目录结构必须先理清楚。我推荐的布局是这样的mbist_project/ ├── env/ # 环境配置 │ └── env_setup.sh ├── config/ # 配置文件 │ ├── memory_list.cfg │ └── mbist_config.cfg ├── scripts/ # 主流程脚本 │ ├── run_mbist.tcl │ └── run_simulation.tcl ├── models/ # memory model │ └── sram_models/ ├── work/ # 运行目录 │ ├── dft_insert/ │ └── simulation/ └── reports/ # 输出报告 ├── dft/ └── sim/这个结构的好处是职责清晰。config/放所有可变的参数scripts/放不变的流程逻辑work/放工具生成的中间文件reports/放最终结果。当你需要归档或者交接的时候直接把config/和scripts/打包就够了。2.3 Memory Model的准备与检查Memory model是MBIST流程的输入基础。Tessent支持多种memory model格式常见的有Liberty、Verilog behavioral model和Tessent专用的memory model格式。我建议优先使用foundry提供的Tessent memory model因为里面已经包含了BIST相关的引脚定义和timing信息。拿到memory model之后第一件事是检查model的完整性。我一般会写一个小脚本快速扫描# check_memory_model.tcl set mem_files [glob -nocomplain ./models/sram_models/*.lib] foreach mem_file $mem_files { puts Checking: $mem_file if {[catch {read_cell_library $mem_file} err]} { puts ERROR: Failed to read $mem_file puts Reason: $err } else { puts OK: $mem_file loaded successfully } }这个检查步骤看起来简单但能帮你提前发现model缺失、格式不兼容等问题。我踩过的坑是有些memory model的Liberty文件里没有定义memory属性Tessent读进去之后不认它是memory导致后续BIST controller插入失败。遇到这种情况需要在脚本里手动指定memory类型。3. MBIST脚本核心流程拆解3.1 配置文件的组织方式配置文件是整个脚本框架的灵魂。我把配置分成两个层次memory级别的配置和BIST controller级别的配置。Memory级别的配置用表格形式管理最清晰参数名说明示例值memory_namememory实例名SRAM_1024x32memory_typememory类型SRAMaddr_width地址位宽10data_width数据位宽32depth深度1024mux_factormux因子4model_filemodel文件路径./models/sram_1024x32.libBIST controller级别的配置则包括参数名说明示例值controller_namecontroller名称MBIST_CTRL_TOPtest_algorithm测试算法March_SSAdata_bg数据背景0x00,0xFF,0xAA,0x55run_bist是否自动运行truepipeline_stages流水级数2把这些参数抽到.cfg文件里主脚本用Tcl的source命令读进来后续所有命令都引用变量。这样换项目的时候只需要改.cfg文件主脚本一行不动。3.2 主流程脚本的骨架主流程脚本我习惯分成五个阶段读库、配置、插入、验证、输出。每个阶段用Tcl的proc封装方便单独调用和调试。# run_mbist.tcl - MBIST主流程脚本 # 阶段1: 读取设计库 proc read_design_libs {} { global STD_CELL_LIB MEM_LIB read_cell_library $STD_CELL_LIB/typical.lib foreach mem_lib [glob $MEM_LIB/*.lib] { read_cell_library $mem_lib } puts INFO: All libraries loaded } # 阶段2: 读取设计 proc read_design {} { set design_verilog ./design/top.v read_verilog $design_verilog set_current_design top puts INFO: Design top loaded } # 阶段3: 配置MBIST proc config_mbist {} { source ./config/mbist_config.cfg # 设置BIST controller set_dft_signal -view existing_dft -type ScanClock -port clk -timing {45 55} set_dft_signal -view existing_dft -type Reset -port rst_n -active_state 0 puts INFO: MBIST configuration done } # 阶段4: 插入BIST逻辑 proc insert_mbist {} { set_context dft -mbist # 自动识别memory并插入controller analyze_mbist -memory_model_file ./config/memory_list.cfg insert_mbist -controller_name MBIST_CTRL_TOP puts INFO: MBIST insertion complete } # 阶段5: 输出与报告 proc output_results {} { write_design -output ./work/dft_insert/top_mbist.v report_mbist -summary ./reports/dft/mbist_summary.rpt puts INFO: Results written } # 主执行流程 read_design_libs read_design config_mbist insert_mbist output_results这个骨架看起来简单但每个proc里面都有很多细节可以展开。比如insert_mbist阶段analyze_mbist命令会自动扫描设计中的memory实例但前提是memory model已经正确加载而且设计中的memory实例名跟model里的cell名能对上。3.3 为什么选择Tcl而不是Shell有人可能会问为什么不用Shell脚本而用Tcl原因很简单Tessent本身就是Tcl-based的工具它的所有命令都是Tcl命令。用Tcl写脚本可以直接调用工具命令不需要通过Shell去拼接字符串再传给工具。而且Tcl的变量作用域、过程定义、错误处理机制都比Shell完善得多。我试过用Shell包装Tessent命令结果在传递复杂参数的时候各种转义问题调试起来非常痛苦。后来全部改用Tcl流程顺畅了很多。Shell脚本适合做外层调度比如批量跑多个项目、管理日志文件但MBIST流程本身一定要用Tcl。4. 实操过程与关键环节实现4.1 Memory识别与BIST Controller插入analyze_mbist是整个流程里最关键的一步。它的作用是扫描设计网表识别出所有memory实例并根据memory model里的信息推断出BIST需要的信号。这一步出问题后面全白搭。我一般会先跑一个dry-run看看工具识别出了哪些memory# dry-run检查memory识别情况 set_context dft -mbist analyze_mbist -memory_model_file ./config/memory_list.cfg -dry_run report_memory_instances ./reports/dft/memory_instances.rpt打开memory_instances.rpt重点看三列instance name、memory type、model matched。如果model matched显示为“NO”说明这个memory实例没有匹配到model需要检查model文件是否加载正确或者实例名是否跟model里的cell名一致。我遇到过一个典型问题设计里memory实例名是u_sram/u_sram_0但model里的cell名是SRAM_1024X32工具匹配不上。解决办法是在配置文件里加一个mappingset_memory_mapping -instance u_sram/u_sram_0 -model SRAM_1024X32匹配成功之后insert_mbist命令会为每个memory或者每组memory插入BIST controller。这里有个策略选择是每个memory单独一个controller还是多个memory共享一个controller我的经验是如果memory数量少于10个可以每个memory独立controller调试方便如果超过20个建议共享controller否则面积开销太大。4.2 BIST算法选择与参数配置Tessent支持多种BIST算法常用的有March C-、March SS、March SSA等。不同算法的故障覆盖率和测试时间不同选择的时候需要权衡。算法故障覆盖率测试周期适用场景March C-中等较短一般SRAMMarch SS高中等高可靠性SRAMMarch SSA高较长安全关键SRAMCheckerboard低短快速筛查配置算法的时候在mbist_config.cfg里指定set_mbist_algorithm -controller MBIST_CTRL_TOP -algorithm March_SSA set_mbist_data_background -controller MBIST_CTRL_TOP -values {0x00 0xFF 0xAA 0x55}数据背景的选择也有讲究。0x00和0xFF用于检测stuck-at故障0xAA和0x55用于检测相邻位之间的耦合故障。如果memory的data width是32位工具会自动把这些pattern扩展到32位。实操心得数据背景不是越多越好。每增加一个背景测试时间就线性增加。我一般先用0x00和0xFF跑一轮看覆盖率报告如果覆盖率达标就不加更多背景了。4.3 Pattern生成与仿真验证BIST逻辑插入完成之后下一步是生成测试pattern并跑仿真。Tessent可以生成Verilog testbench和pattern文件我一般用VCS或者Xcelium跑仿真。# 生成pattern和testbench set_context patterns -mbist create_patterns -output ./work/simulation/mbist_patterns write_testbench -output ./work/simulation/tb_mbist.v -pattern ./work/simulation/mbist_patterns仿真脚本我习惯单独写一个run_simulation.tcl因为仿真环境跟DFT插入环境是分开的# run_simulation.tcl set DESIGN ./work/dft_insert/top_mbist.v set TESTBENCH ./work/simulation/tb_mbist.v set PATTERN ./work/simulation/mbist_patterns # 编译 analyze -format verilog $DESIGN analyze -format verilog $TESTBENCH elaborate top_mbist # 加载pattern并仿真 read_pattern $PATTERN run 100000仿真跑完之后重点看两个东西一是pattern有没有全部pass二是BIST controller的status信号有没有正确拉高。如果pattern fail了先检查memory model的timing是否跟实际一致再检查BIST controller的clock和reset有没有正确连接。4.4 覆盖率分析与报告解读Tessent会生成详细的覆盖率报告包括fault coverage、test coverage和fault efficiency。我一般重点关注fault coverage因为它直接反映了测试pattern能检测到多少故障。# 生成覆盖率报告 report_fault_coverage -summary ./reports/dft/fault_coverage.rpt report_test_coverage -summary ./reports/dft/test_coverage.rpt打开报告之后如果fault coverage低于预期通常有几个原因memory model里的fault list不完整、BIST算法选择不当、或者某些memory实例没有被BIST覆盖到。我遇到过一次覆盖率只有85%的情况排查后发现是一个小容量SRAM被工具自动排除了因为它的深度小于BIST controller支持的最小深度。解决办法是在配置里强制指定set_mbist_controller -controller MBIST_CTRL_TOP -min_depth 165. 常见问题与排查技巧实录5.1 Memory Model加载失败这是最常见的问题表现是read_cell_library报错或者analyze_mbist识别不到memory。排查步骤确认Liberty文件语法正确可以用lc_shell或者read_liberty命令单独验证检查Liberty文件里是否有memory属性没有的话需要手动添加确认memory的pin定义跟设计中的实例端口能对上我整理了一个速查表现象可能原因解决方法read_cell_library报语法错误Liberty文件格式问题用liberty parser检查analyze_mbist识别不到memorymodel缺少memory属性手动添加memory属性model匹配失败实例名与cell名不一致添加memory mappingBIST插入后DRC报错clock/reset未正确连接检查set_dft_signal配置5.2 BIST Controller插入后DRC违例DRC违例是另一个高频问题。Tessent在插入BIST逻辑后会跑一遍DRC检查常见的违例包括clock domain crossing、reset同步问题、test mode信号冲突等。我遇到最多的是clock domain问题。如果memory的clock和BIST controller的clock不是同一个时钟域工具会报CDC违例。解决办法有两种一是让BIST controller使用跟memory相同的clock二是在CDC路径上插入同步逻辑。我一般优先选第一种因为实现简单、面积开销小。注意DRC违例不要强行waive除非你完全理解违例的原因和影响。我见过有人为了赶进度把CDC违例全部waive掉结果芯片回来之后memory测试不稳定排查了两个月才发现是CDC问题。5.3 仿真Pattern Fail的排查思路仿真fail的排查是最耗时的因为可能的原因太多。我一般按照以下顺序排查先看fail的pattern编号定位到具体的memory和操作检查memory model的timing是否跟仿真环境一致检查BIST controller的clock频率是否在memory支持范围内检查reset释放时机是否正确如果以上都没问题用波形工具抓BIST controller的内部信号看状态机卡在哪一步我踩过的一个坑是memory model里的setup/hold时间跟实际仿真环境不一致导致pattern在仿真里fail但实际芯片没问题。后来统一用foundry提供的timing model问题就消失了。5.4 多项目脚本复用的经验当你手上有多个项目的时候脚本复用就变得很重要。我的做法是把所有项目相关的参数抽到独立的.cfg文件主脚本框架保持不变。每个项目一个目录目录里放自己的config/和models/scripts/目录用软链接指向公共脚本库。# 项目目录结构 project_a/ ├── config/ │ └── mbist_config.cfg ├── models/ │ └── sram_models/ └── scripts - ../common_scripts/这样维护的好处是当公共脚本有更新的时候所有项目自动生效。但要注意版本控制我一般会在公共脚本库里打tag项目目录里记录使用的tag版本避免脚本更新导致老项目跑不通。6. 脚本调试与性能优化技巧6.1 Tcl脚本的调试方法Tcl脚本调试不像Python那么方便没有pdb那样的交互式调试器。我常用的方法是在关键位置插入puts语句输出变量值和执行状态。另外Tessent支持-verbose选项打开之后会输出详细的执行日志。# 调试示例 puts DEBUG: Current design [get_current_design] puts DEBUG: Memory count [llength [get_memory_instances]] puts DEBUG: Controller $controller_name如果脚本比较复杂我会用Tcl的catch命令捕获错误然后输出错误信息和堆栈if {[catch {insert_mbist -controller_name $ctrl} err]} { puts ERROR: insert_mbist failed puts Error message: $err puts Error info: $::errorInfo return -code error }6.2 大型设计的运行时间优化当设计规模比较大的时候MBIST插入和pattern生成可能跑几个小时。我总结了几条优化经验用-parallel选项开启多线程Tessent支持多核并行处理把memory分组每组单独跑最后合并结果减少不必要的data background只保留覆盖率贡献最大的几个用-incremental模式只重新处理修改过的部分# 开启并行处理 set_parallel_options -threads 8 # 增量模式 set_incremental_options -enable true -checkpoint ./work/checkpoint6.3 报告自动化与结果归档每次跑完MBIST流程我都会自动生成一份汇总报告包括memory列表、controller配置、覆盖率数据和运行时间。这样项目交接或者review的时候直接看报告就够了。# 生成汇总报告 set rpt [open ./reports/dft/summary.rpt w] puts $rpt MBIST Run Summary puts $rpt Date: [clock format [clock seconds]] puts $rpt Design: [get_current_design] puts $rpt Memory count: [llength [get_memory_instances]] puts $rpt Fault coverage: [get_fault_coverage] close $rpt报告归档我习惯按日期建目录每次运行的结果单独存放方便回溯。如果项目周期长还可以用git管理配置文件和脚本每次修改都有记录。7. 从参考脚本到项目落地7.1 脚本框架的定制化调整参考脚本拿到手之后不能直接照搬需要根据项目实际情况调整。我一般会先跑一个最小化的demo用一个简单的memory model验证流程能跑通然后再逐步加入项目里的真实memory。调整的重点包括memory model的适配、BIST controller的命名规范、clock/reset信号的映射、输出文件的路径和格式。这些调整都集中在配置文件和少量脚本参数里不需要改动主流程逻辑。7.2 与后端流程的衔接MBIST插入完成之后输出的网表需要交给后端做物理实现。这里有几个衔接点需要注意BIST controller的物理位置、test mode信号的布线、memory和controller之间的连线长度。我一般会在脚本里输出一份constraint文件给后端参考# 输出后端约束 write_constraints -output ./work/dft_insert/mbist_constraints.sdc这份约束文件里包含了BIST相关的clock定义、false path和multicycle path后端读进去之后可以避免时序违例。7.3 团队协作中的脚本管理如果是团队协作脚本管理就很重要。我的做法是公共脚本库用git管理每个项目一个branch配置文件跟项目代码一起管理运行结果和报告用共享目录存放。另外脚本里所有硬编码的路径都抽成变量放在env_setup.sh里统一管理这样不同人的机器上都能跑。我还会在脚本库里放一份README说明每个脚本的作用、依赖关系和运行方法。新人拿到之后照着README跑一遍就能上手不需要每次都来问我。7.4 持续维护与版本更新Tessent的版本更新比较频繁每次升级都可能影响脚本的兼容性。我一般会在升级之前先用一个小设计跑一遍回归测试确认脚本在新版本上能正常工作。如果发现问题先查Release Note看是不是命令语法变了或者默认行为改了。另外foundry的memory model也会更新新版本可能修复了timing问题或者增加了新的fault model。每次更新model之后需要重新跑一遍MBIST流程确认覆盖率和仿真结果没有退化。我个人在实际操作中的体会是MBIST脚本框架的搭建不是一蹴而就的而是在项目中不断迭代出来的。第一版可能只能跑通基本流程第二版加入了错误处理和报告自动化第三版才做到多项目复用。关键是先把流程跑通再逐步优化不要一开始就追求完美。踩过的坑越多脚本就越健壮。
返回列表