summaryrefslogtreecommitdiff
path: root/aisa
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--aisa/aisa.cpp6
-rw-r--r--aisa/aisa.h20
-rw-r--r--aisa/async.h225
-rw-r--r--aisa/coroutine.h119
-rw-r--r--aisa/simple-models.cpp49
-rw-r--r--aisa/simple-models.h39
6 files changed, 63 insertions, 395 deletions
diff --git a/aisa/aisa.cpp b/aisa/aisa.cpp
index 811c882..8c8cd1e 100644
--- a/aisa/aisa.cpp
+++ b/aisa/aisa.cpp
@@ -6,6 +6,12 @@
6 6
7namespace aisa { 7namespace aisa {
8 8
9 ISA::~ISA() { }
10
11 Task::~Task() { }
12
13 Step::~Step() { }
14
9 std::optional<std::pair<std::unique_ptr<const Step>, regval_t>> Task::step(regval_t environment_val) const { return {}; } 15 std::optional<std::pair<std::unique_ptr<const Step>, regval_t>> Task::step(regval_t environment_val) const { return {}; }
10 16
11 MemInfo Step::meminfo(const Wires &wires) const { return {}; } 17 MemInfo Step::meminfo(const Wires &wires) const { return {}; }
diff --git a/aisa/aisa.h b/aisa/aisa.h
index e4e1074..a986cd7 100644
--- a/aisa/aisa.h
+++ b/aisa/aisa.h
@@ -17,7 +17,7 @@ namespace aisa {
17 struct Task; 17 struct Task;
18 18
19 struct ISA { 19 struct ISA {
20 virtual ~ISA() { } 20 virtual ~ISA();
21 21
22 virtual std::pair<std::unique_ptr<const Task>, regval_t> initial_task() const = 0; 22 virtual std::pair<std::unique_ptr<const Task>, regval_t> initial_task() const = 0;
23 }; 23 };
@@ -27,7 +27,7 @@ namespace aisa {
27 struct Task { 27 struct Task {
28 regnum_t environment; 28 regnum_t environment;
29 29
30 virtual ~Task() { } 30 virtual ~Task();
31 31
32 virtual std::string disasm() const = 0; 32 virtual std::string disasm() const = 0;
33 33
@@ -58,24 +58,10 @@ namespace aisa {
58 std::vector<regnum_t> source_regs; 58 std::vector<regnum_t> source_regs;
59 std::vector<regnum_t> destination_regs; 59 std::vector<regnum_t> destination_regs;
60 60
61 virtual ~Step() { } 61 virtual ~Step();
62 62
63 virtual std::string disasm(const Wires *w = nullptr) const = 0; 63 virtual std::string disasm(const Wires *w = nullptr) const = 0;
64 64
65 std::optional<regnum_t> predicate_reg() const
66 {
67 if (predicate.has_value())
68 return predicate->first;
69 return {};
70 }
71
72 std::optional<regnum_t> expected_predicate_val() const
73 {
74 if (predicate.has_value())
75 return predicate->second;
76 return {};
77 }
78
79 MOp mop = MOp::NONE; 65 MOp mop = MOp::NONE;
80 66
81 virtual MemInfo meminfo(const Wires &wires) const; 67 virtual MemInfo meminfo(const Wires &wires) const;
diff --git a/aisa/async.h b/aisa/async.h
deleted file mode 100644
index 42e99e7..0000000
--- a/aisa/async.h
+++ /dev/null
@@ -1,225 +0,0 @@
1#pragma once
2
3#include <coroutine>
4#include <optional>
5#include <utility>
6#include <memory>
7#include <vector>
8
9#include "aisa/aisa.h"
10#include "aisa/coroutine.h" // IWYU pragma: export
11
12namespace aisa {
13
14 template<typename CRTP> struct AsyncEval {
15 CRTP & crtp() noexcept { return static_cast<CRTP &>(*this); }
16
17 task<regval_t> async_load_reg(regnum_t rn)
18 {
19 while (true) {
20 if (auto rv = crtp().load_reg(rn); rv.has_value())
21 co_return *rv;
22 co_await std::suspend_always{};
23 }
24 }
25
26 task<void> async_store_reg(regnum_t rn, regval_t rv)
27 {
28 while (true) {
29 if (crtp().store_reg(rn, rv))
30 co_return;
31 co_await std::suspend_always{};
32 }
33 }
34
35 task<void> async_fetch_mem(byte_t *bytes, addr_t physical_addr, addr_t size)
36 {
37 while (true) {
38 if (crtp().fetch_mem(bytes, physical_addr, size))
39 co_return;
40 co_await std::suspend_always{};
41 }
42 }
43
44 task<void> async_store_mem(addr_t physical_addr, const byte_t *bytes, addr_t size)
45 {
46 while (true) {
47 if (crtp().store_mem(physical_addr, bytes, size))
48 co_return;
49 co_await std::suspend_always{};
50 }
51 }
52
53 task<bool> async_predicate(const Step &step)
54 {
55 if (step.predicate.has_value()) {
56 regval_t pval = co_await crtp().async_load_reg(step.predicate->first);
57 co_return pval == step.predicate->second;
58 }
59 co_return true;
60 }
61
62 task<void> async_load_source_registers(const Step &step, Wires &w)
63 {
64 w.source_vals.resize(step.source_regs.size());
65 for (unsigned int i = 0; i < step.source_regs.size(); ++i)
66 w.source_vals[i] = co_await crtp().async_load_reg(step.source_regs[i]);
67 }
68
69 task<void> async_load_source_memory(const Step &step, const MemInfo &mi, Wires &w)
70 {
71 w.memory_val.resize(mi.size);
72 co_await crtp().async_fetch_mem(w.memory_val.data(), mi.physical_addr, mi.size);
73 }
74
75 task<void> async_load_sources(const Step &step, Wires &w)
76 {
77 co_await crtp().async_load_source_registers(step, w);
78
79 if (step.mop == MOp::LOAD) {
80 auto mi = step.meminfo(w);
81 co_await crtp().async_load_source_memory(step, mi, w);
82 }
83 }
84
85 task<void> async_write_destination_registers(const Step &step, const Wires &w)
86 {
87 for (unsigned int i = 0; i < step.destination_regs.size(); ++i)
88 co_await crtp().async_store_reg(step.destination_regs[i], w.destination_vals[i]);
89 }
90
91 task<void> async_write_destination_memory(const Step &step, const MemInfo &mi, const Wires &w)
92 {
93 co_await crtp().async_store_mem(mi.physical_addr, w.memory_val.data(), mi.size);
94 }
95
96 task<void> async_write_destinations(const Step &step, const Wires &w)
97 {
98 if (w.aborted)
99 co_return;
100
101 co_await crtp().async_write_destination_registers(step, w);
102
103 if (step.mop == MOp::STORE) {
104 auto mi = step.meminfo(w);
105 co_await crtp().async_write_destination_memory(step, mi, w);
106 }
107 }
108
109 task<void> async_push_task(std::unique_ptr<const Task> &&task)
110 {
111 while (true) {
112 if (crtp().push_task(std::move(task)))
113 co_return;
114 co_await std::suspend_always{};
115 }
116 }
117
118 task<void> async_new_task(std::unique_ptr<const Task> &&task, regval_t environment_val)
119 {
120 auto rn = task->environment;
121 co_await crtp().async_push_task(std::move(task));
122 co_await crtp().async_store_reg(rn, environment_val);
123 }
124
125 task<Wires> async_run_step(const Step &step)
126 {
127 Wires w;
128
129 if (!co_await crtp().async_predicate(step))
130 co_return std::move(w);
131
132 co_await crtp().async_load_sources(step, w);
133
134 step.evaluate(w);
135
136 co_await crtp().async_write_destinations(step, w);
137
138 if (w.new_task.has_value())
139 co_await crtp().async_new_task(std::move(w.new_task->first), w.new_task->second);
140
141 co_return std::move(w);
142 }
143
144 task<const Task *> async_top_task()
145 {
146 while (true) {
147 if (auto rv = crtp().top_task(); rv.has_value())
148 co_return &**rv;
149 co_await std::suspend_always{};
150 }
151 }
152
153 task<void> async_pop_task()
154 {
155 while (true) {
156 if (crtp().pop_task())
157 co_return;
158 co_await std::suspend_always{};
159 }
160 }
161
162 task<std::optional<std::unique_ptr<const Step>>> async_fetch_step()
163 {
164 auto task = co_await crtp().async_top_task();
165
166 auto rn = task->environment;
167 auto rv = co_await crtp().async_load_reg(rn);
168
169 auto step = task->step(rv);
170 if (step.has_value()) {
171 co_await crtp().async_store_reg(rn, step->second);
172 co_return std::move(step->first);
173 } else {
174 co_await crtp().async_pop_task();
175 co_return {};
176 }
177 }
178
179 task<std::pair<std::unique_ptr<const Step>, Wires>> async_fetch_and_run_step()
180 {
181 while (true) {
182 if (auto step = co_await crtp().async_fetch_step(); step.has_value()) {
183 auto wires = co_await crtp().async_run_step(**step);
184 co_return {std::move(*step), std::move(wires)};
185 }
186 }
187 }
188
189 task<void> async_run_subtree()
190 {
191 while (true) {
192 if (auto step = co_await crtp().async_fetch_step(); step.has_value())
193 co_await crtp().async_run_step_and_subtree(**step);
194 else
195 break;
196 }
197 }
198
199 task<Wires> async_run_step_and_subtree(const Step &step)
200 {
201 auto w = co_await crtp().async_run_step(step);
202
203 if (w.new_task.has_value())
204 co_await crtp().async_run_subtree();
205
206 co_return std::move(w);
207 }
208
209 task<void> async_setup_initial_task(const ISA &isa)
210 {
211 auto task = isa.initial_task();
212
213 co_await crtp().async_new_task(std::move(task.first), task.second);
214 }
215
216 task<void> async_run(const ISA &isa)
217 {
218 co_await crtp().async_setup_initial_task(isa);
219
220 co_await crtp().async_run_subtree();
221 }
222
223 };
224
225}
diff --git a/aisa/coroutine.h b/aisa/coroutine.h
deleted file mode 100644
index 1b55362..0000000
--- a/aisa/coroutine.h
+++ /dev/null
@@ -1,119 +0,0 @@
1#pragma once
2
3#include <coroutine>
4#include <optional>
5
6namespace aisa {
7
8 template<typename result_t> struct task_promise;
9
10 template<typename result_t> struct task : public std::coroutine_handle<task_promise<result_t>> {
11 using handle = std::coroutine_handle<task_promise<result_t>>;
12 using promise_type = task_promise<result_t>;
13 bool await_ready() const noexcept { return handle::done(); }
14 result_t await_resume() const noexcept;
15 template<typename other_t> void await_suspend(std::coroutine_handle<task_promise<other_t>> h) const noexcept;
16 std::optional<result_t> operator()() noexcept;
17 };
18
19 template<> struct task<void> : public std::coroutine_handle<task_promise<void>> {
20 using handle = std::coroutine_handle<task_promise<void>>;
21 using promise_type = task_promise<void>;
22 bool await_ready() const noexcept { return handle::done(); }
23 void await_resume() const noexcept;
24 template<typename other_t> void await_suspend(std::coroutine_handle<task_promise<other_t>> h) const noexcept;
25 bool operator()() noexcept;
26 };
27
28 template<typename result_t> struct task_promise {
29 std::coroutine_handle<> precursor;
30 std::optional<result_t> result;
31 task_promise() = default;
32 task_promise(const task_promise &) = delete;
33 task<result_t> get_return_object() noexcept { return task<result_t>{std::coroutine_handle<task_promise<result_t>>::from_promise(*this)}; }
34 std::suspend_never initial_suspend() const noexcept { return {}; }
35 std::suspend_always final_suspend() const noexcept { return {}; }
36 void unhandled_exception() { }
37 void return_value(result_t x) noexcept { result = std::move(x); }
38 };
39
40 template<> struct task_promise<void> {
41 std::coroutine_handle<> precursor;
42 task_promise() = default;
43 task_promise(const task_promise &) = delete;
44 task<void> get_return_object() noexcept { return task<void>{std::coroutine_handle<task_promise<void>>::from_promise(*this)}; }
45 std::suspend_never initial_suspend() const noexcept { return {}; }
46 std::suspend_always final_suspend() const noexcept { return {}; }
47 void unhandled_exception() { }
48 void return_void() noexcept { }
49 };
50
51 template<typename result_t> result_t task<result_t>::await_resume() const noexcept
52 {
53 auto x = std::move(handle::promise().result.value());
54 handle::destroy();
55 return x;
56 }
57
58 template<typename result_t> template<typename other_t> void task<result_t>::await_suspend(std::coroutine_handle<task_promise<other_t>> h) const noexcept
59 {
60 h.promise().precursor = *this;
61 }
62
63 template<typename result_t> std::optional<result_t> task<result_t>::operator()() noexcept
64 {
65 if (!handle::operator bool())
66 return {};
67 if (!handle::done()) {
68 auto &precursor = handle::promise().precursor;
69 if (precursor) {
70 if (!precursor.done())
71 precursor.resume();
72 if (precursor.done())
73 precursor = nullptr;
74 }
75 if (!precursor)
76 handle::resume();
77 }
78 if (handle::done()) {
79 auto x = await_resume();
80 handle::operator=(nullptr);
81 return x;
82 }
83 return {};
84 }
85
86 inline void task<void>::await_resume() const noexcept
87 {
88 handle::destroy();
89 }
90
91 template<typename other_t> void task<void>::await_suspend(std::coroutine_handle<task_promise<other_t>> h) const noexcept
92 {
93 h.promise().precursor = *this;
94 }
95
96 inline bool task<void>::operator()() noexcept
97 {
98 if (!handle::operator bool())
99 return true;
100 if (!handle::done()) {
101 auto &precursor = handle::promise().precursor;
102 if (precursor) {
103 if (!precursor.done())
104 precursor.resume();
105 if (precursor.done())
106 precursor = nullptr;
107 }
108 if (!precursor)
109 handle::resume();
110 }
111 if (handle::done()) {
112 await_resume();
113 handle::operator=(nullptr);
114 return true;
115 }
116 return false;
117 }
118
119}
diff --git a/aisa/simple-models.cpp b/aisa/simple-models.cpp
new file mode 100644
index 0000000..b69dcb7
--- /dev/null
+++ b/aisa/simple-models.cpp
@@ -0,0 +1,49 @@
1#include <algorithm>
2#include <deque>
3#include <memory>
4#include <optional>
5#include <utility>
6#include <vector>
7
8#include "aisa/aisa.h"
9#include "aisa/simple-models.h"
10
11namespace aisa {
12
13 bool TaskStack::pop_task()
14 {
15 if (tasks.empty())
16 return false;
17 tasks.pop_back();
18 return true;
19 }
20
21 bool TaskStack::push_task(std::unique_ptr<const Task> &&task)
22 {
23 tasks.emplace_back(std::move(task));
24 return true;
25 }
26
27 std::optional<const Task *> TaskStack::top_task()
28 {
29 if (tasks.empty())
30 return {};
31 return tasks.back().get();
32 }
33
34 std::optional<regval_t> VectorRF::load_reg(regnum_t rn) const
35 {
36 if (rf.size() <= rn)
37 return {};
38 return rf[rn];
39 }
40
41 bool VectorRF::store_reg(regnum_t rn, regval_t rv)
42 {
43 if (rf.size() <= rn)
44 rf.resize(rn + 1);
45 rf[rn] = rv;
46 return true;
47 }
48
49}
diff --git a/aisa/simple-models.h b/aisa/simple-models.h
index 62b5388..a94f010 100644
--- a/aisa/simple-models.h
+++ b/aisa/simple-models.h
@@ -7,7 +7,6 @@
7#include <map> 7#include <map>
8#include <memory> 8#include <memory>
9#include <optional> 9#include <optional>
10#include <utility>
11#include <vector> 10#include <vector>
12 11
13#include "aisa/aisa.h" 12#include "aisa/aisa.h"
@@ -51,45 +50,17 @@ namespace aisa {
51 struct TaskStack { 50 struct TaskStack {
52 std::deque<std::unique_ptr<const Task>> tasks; 51 std::deque<std::unique_ptr<const Task>> tasks;
53 52
54 bool pop_task() 53 bool pop_task();
55 { 54 bool push_task(std::unique_ptr<const Task> &&task);
56 if (tasks.empty())
57 return false;
58 tasks.pop_back();
59 return true;
60 }
61
62 bool push_task(std::unique_ptr<const Task> &&task)
63 {
64 tasks.emplace_back(std::move(task));
65 return true;
66 }
67 55
68 std::optional<const Task *> top_task() 56 std::optional<const Task *> top_task();
69 {
70 if (tasks.empty())
71 return {};
72 return tasks.back().get();
73 }
74 }; 57 };
75 58
76 struct VectorRF { 59 struct VectorRF {
77 std::vector<std::optional<regval_t>> rf; 60 std::vector<std::optional<regval_t>> rf;
78 61
79 std::optional<regval_t> load_reg(regnum_t rn) const 62 std::optional<regval_t> load_reg(regnum_t rn) const;
80 { 63 bool store_reg(regnum_t rn, regval_t rv);
81 if (rf.size() <= rn)
82 return {};
83 return rf[rn];
84 }
85
86 bool store_reg(regnum_t rn, regval_t rv)
87 {
88 if (rf.size() <= rn)
89 rf.resize(rn + 1);
90 rf[rn] = rv;
91 return true;
92 }
93 }; 64 };
94 65
95} 66}