How to send data from Monitor to Sequence

Hi All,
Can you please share the working code of how to send data from Monitor to sequence using TLM Ports

In reply to srikanth.verification:

If you provide scenario what you want to pass from monitor to sequence.
May be someone can guide you best way.

Btw you can check this :-

sending data from monitor to sequence | Verification Academy.

In reply to srikanth.verification:

whenever there will be change in interrupt, monitor needs to send the data to sequence and then i can perform register operations from the monitor status
Please look this code and share your valuable feedback
//////////////transaction class
class interrupt_transaction extends uvm_sequence_item;

`uvm_object_utils(interrupt_transaction)
rand bit [3:0] interrupt;

extern function new (string name = “interrupt_transaction”);

endclass

function interrupt_transaction::new(string name = “interrupt_transaction”);
super.new(name);
endfunction

class interrupt_mon extends uvm_monitor;
//////////////////////factory registration/////////////////////
`uvm_component_utils(interrupt_mon)

//////////////////////virtual interface //////////////////////

virtual mcu_status_if intr_vif;
interrupt_transaction intr_txn;
function new(string name=“interrupt_mon”, uvm_component parent);
super.new(name, parent);
endfunction : new

function void build_phase(uvm_phase phase);
super.build_phase(phase);
intr_txn = interrupt_transaction::type_id::create(“intr_txn”);

endfunction : build_phase

function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
endfunction : connect_phase

task run_phase(uvm_phase phase);
forever
@(posedge intr_vif.McuClk);
begin
intr_txn.interrupt = intr_vif.Interrupt;
uvm_info("DATA FROM MON", $sformatf("DATA received from Interrupt MONITOR is : [%p] \n", intr_txn.interrupt),UVM_LOW) end endtask : run_phase function void report_phase(uvm_phase phase); uvm_info(get_type_name(), “Interrupt Entering into Monitor”, UVM_LOW)
endfunction
endclass

//////////////////////////Sequence////////////////////////////////////////
class interrupt_sequence extends base_seq;

`uvm_object_utils (interrupt_sequence)

interrupt_transaction intr_item;

function new(string name = “interrupt_sequence”);
super.new(name);
endfunction

task body();
intr_item = interrupt_transaction::type_id::create(“intr_item”);
start_item(intr_item);
assert(intr_item.randomize());
finish_item(intr_item);

`uvm_info(“DATA FROM MON”, $sformatf(“DATA received from Interrupt MONITOR is : [%p] \n”, intr_item.interrupt),UVM_LOW)
if i get the status from monior then i can perform the register operations, please help me to achieve this
/////////////////////////read interrupt controller status
///////////////////////// check intialization is completed or not MCUINITDONE in MCUCL_Reg spec/////
//////////////////////// if it is set mask the init_mask_parm by setting it to 1

endtask
endclass

In reply to srikanth.verification:

the below are steps you can do :

  1. create an analysis port in monitor which is to send a txn’s item
  2. create an analysis fifo in sequencer which receives the txn’s from monitor
  3. connect analysis_port to fifo.analysis_export
  4. in sequence, wait for p_seqeuncer.fifo.get() to get txn’s monitor and do your logic there

sample code: Edit code - EDA Playground

there are many ways you can implement it but this is one of the way

In reply to Desam:
For interrupt handling this is a complicated approach. Output signals of the DUT might share more than 1 virtual interface. You can put it to the oinlevel interface responsible for the interrupt routine. In this case you do not need monitor, because you can send a response from the driver to the sequence.

In reply to chr_sue:

hi Chr_sue,
im getting this error when im connecting in agent analysis port to analysis export connections. “0:E:m_sequencer.res_fifo: Connection Error: connection count of 0 does not meet required minimum of 1”. please find the below code

class interrupt_agent extends vvm_agent_c;
// Factory Registration
`uvm_component_utils(interrupt_agent)

// Declare handles of interrupt_monitor,iterrupt_sequencer
interrupt_mon monh;
interrupt_sequencer m_sequencer;
virtual mcu_status_if intr_vif;
//------------------------------------------
// METHODS
//------------------------------------------

// Standard UVM Methods:
extern function new(string name = “interrupt_agent”, uvm_component parent = null);
extern function void build_phase(uvm_phase phase);
extern function void connect_phase(uvm_phase phase);

endclass : interrupt_agent
//----------------- constructor new method -------------------//

function interrupt_agent::new(string name = “interrupt_agent”, uvm_component parent = null);
super.new(name, parent);
endfunction

//----------------- build() phase method -------------------//
// Call parent build phase
// Create interrupt_agent instance
// If is_active=UVM_ACTIVE, create interrupt_agent and interrupt_agent instances

function void interrupt_agent::build_phase(uvm_phase phase);
super.build_phase(phase);
m_sequencer=interrupt_sequencer::type_id::create(“m_sequencer”,this);

monh=interrupt_mon::type_id::create("monh",this);	

    `

