Sending data from monitor to sequence

Hi,

I’ve two agents in a ENV. one agent is active and another agent is passive. I need to send transactions captured in passive agent’s monitor to Active agent’s sequence, such that active agent’s driver need to drive the next stimulus accordingly.
I know that via peek method and p_sequencer, it’s possible to send transactions from one agent’s monitor to that corresponding agent’s sequence.
But, in my case, I need to send transactions from one agent’s monitor to another agent’s sequence !!
Please let me know, how to approach in this scenario.

In reply to nani9483:

Use the analysis_port of the monitor to send the transaction(s) to another uvm_subscriber - probably with a tlm_fifo in it. If you build a get_port into it (or whatever meets your needs), then you just have to pass that handle to your sequence.

Hi tfitz,

Thanks a lot for your quick response.
uvm_subscriber should be visible to both agents. So, obviously that uvm_subscriber should be in my ENV, which is having my two agents. Am I correct ??

Hi tfitz,

Please let me know the syntax for passing tlm fifio handle to sequence.

In reply to nani9483:

Hi,
I’ve two agents in a ENV. one agent is active and another agent is passive. I need to send transactions captured in passive agent’s monitor to Active agent’s sequence, such that active agent’s driver need to drive the next stimulus accordingly.
I know that via peek method and p_sequencer, it’s possible to send transactions from one agent’s monitor to that corresponding agent’s sequence.
But, in my case, I need to send transactions from one agent’s monitor to another agent’s sequence !!
Please let me know, how to approach in this scenario.

For me it is not clear why you need the 2 agents. Are they connected to the same virtual interface.
There is an easy way to pass responses back from the driver to the sequence you are just executing using item_done(rsp). In the sequence you have to execute get_response to retrive the sequnce from the seuqnce fifo.

Hi chr_sue,

Two agents are connected to two different virtual interfaces.
Please let me know the syntax for passing handle from tlm fifo to uvm_sequence, as tfitz said.

In reply to nani9483:

I believe your story might be more complicated than you are saying. If you need such a cross connection then you have to synchronize the agents in some way. Right?

Yes chr_sue. We need to synchronize the two agents. I want the data collected in passive agent monitor in my active_agent’s sequence (as discussed in my first question) and also in active_agent’s monitor. Please suggest a good plan to achieve this scenario.

First, I’ll answer your question to me. Then I’ll comment on the other responses.
Assuming you build a subscriber with a tlm_fifo or analysis_fifo in it (actually, an analysis_fifo may be all you need), then you simply declare a get_port with the appropriate type parameter in your sequence. Then, after creating the instance of your sequence, you assign its get_port to the analysis_fifo.get_port and then your sequence can call get_port.get() to get the transaction out of the fifo.

There is still the question of synchronization. Assuming that each transaction being driven depends on a transaction being received, then you can use a fifo of depth one. Except for the first transaction being driven, of course.

I think a better explanation of why you think you need such a setup would be helpful. There may be better ways of accomplishing what you think you need.

In reply to nani9483:

Yes chr_sue. We need to synchronize the two agents. I want the data collected in passive agent monitor in my active_agent’s sequence (as discussed in my first question) and also in active_agent’s monitor. Please suggest a good plan to achieve this scenario.

If you really need to send data from 1 agent to another one you could use the uvm_event_pool and passing the constraints along with the trigger.

Hi chr_sue and Tfitz,

As per your inputs, how to pass data using uvm_event_pool and how to get that data using uvm_event_pool ??

If this happens means, I’ll pass the data in my passive agent using uvm_event_pool.
I’ll get that data in my active agent’s sequence and also in my active agent’s monitor.

Please let me know the syntax for passing and getting data using uvm_event_pool.

Thanks.

In reply to nani9483:

Please try this.
In your monitor:

class monitor extends uvm_monitor;
  my_transaction req;
  uvm_event_pool ev_pool = uvm_event_pool::get_global_pool();
  ...
  task run_phase(uvm_phase phase);
    req = my_transaction::type_id::create("req");
    req.<data_members>; //assemble your transaction

    uvm_event ev = ev_pool.get("mon_ev");
    ev.trigger(req);
   .....
  endtask
endclass

In your sequence:

class my_sequence extends uvm_sequence #(my_transaction);
  uvm_event_pool ev_pool = uvm_event_pool::get_global_pool();
  ...
  task body();
    my_transaction req;
    req = my_transaction::type_id::create("req");
    uvm_event ev = ev_pool.get("mon_ev");
    ev.wait_trigger();
    $cast(req, ev.get_trigger_data()); 
   ....
  endtask
