UVMに入門したくて、簡単な例を用いて試してみることにした。以下のようなシンプルなデザインをテストしたい。
adder
とのインタフェースとして、以下を定義する。これによりテストベンチとDUTを接続する。
verify/addr_if.sv
interface add_if(input logic clk, reset); logic [ 7: 0] ip1, ip2; logic [ 8: 0] out; endinterface // add_if
次に、SequencerとDriverについて見て行く。Sequencerはテストベンチを作成するところだ。
まず、seq_item
によって、ドライブしたい要素をリストアップしていくらしい。ip1
とip2
はランダムに駆動するものと思われるが、out
は値を受け取るだけなので駆動しない。
verify/seq_item.sv
`include "uvm_macros.svh" import uvm_pkg::*; class seq_item extends uvm_sequence_item; rand bit [ 7: 0] ip1, ip2; bit [ 8: 0] out; function new(string name = "seq_item"); super.new(name); endfunction `uvm_object_utils_begin(seq_item) `uvm_field_int(ip1, UVM_ALL_ON) `uvm_field_int(ip2, UVM_ALL_ON) `uvm_object_utils_end constraint ip_c {ip1 < 100; ip2 < 100;} endclass // seq_item
これに基づいて、seqcr
を定義する。seq_item
を拡張する形で定義する。これはテンプレートとして使えそうな構成だ。
verify/seqcr.sv
`include "uvm_macros.svh" import uvm_pkg::*; class seqcr extends uvm_sequencer#(seq_item); `uvm_component_utils(seqcr) function new(string name = "seqcr", uvm_component parent = null); super.new(name, parent); endfunction function void build_phase(uvm_phase phase); super.build_phase(phase); endfunction // build_phase endclass // seqcr
これに基づいてDriverを定義する。Driverはadder_if
を駆動するものだ。ポイントはvif.ip1
とvif.ip2
を駆動するところだ。
どうもこれはseq_item_port.get_next_item(req)
とseq_item_port.item_done()
で囲むところがポイントらしい。
verify/driver.sv
`include "uvm_macros.svh" import uvm_pkg::*; class driver extends uvm_driver#(seq_item); virtual add_if vif; `uvm_component_utils(driver) function new(string name = "driver", uvm_component parent = null); super.new(name, parent); endfunction function void build_phase(uvm_phase phase); super.build_phase(phase); if(!uvm_config_db#(virtual add_if) :: get(this, "", "vif", vif)) `uvm_fatal(get_type_name(), "Not set at top level"); endfunction task run_phase (uvm_phase phase); forever begin // Driver to the DUT seq_item_port.get_next_item(req); `uvm_info(get_type_name, $sformatf("ip1 = %0d, ip2 = %0d", req.ip1, req.ip2), UVM_LOW); vif.ip1 <= req.ip1; vif.ip2 <= req.ip2; seq_item_port.item_done(); end endtask // run_phase endclass // driver