UVM驗證(三)—UVM機制(1)

目錄

(一)Factory工廠機制

1. 工廠機制核心邏輯:“注冊 - 創建 - 覆蓋”

2. 代碼映射:從概念到實現

3. 實驗目標:用?dadd_fixen_driver?固定?data_en=1

4. 工廠機制的價值:“靈活驗證的基石”

5. 常見問題與調試

6. 總結

(二)Phase階段運行機制

1. 核心規則:“三類 phase 執行順序”

2. 實驗驗證:代碼與日志的映射

3. 關鍵細節與易錯點

4. 實驗價值與應用場景

5. 總結

(三)sequence 激勵產生與交互執行機制

1.?sequence 核心機制概述

2. sequence_item的發送

2.1 核心規則:sequence_item?發送的三種方法

2.2 逐類解析:代碼邏輯與實驗驗證

2.3 關鍵細節與對比

2.4 實驗價值與總結

3. sequence 的發送

3.1 核心規則:子?sequence?發送的三類方法

3.2 逐類解析:結合?dadd?代碼與腳本

3.3 關鍵細節與對比

3.4 實驗價值與總結


(一)Factory工廠機制

1. 工廠機制核心邏輯:“注冊 - 創建 - 覆蓋”

????????UVM 工廠機制本質是?“對象創建的集中管控”,核心解決兩個問題:

(1)解耦創建邏輯:讓對象的 “創建” 與 “使用” 分離,無需硬編碼?new(),便于后續替換實現(如用?dadd_fixen_driver?替換?dadd_driver?)。

(2)支持動態替換:通過?set_type_override?或?set_inst_override,可在不修改代碼的前提下,替換組件類型(如把?dadd_driver?換成?dadd_fixen_driver?),靈活控制驗證行為。

2. 代碼映射:從概念到實現

(1) 注冊(uvm_component_utils

  • 作用:把類 “登記” 到 UVM 工廠的 “查找表”,讓工廠能識別并創建它。
  • 代碼示例dadd_driver?注冊):
class dadd_driver extends uvm_driver #(dadd_item);`uvm_component_utils(dadd_driver)  // 注冊 component 到工廠// ... 類定義 ...
endclass
  • 關鍵
    • uvm_component_utils?是注冊?component(繼承?uvm_component?的類,如?drivermonitor?)的宏;若為?object(繼承?uvm_object?的類,如?sequence_item?),則用?uvm_object_utils
    • 注冊后,類會被加入 UVM 工廠的 “類型映射表”,后續可通過?type_id::create()?創建實例。

(2)創建(type_id::create

  • 作用:通過工廠創建對象,自動檢查是否有 “類型覆蓋”,再決定實例化原類還是替換類。
  • 代碼示例dadd_iagent?中創建?dadd_driver?):
function dadd_iagent::new(string name = "dadd_iagent", uvm_component parent);super.new(name, parent);// 通過工廠創建 driver,而非直接 new(dadd_driver::new(...))drv = dadd_driver::type_id::create("drv", this);  // ... 其他組件創建 ...
endfunction
  • 關鍵
    • type_id::create("drv", this)?會先查工廠是否有?dadd_driver?的覆蓋類型(如?dadd_fixen_driver?),若有則創建覆蓋類,否則創建原類。
    • 替換?new()?為?create()?是實現 “動態覆蓋” 的核心:后續只需調用?set_type_override,無需修改?dadd_iagent?代碼,就能替換?driver?類型。

