#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; } } }; }