UVM核心知识点-1

 UVM

TLM通讯
class master;
	uvm_analysis_port #(lvc_apb_transfer)item_collected_port

	function new();
	item_collected_port = new("item_collected_port",this);
	endfunction

  endclass

  class slave;
		uvm_analysis_port #(lvc_i2c_slave_transaction)xact_observed_port
  endclass

	`uvm_analysis_imp_decl(_apb_master)
	`uvm_analysis_imp_decl(_i2c_slave)
  class scoreboard;
	uvm_analysis_imp_apb_master #(lvc_apb_transfer,scoreboard) apb_trans_observe_imp;
	uvm_analysis_imp_i2c_slave #(lvc_i2c_slave_transaction,scoreboard) i2c_trans_observe_imp;
	
	
	virtual function void write_apb_master();
	endfunction
	
	virtual function void write_i2c_slave();
	endfunction
  endclass
  
  class cgm;
	uvm_analysis_imp_apb_master #(lvc_apb_transfer,scoreboard) apb_trans_observe_imp;
	uvm_analysis_imp_i2c_slave #(lvc_i2c_slave_transaction,scoreboard) i2c_trans_observe_imp;
  endclass


	class env;
	
	virtual void connect_phase(uvm_phase phase);
		master.item_collected_port.connect(scoreboard.apb_trans_observe_imp);
		slave.xact_observed_port.connect(scoreboard.i2c_trans_observe_imp);
		
		master.item_collected_port.connect(cgm.apb_trans_observe_imp);
		slave.xact_observed_port.connect(cgm.i2c_trans_observe_imp);
	endfunction
	
	endclass
总结:一个port连接多个import是通过analysis_port解决的,但是一个import被多个port连接,是通过宏定义来解决方法重名的问题。
在这里,由于使用了analysis port,因此方法必然是write函数,宏定义后也是在write函数后加后缀。

1.关于回调函数的使用:

应用1:下图是正向的使用测试用例进行测试

