summaryrefslogtreecommitdiff
path: root/backend/exec.h
diff options
context:
space:
mode:
Diffstat (limited to 'backend/exec.h')
-rw-r--r--backend/exec.h72
1 files changed, 72 insertions, 0 deletions
diff --git a/backend/exec.h b/backend/exec.h
new file mode 100644
index 0000000..f1474b8
--- /dev/null
+++ b/backend/exec.h
@@ -0,0 +1,72 @@
1#pragma once
2
3#include "infra/port.h"
4#include "inst.h"
5#include "memory/dram.h"
6
7namespace backend {
8 struct exec : public infra::sim {
9 infra::port<inst> execp;
10 infra::port<inst> *writebackp = nullptr;
11 infra::port<memory::dram::command> *loadp = nullptr;
12 infra::port<memory::dram::response> loadresultp;
13
14 infra::port<inst> stallp;
15
16 void clock() {
17 if (stallp.can_read() && writebackp->can_write()) {
18 const auto &i = stallp.peek();
19 switch (i.field[OPCODE]) {
20 case OP_LOAD:
21 if (loadresultp.can_read()) {
22 auto i = stallp.read();
23 auto addr = i.field[SRC1] + i.field[SRC2];
24 auto offset = addr & memory::LINE_BYTE_OFFSET_MASK;
25 pte(i.transaction, "", fmt::format("addr={:x} offset={:x}", addr, offset));
26 auto f = loadresultp.read();
27 std::uint64_t r = 0;
28 for (unsigned int i = 0; i < sizeof(r); ++i)
29 r |= f.data[i + offset] << (8 * i);
30 i.result = r;
31 writebackp->write(std::move(i));
32 }
33 break;
34 }
35 } else if (execp.can_read() && writebackp->can_write() && loadp->can_write()) {
36 auto i = execp.read();
37 pte(i.transaction, "E", fmt::format("exec gen={} op={:x} a={:x} b={:x}", i.generation, i.field[OPCODE], i.field[SRC1], i.field[SRC2]));
38 switch (i.field[OPCODE]) {
39 case OP_JUMP_ABS_IF_ZERO:
40 if (i.field[SRC2] == 0)
41 i.result = i.field[SRC1];
42 else
43 i.result = i.linear_next_pc;
44 break;
45 case OP_JUMP_ABS_IF_NONZERO:
46 if (i.field[SRC2] != 0)
47 i.result = i.field[SRC1];
48 else
49 i.result = i.linear_next_pc;
50 break;
51 case OP_EMIT:
52 case OP_ADD:
53 i.result = i.field[SRC1] + i.field[SRC2];
54 break;
55 case OP_LOAD:
56 {
57 memory::dram::command c;
58 c.transaction = i.transaction;
59 c.line_address = (i.field[SRC1] + i.field[SRC2]) >> memory::LINE_BYTES_LOG2;
60 c.write = false;
61 c.responsep = &loadresultp;
62 loadp->write(std::move(c));
63 }
64 stallp.write(std::move(i));
65 break;
66 }
67 if (stallp.can_write())
68 writebackp->write(std::move(i));
69 }
70 }
71 };
72}