# IOb-Cache: A High-Performance Configurable Open-Source Cache
## 2 IOb-Cache
### Cache-Memory  
Cache-Memory is a module that contains the cache controller and memories. The available memories are the Tag, the Valid, the Data, the Write-Through-Buffer, and, if applicable, the Replacement-Policy memory (see Figure 2). The cache can be configured as direct-mapped or set-associative based on the number of ways given by parameter N_WAYS. There is one Tag memory per cache way. Each of these has tag-sized width, and depth equal to the total number of cache lines. The Tag memory has one clock-cycle read latency. The Valid memory is composed of an array of 1-bit registers (register-file), one for each way. Each array length equals the number of cache lines. This choice of implementation is a simple design choice to set its contents to zero during either a system reset or a cache-invalidate. The Data memory is implemented with one RAM for each way and (word) offset. Each RAM has a width FE_DATA_W (cache word-size) and a depth of \(2^{LINE\_OFF\_W}\) (number of cache lines). Since the write-strobe signal selects which bytes are stored, each RAM requires a write enable for each byte. The Write-Though Buffer is implemented using a synchronous FIFO [16]. It requires the data to be available on its output a clock cycle after being read. The input address signals are segmented as \(tag:index:offset\). The address is only used for the initial addressing (indexing) of the main memories: Valid, Tag, and Data. The stored address will be checked to see if a \"cache hit\" occurred to identify it within the cache line. Each of its bits indicates a hit in a separate way. The hit is the result of a tag match. If any bit of the \"data_wstrb_reg\" signal is enabled, it is a write-request; otherwise, it is a read-request. Figure 1: IOb-Cache top-level module diagram. If a read request produces a hit, the respective word is already available at the output of Data-Memory so that the request can be acknowledged. The Data memory allows input data from both the Front-End and the Back-End. This selection is made using the signal _replace_, which indicates if the replacement on a cache line is in action. When _replace_ is not asserted, all accesses are from the Front-End. During a read-miss, the signal _replace_ is asserted, which will start the Back-End Read-Channel controller, responsible for line-replacement. Both Tag and Valid memories are updated when the _replace_valid_ signal is high (read miss), forcing a hit in the selected way. Hence, the replacement process acts similarly to a regular write hit access. The replaced data (_read_data_) is validated (_read_valid_) and positioned in the cache line (_read_addr_). This process depends on the size of the line and the back-end word-size. The replacement can only start if there are currently no write transfers to the main-memory. The signals \"write_valid\" and \"write_ready\" constitute a handshaking pair for Cache-Memory to write to the Back-End Write-Channel. The former indicates that the Write-Through Buffer is not empty, validating the transfer. The latter indicates that the Back-End Write-Channel is idle and thus enables reading the Write-Through Buffer. The requirement that the replacement only starts after the write transfer is to avoid coherency issues.Write requests do not depend on the data being available in the cache, since it follows the write-not-allocate policy. Instead, it depends on the space available on the Writing-Through Buffer, which stores the address, write-data, and write-strobe array. During a write-hit, to avoid stalling, the Data memory uses the registered input signals to store the data so that the cache can receive a new request. If a read-access follows a write-access, Read-After Write (_RAW_) hazards can become an issue. The requested word may not be available at the memory output, since it was written just the cycle before. This word will only be available in the following clock-cycle, therefore the cache needs to stall. Stalling on every read-request that follows a write hit-access can become costly performance-wise.