SystemVerilog pre_randomize & post_randomize

使用内置的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

发布了71 篇原创文章 · 获赞 8 · 访问量 7379

猜你喜欢

转载自blog.csdn.net/qq_43042339/article/details/104587794
今日推荐