A monitor is a sub-component of the agent (along with other sub-components such as driver, sequencer, etc)
So it’s typical that the monitor has an analysis port which transactions get sent out on.
Then there is usually code within the agent (in the connect phase) to connect the monitor analysis port up to an agent level analysis port.
Within your environment you will instantiate the agent (not the monitor) plus other TLM components such as scoreboards, predictors, etc. So then you will see in the environment connect phase that you make a connection from the agent analysis port to an analysis export on either a predictor or scoreboard.
Thanks for the replies — that explains how it works, but I’m still trying to understand why it’s better, not just “cleaner.”
I get that env only has an agent handle, not a monitor handle. But SystemVerilog still lets me write agt.mon.ap.connect(...) and it works fine — so what actually breaks if I do that?
My best guess: if the same agent is reused in multiple environments, connecting through agt.ap means monitor-wiring logic lives in one place (inside the agent). Connecting agt.mon.ap directly means that wiring gets copy-pasted into every environment, so any internal change to the monitor means fixing it in N places instead of one.
Is that the real reason, or is there something else (active/passive agent, factory override, elaboration order) that actually breaks even in a single environment?