日常记录(43)phase、seq部分

phase的

跳转

在drv中,phase.jump控制了跳转。当线程中发现了复位信号,则跳转到reset相位(task_phase族中的)。

可跳转的phase包括12个动态运行的phase(task_phase)以及随后的phase(不包括和task_phase并行运行的run_phase)

task my_driver::main_phase(uvm_phase phase);
   `uvm_info("driver", "main phase", UVM_LOW)
   fork
      while(1) begin
         seq_item_port.get_next_item(req);
         drive_one_pkt(req);
         seq_item_port.item_done();
      end
      begin
         @(negedge vif.rst_n);
         phase.jump(uvm_reset_phase::get());
      end
   join
endtask

  

调试

+UVM_PHASE_TRACE

 

超时退出

uvm_set_timeout(500ns, 0)

超时时间和是否能被覆盖。

 

run_phase与task_phase

task_phase进行raise后,可使得run_phase进行运行(由其它task_phase控制)。

而run_phase本身raise并不能使得task_phase运行。

 

phase的drain_time

在drop_objection之前延时一定的时间。

phase.phase_done.set_drain_time(this, 200);

 

调试与显示更多

+UVM_OBJECTION_TRACE

以下是seq的raise与drop完整。第二个参数为打印信息中括号里显示的字符串,第三个为raise和drop的数量。

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, "case0 objection", 2);
      #10000;
      if(starting_phase != null) 
         starting_phase.drop_objection(this, "case0 objection", 2);
   endtask

   `uvm_object_utils(case0_sequence)
endclass

  

domain概念

在不同的comp中,domain将不同的task_phase过程进行了分隔。

默认情况下,所有comp位于相同名为common_domain域中,task_phase中的各个phase同步

使用以下实例,可创建domain,set过程中第二个参数hier默认为1,表示继承。

domain实现不同后,jump过程只能在各自的domain中。

class B extends uvm_component;
   uvm_domain new_domain;
   `uvm_component_utils(B)

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

   virtual function void connect_phase(uvm_phase phase);
      set_domain(new_domain);
   endfunction

   extern virtual  task reset_phase(uvm_phase phase);
   extern virtual  task post_reset_phase(uvm_phase phase);
   extern virtual  task main_phase(uvm_phase phase);
   extern virtual  task post_main_phase(uvm_phase phase);
endclass

  

 

时间域

61页,4.4节

NBA域

NBA events region

The NBA (nonblocking assignment update) region holds the events to be evaluated after all the Inactive events are processed

NBA(非阻塞赋值更新)区域在处理完所有Inactive事件后,保存要评估的事件

 

Sequence

仲裁机制优先级

默认优先级为-1,优先级越高越先执行。

在main_phase中设置了仲裁算法。默认算法为FIFO,先入先出,不考虑优先级。

而STRICT表示按照优先级仲裁。STRICT_FIFO表示先按照优先级,相同则使用先入先出。

此外还有RANDOM、WEIGHTED等方式。(优先级也可在start处指定。)

         `uvm_do_pri(m_trans, 100)

         `uvm_do_pri_with(m_trans, 200, {m_trans.pload.size < 500;})

   env.i_agt.sqr.set_arbitration(SEQ_ARB_STRICT_FIFO);

  

LOCK机制

在seq中的task body内,进行lock操作后,阻断了其它seq的发送,使得sqr只处理当前的seq。当前的seq进行unlock后,恢复正常。

      lock();
      unlock();

  

GRAB机制

和lock相同,但是优先级更高。在sqr的处理过程中,比如之前提到的FIFO,有执行顺序。

seq的lock需要等待到fifo到达指定的lock位置后才可执行。而grab则无需该规则,进入fifo后打断fifo,直接生效。

     grab();

    ungrab();

  

seq的失效和有效

seq中,重载is_relevant函数,进行失效和有效的控制。无效时sqr不发出该seq的trans。

   virtual function bit is_relevant();
      if((num >= 3)&&(!has_delayed)) return 0;
      else return 1;
   endfunction

is_relevant应该与wait_for_relevant成对出现。当前seq失效后,等到其它所有seq执行完毕

则进入到该seq的wait_for_relevant中。等待必须将seq无效的条件清除(否则进入该函数的死循环)

   virtual task wait_for_relevant();
      #10000;
      has_delayed = 1;
   endtask

  

其它宏和函数

uvm_do_on指定trans和sqr。

uvm_do_pri指定trans和优先级。

uvm_create创建trans

uvm_send发送trans

uvm_send_pri发送时候指定优先级

uvm_rand_send发送前进行随机化

任务

start_item和finish_item。在trans实例化后调用(参数为trans),可指定优先级,被封装在了uvm_do系列宏中。

pre_do在start_item前调用。参数is_item为1表示对seq操作,0为对trans操作。

mid_do在finish_item前调用。参数为seq_item

post_do在finish_item后调用。参数为seq_item

 

不同的trans相同的sqr

drv设置为了uvm_seq_item而不是trans(sqr需要同样的设置),这样。

class my_driver extends uvm_driver#(uvm_sequence_item);

在main_phase过程中,使用$cast即可判断是哪个trans

   while(1) begin
      seq_item_port.get_next_item(req);
      if($cast(m_tr, req)) begin
          drive_my_transaction(m_tr);
         `uvm_info("driver", "receive a transaction whose type is my_transaction", UVM_MEDIUM)
      end
      else if($cast(y_tr, req)) begin
         drive_your_transaction(y_tr);
         `uvm_info("driver", "receive a transaction whose type is your_transaction", UVM_MEDIUM)
      end
      else begin
         `uvm_error("driver", "receive a transaction whose type is unknown")
      end
      seq_item_port.item_done();
   end

  

m_sequencer和p_sequencer

m_sequencer为当前的seq启动时默认使用的sqr,如在实例化一个seq后,通过该seq的start函数启动,传入参数为m_sequencer。

 

m_sequencer本质为uvm_sequencer_item类型。有时候需要将其\$cast转换为sqr类型,则可以使用uvm_declare_p_sequencer的宏,其中参数为sqr。

然后在seq的task body中,引用p_sequencer,即为m_sequencer对应的sqr。

 

posted @ 2022-01-19 20:16  大浪淘沙、  阅读(439)  评论(0)    收藏  举报