<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      SystemVerilog 代碼風(fēng)格指南

      SystemVerilog 代碼風(fēng)格指南

      前言

      代碼被閱讀的頻率遠(yuǎn)遠(yuǎn)超過編寫的頻率。在團(tuán)隊(duì)中保持一致的編碼風(fēng)格能夠顯著提升代碼的可讀性,這是節(jié)省工程時(shí)間最有效(也是最簡單)的方法之一。

      在眾多編程語言中,Python 可以說是最優(yōu)雅的。閱讀他人編寫的 Python 代碼非常輕松,即使是復(fù)雜的代碼邏輯也不會(huì)讓人望而卻步。更重要的是,初學(xué)者編寫的代碼與核心開發(fā)者的代碼在風(fēng)格上高度一致。這主要?dú)w功于 PEP8 這一 Python 代碼風(fēng)格指南,整個(gè)社區(qū)對這份文檔的采納程度令人驚嘆。

      本風(fēng)格指南借鑒了 PEP8 的成功經(jīng)驗(yàn)和部分結(jié)構(gòu),同時(shí)結(jié)合了 UVM 庫的最佳實(shí)踐,避免重復(fù)造輪子。

      PEP8 核心理念

      風(fēng)格指南的本質(zhì)在于一致性。遵循本指南的一致性很重要,項(xiàng)目內(nèi)部的一致性更重要,單個(gè)模塊或功能內(nèi)的一致性是最重要的。

      但要知道何時(shí)打破常規(guī)——有時(shí)風(fēng)格指南的建議并不適用。遇到疑惑時(shí),請運(yùn)用最佳判斷。

      代碼布局規(guī)范

      縮進(jìn)規(guī)則

      基本原則: 每個(gè)縮進(jìn)級別使用 4 個(gè)空格。

      ? 推薦寫法:

      // 參數(shù)換行時(shí),第二行從函數(shù)名下方開始
      foo = long_function_name(
              var_one, var_two, var_three,
              var_four);
      
      // 或者與第一個(gè)參數(shù)對齊(4空格縮進(jìn)可選)
      foo = long_function_name(var_one, var_two,
                              var_three, var_four);
      
      // 函數(shù)聲明中增加額外縮進(jìn),區(qū)分函數(shù)體
      function void long_function_name(var_one, var_two,
              var_three, var_four);
          int x;
          // ...函數(shù)體...
      endfunction: long_function_name
      
      // 條件表達(dá)式換行時(shí)增加縮進(jìn)
      if (expr_one && expr_two &&
              expr_three) begin
          do_something();
      end
      

      ? 不推薦寫法:

      // 第二行參數(shù)位置不當(dāng)
      foo = long_function_name(var_one, var_two,
          var_three, var_four);
      
      // 函數(shù)聲明縮進(jìn)不清晰,容易與函數(shù)體混淆
      function void long_function_name(var_one, var_two,
          var_three, var_four);
          int x;
          // ...
      endfunction: long_function_name
      

      制表符與空格的選擇

      推薦使用空格進(jìn)行縮進(jìn)。 制表符僅在與已有制表符縮進(jìn)的代碼保持兼容時(shí)使用。

      編輯器配置示例:

      Vi/Vim 配置:

      " 將以下內(nèi)容添加到 ~/.vimrc
      set tabstop=4
      set shiftwidth=4
      set expandtab
      

      Emacs 配置:

      ; 將以下內(nèi)容添加到 ~/.emacs
      (setq-default indent-tabs-mode nil)
      (setq-default tab-width 4)
      (setq indent-line-function 'insert-tab)
      

      最大行長度限制

      建議將所有行(包括注釋)限制為最多 100 個(gè)字符。

      傳統(tǒng)建議是 80 個(gè)字符,但考慮到 UVM 的長宏定義特點(diǎn):

      `uvm_object_utils
      `uvm_info(get_name(), "detailed message here", UVM_MEDIUM)
      

      在這些聲明中,僅宏和函數(shù)名就占用了約 30 個(gè)字符。如果嚴(yán)格遵循 80 字符限制,會(huì)頻繁遇到換行困擾。因此,100 字符的限制更為實(shí)用和合理。

      重要提醒: 確保換行時(shí)進(jìn)行適當(dāng)?shù)目s進(jìn)對齊。

      begin & end 語句塊

      • begin 與它所屬的塊語句在同一行
      • end 獨(dú)占一行

      ? 推薦寫法:

      always_ff @(posedge clk) begin
          // 邏輯代碼
      end
      
      if (big_endian == 1) begin
          m_bits[count+i] = value[size-1-i];
      end
      else begin
          m_bits[count+i] = value[i];
      end
      
      for (int i = 0; i < size; i++) begin
          if (big_endian == 1) begin
              m_bits[count+i] = value[size-1-i];
          end
          else begin
              m_bits[count+i] = value[i];
          end
      end
      

      if & else 條件語句

      else 從新行開始

      ? 推薦寫法:

      if (big_endian == 1) begin
          m_bits[count+i] = value[size-1-i];
      end
      else begin
          m_bits[count+i] = value[i];
      end
      

      ? 不推薦寫法:

      if (big_endian == 1) begin
          m_bits[count+i] = value[size-1-i];
      end else begin
          m_bits[count+i] = value[i];
      end
      

      強(qiáng)烈建議: 始終與條件語句一起使用 begin/end。不使用花括號是產(chǎn)生 bug 的溫床。

      ? 危險(xiǎn)的寫法:

      // 避免這種寫法
      if (big_endian == 1)
          m_bits[count+i] = value[size-1-i];
      else
          m_bits[count+i] = value[i];
      
      // 特別要避免嵌套時(shí)不用花括號:
      // 雖然代碼能正常工作,但其他人可能會(huì)在 else 后添加代碼
      // 并誤以為會(huì)在 else 條件下執(zhí)行,從而引入難以發(fā)現(xiàn)的 bug
      for (int i = 0; i < size; i++)
          if (big_endian == 1)
              m_bits[count+i] = value[size-1-i];
          else
              m_bits[count+i] = value[i];
      

      空行使用原則

      • 用空行包圍類、函數(shù)和任務(wù)定義
      • 相關(guān)的單行代碼之間可以省略空行
      • 在函數(shù)和任務(wù)中謹(jǐn)慎使用空行來區(qū)分邏輯段落

      空格使用規(guī)范

      函數(shù)與任務(wù)調(diào)用

      基本規(guī)則: 函數(shù)名與左括號之間不加空格,左括號與第一個(gè)參數(shù)之間也不加空格。

      ? 推薦寫法:

      function void foo(x, y, z); 
      foo(x, y, z);
      

      ? 不推薦寫法:

      function void foo (x, y, z);
      foo (x, y, z);
      foo( x, y, z );
      

      默認(rèn)參數(shù)處理: 默認(rèn)參數(shù)值的等號周圍不加空格。

      ? 推薦寫法:

      function void foo(name="foo", x=1, y=20);
      

      ? 不推薦寫法:

      function void foo(name = "foo", x = 1, y = 20);
      

      賦值和運(yùn)算符規(guī)范

      基本原則: 不要為了對齊而在賦值運(yùn)算符周圍添加多余的空格。

      ? 推薦寫法:

      x = 1;
      y = 2;
      long_variable = 3;
      

      ? 不推薦寫法:

      x             = 1;
      y             = 2;
      long_variable = 3;
      

      運(yùn)算符空格規(guī)則: 以下二元運(yùn)算符兩側(cè)應(yīng)該始終保持空格:

      • 賦值操作符: =
      • 復(fù)合賦值: +=, -=, *=, /=
      • 比較操作符: ==, ===, <, >, !=, !==, <=, >=
      • 邏輯操作符: &, &&, |, ||
      // 正確的操作符使用
      result = (a + b) * c;
      if (count >= max_value && enable == 1'b1) begin
          status += increment_value;
      end
      

      循環(huán)和條件語句

      基本規(guī)則:

      • if, for, while 等關(guān)鍵字與左括號之間加一個(gè)空格
      • for 循環(huán)中的各個(gè)部分之間保持空格:int i = 0; i < 10; i++

      ? 推薦寫法:

      if (x == 10)
      for (int ii = 0; ii < 20; ii++)
      while (condition_true)
      

      ? 不推薦寫法:

      if(x == 10)
      if( x == 10 )
      for(int ii=0;ii<20;ii++)
      

      復(fù)合語句: 通常不建議在同一行寫多個(gè)語句。

      ? 不推薦寫法:

      if (foo == 1) $display("bar");
      

      always 塊的格式

      ? 推薦寫法:

      always_ff @(posedge clk) begin
          // 時(shí)序邏輯
      end
      
      always_comb begin
          // 組合邏輯
      end
      

      注釋規(guī)范

      關(guān)于注釋的重要提醒

      與代碼相矛盾的注釋比沒有注釋更糟糕。當(dāng)代碼更改時(shí),始終優(yōu)先保持注釋的及時(shí)更新!

      注釋基本規(guī)范:

      • 注釋應(yīng)該是完整的句子
      • 如果注釋是短語或句子,第一個(gè)單詞應(yīng)大寫(除非是小寫標(biāo)識(shí)符)
      • 短注釋可以省略末尾的句點(diǎn)
      • 塊注釋通常由完整句子組成,每句都應(yīng)以句點(diǎn)結(jié)尾

      版權(quán)橫幅

      對于許可/版權(quán)橫幅,請使用以下樣式注釋塊:

      /***********************************************************************
       * Copyright 2007-2011 Mentor Graphics Corporation
       * Copyright 2007-2010 Cadence Design Systems, Inc.
       * Copyright 2010 Synopsys, Inc.
       * Copyright 2013 NVIDIA Corporation
       * All Rights Reserved Worldwide
       *
       * Licensed under the Apache License, Version 2.0 (the
       * "License"); you may not use this file except in
       * compliance with the License.  You may obtain a copy of
       * the License at
       *
       *     http://www.apache.org/licenses/LICENSE-2.0
       *
       * Unless required by applicable law or agreed to in
       * writing, software distributed under the License is
       * distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
       * CONDITIONS OF ANY KIND, either express or implied.  See
       * the License for the specific language governing
       * permissions and limitations under the License.
       **********************************************************************/
      

      文檔字符串

      Docstring(文檔字符串)是位于文件頂部的注釋,提供該文件中代碼功能的高級描述。將文檔字符串放在版權(quán)橫幅的正后方。不要將它們混合在一起。對此段使用以下樣式:

       * Ending of copyright banner
       **********************************************************************/
      /*
       * Module `ABC`
       *
       * This is the 1st paragraph. Separate paragraphs with
       * an empty line with just the ` *` character.
       *
       * This is the 2nd paragraph. Do not fence the docstring
       * in a banner of `*****`. Only the copyright segment
       * above the docstring gets a fence.
       */
      

      塊注釋

      塊注釋通常適用于其后面的某些(或全部)代碼,并與該代碼保持相同的縮進(jìn)級別。

      塊注釋的每一行都以 // 和一個(gè)空格開頭(除非是注釋內(nèi)的縮進(jìn)文本)。塊注釋中的段落由包含單個(gè) // 的行分隔。

      你也可以使用多行塊注釋格式 /* */

      // 這是塊注釋的第一行
      // 這是第二行
      //
      // 這是塊注釋的第二段
      
      /* 
       * 這種注釋描述了
       * 下面代碼的功能
       */
       foo = bar + 1;
      

      內(nèi)聯(lián)注釋

      避免使用內(nèi)聯(lián)注釋,它們會(huì)影響代碼的整潔性:

      // 不要這樣做
      x = x + 1;    // 增加數(shù)據(jù)包計(jì)數(shù)
      

      注釋使用建議

      為了趕上項(xiàng)目截止日期,注釋往往會(huì)被忽略。但當(dāng)你在一段時(shí)間后重新審視代碼時(shí),總是會(huì)后悔這個(gè)決定。因此,現(xiàn)在花一點(diǎn)時(shí)間寫注釋,能為將來省去很多痛苦。未來的你會(huì)感謝現(xiàn)在的你。

      避免使用注釋圍欄,例如:

      • /***********************/
      • //######################
      • //////////////

      這些圍欄會(huì)讓代碼顯得雜亂,實(shí)際幫助有限。良好的塊注釋就能提供清晰的代碼分隔效果。只有版權(quán)橫幅應(yīng)該使用圍欄格式。

      命名約定

      為了統(tǒng)一理解,我們先定義幾種常見的命名約定:

      • PascalCase - 每個(gè)單詞的第一個(gè)字母都大寫
      • camelCase - 每個(gè)單詞的第一個(gè)字母(除第一個(gè)單詞外)均大寫
      • lowercase_with_underscores - 小寫字母加下劃線
      • UPPERCASE_WITH_UNDERSCORES - 大寫字母加下劃線

      文件名

      文件名應(yīng)使用 lowercase_with_underscore

      crc_generator.sv
      tb_defines.svh
      module_specification.docx
      input_message_buffer.sv
      

      類和模塊

      類和模塊名稱應(yīng)使用 lowercase_with_underscore。如果文件中只有一個(gè)類或模塊,則其名稱應(yīng)與文件名相同。

      class packet_parser_agent;
      endclass: packet_parser_agent
      
      module packet_parser_engine;
      endmodule: packet_parser_engine
      

      類實(shí)例應(yīng)被視為變量,并應(yīng)使用 lowercase_with_underscore 格式。模塊實(shí)例應(yīng)使用純駝峰命名法,不帶任何下劃線。

      // Class
      packet_parser_agent parser_agent;
      parser_agent = new();
      
      // Module
      packet_parser_engine ppe0(.*);
      packet_parser_engine packetParserEngine4a(.*);
      packet_parser_engine packetParserEngine4b(.*);
      

      接口

      • 接口定義使用 lowercase_with_underscores 以 "_io" 結(jié)尾
      • 接口實(shí)例以 "_if" 結(jié)尾
      • clocking 塊使用 camelCase
      • modport 最好只是一個(gè)詞 lowercase
      interface bus_io(input bit clk);
          logic vld;
          logic [7:0] addr, data;
      
          clocking ioDrv @posedge(clk);
              input addr;
              output vld;
              output data;
          endclocking: ioDrv
      
          modport dut(input addr, output vld, data);
          modport tb(clocking ioDrv);
      endinterface: bus_io
      
      module tb_top;
          bus_io bus_if(clk);
      endmodule: tb_top
      

      變量

      變量名稱應(yīng)始終使用 lowercase_with_underscore

      ethernet_agent eth_agent;
      int count_packets, count_errors;
      logic [15:0] some_long_var;
      

      如有必要,使用前綴輕松識(shí)別和分組變量:

      logic [31:0] pe_counter_0;
      logic [31:0] pe_counter_1;
      logic [31:0] pe_counter_2;
      

      結(jié)構(gòu)、聯(lián)合和枚舉

      typedef 所有結(jié)構(gòu)、聯(lián)合和枚舉。他們應(yīng)該使用駝峰命名法,并具有以下區(qū)別:

      • 結(jié)構(gòu)體以 _s 結(jié)尾
      • 聯(lián)合以 _u 結(jié)尾
      • 枚舉以 _e 結(jié)尾。此外,枚舉應(yīng)使用 UPPERCASE_WITH_UNDERSCORES
      typedef struct packed {
          logic [47:0] macda;
          logic [47:0] macsa;
          logic [15:0] etype;
      } ethPacket_s;
      
      typedef union packed {
          logic [15:0] tx_count;
          logic [15:0] rx_count;
      } dataPacketCount_u;
      
      typedef enum logic [1:0] {
          IPV4_TCP,
          IPV4_UDP,
          IPV6_TCP,
          IPV6_UDP
      } packetType_e;
      

      類型變量名稱

      類型變量名稱應(yīng)為 UPPERCASE,最好只有一個(gè)單詞。

      // Following examples were extracted from the UVM code base.
      // The file path where they can be found is also mentioned.
      
      // tlm1/uvm_exports.svh
      class uvm_get_peek_export #(type T=int);
      class uvm_blocking_master_export #(type REQ=int, type RSP=REQ);
      
      // base/uvm_traversal.svh
      virtual class uvm_visitor_adapter #(type STRUCTURE=uvm_component,
          VISITOR=uvm_visitor#(STRUCTURE)) extends uvm_object;
      

      宏命名規(guī)范

      宏的命名需要根據(jù)用途進(jìn)行區(qū)分:

      • 函數(shù)/任務(wù)宏: 使用 UPPERCASE 宏名稱和 lowercase 參數(shù)名稱
      • 類/代碼片段宏: 使用 lowercase 宏名稱和 UPPERCASE 參數(shù)名稱
      • 單詞分隔: 統(tǒng)一使用下劃線分隔
      // 函數(shù)/任務(wù)宏:UPPERCASE 宏名 + lowercase 參數(shù)  
      `define PRINT_BYTES(arr, startbyte, numbytes) \
          function print_bytes(logic[7:0] arr[], int startbyte, int numbytes); \
              for (int ii=startbyte; ii<startbyte+numbytes; ii++) begin \
                  if ((ii != 0) && (ii % 16 == 0)) \
                      $display("\n"); \
                  $display("0x%x ", arr[ii]); \
              end \
          endfunction: print_bytes
      
      // 類定義宏:lowercase 宏名 + UPPERCASE 參數(shù)
      `define uvm_analysis_imp_decl(SFX) \
          class uvm_analysis_imp``SFX #(type T=int, type IMP=int) \
            extends uvm_port_base #(uvm_tlm_if_base #(T,T)); \
            `UVM_IMP_COMMON(`UVM_TLM_ANALYSIS_MASK,`"uvm_analysis_imp``SFX`",IMP) \
            function void write( input T t); \
              m_imp.write``SFX( t); \
            endfunction \
          endclass
      
      // 代碼片段宏:lowercase 宏名 + UPPERCASE 參數(shù)
      `define uvm_create_on(SEQ_OR_ITEM, SEQR) \
        begin \
        uvm_object_wrapper w_; \
        w_ = SEQ_OR_ITEM.get_type(); \
        $cast(SEQ_OR_ITEM , create_item(w_, SEQR, `"SEQ_OR_ITEM`"));\
        end
      

      擴(kuò)展閱讀

      想了解更多 SystemVerilog 宏的使用技巧,可以參考宏使用詳細(xì)指南

      結(jié)束標(biāo)識(shí)符

      在適用的情況下始終使用結(jié)束標(biāo)識(shí)符:

      endclass: driver_agent
      endmodule: potato_block
      endinterface: memory_io
      endtask: cowboy_bebop
      

      編程實(shí)踐建議

      由于 SystemVerilog 橫跨設(shè)計(jì)和驗(yàn)證兩個(gè)領(lǐng)域,擁有豐富的語言特性。對于本風(fēng)格指南中未明確提及的其他語言結(jié)構(gòu),如斷言、覆蓋率、約束、時(shí)序控制等,都可以參照以上原則進(jìn)行相應(yīng)擴(kuò)展。

      結(jié)語

      編寫優(yōu)雅的代碼并非易事。在緊張的項(xiàng)目交付期限和繁重的工作任務(wù)中,很難有精力去關(guān)注、回顧、重構(gòu)和優(yōu)化匆忙產(chǎn)生的代碼。在這樣的時(shí)刻,一些前輩的智慧話語能夠幫助我們堅(jiān)持編寫優(yōu)雅代碼的初心:

      讓我們改變對程序構(gòu)建的傳統(tǒng)態(tài)度:與其想象我們的主要任務(wù)是指示計(jì)算機(jī)做什么,不如讓我們專注于向人類解釋我們希望計(jì)算機(jī)做什么。

      — 唐納德·克努斯

      所以,漂亮的代碼是清晰的,易于閱讀和理解;它的組織、形狀、架構(gòu)和聲明性語法一樣揭示了意圖。每個(gè)小部分都是連貫的,其目的是單一的,盡管所有這些小部分都像復(fù)雜馬賽克的碎片一樣組合在一起,但當(dāng)一個(gè)元素需要更改或替換時(shí),它們很容易分開。

      — 維克拉姆·錢德拉 (Vikram Chandra) 作者《Geek Sublime》

      參考資料

      posted @ 2025-09-23 16:08  LeslieQ  閱讀(13)  評論(0)    收藏  舉報(bào)
      主站蜘蛛池模板: 国产精品成人午夜久久| 中文字幕有码在线第十页| 国产AV影片麻豆精品传媒| 日本一道高清一区二区三区| 日本欧美大码a在线观看| 狠狠做五月深爱婷婷伊人| 亚洲人妻系列中文字幕| 亚洲爆乳成av人在线视菜奈实| 中文字幕亚洲综合久久2020| 成人啪啪高潮不断观看| 99人中文字幕亚洲区三| 久久亚洲精品人成综合网| 国产精品久久久福利| 午夜久久水蜜桃一区二区| 一本大道色婷婷在线| 国产超碰人人做人人爱| 国内揄拍国内精品人妻| 男女xx00上下抽搐动态图| 久久国产精品精品国产色婷婷| 国产国产乱老熟女视频网站97| 国内精品大秀视频日韩精品 | 日本中文字幕有码在线视频| 苏尼特右旗| 中文字幕亚洲综合第一页| 国产99视频精品免费观看9| 天啦噜国产精品亚洲精品| 最近中文字幕日韩有码| 亚洲尤码不卡av麻豆| 欧美成人h精品网站| 制服丝袜美腿一区二区| 少妇高潮水多太爽了动态图| 国产精品色一区二区三区| 国产网红主播精品一区| 日韩熟妇中文色在线视频| 东方四虎av在线观看| 岢岚县| 伊人久久大香线蕉av色婷婷色| 国产AV福利第一精品| 一本久久a久久精品综合| 最近中文字幕国产精选| 欧洲熟妇色xxxx欧美老妇免费 |