summaryrefslogtreecommitdiff
path: root/frontend/fetch.h
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/fetch.h')
-rw-r--r--frontend/fetch.h79
1 files changed, 79 insertions, 0 deletions
diff --git a/frontend/fetch.h b/frontend/fetch.h
new file mode 100644
index 0000000..0eaebd5
--- /dev/null
+++ b/frontend/fetch.h
@@ -0,0 +1,79 @@
1#pragma once
2
3#include <cassert>
4#include <cstdint>
5#include <cstring>
6#include <map>
7#include <optional>
8#include <utility>
9
10#include "frontend/bundle.h"
11#include "infra/pipetrace.h"
12#include "infra/sim.h"
13#include "memory/dram.h"
14
15namespace frontend {
16 struct fetch : public infra::sim {
17 struct restart {
18 unsigned int new_generation;
19 std::uint64_t previous_line_address;
20 std::uint64_t new_next_line_address;
21 };
22 infra::port<restart> restartp;
23
24 infra::port<memory::dram::command> *commandp = nullptr;
25 infra::port<memory::dram::response> responsep;
26
27 infra::port<bundle> *bundlep = nullptr;
28
29 unsigned int generation = 0;
30 std::uint64_t next_line_address = 0;
31
32 // FIXME make prediction table finite
33 std::map<std::uint64_t, std::uint64_t> predictor;
34
35 bool fill_request_sent = false;
36
37 void clock() {
38 if (restartp.can_read()) {
39 auto r = restartp.read();
40 generation = r.new_generation;
41 next_line_address = r.new_next_line_address;
42 fill_request_sent = false;
43 if (r.new_next_line_address == r.previous_line_address || r.new_next_line_address == r.previous_line_address + 1)
44 predictor.erase(r.previous_line_address);
45 else
46 predictor[r.previous_line_address] = r.new_next_line_address;
47 }
48 if (fill_request_sent && responsep.can_read() && bundlep->can_write()) {
49 auto r = responsep.read();
50 if (r.line_address == next_line_address) {
51 bundle b;
52 b.transaction = r.transaction;
53 b.generation = generation;
54 b.line_address = next_line_address;
55 if (auto p = predictor.find(next_line_address); p != predictor.end())
56 b.next_line_address = p->second;
57 else
58 b.next_line_address = next_line_address + 1;
59 next_line_address = b.next_line_address;
60 pte(b.transaction, "", fmt::format("next fetch line {:x}", next_line_address));
61 b.data = std::move(r.data);
62 bundlep->write(std::move(b));
63 fill_request_sent = false;
64 }
65 }
66 if (!fill_request_sent && commandp->can_write()) {
67 memory::dram::command c;
68 c.transaction = infra::pt::toplevel();
69 pte(c.transaction, "F", fmt::format("fetch gen={}", generation));
70 c.line_address = next_line_address;
71 c.responsep = &responsep;
72 commandp->write(std::move(c));
73 fill_request_sent = true;
74 }
75 if (!fill_request_sent)
76 responsep.discard();
77 }
78 };
79}