WayLookup Sub-module Documentation
WayLookup is a FIFO structure that temporarily stores metadata queried from MetaArray and ITLB by the IPrefetchPipe, for use by the MainPipe. It also monitors cacheline writes to SRAM by the MSHR and updates hit information. The update logic is the same as in the IPrefetchPipe; refer to the "Hit Information Update" section in the IPrefetchPipe Sub-module Documentation.
Bypass is allowed (i.e., when WayLookup is empty, enqueue requests can be dequeued directly). To avoid introducing the delay of the update logic into the DataArray access path, dequeueing is prohibited when MSHR has new writes. The MainPipe's S0 pipeline stage also needs to access the DataArray, and it cannot proceed when MSHR has new writes, so this measure does not introduce additional impact.
GPaddr Area-Saving Mechanism
Since gpaddr
is only useful when a guest page fault occurs, and after each gpf the front end is essentially working on an error path, the back end is guaranteed to send a redirect (WayLookup flush) to the front end (whether due to a misprediction/exception interrupt before the gpf, or the gpf itself). Therefore, WayLookup only needs to store the gpaddr
when the first gpf is valid after a reset/flush. For dual-line requests, only the gpaddr
of the first line with a gpf needs to be stored.
In implementation, gpaddr
and related signals (currently only gpaddr
) are split into two bundles with other signals (paddr
, etc.). Other signals are instantiated nWayLookupSize
times, while gpf-related signals are instantiated as only one register. A gpfPtr
pointer is also used. In total, this can save \((\text{nWayLookupSize}*2-1)* \text{GPAddrBits} - \log_2{(\text{nWayLookupSize})} - 1\) bits of registers.
When a prefetch writes to WayLookup, if a gpf occurs and there is no existing gpf in WayLookup, the gpf/gpaddr is written to the gpf_entry
register, and the gpfPtr
is set to the current writePtr
.
When the MainPipe reads from WayLookup, if bypass is active, the data enqueued by the prefetch is still dequeued directly; otherwise, if readPtr === gpfPtr
, the gpf_entry
is read out; otherwise, all zeros are read out.
It should be noted:
- Considering dual-line requests, only one copy of
gpaddr
needs to be stored (if the first line has a gpf, the second line must also be on the error path and doesn't need to be stored), but the gpf signal itself still needs to be stored twice because the IFU needs to determine if it's a cross-line exception. - The condition
readPtr === gpfPtr
might causereadPtr
to wrap around and become equal togpfPtr
again if the flush arrives late, thus incorrectly reading out the gpf again. However, as mentioned earlier, at this point the system is working on an error path, so reading out the gpf again is acceptable. - A special case needs attention: a fetch block that crosses a page boundary, where the first 32B are on the previous page without exception, and the last 2B are on the next page with a gpf. If the first 32B happen to be 16 RVC compressed instructions, the IFU will discard the last 2B and corresponding exception information. This might lead to the
gpaddr
for the next fetch block being lost. When WayLookup already contains gpf information that hasn't been consumed by the MainPipe, WayLookup's enqueue (i.e., IPrefetchPipe s1 pipeline stage) needs to be blocked. See PR#3719.