A better way of getting response back to a waiting sequence?

For a while I have been annoyed that UVM is inconsistent in the way responses are passed back through the sequencer, but maybe I am missing something obvious?
Let me try to explain my problem

I have highly pipelined agent - where the driver must drive transactions back to back - without waiting for response data.
but when that data comes it must be passed back to the sequence that initiated the transaction.
un fortunately the responses come out of order!

A way of doing this, is by using the get_response() in the sequence.
unfortunately the monitor does not have access to the response FIFO in the sequencer, so the put() must be called from the driver.

and this is where I find that UVM is inconsistent at best.
The UVM methodology has a clear boundary between driver and monitor tasks.
the driver drives transactions on the pins,
the monitor convert from pin wiggles into transactions.
the monitor also passes the transactions on to a scoreboard and any other subscriber that needs the info - except the sequence!
that has to come from the driver.

so now I am forced to make the driver a subscriber of my monitor to be able to pass it to the correct sequence.

I want to note here that I have N sequences that starts items on my sequencer in parallel!

is there a better way of doing this?
if UVM where to be consistent - there should be a build in tlm port in the driver - where the monitor could get the items and then the monitor would do the response matching and the put to the sequence response fifo!

As you mentioned, the response is passed from driver using item_done(rsp)/put(rsp) and sequencer fetches those using get_response(rsp).

Monitor fetches trans on pin level and it does transfer of the trans to SB/subscriber based on need.

But, rsp and req of the driver are two different entities and they are not same. Monitor implements run_phase to compose “req” transaction, and the driver sends “rsp” which contains modified sequence_item properties to sequence via sequencer which may be used by sequence. So, its not duty of sequencer to send those to monitor.

Also, the rsp are out of order due to arbitration and processing of multiple sequence items in parallel.

You can make use of TLM analysis port “rsp_port” "of the driver to get the responses into your desired component.

    m_driver.rsp_port.connect(m_sequencer.rsp_export);

I think there is a misunderstanding,
I never asked for the sequencer to send anything to the monitor, IMO it would make more sense if the monitor used the put(), not the driver.
because now you need to get pin level transactions from monitor to driver.
which is contradicting the purpose of the driver!

an example is a memory read.
the driver, drives the request - the monitor records the reponse data.
now this is passed to the driver to match with the request - copy the underlying ID using set_id_info() and the passed to the sequencer using put()

a more natural way,(and more uvm like) would have been the driver sends a request,
and forwards the item to the monitor (which will already record the request from the pins),
the monitor copies the underlying id using set_id_info().
when the response comes it adds it to the original request and send it to the sequencer using put.
now we have separated the behavior of monitor/driver - such that they are uni-directional.
driver send stuff downstream - monitor sends stuff upstream.
Anyway I don’t think that UVM currently allows for this.
I was just looking for an alternate way than my 1st described way

I am also struggling with how to best handle response “traffic” (of template RSP ) back up to the pertinent sequence in a clean way, and furthermore, how to handle the passing of a request (of template type REQ) up to a responder sequence (using template type RSP for its sequence items).

I quote from the previous reply post: “a more natural way,(and more uvm like) would have been the driver sends a request,
and forwards the item to the monitor (which will already record the request from the pins), …”

I too like the involvement of the monitor of this, though contrary to the quoted above, it should not have to depend on the presence of the driver, since passive agents don’t have a driver (albeit that in that case you will not be running a sequence on the passively monitored interface). IMO, there should be a monitor on a bidirectional REQ/RSP interface and it should monitor both uncompleted requests (ie w/o response) to feed predictor/scoreboard for computing expected responses, and also monitor completed requests (ie w/ response) to feed scoreboard for actual responses. Or should this be a separate request and separate response monitor?

Wrt to slave/responder sequences, the examples given from the cookbook are interesting, but I find them still rather confusing in that a reponder sequence tends to do start/finish item twice in the body, the first time to set up the request object for the driver, to be filled by the DUT as master when it issues a request on the interface, then secondly for the response object, now randomizable based on request attributes as the actual item driven by the response agent. It is the use of REQ and RSP template types in these scenarios that really hurst the head.

Isn’t there a better, more intuitive way - causing less headache - to handle the very common scenario of a bidirectional req/resp interface where the testbench is the cclient/slave?

Also, the UVMF doesn’t really deal with this at all, and aims to simplify the use model by just assuming that the response item is embedded in the request item so that one can deal only with one sequence item type through get_next_item(txn) … item_done() - no need for the arguent to item_done as all parties involved, sequence(r) and driver have a pointer to the txn item and will see any updates to the item’s attributes during the handshake.

As much as I like the UVM for the structure it imposes, and UVMF does even a better job in that, I’ve always much disliked the way sequences have been implemented - rather convoluted, and this comes back to haunt me yet again ;)

Driver also can to do the monitoring if it needs to handle out of order response.

My understanding is that monitor is a passive component. It should never be involved at stimulus generation which is done by driver and sequencer. If the sequencer needs to use dut response to decide future transaction, it is allowed to capture response from driver. But that is not the job of monitor.