☰
Tessent ICL模型与IJTAG网络插入实战:从蓝图到向量生成
2026/10/6 11:33:45 网站建设 项目流程

1. 从一次调试翻车说起:为什么ICL模型值得单独拎出来讲

第一次接触Tessent的IJTAG Network Insertion,很多人会以为这只是工具里点几下、跑个脚本的事。我当初也这么想,直到有一次在项目里插完网络,仿真死活过不去,波形上某个SIB的更新信号比预期晚了整整一个TCK周期。查了两天,最后发现问题出在ICL模型里一个CaptureEn的极性写反了。那次之后我才真正意识到,ICL不是一份“配置文件”,它是整个IJTAG网络的连接蓝图,是工具理解你芯片内部JTAG结构的唯一依据。

ICL,全称Instrument Connectivity Language,是Tessent用来描述片上仪器(Instrument)与IJTAG网络之间连接关系的建模语言。你可以把它理解成一张“接线表”:哪个仪器挂在哪个SIB下面、数据从哪进从哪出、时钟和复位怎么走、更新和捕获的时序怎么对齐,全都写在里面。而IJTAG Network Insertion,就是Tessent根据这张接线表,自动把SIB、TDR、扫描链路这些硬件逻辑插入到网表里的过程。蓝图错了,插出来的网络必然错;蓝图对了,插入过程才会顺理成章。

这篇内容适合几类人看:正在用Tessent做DFT插入的工程师、需要手写或修改ICL模型的验证人员、以及那些被IJTAG网络调试折磨过、想搞清楚底层逻辑的从业者。我会从ICL模型的结构讲起,拆解它和Network Insertion之间的对应关系,然后给出可复现的实操步骤、参数计算过程,以及我在实际项目中踩过的坑和总结出的排查方法。不堆术语,尽量用工程语言把这件事讲透。

2. ICL模型到底是什么:拆开这份“连接蓝图”看骨架

2.1 ICL的核心作用与在流程中的位置

在Tessent的整个DFT流程里,ICL模型处在“设计描述”和“硬件插入”之间的关键位置。上游是仪器的定义和RTL设计,下游是IJTAG网络的物理插入和向量生成。没有ICL,Tessent就不知道你芯片里有哪些仪器、它们怎么连、用什么协议通信;有了ICL但写得不准确,插入出来的网络就会在仿真或硅后测试中出各种时序和协议问题。

我习惯把ICL比作建筑行业的“施工图”。RTL是建筑的功能需求,网表是最终盖好的楼,而ICL就是那张标明每根钢筋怎么绑、每根管线怎么走的施工图。施工图错了,楼可能也能盖起来,但住进去就会发现水管接错、电路跳闸。IJTAG网络也一样,ICL写错,网络能插进去,但测试向量跑不通。

从工具流程看,ICL模型通常在Network Insertion之前由设计者提供或由工具自动生成,然后Tessent读取ICL,结合IJTAG的协议规则,在网表中实例化SIB、TDR、时钟门控等逻辑。插入完成后,工具还会生成一份更新后的ICL或网表描述,供后续的向量生成和验证使用。所以ICL不是一次性的输入,它在整个流程中是被反复引用和更新的。

2.2 ICL的模块化结构:Instrument、SIB、Network三者的关系

ICL模型的结构可以分成三个层次来理解。最底层是Instrument,也就是片上仪器,比如温度传感器、PLL、存储器BIST控制器等。每个Instrument在ICL里都有自己的接口描述,包括数据端口、时钟端口、控制端口。中间层是SIB,即Scan Interface Block,它是IJTAG网络的基本节点,负责在扫描链和仪器之间做数据搬运。最上层是Network,描述SIB之间怎么串接、数据怎么从TAP控制器流到各个仪器。

这三者的关系有点像城市交通:Instrument是各个小区,SIB是路口或公交站,Network是道路网。ICL要做的就是标明每个小区有几个门、每个路口怎么转向、道路是单行道还是双行道。如果某个小区的门标错了,公交车就到不了;如果某个路口的方向写反了,整个路网就堵死。

在实际ICL文件里,你会看到类似这样的结构:

