summaryrefslogtreecommitdiff
path: root/memory
diff options
context:
space:
mode:
authorJulian Blake Kongslie2022-10-02 15:32:49 -0700
committerJulian Blake Kongslie2022-10-02 15:32:49 -0700
commit82cc71261d3d32012d33d3bebe56ca5e3b0bcdbd (patch)
treef1358a38d244e27d9740e914c54328d753cb0b4f /memory
downloadbiggolf-82cc71261d3d32012d33d3bebe56ca5e3b0bcdbd.tar.xz
Initial commit.
Diffstat (limited to '')
-rw-r--r--memory/dram.h96
-rw-r--r--memory/line.h15
2 files changed, 111 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
13namespace 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}
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 @@
1#pragma once
2
3#include <array>
4#include <cstdint>
5
6#include "infra/port.h"
7#include "infra/sim.h"
8
9namespace memory {
10 constexpr std::uint64_t LINE_BYTES_LOG2 = 4;
11 constexpr std::uint64_t LINE_BYTES = 1 << LINE_BYTES_LOG2;
12 constexpr std::uint64_t LINE_BYTE_OFFSET_MASK = LINE_BYTES - 1;
13
14 typedef std::array<std::uint8_t, LINE_BYTES> line;
15}