There’s a lot of useful information in the UVM Cookbook:
Cookbook/Agent
Cookbook/MonitorComponent
Cookbook/AnalysisConnections
Use the “Multiple Transaction Streams With Synchronization” example as a template for agent2. You’ll do something like:
class agent2 extends uvm_agent;
`uvm_component_utils(agent2)
uvm_analysis_export #(agent1_pkt) from_agent1;
uvm_tlm_analysis_fifo #(agent1_pkt) from_agent1_fifo;
function new( string name , uvm_component parent) ;
super.new( name , parent );
endfunction
function void build_phase( uvm_phase phase );
agent1_fifo = new("agent1_fifo", this);
from_agent1 = new("from_agent1", this);
endfunction
function void connect_phase( uvm_phase phase );
from_agent1.connect(agent1_fifo.analysis_export);
endfunction
endclass
Then, you’ll have to connect the agent1_fifo.get_peek_export to your agent2.driver (just extend the driver and add in a get_peek_port). Then, in your agent2.driver’s run_phase method, do something like:
task run_phase(uvm_phase phase);
get_peek_port.get(t1);
// process t1 in some way
seq_item_port.get_next_item(t2);
// send t2 to bus
endtask
If this doesn’t make sense, I’d suggest that you read the Cookbook and watch the Beginner and Advanced UVM videos here on Verification Academy.
Good luck,
-Tom