randomize 制約 implication(->) , if , solve

implication(->)

「->」は expressionが真であれば、constraint_setを満たす。偽ならdont careの場合に使用します。

expressionが真であればconstraint_setを行う。(constraint_setを満たす) 
expression -> constraint_set 

記述例

「a00が5より大きな数値であれば、b00はa00より小さい値にする」制約です。

class c_imp ;
  rand bit [3:0] a00,b00 ;
  constraint C01 {a00>5 -> b00<a00 ; }
endclass

module test () ;
  c_imp class00 ;
   initial begin
     class00 = new() ;
     for (int iiii=0;iii<10;iii++) begin
       class00.randomize() ;
       $display("a00=%3d b00=%3d",class00.a00,class00.b00) ;
     end
   end
endmodule

実行結果

10回志向した結果です。a00が12、14、6、14のときにb00の値がそれぞれ1、8、3、12となっていることが確認できました。

a00=  4 b00= 13
a00=  3 b00=  3
a00=  1 b00= 13
a00=  2 b00=  5
a00=  4 b00=  0
a00= 12 b00=  1
a00= 14 b00=  8
a00=  6 b00=  3
a00=  5 b00= 12
a00= 14 b00= 12

if-else

“->”にさらにそうでなければ別のことを設定したい場合には”if-else”を使用します。

expressionが真であれば、constraint1_setを実行、expressionが偽であればconstraint2_setを実行
if (expression) constraint1_set
else            constraint2_set 

実行例

a00とb00は4ビット信号、a00が10より大きな値のときはb00は10、それ以外はb00は1にする制約を行う例です。

class_if ;
  rand bit [3:0] a00,b00 ;
  constraint C1 {
    if(a00>10)
      b00==10 ;
    else
      b00==1 ;
  }
endclass

module test () ;
  c_if class00 ;

  initial begin
  class00 = new( ) ;
    for(int iii=0;iii<10;iii++) begin
      class00.randomize() ;
      $display("a00=%d b00=%d",class00.a00,class00.b00) ;
    end
  end
endmodule

実行結果

制約通りの結果が確認できました。

a00= 11 b00= 10
a00= 11 b00= 10
a00= 13 b00= 10
a00= 13 b00= 10
a00= 0 b00= 1
a00= 10 b00= 1
a00= 1 b00= 1
a00= 10 b00= 1
a00= 14 b00= 10
a00= 15 b00= 10

else if

if と elseの間にelse ifも制約条件で利用できます。

以下の例では、a00が10以下で5より大きい場合はelse ifの条件となり、b00に5を設定します。

(module部分は前回と同様の記述)

class_if ;
rand bit [3:0] a00,b00 ;
constraint C1 {
if(a00>10)
b00==10 ;
else if (a00>5)
b00==5 ;
else
b00==1 ;
}
endclass

実行結果

a00= 11 b00= 10
a00= 11 b00= 10
a00= 13 b00= 10
a00= 13 b00= 10
a00= 0 b00= 1
a00= 10 b00= 5
a00= 1 b00= 1
a00= 10 b00= 5
a00= 14 b00= 10
a00= 15 b00= 10

複数の変数に対して制約

もう一つ変数を追加した例です。同じ条件で別々の変数にそれぞれ設定したい場合は、”&”記号でつなぎます。

class_if ;
  rand bit [3:0] a00,b00,c00 ;
  constraint C1 {
  if(a00>10)
    b00==10 & c00==5;
  else if (a00>5)
    b00==5 & c00==10;
  else
    b00==1 & c00 ==1;
  }
endclass

module test () ;
・・・
$display("a00=%3d b00=%3d c00=%3d",class00.a00,class00.b00,class00.c00) ;
・・・
endmodule

実行結果

a00= 11 b00= 10 c00=  5
a00= 11 b00= 10 c00=  5
a00= 13 b00= 10 c00=  5
a00= 13 b00= 10 c00=  5
a00=  0 b00=  1 c00=  1
a00= 10 b00=  5 c00= 10
a00=  1 b00=  1 c00=  1
a00= 10 b00=  5 c00= 10
a00= 14 b00= 10 c00=  5
a00= 15 b00= 10 c00=  5

solve a before b

-> やif文などの制約を付加する前に条件に利用する変数をランダマイズする場合に使用します。

例えば、”constraint C00 {a00>5 -> b00>5 ; }”のようにa00が5より大きい場合にb00も5より大きい値であると設定する場合、b00が確定するためには事前にa00がランダムされ確定されている必要があります。

その場合”constraint C01 {solve a00 before b00 ; }”を追加することで明示的にa00の値をb00の設定前に設定することを表しています。(なくてもうまくいくときもあります)

constraint C01 {solve b00 before a00 ; }”としてしまうと、b00がa00より先に値が決定するため、2つ目の制約C02 の制約は無効となります。

class c_solve ;
  rand [3:0] a00,b00 ;
  constraint C01 {solve b00 before a00 ; }
  constraint C02 {a00>5 -> b00>5 ; }
endclass

module test () ;
  c_solve class00 ;

  initial begin
    class00 = new() ;
    for(int iii=0;iii<10;iii++) begin
      class00.randomize() ;
      $display("a00=%3d b00=%3d",class00.a00,clas00.b00) ;
    end
  end
endmodule

実行結果

b00=4のとき、a00=6となり、制約C02に合っていません。これは先にC01が実行され、b00の値が6に決定した後にa00がランダム生成され4になったためです。

a00=  3 b00=  4
a00=  0 b00=  3
a00=  5 b00=  1
a00=  2 b00=  2
a00=  3 b00=  4
a00=  7 b00= 12
a00=  5 b00= 14
a00= 13 b00=  6
a00=  4 b00=  6
a00= 12 b00=  6

”class00.randomize() ;”の前に”class00.C01.constraint_mode(0);” を追加し、制約を

OFFにして実行すると、a00>5のときはb00>5となっていることが確認できました。

a00=  4 b00= 13
a00=  3 b00=  3
a00=  1 b00= 13
a00=  2 b00=  5
a00=  4 b00=  0
a00= 12 b00=  6
a00= 14 b00=  8
a00=  6 b00=  6
a00=  6 b00= 11 
a00=  6 b00= 15

コメント

Copied title and URL