我正在尝试一些应该阻塞的代码,直到移动到新的模拟时间步长(类似于在 e 中等待 sys.tick_start
)。
我尝试编写一个执行此操作的函数:
task wait_triggered();
event e;
`uvm_info("DBG", "Waiting trig", UVM_NONE)
-> e;
$display("e.triggered = ", e.triggered);
wait (!e.triggered);
`uvm_info("DBG", "Wait trig done", UVM_NONE)
endtask
它背后的想法是我触发了一些事件,这意味着它的
triggered
当控制到达 wait(!e.triggered)
行时,字段将为 1 .当 triggered
时,这条线路应该在下一个时隙解除阻塞将被清除。为了测试这一点,我添加了一些其他消耗模拟时间的线程:
fork
wait_triggered();
begin
`uvm_info("DBG", "Doing stuff", UVM_NONE)
#1;
`uvm_info("DBG", "Did stuff", UVM_NONE)
end
join
#1;
$finish(1);
我看到消息正在做东西和做了东西,但等待触发完成从未出现。模拟也会在到达
finish(1)
之前停止。 .一位模拟器告诉我,这是因为没有安排更多的事件。所有模拟器都表现出相同的行为,所以一定有我遗漏的东西。谁能解释一下这是怎么回事?
最佳答案
问题出在 wait (!e.triggered);
当e.triggered
正在从 1 变为 0。它必须在一个什么都不能调度的区域发生变化,所以它是在当前时隙结束时发生变化,还是在下一个时隙开始时发生变化是不可观察的。所以wait
将挂起等待当前时间段的结束,该时间段永远不会到来。
我认为与您要查找的内容最接近的是 #1step
.这会阻止最小的仿真精度时间步长。但是我必须相信有一种更好的方法可以编写您想要的代码,而无需知道时间是否在前进。
关于system-verilog - 关于 event.triggered 使用的困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35624138/