Deepseek解析的回調(diào)繼承關(guān)系
整個(gè)實(shí)現(xiàn)可以分解為三個(gè)關(guān)鍵部分:
-
宏本身: 發(fā)起注冊(cè)請(qǐng)求。
-
注冊(cè)函數(shù) (
register_super_type): 記錄類(lèi)型關(guān)系。 -
回調(diào)執(zhí)行引擎 (
uvm_do_callbacks): 查詢(xún)并使用記錄的關(guān)系。
下圖清晰地展示了這三個(gè)部分如何協(xié)同工作,實(shí)現(xiàn)回調(diào)繼承:
flowchart TD
A[派生類(lèi)中的宏<br>uvm_set_super_type(B, A)]
--> B["調(diào)用 register_super_type()<br>在內(nèi)部映射表添加條目: B -> A"]
C["uvm_do_callbacks(A, ...)<br>在類(lèi)型B的對(duì)象中執(zhí)行"]
--> D{"查詢(xún)映射表:<br>B是否有超類(lèi)型?"}
D -- 是 --> E["獲取超類(lèi)型A<br>合并A和B的回調(diào)列表"]
D -- 否 --> F[僅使用類(lèi)型B的回調(diào)列表]
E --> G[執(zhí)行合并后列表中的所有回調(diào)]
F --> G
第1部分:宏 - 注冊(cè)請(qǐng)求的發(fā)起者
宏的定義非常簡(jiǎn)單:
`define uvm_set_super_type(T,ST) \ static local bit m_register_``T``ST = uvm_derived_callbacks#(T,ST)::register_super_type(`"T`",`"ST`");
-
作用: 在派生類(lèi)
T的代碼中,在編譯時(shí)插入一行靜態(tài)變量的初始化語(yǔ)句。 -
執(zhí)行時(shí)機(jī): 在仿真開(kāi)始前的** elaboration **階段,當(dāng)類(lèi)被加載時(shí),這個(gè)靜態(tài)變量會(huì)被初始化,從而觸發(fā)
register_super_type函數(shù)的執(zhí)行。 -
結(jié)果: 函數(shù)調(diào)用后,UVM系統(tǒng)內(nèi)部就知道了一個(gè)新的類(lèi)型關(guān)系:“
T是ST的派生類(lèi),在執(zhí)行T的回調(diào)時(shí),也需要檢查ST的回調(diào)?!?/p>
第2部分:注冊(cè)函數(shù) - 關(guān)系記錄員
這是實(shí)現(xiàn)的核心。我們需要想象在UVM內(nèi)部有一個(gè)全局的“類(lèi)型關(guān)系映射表”(通常是一個(gè)關(guān)聯(lián)數(shù)組或隊(duì)列)。
uvm_derived_callbacks#(T, ST)::register_super_type(“T”, “ST”) 這個(gè)函數(shù)的大致偽代碼如下:
class uvm_derived_callbacks #(type T, ST);
static function bit register_super_type(string T_name, ST_name);
// 1. 獲取全局唯一的“類(lèi)型關(guān)系映射表”
// 假設(shè)它叫 `super_type_map` (類(lèi)型: uvm_derived_callbacks_info associative array)
// 2. 創(chuàng)建一個(gè)關(guān)系記錄項(xiàng)
uvm_derived_callbacks_info info = new();
info.super_type = ST; // 記錄超類(lèi)型
// 3. 將關(guān)系記錄到映射表中,鍵是派生類(lèi)型 T
super_type_map[T] = info; // super_type_map[T] = ST
return 1;
endfunction
endclass
這個(gè)函數(shù)的作用就是在上圖所示的“內(nèi)部映射表”中填了一條記錄,將類(lèi)型 T 映射到它的超類(lèi)型 ST。
第3部分:回調(diào)執(zhí)行 - 關(guān)系查詢(xún)與使用者
真正的功能體現(xiàn)在 uvm_do_callbacks 宏(或其背后的 uvm_callback_iter 類(lèi))執(zhí)行時(shí)。
當(dāng)你在代碼中寫(xiě)下:
`uvm_do_callbacks(my_comp, mycb, doit())
UVM會(huì)展開(kāi)這個(gè)宏,其底層會(huì)執(zhí)行類(lèi)似以下的邏輯:
-
獲取當(dāng)前對(duì)象的類(lèi)型 (
obj_type)。 -
查找該類(lèi)型對(duì)應(yīng)的回調(diào)鏈表。
-
關(guān)鍵的一步:遞歸查找超類(lèi)型的回調(diào)!
systemverilog// 偽代碼: 如何構(gòu)建最終的回調(diào)執(zhí)行列表 function uvm_callback::get_tw_cbs(...); uvm_queue #(uvm_callback) callback_queue = new(); // 首先,加入當(dāng)前類(lèi)型 (T) 的所有回調(diào) callback_queue = {current_type_callback_list}; // 然后,開(kāi)始遞歸查找超類(lèi)型 uvm_derived_callbacks_info info; type current = obj_type; // 循環(huán)檢查:當(dāng)前類(lèi)型是否在“類(lèi)型關(guān)系映射表”中注冊(cè)了超類(lèi)型? while (super_type_map.exists(current)) begin // 如果有,就獲取它的超類(lèi)型 (ST) info = super_type_map[current]; current = info.super_type; // 將這個(gè)超類(lèi)型 (ST) 的所有回調(diào)加入到執(zhí)行隊(duì)列中 callback_queue = {callback_queue, get_callback_list_for_type(current)}; end return callback_queue; // 返回合并后的隊(duì)列 endfunction -
按順序執(zhí)行這個(gè)合并后隊(duì)列中的所有回調(diào)函數(shù)。
總結(jié):整個(gè)工作流程
讓我們用之前的例子 my_derived_comp 和 my_comp 來(lái)串聯(lián)整個(gè)流程:
-
注冊(cè)(Elaboration階段):
-
編譯器看到
uvm_set_super_type(my_derived_comp, my_comp)。 -
宏展開(kāi),調(diào)用
register_super_type(“my_derived_comp”, “my_comp”)。 -
函數(shù)執(zhí)行,在內(nèi)部映射表中寫(xiě)入:
my_derived_comp -> my_comp。
-
-
執(zhí)行(Simulation階段):
-
用戶(hù)為
my_comp添加了一個(gè)全局回調(diào)cb_obj。 -
my_derived_comp的實(shí)例在run_phase中執(zhí)行uvm_do_callbacks(my_comp, mycb, doit())。 -
UVM回調(diào)系統(tǒng):
a. 發(fā)現(xiàn)當(dāng)前對(duì)象類(lèi)型是my_derived_comp。
b. 查找my_derived_comp類(lèi)型的回調(diào)鏈表(假設(shè)為空)。
c. 查詢(xún)映射表:”my_derived_comp有超類(lèi)型嗎?“ -> 有,是my_comp。
d. 查找my_comp類(lèi)型的回調(diào)鏈表 -> 找到了用戶(hù)添加的cb_obj。
e. 將my_comp的回調(diào)鏈表合并到最終的執(zhí)行列表中。
f. 執(zhí)行cb_obj.doit()。
-
因此,這個(gè)宏的實(shí)現(xiàn)精髓在于:它通過(guò)在UVM內(nèi)部建立一個(gè)“類(lèi)型關(guān)系地圖”,讓回調(diào)執(zhí)行引擎在執(zhí)行時(shí)能夠“順藤摸瓜”,找到所有相關(guān)基類(lèi)上注冊(cè)的回調(diào),從而實(shí)現(xiàn)繼承。 這是一種經(jīng)典的注冊(cè)-查詢(xún)(Registration-Lookup) 設(shè)計(jì)模式。

浙公網(wǎng)安備 33010602011771號(hào)