endfunction

//----------------- connect() phase method -------------------//
//If is_active=UVM_ACTIVE,
//connect driver(TLM seq_item_port) and sequencer(TLM seq_item_export)

function void interrupt_agent::connect_phase(uvm_phase phase);
super.connect_phase(phase);
monh.intr_vif = intr_vif;

 monh.ap.connect(m_sequencer.res_fifo);

endfunction

////////////////////////////Sequencer///////////////////
class interrupt_sequencer extends vvm_sqr_c #(interrupt_transaction);

`uvm_component_utils(interrupt_sequencer)

//uvm_tlm_analysis_fifo#(interrupt_transaction) res_fifo; //I have used both tlm analysis fifo and analysis_export

uvm_analysis_export #(interrupt_transaction) res_fifo;
function new(string name=“interrupt_sequencer”,uvm_component parent=null);
super.new(name);
res_fifo = new(“res_fifo”,this);
endfunction

endclass

/////////////////Monitor/////////////////
class interrupt_mon extends vvm_monitor_c;
//////////////////////factory registration/////////////////////
`uvm_component_utils(interrupt_mon)
//uvm_blocking_peek_imp#(interrupt_transation) intr_imp;

//////////////////////virtual interface //////////////////////

virtual mcu_status_if intr_vif;
interrupt_transaction intr_txn;

uvm_analysis_port #(interrupt_transaction) ap;

function new(string name=“interrupt_mon”, uvm_component parent);
super.new(name, parent);
ap = new(“ap”,this);

endfunction : new

function void build_phase(uvm_phase phase);
super.build_phase(phase);
intr_txn = interrupt_transaction::type_id::create(“intr_txn”);

endfunction : build_phase

function void connect_phase(uvm_phase phase);
super.connect_phase(phase);
endfunction : connect_phase

task run_phase(uvm_phase phase);
forever begin
@(posedge intr_vif.McuClk);
intr_txn.interrupt = intr_vif.Interrupt;
`
ap.write(intr_txn);

  end

endtask : run_phase

function void report_phase(uvm_phase phase);
`uvm_info(get_type_name(), “Interrupt Entering into Monitor”, UVM_LOW)
endfunction

endclass

In reply to srikanth.verification:

Fllow the code as shown here
https://www.edaplayground.com/x/NiBA

Again, this is a complicated solution. Using a response detected in the driver and put back to the sequence is the easiest way to deal with interrupts.

In reply to chr_sue:

As I mentioned in the code using both analysis export and tlm_analysia_fifo throughing the same error

In reply to srikanth.verification:

** Error: (vsim-7065) Illegal assignment to class libextdv.uvm_pkg::uvm_port_base #(class libextdv.uvm_pkg::uvm_tlm_if_base #(class libbdv.mcu_units_pkg::interrupt_transaction, class libbdv.mcu_units_pkg::interrupt_transaction)) from class libextdv.uvm_pkg::uvm_tlm_analysis_fifo #(class libbdv.mcu_units_pkg::interrupt_transaction)

In the agent im getting this error when im connecting in the agent, monitor to sequencer connection

In reply to chr_sue:

Thanks for your suggestion…

In reply to srikanth.verification:

plz try using method mentioned by @chr_sue.
“Using a response detected in the driver and put back to the sequence is the easiest way to deal with interrupts” → This is good way to implement it

In reply to chr_sue:
with tlm_analysis fifo connections are compiled but It is hanging in forever loop of the sequence
Please find the sequence
typedef class mcu_base_seq_c;

class interrupt_sequence extends mcu_base_seq_c;
interrupt_transaction intr_item;
`uvm_declare_p_sequencer(interrupt_sequencer)

uvm_object_utils (interrupt_sequence) // uvm_event_pool ev_pool = uvm_event_pool::get_global_pool(); // uvm_event ev; //interrupt_transaction intr_item; //uvm_declare_p_sequencer(interrupt_sequencer)

function new(string name = “interrupt_sequence”);
super.new(name);
intr_item = interrupt_transaction::type_id::create(“intr_item”);

endfunction

task body();
bit [31:0] intr_data;
forever begin
// wait for a txn from monitor fifo.get() → it’s a blocking statement
p_sequencer.intr_fifo.get(intr_item);
`uvm_info(“DATA FROM Mon_Seq”, $sformatf(“DATA received from RX MONITOR is : [%p] \n”, intr_item.interrupt),UVM_LOW)
// DO your logic and send the txns to sequener again
if(intr_item.interrupt[0]) begin
axi_read(“INT_STATUS_INIT”,intr_data, 0, “CTL”);
if(intr_data == 1) begin
axi_write(“INT_MASK_INIT”,0, 0, “CTL”);
end
end
end