(3)覆蓋(set_type_override

  • 作用:告訴工廠 “用類 B 替換類 A 的創建”,實驗中把?dadd_driver?換成?dadd_fixen_driver,固定?data_en=1
  • 代碼示例(在?dadd_rand_test?中覆蓋 ):
class dadd_rand_test extends uvm_test;`uvm_component_utils(dadd_rand_test)function void build_phase(uvm_phase phase);// 全局覆蓋:所有 dadd_driver 類型都替換為 dadd_fixen_driverdadd_driver::type_id::set_type_override(dadd_fixen_driver::get_type());  super.build_phase(phase);endfunction
endclass
  • 關鍵
    • set_type_override?需在?build_phase?調用,確保工廠在創建組件前生效。
    • 替換后,dadd_iagent?中?drv = dadd_driver::type_id::create(...)?會自動創建?dadd_fixen_driver?實例,實現 “無代碼修改替換組件”。

3. 實驗目標:用?dadd_fixen_driver?固定?data_en=1

????????原?dadd_driver?中?data_en?是隨機的,實驗通過?“工廠覆蓋”?替換為?dadd_fixen_driver,強制?data_en=1

(1)dadd_fixen_driver?邏輯

task dadd_fixen_driver::main_phase(uvm_phase phase);wait(tb_dadd.dadd_if.reset_n);forever beginseq_item_port.get_next_item(req);@(posedge tb_dadd.dadd_if.clk);// 固定 data_en=1(與原 driver 的隨機邏輯區分)tb_dadd.dadd_if.mcb.dadd_in_en <= 1'b1;  tb_dadd.dadd_if.mcb.dadd_in     <= req.data;tb_dadd.dadd_if.mcb.dadd_in_addr<= req.addr;seq_item_port.item_done();end
endtask
  • 關鍵dadd_in_en <= 1'b1?硬編碼為 1,覆蓋原?driver?的隨機行為。

(2)覆蓋流程

  • 在?dadd_rand_test?的?build_phase?調用?set_type_override,替換?dadd_driver?為?dadd_fixen_driver
  • dadd_iagent?中通過?dadd_driver::type_id::create()?創建?driver?時,工廠自動實例化?dadd_fixen_driver
  • 仿真時,driver?驅動 DUT 的?data_en?恒為 1,實現實驗目標。

4. 工廠機制的價值:“靈活驗證的基石”

(1)解耦與復用:組件創建邏輯與使用邏輯分離,dadd_iagent?無需關心?driver?具體類型,只需通過工廠創建,復用性更高。

(2)動態配置:通過一行?set_type_override,就能切換?driver?行為(隨機 / 固定?data_en?),無需修改?agentenv?代碼。

(3)可維護性:驗證需求變化時(如替換?driver?協議),只需修改?driver?子類和覆蓋邏輯,不影響上層組件。

5. 常見問題與調試

(1)覆蓋不生效

  • 檢查?set_type_override?是否在?build_phase?調用(main_phase?調用無效,因組件已創建 )。
  • 檢查?create()?是否用?type_id::create,而非直接?new()(直接?new()?會繞過工廠,覆蓋失效 )。

(2)類型注冊遺漏

  • 若子類(如?dadd_fixen_driver?)未注冊(忘記?uvm_component_utils?宏 ),工廠無法識別,覆蓋會失敗。

(3)層次化覆蓋

  • 若需只替換某個?agent?中的?driver(而非全局替換 ),可用?set_inst_override,指定實例路徑(如?uvm_test_top.env.iagt.drv?)。

6. 總結

????????UVM 工廠機制通過?“注冊 - 創建 - 覆蓋”?三步,實現了:

  • 動態替換組件:實驗中用?dadd_fixen_driver?替換?dadd_driver,無需修改?agent?代碼。
  • 解耦創建邏輯:組件創建由工廠統一管控,上層組件只需關注接口,無需關心具體實現。
  • 靈活驗證配置:一行代碼切換驗證行為(隨機 / 固定?data_en?),讓驗證平臺可適配不同場景。

????????這是 UVM 實現 “可復用、可配置驗證平臺” 的核心機制,掌握后能大幅提升驗證環境的擴展性與維護性。

(二)Phase階段運行機制

1. 核心規則:“三類 phase 執行順序”

????????UVM phase 執行順序分為?“組件內順序”“樹形結構順序”“同級組件順序”?三類,需結合實驗場景理解:

(1)同一組件內的 phase 順序(縱向順序)

  • 規則:同一組件(如?dadd_iagent?)內,phase 按?“功能階段”?順序執行,從?build_phase?開始,到?final_phase?結束,流程為:
build_phase → connect_phase → end_of_elaboration_phase → start_of_simulation_phase → 
reset_phase → configure_phase → run_phase → main_phase → shutdown_phase → 
extract_phase → check_phase → report_phase → final_phase
  • 實驗映射:若在?dadd_driver?的所有 phase 中加入打印,會看到該組件內 phase 嚴格按上述順序執行。

(2) 樹形結構中的 phase 順序(橫向跨組件)

????????UVM 組件構成?樹形層次結構uvm_test_top → env → agent → driver/monitor?),同一類型 phase 在樹形結構中的執行順序分兩種:

phase 類型執行方向典型 phase 舉例實驗流程映射(以?build_phase?和?connect_phase?為例)
自上而下(Top-Down)從根到葉子build_phasefinal_phaseuvm_test_top.build_phase?→?env.build_phase?→?agent.build_phase?→?driver.build_phase
自下而上(Bottom-Up)從葉子到根connect_phasereport_phase?等driver.connect_phase?→?agent.connect_phase?→?env.connect_phase?→?uvm_test_top.connect_phase

(3)同級組件的 phase 順序(橫向同層)

  • 規則:同一父組件下的?同級組件(如?agent?內的?drivermonitorsequencer?),同一 phase 的執行順序按?“實例化名稱的字典序”?執行。
  • 實驗映射:若?agent?中?driver?命名為?drvmonitor?命名為?imonsequencer?命名為?sqr,則?build_phase?執行順序為:
drv.build_phase → imon.build_phase → sqr.build_phase 

(因字典序?drv?<?imon?<?sqr?,按字母順序排列 )

2. 實驗驗證:代碼與日志的映射

(1)代碼中加入 phase 打印(以?dadd_driver?為例)

class dadd_driver extends uvm_driver #(dadd_item);`uvm_component_utils(dadd_driver)function new(string name="dadd_driver", uvm_component parent);super.new(name, parent);endfunctiontask build_phase(uvm_phase phase);`uvm_info("DRV", "build_phase executed", UVM_LOW)super.build_phase(phase);endtasktask connect_phase(uvm_phase phase);`uvm_info("DRV", "connect_phase executed", UVM_LOW)super.connect_phase(phase);endtask// ... 其他 phase 同理加入打印 ...
endclass

(2)日志分析(以?build_phase?和?connect_phase?為例)

build_phase?日志(自上而下)

UVM_INFO dadd_driver.sv(10) @ 0: uvm_test_top.env.iagt.drv [DRV] build_phase executed
UVM_INFO dadd_imonitor.sv(10) @ 0: uvm_test_top.env.iagt.imon [MON] build_phase executed
UVM_INFO dadd_sequencer.sv(10) @ 0: uvm_test_top.env.iagt.sqr [SQR] build_phase executed
UVM_INFO dadd_oagent.sv(10) @ 0: uvm_test_top.env.oagt [OAGT] build_phase executed
  • 邏輯:先執行?uvm_test_top?的?build_phase(未完整打印 ),再執行?env?的?build_phase,然后按字典序執行?iagt?內的?drvimonsqr,最后執行?oagt(因?iagt?字典序小于?oagt?)。

connect_phase?日志(自下而上)

UVM_INFO dadd_driver.sv(15) @ 0: uvm_test_top.env.iagt.drv [DRV] connect_phase executed
UVM_INFO dadd_imonitor.sv(15) @ 0: uvm_test_top.env.iagt.imon [MON] connect_phase executed
UVM_INFO dadd_sequencer.sv(15) @ 0: uvm_test_top.env.iagt.sqr [SQR] connect_phase executed
UVM_INFO dadd_oagent.sv(15) @ 0: uvm_test_top.env.oagt [OAGT] connect_phase executed
UVM_INFO dadd_env.sv(15) @ 0: uvm_test_top.env [ENV] connect_phase executed
UVM_INFO dadd_test.sv(15) @ 0: uvm_test_top [TEST] connect_phase executed
  • 邏輯:先執行葉子組件(drvimonsqr?),再執行父組件(oagtenvuvm_test_top?),符合 “自下而上” 規則。

3. 關鍵細節與易錯點

(1)?run_phase?與?main_phase?的關系

  • run_phase?是?task phase?的父 phase,main_phase?是?run_phase?的子 phase(屬于?task phase?類別 )。
  • 執行順序:run_phase?啟動后,main_phase?會自動執行,且遵循?自下而上?規則(如先?driver.main_phase,再?agent.main_phase?等 )。

(2)字典序的具體表現

  • 同級組件的 phase 執行順序,嚴格按?“new 時的名稱字符串比較”,如:
    • 名稱為?a_drv?和?b_drv?→?a_drv?先執行(因?a?的 ASCII 碼小于?b?)。
    • 名稱為?drv1?和?drv2?→?drv1?先執行(數字?1?的 ASCII 碼小于?2?)。

(3)phase?阻塞與 objection 機制

  • task phase(如?main_phaserun_phase?)需要通過?phase.raise_objection?和?phase.drop_objection?控制仿真進度,否則仿真會直接結束。
  • function phase(如?build_phaseconnect_phase?)是純函數,無需 objection 機制,執行完立即退出。

4. 實驗價值與應用場景

(1)驗證平臺構建

  • build_phase?自上而下:確保父組件先完成 “資源分配”(如創建子組件 ),子組件再初始化(如?driver?在?agent.build_phase?中被創建 )。
  • connect_phase?自下而上:確保子組件先完成 “端口連接”(如?driver.seq_item_port?連接?sequencer?),父組件再做全局連接(如?agent?連接?scoreboard?)。

(2)調試與問題定位

  • 若子組件的?build_phase?未執行,需檢查父組件是否在?build_phase?中正確創建了它(因?build_phase?自上而下,父組件未創建則子組件無法執行 )。
  • 若?connect_phase?邏輯異常,需檢查是否因 “自下而上” 順序導致,子組件的端口未準備好時父組件已開始連接。

(3) 復雜場景控制

  • 對于多?agent、多?sequence?的驗證平臺,利用?字典序控制同級組件執行順序,可確保特定組件優先執行(如?monitor?先采樣,driver?后驅動 )。

5. 總結

????????UVM phase 執行順序的核心邏輯可歸納為:

  • 同一組件內:按功能階段順序(buildconnectrun?等 )依次執行。
  • 樹形結構中build_phase?和?final_phase?自上而下,其余 phase 自下而上。
  • 同級組件間:按實例化名稱的字典序執行。

????????理解這三類順序,能精準控制驗證平臺的?組件初始化流程端口連接時機激勵注入順序,是構建復雜 UVM 驗證環境的基礎。實驗中通過打印各 phase 執行日志,可直觀驗證這些規則,為調試和優化驗證平臺提供依據。

(三)sequence 激勵產生與交互執行機制

1.?sequence 核心機制概述

????????在 UVM 中,sequence?機制是激勵產生、調度與驅動的核心,通過?sequencesequencerdriver?的協作,實現 “激勵生成→仲裁調度→信號驅動→結果反饋” 的完整閉環。以下從?執行規則代碼映射實驗驗證?三個維度解析其核心邏輯:

(1)執行規則

  • 角色分工
    • sequence:作為 “激勵生成器”,負責創建、隨機化?sequence_item(事務包),并通過?sequencer?發送給?driver
    • sequencer:作為 “調度中心”,接收多個?sequence?的請求,通過仲裁算法(如 FIFO、優先級)決定發送順序,再轉發給?driver
    • driver:作為 “執行者”,從?sequencer?獲取?sequence_item,轉換為物理信號驅動 DUT,并可通過?response?反饋結果。
  • 交互流程(完整握手):
    • sequence?生成?sequence_item?并隨機化,通過?start_item/finish_item?提交給?sequencer
    • sequencer?仲裁后將?item?放入?REQ_FIFOdriver?通過?get_next_item?取走并驅動 DUT。
    • 若需反饋,driver?生成?response?放入?RSP_FIFOsequence?通過?get_response?獲取結果,完成生命周期。

(2)總結

  • sequence?專注于 “產生什么激勵”,支持隨機化和約束,覆蓋多樣化測試場景。
  • sequencer?專注于 “何時發送激勵”,通過仲裁算法協調多?sequence?競爭。
  • driver?專注于 “如何驅動激勵”,將抽象事務轉換為物理信號,確保時序正確

2. sequence_item的發送

sequence 的執行必須在 task body 中執行,task body 是在 task phase 中自動調用的。

    2.1 核心規則:sequence_item?發送的三種方法

    ????????在 UVM 中,sequence?發送?sequence_item(事務包,如?dadd_item?)有三類典型方法,本質都是?“實例化→隨機化→發送給?sequencer?的流程封裝,但語法和復雜度不同:

    方法分類核心語法封裝層級適用場景
    基礎方法start_item?+?finish_item最底層,無封裝需精準控制發送流程(如調試)
    宏封裝方法uvm_create?+?uvm_send封裝?new?+?start_item/finish_item需靈活指定?sequencer
    高級宏(常用)uvm_do?系列宏封裝?uvm_create?+ 完整流程日常驗證(簡潔高效)
    2.2 逐類解析:代碼邏輯與實驗驗證

    ????????以下結合?dadd?驗證平臺的?dadd_rand_sequence.sv?代碼和?Makefile?腳本,說明每種方法的細節:

    (1)方法 1:start_item?+?finish_item(基礎流程)

    執行規則:手動完成?sequence_item?的?“實例化→連接?sequencer→隨機化→發送”?全流程,每一步需顯式調用:

    步驟代碼邏輯作用說明
    1. 實例化?itemitem = new("item");創建?dadd_item?事務對象,準備承載激勵數據
    2. 連接?sequencerstart_item(item);讓?item?與?iagt.sqr(輸入?agent?的?sequencer?)建立調度連接
    3. 隨機化?itemitem.randomize();隨機生成?addrdatadata_en?等字段,模擬真實激勵
    4. 發送給?driverfinish_item(item);通知?sequencer?完成調度,將?item?轉發給?driver?驅動 DUT

    代碼映射dadd_sequence.sv?中?START_ITEM?分支 ):

    `ifdef START_ITEM
    task body();if(starting_phase != null) starting_phase.raise_objection(this);  // 阻止仿真提前結束repeat(20) begin  // 發送20個事務item = new("item");         // 1. 實例化start_item(item);           // 2. 連接sequenceritem.randomize();           // 3. 隨機化finish_item(item);          // 4. 發送給driverendif(starting_phase != null) starting_phase.drop_objection(this);  // 允許仿真結束
    endtask : body
    `endif
    

    實驗驗證(執行?make send_item_start_item?):

    • 日志顯示 20 次?item?發送,每次含隨機化的?addrdata。
    • 波形中?dadd_if?接口的信號(如?addrdata?)與日志匹配,證明?driver?正確驅動 DUT。
    UVM_INFO dadd_sequence.sv(12) @ 100ns: uvm_test_top.env.iagt.sqr [SEQ] Sent item: addr=0x12, data=0x34, data_en=1
    

      (2)方法 2:uvm_create?+?uvm_send(宏封裝基礎流程)

      執行規則:用?uvm_create?替代?new?實例化?item,用?uvm_send?替代?start_item/finish_item?發送,本質是?封裝了基礎方法的語法糖,但更靈活(可指定?sequencer?):

      步驟代碼邏輯作用說明
      1. 實例化?itemuvm_create(item);?或?uvm_create_on(item, sqr);不僅創建?item,還可指定發送到哪個?sequencer(如?iagt.sqr?或?oagt.sqr?)
      2. 隨機化?itemitem.randomize();同方法 1
      3. 發送給?driveruvm_send(item);封裝?start_item/finish_item,簡化發送流程

      代碼映射dadd_sequence.sv?中?UVM_CREATE?分支 ):

      `elsif UVM_CREATE
      task body();if(starting_phase != null) starting_phase.raise_objection(this);repeat(20) begin`uvm_create(item);  // 1. 實例化(可指定sequencer)item.randomize();   // 2. 隨機化`uvm_send(item);    // 3. 發送(封裝start_item/finish_item)endif(starting_phase != null) starting_phase.drop_objection(this);
      endtask : body
      `endif
      

      實驗驗證(執行?make send_item_uvm_create?):

      • 日志與方法 1 類似,但代碼更簡潔,uvm_create/uvm_send?隱式完成連接和發送。
      • 若修改為?uvm_create_on(item, env.oagt.sqr);item?會發送到?oagt?的?sequencer,波形中?oagt?接口信號變化,驗證跨?agent?發送。

      (3)方法 3:uvm_do?系列宏(高級封裝,最常用)

      執行規則
      uvm_do?是?“一站式” 宏,直接封裝 “實例化→隨機化→發送” 全流程,甚至可帶約束(uvm_do_with?)或優先級(uvm_do_pri?),是日常驗證最常用的方法:

      宏類型語法示例作用說明
      基礎發送uvm_do(item);自動完成實例化、隨機化、發送
      帶約束發送uvm_do_with(item, {item.data_en==1;});隨機化時固定?data_en=1,其他字段隨機
      指定?sequencer?發送uvm_do_on(item, env.iagt.sqr);強制?item?發送到?iagt?的?sequencer

      代碼映射dadd_sequence.sv?中?UVM_DO?分支 ):

      `else//UVM_DO
      task body();if(starting_phase != null) starting_phase.raise_objection(this);repeat(20) begin`uvm_do(item)  // 一站式完成實例化、隨機化、發送endif(starting_phase != null) starting_phase.drop_objection(this);
      endtask : body
      `endif
      

      實驗驗證(執行?make send_item_uvm_do?):

      • 日志與前兩種方法一致,但代碼行數最少,uvm_do?隱式完成所有步驟。
      • 若修改為?uvm_do_with(item, {item.addr==0x5a5a;});,日志中?addr?固定為?0x5a5a,驗證約束生效。
      2.3 關鍵細節與對比

      (1)方法選擇建議

      • 調試階段:用?start_item/finish_item,逐行控制流程,方便定位問題。
      • 跨?agent?發送:用?uvm_create_on?或?uvm_do_on,明確指定?sequencer,避免發送到錯誤?agent
      • 日常驗證:優先用?uvm_do?系列宏,代碼簡潔,減少樣板代碼。

      (2)易錯點

      • starting_phase?為空:若?sequence?未關聯?phase(如未在?test?中設置?starting_phase?),raise_objection?會報錯,需確保?sequence.starting_phase = phase;
      • uvm_create?未指定?sequencer:若未用?uvm_create_on?且?p_sequencer?未正確連接,item?可能發送到?null?sequencer,觸發?UVM_ERROR
      2.4 實驗價值與總結

      通過?Makefile?腳本切換宏定義(START_ITEM/UVM_CREATE/UVM_DO?),可直觀對比三種方法的執行流程:

      • 證明三類方法本質是同一流程的不同封裝,uvm_do?是最簡潔的高階用法。
      • 驗證平臺可靈活切換發送方式,適配不同測試場景(如調試、跨?agent?、帶約束發送 )。

      3. sequence 的發送

      3.1 核心規則:子?sequence?發送的三類方法

      ????????當?sequence?需發送子?sequence(如?dadd_fixen_sequence?調用?dadd_rand_sequence?)時,本質是?“父?sequence?調度子?sequence?的生命周期”,三類方法的核心差異在于 “調度的封裝層級”:

      方法分類核心語法封裝層級適用場景
      start?函數seq.start(p_sequencer);最底層,手動控制實例化、隨機化、啟動需精準控制子?sequence?流程
      uvm_create/uvm_senduvm_create(seq);?+?uvm_send(seq);封裝?start?函數,簡化調用需顯式控制隨機化步驟
      uvm_do?宏uvm_do_with(seq, {約束;})封裝 “實例化 + 隨機化 + 啟動” 全流程日常驗證(簡潔高效)
      3.2 逐類解析:結合?dadd?代碼與腳本

      以下基于?dadd_fixen_sequence.sv?和?dadd_rand_sequence.sv?代碼,說明每種方法的細節:

      (1)方法 1:start?函數(手動調度子?sequence

      執行規則
      手動完成子?sequence?的?“實例化→隨機化約束→啟動”?全流程,需顯式調用?start?函數關聯?p_sequencer(父?sequence?所在的?sequencer?)。

      步驟代碼邏輯作用說明
      1. 實例化子?seqseq = dadd_rand_sequence::type_id::create("seq");創建子?sequence?對象(dadd_rand_sequence?)
      2. 隨機化約束seq.randomize() with {data_en_rand == 1;};固定子?sequence?的?data_en_rand?為 1,間接約束?dadd_item.data_en=1
      3. 啟動子?seqseq.start(p_sequencer);讓子?sequence?掛載到父?sequence?的?sequenceriagt.sqr?)上

      代碼映射dadd_fixen_sequence.sv?中?SEND_SEQ?分支 ):

      `ifdef SEND_SEQ
      `ifdef START
      task body();if(starting_phase != null) starting_phase.raise_objection(this);  // 阻止仿真提前結束// 1. 實例化子 sequenceseq = dadd_rand_sequence::type_id::create("seq");  // 2. 約束子 sequence 的 data_en_rand 為 1seq.randomize() with {data_en_rand == 1;};  // 3. 啟動子 sequence,掛載到 p_sequencer(iagt.sqr)seq.start(p_sequencer);  if(starting_phase != null) starting_phase.drop_objection(this);  // 允許仿真結束
      endtask : body
      `endif
      `endif
      

      實驗驗證(執行?make send_seq_start?):

      • 日志顯示子?sequence?被啟動,且?data_en?固定為 1:

        plaintext

        UVM_INFO dadd_rand_sequence.sv(20) @ 100ns: uvm_test_top.env.iagt.sqr [SEQ] Sent item: data_en=1, addr=0x12, data=0x34
        
      • 波形中?dadd_if.data_en?恒為 1,證明約束生效。

      (2)方法 2:uvm_create?+?uvm_send(封裝?start?函數)

      執行規則
      用?uvm_create?替代手動?new?實例化子?sequence,用?uvm_send?替代?start?函數,封裝部分流程,但仍需手動隨機化。

      步驟代碼邏輯作用說明
      1. 實例化子?sequvm_create(seq);隱式創建子?sequence,并關聯到?p_sequencer
      2. 隨機化約束seq.randomize() with {data_en_rand == 1;};同方法 1
      3. 啟動子?sequvm_send(seq);封裝?start?函數,簡化發送流程

      代碼映射dadd_fixen_sequence.sv?中?UVM_CREATE?分支 ):

      `elsif UVM_CREATE
      task body();if(starting_phase != null) starting_phase.raise_objection(this);// 1. 實例化子 sequence(隱式關聯 p_sequencer)`uvm_create(seq);  // 2. 約束子 sequenceseq.randomize() with {data_en_rand == 1;};  // 3. 發送子 sequence(封裝 start 函數)`uvm_send(seq);  if(starting_phase != null) starting_phase.drop_objection(this);
      endtask : body
      

      實驗驗證(執行?make send_seq_uvm_create?):

      • 日志與方法 1 類似,但代碼更簡潔,uvm_create/uvm_send?隱式完成部分流程。
      • 若刪除?seq.randomize()data_en_rand?會隨機化,驗證?uvm_create?不自動隨機化,需手動調用。

      (3)方法 3:uvm_do?系列宏(一站式封裝)

      執行規則
      uvm_do_with?宏?一站式封裝“實例化 + 隨機化 + 啟動” 全流程,甚至可在宏內直接寫約束,無需手動調用?randomize

      步驟代碼邏輯作用說明
      1. 實例化 + 隨機化 + 啟動uvm_do_with(seq, {data_en_rand == 1;});隱式完成 “創建→隨機化(帶約束)→啟動”,最簡潔

      代碼映射dadd_fixen_sequence.sv?中?UVM_DO?分支 ):

      `else//UVM_DO
      task body();if(starting_phase != null) starting_phase.raise_objection(this);// 一站式完成:實例化+隨機化(約束 data_en_rand=1)+啟動`uvm_do_with(seq, {data_en_rand == 1;});  if(starting_phase != null) starting_phase.drop_objection(this);
      endtask : body
      

      實驗驗證(執行?make send_seq_uvm_do?):

      • 日志與前兩種方法一致,但代碼行數最少,uvm_do_with?隱式完成所有步驟。
      • 若修改約束為?{data_en_rand == 0;},波形中?data_en?恒為 0,驗證宏內約束生效。
      3.3 關鍵細節與對比

      (1)方法選擇建議

      • 調試子?sequence:用?start?函數,逐行控制實例化、隨機化、啟動,方便定位問題(如約束不生效時,檢查?randomize?調用 )。
      • 需顯式隨機化:用?uvm_create/uvm_send,手動控制隨機化時機(如先隨機化部分字段,再覆蓋其他約束 )。
      • 日常嵌套發送:優先用?uvm_do_with,代碼最簡潔,減少樣板代碼,適合高頻使用。

      (2)易錯點

      • p_sequencer?未關聯:若子?sequence?未通過?uvm_declare_p_sequencer?關聯父?sequencerp_sequencer?會空指針報錯,需確保:

        systemverilog

        `uvm_declare_p_sequencer(dadd_sequencer)  // 在子 sequence 中聲明
        
      • 約束未生效:若?uvm_do_with?中約束語法錯誤(如?data_en_rand = 1;?少寫?==?),約束會被忽略,需檢查約束表達式。
      3.4 實驗價值與總結

      通過?Makefile?腳本切換方法(send_seq_start/send_seq_uvm_create/send_seq_uvm_do?),可直觀對比三類方法的執行流程:

      • 證明三類方法本質是同一流程的不同封裝,uvm_do?是最簡潔的高階用法。
      • 驗證平臺可靈活切換子?sequence?的調度方式,適配不同測試場景(如調試、高效開發、復雜約束 )。

      掌握這三類方法,可高效實現 “父?sequence?調度子?sequence” 的嵌套邏輯,是構建復雜驗證場景(如 “先復位子?sequence,再隨機讀寫子?sequence” )的基礎。

      本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
      如若轉載,請注明出處:http://www.pswp.cn/web/93276.shtml
      繁體地址,請注明出處:http://hk.pswp.cn/web/93276.shtml
      英文地址,請注明出處:http://en.pswp.cn/web/93276.shtml

      如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

      相關文章

      前往中世紀 送修改器(Going Medieval)免安裝中文版

      網盤鏈接&#xff1a; 前往中世紀 免安裝中文版 名稱&#xff1a;前往中世紀 送修改器&#xff08;Going Medieval&#xff09;免安裝中文版 描述&#xff1a; 在Going Medieval的世界中&#xff0c;黑暗時代的社會已瀕臨崩潰。14世紀末瘟疫肆虐&#xff0c;全球95%的人口因…

      Font Awesome 參考手冊

      Font Awesome 參考手冊 引言 Font Awesome 是一個功能強大的圖標庫,它允許開發者通過簡單的 CSS 類來添加圖標到網頁中。本手冊旨在為開發者提供全面的 Font Awesome 使用指南,包括圖標選擇、樣式定制以及常見問題解答。 圖標選擇 圖標分類 Font Awesome 提供了多種類別…

      源網荷儲一體化零碳智慧工業園區建設

      針對傳統工業園區等電力消納大戶存在的供電模式單一、能源管理錯雜、園區人員設備安全統籌不到位等諸多問題&#xff0c;通過AI分析及物聯網等新技術和自研交直流關鍵設備的應用&#xff0c;在三維場景中構建集智慧能源、智慧安防、碳排放管理及智慧運營等功能于一體的新型零碳…

      MySQL表操作(DDL)

      MySQL表操作創建表查看表結構修改表結構增加一列刪除一列修改某一列的屬性修改某一列的名字修改某一列的屬性和名字插入幾條信息刪除表創建表 語法&#xff1a; CREATE TABLE table_name ( field1 datatype, field2 datatype, field3 datatype ) character set 字符集 collat…

      【總結】Python多線程

      【總結】Python多線程備注一、基本概念二、備注 2025/08/15 星期五 最近用到了python的多線程發現和其他語言有點不同記錄一下 一、基本概念 首先要理解一下線程、進程和協程的概念 線程&#xff08;Thread&#xff09;&#xff1a;是計算機能夠調度的最小計算單位 進程&…

      【c++深入系列】:萬字詳解模版(下)

      &#x1f525; 本文專欄&#xff1a;c &#x1f338;作者主頁&#xff1a;努力努力再努力wz &#x1f4aa; 今日博客勵志語錄&#xff1a; 成功沒有標準答案&#xff0c;但堅持永遠是必選項 ★★★ 本文前置知識&#xff1a; 模版(上&#xff09; 那么在之前的文章中我們展示…

      Docker部署美化SunPanel導航頁

      使用Cloudflare Tunnels穿透的地址:星霜導航 由于是使用的iStore里面的SunPanel導航頁,只是基本的功能 頁腳配置 <!DOCTYPE html> <html lang="zh-CN"> <head><meta charset="UTF-8"><meta name="viewport" conte…

      支持向量機的原理和案例解析

      支持向量機的原理和案例解析一、支持向量機的核心目標&#xff1a;間隔最大化步驟1&#xff1a;定義分離超平面步驟2&#xff1a;定義樣本到超平面的距離&#xff08;間隔&#xff09;步驟3&#xff1a;間隔最大化的目標步驟4&#xff1a;簡化目標函數二、通過拉格朗日乘子法求…

      【教程】Nginx 源碼安裝

      開發環境&#xff1a;VMWare 操作系統&#xff1a;紅帽 Linux 8 ? 前言 以離線環境安裝為前提&#xff0c;需準備以下 rmp 包內容&#xff1a; gccmakepcre-develzlib-developenssl-devel 如何準備可參考【教程】準備離線可用的 RPM 包 ? 流程 準備離線包 # 安裝 rpm yu…

      俄羅斯信封套娃問題-二維最長遞增子序列

      354. 俄羅斯套娃信封問題 - 力扣&#xff08;LeetCode&#xff09; Solution 對一個維度從小到大排序&#xff0c;然后對另外一個維度求最長上升子序列即可。 class Solution { public:struct node {int w, h;node(int w, int h) {this->w w;this->h h;}};static bool…

      區塊鏈:用數學重構信任的數字文明基石

      在數字經濟浪潮席卷全球的今天&#xff0c;虛擬與現實的融合正面臨一個根本性挑戰——如何讓數字世界的"承諾"擁有與現實世界同等的可信度&#xff1f; 當我們在電商平臺下單時&#xff0c;如何確保商品質量與描述一致&#xff1f;當企業簽署電子合同時&#xff0c;如…

      Go語言defer機制詳解與應用

      一、defer作用Go語言的defer關鍵字提供了一種延遲執行機制&#xff0c;它能確保指定的函數調用在當前函數返回前被執行。這一特性常用于資源釋放和異常處理場景。二、defer基本特性&#xff08;1&#xff09;執行時機&#xff1a;defer 語句會在外層函數返回前執行&#xff0c;…

      服務器安全防護詳細介紹

      一、方案概述隨著信息技術的飛速發展&#xff0c;服務器作為企業數據存儲、業務運行的核心載體&#xff0c;其安全性至關重要。本服務器安全防護方案旨在通過多層次、全方位的安全防護策略&#xff0c;構建一個完整的服務器安全防護體系&#xff0c;有效抵御各類安全威脅&#…

      網站與政務新媒體自查情況的報告工具功能

      要高效地完成網站與政務新媒體的自查&#xff0c;并生成報告&#xff0c;通常需要借助專業的自動化巡檢工具。這些工具能夠模擬人工檢查&#xff0c;但速度更快、覆蓋面更廣&#xff0c;并且能將發現的問題匯總成結構化的報告。一、網站與政務新媒體自查報告的工具實現功能這類…

      JVM核心原理與實戰優化指南

      一、成為卓越的Java開發者 無論你是大學生還是資深工程師&#xff0c;學習JVM都至關重要。你可能是為了&#xff1a; 征服技術面試進行系統調優深入理解Java生態 學習路徑建議&#xff1a; 從Java語言本質切入&#xff0c;逐步深入JVM核心機制&#xff0c;兼顧不同背景學習者…

      TCP/IP、socket、http

      區分與聯系 TCP/IP 是底層規則,規定數據如何傳輸; Socket 是操作 TCP/IP 的工具,讓程序能實現通信; HTTPS 是上層應用,用 Socket 調用 TCP/IP 協議,實現安全的數據傳輸。 應用層:HTTPS(基于 HTTP + SSL/TLS)| | socket連接了應用層和傳輸層↓ 傳輸層:TCP(可靠…

      Go語言中的指針接收者

      Go語言中的指針接收者&#xff08;Pointer Receiver&#xff09;與Java類中的方法在設計思想上確實有相似之處&#xff0c;尤其在對象狀態修改和性能優化上&#xff0c;但兩者在實現機制和語言哲學上存在顯著差異。以下從核心特性、設計對比和應用場景展開分析&#xff1a;一、…

      計算機視覺(opencv)實戰三——圖像運算、cv2.add()、cv2.addWeighted()

      圖像運算詳解&#xff1a;加法運算與加權運算在數字圖像處理中&#xff0c;圖像運算是基礎且常用的操作之一。它能夠對兩幅圖像或圖像與常數進行加減乘除&#xff0c;從而實現亮度調整、融合疊加、特效制作等功能。本文將重點介紹 OpenCV 中的圖像加法運算與加權運算&#xff0…

      Redis核心架構

      一、核心模塊如圖 Client 客戶端&#xff0c;官方提供了 C 語言開發的客戶端&#xff0c;可以發送命令&#xff0c;性能分析和測試等。網絡層事件驅動模型&#xff0c;基于 I/O 多路復用&#xff0c;封裝了一個短小精悍的高性能 ae 庫&#xff0c;全稱是 a simple event-driven…

      Python爬蟲大師課:HTTP協議深度解析與工業級請求封裝

      Python爬蟲大師課&#xff1a;HTTP協議深度解析與工業級請求封裝 從零構建企業級爬蟲框架&#xff08;附完整源碼&#xff09; 一、爬蟲基礎&#xff1a;網絡世界的通行證 ??HTTP協議核心數據??&#xff1a; 全球網站數量&#xff1a;20億 HTTP請求占比&#xff1a;83% …