日常记录(44)seq部分

Sequence

Virtual Sqr

在my_vsqr.sv中

class my_vsqr extends uvm_sequencer;
  
   my_sequencer p_sqr0;
   my_sequencer p_sqr1;
   
   function new(string name, uvm_component parent);
      super.new(name, parent);
   endfunction 
   
   `uvm_component_utils(my_vsqr)
endclass

在base_test.sv中

   my_env         env0;
   my_env         env1;
   my_vsqr        v_sqr;   

   env0  =  my_env::type_id::create("env0", this); 
   env1  =  my_env::type_id::create("env1", this); 
   v_sqr =  my_vsqr::type_id::create("v_sqr", this); 

   v_sqr.p_sqr0 = env0.i_agt.sqr;
   v_sqr.p_sqr1 = env1.i_agt.sqr;

在my_agent.sv中

my_sequencer  sqr;

   if (is_active == UVM_ACTIVE) begin
      sqr = my_sequencer::type_id::create("sqr", this);
      drv = my_driver::type_id::create("drv", this);
   end

   if (is_active == UVM_ACTIVE) begin
      drv.seq_item_port.connect(sqr.seq_item_export);
   end

在my_case0.sv的case0_vseq中,

uvm_do_on确定由那个sqr发送seq。

而uvm_declare_p_sequencer则声明了p_sequencer

(seq启动后默认的m_sqr转换为对应的my_vsqr类型【使用p_sqr表示】)。

https://blog.csdn.net/u011177284/article/details/106274611/

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();
      my_transaction tr;
      drv0_seq seq0;
      drv1_seq seq1;
      if(starting_phase != null) 
         starting_phase.raise_objection(this);
      `uvm_do_on_with(tr, p_sequencer.p_sqr0, {tr.pload.size == 1500;})
      `uvm_info("vseq", "send one longest packet on p_sequencer.p_sqr0", UVM_MEDIUM)
      fork
         `uvm_do_on(seq0, p_sequencer.p_sqr0);
         `uvm_do_on(seq1, p_sequencer.p_sqr1);
      join 
      #100;
      if(starting_phase != null) 
         starting_phase.drop_objection(this);
   endtask
endclass

virtual sequence可以简化config_db的使用

case0_vseq进行发送。cvseq

class cfg_vseq extends uvm_sequence;
   `uvm_object_utils(cfg_vseq)
   `uvm_declare_p_sequencer(my_vsqr) 
   function new(string name = "cfg_vseq");
      super.new(name);
   endfunction

   virtual task body();
      my_transaction tr;
      drv0_seq seq0;
      drv1_seq seq1;
      `uvm_do_on_with(tr, p_sequencer.p_sqr0, {tr.pload.size == 1500;})
      `uvm_info("vseq", "send one longest packet on p_sequencer.p_sqr0", UVM_MEDIUM)
      fork
         `uvm_do_on(seq0, p_sequencer.p_sqr0);
         `uvm_do_on(seq1, p_sequencer.p_sqr1);
      join 
   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();
      cfg_vseq cvseq;
      if(starting_phase != null) 
         starting_phase.raise_objection(this);
      `uvm_do(cvseq)
      #100;
      if(starting_phase != null) 
         starting_phase.drop_objection(this);
   endtask
endclass


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

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

  

其它函数

1. get_full_name获取component完整路径

2. 以下函数,检测到第三个参数被更新后返回。

         uvm_config_db#(bit)::wait_modified(this, "", "cmp_en");

3. drv,seq,sqr的req和rsp是默认相同的,可以在定义时候通过传入两个类参数使用不同的trans。其它相同。

 

response的使用

一般trans的流向为:seq->sqr->drv,当seq需要来自drv的响应时,有以下代码

在drv中

其中的set_id_info确定drv发送给哪个seq。

task my_driver::main_phase(uvm_phase phase);
   vif.data <= 8'b0;
   vif.valid <= 1'b0;
   while(!vif.rst_n)
      @(posedge vif.clk);
   while(1) begin
      seq_item_port.get_next_item(req);
      drive_one_pkt(req);
      rsp = new("rsp");
      rsp.set_id_info(req);
      seq_item_port.put_response(rsp);
      seq_item_port.item_done();
   end
endtask

在seq中(my_case0.sv)

class case0_sequence extends uvm_sequence #(my_transaction);
   my_transaction m_trans;

   function  new(string name= "case0_sequence");
      super.new(name);
   endfunction 
   
   virtual task body();
      if(starting_phase != null) 
         starting_phase.raise_objection(this);
      repeat (10) begin
         `uvm_do(m_trans)
         get_response(rsp);
         `uvm_info("seq", "get one response", UVM_MEDIUM)
         rsp.print();
      end
      #100;
      if(starting_phase != null) 
         starting_phase.drop_objection(this);
   endtask

   `uvm_object_utils(case0_sequence)
endclass

drv将rsp推送给sqr中的一个长8的队列,超过一定限制可能会报错。

response handler

seq中异步接收rsp

需要将response转换为rsp

   virtual task pre_body();
      use_response_handler(1);
   endtask

   virtual function void response_handler(uvm_sequence_item response);
      if(!$cast(rsp, response))
         `uvm_error("seq", "can't cast")
      else begin
         `uvm_info("seq", "get one response", UVM_MEDIUM)
         rsp.print();
      end
   endfunction

或者使用uvm_do的返回值获取rsp

   virtual task body();
      if(starting_phase != null) 
         starting_phase.raise_objection(this);
      repeat (10) begin
         `uvm_do(m_trans)
         `uvm_info("seq", $sformatf("get information from driver: %0s", m_trans.frm_drv), UVM_MEDIUM)
      end
      #100;
      if(starting_phase != null) 
         starting_phase.drop_objection(this);
   endtask

  

Sequence library

定义和注册

class simple_seq_library extends uvm_sequence_library#(my_transaction);
   function  new(string name= "simple_seq_library");
      super.new(name);
      init_sequence_library();
   endfunction

   `uvm_object_utils(simple_seq_library)
   `uvm_sequence_library_utils(simple_seq_library);

endclass

添加seq

class seq0 extends uvm_sequence#(my_transaction);
   function  new(string name= "seq0");
      super.new(name);
   endfunction

   `uvm_object_utils(seq0)
   `uvm_add_to_seq_lib(seq0, simple_seq_library)
   virtual task body();
      repeat(10) begin
         `uvm_do(req)
         `uvm_info("seq0", "this is seq0", UVM_MEDIUM)
      end
   endtask 
endclass

设置

启动方式中的选择seq,最小执行次数,最大执行次数。

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

   cfg = new("cfg", UVM_SEQ_LIB_RANDC, 5, 20);
   
   uvm_config_db#(uvm_object_wrapper)::set(this, 
                                           "env.i_agt.sqr.main_phase", 
                                           "default_sequence", 
                                           simple_seq_library::type_id::get());
   uvm_config_db#(uvm_sequence_library_cfg)::set(this, 
                                           "env.i_agt.sqr.main_phase", 
                                           "default_sequence.config", 
                                           cfg);
endfunction

  

 

posted @ 2022-01-20 17:47  大浪淘沙、  阅读(206)  评论(0)    收藏  举报