Non-blocking Cache and MSHR
---------------------------

At the cache level, non-blocking caches are used to handle multiple simultaneous cache-misses. This is especially crucial for the shared last level cache (LLC), as it is shared by all cores. The state of the outstanding memory requests are maintained by a set of miss status holding registers (MSHRs). On a cache-miss, the LLC allocates a MSHR entry to track the status of the ongoing request and the entry is cleared when the corresponding memory request is serviced from the main memory. As such, the number of MSHRs effectively determines the maximum number of outstanding memory requests directed to the DRAM controller.

DRAM Controller
---------------

The DRAM controller receives requests from the LLC (or other DMA devices) and generates DRAM specific commands to access data in the DRAM. Modern DRAM controllers often include separate read and write *request buffers* and *prioritize reads* over writes because writes are not on the critical path for program execution. Write requests are buffered on the write buffer of the DRAM controller and serviced when there are no pending read requests or the write queue is near full [@natarajan2004study; @chatterjee2012staged]. The DRAM controller and the DRAM module are connected through 