SV学习(9)——随机函数、数组约束、随机控制
SV學習(9)——隨機函數、數組約束、隨機控制
- 1. 隨機函數
- 1.1. pre_randomize(0和post_randomize()
- 1.2. 隨機數函數
- 1.3. 隨機化個別變量
- 2. 數組約束
- 2.1. 數組的屬性約束
- 2.2. 約束數組中的元素
- 2.3. 產生唯一元素值的數組
- 2.4. 數組約束例題
- 2.5. 隨機化句柄數組
- 3. 隨機控制
- 3.1. 隨機序列
- 3.2. 隨機控制
- 3.3. 總結
1. 隨機函數
1.1. pre_randomize(0和post_randomize()
- 有時需要在調用randomize()之前或之后立即執行一些操作,例如在隨機前設置例化的一些非隨機變量(上下限、條件值、權重),或者在隨機化之后需要計算隨機數據的誤差、分析和記錄隨機數據等
- SV提供了兩個預定義的void類型函數pre_randomize()和post_randomize()函數。用戶可以在類中定義這兩個函數,分別在其中定義隨機化前的行為和隨機化后的行為
- 如果某個類中定義了pre_randomize()和post_randomize()函數,那么對象在執行randomize()之前或者之后會分別執行這兩個函數。所以,pre_randomize()和post_randomize()函數可以看作是randomize()函數的回調函數(callback function)
1.2. 隨機數函數
- SV提供了一些常用的系統隨機函數,可以直接調用來返回隨機數值
- $random()平均分布,返回32位有符號隨機數
- $urandom()平均分布,返回32位無符號隨機數
- $urandom_range()在指定范圍內的平均分布
1.3. 隨機化個別變量
- 在調用randomize()時可以傳遞變量的一個子集,這樣只會隨機化類里的幾個變量
- 只有參數列表里的變量才會被隨機化,其他變量會被當做狀態變量而不被隨機化
- 所有的約束仍然有效
- 所有被指定或者沒有被指定rand的變量都可以作為randomize()的參數而被隨機化
【Q】
如下代碼,例化r之后,先調用r.randomize(low),那么low、med、hi的組合可能是什么?
A. low = -1, med = 0, hi = 0
B. low = -1, med = 1, hi = 2
C. low = 報錯, med = 0, hi = 0
D. low = 報錯, med = null, hi = 報錯
【An】
約束不一致,無法被解決。
讓執行r.randomize(low)的時候,med、hi沒有被隨機,默認為0,約束條件不滿足,err
2. 數組約束
2.1. 數組的屬性約束
- 在約束隨機標量的同時,還可以對隨機化數組進行約束
- 多數情況下,數組的大小應該給定范圍,防止生成體積過大的數組或者空數組
- 還可以在約束中結合數組的其他方法sum()、product()、and()、or()和xor()
2.2. 約束數組中的元素
- SV可以利用foreach對數組的每一個元素進行約束
- 針對動態數組,foreach更合適于對非固定大小數組中每個元素的約束
2.3. 產生唯一元素值的數組
- 產生一個隨機數組,它的每一個元素的值都是唯一的
方法1
class UniqueSlow;rand bit [7:0] ua[64];constraint c {foreach (ua[i]) // 對數組中的每一個元素操作foreach (ua[j])if (i != j) // 除了元素自己ua[i] != ua[j]; /// 和其他元素比較} endclass方法2
class randc8;randc bit [7:0] val; endclassclass LittleUniqueArray;bit [7:0] ua[64];function void pre_randomize ();randc8 rc8;rc8 = new();foreach (ua[i]) beginassert(rc8.randomize());ua[i] = rc8.val;endendfunction endclass說明:
rc8 = new(); 需要放在foreach循環外部,能很好的完成randc的要求,相當于一直在一副撲克牌中抽,1/255、1/254、1/253、1/252、…;如果放在里面,相當于每次抽牌都拿來一副新的撲克牌,1/255、1/255、1/255、1/255、…
2.4. 數組約束例題
class packedrand bit [3:0] da[];constraint da {da.size() inside {[3:5]};foreach (da[i])da[i] <= da[i+1];} endclassmodule test;packet p;initial beginp = new();p.randomize() with {da.size() inside {3, 5};} // 數組大小3或5end endmodule【Q】
下面哪些可能是隨機化的p.da的數組值?
A. da[0] = 0, da[1] = 2, da[2] = 4
B. da[0] = 0, da[1] = 2, da[2] = 4, da[3] = 7
C. da[0] = 0, da[1] = 2, da[2] = 4, da[3] = 7, da[4] = 10
D. 以上全錯
【An】
以上全錯。當約束da.size = 5,那么da數組的索引就是[0:4],foreach里面的循環變量i的索引就是[0:4],但進行到最后一遍循環的時候,da[4] <= da[5],da[5]索引超出范圍了,約束沖突,隨機化失敗,err。修改方案如下,
2.5. 隨機化句柄數組
- 隨機句柄數組的功能是在調用其所在類的隨機函數時,隨機函數會隨機化數組中的每一個句柄所指向的對象。因此隨機句柄數組的聲明一定要添加rand來表示其隨機化的屬性,同時在調用隨機函數前要保證句柄數組的每一個句柄元素都是非懸空的,這需要在隨機化之前為每一個元素句柄構建對象
- 如果要產生多個隨即對象,那么需要建立隨機句柄數組。和整數數組不同,需要在隨機化前分配所有的元素,因為隨機求解器不會創建對象。使用動態數組可以按照需要分配最大數量的元素,然后再使用約束減小數組的大小。在隨機化時,動態句柄數組的大小可以保持不變或縮小,但不能增加
因為RandStuff類中的變量沒有進行隨機化聲明,默認為1。
3. 隨機控制
3.1. 隨機序列
- 產生事務序列的另一個方法時使用SV的randsequence結構。這對于隨機安排組織原子(atomic)測試序列很有幫助
3.2. 隨機控制
- 可以使用randcase來建立隨機決策樹,但它帶來的問題時沒有變量可供追蹤調試
3.3. 總結
- randsequence和randcase是針對輕量級的隨機控制的應用。我們可以通過定義隨即類取代上述隨機控制的功能,并且由于類的繼承性使得在后期維護代碼時更加方便
- randsequence的相關功能我們在協調激勵組件和測試用例時,可能會用到
- randcase則應對這隨機約束中的dist權重約束+if-else條件約束的組合
總結
以上是生活随笔為你收集整理的SV学习(9)——随机函数、数组约束、随机控制的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【历史上的今天】7 月 23 日:Nov
- 下一篇: 读《当下的力量》有感