UVM_Sequence

  • 13.3.2 事务传输实例
    一、sequence body()的四步骤:
    1、create_item() //创建request对象
    2、start_item() //准备发送item
    3、req.randomize with //发送前的随机化处理
    4、finish_item() //完成item的发送
    二、driver run_phase()的几个步骤
    1、seq_item_port.get_next_item(tmp) //从sequencer中获取到有效的item\sequence
    2、$ cast(req,tmp) //进行动态句柄转换
    3、void’($cast(rep,req.clone())) //若有需要进行clone一份给rsp
    4、seq_item_port.item_done(rsp) //最后通过此形式将rsp反馈给sequence
class bus_trans extends uvm_sequence_item;
	rand int data;
	`uvm_object_utils_begin(bus_trans)
		`uvm_field_int(data,UVM_ALL_ON)
	`uvm_object_utils_end
	//...
endclass

class flas_seq extends uvm_sequence;
	`uvm_object_utils(flat_seq)
	//...
	task body();
		uvm_sequence_item tmp;
		bud_trans req,rdp;
		tmp = creat_item(bus_trans::get_type().m_sequencer,"req");
		void'($cast(req,tmp));
		start_item(req);
		req.randomize with (data == 10);
		`uvm_info("SEQ",$sformatf("sent a item \n%s",req.sprint()),UVM_LOW)
		finish_item(req);
		get_response(tmp);
		vod'($cast(rsp,tmp));
		`uvm_info("RSP",$sformatf("recived a item \n %s"),rsp.sprint(),UVM_LOW)
	endtask
endclass

class sequencer extends uvm_sequencer;
	`uvm_component_utils(sequencer);
	//...
endclass

class driver extends uvm_driver;
	`uvm_component_utils(driver)
	//...
	task run_phase(uvm_phase phase);
		REQ tmp;
		bus_trans req,rsp;
		seq_item_port.get_next_item(tmp);
		void'($cast(req,tmp));
		`uvm_info("DRV",$sformatf("got an item \n %s"),req.sprint(),UVM_LOW)
		
		void'($cast(rsp,req.clone()));
		rsp.set_sequence_id(req.get_sequence_id());
		rsp.data += 100;
		seq_item_port.item_done(rsp);
		`uvm_info("DRV",$sformatf("sent an item \n %s"),rsp.sprintf(),UVM_LOW)
	endtask
endclass

class env extends uvm_env;
	sequencer sqr;
	driver drv;
	`uvm_component_utils(env)
	//...
	function void build_phase (uvm_phase phase);
		sqr = sequencer::type_id::create("sqr",this);
		drv = driver::type_id::create("drv",this);
	endfunction
	function void connect_phase (uvm_phase phase)
		drv.seq_item_port.connect(sqr.seq_item_export);
	endfunction
endclass

class test1 extends uvm_test;
	env e;
	`uvm_component_utils(test1)
	//...
	function void build_phase (uvm_phase phase);
		e = env::type_id::create("e",this);
	endfunction
	task run_phase (uvm_phase phase);
		flat_seq seq;
		phase.raise_objection(phase);
		seq = new();
		seq.start(e.sqr);   //实现了将sequence挂载到sequencer上
		phase.drop_objection(phase);
	endtask
endclass

在这里插入图片描述

  • sequence中发送item跟sequence的区别
    1、sequence挂载到sequencer上:HANDLE.start(m_sequencer,this) //若是没有更上层的sequence嵌套时可以省略this,例如在test层调top_seq的时候:HANLE.start(e.start‘“路径”)
    2、将item挂载到sequencer上:
    create_item(bus_trans::get_type(), m_sequencer, “req”)
    finish_item(req)
