Using lock/unlock with STRICT_FIFO arbitration

I was just playing around with lock()/unlock() along with different arbitration schemes and created two seqs staring in a fork join in body of one vseq. Arbitration is set to UVM_SEQ_ARB_STRICT_FIFO. Priority of seq1 is 300 & that of seq2 is 200. I used lock to get control over sequencer in seq2 and was expecting that the output will be in following order as lock calling sequence will be granted
exclusive access to the driver when it gets its next slot via the sequencer arbitration mechanism:
CMD1,CMD1,CMD1,CMD1,CMD1,CMD2,CMD2,CMD2,CMD2,CMD2

But output was:

UVM_INFO @ 0: reporter [RNTST] Running test test…

UVM_INFO driver.sv(12) @ 0: uvm_test_top.my_env.agt.drv [uvm_test_top.my_env.agt.drv] Driving packet:cmd: CMD1

UVM_INFO driver.sv(12) @ 10: uvm_test_top.my_env.agt.drv [uvm_test_top.my_env.agt.drv] Driving packet:cmd: CMD2

UVM_INFO driver.sv(12) @ 20: uvm_test_top.my_env.agt.drv [uvm_test_top.my_env.agt.drv] Driving packet:cmd: CMD2

UVM_INFO driver.sv(12) @ 30: uvm_test_top.my_env.agt.drv [uvm_test_top.my_env.agt.drv] Driving packet:cmd: CMD2

UVM_INFO driver.sv(12) @ 40: uvm_test_top.my_env.agt.drv [uvm_test_top.my_env.agt.drv] Driving packet:cmd: CMD2

UVM_INFO driver.sv(12) @ 50: uvm_test_top.my_env.agt.drv [uvm_test_top.my_env.agt.drv] Driving packet:cmd: CMD2

UVM_INFO driver.sv(12) @ 60: uvm_test_top.my_env.agt.drv [uvm_test_top.my_env.agt.drv] Driving packet:cmd: CMD1

UVM_INFO driver.sv(12) @ 70: uvm_test_top.my_env.agt.drv [uvm_test_top.my_env.agt.drv] Driving packet:cmd: CMD1

UVM_INFO driver.sv(12) @ 80: uvm_test_top.my_env.agt.drv [uvm_test_top.my_env.agt.drv] Driving packet:cmd: CMD1

UVM_INFO driver.sv(12) @ 90: uvm_test_top.my_env.agt.drv [uvm_test_top.my_env.agt.drv] Driving packet:cmd: CMD1

Can anyone please justify the output?


class packet extends uvm_sequence_item;
  typedef enum bit[1:0]{CMD0,CMD1,CMD2,CMD3} cmd_e;
  rand cmd_e cmd;

  function new(string name="");
    super.new(name);
  endfunction

  function string convert2string();
    convert2string = $sformatf("cmd: %0s",cmd.name());
  endfunction

  `uvm_object_utils_begin(packet)
  `uvm_field_enum(cmd_e,cmd,UVM_ALL_ON)
  `uvm_object_utils_end
endclass:packet

class seq1 extends uvm_sequence;
  `uvm_object_utils(seq1)
  
  function new(string name="");
    super.new(name);
  endfunction
  
  task body;
    packet p1;
    repeat(5)begin
      `uvm_do_pri_with(p1,300,{p1.cmd == CMD1;});
    end
  endtask
endclass: seq1

class seq2 extends uvm_sequence;
  `uvm_object_utils(seq2)
  
  function new(string name="");
    super.new(name);
  endfunction
  
  task body;
    packet p1;
    lock();
    repeat(5)begin
      `uvm_do_pri_with(p1,200,{p1.cmd == CMD2;});
    end
    unlock();
  endtask
endclass: seq2

class vseq extends uvm_sequence;
  `uvm_object_utils(vseq)
  seq1 s1;
  seq2 s2;
  
  function new(string name="");
    super.new(name);
  endfunction
  
  task body;
    s1=seq1::type_id::create("s1");
    s2=seq2::type_id::create("s2");

    fork
      s1.start(m_sequencer);
      s2.start(m_sequencer);
    join
    
  endtask
endclass: vseq

class test extends uvm_test;
  
  env my_env;
  vseq para_seq;
  `uvm_component_utils(test)
  
  function new(string name="",uvm_component parent);
    super.new(name,parent);
  endfunction
  
  virtual function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    my_env=env::type_id::create("my_env",this);
    para_seq = vseq::type_id::create("p_seq");
  endfunction
  
  virtual task run_phase(uvm_phase phase);
    phase.raise_objection(this);
    my_env.agt.sqr.set_arbitration(UVM_SEQ_ARB_STRICT_FIFO);
    para_seq.start(my_env.agt.sqr);
    phase.drop_objection(this);
  endtask
endclass: test

class env extends uvm_env;
  agent agt;
  
  `uvm_component_utils(env)
  
  function new(string name="",uvm_component parent);
    super.new(name,parent);
  endfunction
  
  virtual function void build_phase(uvm_phase phase);
    super.build_phase(phase);
    agt=agent::type_id::create("agt",this);
  endfunction
  
endclass

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

class my_sequencer extends uvm_sequencer #(packet);
  `uvm_sequencer_utils(my_sequencer)

  function new (string name = "my_sequencer", uvm_component parent = null);
    super.new(name, parent);
  endfunction : new
endclass : my_sequencer

class driver extends uvm_driver#(packet);

  `uvm_component_utils(driver)
  
  function new(string name="",uvm_component parent);
    super.new(name,parent);
  endfunction
  
  task run_phase(uvm_phase phase);
    forever begin
      seq_item_port.get_next_item(req);
      `uvm_info(get_full_name(),$sformatf("Driving packet:%0s",req.convert2string()),UVM_LOW)
      #10
      seq_item_port.item_done();
    end
  endtask
endclass

`include "uvm_macros.svh"
`include "pkg.sv"

module tb;
  import uvm_pkg::*;
  import pkg::*;
  
  initial begin
    run_test("test");
  end
endmodule: tb


In reply to saumya thacker:

The problem is that sequences do not get arbitrated, only sequence_items. seq1 and seq2 start concurrently and the lock in seq2::body() takes effect at time 0.

There are many different schemes to get the effect of arbitrating sequences, one is to use layering.