Instrument TemperatureSensor { Ports { DataIn : input; DataOut : output; ShiftEn : input; CaptureEn : input; UpdateEn : input; Clock : input; Reset : input; } } SIB TempSensorSIB { Ports { ... } Instrument : TemperatureSensor; } Network MainNetwork { SIBs { TempSensorSIB; ... } Connections { ... } }

这段是简化后的示意,真实ICL会更复杂,但核心逻辑就是这样:先定义仪器,再定义SIB并绑定仪器,最后在Network里把SIB连起来。理解了这个骨架,后面看Network Insertion的每一步就都有依据了。

2.3 ICL与IJTAG协议标准的对应关系

IJTAG是IEEE 1687标准定义的片上仪器访问协议,ICL是Tessent对这个标准的一种实现和扩展。标准里规定了SIB的行为模型、扫描链的时序、TAP控制器的状态机,而ICL把这些抽象概念具体化成工具能读懂的语法。比如标准里说SIB在CaptureDR状态要捕获仪器数据,在UpdateDR状态要更新仪器控制,ICL里就会用CaptureEn和UpdateEn这两个信号来对应。

这里有个容易混淆的点:ICL不是IJTAG标准的唯一实现方式,不同工具厂商可能有自己的描述语言。但Tessent的ICL在业界用得比较广,因为它和Tessent的插入、向量生成流程绑定得很紧。你如果从其他工具转过来,第一件事就是搞清楚ICL里哪些是标准要求的、哪些是Tessent特有的扩展。比如Tessent在ICL里支持一些用于时钟门控和复位同步的扩展属性,这些在标准里没有,但实际项目中很常用。

3. Network Insertion的底层逻辑:工具拿着蓝图怎么施工

3.1 插入流程的四个阶段:解析、映射、实例化、连接

Tessent执行IJTAG Network Insertion时,内部大致分四个阶段。第一阶段是解析ICL,工具读取ICL文件,构建内部的仪器和SIB数据库,检查语法和基本一致性。第二阶段是映射,把ICL里的逻辑SIB映射到工艺库里的物理SIB单元,同时确定每个SIB的地址和扫描链位置。第三阶段是实例化,在网表里真正创建SIB、TDR、时钟门控等实例。第四阶段是连接,按照ICL里的Network描述,把SIB之间、SIB和仪器之间的端口连起来。

这四个阶段里,解析和映射是“纸上作业”,实例化和连接是“动手施工”。很多问题出在映射阶段,比如ICL里定义的SIB端口和工艺库里的SIB单元端口对不上,工具就会报错或自动插入一些额外的逻辑来“补救”,结果就是网络行为跟预期不一致。我遇到过一种情况:ICL里SIB的ShiftEn是低有效,但工艺库里的SIB单元是高有效,工具没有报错,而是自动加了一个反相器。仿真时功能是对的,但时序上多了一级门延迟,高速测试时就出了问题。所以映射阶段的日志一定要仔细看,不能只看“Insertion completed successfully”就完事。

3.2 ICL中的连接描述如何驱动SIB链的生成

ICL里的Network部分描述了SIB之间的连接关系,工具根据这些描述生成SIB链。SIB链的拓扑结构直接影响测试向量的生成和测试时间。常见的拓扑有菊花链、星型、混合型。菊花链最简单,所有SIB串成一条链,数据从TAP控制器依次流过每个SIB。星型是每个SIB单独连到TAP控制器,需要更多的TAP端口。混合型是两者的结合,根据仪器的访问频率和测试时间要求来分组。

ICL里描述连接时,通常会指定ScanIn、ScanOut、Select、ShiftEn、CaptureEn、UpdateEn、Clock、Reset这些信号的来源和去向。工具读取这些描述后,会生成对应的网表连接。这里的关键是:ICL里的连接是逻辑连接,工具在插入时会根据物理约束(比如布局、时钟域)做优化和调整。如果你在ICL里写的连接和实际物理约束冲突,工具可能会插入额外的缓冲器或门控逻辑,导致时序和功耗跟预期不符。

3.3 插入过程中工具自动做的“隐藏操作”

