14.3 Lock and Grab Methods in UVM sequencer

UVM sequencer通过使用锁定机制向driver提供对序列的独占访问权限(exclusive access)。此锁定机制是使用lock和grab方法实现的。
例如:在控制器或微处理器中,internal core中断服务处理以及其他操作。有时,如果设备引发特定中断,需要立即关注并停止正在进行的进程执行。一旦core为这个高优先级中断提供服务,就可以恢复之前的进程。

1 Lock method

sequence调用lock方法时,sequencer将在sequence通过sequencer仲裁机制获得下一个可用slot时,授予driver对sequence的独占访问权限。在sequence调用unlock方法之前,没有其他sequence可以访问driver。调用unlock方法时,之前的锁定被释放。lock是一种阻塞方法,一旦锁定被granted就会return。

task lock (uvm_sequencer_base sequencer = null)

2 grab method

The grab method is similar to the lock method except it takes immediate control to grab the next sequencer arbitration slot itself by overriding any other sequence priorities.

The pre-existing lock or grab condition on the sequence will stop from grabbing the sequence for the current sequence.

task grab (uvm_sequencer_base sequencer = null)

3 unlock method

sequencer的lock方法从sequence中调用,以释放lock或grab。必须调用unlock方法以避免sequencer锁定情况。

function void unlock (uvm_sequencer_base sequencer = null)

4 ungrab method

ungrab方法是unlock方法的别称。

function void ungrab( uvm_sequencer_base sequencer = null )

5 is_blocked method

is_block方法可用于查找由于sequencer lock条件而被block的当前sequence,并返回1。它返回0值,则sequence未被阻止,可在sequencer arbitration(仲裁器)中获取下一个slot。如果sequencer在sequence发出请求之前被lock,则sequence可能无法获得slot。

function bit is_blocked()

6 has_lock method

如果当前sequence被lock返回1,否则返回0。

function bit has_lock()

7 kill method

kill函数用于终止sequence,并删除序列默认sequencer中的所有当前locks和requests。这将不允许执行post_body和post_start回调方法,sequence状态将更改为UVM_STOPPED。

function void kill()

8 do_kill method

do_kill是一个用户钩子,当使用sequence kill()或sequencer.stop_sequences()终止序列时,将调用它。
:sequencer.stop_sequences()最终调用sequence.kill方法。

virtual function void do_kill()

注:

  1. lock、grab、unlock和ungrab方法将请求放在指定的sequencer上。如果没有传递参数,将使用默认的sequencer。
  2. lock方法将lock请求放在仲裁队列的后面,而grab方法将grab请求放在了仲裁队列的前面。因此,如果仲裁队列有中间挂起的请求,那么与lock请求相比,grab请求将立即得到服务。

9 Lock and unlock methods example

有三个sequence:seq_A、seq_B和seq_C并行。只有seq_B调用lock和unlock方法。

class seq_A extends uvm_sequence #(seq_item);
  seq_item req;
  `uvm_object_utils(seq_A)
  
  function new (string name = "seq_A");
    super.new(name);
  endfunction

  task body();
    req = seq_item::type_id::create("req");
    wait_for_grant();
    assert(req.randomize());
    send_request(req);
    `uvm_info(get_type_name(), $sformatf("%0t: seq_item is sent", $time), UVM_LOW);
    wait_for_item_done();
  endtask
endclass

class seq_B extends uvm_sequence #(seq_item);
  seq_item req;
  `uvm_object_utils(seq_B)
  
  function new (string name = "seq_B");
    super.new(name);
  endfunction

  task body();
      lock(m_sequencer);
      req = seq_item::type_id::create("req");
      wait_for_grant();
      assert(req.randomize());
      send_request(req);
      `uvm_info(get_type_name(), $sformatf("%0t: seq_item is sent", $time), UVM_LOW);
      wait_for_item_done();
      unlock(m_sequencer);
  endtask
endclass

class seq_C extends uvm_sequence #(seq_item);
  seq_item req;
  `uvm_object_utils(seq_C)
  
  function new (string name = "seq_C");
    super.new(name);
  endfunction

  task body();
    req = seq_item::type_id::create("req");
    wait_for_grant();
    assert(req.randomize());
    send_request(req);
    `uvm_info(get_type_name(), $sformatf("%0t: seq_item is sent", $time), UVM_LOW);
    wait_for_item_done();
  endtask
endclass

Output: 