class top_seq extends uvm_sequence;
    `uvm_object_utils(top_seq)
    function new(string name = "top_seq");
      super.new(name);
    endfunction
    task body();
      uvm_sequence_item tmp;
      child_seq cseq;
      bus_trans req;
      // create child sequence and items
      cseq = child_seq::type_id::create("cseq");
      tmp = create_item(bus_trans::get_type(), m_sequencer, "req");
      // send child sequence via start()
      cseq.start(m_sequencer, this);
      // send sequence item 
      void'($cast(req, tmp));
      start_item(req);
      req.randomize with {data == 20;};
      finish_item(req);
    endtask
  endclass

在这里插入图片描述
在这里插入图片描述

  • sequencer仲裁模式;
    在这里插入图片描述
    在这里插入图片描述
child_seq seq1,seq2,seq3;
m_sequencer.set_arbitration(UVM_SEQ_ARB_STRICT_FIFO);
fork
	`uvm_do_pri_with(seq1, 500, {base == 10;})
	`uvm_do_pri_with(seq1, 500, {base == 10;})
	`uvm_do_pri_with(seq1, 300, {base == 10;})
						 //优先级
join
  • layer sequence

在这里插入图片描述

module layer_seq;
  import uvm_pkg::*;
  `include "uvm_macros.svh"

  typedef class phy_master_sequencer;
  typedef enum {CLKON, CLKOFF, RESET, WRREG, RDREG} phy_cmd_t;
  typedef enum {FREQ_LOW_TRANS, FREQ_MED_TRANS, FREQ_HIGH_TRANS} layer_cmd_t;

  class bus_trans extends uvm_sequence_item;
    rand phy_cmd_t cmd;
    rand int addr;
    rand int data;
    constraint cstr{
      soft addr == 'h0;
      soft data == 'h0;
    }
    `uvm_object_utils_begin(bus_trans)
      `uvm_field_enum(phy_cmd_t, cmd, UVM_ALL_ON)
      `uvm_field_int(addr, UVM_ALL_ON)
      `uvm_field_int(data, UVM_ALL_ON)
    `uvm_object_utils_end
    function new(string name = "bus_trans");
      super.new(name);
    endfunction
  endclass

  class packet_seq extends uvm_sequence;
    rand int len;
    rand int addr;
    rand int data[];
    rand phy_cmd_t cmd;
    constraint cstr{
      soft len inside {[30:50]};
      soft addr[31:16] == 'hFF00;
      data.size() == len;
    }
    `uvm_object_utils(packet_seq)
    function new(string name = "reg_test_seq");
      super.new(name);
    endfunction
    task body();
      bus_trans req;
      foreach(data[i])
        `uvm_do_with(req, {cmd == local::cmd; 
                           addr == local::addr;
                           data == local::data[i];})
    endtask
  endclass

  class layer_trans extends uvm_sequence_item;
    rand layer_cmd_t layer_cmd;
    rand int pkt_len;
    rand int pkt_idle;
    constraint cstr {
      soft pkt_len inside {[10: 20]};
      layer_cmd == FREQ_LOW_TRANS -> pkt_idle inside {[300:400]};
      layer_cmd == FREQ_MED_TRANS -> pkt_idle inside {[100:200]};
      layer_cmd == FREQ_HIGH_TRANS -> pkt_idle inside {[20:40]};
    }
    `uvm_object_utils(layer_trans)
    function new(string name = "layer_trans");
      super.new(name);
    endfunction
  endclass

  class adapter_seq extends uvm_sequence;
    `uvm_object_utils(adapter_seq)
    `uvm_declare_p_sequencer(phy_master_sequencer)
    function new(string name = "adapter_seq");
      super.new(name);
    endfunction
    task body();
      layer_trans trans;
      packet_seq pkt;
      forever begin
        p_sequencer.up_sqr.get_next_item(req);
        void'($cast(trans, req));
        repeat(trans.pkt_len) begin
          `uvm_do(pkt)
          delay(trans.pkt_idle);
        end
        p_sequencer.up_sqr.item_done();
      end
    endtask
    virtual task delay(int delay);
    endtask
  endclass

  class top_seq extends uvm_sequence;
    `uvm_object_utils(top_seq)
    function new(string name = "top_seq");
      super.new(name);
    endfunction
    task body();
      layer_trans trans;
      `uvm_do_with(trans, {layer_cmd == FREQ_LOW_TRANS;})
      `uvm_do_with(trans, {layer_cmd == FREQ_HIGH_TRANS;})
    endtask
  endclass

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

  class phy_master_sequencer extends uvm_sequencer;
    layering_sequencer up_sqr;
    `uvm_component_utils(phy_master_sequencer)
    function new(string name, uvm_component parent);
      super.new(name, parent);
    endfunction
  endclass

  class phy_master_driver extends uvm_driver;
    `uvm_component_utils(phy_master_driver)
    function new(string name, uvm_component parent);
      super.new(name, parent);
    endfunction
    task run_phase(uvm_phase phase);
      REQ tmp;
      bus_trans req;
      forever begin
        seq_item_port.get_next_item(tmp);
        void'($cast(req, tmp));
        `uvm_info("DRV", $sformatf("got a item \n %s", req.sprint()), UVM_LOW)
        seq_item_port.item_done();
      end
    endtask
  endclass

  class phy_master_agent extends uvm_agent;
    phy_master_sequencer sqr;
    phy_master_driver drv;
    `uvm_component_utils(phy_master_agent)
    function new(string name, uvm_component parent);
      super.new(name, parent);
    endfunction
    function void build_phase(uvm_phase phase);
      sqr = phy_master_sequencer::type_id::create("sqr", this);
      drv = phy_master_driver::type_id::create("drv", this);
    endfunction
    function void connect_phase(uvm_phase phase);
      drv.seq_item_port.connect(sqr.seq_item_export);
    endfunction
  endclass

  class test1 extends uvm_test;
    layering_sequencer layer_sqr;
    phy_master_agent phy_agt;
    `uvm_component_utils(test1)
    function new(string name, uvm_component parent);
      super.new(name, parent);
    endfunction
    function void build_phase(uvm_phase phase);
      layer_sqr = layering_sequencer::type_id::create("layer_sqr", this);
      phy_agt = phy_master_agent::type_id::create("phy_agt", this);
    endfunction
    function void connect_phase(uvm_phase phase);
      phy_agt.sqr.up_sqr = layer_sqr;
    endfunction
    task run_phase(uvm_phase phase);
      top_seq seq;
      adapter_seq adapter;
      phase.raise_objection(phase);
      seq = new();
      adapter = new();
      fork
        adapter.start(phy_agt.sqr);
      join_none
      seq.start(layer_sqr);
      phase.drop_objection(phase);
    endtask
  endclass

  initial begin
    run_test("test1");
  end
