summaryrefslogtreecommitdiff
path: root/uarch/core.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--uarch/core.cpp140
1 files changed, 140 insertions, 0 deletions
diff --git a/uarch/core.cpp b/uarch/core.cpp
new file mode 100644
index 0000000..34f422a
--- /dev/null
+++ b/uarch/core.cpp
@@ -0,0 +1,140 @@
1#include <fmt/format.h>
2#include <iostream>
3
4#include "uarch/core.h"
5
6fetch_stage::fetch_stage(core &c)
7 : c(c)
8 , pc(c.checker.pc)
9{ }
10
11decode_stage::decode_stage(core &c)
12 : c(c)
13 , acc(c.checker.acc)
14 , link(c.checker.link)
15 , mq(c.checker.mq)
16 , pc(c.checker.pc)
17 , ctlregs(c.checker.ctlregs)
18 , icount(c.checker.icount)
19{ }
20
21void fetch_stage::clock() {
22 if (c.fetch_restarto.has_value()) {
23 auto &r = *c.fetch_restarto;
24 pte(r.tr, "!");
25 gen = r.new_gen;
26 pc = r.new_pc;
27 didrestart = true;
28 c.fetch_restarto.reset();
29 }
30
31 if (c.fetch_bundlep.can_write()) {
32 fetch_bundle b;
33 b.tr = infra::pt::toplevel();
34 b.gen = gen;
35 b.pc = pc;
36 b.word = c.mem.fetch(pc);
37 if (didrestart)
38 infra::pt::event(b.tr, ">", now-1, "");
39 pte(b.tr, "F");
40 c.fetch_bundlep.write(std::move(b));
41 pc = (pc & 070000) | ((pc + 1) & 007777);
42 didrestart = false;
43 }
44}
45
46void decode_stage::clock() {
47 bool progress = ctlregs[HALTED];
48
49 if (!ctlregs[HALTED] && c.fetch_bundlep.can_read()) {
50 auto b = c.fetch_bundlep.read();
51
52 if (b.gen != gen)
53 goto bail_out;
54
55 if (b.pc != pc) {
56 pte(b.tr, "~");
57 fetch_restart r;
58 r.tr = b.tr;
59 r.new_gen = ++gen;
60 r.new_pc = pc;
61 c.fetch_restarto = std::move(r);
62 goto bail_out;
63 }
64
65 progress = true;
66
67 pte(b.tr, "E");
68
69 inst = decode(ctlregs[FLAGS],
70 pc,
71 c.mem.fetch(pc),
72 interrupt);
73 auto next_pc = inst.next_pc;
74
75 if (inst.need_indirect_load) {
76 auto addr = c.mem.fetch(inst.init_address.value());
77 if (inst.need_autoinc_store) {
78 addr = (addr + 1) & 07777;
79 c.mem.store(*inst.init_address, addr);
80 }
81 auto df = (ctlregs[FLAGS] & FLAG_DF) >> FLAG_DF_SHIFT;
82 inst.final_address = (df << 12) | addr;
83 } else {
84 assert(!inst.need_autoinc_store);
85 }
86
87 pte(b.tr, "", inst.disasm());
88
89 if (inst.need_exec_load)
90 inst.data = c.mem.fetch(inst.final_address.value());
91
92 if (inst.need_read_acc)
93 inst.acc = acc;
94 if (inst.need_read_link)
95 inst.link = link;
96 if (inst.need_read_mq)
97 inst.mq = mq;
98 if (inst.read_ctlreg.has_value())
99 inst.ctlval = ctlregs[*inst.read_ctlreg];
100
101 inst.execute();
102
103 if (inst.need_write_acc)
104 acc = inst.acc.value();
105 if (inst.need_write_link)
106 link = inst.link.value();
107 if (inst.need_write_mq)
108 mq = inst.mq.value();
109 if (inst.write_ctlreg.has_value())
110 ctlregs[*inst.write_ctlreg] = inst.ctlval.value();
111
112 if (inst.need_exec_store)
113 c.mem.store(inst.final_address.value(), inst.data.value());
114
115 assert(inst.next_pc == next_pc || inst.possibly_redirects);
116 pc = inst.next_pc;
117 }
118bail_out:
119
120 if (progress)
121 interrupt = c.system.interact(icount++, ctlregs);
122
123 if (c.checker.icount != icount) {
124 assert(c.checker.icount + 1 == icount);
125
126 c.checker.execute();
127 assert(c.checker.icount == icount);
128 std::cerr << fmt::format("icount={:} pc={:05o} checkerpc={:05o}\n", icount, pc, c.checker.pc);
129 assert(pc == c.checker.pc);
130 assert(acc == c.checker.acc);
131 assert(link == c.checker.link);
132 assert(mq == c.checker.mq);
133 assert(ctlregs == c.checker.ctlregs);
134 if (inst.init_address.has_value())
135 assert(c.mem.fetch(*inst.init_address) == c.checker.mem.fetch(*inst.init_address));
136 if (inst.final_address.has_value())
137 assert(c.mem.fetch(*inst.final_address) == c.checker.mem.fetch(*inst.final_address));
138 assert(c.mem.fetch(pc) == c.checker.mem.fetch(pc));
139 }
140}