sequence机制仲裁

 在sequence被启动是会自动执行它的body、pre_body和post_bosy三个任务,我们常用的是body任务。body任务中可以通过uvm_do_pri及uvm_do_pri_with改变所产生的transaction的优先级。uvm_do_pri与uvm_do_pri_with的第二个参数是优先级, 这个数值必须是一个大于等于-1的整数。 数字越大, 优先级越高。

如下面的这段代码指定了sequence0的优先级为100,sequence1的优先级为200,sequence1的优先级高于sequence0的优先级,同事设定了sequencer采用优先级仲裁机制,这样则会将sequence1的transcation都发送完成后再发送sequence0的transaction。对sequence设置优先级的本质即设置其内产生的transaction的优先级。
 

`ifndef MY_CASE0__SV
`define MY_CASE0__SV
class sequence0 extends uvm_sequence #(my_transaction);
   my_transaction m_trans;
 
   function  new(string name= "sequence0");
      super.new(name);
   endfunction 
   
   virtual task body();
      if(starting_phase != null) 
         starting_phase.raise_objection(this);
      repeat (5) begin
         `uvm_do_pri(m_trans, 100)
         `uvm_info("sequence0", "send one transaction", UVM_MEDIUM)
      end
      #100;
      if(starting_phase != null) 
         starting_phase.drop_objection(this);
   endtask
 
   `uvm_object_utils(sequence0)
endclass
 
class sequence1 extends uvm_sequence #(my_transaction);
   my_transaction m_trans;
 
   function  new(string name= "sequence1");
      super.new(name);
   endfunction 
   
   virtual task body();
      if(starting_phase != null) 
         starting_phase.raise_objection(this);
      repeat (5) begin
         `uvm_do_pri_with(m_trans, 200, {m_trans.pload.size < 500;})
         `uvm_info("sequence1", "send one transaction", UVM_MEDIUM)
      end
      #100;
      if(starting_phase != null) 
         starting_phase.drop_objection(this);
   endtask
 
   `uvm_object_utils(sequence1)
endclass
 
 
class my_case0 extends base_test;
 
   function new(string name = "my_case0", uvm_component parent = null);
      super.new(name,parent);
   endfunction 
   `uvm_component_utils(my_case0)
   extern virtual task main_phase(uvm_phase phase);
endclass
 
task my_case0::main_phase(uvm_phase phase);
   sequence0 seq0;
   sequence1 seq1;
 
   seq0 = new("seq0");
   seq0.starting_phase = phase;
   seq1 = new("seq1");
   seq1.starting_phase = phase;
   env.i_agt.sqr.set_arbitration(SEQ_ARB_STRICT_FIFO);//设置sqr仲裁算法
   fork
      seq0.start(env.i_agt.sqr);
      seq1.start(env.i_agt.sqr);
   join
endtask
 
`endif

此时该sqr先发seq1全部发完再发seq0,因为seq1优先级大于seq0

start函数同样可以设置优先级,start(sqr,parent seq,pri),参数依次为sqr 父seq,以及优先级,这个设置其实和uvm_do设置中一样,都是在设置transaction。 

 lock与grap

lock和grap其实对sequence的仲裁是相似的,都是在lock/grap期间独占sequencer进行transaction传输,区别在于grab操作比lock操作优先级更高。 lock请求是被插入sequencer仲裁队列的最后面, 等到它时, 它前面的仲裁请求都已经结束了。 grab请求则被放入sequencer仲裁队列的最前面, 它几乎是一发出就拥有了sequencer的所有权。如果是两个lock或者grap都试图独占sequencer,则先占用的发送完成再执行后占用的。这样前面说grap有比lock更高的优先级,如果发生在使用lock一个sequence独占sequencer发送transaction没有unlock时来了一个grap请求要怎么处理呢,这个时候grap会等lock的sequence执行完毕再执行自己的请求。