endmodule

在这里插入图片描述

  • virtual sequence
    uvm_do_on宏用于显式地指定使用哪个sequencer发送此transaction,其参数形式为`uvm_do_on(SEQ_OR_ITEM,SEQR),第一个参数是transaction的指针,第二个是sequencer的指针。当使用uvm_do时,它实际等价于将uvm_do_on的第二个参数设置为了默认的sequencer,即此sequence启动时为其指定的sequencer。

'uvm_do_on(data_seq, p_sequencer.chnl_sqr0)在这里插入图片描述

module virtual_seq;
  import uvm_pkg::*;
  `include "uvm_macros.svh"

  typedef class mcdf_virtual_sequencer;

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

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

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

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

  // element sequences definitions above
  // which belong to different sequencers/agents
  // clk_rst_seq
  // reg_cfg_seq
  // data_trans_seq
  // fmt_slv_cfg_seq

  class mcdf_normal_seq extends uvm_sequence;
    `uvm_object_utils(mcdf_normal_seq)
    `uvm_declare_p_sequencer(mcdf_virtual_sequencer)
    function new(string name = "mcdf_normal_seq");
      super.new(name);
    endfunction
    task body();
      clk_rst_seq clk_seq;
      reg_cfg_seq cfg_seq;
      data_trans_seq data_seq;
      fmt_slv_cfg_seq fmt_seq;

      // virtual sequence is to be attached the
      // virtual sequencer, and further attache
      // its child sequences via p_sequencer.OBJ_SQR_HANDLE

      // configure formatter slave agent 
      `uvm_do_on(fmt_seq, p_sequencer.fmt_sqr)
      // turn on clock and assert reset
      `uvm_do_on(clk_seq, p_sequencer.cr_sqr)
      // configure mcdf registers
      `uvm_do_on(cfg_seq, p_sequencer.reg_sqr)
      // transfer data packets
      fork
        `uvm_do_on(data_seq, p_sequencer.chnl_sqr0)
        `uvm_do_on(data_seq, p_sequencer.chnl_sqr1)
        `uvm_do_on(data_seq, p_sequencer.chnl_sqr2)
      join
    endtask
  endclass

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

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

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

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

  
  class reg_master_agent extends uvm_agent;
    reg_master_sequencer sqr;
    // other agents definition/build/connect ignored
    `uvm_component_utils(reg_master_agent)
    function new(string name, uvm_component parent);
      super.new(name, parent);
    endfunction
    function void build_phase(uvm_phase phase);
      sqr = reg_master_sequencer::type_id::create("sqr", this);
    endfunction
  endclass

  class cr_master_agent extends uvm_agent;
    cr_master_sequencer sqr;
    // other agents definition/build/connect ignored
    `uvm_component_utils(cr_master_agent)
    function new(string name, uvm_component parent);
      super.new(name, parent);
    endfunction
    function void build_phase(uvm_phase phase);
      sqr = cr_master_sequencer::type_id::create("sqr", this);
    endfunction
  endclass

  class chnl_master_agent extends uvm_agent;
    chnl_master_sequencer sqr;
    // other agents definition/build/connect ignored
    `uvm_component_utils(chnl_master_agent)
    function new(string name, uvm_component parent);
      super.new(name, parent);
    endfunction
    function void build_phase(uvm_phase phase);
      sqr = chnl_master_sequencer::type_id::create("sqr", this);
    endfunction
  endclass

  class fmt_slave_agent extends uvm_agent;
    fmt_slave_sequencer sqr;
    // other agents definition/build/connect ignored
    `uvm_component_utils(fmt_slave_agent)
    function new(string name, uvm_component parent);
      super.new(name, parent);
    endfunction
    function void build_phase(uvm_phase phase);
      sqr = fmt_slave_sequencer::type_id::create("sqr", this);
    endfunction
  endclass

  // element sequencers and agents definition above
  // cr_master_sequencer | cr_master_agent
  // reg_master_sequencer | reg_master_agent
  // chnl_master_sequencer | chnl_master_agent
  // fmt_slave_sequencer | fmt_slave_agent
  class mcdf_virtual_sequencer extends uvm_sequencer;
    cr_master_sequencer cr_sqr;
    reg_master_sequencer reg_sqr;
    chnl_master_sequencer chnl_sqr0;
    chnl_master_sequencer chnl_sqr1;
    chnl_master_sequencer chnl_sqr2;
    fmt_slave_sequencer fmt_sqr;
    `uvm_component_utils(mcdf_virtual_sequencer)
    function new(string name, uvm_component parent);
      super.new(name, parent);
    endfunction
  endclass

  class mcdf_env extends uvm_env;
    cr_master_agent cr_agt;
    reg_master_agent reg_agt;
    chnl_master_agent chnl_agt0;
    chnl_master_agent chnl_agt1;
    chnl_master_agent chnl_agt2;
    fmt_slave_agent fmt_agt;
    mcdf_virtual_sequencer virt_sqr;
    `uvm_component_utils(mcdf_env)
    function new(string name, uvm_component parent);
      super.new(name, parent);
    endfunction
    function void build_phase(uvm_phase phase);
      cr_agt = cr_master_agent::type_id::create("cr_agt", this);
      reg_agt = reg_master_agent::type_id::create("reg_agt", this);
      chnl_agt0 = chnl_master_agent::type_id::create("chnl_agt", this);
      chnl_agt1 = chnl_master_agent::type_id::create("chnl_agt", this);
      chnl_agt2 = chnl_master_agent::type_id::create("chnl_agt", this);
      fmt_agt = fmt_slave_agent::type_id::create("fmt_agt", this);
      virt_sqr = mcdf_virtual_sequencer::type_id::create("virt_sqr", this);
    endfunction
    function void connect_phase(uvm_phase phase);
      // virtual sequencer connection
      // but no any TLM connection with sequencers
      virt_sqr.cr_sqr = cr_agt.sqr;
      virt_sqr.reg_sqr = reg_agt.sqr;
      virt_sqr.chnl_sqr0 = chnl_agt0.sqr;
      virt_sqr.chnl_sqr1 = chnl_agt1.sqr;
      virt_sqr.chnl_sqr2 = chnl_agt2.sqr;
      virt_sqr.fmt_sqr = fmt_agt.sqr;
    endfunction
  endclass

在这里插入图片描述

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值