是否可以在单个特定类实例中禁用SystemVerilog任务?
在SystemVerilog中,可以使用是否可以在单个特定类实例中禁用SystemVerilog任务?,verilog,system-verilog,Verilog,System Verilog,在SystemVerilog中,可以使用禁用构造终止命名块或任务。但我今天发现,禁用类实例中的任务会影响所有类实例中任务的所有副本 考虑一个类,其中定义了一些任务。如果在类的内部调用了disable,这将在类的所有实例中禁用任务的所有副本。这不是我预期的行为,但根据LRM,这是正确的: 如果一项任务被启用多次,则禁用该任务应禁用该任务的所有激活 是否有一种机制或解决方法,仅在类的特定实例中禁用任务? 下面的代码突出了我面临的问题。基本上,我有一个计时器任务,我想禁用由于一些其他事件。这些都包含在
禁用
构造终止命名块或任务。但我今天发现,禁用类实例中的任务会影响所有类实例中任务的所有副本
考虑一个类,其中定义了一些任务。如果在类的内部调用了disable
,这将在类的所有实例中禁用任务的所有副本。这不是我预期的行为,但根据LRM,这是正确的:
如果一项任务被启用多次,则禁用该任务应禁用该任务的所有激活
是否有一种机制或解决方法,仅在类的特定实例中禁用任务?
下面的代码突出了我面临的问题。基本上,我有一个计时器任务,我想禁用由于一些其他事件。这些都包含在一个类中。在我的验证环境中,我有这个类的多个实例,它们完全独立运行。因此,在一个实例中禁用计时器不应影响其他实例。但是disable
的工作方式正在影响其他实例
我试图禁用这个。计时器,但没有编译
在本例中,我有两个类c
的实例,其中包含一个计时器
任务。有一个并行启动的disabler
任务调用disable timer
。本例中的目的是使计时器在计数的中途被禁用。因此,c1
将在时间5被禁用,c2
将在时间10被禁用。但是,它们在时间5都被禁用,因为源于c1
的disable timer
调用禁用了c1
和c2
中的任务
module top();
class c;
string name;
int count;
function new(string _name, int _count);
name = _name;
count = _count;
endfunction
task t1();
timer();
$display("%t %s timer completed", $time, name);
endtask
task run();
fork
t1();
disabler();
join
endtask
task timer();
$display("%t %s starting timer with count=%0d", $time, name, count);
repeat(count) #1;
endtask
task disabler();
repeat(count/2) #1;
disable timer;
endtask
endclass
class ex;
c c1;
c c2;
function new();
c1 = new("c1", 10);
c2 = new("c2", 20);
endfunction
task run();
fork
c1.run();
c2.run();
join_none
endtask
endclass
ex e = new;
initial begin
e.run();
end
endmodule
输出:
0 c1 starting timer with count=10
0 c2 starting timer with count=20
5 c2 timer completed
5 c1 timer completed
我知道我可以重写它,让它工作,而不必使用禁用
,但这是一种提前终止任务的简单方法,我希望我遗漏了一些东西 我认为这是不可能的。即使在命名块上使用disable,也会停止该任务的所有实例
禁用自动任务或自动任务内的块
对于所有并发执行的
任务
您可以尝试使用进程类。我本人从未使用过它们,因此此代码可能包含错误
class c;
process p1;
task run();
fork
begin
p1 = process::self(); //Get process of this begin..end block
$display("%t %s starting timer with count=%0d", $time, name, count);
repeat(count) #1;
end
disabler()
join_none
endtask
task disabler();
wait (p1 != null);
repeat(count/2) #1;
p1.kill();
endtask
a1类;
过程p1;
任务计时器();
p1=进程::self();
开始
而(1)
开始
$display(“示例数据%t”,$time);
#10;
结束
结束
结束任务
任务计时器2();
对于(int i=0;i<10;i++)
开始
#20;
$display(“shouldnotkilled”,i);
结束
结束任务
末级
模块示例_kill;
a1 ab,bc;
初始开始
ab=新的();
bc=新的();
叉
ab.定时器();
ab.timer2();
bc.timer();
加入
#50;
ab.p1.kill();
#100;
bc.p1.kill();
等待叉;
结束
端模
我认为任务可以在线程内部隔离。其思想是将任务隔离在线程中。您应该只对一个特定实例应用disable fork。所以你必须问问我们现在的情况。
在我们遇到问题之前,因为systemverilog不允许您
e、 g
fork
开始
你的任务呼叫;
结束
加入
如果(类\实例\禁用\成员\ id==1)开始
禁用分叉;
结束
之后,您可以再次包装前面的代码,以便仅为该任务隔离disable fork。e、 g
fork
开始
叉
开始
你的任务呼叫;
结束
加入
如果(类\实例\禁用\成员\ id==1)开始
禁用分叉;
结束
结束
加入
最后,对于要禁用的特定实例,应该从顶部将变量“class\u instance\u disable\u member\u id”设置为1(default value=0)。这可以从外部类或顶级类完成
例如top.class1.class\u实例\u禁用\u成员\u id=1强>
在调用该任务时,该任务将被禁用。因此,必须在调用之前设置“class\u instance\u disable\u member\u id=1变量”。
如果使用UVM,则可以使用阶段(在运行阶段之前构建或连接)。如果是simple systemverilog,则可以使用new()构造函数从顶部为正确的实例设置该变量
如果您想“动态/动态地”激活/停用任务,那么在调用要禁用的任务之前,应该在顶部有另一个线程/任务,该线程/任务修改特定实例的“类\实例\禁用\成员\ id”
还可以检测CaseSuthAsdixDeable成员的ID,以允许在中间杀死任务,使用以下基本块
fork
开始
你的任务呼叫;
结束
开始
如果(类\实例\禁用\成员\ id==0)开始
@(posedge类\实例\禁用\成员\ id);
结束
结束
加入任何
如果(类\实例\禁用\成员\ id==1)开始
禁用分叉;
结束
我希望有帮助
BR谢谢。我已经尝试过使用process类,但无法使其正常工作。我重新审视了这一点,并能够使其发挥作用;关键是应该终止的任务/过程需要位于它们自己的fork/join中,这样它们就处于一个单独的进程中。所以-这是可能的,但不使用禁用
。但我不确定这是否值得付出努力和复杂。
class a1;
process p1;
task timer();
p1=process::self();
begin
while(1)
begin
$display("example data %t",$time);
#10;
end
end
endtask
task timer2();
for(int i = 0; i < 10; i ++)
begin
#20;
$display("shouldnot killed",i);
end
endtask
endclass
module example_kill;
a1 ab,bc;
initial begin
ab = new();
bc= new();
fork
ab.timer();
ab.timer2();
bc.timer();
join_none
#50;
ab.p1.kill();
#100;
bc.p1.kill();
wait fork;
end
endmodule