SystemVerilog中fork join_none后如何仅等待部分指定线程执行完毕
SystemVerilog指定线程等待方案
问题根因
你当前的代码存在两个不符合预期的点:
- 外层包裹for循环的
fork join仅会等待for循环本身执行完成,而for循环内部启动process_that_must_end用的是join_none,因此for循环会在瞬间启动完40个子线程后立刻结束,外层fork join也会随之解除阻塞,不会等待这些子线程执行完成。 wait fork的语义是等待当前进程的所有子线程执行完毕,你提前启动的永久运行进程也属于当前进程的子线程,因此wait fork会被永久阻塞,不符合需求。
可行方案:使用process句柄跟踪指定线程
SystemVerilog内置了process标准类,可以单独跟踪、控制单个线程的执行状态,你只需要把需要等待的线程句柄存入队列,之后逐个等待队列内的线程执行完成即可,完全不会受其他后台线程的影响。
实现代码
// 原有后台永久运行进程,逻辑保持不变 fork process_that_will_never_end(); join_none // 定义队列存储需要等待的线程句柄 process must_end_jobs[$]; for(int i = 0; i < 40; i++) begin // 必须声明automatic变量存储循环索引,避免所有线程捕获到同一个i的引用 automatic int thread_idx = i; fork begin // 记录当前线程的句柄到队列 must_end_jobs.push_back(process::self()); // 执行业务逻辑 process_that_must_end(thread_idx); end join_none end // 等待所有指定线程执行完成 foreach(must_end_jobs[idx]) begin wait(must_end_jobs[idx].status == process::FINISHED); end
核心说明
process::self()会返回当前执行线程的唯一句柄,我们仅把需要等待的线程句柄存入队列,和其他后台永久进程完全隔离- 循环内的
automatic int thread_idx是必须的:如果不加该声明,所有子线程捕获的都是同一个循环变量i的引用,执行时i已经变为40,会出现传参错误 - 该方案不会干扰后台永久进程的运行,也不需要修改原有永久进程的逻辑
内容的提问来源于stack exchange,提问作者juan
相关产品推荐
相关产品推荐

