即使聽起來很簡單,但在實際實現中,在UVM agent中處理reset也不是那麼簡單。
在本文中,我將介紹一種處理reset的通用機制,該機制可以在任何UVM agent中重複使用。
讓我們考慮一下,我們有一個具有以下架構的UVM agent:
步驟#1:處理agent組件中的reset
因爲agent是最重要的組件,所以我們可以在其中實現一些邏輯,該邏輯可以檢測到reset何時變爲活動狀態,然後通知其所有子組件,它們應該reset其邏輯(包括driver,monitor,sequencer等)。
class cfs_agent extends uvm_agent;
...
virtual task run_phase(uvm_phase phase);
forever begin
wait_reset_start();
if(agent_config.get_should_handle_reset() == 1) begin
handle_reset(phase, "HARD");
end
wait_reset_end();
end
endtask
...
endclass
通知所有子組件,它們應該重新reset相應邏輯,其實很簡單:
class cfs_agent extends uvm_agent;
...
virtual function void handle_reset(uvm_phase phase, string kind = "HARD");
monitor.handle_reset(kind);
if(driver != null) begin
driver.handle_reset(kind);
end
if(sequencer != null) begin
sequencer.handle_reset(phase, kind);
end
if(coverage != null) begin
coverage.handle_reset(kind);
end
//add here any other component which might need to be reset
endfunction
...
endclass
在agent配置類中,我們聲明用於控制reset處理的開關:
class cfs_agent_config extends uvm_component;
...
protected bit should_handle_reset;
function new(string name = "");
super.new(name);
should_handle_reset = 1;
endfunction
virtual function bit get_should_handle_reset();
return should_handle_reset();
endfunction
virtual function void set_should_handle_reset(bit should_handle_reset);
this.should_handle_reset = should_handle_reset;
endfunction
endclass
關於此切換背後的原因,請看一下本文的第2部分。
如果您想找到我們如何更好地抽象該agent邏輯,請閱讀SystemVerilog中的“多重繼承”。
步驟#2:處理monitor組件中的復位
從最基本的角度來看,monitor程序邏輯是一個連續的循環,它監視某些物理總線並收集所有傳輸。
基於此,我們可以說復位邏輯應停止該循環(無論復位來時其狀態如何),清除所有臨時信息並在復位完成後重新啓動監視循環。
當然,無論agnet處理的物理協議如何,都必須這樣做。
class cfs_monitor extends uvm_monitor;
...
//process for collect_transactions() task
protected process process_collect_transactions;
//task for collecting all transactions
virtual task collect_transactions();
fork
begin
process_collect_transactions = process::self();
forever begin
collect_transaction();
end
end
join
endtask
virtual task run_phase(uvm_phase phase);
forever begin
fork
begin
wait_reset_end();
collect_transactions();
disable fork;
end
join
end
endtask
//function for handling reset
virtual function void handle_reset(string kind = "HARD");
if(process_collect_transactions != null) begin
process_collect_transactions.kill();
end
//clear here any temporary information from the monitor
endfunction
...
endclass
步驟#3:處理driver組件中的復位
我們在monitor中實現的相同邏輯可以適用於driver組件。最後,driver組件的邏輯只是一個循環,等待sequencer的sequence並將它們放在物理總線上。
class cfs_driver extends uvm_driver;
...
//process for drive_transactions() task
protected process process_drive_transactions;
//task for driving all transactions
virtual task drive_transactions();
fork
begin
process_drive_transactions = process::self();
forever begin
cfs_item_drv_master transaction;
seq_item_port.get_next_item(transaction);
drive_transaction(transaction);
seq_item_port.item_done();
end
end
join
endtask
task run_phase(uvm_phase phase);
forever begin
fork
begin
wait_reset_end();
drive_transactions();
disable fork;
end
join
end
endtask
//function for handling reset
virtual function void handle_reset(string kind = "HARD");
if(process_drive_transactions != null) begin
process_drive_transactions.kill();
end
//clear here any temporary information, initialize some interface signals etc
endfunction
...
endclass
步驟4:在sequencer組件中處理重置
復位sequencer非常簡單。我們只需要確保丟棄所有待處理的項目,以便sequencer可以在重置後處理新項目:
class cfs_sequencer extends uvm_sequencer;
...
virtual function void handle_reset(uvm_phase phase, string kind = "HARD");
uvm_objection objection = phase.get_objection();
int objections_count;
stop_sequences();
objections_count = objection.get_objection_count(this);
if(objections_count > 0) begin
objection.drop_objection(this, $sformatf("Dropping %0d objections at reset", objections_count), objections_count);
end
start_phase_sequence(phase);
endfunction
...
endclass
步驟5:處理Coverage組件中的復位
復位coverage組件更多地取決於物理協議,因爲沒有上述組件必須執行的“標準”邏輯。
因此,您可以使用handle_reset()函數在復位期間進行一些覆蓋率採樣,並清除所有臨時信息:
class cfs_coverage extends uvm_component;
...
virtual function void handle_reset(string kind = "HARD");
//sample coverage groups related to reset
//clear some temporary information
endfunction
...
endclass
就是這樣!
該技術非常通用,因此可以用於任何agent。
如果您想了解有關如何將此技術集成到通用agent中的更多信息,漢密爾頓·卡特(Hamilton Carter)曾在2015年寫過兩篇關於此類通用agent的文章:
- The Ecstasy and the Agony of UVM Abstraction and Encapsulation Featuring the AMIQ APB VIP: Part I
- Part II: The Ecstasy and the Agony of UVM Abstraction and Encapsulation Featuring the AMIQ APB VIP
希望這可以幫助?
在本文的第2部分中,您可以閱讀有關如何在驗證環境中處理重置的信息:SystemVerilog:如何在UVM中處理復位(第2部分)