在本文中,我們將進(jìn)一步實現(xiàn)monitor和coverage collector components,以便在仿真期間收集功能覆蓋信息。
實現(xiàn)monitor
為了在驗證環(huán)境中進(jìn)行檢查或覆蓋率收集,我們首先需要完成monitor的實現(xiàn)。與前文driver代碼的生成實現(xiàn)類似,我們使用template files指示uvm代碼生成器包含我們的任務(wù)。
Filename include/clkndata_do_mon.sv task clkndata_monitor::do_mon(); forever @(posedge vif.clk) begin m_trans = data_tx::create("m_trans"); m_trans.data = vif.data; analysis_port.write(m_trans); end endtask
和driver一樣,任務(wù)的命名需要以agent接口為前綴。do_mon任務(wù)應(yīng)monitor DUT 接口,然后組裝成一個事務(wù)m_trans,最后通過analysis_port發(fā)送出去。
Filename clkndata.tpl ... driver_inc = clkndata_do_drive.sv monitor_inc = clkndata_do_mon.sv ...
實現(xiàn)Covergroup
uvm代碼生成器將生成一個subscriber component,該組件連接到monitor的analysis_port。默認(rèn)情況下,此subscriber將使用covergroup對任何接收到的事務(wù)值進(jìn)行采樣。自動生成的代碼如下所示:
Filename clkndata_coverage.sv class clkndata_coverage extends uvm_subscriber #(data_tx); `uvm_component_utils(clkndata_coverage) bit m_is_covered; data_tx m_item; covergroup m_cov; option.per_instance = 1; cp_data: coverpoint m_item.data; endgroup extern function new(string name, uvm_component_parent); extern function void write(input data_tx t); endclass function clkndata_coverage::new(string name, uvm_component_parent); super.new(name, parent); m_is_covered = 0; m_cov = new; endfunction function void clkndata_coverage::write(input data_tx t); m_item = t; m_cov.sample(); if (m_cov.get_inst_coverage() >= 100) m_is_covered = 1; endfunction ...
為了完成覆蓋模型,可以在include文件中提供一組用戶定義的coverpoints,例如:
Filename include/clkndata_cover_inc.sv covergroup m_cov; option.per_instance = 1; cp_data: coverpoint m_item.data { bins zero = {0}; bins one = {1}; bins negative = { [-128:-1] }; bins positive = { [1:127] }; option.at_least = 16; } endgroup
同樣,必須使用正確的命名約定。文件名前綴為agent interface,必須將covergroup 命名為 m_cov,并且引用輸入事務(wù)的變量名稱必須為m_item。
Filename clkndata.tpl ... driver_inc = clkndata_do_drive.sv monitor_inc = clkndata_do_mon.sv agent_cover_inc = clkndata_cover_inc.sv ...
生成的subscriber component現(xiàn)在包括剛剛提供的covergroup:
Filename clkndata_coverage.sv class clkndata_coverage extends uvm_subscriber #(data_tx); ... data_tx m_item; `include "clkndata_cover_inc.sv" ... extern function void write(input data_tx t); ... endclass
進(jìn)一步擴展生成的代碼
上述文件 clkndata_cover_inc.sv 僅包含一個covergroup。生成的代碼實例化該covergroup,并包含一個用于對covergroup進(jìn)行sample的write方法。但是,如果你需要subscriber 采取除samplecovergroup之外或而不是采樣的其他操作怎么辦?答案是,不僅可以include covergroup,還可以從一組include文件中提取類的所有內(nèi)容。如果要自己提供 new 和 write 方法,則還需要禁止自動生成它們。為此,你需要更改 interface template file,如下所示:
Filename clkndata.tpl ... #agent_cover_inc = clkndata_cover_inc.sv agent_cover_inc_inside_class = clkndata_cover_inc_inside.sv agent_cover_inc_after_class = clkndata_cover_inc_after.sv agent_cover_generate_methods_inside_class = no agent_cover_generate_methods_after_class = no ...
生成的subscriber 組件現(xiàn)在如下所示:
classclkndata_coverageextendsuvm_subscriber#(data_tx); `uvm_component(clkndata_coverage) `include"clkndata_cover_inc_inside.sv" endclass `include "clkndata_cover_inc_after.sv"
然后,可以提供以下兩個include文件:
Filename include/clkndata_cover_inc_inside.sv covergroup m_cov; option.per_instance = 1; cp_data: coverpoint m_item.data { bins zero = {0}; bins one = {1}; bins negative = { [-128:-1] }; bins positive = { [1:127] }; option.at_least = 16; } endgroup extern function new(string name, uvm_component_parent); extern function void write(input data_tx t); Filename include/clkndata_cover_inc_after.sv function clkndata_coverage::new(string name, uvm_component_parent); super.new(name, parent); m_cov = new; endfunction function void clkndata_coverage::write(input data_tx t); m_item = t; m_cov.sample(); endfunction: write
你現(xiàn)在可以靈活地在這兩個include文件中提供任何代碼。你可以讓用戶定義的代碼插入到生成的代碼中,而不是代碼生成器寫出 'include 指令,如下所示:
Filename clkndata.tpl ... agent_cover_inc_inside_class = clkndata_cover_inc_inside.sv inline agent_cover_inc_after_class = clkndata_cover_inc_after.sv inline ...
Override a Sequence
正如我們在前面的文章中看到的,生成的代碼包含一個top-level virtual sequence:
文件名 top_seq_lib.sv
Filename top_seq_lib.sv ... task top_default_seq::body(); super.body(); ... clkndata_default_seq seq; seq = clkndata_default_seq::create("seq"); seq.randomize(); seq.start(m_clkndata_agent.m_sequencer, this); endtask ...
可以通過擴展創(chuàng)建和啟動的任何default sequence,例如
Filename my_clkndata_seq.sv class my_clkndata_seq extends clkndata_default_seq; ... task body(); ... for (int i = 0; i < 16; i++) begin req = data_tx::create("req"); start_item(req); if ( !req.randomize() with { data == i; }) ... finish_item(req); end endtask endclass
然后,需要在interface template file中標(biāo)識該文件,并將用戶定義的sequence作為default sequence:
Filename clkndata.tpl ... agent_cover_inc = clkndata_cover_inc.sv agent_seq_inc = myclkndata_seq.sv agent_factory_set = clkndata_default_seq my_clkndata_seq
然后,uvm代碼生成器會使用工廠機制覆蓋整個default sequence:
Filenametop_test.sv function void top_test::build_phase(uvm_phase phase); ... clkndata_default_seq::get_type()); ... endfunction
審核編輯:劉清
-
UVM
+關(guān)注
關(guān)注
0文章
182瀏覽量
19167 -
生成器
+關(guān)注
關(guān)注
7文章
315瀏覽量
21002 -
DUT
+關(guān)注
關(guān)注
0文章
189瀏覽量
12373
原文標(biāo)題:Easier UVM Code Generator Part 2:添加用戶定義的代碼
文章出處:【微信號:芯片驗證工程師,微信公眾號:芯片驗證工程師】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論