除了显式地实例化SIB和连接端口,Tessent在插入过程中还会做一些“隐藏操作”,这些操作在ICL里看不到,但会影响最终网络的行为。比如:

  • 时钟门控插入:为了降低测试功耗,工具会在SIB的时钟路径上自动插入门控逻辑,只有在SIB被选中时才有时钟。
  • 复位同步:如果ICL里没有明确描述复位信号的同步关系,工具可能会自动插入同步器,避免复位释放时的亚稳态。
  • TDR自动生成:对于某些没有明确TDR的仪器,工具会根据ICL里的端口描述自动生成TDR,用于捕获和更新数据。
  • 扫描链重排序:工具会根据SIB的地址和扫描链长度,自动调整SIB在链中的顺序,以优化测试时间。

这些隐藏操作在大多数情况下是有益的,但在某些对时序和功耗极其敏感的设计里,可能会带来意外。我建议在插入完成后,导出工具生成的更新ICL或网表,和原始ICL做对比,看看工具到底改了哪些地方。这个对比过程虽然繁琐,但能帮你提前发现很多潜在问题。

4. 手把手实操:从ICL编写到Network Insertion的完整流程

4.1 环境准备与ICL文件的基本编写规范

在开始之前,你需要确认Tessent的版本和工艺库已经正确配置。我用的环境是Tessent 2023.1加上某个成熟工艺库,不同版本和库的细节可能有差异,但整体流程是相通的。ICL文件通常以.icl为后缀,可以用任何文本编辑器编写,但建议用支持语法高亮的编辑器,减少低级语法错误。

编写ICL时,有几个基本规范要遵守。第一,所有标识符区分大小写,DataIn和datain是两个不同的东西。第二,端口方向必须明确,input、output、inout不能含糊。第三,每个Instrument和SIB的定义必须以分号结尾,大括号要配对。第四,Network里的连接描述要完整,不能有悬空的端口。这些看起来是小事,但实际项目中很多报错都是因为这些低级问题。

我一般会先写一个最小的ICL模板,只包含一个Instrument和一个SIB,跑通插入流程后再逐步添加。这样做的目的是先验证工具环境和基本流程,避免一上来就面对几百行的ICL和一堆报错。最小模板大概长这样:

Instrument DummyInst { Ports { DataIn : input; DataOut : output; ShiftEn : input; CaptureEn : input; UpdateEn : input; Clock : input; Reset : input; } } SIB DummySIB { Ports { ScanIn : input; ScanOut : output; Select : input; ShiftEn : input; CaptureEn : input; UpdateEn : input; Clock : input; Reset : input; } Instrument : DummyInst; } Network DummyNetwork { SIBs { DummySIB; } Connections { DummySIB.ScanIn = TAPController.ScanOut; DummySIB.ScanOut = TAPController.ScanIn; DummySIB.Select = TAPController.Select; DummySIB.ShiftEn = TAPController.ShiftEn; DummySIB.CaptureEn = TAPController.CaptureEn; DummySIB.UpdateEn = TAPController.UpdateEn; DummySIB.Clock = TAPController.Clock; DummySIB.Reset = TAPController.Reset; } }

这个模板跑通后,你就有了一个可工作的基线。后面添加真实仪器和SIB时,可以逐步替换和扩展。

4.2 定义Instrument和SIB:端口、属性与绑定关系

定义Instrument时,最关键的是端口列表要跟RTL里的仪器接口完全一致。我见过有人把RTL里的data_valid信号在ICL里写成了DataValid,大小写不一致,工具解析时找不到对应端口,插入出来的网络里这个信号就悬空了。仿真时仪器收不到有效数据,测试向量全挂。所以我的习惯是直接从RTL的端口列表复制粘贴到ICL里,再统一调整大小写和命名风格。

SIB的定义除了端口,还要指定它绑定的Instrument。一个SIB可以绑定一个或多个Instrument,取决于仪器的访问方式和数据宽度。如果多个仪器共享一个SIB,ICL里要用Instruments关键字列出所有仪器,并描述它们之间的数据选择逻辑。这里容易出错的地方是数据宽度不匹配:SIB的扫描链宽度和仪器的数据端口宽度不一致时,工具会自动做位宽调整,但调整方式可能不是你想要的。比如仪器是8位数据,SIB是16位扫描链,工具可能会在高8位补零或复制低8位,具体行为取决于ICL里的属性设置。

