diff options
| author | Julian Blake Kongslie | 2022-09-22 11:29:07 -0700 |
|---|---|---|
| committer | Julian Blake Kongslie | 2022-09-22 11:29:07 -0700 |
| commit | eb3fd68203fee7c63245c702914c2acd3332d65a (patch) | |
| tree | 7796707c0372e7fbe4a8bac70aad95f619e8ba29 /memory/dram.h | |
| download | procmodel-eb3fd68203fee7c63245c702914c2acd3332d65a.tar.xz | |
Initial commit.
Diffstat (limited to 'memory/dram.h')
| -rw-r--r-- | memory/dram.h | 96 |
1 files changed, 96 insertions, 0 deletions
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 @@ | |||
| 1 | #pragma once | ||
| 2 | |||
| 3 | #include <array> | ||
| 4 | #include <cstdint> | ||
| 5 | #include <cstring> | ||
| 6 | #include <istream> | ||
| 7 | #include <map> | ||
| 8 | #include <string> | ||
| 9 | #include <utility> | ||
| 10 | |||
| 11 | #include "memory/line.h" | ||
| 12 | |||
| 13 | namespace memory { | ||
| 14 | struct dram : public infra::sim { | ||
| 15 | static constexpr std::uint64_t PAGE_LINES_LOG2 = 20 - LINE_BYTES_LOG2; | ||
| 16 | static constexpr std::uint64_t PAGE_LINES = 1 << PAGE_LINES_LOG2; | ||
| 17 | static constexpr std::uint64_t PAGE_LINE_OFFSET_MASK = PAGE_LINES - 1; | ||
| 18 | static constexpr std::uint64_t PAGE_BYTES_LOG2 = PAGE_LINES_LOG2 + LINE_BYTES_LOG2; | ||
| 19 | static constexpr std::uint64_t PAGE_BYTES = 1 << PAGE_BYTES_LOG2; | ||
| 20 | static constexpr std::uint64_t PAGE_BYTE_OFFSET_MASK = PAGE_BYTES - 1; | ||
| 21 | |||
| 22 | typedef std::array<line, PAGE_LINES> page; | ||
| 23 | |||
| 24 | std::map<std::uint64_t, page> image; | ||
| 25 | |||
| 26 | struct response { | ||
| 27 | infra::transaction transaction; | ||
| 28 | std::uint64_t line_address; | ||
| 29 | line data; | ||
| 30 | }; | ||
| 31 | |||
| 32 | struct command { | ||
| 33 | infra::transaction transaction; | ||
| 34 | std::uint64_t line_address; | ||
| 35 | line data; | ||
| 36 | std::array<bool, LINE_BYTES> mask; | ||
| 37 | bool write = false; | ||
| 38 | infra::port<response> *responsep = nullptr; | ||
| 39 | }; | ||
| 40 | |||
| 41 | infra::port<command> commandp; | ||
| 42 | |||
| 43 | void clock() { | ||
| 44 | if (commandp.can_read()) { | ||
| 45 | const auto &c = commandp.peek(); | ||
| 46 | if (!c.responsep || c.responsep->can_write()) { | ||
| 47 | auto page_address = c.line_address >> PAGE_LINES_LOG2; | ||
| 48 | auto page_line = c.line_address & PAGE_LINE_OFFSET_MASK; | ||
| 49 | if (c.write) { | ||
| 50 | pte(c.transaction, "s", fmt::format("store {:x}-{:x}", page_address, page_line)); | ||
| 51 | if (c.responsep) { | ||
| 52 | response r; | ||
| 53 | r.transaction = c.transaction; | ||
| 54 | r.line_address = c.line_address; | ||
| 55 | r.data = c.data; | ||
| 56 | c.responsep->write(std::move(r)); | ||
| 57 | } | ||
| 58 | auto [p, emplaced] = image.try_emplace(page_address); | ||
| 59 | if (emplaced) | ||
| 60 | for (unsigned int i = 0; i < PAGE_LINES; ++i) | ||
| 61 | p->second[i].fill(0); | ||
| 62 | auto &l = p->second[page_line]; | ||
| 63 | for (unsigned int i = 0; i < LINE_BYTES; ++i) | ||
| 64 | if (c.mask[i]) | ||
| 65 | l[i] = c.data[i]; | ||
| 66 | } else { | ||
| 67 | pte(c.transaction, "f", fmt::format("fill {:x}-{:x}", page_address, page_line)); | ||
| 68 | if (c.responsep) { | ||
| 69 | response r; | ||
| 70 | r.transaction = c.transaction; | ||
| 71 | r.line_address = c.line_address; | ||
| 72 | if (auto p = image.find(page_address); p != image.end()) | ||
| 73 | r.data = p->second[page_line]; | ||
| 74 | else | ||
| 75 | r.data.fill(0); | ||
| 76 | c.responsep->write(std::move(r)); | ||
| 77 | } | ||
| 78 | } | ||
| 79 | commandp.discard(); | ||
| 80 | } | ||
| 81 | } | ||
| 82 | } | ||
| 83 | |||
| 84 | void load(std::istream &fh) { | ||
| 85 | for (unsigned int page = 0; ; ++page) { | ||
| 86 | auto [p, emplaced] = image.try_emplace(page); | ||
| 87 | if (emplaced) | ||
| 88 | for (unsigned int i = 0; i < PAGE_LINES; ++i) | ||
| 89 | p->second[i].fill(0); | ||
| 90 | for (unsigned int line = 0; line < PAGE_LINES; ++line) | ||
| 91 | if (!fh.read(reinterpret_cast<char *>(p->second[line].data()), LINE_BYTES)) | ||
| 92 | return; | ||
| 93 | } | ||
| 94 | } | ||
| 95 | }; | ||
| 96 | } | ||
