2.1 驗(yàn)證平臺(tái)的組成
2.2 只有driver的驗(yàn)證平臺(tái)
2.2.1 最簡(jiǎn)單的驗(yàn)證平臺(tái)
class my_driver extends uvm_driver;
? ? function new(string name = "my_driver", uvm_component parent = null);
? ? ? ? super.new(name, parent);
? ? endfunction
? ? extern virtual task main_phase(uvm_phase phase)
endclass
task my driver::main_phase(uvm_phase phase);
? ? ......
? ? ? ? `uvm_info("my_driver", "data is drived", UVM_LOW)
? ? ......
endtask
uvm_driver是一個(gè)派生字uvm_component的類讹躯,每一個(gè)派生自u(píng)vm_component或其派生類的類在其new函數(shù)種要指明兩個(gè)參數(shù):name 和 parent格郁。
uvm_info宏有三個(gè)參數(shù),第一個(gè)參數(shù)是字符串舷蒲,把打印的信息歸類,第二個(gè)參數(shù)是具體要打印的信息友多,第三個(gè)參數(shù)是冗余級(jí)別(UVM_LOW, UVM_MEDIUM, UVM_HIGH)牲平。
get_full_name() 獲取路徑索引。
2.2.1 加入factory機(jī)制
"my_driver.sv"
class my_driver extends uvm_driver;
? ? `uvm_component_utils(my_driver)
? ? ......
endclass
"top_tb.sv"
module top_tb;
initial begin
? ? run_test("my_driver");
end
endmodule
`uvm_component_utils(my_driver) 其功能之一是將my_driver登記在UVM內(nèi)部的一張表中域滥,這張表是factory功能實(shí)現(xiàn)的基礎(chǔ)纵柿。
一個(gè)run_test語(yǔ)句會(huì)創(chuàng)建一個(gè)my_driver的實(shí)例蜈抓,并會(huì)自動(dòng)調(diào)用my_driver的main_phase。只有在類的定義時(shí)聲明了`uvm_component_utils(my_driver)才能使用這個(gè)功能昂儒。所有派生自u(píng)vm_component及其派生類的類都應(yīng)該使用宏注冊(cè)沟使。
2.2.3 加入objection機(jī)制
task my_driver::main_phase(uvm_phase phase);
? ? phase.raise_objection(this);
? ? ......
? ? phase.drop_objection(this);
endtask
raise_objection語(yǔ)句必須在main_phase種第一個(gè)消耗仿真時(shí)間的語(yǔ)句之前,如$display語(yǔ)句可以放在raise_objection之前渊跋。
2.2.4 加入virtual interface
"top_tb.sv"
module top_tb;
initial begin
? ? run_test("my_driver");
end
initial begin
? ? uvm_config_db#(virtual my_if)::set(null, "uvm_test_top", "vif", input);
end
endmodule
"my_driver.sv"
virtual function void build_phase(uvm_phase phase);
? ? ......
? ? if(!uvm_config_db#(virtual my_if)::get(this, " ", "vif", vif)
? ? ......
endfunction
UVM通過(guò)run_test語(yǔ)句實(shí)例化了一個(gè)脫離了top_tb層次結(jié)構(gòu)的實(shí)例腊嗡,建立了一個(gè)新的層次結(jié)構(gòu)。
對(duì)于這種脫離了top_tb層次結(jié)構(gòu)刹枉,同時(shí)又期望在top_tb中對(duì)其進(jìn)行某些操作的實(shí)例叽唱,UVM引進(jìn)了config_db機(jī)制。
在build_phase中主要通過(guò)config_db的 set 和 get 操作來(lái)傳遞一些數(shù)據(jù)微宝,以及實(shí)例化成員變量等棺亭。build_phase是一個(gè)函數(shù)phase,不消耗仿真時(shí)間蟋软,總是在仿真時(shí)間為0時(shí)執(zhí)行镶摘,而main_phase是一個(gè)任務(wù)phase。
config_db的 set 和 get 函數(shù)都有四個(gè)參數(shù)岳守,這兩個(gè)函數(shù)的第三個(gè)參數(shù)必須完全一致凄敢。set函數(shù)的第四個(gè)參數(shù)表示要將哪個(gè)interface通過(guò)config_db傳遞給my_driver,get函數(shù)的第四個(gè)參數(shù)表示把得到的interface傳遞給哪個(gè)my_driver的成員變量湿痢。set函數(shù)的第二個(gè)參數(shù)表示的是路徑索引涝缝,無(wú)論傳遞給run_test的參數(shù)是什么,創(chuàng)建的實(shí)例的名字都為uvm_test_top譬重,因?yàn)閟et操作的目標(biāo)是my_driver拒逮,所以set函數(shù)的第二個(gè)參數(shù)就是uvm_test_top。
2.3 為驗(yàn)證平臺(tái)加入各個(gè)組件
2.3.1 加入transaction
驗(yàn)證平臺(tái)的組件之間臀规,信息的傳遞是基于transaction的滩援。
class my_transaction extends uvm_sequence_item;
? ? rand bit [47:0] dmac;
? ? ......
? ? constraint ...{}
? ? function bit [31:0] calc_crc();
? ? ? ? return 32'h0;
? ? endfunction
? ? `uvm_object_utils(my_transaction)
? ? function new(...);
? ? ......
endclass
在UVM中,所有transaction都要從uvm_sequence_item派生塔嬉。
my_transaction有生命周期玩徊,這種類都是派生自u(píng)vm_object或者uvm_object的派生類,uvm_sequence_item的祖先就是uvm_object谨究,UVM中具有這種特征的類都要使用uvm_object_utils宏來(lái)實(shí)現(xiàn)恩袱。
2.3.2 加入env
run_test只能實(shí)例化一個(gè)實(shí)例。引入一個(gè)容器類胶哲,在這個(gè)容器類中實(shí)例化driver, monitor, reference model 和 scoreboard等憎蛤,在調(diào)用run_test時(shí),傳遞參數(shù)是這個(gè)容器類,uvm_env俩檬。
class my_env extends uvm_env;
? ? my_driver drv;
? ? ......
? ? virtual function void build_phase(uvm_phase phase);
? ? ? ? super.build_phase(phase);
? ? ? ? drv = my_driver::type_id::create("drv", this);
? ? endfunction
? ? `uvm_component_utils(my_env)
endclass
factory機(jī)制注冊(cè)過(guò)的類的實(shí)例化: type_name::type_id::create()萎胰。
2.3.3 加入monitor
class my_monitor extends uvm_monitor;
? ? virtual my_if vif;
? ? `uvm_component_utils(my_monitor)
? ? function new(...)
? ? ......
? ? virtual function void build_phase(uvm_phase phase);
? ? ......
endclass
2.3.4 封裝成agent
driver和monitor二者處理的是同一種協(xié)議,agent將driver和monitor封裝在一起棚辽,不同agent代表了不同的協(xié)議技竟。
class my_agent extends uvm_agent;
? ? my_driver?????drv;
? ? my_monitor? mon;
? ? ......
? ? `uvm_component_utils(my_agent)
endclass
function void my_agent::build_phase(uvm_phase phase);
? ? super.build_phase(phase);
? ? if(is.active == UVM_ACTIVE) ?? begin
? ? ? ? drv = my_driver::type_id::create("drv", this);
? ? end
? ? mon = my_monitor::type_id::create("mon", this);
endfunction
function void my_agent::connect_phase(uvm_phase phase);
? ? super.connect_phase(phase);
endfunction
is_avtive 是uvm_agent的一個(gè)成員變量:
? ? uvm_active_passive_enum is_active = UVM_ACTIVE;
? ? typedef enum bit {UVM_PASSIVE=0, UVM_ACTIVE=1} uvm_active_passive_enum;
2.3.5 加入reference model
class my_model extends uvm_component;
? ? uvm_blocking_get_port?????#(my_transaction) ? ? port;
? ? uvm_analysis_port ?? #(my_transaction) ?? ap;
在UVM中,通常使用TLM(Transaction Level Modeling)實(shí)現(xiàn)compone之間transaction級(jí)別的通信屈藐。
數(shù)據(jù)的一種發(fā)送方式:uvm_analysis_port
數(shù)據(jù)的一種接收方式:uvm_blocking_get_port
my_monitor在main_phase收集完一個(gè)transaction榔组,將其寫入ap中:
????????????task my_monitor::main_phase(uvm_phase phase);
??????????????? ......
????????????????ap.write(tr);
my_env中使用fifo將 ap 和 port 端口聯(lián)系在一起:
????????????uvm_tlm_analysis_fifo ?? #(my_transaction) ?? agt_mdl_fifo;
????????????......
????????????agt_mdl_fifo = new("agt_mdl_fifo", this);
my_env在connect_phase中將fifo分別與my_monitor中的analysis_port和my_model中的blocking_get_port相連:
? ? ? ? ? ? function void my_env::connect_phase(uvm_phase phase);
? ? ? ? ? ? ? ? super.connect_phase(phase);
? ? ? ? ? ? ? ? i_agt.ap.connect(agt_mdl_fifo.analysis_export);
? ? ? ? ? ? ? ? mdl.port.connect(agt_mdl_fifo.blocking_get_export);
? ? ? ? ? ? endfunction
my_agent在connect_phase中:ap = mon.ap。
2.3.6 加入scoreboard
class my_scoreboard extends uvm_scoreboard;
2.3.7 加入field_automation機(jī)制
class my_transaction extends uvm_sequence_item;
? ? rand bit[47:0] dmac;
? ? rand byte ? ? ? pload[];
? ? ......
? ? `uvm_object_utils_begin(my_transaction)
? ? ? ? `uvm_field_int(dmac, UVM_ALL_ON)
? ? ? ? `uvm_field_array_int(pload, UVM_ALL_ON)
? ? `uvm_object_utils_end
endclass
使用uvm_object_utils_begin和uvm_object_utils_end來(lái)實(shí)現(xiàn)my_factory的factory注冊(cè)联逻,在這兩個(gè)宏中間搓扯,使用uvm_field宏注冊(cè)所有字段,就可以直接調(diào)用copy, compare, print等函數(shù)包归。
data_size = tr.pack_bytes(data_q)/8
? ? ? ? ? ? pack_bytes將 tr 中的所有字段變成byte流放入data_q中锨推,字段按照uvm_field系列宏書寫的順序排列。
data_size = tr.unpack_bytes(data_array)/8
? ? ? ? ? ? unpack_bytes將data_q中的byte流轉(zhuǎn)換成 tr 中的各個(gè)字段公壤,其輸入?yún)?shù)必須是一個(gè)動(dòng)態(tài)數(shù)組换可。
2.4 UVM的終極大作:Sequence
2.4.1 在驗(yàn)證平臺(tái)中加入sequencer
在規(guī)范化的UVM驗(yàn)證平臺(tái)中,driver只負(fù)責(zé)驅(qū)動(dòng)transaction厦幅,而不負(fù)責(zé)產(chǎn)生transaction沾鳄。
class my_sequencer extends uvm_sequencer #(my_transaction);
? ? function new(string name, uvm_component parent);
? ? ? ? super.new(name, parent);
? ? endfunction
? ? `uvm_component_utils(my_sequencer)
endclass
class my_driver extends uvm_driver #(my_transaction);
2.4.2 sequence機(jī)制
class my_sequence extends uvm_sequence #(my_transaction);
? ? my_transaction m_trans;
? ? function new(string name = "my_sequence");
? ? ? ? super.new(name);
? ? endfunction
? ? virtual task body();
? ? ? ? repeat (10) begin
? ? ? ? ? ? `uvm_do(m_trans)
? ? ? ? end
? ? ? ? #1000;
? ? endtask
? ? `uvm_object_utils(my_sequence)
endclass
當(dāng)一個(gè)sequence啟動(dòng)之后,會(huì)自動(dòng)執(zhí)行body中的代碼确憨。
`uvm_do: (1)創(chuàng)建一個(gè)my_transaction的實(shí)例m_trans; (2)將其隨機(jī)化; (3)最終將其送給sequencer译荞。
uvm_driver中有成員變量seq_item_port,uvm_sequencer中有成員變量seq_item_export休弃,這兩者之間可以建立一個(gè)通道吞歼,通道中傳遞transaction。在my_agent中玫芦,使用connect函數(shù)將兩者聯(lián)系在一起:
drv.seq_item_port.connect(sqr.seq_item_export);
2.4.3 default_sequence的使用
"my_env.sv"
virtual function void build_phase(uvm_phase phase);
? ? super.build_phase(phase);
? ? ......
? ? uvm_config_db#(uvm_object_wrapper)::set(this, "i_agt.sqr.main_phase", "default_sequence", my_sequence::type_id::get());
2.5 建造測(cè)試用例
2.5.1 加入base_test
class base_test extends uvm_test;
? ? my_env ?? env;
? ? function new(...)
? ? extern virtual function void build_phase(uvm_phase phase);
? ? extern virtual function void report_phase(uvm_phase phase);
? ? `uvm_component_utils(base_test)
endclass
2.5.2 UVM中測(cè)試用例的啟動(dòng)
class case0_sequence extends uvm_sequence #(my_transaction);
......
endclass
class my_case0 extends base_test
? ? ......
? ? uvm_config_db#(uvm_object_wrapper)::set(this, "env.i_agt.sqr.main_phase", "default_sequence", case0_sequence::type_id::get());
class case1_sequence extends uvm_sequence #(my_transaction);
......
endclass
class my_case1 extends base_test
......
endclass
????????????????