绑定关系里还有一个重要属性是Address,即SIB在IJTAG网络里的地址。地址决定了TAP控制器访问哪个SIB时,哪个SIB被选中。地址分配要唯一,不能冲突。我一般会在ICL里显式指定地址,而不是让工具自动分配,因为自动分配的地址可能在后续流程中变化,导致向量不匹配。

4.3 Network连接描述:ScanIn/ScanOut、Select、ShiftEn等信号的路由

Network部分的连接描述是ICL里最核心也最容易出错的地方。每个SIB的ScanIn和ScanOut要正确串接,形成扫描链。Select信号决定SIB是否被选中,通常来自TAP控制器的地址译码逻辑。ShiftEn、CaptureEn、UpdateEn控制SIB在扫描、捕获、更新状态的行为。Clock和Reset是全局信号,通常所有SIB共享。

连接描述里有一个容易忽略的点:信号的极性。ICL里可以指定信号是高有效还是低有效,比如ShiftEn : input active_low;。如果ICL里写的是高有效,但TAP控制器输出的是低有效,工具会插入反相器来匹配。这个反相器在功能仿真里没问题,但在时序仿真里会增加延迟。如果这条路径是关键路径,就可能影响测试频率。所以我在写ICL时,会尽量让信号极性和TAP控制器的实际输出一致,避免工具插入不必要的逻辑。

另一个点是时钟域。如果SIB和仪器在不同的时钟域,ICL里要明确描述时钟域交叉的处理方式。工具默认可能会插入同步器,但同步器的深度和类型需要根据实际时钟频率和相位关系来定。我遇到过因为同步器深度不够导致数据丢失的情况,后来在ICL里显式指定了同步器属性才解决。

4.4 运行Insertion:命令、参数与日志解读

ICL准备好后,就可以运行Network Insertion了。Tessent里通常用insert_ijtag_network命令,配合一些参数。我常用的参数包括:

  • -icl_file:指定ICL文件路径。
  • -library:指定工艺库。
  • -output_netlist:指定插入后的网表输出路径。
  • -update_icl:指定更新后的ICL输出路径。
  • -verbose:输出详细日志。

命令大概长这样:

insert_ijtag_network \ -icl_file ./icl/top.icl \ -library ./lib/tech.lib \ -output_netlist ./netlist/top_with_ijtag.v \ -update_icl ./icl/top_updated.icl \ -verbose

运行后,日志会输出每个阶段的详细信息。我重点看几个地方:解析阶段有没有语法警告,映射阶段有没有端口不匹配的提示,实例化阶段有没有资源冲突,连接阶段有没有悬空端口。日志里如果有Warning,即使插入成功了,也要逐条确认。很多Warning在后续向量生成时才会变成Error,到时候再查就麻烦了。

插入完成后,我会用diff命令对比原始ICL和更新后的ICL,看看工具改了哪些地方。常见的改动包括:自动添加的TDR、时钟门控、复位同步器、信号极性调整。这些改动如果符合预期,就继续下一步;如果不符合,就要回到ICL里修改描述,重新插入。

5. 常见问题与排查技巧:那些年我踩过的坑

5.1 ICL语法错误与工具报错对照表

ICL语法错误是新手最常遇到的问题。工具报错信息有时候比较晦涩,我整理了一个常见错误对照表,方便快速定位。

报错信息可能原因解决方法
Undefined identifier 'XXX'标识符未定义或拼写错误检查ICL里是否定义了该标识符,注意大小写
Port direction mismatch端口方向与RTL不一致核对RTL端口列表,确保方向一致
Duplicate addressSIB地址冲突检查所有SIB的Address属性,确保唯一
Unconnected port端口悬空检查Network连接描述,补全所有端口连接
Width mismatch数据宽度不匹配检查SIB和Instrument的数据端口宽度,必要时指定位宽调整属性
Clock domain conflict时钟域未正确描述在ICL里显式指定时钟域和同步器属性

这个表不是万能的,但覆盖了大部分常见问题。遇到报错时,先查表,再结合日志上下文分析。

