You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Python cocotb测试中正确使用多进程并行执行循环迭代?

问题分析与解决方案

你的核心问题在于:cocotb的协程(带@coroutine和yield的函数)依赖主进程的仿真事件循环驱动,而multiprocessing.Process启动的子进程没有这个事件循环,也无法访问主进程的DUT对象,导致协程里的host.run_test根本不会被执行。下面给出两种可行的解决思路:


方案一:多进程启动独立仿真实例(适合CPU密集型任务)

直接在cocotb测试外部用多进程启动多个独立的仿真,每个仿真处理一部分迭代任务。这种方式是真正的并行,每个进程对应一个完整的仿真环境。

1. 编写并行启动脚本

# run_parallel.py
from multiprocessing import Process
import os

def run_sim(start_idx, end_idx, arg1, arg2):
    # 通过环境变量传递参数给cocotb测试
    os.environ['START_IDX'] = str(start_idx)
    os.environ['END_IDX'] = str(end_idx)
    os.environ['ARG1'] = str(arg1)
    os.environ['ARG2'] = str(arg2)
    # 启动仿真(根据你的仿真器调整命令,比如Verilator/VCS)
    os.system("make SIM=verilator")

if __name__ == "__main__":
    N = 100  # 总迭代数
    n_processes = 4  # 并行进程数
    arg1 = "your_arg1"
    arg2 = "your_arg2"
    
    processes = []
    step = N // n_processes
    for i in range(n_processes):
        start = i * step
        # 最后一个进程处理剩余的迭代
        end = start + step if i != n_processes-1 else N
        p = Process(target=run_sim, args=(start, end, arg1, arg2))
        processes.append(p)
        p.start()
    
    # 等待所有进程完成
    for p in processes:
        p.join()

2. 修改cocotb测试代码

from cocotb.decorators import coroutine
from cocotb.test import TestFactory
import os

@coroutine
def Run(dut):
    # 从环境变量读取参数
    start_idx = int(os.environ['START_IDX'])
    end_idx = int(os.environ['END_IDX'])
    arg1 = os.environ['ARG1']
    arg2 = os.environ['ARG2']
    
    # 处理分配到的迭代任务
    for i in range(start_idx, end_idx):
        ret = yield host.run_test(arg1, arg2)

factory = TestFactory(Run)
factory.generate_tests()

方案二:用cocotb内置协程并发(适合IO密集型任务)

如果你的host.run_test是IO密集型(比如等待外部设备、文件读写),可以用cocotb自带的fork启动多个协程并发执行,这是单进程内的并发,不需要跨进程,能充分利用IO等待时间。

from cocotb.decorators import coroutine
from cocotb.test import TestFactory
from cocotb.triggers import join

@coroutine
def run_coroutine(arg1, arg2, iterations):
    for i in range(iterations):
        ret = yield host.run_test(arg1, arg2)

@coroutine
def Run(dut, arg1, arg2):
    N = 100
    n_coroutines = 4
    step = N // n_coroutines
    
    coros = []
    for i in range(n_coroutines):
        # 分配每个协程的迭代数
        iters = step if i != n_coroutines-1 else N - (i*step)
        # 用fork启动协程
        coro = cocotb.fork(run_coroutine(arg1, arg2, iters))
        coros.append(coro)
    
    # 等待所有协程执行完成
    yield join(*coros)

factory = TestFactory(Run)
factory.generate_tests()

为什么你的原方案不行?

  1. 协程驱动问题:带@coroutine的函数返回生成器,必须由cocotb的主事件循环迭代才能执行,子进程没有这个循环,生成器永远不会被触发。
  2. DUT对象隔离:仿真器的DUT实例绑定在主进程,子进程无法访问,任何涉及DUT的操作都会失败。

内容的提问来源于stack exchange,提问作者sammy17

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.23 02:24:22