`ifndef MY_CASE0__SV
`define MY_CASE0__SV
class sequence0 extends uvm_sequence #(my_transaction);
   my_transaction m_trans;
 
   function  new(string name= "sequence0");
      super.new(name);
   endfunction 
   
   virtual task body();
      if(starting_phase != null) 
         starting_phase.raise_objection(this);
      repeat (2) begin
         `uvm_do(m_trans)
         `uvm_info("sequence0", "send one transaction", UVM_MEDIUM)
      end
      lock();
      `uvm_info("sequence0", "locked the sequencer ", UVM_MEDIUM)
      repeat (5) begin
         `uvm_do(m_trans)
         `uvm_info("sequence0", "send one transaction", UVM_MEDIUM)
      end
      `uvm_info("sequence0", "unlocked the sequencer ", UVM_MEDIUM)
      unlock();
      repeat (2) begin
         `uvm_do(m_trans)
         `uvm_info("sequence0", "send one transaction", UVM_MEDIUM)
      end
      #100;
      if(starting_phase != null) 
         starting_phase.drop_objection(this);
   endtask
 
   `uvm_object_utils(sequence0)
endclass
 
class sequence1 extends uvm_sequence #(my_transaction);
   my_transaction m_trans;
 
   function  new(string name= "sequence1");
      super.new(name);
   endfunction 
   
   virtual task body();
      if(starting_phase != null) 
         starting_phase.raise_objection(this);
      repeat (3) begin
         `uvm_do_with(m_trans, {m_trans.pload.size < 500;})
         `uvm_info("sequence1", "send one transaction", UVM_MEDIUM)
      end
      lock();/、开始lock
      `uvm_info("sequence1", "locked the sequencer ", UVM_MEDIUM)
      repeat (4) begin
         `uvm_do_with(m_trans, {m_trans.pload.size < 500;})
         `uvm_info("sequence1", "send one transaction", UVM_MEDIUM)
      end
      `uvm_info("sequence1", "unlocked the sequencer ", UVM_MEDIUM)
      unlock();//结束lock
      repeat (3) begin
         `uvm_do_with(m_trans, {m_trans.pload.size < 500;})
         `uvm_info("sequence1", "send one transaction", UVM_MEDIUM)
      end
      #100;
      if(starting_phase != null) 
         starting_phase.drop_objection(this);
   endtask
 
   `uvm_object_utils(sequence1)
endclass
 
 
class my_case0 extends base_test;
 
   function new(string name = "my_case0", uvm_component parent = null);
      super.new(name,parent);
   endfunction 
   `uvm_component_utils(my_case0)
   extern virtual task main_phase(uvm_phase phase);
endclass
 
task my_case0::main_phase(uvm_phase phase);
   sequence0 seq0;
   sequence1 seq1;
 
   seq0 = new("seq0");
   seq0.starting_phase = phase;
   seq1 = new("seq1");
   seq1.starting_phase = phase;
   fork
      seq0.start(env.i_agt.sqr);
      seq1.start(env.i_agt.sqr);
   join
endtask
 
`endif

此时seq0,seq1先交提产生,lock被调用后只产生lock后的transact

is_relevant和wait_for_relevant进行重载

可以对is_relevant和wait_for_relevant进行重载来决定仲裁。sequencer在仲裁时, 会查看sequence的is_relevant函数的返回结果。 如果为1, 说明此sequence有效, 否则无效。 

class sequence0 extends uvm_sequence #(my_transaction);
   my_transaction m_trans;
   int num;
   bit has_delayed;
 
   function  new(string name= "sequence0");
      super.new(name);
      num = 0;
      has_delayed = 0;
   endfunction 
  
   virtual function bit is_relevant();
      if((num >= 3)&&(!has_delayed)) return 0;
      else return 1;
   endfunction
 
   virtual task wait_for_relevant();
      #10000;
      has_delayed = 1;
   endtask
 
   virtual task body();
      if(starting_phase != null) 
         starting_phase.raise_objection(this);
      repeat (10) begin
         num++;
         `uvm_do(m_trans)
         `uvm_info("sequence0", "send one transaction", UVM_MEDIUM)
      end
      #100;
      if(starting_phase != null) 
         starting_phase.drop_objection(this);
   endtask
 
   `uvm_object_utils(sequence0)
endclass
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值