From db82579d3c023c441c895d26d32de3fa039eafa4 Mon Sep 17 00:00:00 2001 From: Julian Blake Kongslie Date: Fri, 11 Nov 2022 16:28:55 -0800 Subject: Starting to write a real memory subsystem for biggolf. --- memory/cache.h | 96 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 memory/cache.h (limited to 'memory/cache.h') diff --git a/memory/cache.h b/memory/cache.h new file mode 100644 index 0000000..8554910 --- /dev/null +++ b/memory/cache.h @@ -0,0 +1,96 @@ +#pragma once + +#include +#include + +#include "memory/dram.h" +#include "memory/line.h" + +namespace memory { + template struct inline_cache { + static constexpr std::uint64_t SETS = 1 << SETS_LOG2; + static constexpr std::uint64_t LINE_SET_OFFSET_MASK = SETS - 1; + + std::uint64_t last_serial = 0; + + struct tag { + std::uint64_t serial = 0; + std::uint64_t line_address; + infra::transaction transaction; + }; + + typedef std::array set_tags; + typedef std::array set_data; + + std::array tags; + std::array data; + + void handle_response(const dram::response &r) { + auto set_address = r.line_address & LINE_SET_OFFSET_MASK; + auto &stags = tags[set_address]; + auto &sdata = data[set_address]; + for (unsigned int i = 0; i < WAYS; ++i) { + auto &stag = stags[i]; + if (stag.serial && stag.line_address == r.line_address) { + handle_response(r, stag, sdata[i]); + return; + } + } + std::uint64_t min_serial = ~(std::uint64_t)0; + unsigned int victim; + for (unsigned int i = 0; i < WAYS; ++i) { + auto &stag = stags[i]; + if (stag.serial < min_serial) { + min_serial = stag.serial; + victim = i; + } + } + handle_response(r, stags[victim], sdata[victim]); + } + + void handle_response(const dram::response &r, tag &t, line &d) { + t.serial = ++last_serial; + t.line_address = r.line_address; + t.transaction = r.transaction; + d = r.data; + } + + std::optional probe(std::uint64_t address) { + auto line_address = address >> LINE_BYTES_LOG2; + auto set_address = line_address & LINE_SET_OFFSET_MASK; + auto &stags = tags[set_address]; + for (unsigned int i = 0; i < WAYS; ++i) { + auto &stag = stags[i]; + if (stag.serial && stag.line_address == line_address) + return stag; + } + return {}; + } + + std::optional fetchline(line &dst, std::uint64_t address) { + auto line_address = address >> LINE_BYTES_LOG2; + auto set_address = line_address & LINE_SET_OFFSET_MASK; + auto &stags = tags[set_address]; + auto &sdata = data[set_address]; + for (unsigned int i = 0; i < WAYS; ++i) { + auto &stag = stags[i]; + if (stag.serial && stag.line_address == line_address) { + stag.serial = ++last_serial; + dst = sdata[i]; + return stag; + } + } + return {}; + } + + std::optional fetch(unsigned int &dst, std::uint64_t address) { + line data; + if (auto tag = fetchline(data, address); tag.has_value()) { + auto line_offset = address & LINE_BYTE_OFFSET_MASK; + dst = data[line_offset]; + return tag; + } + return {}; + } + }; +} -- cgit v1.2.3