VCD 转 WGL,真正难的不是“改格式”,而是“怎么采样”

张开发
2026/4/14 1:50:12 15 分钟阅读

分享文章

VCD 转 WGL,真正难的不是“改格式”,而是“怎么采样”
本文属于《芯片测试自动化与验证基础设施实践》专栏。聚焦芯片测试自动化、测试向量生成、WGL 处理、可综合 Testbench 与验证基础设施工程化。前面几篇文章我已经把这条主线逐步展开过了从功能测试指令出发可以通过模板化方法生成 JTAG 向量多份 WGL 合并后可以进一步组织成可综合 Testbench真正有价值的不是某一个孤立文件而是一条能复用、能扩展的测试基础设施链路但如果把视角再往前推一步就会遇到一个更具体、也更容易被低估的问题VCD 到 WGL到底是不是一个“格式转换”问题很多人第一反应会是VCD 是波形文件WGL 是测试向量文件那中间写个脚本改一下格式不就行了吗表面看这样理解似乎没问题。但真做过这类工具的人很快就会发现真正难的往往不是把一种文本改写成另一种文本而是决定到底在什么时刻把哪些信号值当成“有效向量”采出来。也就是说难点不在“输出长什么样”而在“输入应该怎样被理解”。这篇文章我就专门把这个问题拆开讲清楚。一、为什么很多人会误判 VCD - WGL 的难度VCD 文件本质上记录的是信号值变化历史。只要信号发生变化VCD 就会把那个变化记下来。所以从数据形态看VCD 更接近一串按时间排序的事件流每个时间点上某些信号发生了变化这些变化未必构成一个完整“采样点”而 WGL 更接近什么更接近在特定时刻采到的一组输入/输出状态这些状态被组织成一拍一拍可执行的测试向量最终会被 ATE 或其他测试执行平台消费这两者最大的差别不在文件后缀而在数据语义层次不同。一个是事件变化流一个是采样后的离散向量序列所以VCD - WGL的核心不是怎么把事件文本改写成另一种文本。而是怎么从事件流中恢复出真正应该被保留下来的“采样结果”。这就是为什么很多一开始看起来简单的小脚本最后都会越写越复杂。二、先改格式为什么通常会做错如果把这个问题简单理解为“逐时间展开、逐行写出”很容易掉进几个典型坑里。1. 把所有 value change 都当成有效测试点这会直接导致向量数量膨胀。原因很简单VCD 会记录所有变化包含正常功能翻转时钟跳变中间组合传播瞬态毛刺一些在测试平台上根本不该被当成独立向量的过渡值如果这些都原样写进 WGL那么生成出来的 pattern 往往既冗长又不稳定。2. 没有明确 working clock如果没有定义“哪个时钟决定采样节拍”那你根本无法知道什么时候该取一拍什么时候只是中间传播哪些变化该进入最终向量没有采样时钟所谓“向量生成”很可能就退化成“波形抄写”。3. 把输入变化和输出观测混在一起处理很多信号在 VCD 里只是“发生了变化”但在测试语义上它们并不处于同一层次。例如某些输入信号是在采样点前完成激励设置某些输出信号是在采样点上或采样点后才具有比较意义如果不区分这两类信号WGL 就很容易出现“值写上去了但语义不对”的情况。4. 忽略 x / z / 未定义态的处理ATE 或 pattern 执行环境并不总是接受“你看到什么就照抄什么”这种处理方式。对于xz未驱动状态双向口切换过程中的过渡值到底是保留、屏蔽、转成 don’t care还是转成有效位控制往往都需要明确策略。所以从工程角度说VCD - WGL从来不是一个纯粹的格式问题而是一个采样策略问题。三、真正应该先回答的问题什么叫“一拍有效向量”要把 VCD 转成 WGL最先要定义的其实不是输出格式而是下面这几个问题1. 以谁为采样基准也就是 working clock 是谁。2. 在哪个边沿采上升沿、下降沿还是某个偏移点3. 哪些信号属于输入激励这些信号在采样时刻之前应该已经稳定。4. 哪些信号属于输出观测这些信号在采样时刻才具有比较意义。5. 哪些变化只是中间传播不应进入最终向量如果这一步没定义清楚后面写出来的 WGL 即使格式正确也很可能语义错误。这也是为什么一个真正能用的转换器往往都会被拆成几个独立模块而不是一段从头扫到尾的大脚本。四、一个更合理的 VCD - WGL 处理链路结合实际工程经验一个更合理的处理流程通常会长这样VCD 文件解析时间与信号变化pad_info 或端口定义建立管脚映射识别 working clock识别输入/输出/双向管脚确定采样点提取每个采样点的管脚状态处理 x/z/无效位/过渡态组织成向量序列输出 WGL这个链路里真正决定结果质量的不是最后那一步输出 WGL而是中间这三步识别 working clock确定采样点处理无效与过渡语义也就是说采样模型比输出模板更重要。五、为什么 working clock 是整个转换器的“第一开关”在很多设计里VCD 里会同时出现很多时钟或伪时钟信号系统主时钟JTAG TCK分频时钟门控时钟内部衍生时钟异步控制脉冲如果不先确定 working clock转换器就会立刻失去统一节拍。1. working clock 决定“什么时候采”没有采样节拍就没有离散向量。2. working clock 决定“哪些变化属于同一拍”同一个采样点前后的过渡变化是否应该并入这一拍取决于你怎么定义时钟边沿与观察窗口。3. working clock 决定“输出长度”采样过密WGL 膨胀采样过疏关键信息丢失。所以 working clock 的确定不是实现细节而是整个转换策略的根。在我看到的一些脚本实现里往往也都会把时钟处理单独抽出来而不是和普通向量解析混在一起。这样做其实是非常合理的因为时钟定义的是向量的节拍不只是一个普通信号。六、为什么 pad 映射决定了“你到底在采什么”即使已经有了 working clock如果没有 pad 映射还是不够。因为 VCD 里看到的是仿真层级下的信号名最终 WGL 里关心的是哪些是测试相关 pad哪些只是内部辅助信号哪些信号是输入哪些信号是输出哪些可能是双向口这就是为什么很多工具都会额外读一个pad_info.v或类似描述文件。它的本质作用不是“补充一点名字信息”而是把仿真信号空间投影到测试向量空间。如果没有这一层转换器就很容易出现两类问题1. 采了很多不该进 pattern 的内部信号结果是生成文件巨大而且没有测试意义。2. 漏掉真正需要进入 pattern 的关键 pad结果是看起来文件生成成功但拿去执行就发现向量不完整。所以从工程结构看pad mapping 其实和 clock definition 一样属于上游“语义建模”层而不是下游“文本输出”层。七、采样点一旦确定接下来才轮到“取值”很多人写这类工具时最喜欢一开始就写“怎么把 0/1/x/z 输出成字符”。但其实在那之前更重要的是在某一个采样点上哪些值才应该被认为是这一拍的有效状态。一个更合理的处理思路通常是1. 以采样边沿为中心收集该拍前已经稳定的输入值也就是说输入更像“已设置好的激励条件”。2. 在采样边沿或指定观察窗口内读取输出值输出更像“在这一拍上需要比较的结果”。3. 过滤掉仅仅是传播过程中的短暂中间态例如某些逻辑在拍间发生的瞬时跳变如果不具备测试意义就不应该写进最终向量。这一步本质上是在做一件很重要的事把“仿真变化历史”压缩成“测试平台可执行的拍级语义”。这一步做得对不对直接决定 WGL 的可用性。八、glitch 为什么会把一个看起来“能跑”的脚本拖垮VCD 最大的一个特点就是它对变化非常诚实。这本来是优点但在做测试向量生成时也可能变成负担。因为测试平台要的通常不是“所有真实发生过的过渡”而是“对测试有意义的离散状态”。如果不处理 glitch通常会出现几种情况1. pattern 数量异常增多本来一拍应该只有一个有效向量结果因为中间抖动多写出很多条。2. 输出比较点错位某个输出在最终稳定前短暂经过若干中间值如果直接抄到 WGL就可能造成预期比较提前或错误。3. 输入与输出关系被污染原本属于同一拍的激励和响应被中间变化拆散了。所以 glitch 过滤不是“锦上添花”而是只要你想把 VCD 真正用于 pattern 生成就几乎绕不开的一步。当然具体要不要做强过滤、弱过滤或者只在采样边沿取最近稳定值要看你的目标平台和具体设计。但无论采用哪种策略前提都一样你必须先承认VCD 的原始事件流并不天然等于测试向量。九、为什么 x / z / 双向口处理会比想象中麻烦VCD - WGL在工程上另一个经常被低估的问题是状态语义转换。在 VCD 里常见状态包括01xz问题在于WGL 或测试平台并不一定按同样的方式理解它们。1.x不总是可以直接保留有时候它代表未知有时候它代表 don’t care有时候它其实意味着当前不应比较。这三种语义在测试执行中完全不是一回事。2.z常常涉及驱动方向问题尤其是双向管脚在仿真里看到z可能是当前未驱动当前处于输入状态当前处于方向切换过程如果不结合 pad 类型和当前场景来理解单纯抄值往往会出错。3. 双向口往往要求“值 有效位”一起组织这也是为什么更完整的测试向量系统里经常不只保存逻辑值还会保存哪些位有效当前方向是什么当前比较是否生效这类问题再一次说明VCD - WGL 的核心不是写字符串而是把仿真语义翻译成测试语义。十、一个真正能演进的转换器应该怎样分模块如果目标不是写一段一次性的脚本而是做成可维护、可扩展的工具我更建议把它拆成下面几层输入层VCD 解析器pad 信息解析器时钟识别与时间轴管理管脚角色建模采样点生成向量抽取与状态规整WGL 格式化输出1. 输入层负责读VCDpad 信息文件可选配置项2. VCD 解析层负责恢复时间推进信号定义value change 事件3. pad 建模层负责明确哪些 pad 进入 pattern输入/输出/双向口分类目标输出顺序4. 时钟与采样层负责working clock 识别采样边沿定义采样点生成5. 向量规整层负责采样值抽取glitch 策略x/z处理有效位组织6. WGL 输出层负责headerpad 列表vector section文本格式化这样分层的好处是每一层职责清楚后续更容易替换策略更容易从 Python 脚本演进成 C 工具更容易接到后续的 WGL 合并和 testbench 生成链路十一、为什么我一直强调先定义采样语义再谈输出格式因为从长期维护角度看真正稳定的从来不是某一种文本格式而是你如何定义“一拍测试向量”的生成规则。格式可以变今天输出 WGL明天输出内部中间格式后天接入别的 pattern 组织方式但只要你的采样语义是稳定的整个工具链就有可复用基础。反过来如果一开始只关注“文本怎么写”那就很容易出现这种情况代码写得很快文件也能生成但每换一个设计、一个时钟结构、一个双向口场景就要重写一遍这类工具最怕的不是报错而是看起来成功生成了实际上语义已经偏了。这往往比直接失败更危险。十二、从 VCD 到 WGL本质上是在做一次“语义压缩”如果用一句更抽象的话来概括我会这样定义VCD - WGL 的本质是把连续事件流压缩成离散测试向量。这个压缩过程里真正决定质量的不是打印函数而是你认为什么是一个采样点你认为什么是有效值你如何处理中间过渡态你如何把仿真层级映射到测试 pad 层级所以这件事绝不是“改格式”那么简单。它更像是上游理解仿真语义中间构造测试语义下游再把它组织成测试平台能执行的格式这也是为什么一旦把这个问题做深它很自然就会连接到更大的链路上ATE pattern 组织多 WGL 合并可综合 Testbench 生成验证加速执行框架也就是说VCD - WGL看起来只是中间一环但它本质上是整个测试基础设施链路中的一个关键翻译层。十三、结语把 VCD 转成 WGL真正考验的是你怎么定义“测试”很多工程问题表面看像格式问题做深了才发现其实是语义问题。VCD - WGL就是一个很典型的例子。如果只是想“生成个文件”也许一段脚本就够了。但如果你希望这个文件真正可执行真正可比较真正能接入 ATE 或后续验证链路真正能适配不同设计和时钟场景那你迟早都要回到最核心的问题上我到底怎样定义一个有效测试向量而这个问题的答案首先体现在working clock 怎么定采样点怎么取pad 怎么映射过渡态怎么处理。所以VCD 转 WGL真正难的不是“改格式”而是“怎么采样”。这也是为什么我认为这类工具真正的价值不在于会不会写某种输出模板而在于能不能把仿真变化历史可靠地翻译成测试平台真正需要的离散执行语义。下一篇预告下一篇我准备继续往下写《为什么 VCD-WGL 脚本最后都要重构成 C 工具》重点会展开为什么很多早期脚本都能快速起步为什么一旦进入真实工程场景就会逐渐失控一个更合理的 C 工具架构应该怎样拆为什么“可维护性”本身就是测试基础设施能力的一部分

更多文章