NOTE:
- Avoid program block.
- Ensure you have a wait at the end of initial-block (inside program if you can’t stick to #1 above).
你会在项目中强制使用 SystemVerilog 的 program block 吗?这可能是许多验证工程师心中都有的疑问。它究竟是解决时序竞争问题的“银弹”,还是仅仅是语言演进过程中留下的冗余包袱?本文将深入探讨 program block 的起源、局限性与更优的替代方案。
Program Block 从何而来?
Program block 直接源自 Synopsys 将 Vera 语言捐献给 SystemVerilog 的那部分内容。它试图模仿 PLI 应用与 Verilog 仿真器交互时的调度语义。
因此,对于有 Vera 背景的工程师来说,program block 非常合理,并且确实帮助了从 Vera 过渡到 SystemVerilog 的用户。但如果你从零开始学习 SystemVerilog,它们似乎只是一种额外的语言负担。
谁会想到,我们竟然会在同一种语言内部打“语言之战”呢!
Program Block 解决了什么问题?没解决什么?
据我所知,单独使用 program block 只解决了测试平台与设计(DUT)之间的两类竞争条件,而这两类问题仅用 clocking block 也能解决:
- 顺序逻辑中错误地使用阻塞赋值:无论测试平台与 DUT 之间是否有竞争,你的 DUT 内部都会存在竞争。
- 组合门控时钟逻辑中错误地使用非阻塞赋值:同样,无论测试平台与 DUT 之间是否有竞争,你的 DUT 内部都会存在竞争。
关键在于,作为一名开发者,如果你不理解为什么上述做法会在 DUT 内部造成竞争,那么你在编写测试平台时也会遇到同样的竞争。而 program block 并不能阻止测试平台内部的这些竞争问题。这就是所谓“无竞争测试平台”所营造的虚假安全感。
为什么 Clocking Block 是更好的选择?
单独使用 clocking block 就能解决与 program block 相同的测试平台-DUT 竞争问题。此外,它还能处理由门级传播中非零延迟偏差引起的竞争。其原理是通过输入偏移进行采样,通过输出偏移进行驱动。
除了上述虚假的安全感,以及与 clocking block 的功能冗余之外,还有一些额外原因让我不推荐使用 program block:
- 遗留代码集成问题:如果你有遗留的 Verilog 测试平台代码,并希望基于“类”的测试平台调用这些传统的 BFM 任务,你会遇到棘手的时序问题。如果该任务原本设计在
active 区域调度,而现在却在 re-active 区域调度,采样会偏差一个时钟周期。如果有些任务从 program block 调用,而另一些仍从 module 调用,问题会更严重。
- 模型复用与抽象界限模糊:一个人的设计 IP 可能是另一个人的验证 IP。在系统级建模中,代表设计高层抽象的模型与测试平台部分之间的界限并不明显。不能因为一次从 program 调用,另一次从 module 调用,就出现调度语义的差异。从 program block 或 module 调用 C 代码也会遇到相同的问题。
- 仿真退出的意外行为:除非你是经验丰富的 Vera 用户,否则当仿真在 program block 中的最后一个线程结束后立刻退出时,你会感到意外。这在混合遗留测试平台或混合语言测试平台中尤其麻烦。
- 不必要的复杂性:大多数高级用户即使不使用 program block 也很难完全理解 SystemVerilog 的调度语义,为什么还要引入不必要的复杂性?许多其他环境(如 SystemC 和 VHDL)已经投产多年,却从未需要 program block 引入的这种调度机制。快速小测验:如何在同一个时间槽里得到一个断言既通过又失败的结果?
总结与思考
SystemVerilog 语言的发展凝聚了许多人的努力,包括你和我。我并非否定任何人的贡献,但有时候我们需要退一步,认识到这门语言已经变得多么臃肿。
某个特性仅仅因为写在语言参考手册中,并不代表它就一定要被使用。在构建可靠、可维护的验证环境时,理解工具背后的原理比盲目遵循惯例更重要。对于 program block,或许我们应该更清晰地认识到它的适用边界与潜在代价,而不是将其奉为圭臬。
关于验证方法学和语言特性的更多深度讨论,欢迎在云栈社区与同行们交流碰撞。
|