在運(yùn)行uvm代碼生成器后,我們現(xiàn)在可以開始運(yùn)行仿真。同樣,我們將命令行放入腳本文件中:
Filename runius cd generated_tb/sim compile_ius.sh Filename runquesta cd generated_tb/sim vsim -c -do "do compile_questa.do; run -all" Filename runvcs cd generated_tb/sim compile_vcs.sh Filename runriviera cd generated_tb/sim vsimsa -do compile_riviera.do./sim目錄包含運(yùn)行Cadence,Mentor,Synopsys等仿真器的腳本。 生成的驗(yàn)證環(huán)境將運(yùn)行僅生成單個(gè)transaction的sequence,因此在仿真日志中,應(yīng)該會(huì)看到來(lái)自clkndata_driver的UVM_INFO消息,其中打印出transaction中數(shù)據(jù)字段的值,如下所示:
# UVM_INFO ../tb/clkndata/sv/clkndata_driver.sv(47) @ 0: uvm_test_top.m_env.m_clkndata_agent.m_driver [clkndata_driver] req item # vseq.seq.req # data = f4但是,你不會(huì)看到從 DUT 打印出此數(shù)據(jù)值($display(“mydut data = %h”, data);參考前文中DUT的代碼),因?yàn)槲覀兩形刺峁ヾriver的實(shí)現(xiàn),因此盡管driver正在從sequencer接收事務(wù),但它實(shí)際上并沒有驅(qū)動(dòng)DUT接口。
`ifndef CLKNDATA_DRIVER_SV `define CLKNDATA_DRIVER_SV //Youcaninsertcodeherebysettingdriver_inc_before_classinfileclkndata.tpl classclkndata_driverextendsuvm_driver#(data_tx); `uvm_component_utils(clkndata_driver) virtualclkndata_ifvif; clkndata_configm_config; externfunctionnew(stringname,uvm_componentparent); //Youcaninsertcodeherebysettingdriver_inc_inside_classinfileclkndata.tpl endclass:clkndata_driver function clkndata_driver::new(string name, uvm_component parent); super.new(name, parent); endfunction:new //Youcaninsertcodeherebysettingdriver_inc_after_classinfileclkndata.tpl `endif//CLKNDATA_DRIVER_SV實(shí)現(xiàn)driver
為了驅(qū)動(dòng)DUT的接口,我們需要完成driver的實(shí)現(xiàn)。為此,我們可以提供driver需要調(diào)用的任務(wù)代碼,然后在template files指示uvm代碼生成器包含我們的任務(wù)。
Filename include/clkndata_do_drive.sv task clkndata_driver::do_drive(); vif.data <= req.data; @(posedge vif.clk); endtask在此任務(wù)中必須使用正確的命名約定。clkndata是interface template file中的agent名稱,這需要作為任務(wù)和文件名的前綴。要讓uvm代碼生成器包含我們的任務(wù),我們需要添加到interface template file。
Filename clkndata.tpl ... driver_inc = clkndata_do_drive.sv實(shí)現(xiàn)后的driver代碼:
`ifndefCLKNDATA_DRIVER_SV `define CLKNDATA_DRIVER_SV //Youcaninsertcodeherebysettingdriver_inc_before_classinfileclkndata.tpl classclkndata_driverextendsuvm_driver#(data_tx); `uvm_component_utils(clkndata_driver) virtualclkndata_ifvif; clkndata_configm_config; externfunctionnew(stringname,uvm_componentparent); // Methods run_phase and do_drive generated by setting driver_inc in file clkndata.tpl extern task run_phase(uvm_phase phase); externtaskdo_drive(); //Youcaninsertcodeherebysettingdriver_inc_inside_classinfileclkndata.tpl endclass:clkndata_driver function clkndata_driver::new(string name, uvm_component parent); super.new(name, parent); endfunction : new task clkndata_driver::run_phase(uvm_phase phase); `uvm_info(get_type_name(),"run_phase",UVM_HIGH) forever begin seq_item_port.get_next_item(req); `uvm_info(get_type_name(), {"req item ",req.sprint}, UVM_HIGH) do_drive(); seq_item_port.item_done(); end endtask:run_phase // Start of inlined include file generated_tb/tb/include/clkndata_do_drive.sv task clkndata_driver::do_drive(); vif.data <= req.data; @(posedge vif.clk); endtask //?End?of?inlined?include?file //?You?can?insert?code?here?by?setting?driver_inc_after_class?in?file?clkndata.tpl `endif // CLKNDATA_DRIVER_SV我們現(xiàn)在可以使用與以前相同的腳本簡(jiǎn)單地重新運(yùn)行uvm代碼生成器和仿真。 仿真器log說(shuō)明DUT被正確地驅(qū)動(dòng)了:
# mydata data = f4此消息表明,我們的DUT 現(xiàn)在正在通過(guò) clkndata 接口接收事務(wù)。驗(yàn)證環(huán)境仍然只向 DUT 發(fā)送一個(gè)transaction,如何配置發(fā)送多個(gè)transaction?
發(fā)送多個(gè)transaction
uvm代碼生成器生成的代碼默認(rèn)發(fā)送單個(gè)transaction,可以使用common template file中的設(shè)置輕松更改此值。
Filename common.tpl dut_top = mydut top_default_seq_count = 10修改后再重新生成uvm代碼。
`ifndefTOP_SEQ_LIB_SV `define TOP_SEQ_LIB_SV class top_default_seq extends uvm_sequence #(uvm_sequence_item); `uvm_object_utils(top_default_seq) top_config m_config; clkndata_agent m_clkndata_agent; // Number of times to repeat child sequences int m_seq_count = 10; extern function new(string name = ""); extern task body(); extern task pre_start(); extern task post_start(); `ifndef UVM_POST_VERSION_1_1 // Functions to support UVM 1.2 objection API in UVM 1.1 extern function uvm_phase get_starting_phase(); extern function void set_starting_phase(uvm_phase phase); `endif endclass : top_default_seq function top_default_seq::new(string name = ""); super.new(name); endfunction : new task top_default_seq::body(); `uvm_info(get_type_name(), "Default sequence starting", UVM_HIGH) repeat (m_seq_count) begin fork if (m_clkndata_agent.m_config.is_active == UVM_ACTIVE) begin clkndata_default_seq seq; seq = clkndata_default_seq::create("seq"); seq.set_item_context(this, m_clkndata_agent.m_sequencer); if ( !seq.randomize() ) `uvm_error(get_type_name(), "Failed to randomize sequence") seq.m_config = m_clkndata_agent.m_config; seq.set_starting_phase( get_starting_phase() ); seq.start(m_clkndata_agent.m_sequencer, this); end join end `uvm_info(get_type_name(), "Default sequence completed", UVM_HIGH) endtask : body task top_default_seq::pre_start(); uvm_phase phase = get_starting_phase(); if (phase != null) phase.raise_objection(this); endtask: pre_start task top_default_seq::post_start(); uvm_phase phase = get_starting_phase(); if (phase != null) phase.drop_objection(this); endtask: post_start `ifndef UVM_POST_VERSION_1_1 function uvm_phase top_default_seq::get_starting_phase(); return starting_phase; endfunction: get_starting_phase function void top_default_seq::set_starting_phase(uvm_phase phase); starting_phase = phase; endfunction: set_starting_phase `endif //Youcaninsertcodeherebysettingtop_seq_incinfilecommon.tpl `endif // TOP_SEQ_LIB_SV現(xiàn)在運(yùn)行仿真腳本,將看到 DUT 接收 10 個(gè)transaction而不是1個(gè)transaction。 我們可以通過(guò)類似的方式實(shí)現(xiàn)driver、monitor、fcov收集。
任何包含文件都必須放在名為 ./include 的目錄中或者可以使用common template file設(shè)置inc_path選擇其他目錄名稱。
審核編輯:劉清
-
仿真器
+關(guān)注
關(guān)注
14文章
1019瀏覽量
83849 -
UVM
+關(guān)注
關(guān)注
0文章
182瀏覽量
19197 -
生成器
+關(guān)注
關(guān)注
7文章
317瀏覽量
21062 -
DUT
+關(guān)注
關(guān)注
0文章
189瀏覽量
12439
原文標(biāo)題:Easier UVM Code Generator Part 1: 運(yùn)行仿真
文章出處:【微信號(hào):芯片驗(yàn)證工程師,微信公眾號(hào):芯片驗(yàn)證工程師】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論