From eaef9348431ea331ecf118aefc21246dbcf2c998 Mon Sep 17 00:00:00 2001 From: Julian Blake Kongslie Date: Sat, 15 Oct 2022 14:03:28 -0700 Subject: Add memory implementation as well; reorg. --- memory/dram.h | 96 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ memory/line.h | 15 ++++++++++ 2 files changed, 111 insertions(+) create mode 100644 memory/dram.h create mode 100644 memory/line.h (limited to 'memory') diff --git a/memory/dram.h b/memory/dram.h new file mode 100644 index 0000000..f59c7a6 --- /dev/null +++ b/memory/dram.h @@ -0,0 +1,96 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include "memory/line.h" + +namespace memory { + struct dram : public infra::sim { + static constexpr std::uint64_t PAGE_LINES_LOG2 = 20 - LINE_BYTES_LOG2; + static constexpr std::uint64_t PAGE_LINES = 1 << PAGE_LINES_LOG2; + static constexpr std::uint64_t PAGE_LINE_OFFSET_MASK = PAGE_LINES - 1; + static constexpr std::uint64_t PAGE_BYTES_LOG2 = PAGE_LINES_LOG2 + LINE_BYTES_LOG2; + static constexpr std::uint64_t PAGE_BYTES = 1 << PAGE_BYTES_LOG2; + static constexpr std::uint64_t PAGE_BYTE_OFFSET_MASK = PAGE_BYTES - 1; + + typedef std::array page; + + std::map image; + + struct response { + infra::transaction transaction; + std::uint64_t line_address; + line data; + }; + + struct command { + infra::transaction transaction; + std::uint64_t line_address; + line data; + std::array mask; + bool write = false; + infra::port *responsep = nullptr; + }; + + infra::port commandp; + + void clock() { + if (commandp.can_read()) { + const auto &c = commandp.peek(); + if (!c.responsep || c.responsep->can_write()) { + auto page_address = c.line_address >> PAGE_LINES_LOG2; + auto page_line = c.line_address & PAGE_LINE_OFFSET_MASK; + if (c.write) { + pte(c.transaction, "s", fmt::format("store {:x}-{:x}", page_address, page_line)); + if (c.responsep) { + response r; + r.transaction = c.transaction; + r.line_address = c.line_address; + r.data = c.data; + c.responsep->write(std::move(r)); + } + auto [p, emplaced] = image.try_emplace(page_address); + if (emplaced) + for (unsigned int i = 0; i < PAGE_LINES; ++i) + p->second[i].fill(0); + auto &l = p->second[page_line]; + for (unsigned int i = 0; i < LINE_BYTES; ++i) + if (c.mask[i]) + l[i] = c.data[i]; + } else { + pte(c.transaction, "f", fmt::format("fill {:x}-{:x}", page_address, page_line)); + if (c.responsep) { + response r; + r.transaction = c.transaction; + r.line_address = c.line_address; + if (auto p = image.find(page_address); p != image.end()) + r.data = p->second[page_line]; + else + r.data.fill(0); + c.responsep->write(std::move(r)); + } + } + commandp.discard(); + } + } + } + + void load(std::istream &fh) { + for (unsigned int page = 0; ; ++page) { + auto [p, emplaced] = image.try_emplace(page); + if (emplaced) + for (unsigned int i = 0; i < PAGE_LINES; ++i) + p->second[i].fill(0); + for (unsigned int line = 0; line < PAGE_LINES; ++line) + if (!fh.read(reinterpret_cast(p->second[line].data()), LINE_BYTES)) + return; + } + } + }; +} diff --git a/memory/line.h b/memory/line.h new file mode 100644 index 0000000..3377ec8 --- /dev/null +++ b/memory/line.h @@ -0,0 +1,15 @@ +#pragma once + +#include +#include + +#include "infra/port.h" +#include "infra/sim.h" + +namespace memory { + constexpr std::uint64_t LINE_BYTES_LOG2 = 4; + constexpr std::uint64_t LINE_BYTES = 1 << LINE_BYTES_LOG2; + constexpr std::uint64_t LINE_BYTE_OFFSET_MASK = LINE_BYTES - 1; + + typedef std::array line; +} -- cgit v1.2.3