5.2 插入后仿真失败的典型原因与定位方法

插入成功不代表仿真能过。我遇到过几次仿真失败,原因各不相同。有一次是SIB的CaptureEn极性写反了,导致捕获的数据是错的。定位方法是:在仿真波形里找到SIB的CaptureEn信号,看它在CaptureDR状态时是高还是低,和ICL里的描述对比。还有一次是SIB链的顺序和ICL里描述的不一致,工具自动重排序了,但重排序后的地址映射没更新,导致TAP控制器访问了错误的SIB。定位方法是:导出更新后的ICL,检查SIB链的顺序和地址映射。

仿真失败时,我一般按这个顺序排查:先看TAP控制器的状态机是否正常,再看SIB的选中信号是否正确,然后看数据在SIB链里的流动是否符合预期,最后看仪器是否收到了正确的数据和控制信号。这个顺序是从全局到局部,逐步缩小范围。

5.3 时钟门控与复位同步插入带来的意外时序问题

前面提到工具会自动插入时钟门控和复位同步器,这些逻辑在功能仿真里通常没问题,但在时序仿真或硅后测试中可能带来意外。我遇到过一次时钟门控导致测试频率上不去的情况:工具在SIB的时钟路径上插入了门控单元,门控单元的控制信号来自TAP控制器的译码逻辑,这条路径的组合延迟比较长,限制了时钟频率。后来在ICL里显式指定了门控单元的属性,让工具选择延迟更小的门控单元,才解决了问题。

复位同步器也有类似的情况。工具默认插入的同步器可能是两级触发器,如果复位释放的时间窗口比较窄,两级同步可能不够,需要三级。这个在ICL里可以通过属性指定。我的经验是:对于复位信号,宁可多一级同步,也不要少一级。多一级同步带来的延迟增加通常可以接受,少一级同步带来的亚稳态风险则可能导致芯片工作不稳定。

5.4 独家避坑清单:从ICL编写到插入完成的十个检查点

根据我多个项目的经验,整理了一个避坑清单,每次做Network Insertion前过一遍,能省很多调试时间。

  1. ICL里的所有标识符和RTL保持一致,特别是大小写。
  2. 所有端口方向明确,没有悬空端口。
  3. SIB地址唯一,没有冲突。
  4. 信号极性和TAP控制器实际输出一致。
  5. 时钟域交叉处显式指定同步器属性。
  6. 数据宽度匹配,必要时指定位宽调整方式。
  7. 插入前备份原始ICL和网表。
  8. 插入后对比原始ICL和更新ICL,确认工具改动符合预期。
  9. 日志里的Warning逐条确认,不放过任何一条。
  10. 仿真时先跑功能仿真,再跑时序仿真,逐步验证。

这个清单看起来简单,但每一条背后都有我踩过的坑。比如第4条,我至少遇到过三次因为极性不一致导致的问题。第8条,有一次工具自动添加了一个TDR,我没有注意到,结果向量生成时多了一段扫描数据,测试时间变长了。

6. 从ICL模型到向量生成:蓝图之后的下一步

ICL模型和Network Insertion只是IJTAG流程的前半段。插入完成后,Tessent会根据更新后的ICL和网表生成测试向量。向量生成的质量直接取决于ICL的准确性和插入的正确性。如果ICL里某个仪器的端口描述不完整,向量生成时工具可能无法正确访问该仪器,导致测试覆盖率下降。

我在实际项目中的体会是:ICL模型的维护是一个持续的过程。设计变更时,ICL要同步更新;工艺库升级时,ICL里的SIB绑定可能要调整;测试需求变化时,Network的拓扑可能要重新规划。把ICL当成一份活的文档来管理,而不是一次性的输入文件,能帮你避免很多后期返工。

最后分享一个小技巧:在ICL里给每个Instrument和SIB加上注释,说明它的功能、地址、所属时钟域。这些注释在工具解析时会被忽略,但对后续维护和团队协作非常有帮助。我现在的ICL文件里,注释行数几乎和代码行数一样多,但每次调试时,这些注释都能帮我快速定位问题。这个习惯,推荐你也试试。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询