2.8 interfaces
文章目錄
- 2.8 interfaces
- 前言
- 一、基本介紹
- 二、代碼分析
-
- 1、interface.sv
- 2、仿真結果
- 總結
前言
本文以uvm-1.2/examples/simple/interfaces為例,通過代碼了解UVM中的一些用法。通過這個例子可以基本了解以下知識點:
- interface的作用
- 如何建立一個interface
- 如何使用modport封裝信号
- resource_db機制及其dump
- 如何interface實作驗證環境與待測設計DUT之間的連接配接
一、基本介紹
interface翻譯過來就是接口的意思,interface的作用就是将接口單獨封裝出來,用于驗證環境與待測設計DUT之間的連接配接。将接口單獨封裝出來的好處是,避免接口很多的時候,連接配接的時候容易出錯,另外,當接口有改動的時候,隻需要改變一個檔案即可,不用在每個接口例化的地方全部改一遍。
在這個測試用例中,将通過interface封裝一個接口,在接口内部再通過modport關鍵字,對接口進行分類,最後通過interface,實作驗證環境和待測設計DUT之間的連接配接。
二、代碼分析
代碼比較簡單,隻有一個interface.sv檔案
1、interface.sv
/*
About: uvm_exmples/mechanism/interfaces
This example will illustrate how to create a pin interface and mod port interfaces for a simple dut.
Connect a component "driver" to the pin interfaces, then to the dut.
*/
//----------------------------------------------------------------------
// interface mem_pins_if
//----------------------------------------------------------------------
interface pin_if (input clk);
bit [15:0] address;
bit [7:0] wr_data;
bit [7:0] rd_data;
bit rst;
bit rw;
bit req;
bit ack;
bit err;
modport master_mp(
input clk,
input rst,
output address,
output wr_data,
input rd_data,
output req,
output rw,
input ack,
input err );
modport slave_mp(
input clk,
input rst,
input address,
input wr_data,
output rd_data,
input req,
input rw,
output ack,
output err );
modport monitor_mp(
input clk,
input rst,
input address,
input wr_data,
input rd_data,
input req,
input rw ,
input ack,
input err );
endinterface
import uvm_pkg::*;
package top_pkg;
typedef virtual pin_if pin_vif;
endpackage
package user_pkg;
import uvm_pkg::*;
import top_pkg::*;
`include "uvm_macros.svh"
//---------------------------------------------------------------------
// component driver
//----------------------------------------------------------------------
class driver extends uvm_component;
pin_vif pif;
function new(string name, uvm_component parent = null);
super.new(name, parent);
endfunction
function void connect_phase(uvm_phase phase);
assert(uvm_resource_db#(pin_vif)::read_by_name(get_full_name(),
"pif", pif));
endfunction
task run_phase(uvm_phase phase);
forever begin
@(posedge pif.clk);
`uvm_info("driver", "posedge clk", UVM_NONE);
//...
end
endtask
endclass
//----------------------------------------------------------------------
// environment env
//----------------------------------------------------------------------
class env extends uvm_env;
local pin_vif pif;
driver d;
function new(string name, uvm_component parent = null);
super.new(name, parent);
d = new("driver", this);
endfunction
task run_phase(uvm_phase phase);
phase.raise_objection(this);
#100;
phase.drop_objection(this);
endtask
endclass
endpackage
//import user_pkg::*;
//----------------------------------------------------------------------
// module dut
//----------------------------------------------------------------------
module dut(pin_if pif);
always @(posedge pif.clk) begin
`uvm_info("dut", "posedge clk", UVM_NONE);
//...
end
endmodule
//----------------------------------------------------------------------
// module clkgen
//----------------------------------------------------------------------
module clkgen(output bit clk);
initial begin
forever begin
#5 clk = 1;
#5 clk = 0;
end
end
endmodule
//----------------------------------------------------------------------
// module top
//----------------------------------------------------------------------
module top;
import top_pkg::*;
import user_pkg::*;
bit clk;
clkgen ck(clk);
pin_if pif(clk);
env e;
dut d(pif.slave_mp);
initial begin
e = new("env");
uvm_resource_db#(pin_vif)::set("env.driver", "pif", pif);
uvm_resource_db#(pin_vif)::dump();
run_test();
//$finish;
end
endmodule
第14到56行,利用interface——endinterface關鍵字封裝了一組接口。
14行interface封裝的名字是pin_if,參數clk。
15到22行利用bit聲明了一系列的端口名,其實這裡用logic聲明端口名會更好,因為logic聲明的變量支援四個狀态,包括0、1、x、z,而bit聲明的變量隻支援兩個狀态,包括0和1。
24到55行利用modport關鍵字,将信号進行了分組,并指定了每組中變量的輸入輸出狀态。這裡分了三組,包括master_mp、slave_mp和monitor_mp,前兩組用于驅動,最後一組用于監控。
60到62行,通過package封裝了top_pkg,在top_pkg中,利用typedef關鍵字,将virtual pin_if取名叫pin_vif。
65行到117行,通過package封裝了user_pkg,在user_pkg中,聲明了driver和env。
73到94行聲明了dirver元件,其中關鍵的是81到84行的connect_phase,通過調用uvm_resource_db實作驗證環境和待測設計DUT的連接配接,resource_db機制中,存在一個資源池,在頂層将interface放入這個資源池,這裡将資源池裡面的interface按照名字讀出來,進而實作連接配接。assert關鍵字是斷言,用于判斷uvm_resource_db連接配接是否成功,如果連接配接失敗,斷言就會報錯。
99到115行聲明了env元件,env中聲明并例化了drver元件,另外,在109到113的run_phase中,通過“舉手”和“放手”來保證仿真執行的時間。這裡的舉手和放手可以參考張強《UVM實戰》的5.2節objection機制。
123到143行,聲明了兩個簡單的dut和clkgen子產品。dut子產品帶interface參數,clkgen子產品帶時鐘clk參數。
148到168行,聲明了頂層top子產品。在該子產品中例化了interface、dut、clkgen以及env子產品。
其中,153到158行,clkgen用于産生時鐘信号,interface封裝了端口信号,env構成了驗證環境,dut是待測設計(design under test)。clkgen産生的時鐘信号,送入了interface;interface封裝的slave_mp送入了dut。
160到166行,先例化了env,再通過uvm_resource_db的set函數,将interface送入resource_db機制的資源池中,這裡set函數的第一個參數是路徑,第二個參數是辨別符,第三個參數是變量。
163行調用uvm_resource_db的dump函數,列印資源池中的信号用于debug調試。列印的結果如下所示:
UVM_INFO ../../../src/base/uvm_resource.svh(1347) @ 0: reporter [UVM/RESOURCE/DUMP]
=== resource pool ===
pif [/^env\.driver$/] : (virtual interface pin_if) '{clk:'h0, address:'h0, wr_data:'h0, rd_data:'h0, rst:'h0, rw:'h0, req:'h0, ack:'h0, err:'h0}
164行執行仿真。
2、仿真結果
UVM_INFO ../../../src/base/uvm_resource.svh(1347) @ 0: reporter [UVM/RESOURCE/DUMP]
=== resource pool ===
pif [/^env\.driver$/] : (virtual interface pin_if) '{clk:'h0, address:'h0, wr_data:'h0, rd_data:'h0, rst:'h0, rw:'h0, req:'h0, ack:'h0, err:'h0}
UVM_INFO ../../../src/base/uvm_resource.svh(1354) @ 0: reporter [UVM/RESOURCE/DUMP] === end of resource pool ===
UVM_INFO @ 0: reporter [RNTST] Running test ...
UVM_INFO interface.sv(89) @ 5: env.driver [driver] posedge clk
UVM_INFO interface.sv(126) @ 5: reporter [dut] posedge clk
UVM_INFO interface.sv(89) @ 15: env.driver [driver] posedge clk
UVM_INFO interface.sv(126) @ 15: reporter [dut] posedge clk
UVM_INFO interface.sv(89) @ 25: env.driver [driver] posedge clk
UVM_INFO interface.sv(126) @ 25: reporter [dut] posedge clk
UVM_INFO interface.sv(89) @ 35: env.driver [driver] posedge clk
UVM_INFO interface.sv(126) @ 35: reporter [dut] posedge clk
UVM_INFO interface.sv(89) @ 45: env.driver [driver] posedge clk
UVM_INFO interface.sv(126) @ 45: reporter [dut] posedge clk
UVM_INFO interface.sv(89) @ 55: env.driver [driver] posedge clk
UVM_INFO interface.sv(126) @ 55: reporter [dut] posedge clk
UVM_INFO interface.sv(89) @ 65: env.driver [driver] posedge clk
UVM_INFO interface.sv(126) @ 65: reporter [dut] posedge clk
UVM_INFO interface.sv(89) @ 75: env.driver [driver] posedge clk
UVM_INFO interface.sv(126) @ 75: reporter [dut] posedge clk
UVM_INFO interface.sv(89) @ 85: env.driver [driver] posedge clk
UVM_INFO interface.sv(126) @ 85: reporter [dut] posedge clk
UVM_INFO interface.sv(89) @ 95: env.driver [driver] posedge clk
UVM_INFO interface.sv(126) @ 95: reporter [dut] posedge clk
UVM_INFO ../../../src/base/uvm_objection.svh(1270) @ 100: reporter [TEST_DONE] 'run' phase is ready to proceed to the 'extract' phase
UVM_INFO ../../../src/base/uvm_report_server.svh(847) @ 100: reporter [UVM/REPORT/SERVER]
--- UVM Report Summary ---
** Report counts by severity
UVM_INFO : 25
UVM_WARNING : 0
UVM_ERROR : 0
UVM_FATAL : 0
** Report counts by id
[RNTST] 1
[TEST_DONE] 1
[UVM/RELNOTES] 1
[UVM/RESOURCE/DUMP] 2
[driver] 10
[dut] 10
$finish called from file "../../../src/base/uvm_root.svh", line 517.
$finish at simulation time 100
V C S S i m u l a t i o n R e p o r t
Time: 100 ns
通過log可以看到,首先在82行設定的斷言沒有報錯,其次driver列印一個posedge clk,同一時刻dut也列印了一個posedge clk,這說明驗證環境和dut已經完成連接配接。
總結
這個測試用例非常簡單,利用resource_db實作了驗證環境與待測設計之間,通過interface進行連接配接。其實,還可以利用config_db機制進行連接配接,具體可以參考張強的《UVM實戰》3.5節config_db機制。