本文是基于我写的一个培训材料,内容除了没有寄存器模型以及一些大型环境中需要用到的配置文件,其他的都有涵盖。下面我将会从以下四个方面简单分享。
1,UVM introduction
2,UVM TB Tree
3,UVM TB elements
4,UVM TB example
一,UVM introduction
What is UVM?
UVM is abbreviation for Universal Verification Methodology ,it is evolution from OVM, which is Open Verification Methodology. A new generation of verification methodology jointly developed by Cadence, Mentor and Synopsys.
UVM is mainly used to verify the digital logic circuits whether meet the specification requirements.
UVM is a library based on the system verilog platform , provides a series of interfaces , make it easier for engineers to develop.
简单的test bench
a UVM Test Bench Tree
下面是本文例子中需要用到的时序图
写时序
读时序
UVM 各个组件
1.interface:简单理解就是环境与DUT时序通信用到的组件
interface exp_if (input bit clk);// single clock
logic reset_n; // here is the timing list
logic [17:0] exp_addr_i;
logic [3:0] exp_d_i;
logic exp_ceb_i;
logic exp_rwb_i;
logic [3:0] exp_q_o;
logic exp_dv_o;
logic exp_avail_o;
clocking drv_clk @(posedge clk); //clocking block for single clock, if you have more than clock
output exp_addr_i; // need to separate for each clock area
output exp_d_i;
output exp_ceb_i;
output exp_rwb_i;
input exp_avail_o;
endclocking
clocking imon_clk @(posedge clk); //clocking block for signals sync up for same clock
input exp_addr_i;
input exp_d_i;
input exp_ceb_i;
input exp_rwb_i;
endclocking
clocking omon_clk @(posedge clk);
input exp_addr_i;
input exp_ceb_i;
input exp_rwb_i;
input exp_avail_o;
input exp_q_o;
input exp_dv_o;
endclocking
modport drv_mp(clocking drv_clk,output reset_n); //for grouping and direction
modport imon_mp(clocking imon_clk);
modport omon_mp(clocking omon_clk);
endinterface
2.Transaction
`ifndef EXP_PACKET_SV //avoid the same file confict
define EXP_PACKET_SV
`include "uvm_macros.svh" //include all uvm macro
class exp_packet extends uvm_sequence_item;
rand bit[17:0] exp_addr;
rand bit[3:0] data;
rand bit rw;//0:write;1:read
rand bit cen;//chip enable
rand bit dat_vld_o;
`uvm_object_utils_begin(exp_packet)
`uvm_field_int(exp_addr,UVM_ALL_ON)
`uvm_field_int(data,UVM_ALL_ON)
`uvm_field_int(rw,UVM_ALL_ON)
`uvm_field_int(cen,UVM_ALL_ON)
`uvm_field_int(dat_vld_o,UVM_ALL_ON)
`uvm_object_utils_end
function new(string name = "exp_packet");
super.new(name);
`uvm_info("TRACE",$sformatf("%m"),UVM_HIGH);
endfunction
endclass
`endif
3.Sequence for write
class exp_normal_write_sqs extends uvm_sequence #(exp_packet); //RW = 0 is write
rand bit[17:0] addr;
rand bit[3:0] my_data;
`uvm_object_utils(exp_normal_write_sqs)
function new(string name= "exp_normal_write_sqs" );
super.new(name);
endfunction
virtual task body();
`uvm_info("TRACE",$sformatf("%m"),UVM_HIGH); /* write */
`uvm_create(req)
`uvm_rand_send_with(req,{req.exp_addr == addr;req.data == my_data;req.cen ==1'b0;req.rw ==1'b0;});
endtask:body
endclass
4.Sequence for read
class exp_normal_read_sqs extends uvm_sequence #(exp_packet); // RW =1 is read
rand bit[17:0] addr;
rand bit[3:0] my_data;
`uvm_object_utils(exp_normal_read_sqs)
function new(string name= "exp_normal_read_sqs" );
super.new(name);
endfunction
virtual task body();
`uvm_info("TRACE",$sformatf("%m"),UVM_HIGH); /* read */
`uvm_create(req)
`uvm_rand_send_with(req,{req.exp_addr == addr;req.data == my_data;req.cen ==1'b0;req.rw ==1'b1;});
endtask:body
endclass
5.sequence lib
`include "exp_normal_read_sqs.sv"
`include "exp_normal_write_sqs.sv"
6.driver
`ifndef EXP_DRV_SV
`define EXP_DRV_SV
class exp_drv extends uvm_driver #(exp_packet);
//drive the correct signals to handshake with DUT
virtual exp_if inst_exp_if;
function new(string name,uvm_component parent);
super.new(name,parent);
`uvm_info("TRACE",$sformatf("%m"),UVM_HIGH);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
`uvm_info("TRACE",$sformatf("%m"),UVM_HIGH);
uvm_config_db #(virtual exp_hrqm_io)::get(this,"","exp_if",inst_exp_if);
if(inst_exp_if == null)
`uvm_fatal("CFG INTERFACE ERR","Interface of exp_drv is not set");
endfunction
virtual function void start_of_simulation_phase(uvm_phase phase);
super.start_of_simulation_phase(phase);
`uvm_info("TRACE", $sformatf("%m"), UVM_HIGH);
endfunction: start_of_simulation_phase
virtual task run_phase(uvm_phase phase);
`uvm_info("TRACE",$sformatf("%m"),UVM_HIGH);
send_idle();
repeat(3) @(inst_exp_if.drv_clk);
forever begin
seq_item_port.try_next_item(req);
if(req==null)begin
send_idle();
end
else begin
$display("drv get tran");
req.print();
`uvm_info("DRV_RUN", {"\n", req.sprint()}, UVM_MEDIUM);
wait(inst_exp_if.drv_clk.exp_avail_o==1'b1);
if(req.cen == 0 && req.rw == 0)begin
write_pkt(req);
`uvm_info("DRV_RUN", {"\n", req.sprint()}, UVM_MEDIUM);
end
else if(req.cen == 0 && req.rw == 1)begin
read_pkt(req);
end
else begin
chip_uen(req);
end
seq_item_port.item_done();
end
end
endtask:run_phase
virtual task write_pkt(exp_packet tr);// for exp write drv real data and addr togather
`uvm_info("TRACE",$sformatf("%m"),UVM_HIGH);
inst_exp_if.drv_clk.exp_ceb_i <= 0;
inst_exp_if.drv_clk.exp_rwb_i <= 0;
inst_exp_if.drv_clk.exp_addr_i <= tr.exp_addr;
inst_exp_if.drv_clk.exp_d_i <= tr.data;
@(inst_exp_if.drv_clk);
endtask:write_pkt
virtual task read_pkt(exp_packet tr);//for exp read just drv the real addr to dut
`uvm_info("TRACE",$sformatf("%m"),UVM_HIGH);
inst_exp_if.drv_clk.exp_ceb_i <= 0;
inst_exp_if.drv_clk.exp_rwb_i <= 1;
inst_exp_if.drv_clk.exp_addr_i <= tr.exp_addr;
inst_exp_if.drv_clk.exp_d_i <= '1;//just for debugging
@(inst_exp_if.drv_clk); endtask:read_pkt
virtual task chip_uen(exp_packet tr);
`uvm_info("TRACE",$sformatf("%m"),UVM_HIGH);
inst_exp_if.drv_clk.exp_ceb_i <= 1;
inst_exp_if.drv_clk.exp_rwb_i <= req.rw;
inst_exp_if.drv_clk.exp_addr_i <= '0;//chip unenable default value
inst_exp_if.drv_clk.exp_d_i <= '1;//chip unenable default value
@(inst_exp_if.drv_clk);
endtask
virtual task send_idle();
inst_exp_if.drv_clk.exp_ceb_i <= 1;
inst_exp_if.drv_clk.exp_rwb_i <=0;
inst_exp_if.drv_clk.exp_addr_i <= '0;//chip unenable default value
inst_exp_if.drv_clk.exp_d_i <= '1;//chip unenable default value
@(inst_exp_if.drv_clk);
endtask
endclass:exp_drv
`endif
7.input monitor
`ifndef EXP_IMON_SV
`define EXP_IMON_SV
class exp_imon extends uvm_monitor; //monitor the signals,pack to transaction and transfer to reference model.
virtual exp_if inst_exp_if;
uvm_analysis_port #(exp_packet) analysis_port;
`uvm_component_utils(exp_imon)
function new(string name,uvm_component parent);
super.new(name,parent);
`uvm_info("TRACE",$sformatf("%m"),UVM_HIGH);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
`uvm_info("TRACE",$sformatf("%m"),UVM_HIGH);
if(!uvm_config_db#(virtual exp_if)::get(this,"","exp_if",inst_exp_if))
`uvm_fatal("CFGERR",“EXP_IMON exp_if not set");
analysis_port = new("analysis_port",this);
endfunction
virtual task run_phase(uvm_phase phase);
exp_packet tr;
logic cen;
super.run_phase(phase);
`uvm_info("TRACE",$sformatf("%m"),UVM_HIGH);
while(1) begin
get_packet(tr);
end
endtask
task get_packet( exp_packet tr);
logic cen =1;
wait(inst_exp_if.imon_clk.exp_ceb_i !==1'bx);
while(cen)begin
get_chip_en(cen);
end
while(!cen)begin
tr = exp_packet::type_id::create("tr",this);
tr.data = inst_exp_if.imon_clk.exp_d_i;
tr.exp_addr = inst_exp_if.imon_clk.exp_addr_i;
tr.rw = inst_exp_if.imon_clk.exp_rwb_i;
tr.cen = inst_exp_if.imon_clk.exp_ceb_i;
tr.dat_vld_o= inst_exp_if.imon_clk.exp_dv_o;
$display("imon get the packet:"); // not recommend using display
tr.print();
analysis_port.write(tr);
get_chip_en(cen);
end
endtask
task get_chip_en(ref logic cen);
@(inst_exp_if.imon_clk);
cen = inst_exp_if.imon_clk.exp_ceb_i;
endtask
endclass
`endif
8.sequencer
`ifndef EXP_SEQUENCER_SV
`define EXP_SEQUENCER_SV
`include "uvm_macros.svh" // sequencer is used to transfer the transaction from sequence to driver.
class exp_sequencer extends uvm_sequencer #(exp_packet); // your transaction here
`uvm_component_utils(exp_sequencer)
function new(string name,uvm_component parent);
super.new(name,parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
endfunction
endclass
`endif
9.input agent
`ifndef EXP_IAGENT_SV
`define EXP_IAGENT_SV
`include "exp_packet_sequence.sv"
`include "exp_drv.sv"
`include "exp_imon.sv"
`include "exp_sequencer.sv"
class exp_iagent extends uvm_agent;
virtual exp_if inst_exp_if;
exp_sequencer seqr;
exp_drv drv;
exp_imon imon;
uvm_analysis_port #(exp_packet) analysis_port;
`uvm_component_utils(exp_iagent)
function new(string name,uvm_component parent);
super.new(name,parent);
`uvm_info("exp_IGENT",$sformatf("%m"),UVM_HIGH);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
uvm_config_db #(virtual exp_if)::get(this,"","exp_if",inst_exp_if);
if(is_active == UVM_ACTIVE )begin
seqr = exp_sequencer::type_id::create("seqr",this);
drv = exp_drv::type_id::create("drv",this);
uvm_config_db #(virtual exp_if)::set(this,"drv","exp_if",inst_exp_if);
end
imon = exp_imon::type_id::create("imon",this);
uvm_config_db #(virtual exp_if)::set(this,"imon","exp_if",inst_exp_if);
endfunction
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
`uvm_info("exp_IGENT","Entering exp_igent connect phase",UVM_HIGH);
if(is_active == UVM_ACTIVE)begin
drv.seq_item_port.connect(seqr.seq_item_export);
end
this.analysis_port = imon.analysis_port;
endfunction
endclass
`endif
10.output monitor
`ifndef EXP_OMON_SV
`define EXP_OMON_SV
class exp_omon extends uvm_monitor;
virtual exp_if inst_exp_if;
bit[17:0] addr_scop;
bit[3:0] data_que[$];
bit[3:0] tmp_data;
uvm_analysis_port #(exp_packet) analysis_port_read;
`uvm_component_utils_begin(exp_hrqm_omon)
`uvm_field_int(addr_scop,UVM_ALL_ON|UVM_DEC)
`uvm_component_utils_end
function new(string name,uvm_component parent);
super.new(name,parent);
`uvm_info(“EXP_OMON","Entering exp_omon",UVM_HIGH);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
if(!uvm_config_db #(virtual exp_if)::get(this,"","exp_if",inst_exp_if))
`uvm_fatal("exp_OMON CFGERR","exp_hrqm_io not get config");
analysis_port_read = new("analysis_port_read",this);
endfunction
virtual task run_phase(uvm_phase phase);
exp_packet tr;
`uvm_info("exp_OMON run phase", $sformatf("%m"), UVM_HIGH);
forever begin
this.get_packet(tr);
end
endtask
task get_packet( exp_packet tr);
logic rw =0;
logic cycle =3;
logic vld =0;
begin
while(!vld)begin
get_data_valid(vld);
end
while(vld)begin
tmp_data = inst_exp_if.omon_clk.exp_q_o;
data_que.push_back(tmp_data);
if(data_que.size>0)begin
tr = exp_packet::type_id::create("tr", this);
tr.data = data_que.pop_front();
$display("omon get the pkt:");
tr.print();
analysis_port_read.write(tr);
end
get_data_valid(vld);
end
end
task get_data_valid(ref logic vld);
@(inst_exp_if.omon_clk);
vld = inst_exp_if.omon_clk.exp_dv_o;
endtask
endclass
`endif
11.output agent
`ifndef EXP_OAGENT_SV
`define EXP_OAGENT_SV
`include "exp_omon.sv“
class exp_oagent extends uvm_agent;
virtual exp_if inst_exp_if;
exp_omon omon;
uvm_analysis_port #(exp_packet) analysis_port;
`uvm_component_utils(exp_oagent)
function new(string name,uvm_component parent);
super.new(name,parent);
`uvm_info(“EXP_OAGENT",$sformatf("%m"),UVM_HIGH);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
`uvm_info(“EXP_OAGENT",$sformatf("%m"),UVM_HIGH);
uvm_config_db #(virtual exp_hrqm_io)::get(this,"","exp_if",inst_exp_if);
omon = exp_hrqm_omon::type_id::create("omon",this);
uvm_config_db #(virtual exp_if)::set(this,"omon","exp_if",inst_exp_if);
endfunction
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
`uvm_info(“EXP_OAGENT","Entering connect phase",UVM_HIGH);
this.analysis_port = omon.analysis_port_read;
endfunction
endclass
`endif
12.reference model
`ifndef EXP_RM_SV `define EXP_RM_SV
class exp_rm extends uvm_component;
uvm_blocking_get_port #(exp_packet) rm_get_port;
uvm_analysis_port #(exp_packet) rm_send_port;
bit[3:0] memery_data[bit[31:0]];
`uvm_component_utils_begin(exp_rm)
`uvm_field_array_int(memery_data,UVM_ALL_ON)
`uvm_component_utils_end
function new(string name,uvm_component parent);
super.new(name,parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
rm_get_port =new("rm_get_port",this);
rm_send_port =new("rm_send_port",this);
endfunction
virtual task main_phase(uvm_phase phase);
exp_packet tr;
super.main_phase(phase);
while(1)begin
rm_get_port.get(tr);
$display("exp_rm get the tr");
tr.print();
pkt_process(tr);
if(tr.rw ==1)
rm_send_port.write(tr);
end
endtask
task pkt_process(ref exp_packet tr);
if(tr.exp_addr<245760 && tr.exp_addr>=0)begin
if(tr.rw==0)
memery_data[tr.exp_addr] = tr.data;
else if(tr.rw ==1)
tr.data = memery_data[tr.exp_addr];
end
else
`uvm_warning(“EXP_RM WRITE","Out of memory scope");//add interupt register later
endtask
endclass
`endif
13.scoreboard
`ifndef EXP_SCOREBD_SV
`define EXP_SCOREBD_SV
class exp_scorebd extends uvm_scoreboard;
exp_packet expect_queue[$];
uvm_blocking_get_port #(exp_packet) expect_port;
uvm_blocking_get_port #(exp_packet) act_port;
`uvm_component_utils(exp_scorebd)
function new(string name,uvm_component parent);
super.new(name,parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
expect_port = new("expect_port",this);
act_port = new("act_port",this);
endfunction
task main_phase(uvm_phase phase);
exp_packet get_exp;
exp_packet get_act;
exp_packet tmp_pkt;
bit result;
bit exp_en;
super.main_phase(phase);
fork
while(1)begin
expect_port.get(get_exp);
expect_queue.push_back(get_exp);
end
while(1)begin
act_port.get(get_act);
if(expect_queue.size()>0)begin
tmp_pkt = expect_queue.pop_front();
result = get_act.data_compare(tmp_pkt.data);
if(result)begin
`uvm_info(“EXP_SCOREBOARD","COMPARE SUCESSFULLY ",UVM_LOW);
end
else begin
`uvm_error(“EXP_SCOREBOARD","COMPARE FAILED");
$display("The expect pkt is");
tmp_pkt.print();
$display("The actorl pkt is");
get_act.print();
end
end
else begin
`uvm_error(“EXP_SCOREBOARD","Received from DUT,while the expect queue is empty");
get_act.print();
end
end
join
endtask
endclass
`endif
13.file list
`include "exp_packet.sv"
`include "exp_drv.sv"
`include "exp_imon.sv"
`include "exp_omon.sv"
`include "exp_iagent.sv"
`include "exp_oagent.sv"
`include "exp_rm.sv"
`include "exp_scorebd.sv"
`include "exp_sequencer.sv"
14.virtual sequencer
`ifndef EXP_VSQR_SV
`define EXP_VSQR_SV
class exp_vsqr extends uvm_sequencer;
exp_sequencer exp_seqr;
extern function new(string name =“exp_vsqr",uvm_component parent = null);
`uvm_component_utils(exp_vsqr)
endclass:exp_vsqr
function exp_vsqr::new(string name = “exp_vsqr" ,uvm_component parent=null);
super.new(name,parent);
endfunction
`endif
15.env
`ifndef EXP_ENV_SV
`define EXP_ENV_SV
`include “exp_files.svh"
class exp_env extends uvm_env;
//->exp uvc
exp_iagent iagent;
exp_oagent oagent;
exp_scorebd sbd;
exp_rm rm;
//->exp TLM port
uvm_tlm_analysis_fifo #(exp_packet) iagt_rm_fifo;
uvm_tlm_analysis_fifo #(exp_packet) rm_sbd_fifo;
uvm_tlm_analysis_fifo #(exp_packet) oagt_sbd_fifo;
`uvm_component_utils_begin(exp_env)
`uvm_field_object(iagent,UVM_ALL_ON|UVM_REFERENCE)
`uvm_field_object(oagent,UVM_ALL_ON|UVM_REFERENCE)
`uvm_component_utils_end
function new(string name,uvm_component parent);
super.new(name,parent);
`uvm_info(“EXP_ENV",$sformatf("%m"),UVM_HIGH);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
`uvm_info(“EXP_ENV","Entering build_phase",UVM_LOW);
iagent = exp_iagent::type_id::create("iagent",this);
oagent = exp_oagent::type_id::create("oagent",this);
sbd = exp_scorebd::type_id::create("sbd",this);
rm = exp_rm::type_id::create("rm",this);
iagt_rm_fifo =new("iagt_rm_fifo",this);
rm_sbd_fifo =new("rm_sbd_fifo",this);
oagt_sbd_fifo=new("oagt_sbd_fifo");
iagent.is_active = UVM_ACTIVE;
`uvm_info("EXP_ENV","Exiting build_phase",UVM_LOW);
endfunction
virtual function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
`uvm_info(“EXP_ENV","Entering connnect phase",UVM_LOW);
iagent.analysis_port.connect(iagt_rm_fifo.analysis_export);
rm.rm_get_port.connect(iagt_rm_fifo.blocking_get_export);
rm.rm_send_port.connect(rm_sbd_fifo.analysis_export);
sbd.expect_port.connect(rm_sbd_fifo.blocking_get_export);
oagent.analysis_port.connect(oagt_sbd_fifo.analysis_export);
sbd.act_port.connect(oagt_sbd_fifo.blocking_get_export);
vsqr.exp_seqr = iagent.seqr;
endfunction
endclass
`endif
16.virtual sequence
class exp_normal_write_read_vsqs extends reg_vseqs;
exp_normal_write_sqs inst_normal_write_exp_sqs;
exp_normal_read_sqs inst_normal_read_exp_sqs;
`uvm_object_utils(exp_normal_write_read_vsqs)
`uvm_declare_p_sequencer(exp_vsqr)
function new(string name= "exp_normal_write_read_vsqs" );
super.new(name);
endfunction
virtual task pre_body();
if(starting_phase !=null)begin
starting_phase.raise_objection(this);
end
endtask
virtual task body();
for(int i=0;i<32’h321;i++)begin
`uvm_do_on_with(inst_normal_write_exp_sqs,p_sequencer.exp_seqr,{ addr==i; my_data==i[3:0]; });
end
for(int i=0;i<32’h321;i++)begin
`uvm_do_on_with(inst_normal_read_exp_sqs,p_sequencer.exp_seqr,{ addr==i; my_data==4'he; });
end
endtask
virtual task post_body();
if(starting_phase !=null)begin
uvm_objection objection = starting_phase.get_objection();
objection.set_drain_time(this,100us);
`uvm_info(get_full_name(), "!!!TESTCASE FINISHED!!!", UVM_LOW)
starting_phase.drop_objection(this);
end
endtask
17.base test case
`ifndef EXP_CASE_SV
`define EXP_CASE_SV
class exp_case extends uvm_test;
exp_env env;
`uvm_component_utils(exp_case)
function new(string name,uvm_component parent);
super.new(name,parent);
`uvm_info(“EXP_TEST",$sformatf("%m"),UVM_HIGH);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
`uvm_info(“EXP_TEST","Entering build phase",UVM_HIGH);
env = exp_env::type_id::create("env",this);
endfunction
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
endfunction
virtual function void final_phase(uvm_phase phase);
super.final_phase(phase);
`uvm_info("TEST_exp","Entering final_phase",UVM_HIGH);
endfunction
endclass
`endif
18.test case extends from base test case
class exp_normal_write_read_case extends exp_case;
`uvm_component_utils(exp_normal_write_read_case)
function new(string name = "exp_normal_write_read_case",uvm_component parent);
super.new(name ,parent);
endfunction
function void build_phase(uvm_phase phase);
super.build_phase(phase);
uvm_config_db#(uvm_object_wrapper)::set(this,"env.vsqr.main_phase","default_sequence",exp_normal_write_read_vsqs::type_id::get());
endfunction
function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
endfunction
task main_phase(uvm_phase phase);
super.main_phase(phase);
endtask
endclass
19.interface files
`include “../agent/exp_agent/exp_if.sv”
20.top
`ifndef EXP_TEST_TOP
`define EXP_TEST_TOP
`include "interfaces.svh"
`include "svt.uvm.pkg"
module exp_test_top();
int cycle = 3256;//clock domain 307MHz
//exp variables
wire[17:0] exp_addr;
wire[3:0] exp_indata;
wire exp_cen;
wire exp_rw;
wire[3:0] exp_outdata;
wire exp_avail;
wire exp_data_vld;
initial begin
clk =0;
forever #(cycle/2) clk = ~clk;
end
exp_if exp_if(clk);
assign exp_addr = exp_if.exp_addr_i;
assign exp_indata = exp_if.exp_d_i;
assign exp_cen = exp_if.exp_ceb_i;
assign exp_rw = exp_if.exp_rwb_i;
assign exp_if.exp_avail_o = exp_avail;
assign exp_if.exp_q_o = exp_outdata;
assign exp_if.exp_dv_o = exp_data_vld;
dut dut_ins (
.exp_addr_i (exp_addr),
.exp_d_i (exp_indata),
.exp_ceb_i (exp_cen),
.exp_rwb_i (exp_rw),
.exp_avail_o (exp_avail),
.exp_q_o (exp_outdata),
.exp_dv_o (exp_data_vld)
);
initial begin
uvm_config_db #(virtual exp_if)::set(null,"*.env.iagent","exp_if",exp_if);
uvm_config_db #(virtual exp_if)::set(null,"*.env.oagent","exp_if",exp_if);
run_test();
end
`ifdef VCS
initial $vcdpluson; //enable to dump .vpd file for waveform.
`endif
endmodule
`endif
21.Makefile
GUI =
SEED = 0
test =
CM = line+tgl+cond+branch+fsm
CM_DIR = $(WORKAREA)/project_lib/vcsobj/exp_test_top_simv -cm_hier coverage.hier
VPDFILE = vcdplus.vpd RUN_OPTS = -l simv.log -sml +warn=noMSGLOG-INV-IDENT
VERBOSITY = UVM_LOW MODE = manual
SRC_DIR = example/sv
INCL=+incdir+$(SRC_DIR)/tb/include+$(SRC_DIR)/tb/src+$(SRC_DIR)/tb/env+$(SRC_DIR)/tb/testcase+$(SRC_DIR)/tb/hdl
COMP_OPTS = -sverilog -full64 -ntb_opts rvm+uvm +define+NO_VMM_UVM_INTEROP -l vcs.log $(UVM) $(INCL) -timescale=1ps/1ps \
+define+UVM_NO_DEPRECATED+UVM_OBJECT_MUST_HAVE_CONSTRUCTOR+SYNOPSYS_SV+UVM_DISABLE_AUTO_ITEM_RECORDING \
+define+UVM_PACKER_MAX_BYTES=1500000
COMP_INCDIR = +incdir+$(SRC_DIR)/tb/agent/{exp_agent} \
+incdir+$(SRC_DIR)/tb/hdl\
+incdir+$(SRC_DIR)/tb/seq_lib \
+incdir+$(SRC_DIR)/tb/seq_lib/{exp_lib}\ +incdir+$(SRC_DIR)/tb/agent \
ELAB_OPTS = -debug_all -full64 -cm ${CM} -cm_dir ${CM_DIR} -lca -ntb_opts use_sigprop -ntb_opts uvm -ntb_opts vera_compat +warn=noINAV +warn=noTFIPC +warn=noFRCREF -l elab.log
clean:
rm -rf simv* csrc simlog
rm -rf vc_hdrs.h .vcsmx_rebuild *.log
rm -rf work/* *.svshell vcs_version
rm -rf vcdplus.vpd DVEfiles ucli.key
rm -rf *~
dcomp:
vlogan -full64 -sverilog -f dut.f
.PHONY: comp
comp:
ifndef ERR_STATUS
vlogan $(COMP_OPTS) $(COMP_INCDIR) +define+UVM_VCS_RECORD+UVM_TR_RECORD \
-debug_all
vlogan $(COMP_OPTS) $(COMP_INCDIR)+define+UVM_VCS_RECORD+UVM_TR_RECORD
+warn=noTMR \ -debug_all $(SRC_DIR)/tb/hdl/exp_test_top.sv
endif
.PHONY:elab
elab: comp
ifndef ERR_STATUS
vcs exp_test_top $(ELAB_OPTS) -o $(WORKAREA)/project_lib/vcsobj/exp_test_top_simv
endif
.PHONY: run
run:
ifndef ERR_STATUS
@echo ${DESIGNWARE_HOME}
./simv ${GUI} $(RUN_OPTS) \
+ntb_random_seed=$(SEED) +UVM_TESTNAME=$(test) +UVM_TR_RECORD +UVM_LOG_RECORD +UVM_PHASE_RECORD +UVM_VERBOSITY=$(VERBOSITY) -cm_name $(test)_$(SEED) -cm ${CM}\ +vpdfile+$(VPDFILE)
endif
.PHONY: dve
dve:
dve -full64 -vpd vcdplus.vpd &
.PHONY:cov
cov:
urg -dir simv.vdb
firefox urgReport/dashboard.html &