# ICache Memory UVM Agent

The ICache memory UVM agent models the instruction memory bus downstream of the ICache.
This also includes the PMP machinery.

The basic idea is that instruction memory is modelled with a single 32-bit *seed*.
A simple hash function takes this seed and calculates 32 bits of memory for each (aligned) base address.
The seed also determines a memory region which should result in PMP errors and another memory region that should result in memory errors.

The agent exposes a slave interface to the core using the usual UVM architecture for a reactive slave, but it looks a little complicated because we need to spot PMP errors immediately (rather than on the next clock edge).
The entire dance is as follows:

  1. The monitor spots a new request (either because of a posedge on the `req` line or a change in the `addr` line).
  1. It generates an `ibex_icache_mem_req_item` with `is_grant` field false and writes it to the sequencer's request port.
  1. This request gets picked up by the sequence (in `ibex_icache_mem_resp_seq.sv`).
  1. The sequence checks for a PMP error using its internal memory model and generates a sequence item (of type `ibex_icache_mem_resp_item`) with `is_grant` field false.
  1. This sequence item is picked up by the driver, which uses it to drive the PMP line appropriately.
  1. If the PMP response didn't squash the request, it will get granted at some point when the `grant` line goes high. At this point, the monitor will spot the request being granted and create another `ibex_icache_mem_req_item`, writing it to the sequencer's request port. This time, the `is_grant` field is true.
  1. This request in turn gets picked up by the sequence (in `ibex_icache_mem_resp_seq.sv`).
  1. The sequence uses its memory model to decide the data to be fetched and whether the response should have an error. The results get written into a sequence item with `is_grant` field true.
  1. When the driver picks up this sequence item, it adds it to a response queue.
  1. Responses get popped from the response queue in order. Each causes a delay of zero or more cycles and then the response is finally driven onto the bus with `rvalid`, `rdata` and `err`.