UVM_INFO sequences.sv(14) @ 0: uvm_test_top.env_o.agt.seqr@@seq_a [seq_A] 0: seq_item is sent
UVM_INFO sequences.sv(33) @ 50: uvm_test_top.env_o.agt.seqr@@seq_b [seq_B] 50: seq_item is sent
UVM_INFO sequences.sv(52) @ 100: uvm_test_top.env_o.agt.seqr@@seq_c [seq_C] 100: seq_item is sent
UVM_INFO sequences.sv(14) @ 150: uvm_test_top.env_o.agt.seqr@@seq_a [seq_A] 150: seq_item is sent
UVM_INFO sequences.sv(33) @ 200: uvm_test_top.env_o.agt.seqr@@seq_b [seq_B] 200: seq_item is sent
UVM_INFO sequences.sv(52) @ 250: uvm_test_top.env_o.agt.seqr@@seq_c [seq_C] 250: seq_item is sent
UVM_INFO sequences.sv(14) @ 300: uvm_test_top.env_o.agt.seqr@@seq_a [seq_A] 300: seq_item is sent
UVM_INFO sequences.sv(33) @ 350: uvm_test_top.env_o.agt.seqr@@seq_b [seq_B] 350: seq_item is sent
UVM_INFO sequences.sv(52) @ 400: uvm_test_top.env_o.agt.seqr@@seq_c [seq_C] 400: seq_item is sent

log显示,seq_B的lock请求按默认仲裁模式放到了仲裁队列的后面。因此,所有请求按分配的slot提供服务,seq_B具有独占访问权限。 

10 Grab and ungrab methods example

 有三个sequence:seq_A、seq_B和seq_C并行。只有seq_B调用grab和ungrab方法。

class seq_A extends uvm_sequence #(seq_item);
  seq_item req;
  `uvm_object_utils(seq_A)
  
  function new (string name = "seq_A");
    super.new(name);
  endfunction

  task body();
    req = seq_item::type_id::create("req");
    wait_for_grant();
    assert(req.randomize());
    send_request(req);
    `uvm_info(get_type_name(), $sformatf("%0t: seq_item is sent", $time), UVM_LOW);
    wait_for_item_done();
  endtask
endclass

class seq_B extends uvm_sequence #(seq_item);
  seq_item req;
  `uvm_object_utils(seq_B)
  
  function new (string name = "seq_B");
    super.new(name);
  endfunction

  task body();
      grab(m_sequencer);
      req = seq_item::type_id::create("req");
      wait_for_grant();
      assert(req.randomize());
      send_request(req);
      `uvm_info(get_type_name(), $sformatf("%0t: seq_item is sent", $time), UVM_LOW);
      wait_for_item_done();
      ungrab(m_sequencer);
  endtask
endclass

class seq_C extends uvm_sequence #(seq_item);
  seq_item req;
  `uvm_object_utils(seq_C)
  
  function new (string name = "seq_C");
    super.new(name);
  endfunction

  task body();
    req = seq_item::type_id::create("req");
    wait_for_grant();
    assert(req.randomize());
    send_request(req);
    `uvm_info(get_type_name(), $sformatf("%0t: seq_item is sent", $time), UVM_LOW);
    wait_for_item_done();
  endtask
endclass

Output:

UVM_INFO sequences.sv(33) @ 0: uvm_test_top.env_o.agt.seqr@@seq_b [seq_B] 0: seq_item is sent
UVM_INFO sequences.sv(33) @ 50: uvm_test_top.env_o.agt.seqr@@seq_b [seq_B] 50: seq_item is sent
UVM_INFO sequences.sv(33) @ 100: uvm_test_top.env_o.agt.seqr@@seq_b [seq_B] 100: seq_item is sent
UVM_INFO sequences.sv(14) @ 150: uvm_test_top.env_o.agt.seqr@@seq_a [seq_A] 150: seq_item is sent
UVM_INFO sequences.sv(52) @ 200: uvm_test_top.env_o.agt.seqr@@seq_c [seq_C] 200: seq_item is sent
UVM_INFO sequences.sv(14) @ 250: uvm_test_top.env_o.agt.seqr@@seq_a [seq_A] 250: seq_item is sent
UVM_INFO sequences.sv(52) @ 300: uvm_test_top.env_o.agt.seqr@@seq_c [seq_C] 300: seq_item is sent
UVM_INFO sequences.sv(14) @ 350: uvm_test_top.env_o.agt.seqr@@seq_a [seq_A] 350: seq_item is sent
UVM_INFO sequences.sv(52) @ 400: uvm_test_top.env_o.agt.seqr@@seq_c [seq_C] 400: seq_item is sent

log显示,seq_B grab请求被放到l仲裁队列的前面。因此,seq_B请求被提前服务,随后是其他请求。

你可能感兴趣的:(UVM,vlsiverify_uvm)