精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

教你如何寫出性能更高的SystemVerilog代碼

冬至子 ? 來源:CSDN ? 作者:谷公子 ? 2023-07-26 17:31 ? 次閱讀

本文旨在幫助大家降低在編碼過程中寫出低性能和耗內存的概率,只要大家在寫代碼時稍注意下,積少成多。當然,使用代碼分析工具也可以調試優化代碼的性能,它可以分析出代碼中性能和內存消耗的問題,如果這些地方可以重構,那么代碼也可以得到改進。但在沒有分析工具的情況下,可視化代碼檢查是必需。

1. 循環

循環的性能是由以下因素決定:

  • 循環內進行的工作;
  • 在循環中進行的檢查,以確定它是否可以退出;

在循環內進行的工作應該保持在最低限度,并且對循環邊界進行的檢查應該具有最低的開銷。典型例子如下:

例子1:在循環開始之前將變量設置為數組的大小,可以節省每次迭代時計算a.size()的開銷。

// Lower Performance Version
int a[];
int total = 0;
for(int i = 0; i < a.size(); i++) begin
    total += a[i];
end
// Higher Performance Version
int a[];
int a_size;
int total = 0;
a_size = a.size();
for(int i = 0; i < a_size; i++) begin
    total += a[i];
end

例子2:在循環中搜索數組的特定值,一旦找到就可以終止循環了。

// Lower Performance Version
int a[50];
int find = -1;
// Look up an index via the array:
foreach(a[i]) begin
    if(a[i] == 20) begin
        find = i;
    end
end
// Higher Performance Version
int a[50];
int find = -1;
// Look up an index via the array:
foreach(a[i]) begin
    if(a[i] == 20) begin
        find = i;
        break;
    end
end

