UVM实战--带有寄存器的加法器

news2024/11/15 5:29:44

一.整体的设计结构图

在这里插入图片描述

这里将DUT换成加法器,可以理解为之前UVM加法器加上寄存器,这里总线的功能不做修改,目的看代码的移植那些部分需要修改。
在这里插入图片描述

二.各个组件代码详解

2.1 DUT

module dut(
input          clk,
input          rst_n,
input          bus_cmd_valid,//为1时表示数据有效,只持续一个时钟
input          bus_op,//1时为写。0时为读
input  [15:0]  bus_addr,//地址
input  [15:0]  bus_wr_data,//读取的数据
output [15:0]  bus_rd_data,//写入的数据

input [7:0]  a,
input [7:0]  b,
input cin,
input enable,

output [7:0] sum,
output enable1,
output cout,
reg invert
);

//如果invert为1翻转,否则直接输出
always @(posedge clk) begin
   if(!rst_n) begin
		sum <= 8'b0;
		cout <= 1'b0;
		enable1 <= 1'b0;
   end
   else if(invert) begin
		{cout,sum} <= ~a + ~b + ~cin;
		enable1 <= enable;
   end
   else begin
      enable1 <= enable;
      {cout,sum} <= a + b + cin;
   end
end

always @(posedge clk) begin
   if(!rst_n) 
      invert <= 1'b0;
   else if(bus_cmd_valid && bus_op) begin
      case(bus_addr)
         16'h9: begin
            invert <= bus_wr_data[0];
         end
         default: begin
         end
      endcase
   end
end

