使用内置的randomize()方法随机化类中声明为rand或randc的覆盖变量。如果随机化成功,则该方法返回1;如果随机化失败,则返回0。它可能会因为各种各样的原因而失败,比如约束冲突、求解器不能给出一个满足所有约束的值等等。类对象不是自动随机化的,因此我们应该总是调用randomize()方法来进行随机化。
Syntax
virtual function int randomize ();
让我们看一个简单的示例,看看如何调用randomize()。
class Beverage;
rand bit [7:0] beer_id;
constraint c_beer_id { beer_id >= 10;
beer_id <= 50; };
endclass
module tb;
Beverage b;
initial begin
b = new ();
$display ("Initial beerId = %0d", b.beer_id);
if (b.randomize ())
$display ("Randomization successful !");
$display ("After randomization beerId = %0d", b.beer_id);
end
endmodule
Simulation Log
run -all;
# KERNEL: Initial beerId = 0
# KERNEL: Randomization successful !
# KERNEL: After randomization beerId = 25
# KERNEL: Simulation has finished. There are no more test vectors to simulate.
在计算随机值之前和之后,randomize()会自动调用一些回调函数。
pre_randomize()
此函数在同一类中定义,该类的对象将被随机化并在randomization()之前调用。
function void pre_randomize();
例
我们将pre_randomize()函数添加到前面讨论的示例中。
class Beverage;
rand bit [7:0] beer_id;
constraint c_beer_id { beer_id >= 10;
beer_id <= 50; };
function void pre_randomize ();
$display ("This will be called just before randomization");
endfunction
endclass
Simulation Log
run -all;
# KERNEL: Initial beerId = 0
# KERNEL: This will be called just before randomization
# KERNEL: Randomization successful !
# KERNEL: After randomization beerId = 25
# KERNEL: Simulation has finished. There are no more test vectors to simulate.
post_randomize()
此函数也在同一类中定义,该类的对象将被随机化,并在randomization()之后调用。
function void post_randomize();
例
我们将在前面讨论的示例中添加一个post_randomize()函数。
class Beverage;
rand bit [7:0] beer_id;
constraint c_beer_id { beer_id >= 10;
beer_id <= 50; };
function void pre_randomize ();
$display ("This will be called just before randomization");
endfunction
function void post_randomize ();
$display ("This will be called just after randomization");
endfunction
endclass
Simulation Log
run -all;
# KERNEL: Initial beerId = 0
# KERNEL: This will be called just before randomization
# KERNEL: This will be called just after randomization
# KERNEL: Randomization successful !
# KERNEL: After randomization beerId = 25
# KERNEL: Simulation has finished. There are no more test vectors to simulate.
Override覆写
我们之前所做的是使用我们自己的定义覆盖现有的空pre_randomize()和post_randomize()方法。 这是更改对象随机特性的一种好方法。 如果该类是派生类,并且两个方法都不存在用户定义的实现,则这两个方法将自动调用其超函数。
请注意,pre_randomize()和post_randomize()并非虚拟的,但表现为虚拟方法。 如果尝试手动将它们虚拟化,则可能会遇到如下所示的编译器错误。
class Beverage;
rand bit [7:0] beer_id;
virtual function void pre_randomize ();
$display ("This will be called just before randomization");
endfunction
endclass
Simulation Log
virtual function void pre_randomize ();
|
ncvlog: *E,CLSMNV (testbench.sv,7|36): The pre_randomize() method cannot be declared virtual
请注意以下几点:
【1】如果randomize()失败,则不调用post_randomize();
【2】randomize()方法是内置的,不能被覆盖;
【3】如果随机化失败,则变量将保留其原始值,并且不会被修改;
参考文献:
【1】https://www.chipverify.com/systemverilog/systemverilog-randomization-methods