class mcdf_data_consistence_basic_test extends mcdf_base_test;

    `uvm_component_utils(mcdf_data_consistence_basic_test)

    function new(string name = "mcdf_data_consistence_basic_test", uvm_component parent);
      super.new(name, parent);
    endfunction

    task do_reg();
      bit[31:0] wr_val, rd_val;
      // slv0 with len=8,  prio=0, en=1
      wr_val = (1<<3)+(0<<1)+1;
      this.write_reg(`SLV0_RW_ADDR, wr_val);
      this.read_reg(`SLV0_RW_ADDR, rd_val);
      void'(this.diff_value(wr_val, rd_val, "SLV0_WR_REG"));

      // slv1 with len=16, prio=1, en=1
      wr_val = (2<<3)+(1<<1)+1;
      this.write_reg(`SLV1_RW_ADDR, wr_val);
      this.read_reg(`SLV1_RW_ADDR, rd_val);
      void'(this.diff_value(wr_val, rd_val, "SLV1_WR_REG"));

      // slv2 with len=32, prio=2, en=1
      wr_val = (3<<3)+(2<<1)+1;
      this.write_reg(`SLV2_RW_ADDR, wr_val);
      this.read_reg(`SLV2_RW_ADDR, rd_val);
      void'(this.diff_value(wr_val, rd_val, "SLV2_WR_REG"));

      // send IDLE command
      this.idle_reg();
    endtask

    task do_formatter();
      void'(fmt_gen.randomize() with {fifo == LONG_FIFO; bandwidth == HIGH_WIDTH;});
      fmt_gen.start();
    endtask

    task do_data();
      void'(chnl_gens[0].randomize() with {ntrans==100; ch_id==0; data_nidles==0; pkt_nidles==1; data_size==8; });
      void'(chnl_gens[1].randomize() with {ntrans==100; ch_id==1; data_nidles==1; pkt_nidles==4; data_size==16;});
      void'(chnl_gens[2].randomize() with {ntrans==100; ch_id==2; data_nidles==2; pkt_nidles==8; data_size==32;});
      fork
        chnl_gens[0].start();
        chnl_gens[1].start();
        chnl_gens[2].start();
      join
      #10us; // wait until all data haven been transfered through MCDF
    endtask
  endclass: mcdf_data_consistence_basic_test


下图是使用回调的方式达到和前面的测试用例的相同办法。

class mcdf_base_test extends uvm_test;
`uvm_register_cb(mcdf_base_test, cb_mcdf_base)

task run_phase(uvm_phase phase);
     phase.raise_objection(this);
      this.do_reg();均是虚任务,每个任务中增加了`uvm_do_callbacks(mcdf_base_test, cb_mcdf_base, cb_do_reg()),以此来添加回调函数
      this.do_formatter();
      this.do_data();
      phase.drop_objection(this);
    endtask

endclass

定义一个具体的callback

class cb_mcdf_base extends uvm_callback;
    mcdf_base_test test;
  

    virtual task cb_do_reg();
     虚任务
    endtask

    virtual task cb_do_formatter();
     虚任务
    endtask

    virtual task cb_do_data();
     虚任务
    endtask

  endclass
class cb_mcdf_data_consistence_basic extends cb_mcdf_base;
    task cb_do_reg();
       放具体的内容
    endtask

    task cb_do_formatter();
     具体的内容
    endtask

    task cb_do_data();
      具体的内容
    endtask
  endclass: cb_mcdf_data_consistence_basic

 注意这部分test相当于一个容器的作用,在其中放了具体的回调函数。由于对于回调函数预留的入口在mcdf_base_test中,因此,在这里的绑定实际上也是将mcdf_base_test和具体例化的回调函数cb进行绑定。

class cb_mcdf_data_consistence_basic_test extends mcdf_base_test;
    cb_mcdf_data_consistence_basic cb;
    
    function void build_phase(uvm_phase phase);
      super.build_phase(phase);
      cb = cb_mcdf_data_consistence_basic::type_id::create("cb");
      uvm_callbacks#(mcdf_base_test)::add(this, cb);
    endfunction

    function void connect_phase(uvm_phase phase);
      super.connect_phase(phase);
      cb.test = this;
    endfunction
  endclass: cb_mcdf_data_consistence_basic_test

回调函数关于pre的用法:
(1)在pre函数中定义相关条件,用于判断这个函数是否发生,典型的例子是uvm_event中的pre_trigger函数中的返回值,返回值为0继续执行相关trigger任务,如果返回值为1,不执行后续的内容。
(2)在发送数据前发送一些报文,用于快速定位数据产生的位置,也可以通过pre函数实现;对发送的数据产生一些约束,而具体的约束就可以通过pre函数定义。
启动sequence中的两种方式:(1)uvm_do_on_with(2)start函数,先进行new,一方面可以在new中给参数,另一方面在new之后可以通过句柄索引的方式赋参数。
package arbitration;
  import uvm_pkg::*;
  `include "uvm_macros.svh"
  class item extends uvm_sequence_item;
    `uvm_object_utils(item)
    rand int i;
    function new(string name = "item");
      super.new(name);
    endfunction
  endclass

  class seq extends uvm_sequence#(item);
    `uvm_object_utils(seq)
    int i;
    function new(string name = "seq");
      super.new(name);
    endfunction

    virtual task body();
      item req;
      //#10;
      repeat(5)begin
          //#5;
          `uvm_do_pri_with(req,1000,{i == local::i; })
          //`uvm_do_with(req,{i == local::i; })
          i = i+1;
          `uvm_info("seq",$sformatf("the value of i is %0d",i),UVM_LOW)
      end
      
    endtask
  endclass
  
  class seq2 extends uvm_sequence#(item);
    `uvm_object_utils(seq)
    int i;
    function new(string name = "seq2");
      super.new(name);
    endfunction

    virtual task body();
      item req;
       //#20;
      m_sequencer.grab(this);
      repeat(5)begin
         // #20;
      m_sequencer.grab(this);
          `uvm_do_pri_with(req,1,{i == local::i; })
          //`uvm_do_with(req,{i == local::i; })
          i = i+1;
          `uvm_info("seq2",$sformatf("the value of i is %0d",i),UVM_LOW)
      m_sequencer.ungrab(this);
      end
    endtask
  endclass



    class driver extends uvm_driver#(item);
      `uvm_component_utils(driver)
      function new(string name = "driver",uvm_component parent);
        super.new(name,parent);
      endfunction

      virtual task run_phase(uvm_phase phase);
      forever begin
        item rsp;
        rsp = new();
        seq_item_port.get_next_item(rsp);
        `uvm_info("driver",$sformatf("the value of i is %0d",rsp.i),UVM_LOW)
        seq_item_port.item_done();
      end
      endtask

    endclass

    class sequencer extends uvm_sequencer #(item);
      `uvm_component_utils(sequencer)
      function new(string name = "sequencer",uvm_component parent);
        super.new(name,parent);
      endfunction
    endclass

    class env extends uvm_env;
      `uvm_component_utils(env)
      sequencer sqr;
      driver dr;
      function new(string name = "env",uvm_component parent);
        super.new(name,parent);
      endfunction

      function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        sqr = sequencer::type_id::create("sqr",this);
        dr = driver::type_id::create("dr",this);
      endfunction

      function void connect_phase(uvm_phase phase);
        super.connect_phase(phase);
        dr.seq_item_port.connect(sqr.seq_item_export);
      endfunction
    endclass

    class test extends uvm_test;
      `uvm_component_utils(test)
      env e;
      seq s1;
      seq2 s2;
      function new(string name = "parent",uvm_component parent);
        super.new(name,parent);
      endfunction
      function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        e = env::type_id::create("e",this);
        s1 = new("s1");
        s2 = new("s2");
      endfunction

      task run_phase(uvm_phase phase);
        phase.raise_objection(this);
        e.sqr.set_arbitration(UVM_SEQ_ARB_FIFO);
        fork
          s1.start(e.sqr,null,100);
          s2.start(e.sqr,null,1);
        join
        phase.drop_objection(this);
      endtask
    endclass

endpackage

 

工厂机制和config_db机制
package arbitration;
  import uvm_pkg::*;
  `include "uvm_macros.svh"

 
  class item extends uvm_sequence_item;
    rand int i;
    `uvm_object_utils_begin(item)
        `uvm_field_int(i,UVM_ALL_ON)
    `uvm_object_utils_end
    constraint cstr{i inside {[0:10]};};

    function new(string name = "item");
      super.new(name);
    endfunction
  endclass
 
   class seq extends uvm_sequence#(item);
    `uvm_object_utils(seq)
    function new(string name = "seq");
      super.new(name);
    endfunction

    virtual task body();
      item req;
      req = new("req");
        repeat(5)begin
        `uvm_do(req)
      end
    endtask
  endclass

  
  class seq2 extends seq#(item);
    `uvm_object_utils(seq2)
    bit err_on = 0;
    function new(string name = "seq2");
      super.new(name);
      `uvm_info("seq2",$sformatf("%0s",get_full_name()),UVM_LOW)
    endfunction

    virtual task pre_body();
      if(!uvm_config_db#(int)::get(null,get_full_name(),"err_on",err_on))begin
        `uvm_error("seq2",$sformatf("the value of err_on is not get"))
      end
      if(err_on == 1)begin
          `uvm_info("seq2",$sformatf("the value of err_on is get"),UVM_LOW)
      end
    endtask
    
    virtual task body();
      item req;
      req = new();
      req.cstr.constraint_mode(0);
      repeat(5)begin
        `uvm_do(req)
      end
    endtask
  endclass

   
 class driver3 extends uvm_driver#(item);
        `uvm_component_utils(driver3)
        function new(string name = "driver3",uvm_component parent);
            super.new(name,parent);
        endfunction

        function void build_phase(uvm_phase phase);
          super.build_phase(phase);
        endfunction
        
        virtual task run_phase(uvm_phase phase);
            item req;
            req = new();
          forever begin
            seq_item_port.get_next_item(req);
            if(req.i > 50)
              `uvm_info("driver3",$sformatf("the value is error,50"),UVM_LOW)
            seq_item_port.item_done();
        end
      endtask
    endclass
 
    class driver2 extends driver3;
        `uvm_component_utils(driver2)
          bit err_on = 0;
        function new(string name = "driver2",uvm_component parent);
            super.new(name,parent);
        endfunction

        function void build_phase(uvm_phase phase);
          super.build_phase(phase);
          
          if(!uvm_config_db#(int)::get(this,"","err_on",err_on))begin
            `uvm_error("driver2",$sformatf("the value of err_on is not get"))
          end

            `uvm_info("driver2",$sformatf("%s",get_full_name()),UVM_LOW)

          if(err_on == 1)begin
            `uvm_info("driver2",$sformatf("the value of err_on is get"),UVM_LOW)
          end
        endfunction
        
        virtual task run_phase(uvm_phase phase);
            item req;
            req = new();
          forever begin
            seq_item_port.get_next_item(req);
            if(req.i > 10)
              `uvm_info("driver2",$sformatf("the value is error,10"),UVM_LOW)
            seq_item_port.item_done();
        end
          endtask
      endclass


    class driver extends driver2;
      `uvm_component_utils(driver)
      function new(string name = "driver",uvm_component parent);
        super.new(name,parent);
      endfunction

      function void build_phase(uvm_phase phase);
        super.build_phase(phase);
      endfunction

      virtual task run_phase(uvm_phase phase);
        item req;
        req = new();
        forever begin
          seq_item_port.get_next_item(req);
          `uvm_info("driver",$sformatf("the value of req after get_item is %0d",req.i),UVM_LOW)
          seq_item_port.item_done();
        end
      endtask

    endclass


    class sequencer extends uvm_sequencer#(item);
      `uvm_component_utils(sequencer)
      function new(string name = "sequencer",uvm_component parent);
        super.new(name,parent);
      endfunction
    endclass

    class env extends uvm_env;
      `uvm_component_utils(env)
      sequencer sqr;
      driver dr;
      driver2 dr2;
      driver3 dr3;
      function new(string name = "env",uvm_component parent);
        super.new(name,parent);
      endfunction

      function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        sqr = sequencer::type_id::create("sqr",this);
        dr = driver::type_id::create("dr",this);
        dr2 = driver2::type_id::create("dr2",this);
        dr3 = driver3::type_id::create("dr3",this);
      endfunction

      function void connect_phase(uvm_phase phase);
        super.connect_phase(phase);
        dr3.seq_item_port.connect(sqr.seq_item_export);
        dr2.seq_item_port.connect(sqr.seq_item_export);
        dr.seq_item_port.connect(sqr.seq_item_export);
      endfunction
    endclass

    class test extends uvm_test;
      `uvm_component_utils(test)
      bit err_on = 1;
      bit cov;
      env e;
      seq s1;
      seq2 s2;
      function new(string name = "test",uvm_component parent);
        super.new(name,parent);
      endfunction

      function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        
        
        if(!uvm_config_db#(int)::get(this,"","cov",cov))begin
          `uvm_error("test",$sformatf("the value of cov is not get"))
        end
        else
          `uvm_info("test",$sformatf("the value of cov is get"),UVM_LOW)

        `uvm_info("test",$sformatf("right"),UVM_LOW)

        if(cov)begin
          `uvm_info("driver",$sformatf("the value of err_on is %0d",err_on),UVM_LOW)
          set_type_override_by_type(driver3::get_type(),driver2::get_type());
          //set_type_override_by_type(seq2::get_type(),seq::get_type());
          set_type_override_by_type(driver2::get_type(),driver::get_type());
        end
        `uvm_info("test",$sformatf("right"),UVM_LOW)

        e = env::type_id::create("e",this);
        s2 = seq2::type_id::create("s2");
        s1 = seq::type_id::create("s1");


        `uvm_info("test",$sformatf("right"),UVM_LOW)
        
        uvm_config_db#(int)::set(this,"e.sqr.s2","err_on",err_on);
        uvm_config_db#(int)::set(this,"e.dr*","err_on",err_on);

        

        `uvm_info("test",$sformatf("right"),UVM_LOW)
                
      endfunction

      task run_phase(uvm_phase phase);
        phase.raise_objection(this);
        `uvm_info("test",$sformatf("right"),UVM_LOW)
          s1.start(e.sqr);
        `uvm_info("test",$sformatf("right"),UVM_LOW)
          s2.start(e.sqr);
        `uvm_info("test",$sformatf("right"),UVM_LOW)
        phase.drop_objection(this);
      endtask
    endclass

endpackage


module tb;
  import arbitration::*;
  import uvm_pkg::*;
  `include "uvm_macros.svh"
  bit cov = 0;
  initial begin
    uvm_config_db#(int)::set(null,"uvm_test_top","cov",cov);
    run_test("test");
  end
endmodule


-------------------------------------------------------------------------
package arbitration;
  import uvm_pkg::*;
  `include "uvm_macros.svh"

 
  class item extends uvm_sequence_item;
    rand integer i;
    `uvm_object_utils_begin(item)
        `uvm_field_int(i,UVM_ALL_ON)
    `uvm_object_utils_end
    constraint cstr{i inside {[0:10]};}

    function new(string name = "item");
      super.new(name);
    endfunction
  endclass
 
   class seq extends uvm_sequence#(item);
    `uvm_object_utils(seq)
    function new(string name = "seq");
      super.new(name);
    endfunction

    virtual task body();
      item req;
      req = new("req");
        repeat(5)begin
        `uvm_do(req)
      end
    endtask
  endclass

  
  class seq2 extends seq#(item);
    `uvm_object_utils(seq2)
    bit err_on = 0;
    function new(string name = "seq2");
      super.new(name);
      //`uvm_info("seq2",$sformatf("%0s",get_full_name()),UVM_LOW)
    endfunction

    virtual task pre_body();
      if(!uvm_config_db#(int)::get(null,get_full_name(),"err_on",err_on))begin
        `uvm_error("seq2",$sformatf("the value of err_on is not get"))
      end
      if(err_on == 1)begin
          `uvm_info("seq2",$sformatf("the value of err_on is get"),UVM_LOW)
      end
    endtask
    
    virtual task body();
      item req;
      req = new();
      req.cstr.constraint_mode(0);
      repeat(5)begin
        `uvm_rand_send_with(req,{req.i>10;})
      end
    endtask
  endclass

   
 class driver3 extends uvm_driver#(item);
        `uvm_component_utils(driver3)
        function new(string name = "driver3",uvm_component parent);
            super.new(name,parent);
        endfunction

        function void build_phase(uvm_phase phase);
          `uvm_info("driver3",$sformatf("enter the build phase of driver3"),UVM_LOW)
          super.build_phase(phase);
        endfunction
        
        virtual task run_phase(uvm_phase phase);
            item req;
            req = new();
          forever begin
            seq_item_port.get_next_item(req);
            `uvm_info("driver3",$sformatf("the value of req after get_item is %0d",req.i),UVM_LOW)
            if(req.i > 50)
              `uvm_info("driver3",$sformatf("the value is error,50"),UVM_LOW)
            seq_item_port.item_done();
        end
      endtask
    endclass
 
    class driver2 extends driver3;
        `uvm_component_utils(driver2)
          bit err_on = 0;
        function new(string name = "driver2",uvm_component parent);
            super.new(name,parent);
        endfunction

        function void build_phase(uvm_phase phase);
          `uvm_info("driver2",$sformatf("enter the build phase of driver2"),UVM_LOW)
          super.build_phase(phase);
          if(!uvm_config_db#(int)::get(this,"","err_on",err_on))begin
            `uvm_error("driver2",$sformatf("the value of err_on is not get"))
          end
          else begin
            `uvm_info("driver2",$sformatf("the value of err_on is get"),UVM_LOW)
          end

            `uvm_info("driver2",$sformatf("%s",get_full_name()),UVM_LOW)

          if(err_on == 1)begin
            `uvm_info("driver2",$sformatf("the value of err_on is get"),UVM_LOW)
          end
        endfunction
        
        virtual task run_phase(uvm_phase phase);
            item req;
            req = new();
          forever begin
            seq_item_port.get_next_item(req);
            `uvm_info("driver2",$sformatf("the value of req after get_item is %0d",req.i),UVM_LOW)
            if(req.i > 10)
              `uvm_info("driver2",$sformatf("the value is error,10"),UVM_LOW)
            seq_item_port.item_done();
        end
          endtask
      endclass


    class driver extends driver2;
      `uvm_component_utils(driver)
      function new(string name = "driver",uvm_component parent);
        super.new(name,parent);
      endfunction

      function void build_phase(uvm_phase phase);
        `uvm_info("driver",$sformatf("enter the build phase of driver"),UVM_LOW)
        super.build_phase(phase);
        //`uvm_info("driver2",$sformatf("driver2","enter the build phase of driver"),UVM_LOW)
      endfunction

      virtual task run_phase(uvm_phase phase);
        item req;
        req = new();
        forever begin
          seq_item_port.get_next_item(req);
          `uvm_info("driver",$sformatf("the value of req after get_item is %0d",req.i),UVM_LOW)
          seq_item_port.item_done();
        end
      endtask

    endclass


    class sequencer extends uvm_sequencer#(item);
      `uvm_component_utils(sequencer)
      function new(string name = "sequencer",uvm_component parent);
        super.new(name,parent);
      endfunction
    endclass

    class env extends uvm_env;
      `uvm_component_utils(env)
      sequencer sqr;
      driver dr;
      driver2 dr2;
      driver3 dr3;
      function new(string name = "env",uvm_component parent);
        super.new(name,parent);
      endfunction

      function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        sqr = sequencer::type_id::create("sqr",this);
        dr = driver::type_id::create("dr",this);
        dr2 = driver2::type_id::create("dr2",this);
        dr3 = driver3::type_id::create("dr3",this);
      endfunction

      function void connect_phase(uvm_phase phase);
        super.connect_phase(phase);
        dr3.seq_item_port.connect(sqr.seq_item_export);
        dr2.seq_item_port.connect(sqr.seq_item_export);
        dr.seq_item_port.connect(sqr.seq_item_export);
      endfunction
    endclass

    class test extends uvm_test;
      `uvm_component_utils(test)
      bit err_on = 1;
      bit cov;
      env e;
      seq s1;
      seq2 s2;
      function new(string name = "test",uvm_component parent);
        super.new(name,parent);
      endfunction

      function void build_phase(uvm_phase phase);
        uvm_factory factory = uvm_factory::get();
        
        super.build_phase(phase);

        //uvm_factory factory = uvm_factory::get();
        if(!uvm_config_db#(int)::get(this,"","cov",cov))begin
          `uvm_error("test",$sformatf("the value of cov is not get"))
        end
        else
          `uvm_info("test",$sformatf("the value of cov is get"),UVM_LOW)

        //uvm_factory factory = uvm_factory::get();

        if(cov)begin
          `uvm_info("driver",$sformatf("the value of err_on is %0d",err_on),UVM_LOW)
          set_type_override_by_type(driver3::get_type(),driver2::get_type());
          set_type_override_by_type(seq::get_type(),seq2::get_type());
          set_type_override_by_type(driver2::get_type(),driver::get_type());
        end

        e = env::type_id::create("e",this);
        s2 = seq2::type_id::create("s2");
        s1 = seq::type_id::create("s1");


        
        uvm_config_db#(int)::set(this,"e.sqr.s2","err_on",err_on);
        uvm_config_db#(int)::set(this,"e.dr*","err_on",err_on);

        

                
      endfunction

      task run_phase(uvm_phase phase);
        phase.raise_objection(this);
          //fork 
          //  begin
              `uvm_info("test",$sformatf("start s1"),UVM_LOW)
              s1.start(e.sqr);
              `uvm_info("test",$sformatf("end s1"),UVM_LOW)
              //#20;
          //  end
          //  begin
              `uvm_info("test",$sformatf("start s2"),UVM_LOW)
              s2.start(e.sqr);
              `uvm_info("test",$sformatf("end s2"),UVM_LOW)
          //  end
          //join
        phase.drop_objection(this);
      endtask
    endclass

endpackage


  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值