reg [15:0]  bus_rd_data;
always @(posedge clk) begin
   if(!rst_n)
      bus_rd_data <= 16'b0;
   else if(bus_cmd_valid && !bus_op) begin
      case(bus_addr)
         16'h9: begin
            bus_rd_data <= {15'b0, invert};
         end
         default: begin
            bus_rd_data <= 16'b0; 
         end
      endcase
   end
end

endmodule

2.2 bus_driver.sv

`ifndef BUS_DRIVER__SV
`define BUS_DRIVER__SV
class bus_driver extends uvm_driver#(bus_transaction);

   virtual bus_if vif;

   `uvm_component_utils(bus_driver)
   function new(string name = "bus_driver", uvm_component parent = null);
      super.new(name, parent);
   endfunction

   virtual function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      if(!uvm_config_db#(virtual bus_if)::get(this, "", "vif", vif))
         `uvm_fatal("bus_driver", "virtual interface must be set for vif!!!")
   endfunction

   extern task run_phase(uvm_phase phase);
   extern task drive_one_pkt(bus_transaction tr);
endclass

task bus_driver::run_phase(uvm_phase phase);
   vif.bus_cmd_valid <= 1'b0;
   vif.bus_op <= 1'b0;
   vif.bus_addr <= 15'b0;
   vif.bus_wr_data <= 15'b0;
   while(!vif.rst_n)
      @(posedge vif.clk);
   while(1) begin
      seq_item_port.get_next_item(req);
      drive_one_pkt(req);
      seq_item_port.item_done();
   end
endtask

task bus_driver::drive_one_pkt(bus_transaction tr);
   `uvm_info("bus_driver", "begin to drive one pkt", UVM_LOW);
   repeat(1) @(posedge vif.clk);
   
   vif.bus_cmd_valid <= 1'b1;
   vif.bus_op <= ((tr.bus_op == BUS_RD) ? 0 : 1);
   vif.bus_addr = tr.addr;
   vif.bus_wr_data <= ((tr.bus_op == BUS_RD) ? 0 : tr.wr_data);

   @(posedge vif.clk);
   vif.bus_cmd_valid <= 1'b0;
   vif.bus_op <= 1'b0;
   vif.bus_addr <= 15'b0;
   vif.bus_wr_data <= 15'b0;

   @(posedge vif.clk);
   if(tr.bus_op == BUS_RD) begin
      tr.rd_data = vif.bus_rd_data;   
      //$display("@%0t, rd_data is %0h", $time, tr.rd_data);
   end

   //`uvm_info("bus_driver", "end drive one pkt", UVM_LOW);
endtask


`endif

2.3 bus_sequencer.sv

`ifndef BUS_SEQUENCER__SV
`define BUS_SEQUENCER__SV

class bus_sequencer extends uvm_sequencer #(bus_transaction);
   
   function new(string name, uvm_component parent);
      super.new(name, parent);
   endfunction 
   
   `uvm_component_utils(bus_sequencer)
endclass

`endif

2.4 bus_monitor

`ifndef BUS_MONITOR__SV
`define BUS_MONITOR__SV
class bus_monitor extends uvm_monitor;

   virtual bus_if vif;

   uvm_analysis_port #(bus_transaction)  ap;
   
   `uvm_component_utils(bus_monitor)
   function new(string name = "bus_monitor", uvm_component parent = null);
      super.new(name, parent);
   endfunction

   virtual function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      if(!uvm_config_db#(virtual bus_if)::get(this, "", "vif", vif))
         `uvm_fatal("bus_monitor", "virtual interface must be set for vif!!!")
      ap = new("ap", this);
   endfunction

   extern task main_phase(uvm_phase phase);
   extern task collect_one_pkt(bus_transaction tr);
endclass

task bus_monitor::main_phase(uvm_phase phase);
   bus_transaction tr;
   while(1) begin
      tr = new("tr");
      collect_one_pkt(tr);
      ap.write(tr);
   end
endtask

task bus_monitor::collect_one_pkt(bus_transaction tr);
   
   while(1) begin
      @(posedge vif.clk);
      if(vif.bus_cmd_valid) break;
   end

   tr.bus_op = ((vif.bus_op == 0) ? BUS_RD : BUS_WR);
   tr.addr = vif.bus_addr;
   tr.wr_data = vif.bus_wr_data;
   @(posedge vif.clk);
   tr.rd_data = vif.bus_rd_data;
   `uvm_info("bus_monitor", "end collect one pkt", UVM_LOW);
endtask


`endif

2.5 bus_agent.sv

`ifndef BUS_AGENT__SV
`define BUS_AGENT__SV

class bus_agent extends uvm_agent ;
   bus_sequencer  sqr;
   bus_driver     drv;
   bus_monitor    mon;
   
   uvm_analysis_port #(bus_transaction)  ap;
   
   function new(string name, uvm_component parent);
      super.new(name, parent);
   endfunction 
   
   extern virtual function void build_phase(uvm_phase phase);
   extern virtual function void connect_phase(uvm_phase phase);

   `uvm_component_utils(bus_agent)
endclass 


function void bus_agent::build_phase(uvm_phase phase);
   super.build_phase(phase);
   if (is_active == UVM_ACTIVE) begin
      sqr = bus_sequencer::type_id::create("sqr", this);
      drv = bus_driver::type_id::create("drv", this);
   end
   mon = bus_monitor::type_id::create("mon", this);
endfunction 

function void bus_agent::connect_phase(uvm_phase phase);
   super.connect_phase(phase);
   if (is_active == UVM_ACTIVE) begin
      drv.seq_item_port.connect(sqr.seq_item_export);
   end
   ap = mon.ap;
endfunction

`endif

2.6 bus_transaction.sv

`ifndef BUS_TRANSACTION__SV
`define BUS_TRANSACTION__SV

typedef enum{BUS_RD, BUS_WR} bus_op_e;

class bus_transaction extends uvm_sequence_item;

   rand bit[15:0] rd_data;
   rand bit[15:0] wr_data;
   rand bit[15:0] addr;

   rand bus_op_e  bus_op;

   `uvm_object_utils_begin(bus_transaction)
      `uvm_field_int(rd_data, UVM_ALL_ON)
      `uvm_field_int(wr_data, UVM_ALL_ON)
      `uvm_field_int(addr   , UVM_ALL_ON)
     
      `uvm_field_enum(bus_op_e, bus_op, UVM_ALL_ON)
   `uvm_object_utils_end

   function new(string name = "bus_transaction");
      super.new();
   endfunction

endclass
`endif

2.7 bus_if

`ifndef BUS_IF__SV
`define BUS_IF__SV

interface bus_if(input clk, input rst_n);

   logic         bus_cmd_valid;
   logic         bus_op;
   logic [15:0]  bus_addr;
   logic [15:0]  bus_wr_data;
   logic [15:0]  bus_rd_data;

endinterface

`endif

2.8 my_if

`ifndef MY_IF__SV
`define MY_IF__SV

interface my_if(input clk, input rst_n);

	logic [7:0] a;
	logic [7:0] b;
	logic cin;
	logic enable;
	wire enable1;
	wire [7:0] sum;
	wire cout;
	
endinterface
`endif

2.9 my_driver

`ifndef MY_DRIVER__SV
`define MY_DRIVER__SV
class my_driver extends uvm_driver;
	virtual my_if vif;
	
	`uvm_component_utils(my_driver)
	function new(string name = "my_driver",uvm_component parent = null);
		super.new(name,parent);
	endfunction
	
	virtual function void build_phase(uvm_phase phase);
		super.build_phase(phase);
		if(!uvm_config_db#(virtual my_if)::get(this,"","vif",vif))
			`uvm_fatal("my_driver","virtual interface must be set for vif!!!")
	endfunction

	extern task mian_phase(uvm_phase phase);
	extern task drive_one_pkt(my_transaction_i tr);
endclass

task my_driver::mian_phase(uvm_phase phase);
	vif.a <= 8'b0;
	vif.b <= 8,b0;
	vif.cin <= 1'b0;
	vif.enable <= 1'b0;
	while(!vif.rst_n)begin
		@(posedge vif.clk);
	end
	while(1)begin
		seq_item_port.get_next_item(req);
		drive_one_pkt(req);
		seq_item_port.item_done();
	end
endtask

task my_driver::drive_one_pkt(my_transcation_i tr);
	uvm_info("my_driver","begin to dirve one pkt",UVM_LOW);
	@(posedge vif.clk);
	vif.a <= tr.a;
	vif.b <= tr.b;
	vif.cin <= tr.cin;
	vif.enable <= 1'b1;
	@(posedge vif.clk)
	vif.enable <= 1'b0;
	`uvm_info("my_driver","end to drive one pkt",UVM_LOW);
endtask
`endif


2.10 my_transaction_i

`ifdenf MY_TRANSACTION_I__SV
`define MY_TRANSACTION_I__SV

class my_transaction_i extends uvm_sequence_item;
	
	rand bit [7:0] a;
	rand bit [7:0] b;
	rand bit cin;
	
	`uvm_object_utils_begin(my_transaction_i)
		`uvm_field_int(a,UVM_ALL_ON)
		`uvm_field_int(b,UVM_ALL_ON)
		`uvm_field_int(cin,UVM_ALL_ON)
	`uvm_object_utils_end

	function new(string name = "my_transaction_i");
		super.new();
	endfunction
endclass
`endif

2.11 my_transaction_o

`idndef MY_TRANSACTION_O__SV
`define MY_TRANSACTION_O__SV

class my_transaction_o extends uvm_sequence_item;
	
	 bit [7:0] sum;
	 bit cout;

	function new(string name = "my_transaction_o")
		super.new();
	endfunction
endclass
`endif

2.12 my_sequencer

`ifndef MY_SEQUENCER__SV
`define MY_SEQUENCER__SV

class my_sequencer extends uvm_sequencer #(my_transaction_i);
	
	function new(string name,uvm_component parent);
		super.new(name,parent);
	endfunction

	`uvm_component_utils(my_sequencer)
endclass
`endif

2.13 my_monitor_i

`ifndef MY_MONITOR_I__SV
`define MY_MONITOR_I__SV

class my_monitor_i extends uvm_monitor;
	
	virtual my_if vif;
	
	uvm_analysis_port #(my_transaction_i) ap;

	`uvm_component_utils(my_monitor_i)
	function new(string name = "monitor_i",uvm_component parent = null);
		super.new(name,parent);
	endfunction
	
	virtual function void build_phase(uvm_phase phase);
		super.build_phase(phase);
		if(!uvm_config_db#(virtual my_if)::get(this,"","vif",vif))
			`uvm_fatal("my_monitor","virtual interface must be set for vif!!!")
		ap = new("ap",this);
	endfunction
	
	extern task main_phase(uvm_phase phase);
	extern task drive_one_pkt(my_transaction_i tr);
endclass

task my_monitor::main_phase(uvm_phase phase);
	my_transaction_i tr;
	while(1) begin
		tr.new("tr");
		collect_one_pkt(tr);
		ap.write(tr);
	end
endtask
		
task my_monitor::collcet_one_pkt(my_transaction_i tr);
while(1) begin
	@(posedge vif.clk);
	if(vif.enable) break;
end
	`uvm_info("my_monitor","begin to collcet one pkt",UVM_LOW);	
	@(posedge vif.clk);
	tr.a <= vif.a;
	tr.b <= vif.b;
	tr.cin <= vif.cin;
	`uvm_info("my_monitor","end to collcet one pkt",UVM_LOW);
endtask
`endif

2.14 my_monitor_o

`ifndef MY_MONITOR_O__SV
`define MY_MONITOR_O__SV
class my_monitor_o extends uvm_monitor
	
	virtual my_if vif;
	
	uvm_analysis_port #(my_transaction_o) ap;
	
	`uvm_component_port #(my_transaction_o) ap;
	function new(string name = "my_monitor_o",uvm_component parent = null);
		super.new(name,parent);
	endfunction

	virtual function void build_phase(uvm_phase phase);
		super.build_phase(phase);
		if(!uvm_config_db#(virtual my_if)::get(this,"","vif",vif))
			`uvm_fatal("my_monitor","virtual interface must be set for vif!!!")
		ap = new("ap",this);
	endfunction
		
	extern task main_phase(uvm_phase phase);
	extern task collcet_one_pkt(my_transaction_i tr);
endclass

task my_monitor::main_phase (uvm_phase phase);
	my_transaction_o tr;
	while(1) begin
		tr = new("tr")
		collcet_one_pkt(tr);
		ap.write(tr);
	end
endtask

task my_monitor::collcet_one_pkt(my_transction_o tr);
while(1) begin
	@(posedge vif.clk)
	if(vif.enable1) break;
end
	`uvm_info("my_monitor_o","begin to collcet one pkt",UVM_LOW);
	@(posedge vif.clk)
	tr.sum <= vif.sum;
	tr.cout <= vif.cout;
	`uvm_info("my_monitor_o","end to collcet one pkt",UVM_ALL);
endtask
`endif

2.15 my_agent_i

`ifndef MY_AGENT_I__SV
`define MY_AGENT_I__SV

class my_agent_i extends uvm_agent;
	my_sequencer sqr;
	my_driver    drv;
	my_monitor_i mon_i;
	
	`uvm_analysis_port #(my_transaction_i) ap;
	
	function new(string name,uvm_component parent);
		super.new(name,parent);
	endfunction

	extern virtual function void build_phase(uvm_phase phase);
	extern virtual function void conncet_phase(uvm_phase phase);
	
	`uvm_component_utils(my_agent_i)
endclass

function void my_agent_i::build_phase(uvm_phase phase);
	super.build_phase(phase);
	sqr = my_sequencer::type_id::create("sqr",this);
	drv = my_driver::type_id::create("drv",this);
	mon_i = my_monitor_i::type_id::create("mon_i",this);
endfunction

function void my_agent_i::conncet_phase(uvm_phase phase);
	super.conncet_phase(phase);
	drv_seq_item_port.conncet(sqr.seq_item_export);
	ap = mon.ap;
endfunction
`endif

2.16 my_agent_o

`ifndef MY_AGENT_O__SV
`define MY_AGENT_O__SV

class my_agent_o extends uvm_agent;
	my_sequencer sqr;
	my_driver    drv;
	my_monitor_o mon_o;

	`uvm_analysis_port #(my_transaction_o) ap;
	
	function new(string name,uvm_component parent);
		super.new(name,parent);
	endfunction
	
	extern virtual function void build_phase(uvm_phase phase);
	extern virtual function void conncet_phase(uvm_phase phase);
	
	`uvm_component_utils(my_agent_o)
endclass

function void my_agent_o::build_phase(uvm_phase phase);
	super.build_phase(phase);
	mon_o = my_monitor_o::type_id::create("mon",this);
endfunction

function void my_agent_o::conncet_phase(uvm_phase phase);
	super.conncet_phase(phase);
	ap = mon.ap;
endfunction
`endif

2.17 my_scoreboard

`ifndef MY_SCOREBOARD__SV
`define MY_SCOREBOARD__SV
class my_scoreboard extends uvm_scoreboard;
   my_transaction  expect_queue[$];
   uvm_blocking_get_port #(my_transaction)  exp_port;
   uvm_blocking_get_port #(my_transaction)  act_port;
   `uvm_component_utils(my_scoreboard)

   extern function new(string name, uvm_component parent = null);
   extern virtual function void build_phase(uvm_phase phase);
   extern virtual task main_phase(uvm_phase phase);
endclass 

function my_scoreboard::new(string name, uvm_component parent = null);
   super.new(name, parent);
endfunction 

function void my_scoreboard::build_phase(uvm_phase phase);
   super.build_phase(phase);
   exp_port = new("exp_port", this);
   act_port = new("act_port", this);
endfunction 

task my_scoreboard::main_phase(uvm_phase phase);
   my_transaction  get_expect,  get_actual, tmp_tran;
   bit result;
 
   super.main_phase(phase);
   fork 
      while (1) begin
         exp_port.get(get_expect);
         expect_queue.push_back(get_expect);
      end
      while (1) begin
         act_port.get(get_actual);
         if(expect_queue.size() > 0) begin
            tmp_tran = expect_queue.pop_front();
            result = get_actual.compare(tmp_tran);
            if(result) begin 
               `uvm_info("my_scoreboard", "Compare SUCCESSFULLY", UVM_LOW);
            end
            else begin
               `uvm_error("my_scoreboard", "Compare FAILED");
               $display("the expect pkt is");
               tmp_tran.print();
               $display("the actual pkt is");
               get_actual.print();
            end
         end
         else begin
            `uvm_error("my_scoreboard", "Received from DUT, while Expect Queue is empty");
            $display("the unexpected pkt is");
            get_actual.print();
         end 
      end
   join
endtask
`endif

2.18 my_env

`ifndef MY_ENV__SV
`define MY_ENV__SV

class my_env extends uvm_env;

   my_agent_i   i_agt;
   my_agent_o   o_agt;
   bus_agent  bus_agt;
   my_model   mdl;
   my_scoreboard scb;

   reg_model  p_rm;
   
   uvm_tlm_analysis_fifo #(my_transaction) agt_scb_fifo;
   uvm_tlm_analysis_fifo #(my_transaction) agt_mdl_fifo;
   uvm_tlm_analysis_fifo #(my_transaction) mdl_scb_fifo;
   
   function new(string name = "my_env", uvm_component parent);
      super.new(name, parent);
   endfunction

   virtual function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      i_agt = my_agent::type_id::create("i_agt", this);
      o_agt = my_agent::type_id::create("o_agt", this);
      bus_agt = bus_agent::type_id::create("bus_agt", this);
      bus_agt.is_active = UVM_ACTIVE;
      mdl = my_model::type_id::create("mdl", this);
      scb = my_scoreboard::type_id::create("scb", this);
      agt_scb_fifo = new("agt_scb_fifo", this);
      agt_mdl_fifo = new("agt_mdl_fifo", this);
      mdl_scb_fifo = new("mdl_scb_fifo", this);

   endfunction

   extern virtual function void connect_phase(uvm_phase phase);
   
   `uvm_component_utils(my_env)
endclass

function void my_env::connect_phase(uvm_phase phase);
   super.connect_phase(phase);
   i_agt.ap.connect(agt_mdl_fifo.analysis_export);
   mdl.port.connect(agt_mdl_fifo.blocking_get_export);
   mdl.ap.connect(mdl_scb_fifo.analysis_export);
   scb.exp_port.connect(mdl_scb_fifo.blocking_get_export);
   o_agt.ap.connect(agt_scb_fifo.analysis_export);
   scb.act_port.connect(agt_scb_fifo.blocking_get_export); 
   mdl.p_rm = this.p_rm;
endfunction

`endif


2.19 my_model

`ifndef MY_MODEL__SV
`define MY_MODEL__SV

class my_model extends uvm_component;
	
	uvm_blocking_get_port #(my_transaction_i) port;
	uvm_analysis_port #(my_transaction_o) ap;
	
	
	extern function new(string name,uvm_component parent);
	extern function void build_phase(uvm_phase phase);
	extern virtual task main_phase(uvm_phase phase);
	extern virtual function void invert_tr(my_transaction_o tr2);
	`uvm_component_utils(my_model)
endclass

function my_model::new(string name,uvm_component parent);
	super.new(name,parent);
endfunction

function void my_model::build_phase(uvm_phase phase);
	super.build_phase(phase);
	port = new("port",this);
	ap = new("ap",this);
endfunction

function void my_model::invert_tr(my_transaction_o tr2);
	tr2.sum = tr2.sum ^ 8'hFF;
	tr2.cout = tr2.cout ^ 1'b1;
endfunction
task my_model::main_phase(uvm_phase phase);
	my_transaction_i tr;
	my_transaction_o tr2;
	uvm_state_e states;
	uvm_reg_data_t value;
	bit [8:0] sum_total;
	super.main_phase(phase);
	p_rm.invert.read(status,value,UVM_FRONTDOOR);
	while(1)begin
		port.get(tr);
		tr2 = new("tr2");
		sum_total = tr.a+tr.b+tr.cin;
		tr2.sum = sum_total[7:0];
		tr2.cout = sum_total[8];
		is(value)
				invert_tr(tr2);
		`uvm_info("my_model", "get transactions, add and print it:", UVM_LOW)
		
      	tr2.print();
		ap.write(tr2);
	end
endtask
`endif

2.20 my_env

`ifndef MY_ENV__SV
`define MY_ENV__SV

class my_env extends uvm_env;

   my_agent_i   i_agt;
   my_agent_o   o_agt;
   bus_agent  bus_agt;
   my_model   mdl;
   my_scoreboard scb;

   reg_model  p_rm;
   
   uvm_tlm_analysis_fifo #(my_transaction_o) agt_scb_fifo;
   uvm_tlm_analysis_fifo #(my_transaction_i) agt_mdl_fifo;
   uvm_tlm_analysis_fifo #(my_transaction_o) mdl_scb_fifo;
   
   function new(string name = "my_env", uvm_component parent);
      super.new(name, parent);
   endfunction

   virtual function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      i_agt = my_agent::type_id::create("i_agt", this);
      o_agt = my_agent::type_id::create("o_agt", this);
      bus_agt = bus_agent::type_id::create("bus_agt", this);
      bus_agt.is_active = UVM_ACTIVE;
      mdl = my_model::type_id::create("mdl", this);
      scb = my_scoreboard::type_id::create("scb", this);
      agt_scb_fifo = new("agt_scb_fifo", this);
      agt_mdl_fifo = new("agt_mdl_fifo", this);
      mdl_scb_fifo = new("mdl_scb_fifo", this);

   endfunction

   extern virtual function void connect_phase(uvm_phase phase);
   
   `uvm_component_utils(my_env)
endclass

function void my_env::connect_phase(uvm_phase phase);
   super.connect_phase(phase);
   i_agt.ap.connect(agt_mdl_fifo.analysis_export);
   mdl.port.connect(agt_mdl_fifo.blocking_get_export);
   mdl.ap.connect(mdl_scb_fifo.analysis_export);
   scb.exp_port.connect(mdl_scb_fifo.blocking_get_export);
   o_agt.ap.connect(agt_scb_fifo.analysis_export);
   scb.act_port.connect(agt_scb_fifo.blocking_get_export); 
   mdl.p_rm = this.p_rm;
endfunction

`endif

2.21 base_test

`ifndef BASE_TEST__SV
`define BASE_TEST__SV

class base_test extends uvm_test;

   my_env         env;
   my_vsqr        v_sqr;
   //(2)成员变量的理解
   reg_model      rm;
   my_adapter     reg_sqr_adapter;

   function new(string name = "base_test", uvm_component parent = null);
      super.new(name,parent);
   endfunction
   
   extern virtual function void build_phase(uvm_phase phase);
   extern virtual function void connect_phase(uvm_phase phase);
   extern virtual function void report_phase(uvm_phase phase);
   `uvm_component_utils(base_test)
endclass


function void base_test::build_phase(uvm_phase phase);
   super.build_phase(phase);
   env  =  my_env::type_id::create("env", this); 
   v_sqr =  my_vsqr::type_id::create("v_sqr", this);
   rm = reg_model::type_id::create("rm", this);
   rm.configure(null, "");
   rm.build();
   rm.lock_model();
   rm.reset();
   rm.set_hdl_path_root("top_tb.my_dut");
   reg_sqr_adapter = new("reg_sqr_adapter");
   env.p_rm = this.rm;
endfunction


function void base_test::connect_phase(uvm_phase phase);
   super.connect_phase(phase);
   v_sqr.p_my_sqr = env.i_agt.sqr;
   v_sqr.p_bus_sqr = env.bus_agt.sqr;
   v_sqr.p_rm = this.rm;
   rm.default_map.set_sequencer(env.bus_agt.sqr, reg_sqr_adapter);
   rm.default_map.set_auto_predict(1);
endfunction

function void base_test::report_phase(uvm_phase phase);
   uvm_report_server server;
   int err_num;
   super.report_phase(phase);

   server = get_report_server();
   err_num = server.get_severity_count(UVM_ERROR);

   if (err_num != 0) begin
      $display("TEST CASE FAILED");
   end
   else begin
      $display("TEST CASE PASSED");
   end
endfunction

`endif

2.22 reg_model

`ifndef REG_MODEL__SV
`define REG_MODEL__SV
//uvm_reg是比较小的单位,一个寄存器中至少包含一个uvm_reg_field 
class reg_invert extends uvm_reg;
	//uvm_reg_filed是寄存器模型中的最小单位
    rand uvm_reg_field reg_data;
    
	//build的理解
    virtual function void build();
        reg_data = uvm_reg_field::type_id::create("reg_data");
        // parameter: parent, size, lsb_pos, access, volatile, reset value, has_reset, is_rand, individually accessible
        //(4)configure的参数理解
        reg_data.configure(this, 1, 0, "RW", 1, 0, 1, 1, 0);
    endfunction

    `uvm_object_utils(reg_invert)

    function new(input string name="reg_invert");
        //parameter: name, size, has_coverage
        //(3)new函数的理解
        super.new(name, 16, UVM_NO_COVERAGE);
    endfunction
endclass

class reg_counter extends uvm_reg;

    rand uvm_reg_field reg_data;

    virtual function void build();
        reg_data = uvm_reg_field::type_id::create("reg_data");
        // parameter: parent, size, lsb_pos, access, volatile, reset value, has_reset, is_rand, individually accessible
        reg_data.configure(this, 32, 0, "W1C", 1, 0, 1, 1, 0);
    endfunction

    `uvm_object_utils(reg_counter)

    function new(input string name="reg_counter");
        //parameter: name, size, has_coverage
        super.new(name, 32, UVM_NO_COVERAGE);
    endfunction
endclass

//uvm_reg_block它是一个较大的单位,在其中可以加入很多的uvm_reg,也可以加入其他的uvm_reg_block
class reg_model extends uvm_reg_block;
   rand reg_invert invert;
   rand reg_counter counter;

   virtual function void build();
    //(5)uvm_reg_map
      default_map = create_map("default_map", 0, 2, UVM_BIG_ENDIAN, 0);
	//(6)实例化invert并调用invert.configure函数
      invert = reg_invert::type_id::create("invert", , get_full_name());
      invert.configure(this, null, "invert");
      invert.build();
    //(7)default_map
      default_map.add_reg(invert, 'h9, "RW");
      
      counter= reg_counter::type_id::create("counter", , get_full_name());
      counter.configure(this, null, "counter");
      counter.build();
      default_map.add_reg(counter, 'h5, "RW");
   endfunction

   `uvm_object_utils(reg_model)

    function new(input string name="reg_model");
        super.new(name, UVM_NO_COVERAGE);
    endfunction 

endclass
`endif

2.23 my_adapter

`ifndef MY_ADAPTER__SV 
`define MY_ADAPTER__SV 
//(1)adapter的作用
class my_adapter extends uvm_reg_adapter;
    string tID = get_type_name();

    `uvm_object_utils(my_adapter)

   function new(string name="my_adapter");
      super.new(name);
   endfunction : new

//reg2bus,其作用为寄存器模型通过sequence发出的uvm_reg_bus_op型的变量转换成bus_sequencer能够接收的形式
   function uvm_sequence_item reg2bus(const ref uvm_reg_bus_op rw);
      bus_transaction tr;
      tr = new("tr"); 
      tr.addr = rw.addr;
      tr.bus_op = (rw.kind == UVM_READ) ? BUS_RD: BUS_WR;
      if (tr.bus_op == BUS_WR)
         tr.wr_data = rw.data; 
      return tr;
   endfunction : reg2bus

//bus2reg,其作用为当监测到总线上有操作时,它将收集来的transaction转换成寄存器模型能够接受的形式,以便寄存器模型能够更新相应的寄存器的值。
   function void bus2reg(uvm_sequence_item bus_item, ref uvm_reg_bus_op rw);
      bus_transaction tr;
      if(!$cast(tr, bus_item)) begin
         `uvm_fatal(tID,
          "Provided bus_item is not of the correct type. Expecting bus_transaction")
          return;
      end
      rw.kind = (tr.bus_op == BUS_RD) ? UVM_READ : UVM_WRITE;
      rw.addr = tr.addr;
      rw.byte_en = 'h3;
      rw.data = (tr.bus_op == BUS_RD) ? tr.rd_data : tr.wr_data;
      rw.status = UVM_IS_OK;
   endfunction : bus2reg

endclass : my_adapter
`endif

2.24 my_vsqr

`ifndef MY_VSQR__SV
`define MY_VSQR__SV

class my_vsqr extends uvm_sequencer;
  
   my_sequencer  p_my_sqr;
   bus_sequencer p_bus_sqr;
   reg_model     p_rm;

   function new(string name, uvm_component parent);
      super.new(name, parent);
   endfunction 
   
   `uvm_component_utils(my_vsqr)
endclass

`endif

2.25 my_case0

`ifndef MY_CASE0__SV
`define MY_CASE0__SV
class case0_sequence extends uvm_sequence #(my_transaction_i);
   my_transaction_i m_trans;

   function  new(string name= "case0_sequence");
      super.new(name);
   endfunction 
   
   virtual task body();
      repeat (10) begin
         `uvm_do(m_trans)
      end
   endtask

   `uvm_object_utils(case0_sequence)
endclass

class case0_cfg_vseq extends uvm_sequence;

   `uvm_object_utils(case0_cfg_vseq)
   `uvm_declare_p_sequencer(my_vsqr)
   
   function  new(string name= "case0_cfg_vseq");
      super.new(name);
   endfunction 
   
   virtual task body();
      uvm_status_e   status;
      uvm_reg_data_t value;
      bit[31:0] counter;
      uvm_reg_block blks[$];
      reg_model p_rm;
      if(starting_phase != null) 
         starting_phase.raise_objection(this);
      uvm_reg_block::get_root_blocks(blks);
      if(blks.size() == 0)
          `uvm_fatal("case0_cfg_vseq", "can't find root blocks")
      else begin
         if(!$cast(p_rm, blks[0]))
             `uvm_fatal("case0_cfg_vseq", "can't cast to reg_model")
      end
          
      p_rm.invert.read(status, value, UVM_FRONTDOOR);
      `uvm_info("case0_cfg_vseq", $sformatf("invert's initial value is %0h", value), UVM_LOW)
      p_rm.invert.write(status, 1, UVM_FRONTDOOR);
      p_rm.invert.read(status, value, UVM_FRONTDOOR);
      `uvm_info("case0_cfg_vseq", $sformatf("after set, invert's value is %0h", value), UVM_LOW)
      p_rm.counter.read(status, value, UVM_FRONTDOOR);
      counter = value;
      `uvm_info("case0_cfg_vseq", $sformatf("counter's initial value(FRONTDOOR) is %0h", counter), UVM_LOW)
      p_rm.counter.poke(status, 32'hFFFD);
      p_rm.counter.read(status, value, UVM_FRONTDOOR);
      counter = value;
      `uvm_info("case0_cfg_vseq", $sformatf("after poke, counter's value(FRONTDOOR) is %0h", counter), UVM_LOW)
      p_rm.counter.peek(status, value);
      counter = value;
      `uvm_info("case0_cfg_vseq", $sformatf("after poke, counter's value(BACKDOOR) is %0h", counter), UVM_LOW)
      if(starting_phase != null) 
         starting_phase.drop_objection(this);
   endtask

endclass

class case0_vseq extends uvm_sequence;

   `uvm_object_utils(case0_vseq)
   `uvm_declare_p_sequencer(my_vsqr)
   
   function  new(string name= "case0_vseq");
      super.new(name);
   endfunction 
   
   virtual task body();
      case0_sequence dseq;
      uvm_status_e   status;
      uvm_reg_data_t value;
      if(starting_phase != null) 
         starting_phase.raise_objection(this);
      #10000;
      dseq = case0_sequence::type_id::create("dseq");
      dseq.start(p_sequencer.p_my_sqr);
      
      if(starting_phase != null) 
         starting_phase.drop_objection(this);
   endtask

endclass


class my_case0 extends base_test;

   function new(string name = "my_case0", uvm_component parent = null);
      super.new(name,parent);
   endfunction 
   extern virtual function void build_phase(uvm_phase phase); 
   `uvm_component_utils(my_case0)
endclass


function void my_case0::build_phase(uvm_phase phase);
   super.build_phase(phase);

   uvm_config_db#(uvm_object_wrapper)::set(this, 
                                           "v_sqr.configure_phase", 
                                           "default_sequence", 
                                           case0_cfg_vseq::type_id::get());
   uvm_config_db#(uvm_object_wrapper)::set(this, 
                                           "v_sqr.main_phase", 
                                           "default_sequence", 
                                           case0_vseq::type_id::get());
endfunction

`endif


2.26 top_tb

`timescale 1ns/1ps
`include "uvm_macros.svh" //UVM中的一个文件,包含众多的宏定义

import uvm_pkg::*; //将整个uvm_pkg导入到验证平台中,编译器在编译my_driver.sv文件时才能认识uvm_driver其中的uvm_driver等类名
`include "my_if.sv"
`include "bus_if.sv"
`include "bus_transaction.sv"
`include "bus_agent.sv"
`include "bus_driver.sv"
`include "bus_monitor.sv"
`include "bus_sequencer.sv"
`include "my_transaction_i.sv"
`include "my_transaction_o.sv"
`include "my_sequencer.sv"
`include "my_driver.sv"
`include "my_monitor_i.sv"
`include "my_monitor_o.sv"
`include "my_agent_i.sv"
`include "my_agent_o.sv"
`include "my_model.sv"
`include "my_scoreboard.sv"
`include "my_env.sv"
`include "base_test.sv"
`include "my_case0.sv"
`include "reg_model.sv"
`include "my_adapter.sv"
`include "my_vsqr.sv"

module top_tb;

reg clk;
reg rst_n;
reg [7:0] a;
reg [7:0] b;
reg enable;
reg cin;

wire enable1;
wire cout;
wire [7:0] sum; 

my_if input_if(clk, rst_n);
my_if output_if(clk, rst_n);
bus_if b_if(clk,rst_n);

dut my_dut(.clk(clk),                 //例化DUT
           .rst_n(rst_n),
       	   .a(input_if.a),
       	   .b(input_if.b),
       	   .cin(input_if.cin),
       	   .enable(input_if.enable),
       	   .enable1(output_if.enable1),
       	   .cout(output_if.cout),
       	   .sum(output_if.sum),
       	   .bus_cmd_valid (b_if.bus_cmd_valid),
       	   .bus_op    (b_if.bus_op),
       	   .bus_addr (b_if.bus_addr),
       	   .bus_wr_data (b_if.bus_wr_data),
       	   .bus_rd_data (b_if.bus_rd_data));

initial begin           
   clk = 0;
   forever begin
      #100 clk = ~clk;
   end
end

initial begin
   rst_n = 1'b0;
   #1000;
   rst_n = 1'b1;
end

initial begin           
   run_test();
end

initial begin
	input_if.a = 8'b00000000;
	input_if.b = 8'b00000000;
	input_if.cin = 1'b0;
	input_if.enable = 1'b1;
end

initial begin
   //(1) uvm_config_db::set
   uvm_config_db#(virtual my_if)::set(null, "uvm_test_top.env.i_agt.drv", "vif", input_if);
   uvm_config_db#(virtual my_if)::set(null, "uvm_test_top.env.i_agt.mon", "vif", input_if);
   uvm_config_db#(virtual my_if)::set(null, "uvm_test_top.env.o_agt.mon", "vif", output_if);
   uvm_config_db#(virtual bus_if)::set(null, "uvm_test_top.env.bus_agt.drv", "vif", bus_if);
   uvm_config_db#(virtual bus_if)::set(null, "uvm_test_top.env.bus_agt.mon", "vif", bus_if);
end

endmodule


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/382527.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【深度学习】softmax和交叉熵的配合求导

在分类问题中&#xff0c;尤其是在神经网络中&#xff0c;交叉熵函数非常常见。因为经常涉及到分类问题&#xff0c;需要计算各类别的概率&#xff0c;所以交叉熵损失函数与sigmoid函数或者softmax函数成对出现。 1.softmax softmax用于多分类过程中&#xff0…

这么简单的 CSS 动效,快来瞧瞧

前言 这几天逛网站浏览网页的时候&#xff0c;看到一个不错的CSS效果&#xff0c;便想来实现一下。整个效果实现起来比较简单&#xff0c;但是并不缺少交互感&#xff0c;因此来分享一下这个CSS效果。 效果展示 HTML 搭建 HTML部分一如既往地简单&#xff0c;认清楚它的布局…

密码传输和存储,如何保证数据安全?

本文从一个输入密码登录场景说起&#xff0c;详细介绍了密码传输过程的改进和思路&#xff0c;最后展现出一个相对安全的传输和存储方案。点击上方“后端开发技术”&#xff0c;选择“设为星标” &#xff0c;优质资源及时送达场景在互联网项目中&#xff0c;我们经常会遇到以下…

研报精选230302

目录 【个股230302华西证券_比亚迪】系列点评五十四&#xff1a;迪“王”需求向上 出口“海”阔天空【个股230302华西证券_华利集团】下游去库存背景下承压&#xff0c;毛利率保持稳健【个股230302开源证券_恒顺醋业】公司信息更新报告&#xff1a;四季度业绩承压&#xff0c;期…

运维级医院PACS系统全套源代码

PACS系统源码 运维级医院PACS系统源码&#xff0c;有演示&#xff0c;带使用手册和操作说明书 开发环境&#xff1a;VC MSSQL 文末获取方式&#xff01; PACS系统可实现检查预约、病人信息登记、计算机阅片、电子报告书写、胶片打印、数据备份等一系列满足影像科室日常工作…

每日统计部门人员考勤打卡情况并汇总通知

在值班时&#xff0c;HR需要及时了解到部分人员的打卡情况。这个时候&#xff0c;可以通过腾讯云HiFlow来实现自动通知考勤打卡情况。实现步骤&#xff1a;Step1&#xff1a;我们进入腾讯云HiFlow官网&#xff0c;进入控制台。我们在触发应用选择【定时启动-每天】触发。这里我…

VSCode下载与安装使用教程【超详细讲解】

目录 一、VSCode介绍 二、官方下载地址 三、VSCode安装 1、点击我同意此协议&#xff0c;点击下一步&#xff1b; 2、点击浏览&#xff0c;选择安装路径&#xff0c;点击下一步&#xff1b; 3、添加到开始菜单&#xff0c;点击下一步&#xff1b; 4、根据需要勾选&#…

开创高质量发展新局面,优炫数据库助推数字中国建设

最新印发《数字中国建设整体布局规划》&#xff0c;建设数字中国是数字时代推进中国式现代化的重要引擎&#xff0c;是构筑国家竞争新优势的有力支撑。 数字中国建设按照“2522”的整体框架进行布局&#xff0c;即夯实数字基础设施和数据资源体系“两大基础”&#xff0c;推进…

Java流Stream实战-常用api案例解析

本文介绍java 8 Stream流的常用高频api&#xff0c;通过实战级别的案例进行演示。实现结合实际业务、开发需要来应用技术&#xff0c;不让技术讲解枯燥无味&#xff0c;带来技术落地成生产力的价值。1. 思考&#xff0c;stream 的多个操作&#xff0c;相当于几个for循环&#x…

resultMap 用法?工作中是怎么实现“多表联查”的?

目录 一、resultMap用法 1.1、使用场景 1.2、用法说明 1.2.1、模拟场景 1.2.2、使用 二、多表联查 2.1、分析 2.2、具体步骤 2.3、总结 一、resultMap用法 1.1、使用场景 字段名称和程序中的属性名不同的情况&#xff0c;可使⽤ resultMap 配置映射&#xff1b;⼀对⼀…

英语好不好,不影响做外贸

对于国际贸易而言&#xff0c;英语到底有多重要&#xff1f;还记得我刚去墨西哥的时候&#xff0c;怕语言不通&#xff0c;我还带了一本《西班牙语入门》的书籍&#xff0c;靠着那本书一边说一边学&#xff0c;刚开始的时候很痛苦的。无法想象一个国家大部分的人都不懂得讲英语…

【已解决】nvidia-smi不显示正在使用GPU的进程

目录1 问题背景2 问题探索3 问题解决4 告别Bug1 问题背景 环境&#xff1a; 远程服务器Ubuntu20.04CUDA 11.6 现象&#xff1a;在日志文件和终端均显示Python脚本已使用了GPU 但是nvidia-smi中的Processes进程无显示 2 问题探索 首先&#xff0c;可以看到 | 0 Tesla V…

Android Handler机制(三) Looper源码分析

一. 简介 我们接上一篇文章:Android Handler机制(二) Handler 实现原理 继续分析Looper Looper 的职责很单一&#xff0c;就是单纯的从 MessageQueue 中取出消息分发给消息对应 的宿主 Handler&#xff0c;因此它的代码不多(400行左右) . Looper 是线程独立的且每个线程只能存在…

MySQL运维知识

1 日志1.1 错误日志1.2 二进制日志查看二进制日志&#xff1a;mysqlbinlog ./binlog.000007purge master logs to binlog.000006reset mastershow variables like %binlog_expire_logs_seconds%默认二进制文件只存放30天&#xff0c;30天后会自动删除。1.3 查询日志1.4 慢查询日…

React(四):事件总线、setState的细节、PureComponent、ref

React&#xff08;四&#xff09;一、事件总线二、关于setState的原理1.setState的三种使用方式&#xff08;1&#xff09;基本使用&#xff08;2&#xff09;传入一个回调&#xff08;3&#xff09;第一个参数是对象&#xff0c;第二个参数是回调2.为什么setState要设置成异步…

Android kotlin实战之协程suspend详解与使用

前言 Kotlin 是一门仅在标准库中提供最基本底层 API 以便各种其他库能够利用协程的语言。与许多其他具有类似功能的语言不同&#xff0c;async 与 await 在 Kotlin 中并不是关键字&#xff0c;甚至都不是标准库的一部分。此外&#xff0c;Kotlin 的 挂起函数 概念为异步操作提供…

π型滤波器 计算_π型滤波电路

滤波器在功率和音频电子中常用于滤除不必要的频率。而电路设计中&#xff0c;基于不同应用有着许多不同种类的滤波器&#xff0c;但它们的基本理念都是一致的&#xff0c;那就是移除不必要的信号。所有滤波器都可以被分为两类&#xff0c;有源滤波器和无源滤波器。有源滤波器用…

重新认识 Java 中的内存映射(mmap)

mmap 基础概念 mmap 是一种内存映射文件的方法&#xff0c;即将一个文件映射到进程的地址空间&#xff0c;实现文件磁盘地址和一段进程虚拟地址的映射。实现这样的映射关系后&#xff0c;进程就可以采用指针的方式读写操作这一段内存&#xff0c;而系统会自动回写脏页到对应的文…

电源程控软件下载安装教程

软件&#xff1a;电源程控软件NS-PowerSupply 语言&#xff1a;简体中文 环境&#xff1a;NI-VISA 安装环境&#xff1a;Win10以上版本&#xff08;特殊需求请后台私信联系客服&#xff09; 硬件要求&#xff1a;CPU2GHz 内存4G(或更高&#xff09;硬盘500G(或更高&#xf…

2023年2月安全事件盘点

一、基本信息 2023年2月安全事件共造成约3796万美元损失&#xff0c;相较于上个月&#xff0c;安全事件数量与损失金额都有显著上升&#xff0c;其中Platypus Finance闪电贷攻击为单次利用损失之最高达850万美元。本月RugPull数量基本与上月持平&#xff0c;损失金额占比显著降…