点 击 蓝 字 关 注 我 们 F P G A 之 家 - 中 国 最 好 最 大 的 F P G A 纯 工 程 师 社 群
对于许多FPGA/IC工程师而言,设计实现游刃有余,验证仿真却常成短板——传统验证方法面临两难困局:学习UVM需投入大量时间成本,而纯Verilog自仿又会陷入重复造轮子的低效循环。以通信协议仿真为例,仅报文解析就需要重写整套解析逻辑,相当于用Verilog再实现一次协议栈,耗时费力。 此时,Python的生态优势便锋芒尽显。其丰富的字符串处理库可直接解析报文,配合Cocotb框架,仅需少量Python代码即可构建高效测试平台,将验证工作量压缩70%以上。Cocotb的独特价值正在于此: 用Python解放验证生产力,让工程师专注于设计创新而非重复劳动 。
前言 在日常开发中,我们的仿真一般是串行执行的。如果想批量做回归测试,就会明显感受到速度之慢:当我们焦急等待仿真结果时,CPU 却在“摸鱼”,只有一个核心在跑,其余核心几乎闲置。这时难免会想—— 我花了几千块钱搭的配置,不是让CPU在这里摸鱼的
那 能不能把 CPU 的每一个核心都压榨起来呢?
答案是肯定的。借助 cocotb + pytest ,我们可以轻松实现多核并行仿真,最大化利用 CPU 资源。
如下图所示,图一为普通串行仿真,共 9 个 case,耗时 358.90 s;而使用 6 核并行仿真,仅用 117.03 s,速度提升足足 3 倍 。乍看只是节省了 4 分钟,但这还只是一个简单的测试用例集。若你的用例规模很大,多核可能只需 1 小时,而单核却要 3 小时甚至更久,可见效率差距巨大。
下面我将介绍如何充分压榨 CPU 的性能,并顺带介绍一下 本公众号开源 的 AFX-Cocotb-Pytest 库,让你无需繁琐配置即可开箱即用,实现真正意义上的高效并行仿真。
介绍 pytest-xdist pytest-xdist 是 pytest 的增强插件,通过 并行执行测试用例 与 分布式运行测试 来显著加速整个测试流程。
借助多进程并行、任务负载均衡以及跨机器分布式执行,它能够最大化利用 CPU 资源,特别适用于包含大量测试的大型工程。
如果希望在仿真环境中充分压榨多核性能,就需要在我们的 cocotb 测试框架中引入并配置 pytest-xdist ,以实现高效的并行仿真执行。
安装插件 pip install pytest-xdist
并行运行所有测试 pytest -n auto -n auto 会自动根据 CPU 核心数分配 worker 数量。
你也可以手动指定 worker 数:
pytest -n 8
cocotb+pytest pytest 在 cocotb 进阶专栏的《用 Python 给 Verilog 设计自仿进阶(二):实现仿真平台 Linux/Win 多平台兼容》以及《用 Python 给 Verilog 设计自仿进阶(三):FPGA 仿真,如何兼容 VCS、Iverilog、Modelsim 等多平台仿真器》中,我们已经借助 pytest 实现了跨系统、跨仿真器的批量自动化仿真。
然而,这些批量仿真仍未真正发挥出多核 CPU 的计算潜力。接下来,我将介绍如何将 pytest-xdist 融入现有 pytest 测试体系,从而实现更高效的并行仿真加速。
pytest-xdist 要实现多核并行仿真,关键在于 正确管理仿真过程中使用的文件资源 。在单核环境下,所有测试用例共用同一套文件进行仿真,彼此之间不存在竞争关系,因此不会发生读写冲突。然而,当启用多核并行时,多个 worker 可能会同时对同一文件进行增删查改,从而导致仿真过程出现竞争条件,最终引发报告错误。
对于 Verilog 仿真而言,最核心的文件包括 filelist 和 sim_build ,其中 sim_build 是仿真的实际工作目录。因此,为了保证并行仿真的独立性,我们需要根据 worker 的 ID(即每个 CPU 核心对应的 worker 进程)为它们分别创建并访问独立的 filelist 和 sim_build,从而避免任何文件级冲突。
首先获取当前worker进程的id
worker_id = os.getenv( "PYTEST_XDIST_WORKER" , "gw0" ) filelist 基于 worker ID 创建独立的 filelist 时,这里的 filelist 是通过 指定 RTL 根目录,由 Python 自动遍历所有 .v 与 .sv 文件生成的 。随后,我们根据生成的 filelist 获取文件路径,并将其传递给 cocotb_run 的 verilog_sources 。 这样做的好处在于:
1. 无需手写 filelist 只需将 RTL 文件放入指定目录,即可自动收集所有 Verilog/SV 模块,降低维护成本。 2. 生成的 filelist 可直接供波形工具使用 例如 VCS、ModelSim、Verdi 等工具可以利用 filelist 实现源码追踪(trace),无需重复配置路径。 3. 并行仿真时便于为每个 worker 创建独立 filelist 避免文件竞争问题。 如果你的项目不是通过 filelist 动态生成 verilog_sources ,而是手动指定 RTL 文件列表,那么你可以忽略这一机制。
filelist_path = Path(filelist+worker_id+ ".f" ).resolve() sim_build 在并行仿真中,每个 worker 需要使用独立的仿真工作目录( sim_build ),以避免多个进程同时读写同一目录而导致文件冲突。基于 worker ID 创建独立的 sim_build 可以这样实现:
sim_build = os.path.join(sim_path, "sim_build" , f" {safe_test_name(request.node.name)} _ {worker_id} " ) 随后,将生成的 sim_build 传递给 cocotb_run 即可让每个 worker 使用独立的仿真空间:
cocotb_test.simulator.run( python_search=[ str (tb_files)], verilog_sources=verilog_sources, toplevel=toplevel, module=module, compile_args=compile_args, sim_args=sim_args, parameters=parameters, sim_build=sim_build, extra_env=extra_env, waves=waves ) 这样即可确保每个并行任务都在自己的仿真目录中独立运行,避免竞争条件,提高并行执行的稳定性。
开源cocotb仿真环境介绍 当然,如果你觉得上述配置流程较为繁琐,也可以直接使用我提供的 afx_cocotb_test_run 库。该库的目标是 简化 pytest + cocotb 仿真环境的代码编写与配置复杂度 。 只需将该文件放在你的 Python 仿真脚本所在目录,并直接调用即可完成仿真运行。
目前该库已支持 VCS 和 Icarus 等主流仿真器。如果你需要支持其他仿真器,也可以参考我提供的 VCS 与 Icarus 示例进行扩展,非常方便。
from afx_cocotb_test_run import * 在自己的Python代码末尾加上类似下面代码的模板即可
################################################################### RUN TEST ################################################################### import os import pytest @pytest.mark.parametrize( "cycle" , [ 10 , 30 , 40 , 80 ] ) @pytest.mark.parametrize( "a" , [ 3 , 5 ] ) def test_run ( request,cycle,a ): simulator = os.environ.get( "SIM" , "" ) waves = os.environ.get( "WAVES" , "" ) parameters = {k.upper(): v for k, v in request.node.callspec.params.items()} afx_test_run(request,ctb= "cocotb_top" ,tc= "tb_top" ,wave=waves,sim=simulator,parameters=parameters)
在使用 afx_cocotb_test_run 进行仿真时,我们可以通过 afx_test_run 提供的多种参数灵活配置整个运行环境。 这些参数覆盖了仿真器选择、波形开关、测试平台路径、RTL 文件路径以及可选的参数传递等内容,使得 cocotb + pytest 的仿真流程高度可控、易扩展。
以下是 afx_test_run 支持的主要配置项:
sim: str = "vcs" , # 指定使用的仿真器,如 "vcs" 或 "icarus" wave: str = "1" , # 波形开关,1 表示生成波形,0 表示关闭 ctb: str = "cocotb_top" , # cocotb Python 顶层模块名 tc: str = "tb_top" , # Verilog/SystemVerilog 顶层 testbench 模块名 filelist: str = '../sim/filelist' , # 自动生成或指定的 filelist 路径 tests_dir: str = '../sim/' , # 工作空间路径 include_list: str = '../../design/incl' , # include 头文件目录 tb_list: str = '../../verify/tb' , # Verilog/SV/Python testbench文件路径 pkg: str = '../../design/pkg' , # package 所在目录 rtl: str = '../../design/rtl' , # RTL 源码目录 sim_ip: str = '../ip' , # 仿真依赖的 IP 文件目录 parameters: dict [ str , int ] = {} # Verilog/SystemVerilog 顶层的可配置参数 这些参数的设计使得用户可以根据自己的工程结构轻松适配,无需修改大量路径或脚本,即可快速构建 cocotb 的跨平台仿真环境,同时让 pytest-xdist 并行加速的配置更自然、易于集成。
以上述模板为例,我们将仿真器类型和是否生成波形配置为环境变量,在使用 pytest 时可以灵活指定。
WAVE= 1 SIM=vcs pytest cocotb_top.py 测试用例参数 同时,我们可以传入 RTL 顶层参数(如 parameter A )以及测试环境参数(如表示仿真时钟频率的 cycle )。
对于测试环境参数,需要特别注意: cycle 并不是直接传入 RTL,而是作为测试用例的参数,用于控制仿真时的行为,例如仿真时钟频率、数据流中反压的概率,或者其他与特定测试场景相关的设置。
例如,如果我们在测试用例中使用:
# @pytest.mark.parametrize("a", [3,5]) @pytest.mark.parametrize( "cycle" , [ 10 , 20 ] ) @pytest.mark.parametrize( "press" , [ 0.3 , 0.8 ] ) def test_run ( request,cycle,press ): parameters = {k.upper(): v for k, v in request.node.callspec.params.items()} afx_test_run(request,ctb= "cocotb_top" ,tc= "tb_top" ,wave=waves,sim=simulator,parameters=parameters) 则会生成 4 个不同的测试 case:
在 Python 脚本中,需要配合从环境变量获取参数,例如:
@cocotb.test() async def dff_simple_test ( dut ): cycle = int (os.getenv( "PARAM_CYCLE" , "20" )) press = float (os.getenv( "PARAM_PRESS" , "0.3" )) # clock await cocotb.start(generate_clock(dut,cycle, "ns" , 0 )) 这样就可以保证测试用例能够根据不同参数自动生成,并与仿真环境动态关联。
波形查看 在Python仿真文件夹下输入命令即可仿真:
WAVES= 1 pytest cocotb_top.py -v -s -n auto 在sim_build产生四个仿真结果
AdriftCore@AdriftCore:/sim_build$ ls test_run_0_3_10_gw0 test_run_0_3_20_gw1 test_run_0_8_10_gw2 test_run_0_8_20_gw3 每个仿真结果都会有其对应的波形
AdriftCore@AdriftCore:/sim_build/test_run_0_3_10_gw0$ ls cocotb_top cocotb_top.daidir cocotb_top_ucli.do com.log Makefile novas_dump.log pli.tab simulate.log tb_top.fsdb ucli.key um8pni2k_results.xml vcs_lib
链接 AFX-CocotbSIMENV 的功能不仅限于 pytest 的并行仿真,这只是其中的一部分。由于篇幅所限,这里无法一一展开说明。后续版本中,AFX-CocotbSIMENV 会将实际仿真中常用的功能封装为函数或方法集成到库中,从而减少重复操作,提高仿真效率。
https://github.com/AdriftXCore/CocotbSIMENV https://github.com/AdriftXCore/CocotbSIMENV/blob/master/verify/tb/afx_cocotb_test_run.py
欢 迎 大 家 加 入 全 国 最 大 最 强 的 F P G A 微 信 技 术 群 , 这 个 群 体 拥 有 数 万 工 程 师 、 一 群 热 爱 技 术 的 工 程 师 , 这 里 的 F P G A 工 程 师 相 互 帮 助 , 相 互 分 享 , 技 术 氛 围 浓 厚 ! 赶 紧 叫 上 小 伙 伴 一 起 加 入 吧 !
用 手 指 按 住 就 可 以 加 入 F P G A 全 国 技 术 群 哦 !
国 内 最 好 的 X i l i n x 和 a l t e r a 芯 片 供 应 商 之 一 !
平 台 自 营 , 进 口 原 装 品 质 保 证 !
持 续 供 应 多 家 军 工 研 究 所 和 上 市 公 司 !
最 好 的 F P G A 芯 片 价 格 和 最 好 的 售 后 服 务 !
拥 有 业 内 最 顶 尖 的 服 务 口 碑 !
全 球 顶 尖 供 应 商 质 量 标 准 背 书 !
X I L I N X 全 系 列 订 货 或 者 现 货 优 势 !
X C V U 9 P - 2 F L G B 2 1 0 4 I 2 0 0 P C S
X C V U 9 P - 2 F L G A 2 1 0 4 I 5 0 0 P C S
X C V U 1 3 P - 2 F L G B 2 1 0 4 I 3 0 0 P C S
X C 7 K 3 2 5 T - 2 F F G 9 0 0 I 1 5 0 0 P C S
X C 7 K 3 2 5 T - 2 F F G 6 7 6 I 9 5 0 P C S
X C 7 K 1 6 0 T - 2 F F G 6 7 6 I 8 5 0 P C S
X C 7 V X 6 9 0 T - 2 F F G 1 9 2 7 I 到 货
X C 7 V X 6 9 0 T - 2 F F G 1 7 6 1 I 到 货
更 多 赛 灵 思 型 号 需 求 请 咨 询 我 们 ! 谢 谢 ! 扫 码 二 维 码 即 可 !
F P G A 技 术 群 官 方 鸣 谢 品 牌 : X i l i n x 、 i n t e l ( A l t e r a ) 、 m i c r o s e m i ( , A c t e l ) 、 L a t t I C e , V a n t i s , Q u i c k l o g i c , L u c e n t 等 对 技 术 群 的 支 持 !