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