summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--BigGolf10
-rw-r--r--evts/quickfoobar.evt12
-rw-r--r--isa/decode.cpp4
m---------nanosim0
-rw-r--r--uarch/core.cpp348
-rw-r--r--uarch/core.h74
6 files changed, 353 insertions, 95 deletions
diff --git a/BigGolf b/BigGolf
index a358ed8..4e0e9d2 100644
--- a/BigGolf
+++ b/BigGolf
@@ -26,14 +26,16 @@ Memory transactions: Opcodes that do it: (second set is the indirect versi
26 26
27 27
28 28
29 ----------------->
30Fetch -> Decode -> Indir -> Exec
31
32
29┌─────┐ ┌──────┐ ┌────┐ 33┌─────┐ ┌──────┐ ┌────┐
30│Fetch├──────►│Decode│ ┌─►│Exec│ 34│Fetch├──────►│Decode│ ┌─►│Exec│
31└─────┘ └──────┘ │ └────┘ 35└─────┘ └──────┘ │ └────┘
32 36
33 next_pc ┌───init_indirect_load │ init_execution_store 37 next_pc ┌───init_indirect_load │ init_execution_store
34 │ init_execution_load───┤ retire 38 │ init_execution_load───┤ retire
35 │ init_execution_store │
36 │ retire │
37 │ rubberband_stall(1/2) │ 39 │ rubberband_stall(1/2) │
38 │ │ 40 │ │
39 │ ┌───────┐ │ 41 │ ┌───────┐ │
@@ -42,16 +44,12 @@ Memory transactions: Opcodes that do it: (second set is the indirect versi
42 44
43 ┌───init_autoinc_store │ 45 ┌───init_autoinc_store │
44 │ init_execution_load───┤ 46 │ init_execution_load───┤
45 │ init_execution_store │
46 │ retire │
47 │ │ 47 │ │
48 │ ┌─────┐ │ 48 │ ┌─────┐ │
49 └─►│Indir│ │ 49 └─►│Indir│ │
50 └─────┘ │ 50 └─────┘ │
51 51
52 init_execution_load───┘ 52 init_execution_load───┘
53 init_execution_store
54 retire
55 53
56 54
57 55
diff --git a/evts/quickfoobar.evt b/evts/quickfoobar.evt
new file mode 100644
index 0000000..a89f0d5
--- /dev/null
+++ b/evts/quickfoobar.evt
@@ -0,0 +1,12 @@
1+10
2$foo
3TT_BITS=0x0A01/0xFF01 # kbd in '\n'
4+100
5HALTED=1
6+1000
7HALTED=0
8+10
9$bar
10TT_BITS=0x0A01/0xFF01 # kbd in '\n'
11+100
12HALTED=1
diff --git a/isa/decode.cpp b/isa/decode.cpp
index 061fe5c..f0cdca8 100644
--- a/isa/decode.cpp
+++ b/isa/decode.cpp
@@ -92,7 +92,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
92 inst.next_pc = (pc & ~07777) | ((pc + 1) & 07777); 92 inst.next_pc = (pc & ~07777) | ((pc + 1) & 07777);
93 93
94 if (interrupt) { 94 if (interrupt) {
95 bits = 04000; 95 inst.bits = bits = 04000;
96 assert(df == 0); 96 assert(df == 0);
97 assert(ifb == 0); 97 assert(ifb == 0);
98 inst.next_pc = pc; 98 inst.next_pc = pc;
@@ -146,7 +146,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
146 case 4: // JMS jump subroutine 146 case 4: // JMS jump subroutine
147 inst.need_exec_store = true; 147 inst.need_exec_store = true;
148 inst.possibly_redirects = true; 148 inst.possibly_redirects = true;
149 inst.df = "JMS %a"; 149 inst.df = interrupt ? "<interrupt> JMS %a" : "JMS %a";
150 inst.ef = [ifb](auto &ctx) { 150 inst.ef = [ifb](auto &ctx) {
151 ctx.data = ctx.next_pc; 151 ctx.data = ctx.next_pc;
152 ctx.next_pc = (ifb << 12) | ((ctx.final_address.value() + 1) & 07777); 152 ctx.next_pc = (ifb << 12) | ((ctx.final_address.value() + 1) & 07777);
diff --git a/nanosim b/nanosim
Subproject db82579d3c023c441c895d26d32de3fa039eafa Subproject bab124c8c00053eebd24329b95f0554440a5004
diff --git a/uarch/core.cpp b/uarch/core.cpp
index 8b2db9b..12f8b5b 100644
--- a/uarch/core.cpp
+++ b/uarch/core.cpp
@@ -10,23 +10,30 @@ fetch_stage::fetch_stage(core &c)
10 10
11decode_stage::decode_stage(core &c) 11decode_stage::decode_stage(core &c)
12 : c(c) 12 : c(c)
13 , pc(c.checker.pc)
14 , icount(c.checker.icount)
15{ }
16
17indir_stage::indir_stage(core &c)
18 : c(c)
19{ }
20
21exec_stage::exec_stage(core &c)
22 : c(c)
13 , acc(c.checker.acc) 23 , acc(c.checker.acc)
14 , link(c.checker.link) 24 , link(c.checker.link)
15 , mq(c.checker.mq) 25 , mq(c.checker.mq)
16 , pc(c.checker.pc) 26 , pc(c.checker.pc)
17 , ctlregs(c.checker.ctlregs) 27 , ctlregs(c.checker.ctlregs)
18 , icount(c.checker.icount)
19{ } 28{ }
20 29
21void fetch_stage::clock() { 30void fetch_stage::clock() {
22 if (c.fetch_restarto.has_value()) { 31 if (c.restarto.has_value()) {
23 auto &r = *c.fetch_restarto; 32 auto &r = *c.restarto;
24 pte(r.tr, "!"); 33 pte(r.tr, "!", fmt::format("newpc={:05o}", r.new_pc));
25 gen = r.new_gen;
26 pc = r.new_pc; 34 pc = r.new_pc;
27 didrestart = true; 35 didrestart = true;
28 outstandingfill = false; 36 outstandingfill = false;
29 c.fetch_restarto.reset();
30 } 37 }
31 38
32 if (c.fetch_mem_responsep.can_read()) { 39 if (c.fetch_mem_responsep.can_read()) {
@@ -38,11 +45,11 @@ void fetch_stage::clock() {
38 fetch_bundle b; 45 fetch_bundle b;
39 if (auto t = cache.fetchline(b.data, pc); t.has_value()) { 46 if (auto t = cache.fetchline(b.data, pc); t.has_value()) {
40 b.tr = infra::pt::toplevel(); 47 b.tr = infra::pt::toplevel();
41 b.gen = gen; 48 b.gen = c.gen;
42 b.pc = pc; 49 b.pc = pc;
43 if (didrestart) 50 if (didrestart)
44 infra::pt::event(b.tr, ">", now-1, ""); 51 infra::pt::event(b.tr, ">", now-1, "");
45 pte(b.tr, "F", fmt::format("pc={:05o}", b.pc)); 52 pte(b.tr, "F");
46 c.fetch_bundlep.write(std::move(b)); 53 c.fetch_bundlep.write(std::move(b));
47 pc = (pc & 070000) | (((pc & ~memory::LINE_BYTE_OFFSET_MASK) + memory::LINE_BYTES) & 007777); 54 pc = (pc & 070000) | (((pc & ~memory::LINE_BYTE_OFFSET_MASK) + memory::LINE_BYTES) & 007777);
48 didrestart = false; 55 didrestart = false;
@@ -50,114 +57,309 @@ void fetch_stage::clock() {
50 } 57 }
51 } 58 }
52 59
53 if (!outstandingfill && c./*fetch_*/mem_commandp.can_write() && !cache.probe(pc)) { 60 if (!outstandingfill && c.fetch_mem_commandp.can_write() && !cache.probe(pc)) {
54 memory::dram::command fr; 61 memory::dram::command fr;
55 fr.transaction = infra::pt::toplevel(); 62 fr.transaction = infra::pt::toplevel();
63 pte(fr.transaction, "p", fmt::format("fpc={:05o}", pc));
56 fr.line_address = pc >> memory::LINE_BYTES_LOG2; 64 fr.line_address = pc >> memory::LINE_BYTES_LOG2;
57 fr.responsep = &c.fetch_mem_responsep; 65 fr.responsep = &c.fetch_mem_responsep;
58 c./*fetch_*/mem_commandp.write(std::move(fr)); 66 c.fetch_mem_commandp.write(std::move(fr));
59 outstandingfill = true; 67 outstandingfill = true;
60 } 68 }
61} 69}
62 70
63void decode_stage::clock() { 71void decode_stage::clock() {
64 bool progress = ctlregs[HALTED]; 72 if (c.restarto.has_value()) {
73 auto &r = *c.restarto;
74 pc = r.new_pc;
75 interrupt |= r.interrupt;
76 icount = c.icount;
77 }
65 78
66 if (!ctlregs[HALTED] && c.fetch_bundlep.can_read()) { 79 if (c.fetch_bundlep.can_read() && c.decode_mem_commandp.can_write() && c.indir_instp.can_write() && c.decode_to_exec_instp.can_write()) {
67 auto b = c.fetch_bundlep.peek(); 80 auto b = c.fetch_bundlep.peek();
68 81
69 if (b.gen != gen) 82 if (b.gen != c.gen) {
70 goto bail_out; 83 pte(b.tr, "~");
84 c.fetch_bundlep.discard();
85 return;
86 }
71 87
72 if ((b.pc >> memory::LINE_BYTES_LOG2) != (pc >> memory::LINE_BYTES_LOG2)) { 88 if ((b.pc >> memory::LINE_BYTES_LOG2) != (pc >> memory::LINE_BYTES_LOG2)) {
89 if (!c.restarto.has_value()) {
90 restart r;
91 r.tr = b.tr;
92 r.new_pc = pc;
93 r.interrupt = false;
94 ++c.gen;
95 c.restarto = std::move(r);
96 }
73 pte(b.tr, "~"); 97 pte(b.tr, "~");
74 fetch_restart r;
75 r.tr = b.tr;
76 r.new_gen = ++gen;
77 r.new_pc = pc;
78 c.fetch_restarto = std::move(r);
79 c.fetch_bundlep.discard(); 98 c.fetch_bundlep.discard();
80 goto bail_out; 99 return;
81 } 100 }
82 101
83 progress = true; 102 inst_bundle i;
84 103
85 auto tr = infra::pt::child(b.tr); 104 i.tr = infra::pt::child(b.tr);
105 i.gen = c.gen;
106 i.pc = pc;
107 i.icount = icount++;
86 108
87 pte(tr, "E"); 109 pte(i.tr, "D");
88 110
89 inst = decode(ctlregs[FLAGS], 111 i.inst = decode(c.exec.ctlregs[FLAGS],
90 pc, 112 pc,
91 b.data[pc & memory::LINE_BYTE_OFFSET_MASK], 113 b.data[pc & memory::LINE_BYTE_OFFSET_MASK],
92 interrupt); 114 interrupt);
93 auto next_pc = inst.next_pc; 115 interrupt = false;
116
117 pte(i.tr, "", fmt::format("{:05o}: {}", pc, i.inst.disasm()));
118
119 pc = i.inst.next_pc;
120
121 if (i.inst.need_indirect_load) {
122 memory::dram::command fr;
123 fr.transaction = i.tr;
124 fr.line_address = *i.inst.init_address >> memory::LINE_BYTES_LOG2;
125 fr.responsep = &c.indir_mem_responsep;
126 pte(i.tr, "", fmt::format("iload={:05o}", *i.inst.init_address));
127 c.decode_mem_commandp.write(std::move(fr));
128 c.indir_instp.write(std::move(i));
129 } else {
130 if (i.inst.need_exec_load) {
131 memory::dram::command fr;
132 fr.transaction = i.tr;
133 fr.line_address = *i.inst.final_address >> memory::LINE_BYTES_LOG2;
134 fr.responsep = &c.exec_mem_responsep;
135 pte(i.tr, "", fmt::format("load={:05o}", *i.inst.final_address));
136 c.decode_mem_commandp.write(std::move(fr));
137 }
138 c.decode_to_exec_instp.write(std::move(i));
139 }
140
141 if ((b.pc >> memory::LINE_BYTES_LOG2) != (pc >> memory::LINE_BYTES_LOG2)) {
142 pte(b.tr, "~");
143 c.fetch_bundlep.discard();
144 }
145 }
146}
147
148void indir_stage::clock() {
149 if (c.restarto.has_value()) {
150 gen = c.gen;
151 }
152
153 if (c.indir_instp.can_read() && c.indir_mem_load_commandp.can_write() && c.indir_mem_store_commandp.can_write() && c.indir_to_exec_instp.can_write()) {
154 auto &i = c.indir_instp.peek();
155
156 if (i.gen != gen && i.gen != c.gen) {
157 pte(i.tr, "~");
158 c.indir_instp.discard();
159 return;
160 } else if (i.gen != gen) {
161 gen = c.gen;
162 assert(i.gen == gen);
163 }
94 164
95 if (inst.need_indirect_load) { 165 if (i.inst.need_indirect_load && !c.indir_mem_responsep.can_read())
96 auto addr = c.mem.fetch(inst.init_address.value()); 166 return;
97 if (inst.need_autoinc_store) { 167
168 if (i.inst.need_indirect_load) {
169 auto l = c.indir_mem_responsep.read();
170 if (l.line_address != i.inst.init_address.value() >> memory::LINE_BYTES_LOG2)
171 return;
172 auto addr = l.data[*i.inst.init_address & memory::LINE_BYTE_OFFSET_MASK];
173 if (i.inst.need_autoinc_store) {
98 addr = (addr + 1) & 07777; 174 addr = (addr + 1) & 07777;
99 c.mem.store(*inst.init_address, addr); 175 pte(i.tr, "+", fmt::format("istore={:05o} istoredata={:04o}", *i.inst.init_address, addr));
176 memory::dram::command sr;
177 sr.transaction = i.tr;
178 sr.line_address = *i.inst.init_address >> memory::LINE_BYTES_LOG2;
179 sr.data[*i.inst.init_address & memory::LINE_BYTE_OFFSET_MASK] = addr;
180 sr.mask.fill(false);
181 sr.mask[*i.inst.init_address & memory::LINE_BYTE_OFFSET_MASK] = true;
182 sr.write = true;
183 c.indir_mem_store_commandp.write(std::move(sr));
184 } else {
185 pte(i.tr, "I");
100 } 186 }
101 auto df = (ctlregs[FLAGS] & FLAG_DF) >> FLAG_DF_SHIFT; 187 auto df = (c.exec.ctlregs[FLAGS] & FLAG_DF) >> FLAG_DF_SHIFT;
102 inst.final_address = (df << 12) | addr; 188 i.inst.final_address = (unsigned int)((df << 12) | addr);
103 } else {
104 assert(!inst.need_autoinc_store);
105 } 189 }
106 190
107 pte(tr, "", inst.disasm()); 191 if (i.inst.need_exec_load) {
192 memory::dram::command fr;
193 fr.transaction = i.tr;
194 fr.line_address = *i.inst.final_address >> memory::LINE_BYTES_LOG2;
195 fr.responsep = &c.exec_mem_responsep;
196 pte(i.tr, "", fmt::format("load={:05o}", *i.inst.final_address));
197 c.indir_mem_load_commandp.write(std::move(fr));
198 }
108 199
109 if (inst.need_exec_load) 200 c.indir_to_exec_instp.write(std::move(i));
110 inst.data = c.mem.fetch(inst.final_address.value());
111 201
112 if (inst.need_read_acc) 202 c.indir_instp.discard();
113 inst.acc = acc; 203 }
114 if (inst.need_read_link) 204}
115 inst.link = link; 205
116 if (inst.need_read_mq) 206void exec_stage::clock() {
117 inst.mq = mq; 207 c.restarto.reset();
118 if (inst.read_ctlreg.has_value()) 208
119 inst.ctlval = ctlregs[*inst.read_ctlreg]; 209 std::optional<infra::transaction> restarttr;
210
211 bool progress = ctlregs[HALTED];
120 212
121 inst.execute(); 213 if (!ctlregs[HALTED] && (c.decode_to_exec_instp.can_read() || c.indir_to_exec_instp.can_read()) && c.exec_mem_commandp.can_write()) {
214 infra::port<inst_bundle> *instp = nullptr;
215 if (c.decode_to_exec_instp.can_read()) {
216 auto &i = c.decode_to_exec_instp.peek();
217 if (i.gen != gen && i.gen != c.gen) {
218 pte(i.tr, "~");
219 if (i.inst.need_autoinc_store) {
220 auto addr = (*i.inst.final_address - 1) & 07777;
221 pte(i.tr, "", fmt::format("unstore={:05o}, unstoredata={:04o}", *i.inst.init_address, addr));
222 memory::dram::command sr;
223 sr.transaction = i.tr;
224 sr.line_address = *i.inst.init_address >> memory::LINE_BYTES_LOG2;
225 sr.data[*i.inst.init_address & memory::LINE_BYTE_OFFSET_MASK] = addr;
226 sr.mask.fill(false);
227 sr.mask[*i.inst.init_address & memory::LINE_BYTE_OFFSET_MASK] = true;
228 sr.write = true;
229 c.exec_mem_commandp.write(std::move(sr));
230 }
231 c.decode_to_exec_instp.discard();
232 } else if (i.icount == c.icount) {
233 instp = &c.decode_to_exec_instp;
234 }
235 }
236 if (c.indir_to_exec_instp.can_read()) {
237 auto &i = c.indir_to_exec_instp.peek();
238 if (i.gen != gen && i.gen != c.gen) {
239 pte(i.tr, "~");
240 if (i.inst.need_autoinc_store) {
241 auto addr = (*i.inst.final_address - 1) & 07777;
242 pte(i.tr, "", fmt::format("unstore={:05o}, unstoredata={:04o}", *i.inst.init_address, addr));
243 memory::dram::command sr;
244 sr.transaction = i.tr;
245 sr.line_address = *i.inst.init_address >> memory::LINE_BYTES_LOG2;
246 sr.data[*i.inst.init_address & memory::LINE_BYTE_OFFSET_MASK] = addr;
247 sr.mask.fill(false);
248 sr.mask[*i.inst.init_address & memory::LINE_BYTE_OFFSET_MASK] = true;
249 sr.write = true;
250 c.exec_mem_commandp.write(std::move(sr));
251 }
252 c.indir_to_exec_instp.discard();
253 } else if (i.icount == c.icount) {
254 instp = &c.indir_to_exec_instp;
255 }
256 }
257 if (!instp)
258 goto bail_out;
259 if (!c.exec_mem_commandp.can_write())
260 goto bail_out;
261 auto &i = instp->peek();
122 262
123 if (inst.need_write_acc) 263 assert(i.gen == gen || i.gen == c.gen);
124 acc = inst.acc.value(); 264 if (i.gen != gen) {
125 if (inst.need_write_link) 265 gen = c.gen;
126 link = inst.link.value(); 266 assert(i.gen == gen);
127 if (inst.need_write_mq) 267 }
128 mq = inst.mq.value();
129 if (inst.write_ctlreg.has_value())
130 ctlregs[*inst.write_ctlreg] = inst.ctlval.value();
131 268
132 if (inst.need_exec_store) 269 if (i.inst.need_exec_load && !c.exec_mem_responsep.can_read())
133 c.mem.store(inst.final_address.value(), inst.data.value()); 270 return;
134 271
135 assert(inst.next_pc == next_pc || inst.possibly_redirects); 272 if (i.inst.need_exec_load) {
136 pc = inst.next_pc; 273 auto l = c.exec_mem_responsep.read();
274 if (l.line_address != i.inst.final_address.value() >> memory::LINE_BYTES_LOG2)
275 return;
276 i.inst.data = l.data[*i.inst.final_address & memory::LINE_BYTE_OFFSET_MASK];
277 pte(i.tr, "", fmt::format("loaddata={:04o}", *i.inst.data));
278 }
137 279
138 if ((b.pc >> memory::LINE_BYTES_LOG2) != (pc >> memory::LINE_BYTES_LOG2)) 280 pte(i.tr, "E");
139 c.fetch_bundlep.discard(); 281 progress = true;
282
283 assert(i.pc == pc);
284
285 auto next_pc = i.inst.next_pc;
286
287 if (i.inst.need_read_acc)
288 i.inst.acc = acc;
289 if (i.inst.need_read_link)
290 i.inst.link = link;
291 if (i.inst.need_read_mq)
292 i.inst.mq = mq;
293 if (i.inst.read_ctlreg.has_value())
294 i.inst.ctlval = ctlregs[*i.inst.read_ctlreg];
295
296 i.inst.execute();
297
298 if (i.inst.need_write_acc)
299 acc = i.inst.acc.value();
300 if (i.inst.need_write_link)
301 link = i.inst.link.value();
302 if (i.inst.need_write_mq)
303 mq = i.inst.mq.value();
304 if (i.inst.write_ctlreg.has_value()) {
305 ctlregs[*i.inst.write_ctlreg] = i.inst.ctlval.value();
306 restarttr = i.tr;
307 }
308
309 if (i.inst.need_exec_store) {
310 pte(i.tr, "", fmt::format("store={:05o} storedata={:04o}", *i.inst.final_address, *i.inst.data));
311 memory::dram::command sr;
312 sr.transaction = i.tr;
313 sr.line_address = *i.inst.final_address >> memory::LINE_BYTES_LOG2;
314 sr.data[*i.inst.final_address & memory::LINE_BYTE_OFFSET_MASK] = *i.inst.data;
315 sr.mask.fill(false);
316 sr.mask[*i.inst.final_address & memory::LINE_BYTE_OFFSET_MASK] = true;
317 sr.write = true;
318 c.exec_mem_commandp.write(std::move(sr));
319 }
320
321 assert(i.inst.next_pc == next_pc || i.inst.possibly_redirects);
322 pc = i.inst.next_pc;
323
324 if (pc != next_pc) {
325 pte(i.tr, "", fmt::format("jump={:05o}", pc));
326 restarttr = i.tr;
327 }
328
329 instp->discard();
140 } 330 }
331
141bail_out: 332bail_out:
333 bool interrupt = false;
142 334
143 if (progress) 335 if (progress) {
144 interrupt = c.system.interact(icount++, ctlregs); 336 auto oldctlregs = ctlregs;
337 interrupt = c.system.interact(c.icount++, ctlregs);
338 if (interrupt || oldctlregs != ctlregs)
339 if (!restarttr.has_value())
340 restarttr = infra::pt::toplevel();
341 }
342
343 if (restarttr.has_value()) {
344 restart r;
345 r.tr = *restarttr;
346 r.new_pc = pc;
347 r.interrupt = interrupt;
348 gen = ++c.gen;
349 c.restarto = std::move(r);
350 }
145 351
146 if (c.checker.icount != icount) { 352 if (c.checker.icount != c.icount) {
147 assert(c.checker.icount + 1 == icount); 353 assert(c.checker.icount + 1 == c.icount);
148 354
149 c.checker.execute(); 355 c.checker.execute();
150 assert(c.checker.icount == icount); 356 assert(c.checker.icount == c.icount);
151// std::cerr << fmt::format("icount={:} pc={:05o} checkerpc={:05o}\n", icount, pc, c.checker.pc); 357// std::cerr << fmt::format("icount={:} pc={:05o} checkerpc={:05o}\n", c.icount, pc, c.checker.pc);
152 assert(pc == c.checker.pc); 358 assert(pc == c.checker.pc);
153 assert(acc == c.checker.acc); 359 assert(acc == c.checker.acc);
154 assert(link == c.checker.link); 360 assert(link == c.checker.link);
155 assert(mq == c.checker.mq); 361 assert(mq == c.checker.mq);
156 assert(ctlregs == c.checker.ctlregs); 362 assert(ctlregs == c.checker.ctlregs);
157 if (inst.init_address.has_value())
158 assert(c.mem.fetch(*inst.init_address) == c.checker.mem.fetch(*inst.init_address));
159 if (inst.final_address.has_value())
160 assert(c.mem.fetch(*inst.final_address) == c.checker.mem.fetch(*inst.final_address));
161 assert(c.mem.fetch(pc) == c.checker.mem.fetch(pc));
162 } 363 }
364
163} 365}
diff --git a/uarch/core.h b/uarch/core.h
index a6772f3..b53a205 100644
--- a/uarch/core.h
+++ b/uarch/core.h
@@ -13,6 +13,12 @@
13 13
14struct core; 14struct core;
15 15
16struct restart {
17 infra::transaction tr;
18 unsigned int new_pc;
19 bool interrupt;
20};
21
16struct fetch_bundle { 22struct fetch_bundle {
17 infra::transaction tr; 23 infra::transaction tr;
18 unsigned int gen; 24 unsigned int gen;
@@ -20,10 +26,12 @@ struct fetch_bundle {
20 memory::line data; 26 memory::line data;
21}; 27};
22 28
23struct fetch_restart { 29struct inst_bundle {
24 infra::transaction tr; 30 infra::transaction tr;
25 unsigned int new_gen; 31 unsigned int gen;
26 unsigned int new_pc; 32 unsigned int pc;
33 std::uint64_t icount;
34 instruction_context inst;
27}; 35};
28 36
29struct fetch_stage : public infra::sim { 37struct fetch_stage : public infra::sim {
@@ -31,8 +39,8 @@ struct fetch_stage : public infra::sim {
31 39
32 memory::inline_cache<8, 2> cache; 40 memory::inline_cache<8, 2> cache;
33 41
34 unsigned int gen = 0;
35 unsigned int pc; 42 unsigned int pc;
43
36 bool didrestart = false; 44 bool didrestart = false;
37 bool outstandingfill = false; 45 bool outstandingfill = false;
38 46
@@ -44,20 +52,38 @@ struct fetch_stage : public infra::sim {
44struct decode_stage : public infra::sim { 52struct decode_stage : public infra::sim {
45 core &c; 53 core &c;
46 54
55 bool interrupt = false;
56
57 unsigned int pc;
58 std::uint64_t icount;
59
60 decode_stage(core &c);
61
62 void clock();
63};
64
65struct indir_stage : public infra::sim {
66 core &c;
67
47 unsigned int gen = 0; 68 unsigned int gen = 0;
48 69
49 bool interrupt = false; 70 indir_stage(core &c);
71
72 void clock();
73};
74
75struct exec_stage : public infra::sim {
76 core &c;
77
78 unsigned int gen = 0;
50 79
51 unsigned int acc; 80 unsigned int acc;
52 unsigned int link; 81 unsigned int link;
53 unsigned int mq; 82 unsigned int mq;
54 unsigned int pc; 83 unsigned int pc;
55 std::array<uint_fast32_t, NUM_CTLREGS> ctlregs; 84 std::array<uint_fast32_t, NUM_CTLREGS> ctlregs;
56 std::uint64_t icount;
57 instruction_context inst;
58 bool outstandingfill = false;
59 85
60 decode_stage(core &c); 86 exec_stage(core &c);
61 87
62 void clock(); 88 void clock();
63}; 89};
@@ -66,30 +92,50 @@ struct core {
66 iomodel &system; 92 iomodel &system;
67 funcchecker checker; 93 funcchecker checker;
68 94
69 memory::dram mem{12}; 95 std::optional<restart> restarto;
96 unsigned int gen = 0;
97
98 std::uint64_t icount;
99
100 memory::dram mem{0};
70 infra::port<memory::dram::command> mem_commandp; 101 infra::port<memory::dram::command> mem_commandp;
71 102
72 infra::priority_arbiter<memory::dram::command, 2> mem_command_arb; 103 infra::priority_arbiter<memory::dram::command, 5> mem_command_arb;
73 104
74 infra::port<memory::dram::command> fetch_mem_commandp; 105 infra::port<memory::dram::command> fetch_mem_commandp;
75 infra::port<memory::dram::response> fetch_mem_responsep; 106 infra::port<memory::dram::response> fetch_mem_responsep;
76 infra::port<fetch_bundle> fetch_bundlep; 107 infra::port<fetch_bundle> fetch_bundlep;
77 std::optional<fetch_restart> fetch_restarto;
78 108
79 infra::port<memory::dram::command> decode_mem_commandp; 109 infra::port<memory::dram::command> decode_mem_commandp;
80 infra::port<memory::dram::response> decode_mem_responsep; 110 infra::port<memory::dram::response> decode_mem_responsep;
111 infra::port<inst_bundle> decode_to_exec_instp;
112
113 infra::port<inst_bundle> indir_instp;
114 infra::port<memory::dram::command> indir_mem_load_commandp;
115 infra::port<memory::dram::command> indir_mem_store_commandp;
116 infra::port<memory::dram::response> indir_mem_responsep;
117 infra::port<inst_bundle> indir_to_exec_instp;
118
119 infra::port<memory::dram::command> exec_mem_commandp;
120 infra::port<memory::dram::response> exec_mem_responsep;
81 121
82 // Construction order is execution order within a cycle, so this list should be back-to-front (for zero-cycle restarts) 122 // Construction order is execution order within a cycle, so this list should be back-to-front (for zero-cycle restarts)
123 exec_stage exec{*this};
124 indir_stage indir{*this};
83 decode_stage decode{*this}; 125 decode_stage decode{*this};
84 fetch_stage fetch{*this}; 126 fetch_stage fetch{*this};
85 127
86 core(iomodel &model) 128 core(iomodel &model)
87 : system(model) 129 : system(model)
88 , checker(model) 130 , checker(model)
131 , icount(checker.icount)
89 { 132 {
90 mem.commandp = &mem_commandp; 133 mem.commandp = &mem_commandp;
91 mem_command_arb.outp = &mem_commandp; 134 mem_command_arb.outp = &mem_commandp;
92 mem_command_arb.peerp[0] = &decode_mem_commandp; 135 mem_command_arb.peerp[0] = &exec_mem_commandp;
93 mem_command_arb.peerp[1] = &fetch_mem_commandp; 136 mem_command_arb.peerp[1] = &indir_mem_store_commandp;
137 mem_command_arb.peerp[2] = &indir_mem_load_commandp;
138 mem_command_arb.peerp[3] = &decode_mem_commandp;
139 mem_command_arb.peerp[4] = &fetch_mem_commandp;
94 } 140 }
95}; 141};