//   `uvm_info("DATA FROM MON", $sformatf("DATA received from Interrupt MONITOR is : [%p] \n", intr_item.interrupt),UVM_LOW)

endtask
endclass

In reply to srikanth.verification:

Then there is no interrupt transaction. The get method is a blocking method and is waiting for the interrupt transaction.

///////////////////Data Entering to Sequence//////////// From sequence prints Sequence

93130000:I:m_sequencer@@intr_seq: Sequence: #########Entering in to body method

93130000:I:m_sequencer@@intr_seq: DATA FROM Mon_Seq: DATA received from RX MONITOR is : [0]

93130000:I:m_sequencer@@intr_seq: DATA FROM Mon_Seq: DATA received from RX MONITOR is : [0]

19902960000:I:m_sequencer@@intr_seq: DATA FROM Mon_Seq: DATA received from RX MONITOR is : [1]

////////////Sequence Body Method//////////////
task body();
uvm_info("Sequence","#########Entering in to body method",UVM_LOW) forever begin // wait for a txn from monitor fifo.get() -> it's a blocking statement p_sequencer.intr_fifo.get(intr_item); uvm_info(“DATA FROM Mon_Seq”, $sformatf(“DATA received from RX MONITOR is : [%p] \n”, intr_item.interrupt),UVM_LOW)
// DO your logic and send the txns to sequener again
end
// `uvm_info(“DATA FROM MON”, $sformatf(“DATA received from Interrupt MONITOR is : [%p] \n”, intr_item.interrupt),UVM_LOW)

endtask

//////////////in Test im calling the sequence on sequencer///////////

       intr_seq.start(m_mcu_env.intrpt.m_sequencer);

im not using fork join_none, the sequence is not getting the transaction from the monitor and it is running continously.

when i kept fork_join_none, simulation is completed but from monitor to sequence only 3 transaction are coming remaining transactions are not coming to sequence but the remainin transaction im able to see from monitor. Can you please let me know what i need to do to capture all transactions from monitor to sequence

In reply to srikanth.verification:

Your simulation stops after all objections has been dropped. To extend the processing you can set a drain_time or use the method

phase_ready_to_end (uvm_phase phase);

which is a method of uvm_component.
Both ways will extend your phaseses and ensure you get all transactions.

You should ask you if it is sufficient to get 1 or 2 transaction less than generated.
If you are generatin 1 million of seq_items. 2 missing transaction in the analysis path might not be relevant.

Hi Chr_sue can you please tell how to use phase_ready_to_end phase in my code. can you please give modify my below code

task configure_phase(uvm_phase phase);

    phase.raise_objection(this);
    do_init();
    if(m_mcu_tsm_pem_seq_enable)
      do_tsm_pem_seq();
    phase.drop_objection(this);
endtask : configure_phase