1 Like

Hi chr_sue,

Thanks a lot for your quick response. I’ll try this code once the DUT is ready.
Can I use the same procedure to send data from passive monitor to active monitor via uvm_event_pool??

In reply to SV_UVM_Learner:

This works for any component you want to send data.

1 Like

Okay chr_sue,

Thanks a lot.

Hi chr_sue,

I tried this logic in my passive monitor and my sequence. In my passive monitor, I kept a display message after triggering the data, and I’m getting that display message. I tried the same logic in my sequence too. But my simulation is blocking, after getting the display message from my passive monitor. Please help me.

I’ve a doubt. Do we need to use the same transaction class handle in both monitor and sequence (in this case, it’s “req”), while using this event_pool ??

// --------------------- monitor run phase method ------------------------ //

task run_phase(uvm_phase phase);
	//forever
		begin
			txn = rx_txn ::type_id::create("txn");
                            txn.array = {10,20,30,40,50}; //assigning some dummy data to my transaction class, as DUT is not yet ready!
		
	 `uvm_info("RX_MON_DATA", $sformatf("DATA sending from RX MONITOR is : [%p] \n", txn.array),UVM_LOW) // data {10,20,30,40,50} is printing
            ev = ev_pool.get("mon_ev");
            //uvm_event ev = ev_pool.get("mon_ev");
                ev.trigger(txn);
              `uvm_info("TRIGGER_DATA", $sformatf("DATA triggered in  RX Monitor"),UVM_LOW) //This display is printing , after that simulation is getting blocked/hanged!! 

		end
endtask : run_phase

// --------------------- sequence ------------------------ //

class rx_reset_seq extends rx_base_seq;
uvm_event_pool ev_pool = uvm_event_pool::get_global_pool();
uvm_event ev;

`uvm_object_utils(rx_reset_seq)

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

task body();
	req = rx_txn ::type_id::create("req");
            //uvm_event ev = ev_pool.get("mon_ev");
            ev = ev_pool.get("mon_ev");
           	start_item(req);
	assert(req.randomize());
	finish_item(req);
            ev.wait_trigger();
            $cast(req, ev.get_trigger_data());

// How to print my data here ?? ie., how can I print my sent data here ?? ie., {10,20,30,40,50}
endtask : body

endclass

Hi chr_sue,
Please see my code, and help me, if I’m doing wrong …
Do we need to create a separate class for uvm_event by extending from uvm_object ?? or not necessary ??
Anticipating a favourable reply from you at the earliest.

In reply to SV_UVM_Learner:

Please try this code. It is only slidely modified:

// --------------------- monitor run phase method ------------------------ //
class driver extends uvm_driver #(txn);

  ....
  uvm_event_pool ev_pool = uvm_event_pool::get_global_pool();

task run_phase(uvm_phase phase);
//forever
  begin
    txn = rx_txn ::type_id::create("txn");
    txn.array = {10,20,30,40,50}; //assigning some dummy data to my transaction class, as DUT is not yet ready!

    `uvm_info("RX_MON_DATA", $sformatf("DATA sending from RX MONITOR is : [%p] \n", txn.array),UVM_LOW) // data {10,20,30,40,50} is printing
    uvm_event ev = ev_pool.get("mon_ev");  //creates the event "mon_event" 
    ev.trigger(txn);
    `uvm_info("TRIGGER_DATA", $sformatf("DATA triggered in RX Monitor"),UVM_LOW) //This display is printing , after that simulation is getting blocked/hanged!!

  end
endtask : run_phase

// --------------------- sequence ------------------------ //

class rx_reset_seq extends rx_base_seq;
  uvm_event_pool ev_pool = uvm_event_pool::get_global_pool();
  uvm_event ev;

  `uvm_object_utils(rx_reset_seq)

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

task body();
  req = rx_txn ::type_id::create("req");
  //uvm_event ev = ev_pool.get("mon_ev");
  ev = ev_pool.get("mon_ev");
  start_item(req);
  assert(req.randomize());
  finish_item(req);
  ev.wait_trigger();
  $cast(req, ev.get_trigger_data());
  `uvm_info("DATA FROM MON", $sformatf("DATA received from RX MONITOR is : [%p] \n", req.array),UVM_LOW) 
endtask : body

endclass

Thanks a lot for your quick response.
Can we use different transaction class handles in monitor and sequence?? Like here, txn in monitor and req in sequence??

In reply to SV_UVM_Learner:

txn and req are only the names. We have to use the same types.