testbench.sv
import uvm_pkg::*;
`include "bfm_base_pkg.sv"
`include "base_intf.sv"
`include "tc_001.sv"
`include "tc_002.sv"
`include "tc_003.sv"
module harness;
import bfm_base_pkg::*;
base_intf base_bfm();
initial begin
uvm_config_db#(virtual base_intf)::set(uvm_top,"driver","vbif",base_bfm);
uvm_config_db#(virtual base_intf)::set(uvm_top,"test","vbif",base_bfm);
run_test();
end
initial begin
$dumpfile("dump.vcd");
$dumpvars;
end
endmodule
base_intf.sv
interface base_intf();
logic [3:0] in;
import uvm_pkg::*;
import bfm_base_pkg::*;
base_drv driver;//for override
task drv_bfm(uvm_sequence_item req);
if(driver != null)
driver.drv_sig(req);
else
`uvm_fatal("base_bfm","driver does not initialized ...");
// create_drv(req);
// start_drv(req);
endtask
function void create_drv(uvm_sequence_item req);
if(driver == null)begin
uvm_component obj;
obj = f.create_component_by_type(lookup_table::search_lookup(req.get_object_type()),"","driver",null);
$cast(driver, obj);
// $cast(driver, lookup_table::search_lookup(req.get_object_type()).create_component($sformatf("drv_%0s",req.get_type_name()),null));
$display("============= %0s ============",driver.get_type_name());
end
endfunction
endinterface
base_bfm_pkg.sv
package bfm_base_pkg;
import uvm_pkg::*;
typedef virtual base_intf vbif;
uvm_coreservice_t cs = uvm_coreservice_t::get();
uvm_factory f = cs.get_factory();
uvm_root uvm_top = cs.get_root();
class lookup_table;
static local uvm_object_wrapper lookup[uvm_object_wrapper];
static function void add_lookup(uvm_object_wrapper ind, uvm_object_wrapper wrp);
lookup[ind] = wrp;
endfunction
static function uvm_object_wrapper search_lookup(uvm_object_wrapper ind);
return lookup[ind];
endfunction
endclass
class base_trans extends uvm_sequence_item;
rand bit[2:0] opcode;
`uvm_object_utils_begin(base_trans)
`uvm_field_int(opcode,UVM_ALL_ON)
`uvm_object_utils_end
function new(string name = "base_trans");
super.new(name);
endfunction
endclass
class user_def_trans extends base_trans;
`uvm_object_utils_begin(user_def_trans)
`uvm_field_int(opcode,UVM_ALL_ON)
`uvm_object_utils_end
function new(string name = "user_def_trans");
super.new(name);
endfunction
constraint cons{
this.opcode == 1;
};
endclass
class user_def_abn_trans extends base_trans;
`uvm_object_utils_begin(user_def_abn_trans)
`uvm_field_int(opcode,UVM_ALL_ON)
`uvm_object_utils_end
function new(string name = "user_def_abn_trans");
super.new(name);
endfunction
constraint cons{
this.opcode == 3;
};
endclass
class base_drv extends uvm_component;
`uvm_component_utils(base_drv)
protected virtual base_intf vif;
function new(string name, uvm_component parent);
super.new(name,parent);
set_if();
endfunction
protected function void set_if();
if(vif == null)
void'(uvm_config_db#(virtual base_intf)::get(null,"driver","vbif",vif));//todo
endfunction
virtual task drv_sig(uvm_sequence_item req); endtask
endclass
class drv#(type T = int) extends base_drv;
protected T tr;
`uvm_component_param_utils(drv#(T))
`uvm_type_name_decl("drv")
function new(string name, uvm_component parent);
super.new(name,parent);
endfunction
virtual task drv_sig(uvm_sequence_item req);
$display("%0s start stimulus ...", this.get_type_name());
assert($cast(tr,req.clone())) else `uvm_error("drv","errot type of trans to be sent ")//todo
$display("tr.opcode is %0b", tr.opcode);
if(vif == null) `uvm_fatal("drv","no vif set, pls call set_if() func ...");
$display("drive signal start...");
vif.in = 4'hf;
#10ns;
vif.in = 0;
#10ns;
vif.in = 4'hf;
#10ns;
$display("drive signal done...");
$display("%0s end stimulus ...", this.get_type_name());
endtask
// virtual function string get_type_name();
// return {"drv_",`"T`"};
// endfunction
endclass
class drv_nor#(type T = int) extends drv#(T);
`uvm_component_param_utils(drv_nor#(T))
`uvm_type_name_decl("drv_nor")
function new(string name, uvm_component parent);
super.new(name,parent);
endfunction
virtual task drv_sig(uvm_sequence_item req);
$display("%0s start stimulus ...", this.get_type_name());
assert($cast(tr,req.clone())) else `uvm_error("drv","errot type of trans to be sent ")//todo
$display("tr.opcode is %0b", tr.opcode);
if(vif == null) `uvm_fatal("drv","no vif set, pls call set_if() func ...");
$display("drive signal start...");
vif.in = 4'b1010;
#10ns;
vif.in = 0;
#10ns;
vif.in = 4'b1010;
#10ns;
$display("drive signal done...");
$display("%0s end stimulus ...", this.get_type_name());
endtask
endclass
endpackage
tc_001.sv
class tc_001 extends uvm_test;
`uvm_component_utils(tc_001)
import bfm_base_pkg::*;
protected virtual base_intf base_bfm;
base_trans a;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
lookup_table::add_lookup(base_trans::get_type(), drv#(base_trans)::get_type());
void'(uvm_config_db#(virtual base_intf)::get(null,"test","vbif",base_bfm));//todo
//always do in sequence
a = base_trans::type_id::create("base_trans");
//always do in driver_proxy
base_bfm.create_drv(a);
endfunction
virtual task main_phase(uvm_phase phase);
phase.raise_objection(this);
/*
lookup_table::add_lookup(base_trans::get_type(), drv#(base_trans)::get_type());
lookup_table::add_lookup(user_def_trans::get_type(), drv#(user_def_trans)::get_type());
lookup_table::add_lookup(user_def_abn_trans::get_type(), drv#(user_def_abn_trans)::get_type());
// f.set_type_override_by_type(base_trans::get_type(), user_def_trans::get_type());
f.set_type_override_by_type(drv#(user_def_abn_trans)::get_type(), drv_nor#(user_def_abn_trans)::get_type());
f.set_type_override_by_type(base_trans::get_type(), user_def_abn_trans::get_type());
// f.set_type_override_by_type(drv#(user_def_trans)::get_type(), drv#(user_def_abn_trans)::get_type());
// f.set_type_override_by_type(drv#(user_def_trans)::get_type(), drv_nor#(user_def_trans)::get_type());
*/
repeat(10)begin
a.randomize();
base_bfm.drv_bfm(a);
#10ns;
end
phase.drop_objection(this);
endtask
virtual task shutdown_phase(uvm_phase phase);
uvm_top.print_topology();
endtask
endclass
tc_002.sv
class tc_002 extends uvm_test;
`uvm_component_utils(tc_002)
import bfm_base_pkg::*;
protected virtual base_intf base_bfm;
base_trans a;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
// lookup_table::add_lookup(base_trans::get_type(), drv#(base_trans)::get_type());
lookup_table::add_lookup(user_def_trans::get_type(), drv#(user_def_trans)::get_type());
void'(uvm_config_db#(virtual base_intf)::get(null,"test","vbif",base_bfm));//todo
f.set_type_override_by_type(base_trans::get_type(), user_def_trans::get_type());
//always do in sequence
a = base_trans::type_id::create("base_trans");
//always do in driver_proxy
base_bfm.create_drv(a);
endfunction
virtual task main_phase(uvm_phase phase);
phase.raise_objection(this);
/*
lookup_table::add_lookup(base_trans::get_type(), drv#(base_trans)::get_type());
lookup_table::add_lookup(user_def_trans::get_type(), drv#(user_def_trans)::get_type());
lookup_table::add_lookup(user_def_abn_trans::get_type(), drv#(user_def_abn_trans)::get_type());
// f.set_type_override_by_type(base_trans::get_type(), user_def_trans::get_type());
f.set_type_override_by_type(drv#(user_def_abn_trans)::get_type(), drv_nor#(user_def_abn_trans)::get_type());
f.set_type_override_by_type(base_trans::get_type(), user_def_abn_trans::get_type());
// f.set_type_override_by_type(drv#(user_def_trans)::get_type(), drv#(user_def_abn_trans)::get_type());
// f.set_type_override_by_type(drv#(user_def_trans)::get_type(), drv_nor#(user_def_trans)::get_type());
*/
repeat(10)begin
a.randomize();
base_bfm.drv_bfm(a);
#10ns;
end
phase.drop_objection(this);
endtask
virtual task shutdown_phase(uvm_phase phase);
uvm_top.print_topology();
endtask
endclass
tc_003.sv
class tc_003 extends uvm_test;
`uvm_component_utils(tc_003)
import bfm_base_pkg::*;
protected virtual base_intf base_bfm;
base_trans a;
function new(string name, uvm_component parent);
super.new(name, parent);
endfunction
virtual function void build_phase(uvm_phase phase);
super.build_phase(phase);
// lookup_table::add_lookup(base_trans::get_type(), drv#(base_trans)::get_type());
lookup_table::add_lookup(user_def_abn_trans::get_type(), drv_nor#(user_def_abn_trans)::get_type());
void'(uvm_config_db#(virtual base_intf)::get(null,"test","vbif",base_bfm));//todo
f.set_type_override_by_type(base_trans::get_type(), user_def_abn_trans::get_type());
//always do in sequence
a = base_trans::type_id::create("base_trans");
//always do in driver_proxy
base_bfm.create_drv(a);
endfunction
virtual task main_phase(uvm_phase phase);
phase.raise_objection(this);
/*
lookup_table::add_lookup(base_trans::get_type(), drv#(base_trans)::get_type());
lookup_table::add_lookup(user_def_trans::get_type(), drv#(user_def_trans)::get_type());
lookup_table::add_lookup(user_def_abn_trans::get_type(), drv#(user_def_abn_trans)::get_type());
// f.set_type_override_by_type(base_trans::get_type(), user_def_trans::get_type());
f.set_type_override_by_type(drv#(user_def_abn_trans)::get_type(), drv_nor#(user_def_abn_trans)::get_type());
f.set_type_override_by_type(base_trans::get_type(), user_def_abn_trans::get_type());
// f.set_type_override_by_type(drv#(user_def_trans)::get_type(), drv#(user_def_abn_trans)::get_type());
// f.set_type_override_by_type(drv#(user_def_trans)::get_type(), drv_nor#(user_def_trans)::get_type());
*/
repeat(10)begin
a.randomize();
base_bfm.drv_bfm(a);
#10ns;
end
phase.drop_objection(this);
endtask
virtual task shutdown_phase(uvm_phase phase);
uvm_top.print_topology();
endtask
endclass