protected task do_init();

      `vvm_info("do_init", "start")

      do_cdn();
 fork
       do_interrupt();
 join_none ////////////////////
      
      train();
     
endtask : do_init

protected task do_interrupt();
interrupt_sequence seq;
`vvm_info(“interrupt_sequence”, “start”)
seq = new(“interrupt_sequence”);

    seq.start(intrpt.m_sequencer);
  `vvm_info("interrupt_sequence", "finish")
endtask : do_interrupt

fork
do_interrupt();
join_none ////////////////////

If i remove fork join_none block it is hanging. if i kept fork join_none then only 3 transactions are coming but in my fifo there are 26 transactions. want to use all of those in to the sequence. can you please tell how to use phase ready to end to with or with out fork join_none?

////////////////////////Information from Monitor ////////////////////////////////

840000:I:uvm_test_top.chip0_mcu0.intrpt.monh: DATA FROM MON: DATA received from Interrupt MONITOR is : [0]

2520000:I:uvm_test_top.chip0_mcu0.intrpt.monh: DATA FROM MON: DATA received from Interrupt MONITOR is : [0]

19902960000:I:uvm_test_top.chip0_mcu0.intrpt.monh: DATA FROM MON: DATA received from Interrupt MONITOR is : [1]

45142440000:I:uvm_test_top.chip0_mcu0.intrpt.monh: DATA FROM MON: DATA received from Interrupt MONITOR is : [5]

45148320000:I:uvm_test_top.chip0_mcu0.intrpt.monh: DATA FROM MON: DATA received from Interrupt MONITOR is : [1]

45377640000:I:uvm_test_top.chip0_mcu0.intrpt.monh: DATA FROM MON: DATA received from Interrupt MONITOR is : [5]

45383520000:I:uvm_test_top.chip0_mcu0.intrpt.monh: DATA FROM MON: DATA received from Interrupt MONITOR is : [1]

45602760000:I:uvm_test_top.chip0_mcu0.intrpt.monh: DATA FROM MON: DATA received from Interrupt MONITOR is : [5]

45608640000:I:uvm_test_top.chip0_mcu0.intrpt.monh: DATA FROM MON: DATA received from Interrupt MONITOR is : [1]

45832920000:I:uvm_test_top.chip0_mcu0.intrpt.monh: DATA FROM MON: DATA received from Interrupt MONITOR is : [5]

45838800000:I:uvm_test_top.chip0_mcu0.intrpt.monh: DATA FROM MON: DATA received from Interrupt MONITOR is : [1]

46062240000:I:uvm_test_top.chip0_mcu0.intrpt.monh: DATA FROM MON: DATA received from Interrupt MONITOR is : [5]

46068120000:I:uvm_test_top.chip0_mcu0.intrpt.monh: DATA FROM MON: DATA received from Interrupt MONITOR is : [1]

46282320000:I:uvm_test_top.chip0_mcu0.intrpt.monh: DATA FROM MON: DATA received from Interrupt MONITOR is : [5]

46288200000:I:uvm_test_top.chip0_mcu0.intrpt.monh: DATA FROM MON: DATA received from Interrupt MONITOR is : [1]

46512480000:I:uvm_test_top.chip0_mcu0.intrpt.monh: DATA FROM MON: DATA received from Interrupt MONITOR is : [5]

46518360000:I:uvm_test_top.chip0_mcu0.intrpt.monh: DATA FROM MON: DATA received from Interrupt MONITOR is : [1]

46737600000:I:uvm_test_top.chip0_mcu0.intrpt.monh: DATA FROM MON: DATA received from Interrupt MONITOR is : [5]

46743480000:I:uvm_test_top.chip0_mcu0.intrpt.monh: DATA FROM MON: DATA received from Interrupt MONITOR is : [1]

46967760000:I:uvm_test_top.chip0_mcu0.intrpt.monh: DATA FROM MON: DATA received from Interrupt MONITOR is : [5]

46973640000:I:uvm_test_top.chip0_mcu0.intrpt.monh: DATA FROM MON: DATA received from Interrupt MONITOR is : [1]

47197920000:I:uvm_test_top.chip0_mcu0.intrpt.monh: DATA FROM MON: DATA received from Interrupt MONITOR is : [5]

47203800000:I:uvm_test_top.chip0_mcu0.intrpt.monh: DATA FROM MON: DATA received from Interrupt MONITOR is : [1]

47423040000:I:uvm_test_top.chip0_mcu0.intrpt.monh: DATA FROM MON: DATA received from Interrupt MONITOR is : [5]

47428920000:I:uvm_test_top.chip0_mcu0.intrpt.monh: DATA FROM MON: DATA received from Interrupt MONITOR is : [1]

50150631000:I:uvm_test_top.chip0_mcu0.intrpt.monh: interrupt_mon: Interrupt Entering into Monitor

////////////////////////From Sequence

21930630000:I:m_sequencer@@interrupt_sequence: DATA FROM Mon_Seq: DATA received from RX MONITOR is : [0]

21940630000:I:m_sequencer@@interrupt_sequence: DATA FROM Mon_Seq: DATA received from RX MONITOR is : [0]

21950630000:I:m_sequencer@@interrupt_sequence: DATA FROM Mon_Seq: DATA received from RX MONITOR is : [1]

only 2 transactions only im able to get into the sequence, can you please tell me why remaining transfers are not coming to sequence

In reply to srikanth.verification:

do_interrupt is the task which calls my sequence on sequencer. can you tell me how to do other changes for this inorder to get remaining transactions int the sequence from monitor

In reply to srikanth.verification:

First recommendation.
Please do not use the sub-phases of the run_phase. Your problem might be caused by this.