Question on using uvm_sequence_base

Hi
I have a question on using one uvm_sequence_base to start transactions on different agents in parallel. If I have the test snippet as below:


    class my_test extends uvm_test;
      base_env my_env;
      uvm_sequence_base seqb;
      
      `uvm_component_utils(test_base_seq)
      function new(string name="test_base_seq", uvm_component parent=null);
        super.new(name, parent);
      endfunction
      function void build_phase(uvm_phase phase);
        super.build_phase(phase);
        my_env=base_env::type_id::create("my_env", this);
        seqb = new("seqb");
      endfunction
      
      virtual task run_phase(uvm_phase phase);
        uvm_sequence_item rsp;
        super.run_phase(phase);
        phase.raise_objection(this);
        fork
          begin  //Thread 1
            pkt_type1 mypkt1;
            mypkt1= pkt_type1::type_id::create("mypkt1");
            seqb.start_item(mypkt1, -1, my_env.m_agent.sqr1);
            mypkt1.randomize();
            seqb.finish_item(mypkt1, -1);
            seqb.get_base_response(rsp, -1);
          end
          begin  //Thread 2
            pkt_type1 mypkt2;
            mypkt2= pkt_type2::type_id::create("mypkt2");
            seqb.start_item(mypkt2, -1, my_env.m_agent.sqr2);
            mypkt2.randomize();
            seqb.finish_item(mypkt2, -1);
            seqb.get_base_response(rsp, -1);
          end
          begin  //Thread 3
            pkt_type1 mypkt3;
            mypkt3= pkt_type3::type_id::create("mypkt3");
            seqb.start_item(mypkt3, -1, my_env.m_agent.sqr3);
            mypkt3.randomize();
            seqb.finish_item(mypkt3, -1);
            seqb.get_base_response(rsp, -1);
          end
          begin  //Thread 4
            pkt_type1 mypkt4;
            mypkt4= pkt_type4::type_id::create("mypkt4");
            seqb.start_item(mypkt4, -1, my_env.m_agent.sqr4);
            mypkt4.randomize();
            seqb.finish_item(mypkt4, -1);
            seqb.get_base_response(rsp, -1);
          end
        join
        phase.drop_objection(this);
      endtask
      
    endclass


I have 4 thread launched in parallel. These threads are using same sequence (seqb) but starting the transactions on different agents. Assuming these agents are independent, will the use of same sequence (seqb) result in serializing the transaction instead of launching the transactions simultaneously on all the agents.
My understanding is seqb.start_item() block until it get a grant from the sequencer which is triggered by get_next_item() call in driver. So if one driver is blocked while processing the current transaction will it effect the transactions being sent to other agents.

Please let me know if my understanding is incorrect.

Thank you
Sudarshan Vempati

In reply to svempati:

You should write a clean code, not mixing the content of a sequence with the content in a virtual sequence.
You have 1 sequence object and working with the same object in different agents. I do not believe this is your intent.
BTW the sequence does not belong to the topology of yout testbench and should not be constructed in the build_phase.

Hi
I have come up with a simpler version of the code which mimics the model I am working on to explain my question. So it is not perfect but just a working model. Below is the link to the complete TB code (simple code).

I see the below output with the code:

time: 0 : Thread 1
time: 0 : Thread 2
UVM_INFO testbench.sv(30) @ 10: uvm_test_top.my_env.m_agent.m_drv [DRIVER] time: 10: Drive pkt with addr: 10
UVM_INFO testbench.sv(87) @ 10: uvm_test_top.my_env.d_agent.m_drv [DRIVER] time: 10: Drive pkt with Data: 20
time: 10 : Thread 3
time: 10 : Thread 4
UVM_INFO testbench.sv(30) @ 20: uvm_test_top.my_env.m_agent.m_drv [DRIVER] time: 20: Drive pkt with addr: 30
UVM_INFO testbench.sv(87) @ 20: uvm_test_top.my_env.d_agent.m_drv [DRIVER] time: 20: Drive pkt with Data: 40

But I was expecting :

time: 0 : Thread 1
time: 0 : Thread 2
UVM_INFO testbench.sv(30) @ 10: uvm_test_top.my_env.m_agent.m_drv [DRIVER] time: 10: Drive pkt with addr: 10
UVM_INFO testbench.sv(87) @ 20: uvm_test_top.my_env.d_agent.m_drv [DRIVER] time: 20: Drive pkt with Data: 20
time: 20 : Thread 3
time: 20 : Thread 4
UVM_INFO testbench.sv(30) @ 30: uvm_test_top.my_env.m_agent.m_drv [DRIVER] time: 30: Drive pkt with addr: 30
UVM_INFO testbench.sv(87) @ 40: uvm_test_top.my_env.d_agent.m_drv [DRIVER] time: 40: Drive pkt with Data: 40

Can you please explain me if my understanding about sequence to driver communication is incorrect.

Thank you
Regards
Sudarshan Vempati

In reply to svempati:

As I said above the timing is defiend by the driver and not by the test.
You are progressing by #10 in the driver. This is exactly what you see.

Hi
Will the result be same if I have the same clock used by all these drivers of different agents.
From my understanding of sequence - driver communication:

seq.start_item is blocked till driver calls get_next_item.
seq.item_done is blocked till item_done is called by driver.

So will the start_item of the same sequence object in different threads result in simultaneously driving transaction or will it serialize them.

Thank you
Regards
Sudarshan Vempati

In reply to svempati:

Currently you do not use any clock.
If you are using different clocks in the drivers then the timing is defined by the actual clocks.