例子3:在每次循環迭代時查找關聯數組中的值是不必要的,因為它可以在循環開始時查找。另外在小數組方面,foreach()循環結構通常比for(int i = 0;i

// Lower Performance Version
int a[];
int b[string];
foreach ( a[i] ) begin
    total += a[i] * b["yes"];
end
// Higher Performance Version
int a[];
int b[string];
int t = b["yes"];
foreach ( a[i] ) begin
    total += a[i] * t;
end

2. 決策

在邏輯或算術基礎上做決策時,有許多優化可以幫助提高性能。

一旦發現邏輯表達式的一個元素為假,就放棄對它的求值,它可以加快決策的速度,因此邏輯表達式中各個運算數的排序可以避免不必要的性能開銷,如下例子:

例子1:對于AND求值,如果表達式的第一項為假,則跳過求值的其余部分。

if(A && B && C) begin
    // do something
end

例子2:對于OR求值,如果表達式的第一項為真,則跳過求值的其余部分。

if(A || B || C) begin
    // do something
end

例子3:如果表達式中的各項具有不同級別的性能開銷,則應該對這些項進行排序,首先計算開銷最小的項。

// Lower Performance Version
if((B.size() > 0) && B[$] == 42 && A) begin
    // do something
end
// Higher Performance Version
if(A && (B.size() > 0) && B[$] == 42) begin
    // do something
end

優化算術運算也可以實現優化,這不僅適用于決策邏輯,也適用于計算變量。如下例子避免了一個乘法操作。

// Lower Performance Version
if(((A*B) - (A*C)) > E) begin
    // do something
end
// Higher Performance Version
if((A*(B - C)) > E) begin
    // do something
end

如果知道決策樹中條件的相對頻率,則將最頻繁出現的條件移到樹的頂部,這最常應用于case語句和嵌套if語句。

例子1:大多數情況下,case語句在一次檢查后退出,節省了進一步的比較。

// Lower Performance Version
// Case options follow the natural order:
case(char_state)
    START_BIT:  // do_something to start tracking the char (once per word)
    TRANS_BIT:  // do something to follow the char bit value (many times per word)
    PARITY_BIT: // Check parity (once per word, optional)
    STOP_BIT:   // Check stop bit (once per word)
endcase
// Higher Performance Version
// case options follow order of likely occurrence:
case(char_state)
    TRANS_BIT:  // do something to follow the char bit value (many times per word)
    START_BIT:  // do_something to start tracking the char (once per word)
    STOP_BIT:   // Check stop bit (once per word)
    PARITY_BIT: // Check parity (once per word, optional)
endcase

例子2:如果ready無效,則不會計算其余代碼,然后進行read_cycle檢查,這樣就不需要進行write_cycle檢查了。

// Lower Performance Version
// ready is not valid most of the time
// read cycles predominate
if(write_cycle) begin
    if(addr inside {[2000:10000]}) begin
        if(ready) begin
            // do something
        end
    end
end
else if(read_cycle) begin
    if(ready) begin
        // do something
    end
end
// Higher Performance Version
// ready is not valid most of the time
// read cycles predominate
if(ready) begin
    if(read_cycle) begin
        // do something
    end
    else begin
        if(addr inside {[2000:10000]}) begin
        // do something
        end
    end
end

3. 方法調用

task和function統稱為method(方法)。在某些情況下,重構調用方法的代碼會更好,以便將方法的內容展開直接放到代碼中,而不是使用方法調用。如果方法相對較短并且有多個參數,那更可以提升性能了。

在Systemverilog中,通過在task或function調用開始時復制變量,然后將方法執行期間所做的任何更改結果復制回去,來完成向task和function傳遞參數的功能。如果參數是復雜的變量類型(如字符串或數組),那么這可能會造成相當大的開銷,而另一種選擇是使用引用(ref)。使用ref節省了參數傳遞拷貝的開銷,如果變量在任務或函數中被更新,則它不會被復制到函數中,因此它也會在調用方法中被更新。如果不想讓它被更新,可以讓變量為const ref,這將使其稱為只讀引用的。例子如下,在性能較低的代碼版本中,將一個int類型隊列和一個字符串復制到函數中。隨著隊列長度的增長,將會影響到更多的性能和內存。而在高性能版本中,int類型隊列和string參數都是引用,這避免了復制操作并加快了函數的執行速度。

// Lower Performance Version
function void do_it(input int q[$], input string name);
    // ...
endfunction: do_it
// Higher Performance Version
function void do_it(ref int q[$], ref string name);
    // ...
endfunction: do_it

4. 數組

SystemVerilog有許多具有不同特征的數據類型,在使用時需要考慮哪種類型的數組最適合。如下列出了這些數組的特性。

image.png

例如,使用關聯數組而不是使用靜態數組對只有稀疏條目的大型內存空間進行建模可能更有效。但是,如果關聯數組由于條目的數量而變得很大,那么使用固定數組來建模內存空間將變得更有效。

在關聯數組的使用中,可能會使用未添加到數組的索引進行訪問,例如稀疏內存。當關聯數組獲得超出范圍的訪問權限時,默認情況下它將返回一條警告消息以及一個未初始化的值。為了避免這種情況,可以查詢數組以確定索引是否存在,如果不存在,則不進行訪問。如果使用默認變量語法,那么可以通過性能改進來避免這項工作,例子如下:

// Lower Performance Version
// Associative array declaration - no default value:
int aa[int];
if(aa.exists(i)) begin
    lookup = aa[i];
end
// Higher Performance Version
// Associative array declaration - setting the default to 0
int aa[int] = {default:0};
lookup = aa[i];

5. 類

在Systemverilog中,類封裝了屬性(數據變量)和對這些屬性進行操作的方法。可以擴展類以添加更多變量,并添加或擴展現有方法以提供新功能。所有這些便利和功能帶來了性能開銷,可以通過以下方法來優化。

盡量減少創建對象的數量,因為每構造一個對象可能會有一個與之相關的開銷。如下優化例子:

// Lower Performance Version
function chi_class get(chi_state_t chi_state);
    chi_class chi_txn = new();
    if ( chi_state == ON ) begin
        // ...
    end
    return null;
endfunction : get
// Higher Performance Version
function chi_class get(chi_state_t chi_state);
    chi_class chi_txn;
    if ( chi_state == ON ) begin
        chi_txn = new();
        // ...
    end
    return chi_txn;
endfunction : get

直接對變量賦值比調用set()/get()方法更快,調用方法來更新或檢查變量比通過類層次路徑直接訪問帶來更高的開銷。普通的OOP準則建議類中的數據變量只能通過方法訪問。使用直接類層次路徑訪問變量可以提高性能,但可能會降低代碼的可重用性,并且依賴于用戶知道所討論的變量的名稱和類型的假設。具體情況需要具體分析。

class name;
    int A;
    function void set_A(int value);
        A = value;
    endfunction: set_A
endclass : name
// Lower Performance Version
name m = new();
m.set_A(1);
// Higher Performance Version
name m = new();
m.A = 1;

另外在類中調用方法會帶來開銷,嵌套或將方法調用鏈接在一起也會增加開銷,在實現或擴展類時,盡量減少所涉及的方法嵌套層次。

6. 隨機約束

隨機約束生成是SystemVerilog中最強大的功能之一。在類中編寫受約束的隨機代碼時,需要考慮以下幾點:

  • 除非必須,要盡量減少隨機函數的調用;
  • 盡量減少rand變量的數量,如果一個值可以從其它隨機變量中計算出來,那么它不應該被定義為rand;
  • 使用最小的數據類型,比如能用bit就不用logic,并將數據位寬調整到所需要的最小值;
  • 使用分層類結構來減少隨機化;
  • 避免在約束中使用算術運算符;
  • 隱含運算符是雙向的,使用solve before來強制前項的概率分布;
  • 使用pre_randomize()方法預先設置或預先計算隨機化過程中使用的狀態變量;
  • 使用post_randomize()方法來計算依賴于隨機變量的變量值;

7. 覆蓋率

Covergroup基本上是一組計數器,當采樣值與bin匹配時,計數器會增加,覆蓋率提升性能的方法是盡可能使用covergroup。Covergroup的基本規則是管理采樣bins的創建和covergroup的采樣。

每個coverpoint自動轉換為一組bins或計數器,用于在覆蓋點中采樣的變量的每個可能值。這相當于2n個bins,其中n是變量中的位數,但這通常被SystemVerilog auto_bins_max變量限制為最多64個bins。在寫covergroup時要仔細分析,在目的達到的基礎上,盡量減少創建bins的數目,有助于提供性能。另外,在控制采樣時刻上要盡量在期望的行為發生時去調用sample,而不是在每個時鐘沿。

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 編碼器
    +關注

    關注

    45

    文章

    3595

    瀏覽量

    134149
  • 計數器
    +關注

    關注

    32

    文章

    2253

    瀏覽量

    94352
  • 運算器
    +關注

    關注

    1

    文章

    163

    瀏覽量

    16563
  • Verilog語言
    +關注

    關注

    0

    文章

    113

    瀏覽量

    8213
收藏 人收藏

    評論

    相關推薦

    何為高質量的代碼如何寫出高質量代碼

    懂得“數據結構與算法” 寫出高效的代碼,懂得“設計模式”寫出高質量的代碼
    發表于 08-02 09:44 ?777次閱讀
    何為高質量的<b class='flag-5'>代碼</b>?<b class='flag-5'>如何寫出</b>高質量<b class='flag-5'>代碼</b>?

    如何寫出好的代碼?高質量代碼的三要素

    膾炙人口的詩"春有百花秋有月,夏有涼風冬有雪",意境唯美,簡明易懂。好的代碼也是讓人陶醉的,那么如何寫出好的代碼
    的頭像 發表于 01-05 11:29 ?1183次閱讀
    <b class='flag-5'>如何寫出</b>好的<b class='flag-5'>代碼</b>?高質量<b class='flag-5'>代碼</b>的三要素

    如何寫出時序最優的HDL代碼如何寫出時序裕量足夠的代碼

    你想寫出可以跑出700M以上的代碼嗎,直逼FPGA內部PLL的極限。
    的頭像 發表于 03-12 09:59 ?804次閱讀
    <b class='flag-5'>如何寫出</b>時序最優的HDL<b class='flag-5'>代碼</b>?<b class='flag-5'>如何寫出</b>時序裕量足夠的<b class='flag-5'>代碼</b>?

    如何寫出可以讓人理解的代碼(以verilog語言為例)?

    如何寫出可以讓人理解的代碼(以verilog語言為例)?1. 代碼要比較好理解,最容易做到的就是把代碼寫短,因此在每個always語句塊盡可能只處理一個信號,或者只處理一組相關度很高的
    發表于 02-01 11:39

    round robin 的 systemverilog 代碼

    大家好,我對一個 round robin 的 systemverilog 代碼有疑惑。https://www.edaplayground.com/x/2TzD代碼第49和54行是怎么解析呢 ?
    發表于 03-14 19:16

    如何寫出高效并且簡潔易于閱讀的單片機C語言代碼呢?

    單片機的運行除去需要硬件的支持之外,高效簡潔的C語言也是非常重要的因素之一。那么如何寫出高效并且簡潔易于閱讀的單片機C語言代碼呢?本文將為大家介紹如何寫出優美簡潔 的單片機循環語句,感興趣的朋友快來
    發表于 07-15 06:34

    如何寫出多串口共用printf函數語句呢

    如何寫出多串口共用printf函數語句呢?求大神解答
    發表于 11-17 06:37

    用C語言如何寫出單片機延時程序,且延時時間如何計算的?

    用C語言,如何寫出單片機延時程序,且延時時間如何計算的?
    發表于 10-18 08:19

    設備驅動的入門教程 (教你如何寫驅動)

    設備驅動的入門教程 (教你如何寫驅動)
    發表于 03-28 09:44 ?61次下載

    如何寫出讓CPU執行更快的代碼

    轉自:小林coding 前言 代碼都是由 CPU 跑起來的,我們代碼寫的好與壞就決定了 CPU 的執行效率,特別是在編寫計算密集型的程序,更要注重 CPU 的執行效率,否則將會大大影響系統性能
    的頭像 發表于 10-29 11:21 ?2326次閱讀
    <b class='flag-5'>如何寫出</b>讓CPU執行更快的<b class='flag-5'>代碼</b>?

    一本教你怎么寫出讓同事無法維護的代碼

    ?對,你沒看錯,本文就是教你怎么寫出讓同事無法維護的代碼。一、程序命名 容易輸入的變量名 。比如:Fred,asdf 單字母的變量名 。比如:a,b,c, x,y,z(如果不夠用,可以考慮a1,a2
    的頭像 發表于 10-11 15:45 ?1159次閱讀

    教你如何寫ADC代碼,輸出電壓,讀取光敏值。

    如何寫DA轉化代碼:s: 即startADDRESS: 即器件地址(0表示為寫)A:表示等待回應CONTROL BYTE: 表示控制字(第二個發送的字節)A:表示等待回應DATE BYTE: 表示寫入的電壓值(注意如果寫入255,其實結果是5v,以此來換算)A:表示等待
    發表于 12-20 18:44 ?6次下載
    <b class='flag-5'>教你</b><b class='flag-5'>如何寫</b>ADC<b class='flag-5'>代碼</b>,輸出電壓,讀取光敏值。

    C語言如何寫出高效代碼呢?

    當涉及復雜的高效C代碼案例時,這些代碼示例展示了C語言中一些復雜且高效的應用案例,涵蓋了排序算法、圖算法、位操作、文件操作、多線程編程等領域。
    發表于 09-06 14:57 ?471次閱讀
    C語言<b class='flag-5'>如何寫出</b>高效<b class='flag-5'>代碼</b>呢?

    如何寫出高效優美的C語言代碼

    電子發燒友網站提供《如何寫出高效優美的C語言代碼.pdf》資料免費下載
    發表于 11-18 10:55 ?0次下載
    <b class='flag-5'>如何寫出</b>高效優美的C語言<b class='flag-5'>代碼</b>

    如何寫出穩定的單片機代碼

    這篇文章分享怎么寫出穩定的單片機代碼。? ?? 我對優秀代碼的理解,大體分為兩個部分:高效和穩定。 ? 兩者都能做到很好的,如果靠自己摸索,沒有刻意去練習,可能需要花10年,甚至更久
    的頭像 發表于 11-15 16:40 ?271次閱讀
    <b class='flag-5'>如何寫出</b>穩定的單片機<b class='flag-5'>代碼</b>