1. 程式人生 > >第六章:隨機化

第六章:隨機化

gin fat 偽隨機數發生器 偽隨機 運行 合成 內嵌 想要 ini

隨著設計變得越來越復雜,要想產生一個完整的激勵集來測試設計的功能也變得越來越困難。采用受約束的隨機測試法(CRT)自動產生測試集是目前的一種主要的方法。CRT由兩部分組成:使用隨機的數據流為DUT產生輸入的測試代碼,以及偽隨機數發生器的種子。

6.1 什麽需要隨機化

在產生隨機化的激勵時,我們最容易想到的就是使用$random函數。但是這種方法找bug的能力是十分有限的,它只能找到數據路徑的問題,或者是bit級別的錯誤。從某種意義上講,這種方法還是基於定向測試。那些具有挑戰性的bug大都在控制路徑裏面。因此,必須對DUT裏所有關鍵點都采用隨機化技術。隨機化使控制路徑裏每一個分支都可能被測試。

你需要考慮設計輸入下列的各個方面。

  • 器件配置
  • 環境配置
  • 原始輸入數據
  • 封裝後的輸入數據
  • 協議異常
  • 延時
  • 事務狀態
  • 錯誤和違規

    6.2 SystemVerilog中的隨機化

    基於OOP使用SystemVerilog中的隨機激勵產生是最有效的。首先,建立一個具有一組相關的隨機變量的類,然後用隨機函數為這些變量賦隨機值,你可以用約束來限制這些隨機值的範圍,使他們是有效的值,也可以某些專用的功能。
    技術分享圖片
  • rand:每次隨機化這個類,這些變量都會賦一個值。就好像擲骰子,每擲一次就產生一個新的數字。
  • randc:表示周期性隨機。就好像從一副牌裏一張一張地、隨機抽出所有的牌,洗牌後再按另一個順序隨機地抽出牌。
  • constraint:約束的條件放在{}裏面,而不是begin---end裏面。
  • randomize():函數遇到約束方面的問題時,返回0.如果隨機化成功則返回1.
  • assert:判斷隨機化有沒有成功。
  • $fatal:用來結束仿真。
    註意:
    1、不能在類的構造函數裏隨機化對象。
    2、constraint中受到約束的變量必須是聲明成rand或者randc類型。

    6.2.1 簡單的表達式

    在一個表達式中最多只能使用一個關系操作符。

        class order;
               rand bit[7:0] lo,med,hi;
               constraint bad {lo<med<hi;}
        endclass

    lo<med<hi會被劃分成(lo<med)<hi,(lo<med)會得到一個布爾函數值0或1,然後與hi相比較。顯然結果並不是我們想要的。正確的寫法如下:

       class order;
               rand bit[7:0] lo,med,hi;
               constraint good {lo<med;
                                med<hi;}
      endclass
    6.2.2 權重分布
    dist操作符允許產生權重分布,這樣的話某些值得選取機會就會比其他值大一些。
  • :=表示值範圍內的每一個值得權重是相同的。
  • :/表示權重要均分到值範圍內的每一個值。
  • 值可以是一個值,也可以是一個範圍,例如[lo:hi]

       class test;
          rand int src,dst;
          constraint c {
                         src dist {0:=40,[1:3]:=60;}
                         dst dist {0:/40,[1,3]:/60;}
                              }
        endclass

    src=0 40/220
    src=1 60/220
    src=2 60/220
    src=3 60/220
    dst=0 40/100
    dst=1 20/100
    dst=2 20/100
    dst=3 20/100

    6.2.3 集合成員和inside運算符

    可以用inside運算符產生一個值的集合。

       class test;
          rand int src;
          constraint c {
                         src inside {[0:3]};
                              }
       endclass
  • inside {lo:hi};lo<hi,否則的話為空集;
  • $,可以代表取值範圍的最大值和最小值;
  • !取反操作符可以選取集合範圍之外的數據;

    6.2.4 在集合裏使用數組
    技術分享圖片
    技術分享圖片
  • 對數組裏面的每一個值的取值的概率都相等。

    6.2.5 條件約束

    通常約束塊裏所有的約束表達式都是有效的,但怎樣才能只讓一個表達式在某些情況下有效呢?SystemVerilog支持兩種關系操作符:->和if-else。

      class BusOp;
             ......
      constraint c {(io_space_mode) ->
                   addr[31]==1‘b1;
                  }

    if-else並不是包含在begin-end塊中,而是放在constraint的{}中。

    6.2.6雙向約束

    約束塊並不想自上而下執行的程序性代碼,它們是聲明性代碼,是並行的,所有的約束表達式同時有效。
    就算是在條件約束中,if-else語句中,並不是if中的語句成立才執行才執行下一條語句,而是所有的語句事先都已經知道。

    6.3 解的概率

    提到隨機,那麽概率必然與之相隨。SystemVerilog並不能保證求解器能夠給出確定的解,但是我們可以幹預解得概率分布。

    6.4 控制多個約束塊

    在一個類中可以包含多個約束塊。那麽我們應該如何去控制這些約束呢?
    在運行期間,可以使用constraint_mode()函數來打開或者關閉約束。

       class Test;
          rand int src;
          constraint c {
                         src inside {[0:3]};
                              }
         constraint c_1 {
                         dst inside {[0:3]};
                              }
        endclass
    
     Test t;
       initial begin
         t=new();
        t.c.constraint_mode(0);//關閉c
        assert(t.randomize());
        t.constraint_mode(0); //關閉所有的限制c和dst
        t.c_1.constraint_mode(1);//打開c_1這個約束
  • t.c.constraint_mode(0);//關閉c
  • t.constraint_mode(0); //關閉所有的限制c和dst
  • t.c_1.constraint_mode(1);//打開c_1這個約束

    6.5 內嵌約束

    SystemVerilog允許使用randomize()with來增加額外的約束,這和在類裏增加約束是等效的。

     class Test;
          rand int src;
          constraint c {
                         src inside {[0:3]};
                              }
       endclass
    
    Test t;
     initial begin
        t=new();
     assert(randomize() with {src>2});
    end

    註意:在此處,with{}語句裏面類似於作用域,但是使用了變量src而不是t.src.

第六章:隨機化