summaryrefslogtreecommitdiff
path: root/isa/fib/fib.h
diff options
context:
space:
mode:
authorJulian Blake Kongslie2022-06-26 16:24:13 -0700
committerJulian Blake Kongslie2022-06-26 16:24:13 -0700
commitbbaf58c9fd0f485266d86868dc35f1d2be3589cd (patch)
tree4ae2b78bad51e3aa10776707ed9048804f378487 /isa/fib/fib.h
parentUse a separate EvalContext structure for holding some state. (diff)
downloadissim-bbaf58c9fd0f485266d86868dc35f1d2be3589cd.tar.xz
Significant changes, and a working "ISA" that just computes fib(n).
Diffstat (limited to 'isa/fib/fib.h')
-rw-r--r--isa/fib/fib.h288
1 files changed, 288 insertions, 0 deletions
diff --git a/isa/fib/fib.h b/isa/fib/fib.h
new file mode 100644
index 0000000..13801c8
--- /dev/null
+++ b/isa/fib/fib.h
@@ -0,0 +1,288 @@
1#pragma once
2
3#include <fmt/core.h>
4#include <memory>
5#include <optional>
6#include <string>
7#include <utility>
8#include <vector>
9
10#include "aisa/aisa.h"
11
12namespace isa::fib {
13
14 namespace Reg {
15 enum {
16 ENV_TOP,
17 ENV_FIB,
18
19 AREG,
20 ATMP,
21
22 PC,
23
24 A,
25 B,
26 Q,
27 };
28
29 const char *disasm(aisa::regnum_t x)
30 {
31 switch (x) {
32 case ENV_TOP: return "ENV_TOP";
33 case ENV_FIB: return "ENV_FIB";
34 case AREG: return "AREG";
35 case ATMP: return "ATMP";
36 case PC: return "PC";
37 case A: return "A";
38 case B: return "B";
39 case Q: return "Q";
40 default: return "???";
41 }
42 }
43 }
44
45 struct StepAdd : public aisa::Step {
46 StepAdd(aisa::regnum_t q, aisa::regnum_t a, aisa::regnum_t b)
47 {
48 source_regs.resize(2);
49 source_regs[0] = a;
50 source_regs[1] = b;
51
52 destination_regs.resize(1);
53 destination_regs[0] = q;
54 }
55
56 std::string disasm(const aisa::Wires *w) const override
57 {
58 if (w)
59 return fmt::format("{}({}) <- {}({}) + {}({})", Reg::disasm(destination_regs[0]), w->destination_vals[0], Reg::disasm(source_regs[0]), w->source_vals[0], Reg::disasm(source_regs[1]), w->source_vals[1]);
60 return fmt::format("{} <- {} + {}", Reg::disasm(destination_regs[0]), Reg::disasm(source_regs[0]), Reg::disasm(source_regs[1]));
61 }
62
63 void evaluate(aisa::Wires &w) const override
64 {
65 w.destination_vals.resize(1);
66 w.destination_vals[0] = w.source_vals[0] + w.source_vals[1];
67 }
68 };
69
70 struct StepAddImmediate : public aisa::Step {
71 aisa::regval_t x;
72
73 StepAddImmediate(aisa::regnum_t q, aisa::regnum_t a, aisa::regval_t x)
74 :x(x)
75 {
76 source_regs.resize(1);
77 source_regs[0] = a;
78
79 destination_regs.resize(1);
80 destination_regs[0] = q;
81 }
82
83 std::string disasm(const aisa::Wires *w) const override
84 {
85 if (w)
86 return fmt::format("{}({}) <- {}({}) + {}", Reg::disasm(destination_regs[0]), w->destination_vals[0], Reg::disasm(source_regs[0]), w->source_vals[0], x);
87 return fmt::format("{} <- {} + {}", Reg::disasm(destination_regs[0]), Reg::disasm(source_regs[0]), x);
88 }
89
90 void evaluate(aisa::Wires &w) const override
91 {
92 w.destination_vals.resize(1);
93 w.destination_vals[0] = w.source_vals[0] + x;
94 }
95 };
96
97 template<unsigned int WORD> struct StepLoad : public aisa::Step {
98 StepLoad(aisa::regnum_t q, aisa::regnum_t a)
99 {
100 source_regs.resize(1);
101 source_regs[0] = a;
102
103 destination_regs.resize(1);
104 destination_regs[0] = q;
105
106 mop = aisa::MOp::LOAD;
107 }
108
109 std::string disasm(const aisa::Wires *w) const override
110 {
111 if (w)
112 return fmt::format("{}({}) <- [{}({})]", Reg::disasm(destination_regs[0]), w->destination_vals[0], Reg::disasm(source_regs[0]), w->source_vals[0]);
113 return fmt::format("{} <- [{}]", Reg::disasm(destination_regs[0]), Reg::disasm(source_regs[0]));
114 }
115
116 aisa::MemInfo meminfo(const aisa::Wires &w) const override
117 {
118 aisa::MemInfo mi;
119 mi.physical_addr = w.source_vals[0] * WORD;
120 mi.size = WORD;
121 return mi;
122 }
123
124 void evaluate(aisa::Wires &w) const override
125 {
126 w.destination_vals.resize(1);
127 auto &q = w.destination_vals[0];
128 q = 0;
129 for (unsigned int i = 0; i < WORD; ++i)
130 q |= static_cast<aisa::regval_t>(w.memory_val[i]) << (8 * i);
131 }
132 };
133
134 struct StepMove : public aisa::Step {
135 StepMove(aisa::regnum_t q, aisa::regnum_t a)
136 {
137 source_regs.resize(1);
138 source_regs[0] = a;
139
140 destination_regs.resize(1);
141 destination_regs[0] = q;
142 }
143
144 std::string disasm(const aisa::Wires *w) const override
145 {
146 if (w)
147 return fmt::format("{}({}) <- {}({})", Reg::disasm(destination_regs[0]), w->destination_vals[0], Reg::disasm(source_regs[0]), w->source_vals[0]);
148 return fmt::format("{} <- {}", Reg::disasm(destination_regs[0]), Reg::disasm(source_regs[0]));
149 }
150
151 void evaluate(aisa::Wires &w) const override
152 {
153 w.destination_vals = w.source_vals;
154 }
155 };
156
157 struct StepMoveImmediate : public aisa::Step {
158 aisa::regval_t x;
159
160 StepMoveImmediate(aisa::regnum_t q, aisa::regval_t x)
161 : x(x)
162 {
163 destination_regs.resize(1);
164 destination_regs[0] = q;
165 }
166
167 std::string disasm(const aisa::Wires *w) const override
168 {
169 if (w)
170 return fmt::format("{}({}) <- {}", Reg::disasm(destination_regs[0]), w->destination_vals[0], x);
171 return fmt::format("{} <- {}", Reg::disasm(destination_regs[0]), x);
172 }
173
174 void evaluate(aisa::Wires &w) const override
175 {
176 w.destination_vals.resize(1);
177 w.destination_vals[0] = x;
178 }
179 };
180
181 template<typename Subtask> struct StepSpawn : public aisa::Step {
182 void evaluate(aisa::Wires &w) const override
183 {
184 w.new_task = {std::make_unique<Subtask>(), 0};
185 }
186
187 std::string disasm(const aisa::Wires *w) const override
188 {
189 return fmt::format("spawn");
190 }
191 };
192
193 template<unsigned int WORD> struct StepStore : public aisa::Step {
194 StepStore(aisa::regnum_t a, aisa::regnum_t d)
195 {
196 source_regs.resize(2);
197 source_regs[0] = a;
198 source_regs[1] = d;
199
200 mop = aisa::MOp::STORE;
201 }
202
203 std::string disasm(const aisa::Wires *w) const override
204 {
205 if (w)
206 return fmt::format("[{}({})] <- {}({})", Reg::disasm(source_regs[0]), w->source_vals[0], Reg::disasm(source_regs[1]), w->source_vals[1]);
207 return fmt::format("[{}] <- {}", Reg::disasm(source_regs[0]), Reg::disasm(source_regs[1]));
208 }
209
210 aisa::MemInfo meminfo(const aisa::Wires &w) const override
211 {
212 aisa::MemInfo mi;
213 mi.physical_addr = w.source_vals[0] * WORD;
214 mi.size = WORD;
215 return mi;
216 }
217
218 void evaluate(aisa::Wires &w) const override
219 {
220 w.memory_val.resize(WORD);
221 for (unsigned int i = 0; i < WORD; ++i)
222 w.memory_val[i] = w.source_vals[1] >> (8 * i);
223 }
224 };
225
226 template<unsigned int WORD> struct TaskFib : public aisa::Task {
227 TaskFib()
228 {
229 environment = Reg::ENV_FIB;
230 }
231
232 std::string disasm() const override
233 {
234 return "fib";
235 }
236
237 std::optional<std::pair<std::unique_ptr<const aisa::Step>, aisa::regval_t>> step(aisa::regval_t env) const override
238 {
239 switch (env) {
240 case 0: return {{std::make_unique<StepLoad<WORD>>(Reg::A, Reg::PC), env+1}};
241 case 1: return {{std::make_unique<StepAddImmediate>(Reg::PC, Reg::PC, 1), env+1}};
242 case 2: return {{std::make_unique<StepLoad<WORD>>(Reg::B, Reg::PC), env+1}};
243 case 3: return {{std::make_unique<StepAddImmediate>(Reg::AREG, Reg::PC, 1), env+1}};
244 case 4: return {{std::make_unique<StepAdd>(Reg::Q, Reg::A, Reg::B), env+1}};
245 case 5: return {{std::make_unique<StepStore<WORD>>(Reg::AREG, Reg::Q), env+1}};
246 }
247
248 return {};
249 }
250 };
251
252 template<unsigned int WORD> struct TaskTop : public aisa::Task {
253 TaskTop()
254 {
255 environment = Reg::ENV_TOP;
256 }
257
258 std::string disasm() const override
259 {
260 return "top";
261 }
262
263 std::optional<std::pair<std::unique_ptr<const aisa::Step>, aisa::regval_t>> step(aisa::regval_t env) const override
264 {
265 switch (env) {
266 case 0: return {{std::make_unique<StepMoveImmediate>(Reg::PC, 0), env+1}};
267 case 1: return {{std::make_unique<StepMoveImmediate>(Reg::AREG, 0), env+1}};
268 case 2: return {{std::make_unique<StepMoveImmediate>(Reg::ATMP, 0), env+1}};
269 case 3: return {{std::make_unique<StepStore<WORD>>(Reg::AREG, Reg::ATMP), env+1}};
270 case 4: return {{std::make_unique<StepMoveImmediate>(Reg::AREG, 1), env+1}};
271 case 5: return {{std::make_unique<StepMoveImmediate>(Reg::ATMP, 1), env+1}};
272 case 6: return {{std::make_unique<StepStore<WORD>>(Reg::AREG, Reg::ATMP), env+1}};
273 case 7: return {{std::make_unique<StepSpawn<TaskFib<WORD>>>(), env}};
274 }
275
276 return {};
277 }
278 };
279
280 template<unsigned int WORD=1> struct Fib : public aisa::ISA {
281 std::pair<std::unique_ptr<const aisa::Task>, aisa::regval_t> initial_task() const override
282 {
283 auto t = std::make_unique<TaskTop<WORD>>();
284 return {std::move(t), 0};
285 }
286 };
287
288}