summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Blake Kongslie2022-11-05 16:59:17 -0700
committerJulian Blake Kongslie2022-11-05 16:59:31 -0700
commit68bdebd8cae39c30acc384664faa136aeaa9bb84 (patch)
tree4b0c489accd2eb10af6bc359c9ee0d4b22af64ff
parentSupport for more line formats in evt reader (diff)
downloadbiggolf-68bdebd8cae39c30acc384664faa136aeaa9bb84.tar.xz
Add initial uarch model
Diffstat (limited to '')
-rw-r--r--isa/checker.cpp87
-rw-r--r--isa/checker.h10
-rw-r--r--isa/decode.cpp150
-rw-r--r--isa/isa.h10
-rw-r--r--main.cpp33
m---------nanosim0
-rw-r--r--programs/queue.pal45
-rw-r--r--uarch/core.cpp140
-rw-r--r--uarch/core.h74
9 files changed, 476 insertions, 73 deletions
diff --git a/isa/checker.cpp b/isa/checker.cpp
index c6ab161..70b0f88 100644
--- a/isa/checker.cpp
+++ b/isa/checker.cpp
@@ -3,56 +3,55 @@
3#include "isa/checker.h" 3#include "isa/checker.h"
4#include "isa/isa.h" 4#include "isa/isa.h"
5 5
6void checker::execute() { 6void funcchecker::execute() {
7 bool interrupt = system.interact(ctlregs); 7 if (!ctlregs[HALTED]) {
8 inst = decode(ctlregs[FLAGS],
9 pc,
10 mem.fetch(pc),
11 interrupt);
12 auto next_pc = inst.next_pc;
8 13
9 if (ctlregs[HALTED]) 14 if (inst.need_indirect_load) {
10 return; 15 auto addr = mem.fetch(inst.init_address.value());
11 16 if (inst.need_autoinc_store) {
12 inst = decode(ctlregs[FLAGS], 17 addr = (addr + 1) & 07777;
13 pc, 18 mem.store(*inst.init_address, addr);
14 mem.fetch(pc), 19 }
15 interrupt); 20 auto df = (ctlregs[FLAGS] & FLAG_DF) >> FLAG_DF_SHIFT;
16 auto next_pc = inst.next_pc; 21 inst.final_address = (df << 12) | addr;
17 22 } else {
18 if (inst.need_indirect_load) { 23 assert(!inst.need_autoinc_store);
19 auto addr = mem.fetch(inst.init_address.value());
20 if (inst.need_autoinc_store) {
21 addr = (addr + 1) & 07777;
22 mem.store(*inst.init_address, addr);
23 } 24 }
24 auto df = (ctlregs[FLAGS] & FLAG_DF) >> FLAG_DF_SHIFT;
25 inst.final_address = (df << 12) | addr;
26 } else {
27 assert(!inst.need_autoinc_store);
28 }
29 25
30 if (inst.need_exec_load) 26 if (inst.need_exec_load)
31 inst.data = mem.fetch(inst.final_address.value()); 27 inst.data = mem.fetch(inst.final_address.value());
32 28
33 if (inst.need_read_acc) 29 if (inst.need_read_acc)
34 inst.acc = acc; 30 inst.acc = acc;
35 if (inst.need_read_link) 31 if (inst.need_read_link)
36 inst.link = link; 32 inst.link = link;
37 if (inst.need_read_mq) 33 if (inst.need_read_mq)
38 inst.mq = mq; 34 inst.mq = mq;
39 if (inst.read_ctlreg.has_value()) 35 if (inst.read_ctlreg.has_value())
40 inst.ctlval = ctlregs[*inst.read_ctlreg]; 36 inst.ctlval = ctlregs[*inst.read_ctlreg];
41 37
42 inst.execute(); 38 inst.execute();
43 39
44 if (inst.need_write_acc) 40 if (inst.need_write_acc)
45 acc = inst.acc.value(); 41 acc = inst.acc.value();
46 if (inst.need_write_link) 42 if (inst.need_write_link)
47 link = inst.link.value(); 43 link = inst.link.value();
48 if (inst.need_write_mq) 44 if (inst.need_write_mq)
49 mq = inst.mq.value(); 45 mq = inst.mq.value();
50 if (inst.write_ctlreg.has_value()) 46 if (inst.write_ctlreg.has_value())
51 ctlregs[*inst.write_ctlreg] = inst.ctlval.value(); 47 ctlregs[*inst.write_ctlreg] = inst.ctlval.value();
52 48
53 if (inst.need_exec_store) 49 if (inst.need_exec_store)
54 mem.store(inst.final_address.value(), inst.data.value()); 50 mem.store(inst.final_address.value(), inst.data.value());
51
52 assert(inst.next_pc == next_pc || inst.possibly_redirects);
53 pc = inst.next_pc;
54 }
55 55
56 assert(inst.next_pc == next_pc || inst.possibly_redirects); 56 interrupt = system.interact(icount++, ctlregs, true);
57 pc = inst.next_pc;
58} 57}
diff --git a/isa/checker.h b/isa/checker.h
index 65ef8c9..30a8356 100644
--- a/isa/checker.h
+++ b/isa/checker.h
@@ -37,16 +37,18 @@ struct funcmem {
37 } 37 }
38}; 38};
39 39
40struct checker { 40struct funcchecker {
41 unsigned int acc = 0; 41 unsigned int acc = 0;
42 unsigned int link = 0; 42 unsigned int link = 0;
43 unsigned int mq = 0; 43 unsigned int mq = 0;
44 unsigned int pc = 00200; 44 unsigned int pc = 000200;
45 std::array<std::uint_fast32_t, NUM_CTLREGS> ctlregs; 45 std::array<std::uint_fast32_t, NUM_CTLREGS> ctlregs;
46 std::uint64_t icount = 0;
47 bool interrupt = false;
46 iomodel &system; 48 iomodel &system;
47 instruction_context inst; 49 instruction_context inst;
48 funcmem mem; 50 funcmem mem;
49 checker(iomodel &system) 51 funcchecker(iomodel &system)
50 : system(system) 52 : system(system)
51 { 53 {
52 ctlregs.fill(0); 54 ctlregs.fill(0);
@@ -54,6 +56,6 @@ struct checker {
54 } 56 }
55 void execute(); 57 void execute();
56 bool done() { 58 bool done() {
57 return ctlregs[HALTED] && system.done(); 59 return ctlregs[HALTED] && system.done(icount);
58 } 60 }
59}; 61};
diff --git a/isa/decode.cpp b/isa/decode.cpp
index 745e529..2151e2b 100644
--- a/isa/decode.cpp
+++ b/isa/decode.cpp
@@ -1,9 +1,78 @@
1#include <cassert> 1#include <cassert>
2#include <cstdint> 2#include <cstdint>
3#include <fmt/format.h>
3#include <iostream> 4#include <iostream>
5#include <sstream>
4 6
5#include "isa/isa.h" 7#include "isa/isa.h"
6 8
9void init_disasm_tables()
10{
11 for (unsigned int i = 0; i < 0377; ++i) {
12 auto &s = opr_disasm_group1[i];
13 bool cla = i & 0200;
14 bool cll = i & 0100;
15 bool cma = i & 0040;
16 bool cml = i & 0020;
17 bool rar = i & 0010;
18 bool ral = i & 0004;
19 bool bsw = i & 0002;
20 bool iac = i & 0001;
21 if (cla) s += "CLA ";
22 if (cll) s += "CLL ";
23 if (cma) s += "CMA ";
24 if (cml) s += "CML ";
25 if (iac) s += "IAC ";
26 if (rar) s += "RAR ";
27 if (ral) s += "RAL ";
28 if (bsw) s += "BSW ";
29 if (s.size())
30 s = s.substr(0, s.size() - 1);
31 else
32 s = "NOP";
33 }
34
35 for (unsigned int i = 0; i < 0366; ++i) {
36 auto &s = opr_disasm_group2_pos[i];
37 bool cla = i & 0200;
38 bool sma = i & 0100;
39 bool sza = i & 0040;
40 bool snl = i & 0020;
41 bool osr = i & 0004;
42 bool hlt = i & 0002;
43 if (sma) s += "SMA ";
44 if (sza) s += "SZA ";
45 if (snl) s += "SNL ";
46 if (cla) s += "CLA ";
47 if (osr) s += "OSR ";
48 if (hlt) s += "HLT ";
49 if (s.size())
50 s = s.substr(0, s.size() - 1);
51 else
52 s = "NOP";
53 }
54
55 for (unsigned int i = 0; i < 0366; ++i) {
56 auto &s = opr_disasm_group2_neg[i];
57 bool cla = i & 0200;
58 bool spa = i & 0100;
59 bool sna = i & 0040;
60 bool szl = i & 0020;
61 bool osr = i & 0004;
62 bool hlt = i & 0002;
63 if (spa) s += "SPA ";
64 if (sna) s += "SNA ";
65 if (szl) s += "SZL ";
66 if (cla) s += "CLA ";
67 if (osr) s += "OSR ";
68 if (hlt) s += "HLT ";
69 if (s.size())
70 s = s.substr(0, s.size() - 1);
71 else
72 s = "SKP";
73 }
74}
75
7instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned int bits, bool interrupt) 76instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned int bits, bool interrupt)
8{ 77{
9#pragma GCC diagnostic push 78#pragma GCC diagnostic push
@@ -19,6 +88,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
19#pragma GCC diagnostic pop 88#pragma GCC diagnostic pop
20 89
21 instruction_context inst; 90 instruction_context inst;
91 inst.bits = bits;
22 inst.next_pc = (pc & ~07777) | ((pc + 1) & 07777); 92 inst.next_pc = (pc & ~07777) | ((pc + 1) & 07777);
23 93
24 if (interrupt) { 94 if (interrupt) {
@@ -34,6 +104,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
34 inst.need_exec_load = true; 104 inst.need_exec_load = true;
35 inst.need_read_acc = true; 105 inst.need_read_acc = true;
36 inst.need_write_acc = true; 106 inst.need_write_acc = true;
107 inst.df = "AND %a";
37 inst.ef = [](auto &ctx) { 108 inst.ef = [](auto &ctx) {
38 ctx.acc = ctx.acc.value() & ctx.data.value() & 07777; 109 ctx.acc = ctx.acc.value() & ctx.data.value() & 07777;
39 }; 110 };
@@ -44,6 +115,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
44 inst.need_read_link = true; 115 inst.need_read_link = true;
45 inst.need_write_acc = true; 116 inst.need_write_acc = true;
46 inst.need_write_link = true; 117 inst.need_write_link = true;
118 inst.df = "TAD %a";
47 inst.ef = [](auto &ctx) { 119 inst.ef = [](auto &ctx) {
48 unsigned int sum = ctx.acc.value() + ctx.data.value(); 120 unsigned int sum = ctx.acc.value() + ctx.data.value();
49 ctx.link = ctx.link.value() ^ (sum >> 12); 121 ctx.link = ctx.link.value() ^ (sum >> 12);
@@ -54,6 +126,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
54 inst.need_exec_load = true; 126 inst.need_exec_load = true;
55 inst.need_exec_store = true; 127 inst.need_exec_store = true;
56 inst.possibly_redirects = true; 128 inst.possibly_redirects = true;
129 inst.df = "ISZ %a";
57 inst.ef = [](auto &ctx) { 130 inst.ef = [](auto &ctx) {
58 ctx.data = (ctx.data.value() + 1) & 07777; 131 ctx.data = (ctx.data.value() + 1) & 07777;
59 if (*ctx.data == 0) 132 if (*ctx.data == 0)
@@ -64,6 +137,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
64 inst.need_read_acc = true; 137 inst.need_read_acc = true;
65 inst.need_write_acc = true; 138 inst.need_write_acc = true;
66 inst.need_exec_store = true; 139 inst.need_exec_store = true;
140 inst.df = "DCA %a";
67 inst.ef = [](auto &ctx) { 141 inst.ef = [](auto &ctx) {
68 ctx.data = ctx.acc.value(); 142 ctx.data = ctx.acc.value();
69 ctx.acc = 0; 143 ctx.acc = 0;
@@ -72,6 +146,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
72 case 4: // JMS jump subroutine 146 case 4: // JMS jump subroutine
73 inst.need_exec_store = true; 147 inst.need_exec_store = true;
74 inst.possibly_redirects = true; 148 inst.possibly_redirects = true;
149 inst.df = "JMS %a";
75 inst.ef = [ifb](auto &ctx) { 150 inst.ef = [ifb](auto &ctx) {
76 ctx.data = ctx.next_pc; 151 ctx.data = ctx.next_pc;
77 ctx.next_pc = (ifb << 12) | ((ctx.final_address.value() + 1) & 07777); 152 ctx.next_pc = (ifb << 12) | ((ctx.final_address.value() + 1) & 07777);
@@ -79,6 +154,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
79 break; 154 break;
80 case 5: // JMP jump 155 case 5: // JMP jump
81 inst.possibly_redirects = true; 156 inst.possibly_redirects = true;
157 inst.df = "JMP %a";
82 inst.ef = [ifb](auto &ctx) { 158 inst.ef = [ifb](auto &ctx) {
83 ctx.next_pc = (ifb << 12) | (ctx.final_address.value() & 07777); 159 ctx.next_pc = (ifb << 12) | (ctx.final_address.value() & 07777);
84 }; 160 };
@@ -91,6 +167,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
91 case 0: 167 case 0:
92 // SKON skip if interrupts enabled 168 // SKON skip if interrupts enabled
93 inst.possibly_redirects = true; 169 inst.possibly_redirects = true;
170 inst.df = "SKON";
94 inst.ef = [ie](auto &ctx) { 171 inst.ef = [ie](auto &ctx) {
95 if (ie) 172 if (ie)
96 ctx.next_pc = (ctx.next_pc & 07777) | ((ctx.next_pc + 1) & 07777); 173 ctx.next_pc = (ctx.next_pc & 07777) | ((ctx.next_pc + 1) & 07777);
@@ -99,6 +176,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
99 case 1: 176 case 1:
100 // ION set int_enable_delay 177 // ION set int_enable_delay
101 inst.write_ctlreg = FLAGS; 178 inst.write_ctlreg = FLAGS;
179 inst.df = "ION";
102 inst.ef = [flags](auto &ctx) { 180 inst.ef = [flags](auto &ctx) {
103 ctx.ctlval = flags | FLAG_INT_ENABLE_DELAY; 181 ctx.ctlval = flags | FLAG_INT_ENABLE_DELAY;
104 }; 182 };
@@ -106,6 +184,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
106 case 2: 184 case 2:
107 // IOF clear int_enable and int_enable_delay 185 // IOF clear int_enable and int_enable_delay
108 inst.write_ctlreg = FLAGS; 186 inst.write_ctlreg = FLAGS;
187 inst.df = "IOF";
109 inst.ef = [flags](auto &ctx) { 188 inst.ef = [flags](auto &ctx) {
110 ctx.ctlval = flags & ~FLAG_INT_ENABLE_DELAY & ~FLAG_INT_ENABLE; 189 ctx.ctlval = flags & ~FLAG_INT_ENABLE_DELAY & ~FLAG_INT_ENABLE;
111 }; 190 };
@@ -113,6 +192,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
113 case 3: 192 case 3:
114 // SRQ skip if pending interrupt 193 // SRQ skip if pending interrupt
115 inst.possibly_redirects = true; 194 inst.possibly_redirects = true;
195 inst.df = "SRQ";
116 inst.ef = [ir](auto &ctx) { 196 inst.ef = [ir](auto &ctx) {
117 if (ir) 197 if (ir)
118 ctx.next_pc = (ctx.next_pc & 07777) | ((ctx.next_pc + 1) & 07777); 198 ctx.next_pc = (ctx.next_pc & 07777) | ((ctx.next_pc + 1) & 07777);
@@ -122,6 +202,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
122 // GTF get flags 202 // GTF get flags
123 inst.read_ctlreg = FLAGS_SAVED; 203 inst.read_ctlreg = FLAGS_SAVED;
124 inst.need_read_link = true; 204 inst.need_read_link = true;
205 inst.df = "GTF";
125 inst.ef = [](auto &ctx) { 206 inst.ef = [](auto &ctx) {
126 auto flags = ctx.ctlval.value(); 207 auto flags = ctx.ctlval.value();
127 flags |= (unsigned int)ctx.link.value() << 11; 208 flags |= (unsigned int)ctx.link.value() << 11;
@@ -133,6 +214,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
133 inst.need_read_acc = true; 214 inst.need_read_acc = true;
134 inst.need_write_link = true; 215 inst.need_write_link = true;
135 inst.write_ctlreg = FLAGS; 216 inst.write_ctlreg = FLAGS;
217 inst.df = "RTF";
136 inst.ef = [ie](auto &ctx) { 218 inst.ef = [ie](auto &ctx) {
137 if (ie && (ctx.acc.value() & FLAG_INT_ENABLE)) { 219 if (ie && (ctx.acc.value() & FLAG_INT_ENABLE)) {
138 ctx.ctlval = ctx.acc.value() | FLAG_INT_ENABLE_DELAY; 220 ctx.ctlval = ctx.acc.value() | FLAG_INT_ENABLE_DELAY;
@@ -147,6 +229,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
147 break; 229 break;
148 case 6: 230 case 6:
149 // SGT skip if greater than 231 // SGT skip if greater than
232 inst.df = "SGT";
150 inst.ef = [](auto &ctx) { 233 inst.ef = [](auto &ctx) {
151 std::cerr << "unimplemented SGT\n"; 234 std::cerr << "unimplemented SGT\n";
152 assert(false); 235 assert(false);
@@ -154,6 +237,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
154 break; 237 break;
155 case 7: 238 case 7:
156 // CAF clear all flags 239 // CAF clear all flags
240 inst.df = "CAF";
157 inst.ef = [](auto &ctx) { 241 inst.ef = [](auto &ctx) {
158 std::cerr << "unimplemented CAF\n"; 242 std::cerr << "unimplemented CAF\n";
159 assert(false); 243 assert(false);
@@ -168,6 +252,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
168 // KSF skip if TTI flag is set 252 // KSF skip if TTI flag is set
169 inst.read_ctlreg = TT_BITS; 253 inst.read_ctlreg = TT_BITS;
170 inst.possibly_redirects = true; 254 inst.possibly_redirects = true;
255 inst.df = "KSF";
171 inst.ef = [](auto &ctx) { 256 inst.ef = [](auto &ctx) {
172 if (ctx.ctlval.value() & TTI_FLAG) 257 if (ctx.ctlval.value() & TTI_FLAG)
173 ctx.next_pc = (ctx.next_pc & ~07777) | ((ctx.next_pc + 1) & 07777); 258 ctx.next_pc = (ctx.next_pc & ~07777) | ((ctx.next_pc + 1) & 07777);
@@ -177,6 +262,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
177 // KIE set TT_FLAGS from the accumulator 262 // KIE set TT_FLAGS from the accumulator
178 inst.need_read_acc = true; 263 inst.need_read_acc = true;
179 inst.write_ctlreg = TT_FLAGS; 264 inst.write_ctlreg = TT_FLAGS;
265 inst.df = "KIE";
180 inst.ef = [](auto &ctx) { 266 inst.ef = [](auto &ctx) {
181 ctx.ctlval = ctx.acc.value(); 267 ctx.ctlval = ctx.acc.value();
182 }; 268 };
@@ -186,12 +272,14 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
186 inst.read_ctlreg = TT_BITS; 272 inst.read_ctlreg = TT_BITS;
187 inst.need_write_acc = true; 273 inst.need_write_acc = true;
188 inst.write_ctlreg = TT_BITS; 274 inst.write_ctlreg = TT_BITS;
275 inst.df = "KRB";
189 inst.ef = [](auto &ctx) { 276 inst.ef = [](auto &ctx) {
190 ctx.acc = (ctx.ctlval.value() & TTI_DATA) >> TTI_DATA_SHIFT; 277 ctx.acc = (ctx.ctlval.value() & TTI_DATA) >> TTI_DATA_SHIFT;
191 ctx.ctlval.value() &= ~TTI_FLAG; 278 ctx.ctlval.value() &= ~TTI_FLAG;
192 }; 279 };
193 break; 280 break;
194 default: 281 default:
282 inst.df = "IOT %b";
195 inst.ef = [bits](auto &ctx) { 283 inst.ef = [bits](auto &ctx) {
196 std::cerr << "unimplemented IOT KB suboperation " << (bits & 07) << "\n"; 284 std::cerr << "unimplemented IOT KB suboperation " << (bits & 07) << "\n";
197 assert(false); 285 assert(false);
@@ -205,6 +293,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
205 // TFL set TTO flag 293 // TFL set TTO flag
206 inst.read_ctlreg = TT_BITS; 294 inst.read_ctlreg = TT_BITS;
207 inst.write_ctlreg = TT_BITS; 295 inst.write_ctlreg = TT_BITS;
296 inst.df = "TFL";
208 inst.ef = [](auto &ctx) { 297 inst.ef = [](auto &ctx) {
209 ctx.ctlval.value() |= TTO_FLAG; 298 ctx.ctlval.value() |= TTO_FLAG;
210 }; 299 };
@@ -213,6 +302,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
213 // TSF skip if TTO flag is set 302 // TSF skip if TTO flag is set
214 inst.read_ctlreg = TT_BITS; 303 inst.read_ctlreg = TT_BITS;
215 inst.possibly_redirects = true; 304 inst.possibly_redirects = true;
305 inst.df = "TSF";
216 inst.ef = [](auto &ctx) { 306 inst.ef = [](auto &ctx) {
217 if (ctx.ctlval.value() & TTO_FLAG) 307 if (ctx.ctlval.value() & TTO_FLAG)
218 ctx.next_pc = (ctx.next_pc & ~07777) | ((ctx.next_pc + 1) & 07777); 308 ctx.next_pc = (ctx.next_pc & ~07777) | ((ctx.next_pc + 1) & 07777);
@@ -222,6 +312,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
222 // TCF clear TTO flag 312 // TCF clear TTO flag
223 inst.read_ctlreg = TT_BITS; 313 inst.read_ctlreg = TT_BITS;
224 inst.write_ctlreg = TT_BITS; 314 inst.write_ctlreg = TT_BITS;
315 inst.df = "TCF";
225 inst.ef = [](auto &ctx) { 316 inst.ef = [](auto &ctx) {
226 ctx.ctlval.value() &= ~TTO_FLAG; 317 ctx.ctlval.value() &= ~TTO_FLAG;
227 }; 318 };
@@ -231,6 +322,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
231 inst.need_read_acc = true; 322 inst.need_read_acc = true;
232 inst.read_ctlreg = TT_BITS; 323 inst.read_ctlreg = TT_BITS;
233 inst.write_ctlreg = TT_BITS; 324 inst.write_ctlreg = TT_BITS;
325 inst.df = "TPC";
234 inst.ef = [](auto &ctx) { 326 inst.ef = [](auto &ctx) {
235 auto &x = ctx.ctlval.value(); 327 auto &x = ctx.ctlval.value();
236 auto chr = ctx.acc.value(); 328 auto chr = ctx.acc.value();
@@ -243,6 +335,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
243 // TSK skip if TTO flag is set or TTI flag is set 335 // TSK skip if TTO flag is set or TTI flag is set
244 inst.read_ctlreg = TT_BITS; 336 inst.read_ctlreg = TT_BITS;
245 inst.possibly_redirects = true; 337 inst.possibly_redirects = true;
338 inst.df = "TSK";
246 inst.ef = [](auto &ctx) { 339 inst.ef = [](auto &ctx) {
247 if (ctx.ctlval.value() & (TTI_FLAG | TTO_FLAG)) 340 if (ctx.ctlval.value() & (TTI_FLAG | TTO_FLAG))
248 ctx.next_pc = (ctx.next_pc & ~07777) | ((ctx.next_pc + 1) & 07777); 341 ctx.next_pc = (ctx.next_pc & ~07777) | ((ctx.next_pc + 1) & 07777);
@@ -253,6 +346,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
253 inst.need_read_acc = true; 346 inst.need_read_acc = true;
254 inst.read_ctlreg = TT_BITS; 347 inst.read_ctlreg = TT_BITS;
255 inst.write_ctlreg = TT_BITS; 348 inst.write_ctlreg = TT_BITS;
349 inst.df = "TLS";
256 inst.ef = [](auto &ctx) { 350 inst.ef = [](auto &ctx) {
257 auto &x = ctx.ctlval.value(); 351 auto &x = ctx.ctlval.value();
258 auto chr = ctx.acc.value(); 352 auto chr = ctx.acc.value();
@@ -262,6 +356,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
262 }; 356 };
263 break; 357 break;
264 default: 358 default:
359 inst.df = "IOT %b";
265 inst.ef = [bits](auto &ctx) { 360 inst.ef = [bits](auto &ctx) {
266 std::cerr << "unimplemented IOT TT suboperation " << (bits & 07) << "\n"; 361 std::cerr << "unimplemented IOT TT suboperation " << (bits & 07) << "\n";
267 assert(false); 362 assert(false);
@@ -283,6 +378,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
283 case 01: 378 case 01:
284 // CDF change data field 379 // CDF change data field
285 inst.write_ctlreg = FLAGS; 380 inst.write_ctlreg = FLAGS;
381 inst.df = "CDF %f";
286 inst.ef = [flags, field](auto &ctx) { 382 inst.ef = [flags, field](auto &ctx) {
287 ctx.ctlval = (flags & ~FLAG_DF) | (field << FLAG_DF_SHIFT); 383 ctx.ctlval = (flags & ~FLAG_DF) | (field << FLAG_DF_SHIFT);
288 }; 384 };
@@ -293,12 +389,14 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
293 // RMF restore memory field 389 // RMF restore memory field
294 inst.read_ctlreg = FLAGS_SAVED; 390 inst.read_ctlreg = FLAGS_SAVED;
295 inst.write_ctlreg = FLAGS; 391 inst.write_ctlreg = FLAGS;
392 inst.df = "RMF";
296 inst.ef = [flags](auto &ctx) { 393 inst.ef = [flags](auto &ctx) {
297 ctx.ctlval.value() &= FLAG_DF | FLAG_IF | FLAG_USER_MODE; 394 ctx.ctlval.value() &= FLAG_DF | FLAG_IF | FLAG_USER_MODE;
298 ctx.ctlval.value() |= flags & ~(FLAG_DF | FLAG_IF | FLAG_USER_MODE); 395 ctx.ctlval.value() |= flags & ~(FLAG_DF | FLAG_IF | FLAG_USER_MODE);
299 }; 396 };
300 break; 397 break;
301 default: 398 default:
399 inst.df = "IOT %b";
302 inst.ef = [bits, field](auto &ctx) { 400 inst.ef = [bits, field](auto &ctx) {
303 std::cerr << "unimplemented IOT MEMORY suboperation " << (bits & 07) << " upon field " << field << "\n"; 401 std::cerr << "unimplemented IOT MEMORY suboperation " << (bits & 07) << " upon field " << field << "\n";
304 assert(false); 402 assert(false);
@@ -306,6 +404,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
306 } 404 }
307 break; 405 break;
308 default: 406 default:
407 inst.df = "IOT %b";
309 inst.ef = [bits, field](auto &ctx) { 408 inst.ef = [bits, field](auto &ctx) {
310 std::cerr << "unimplemented IOT MEMORY suboperation " << (bits & 07) << " upon field " << field << "\n"; 409 std::cerr << "unimplemented IOT MEMORY suboperation " << (bits & 07) << " upon field " << field << "\n";
311 assert(false); 410 assert(false);
@@ -314,6 +413,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
314 } 413 }
315 break; 414 break;
316 default: 415 default:
416 inst.df = "IOT %b";
317 inst.ef = [bits](auto &ctx) { 417 inst.ef = [bits](auto &ctx) {
318 std::cerr << "warning: unimplemented IOT device " << ((bits >> 6) & 07) << ((bits >> 3) & 07) << " suboperation " << (bits & 07) << "\n"; 418 std::cerr << "warning: unimplemented IOT device " << ((bits >> 6) & 07) << ((bits >> 3) & 07) << " suboperation " << (bits & 07) << "\n";
319 }; 419 };
@@ -333,6 +433,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
333 inst.need_read_link = cml || rar || ral || iac; 433 inst.need_read_link = cml || rar || ral || iac;
334 inst.need_write_acc = cla || cma || rar || ral || bsw || iac; 434 inst.need_write_acc = cla || cma || rar || ral || bsw || iac;
335 inst.need_write_link = cll || cml || rar || ral || iac; 435 inst.need_write_link = cll || cml || rar || ral || iac;
436 inst.df = opr_disasm_group1[bits & 0377].c_str();
336 inst.ef = [cla, cll, cma, cml, rar, ral, bsw, iac](auto &ctx) { 437 inst.ef = [cla, cll, cma, cml, rar, ral, bsw, iac](auto &ctx) {
337 if (cla) ctx.acc = 0; 438 if (cla) ctx.acc = 0;
338 if (cll) ctx.link = 0; 439 if (cll) ctx.link = 0;
@@ -374,6 +475,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
374 if (hlt) 475 if (hlt)
375 inst.write_ctlreg = HALTED; 476 inst.write_ctlreg = HALTED;
376 inst.possibly_redirects = true; 477 inst.possibly_redirects = true;
478 inst.df = opr_disasm_group2_pos[bits & 0366].c_str();
377 inst.ef = [cla, sma, sza, snl, osr, hlt](auto &ctx) { 479 inst.ef = [cla, sma, sza, snl, osr, hlt](auto &ctx) {
378 bool skip = false; 480 bool skip = false;
379 if (sma && (ctx.acc.value() & 04000)) skip = true; 481 if (sma && (ctx.acc.value() & 04000)) skip = true;
@@ -398,6 +500,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
398 if (hlt) 500 if (hlt)
399 inst.write_ctlreg = HALTED; 501 inst.write_ctlreg = HALTED;
400 inst.possibly_redirects = true; 502 inst.possibly_redirects = true;
503 inst.df = opr_disasm_group2_neg[bits & 0366].c_str();
401 inst.ef = [cla, spa, sna, szl, osr, hlt](auto &ctx) { 504 inst.ef = [cla, spa, sna, szl, osr, hlt](auto &ctx) {
402 bool skip = true; 505 bool skip = true;
403 if (spa && (ctx.acc.value() & 04000)) skip = false; 506 if (spa && (ctx.acc.value() & 04000)) skip = false;
@@ -418,6 +521,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
418 inst.need_read_mq = mqa; 521 inst.need_read_mq = mqa;
419 inst.need_write_acc = cla || mqa; 522 inst.need_write_acc = cla || mqa;
420 inst.need_write_mq = mql; 523 inst.need_write_mq = mql;
524 inst.df = opr_disasm_extended_arith[bits & 0376].c_str();
421 inst.ef = [cla, mqa, mql, extended_arith](auto &ctx) { 525 inst.ef = [cla, mqa, mql, extended_arith](auto &ctx) {
422 assert(!extended_arith); 526 assert(!extended_arith);
423 if (cla) ctx.acc = 0; 527 if (cla) ctx.acc = 0;
@@ -429,6 +533,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
429 ctx.mq = new_mq; 533 ctx.mq = new_mq;
430 }; 534 };
431 } else { 535 } else {
536 inst.df = "OPR %b";
432 inst.ef = [bits](auto &ctx) { 537 inst.ef = [bits](auto &ctx) {
433 std::cerr << "unimplemented OPR " << ((bits >> 6) & 07) << ((bits >> 3) & 07) << (bits & 07) << "\n"; 538 std::cerr << "unimplemented OPR " << ((bits >> 6) & 07) << ((bits >> 3) & 07) << (bits & 07) << "\n";
434 assert(false); 539 assert(false);
@@ -438,7 +543,7 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
438 } 543 }
439 544
440 // Instructions with memory operands may be direct or indirect 545 // Instructions with memory operands may be direct or indirect
441 if (inst.need_exec_load || inst.need_exec_store || inst.possibly_redirects) { 546 if (inst.need_exec_load || inst.need_exec_store || (bits & 06000) == 04000 /* JMS and JMP */) {
442 auto addr = (pc & 070000) | ((bits & 00200) ? (pc & 07600) : 0) | (bits & 00177); 547 auto addr = (pc & 070000) | ((bits & 00200) ? (pc & 07600) : 0) | (bits & 00177);
443 if (bits & 00400) { 548 if (bits & 00400) {
444 inst.need_indirect_load = true; 549 inst.need_indirect_load = true;
@@ -454,3 +559,46 @@ instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned i
454 559
455 return inst; 560 return inst;
456} 561}
562
563std::string instruction_context::disasm() const
564{
565 if (!df)
566 return "<null>";
567
568 std::ostringstream s;
569 for (const char *p = df; *p; ++p) {
570 if (*p != '%') {
571 s << *p;
572 continue;
573 }
574 switch (*++p) {
575 case '\0':
576 case '%':
577 s << '%';
578 break;
579 case 'a':
580 if (bits & 00400)
581 s << "I ";
582 if (~bits & 00200)
583 s << "Z ";
584 s << fmt::format("{:03o}", bits & 00177);
585 break;
586 case 'b':
587 s << fmt::format("{:04o}", bits);
588 break;
589 case 'f':
590 s << fmt::format("{:01o}", (bits & 00070) >> 3);
591 break;
592 default:
593 s << '%' << *p;
594 break;
595 }
596 }
597
598 if (init_address.has_value())
599 s << fmt::format(" [{:05o}] ->", *init_address);
600 if (final_address.has_value())
601 s << fmt::format(" [{:05o}]", *final_address);
602
603 return s.str();
604}
diff --git a/isa/isa.h b/isa/isa.h
index 8156c08..4083e16 100644
--- a/isa/isa.h
+++ b/isa/isa.h
@@ -51,6 +51,11 @@ static constexpr std::uint_fast32_t TTO_DATA = 0xff << TTO_DATA_SHIFT;
51static constexpr std::uint_fast32_t TTF_INT_ENABLE = 1 << 0; 51static constexpr std::uint_fast32_t TTF_INT_ENABLE = 1 << 0;
52static constexpr std::uint_fast32_t TTF_STATUS_ENABLE = 1 << 1; 52static constexpr std::uint_fast32_t TTF_STATUS_ENABLE = 1 << 1;
53 53
54static std::string opr_disasm_group1[0377];
55static std::string opr_disasm_group2_pos[0366];
56static std::string opr_disasm_group2_neg[0366];
57static std::string opr_disasm_extended_arith[0376];
58
54struct instruction_context { 59struct instruction_context {
55 // Known statically at decode time 60 // Known statically at decode time
56 bool need_indirect_load = false; // final_address = mem[init_address] 61 bool need_indirect_load = false; // final_address = mem[init_address]
@@ -67,10 +72,14 @@ struct instruction_context {
67 bool need_exec_store = false; // mem[final_address] = data 72 bool need_exec_store = false; // mem[final_address] = data
68 bool possibly_redirects = false; // %pc = next_pc 73 bool possibly_redirects = false; // %pc = next_pc
69 74
75 const char *df = nullptr;
76 std::string disasm() const;
77
70 std::function<void(instruction_context &ctx)> ef; 78 std::function<void(instruction_context &ctx)> ef;
71 void execute() { ef(*this); } 79 void execute() { ef(*this); }
72 80
73 // May change over the lifetime of the instruction execution 81 // May change over the lifetime of the instruction execution
82 unsigned int bits;
74 unsigned int next_pc; // includes IF 83 unsigned int next_pc; // includes IF
75 std::optional<unsigned int> init_address; // includes DF 84 std::optional<unsigned int> init_address; // includes DF
76 std::optional<unsigned int> final_address; // includes DF 85 std::optional<unsigned int> final_address; // includes DF
@@ -81,4 +90,5 @@ struct instruction_context {
81 std::optional<unsigned int> mq; 90 std::optional<unsigned int> mq;
82}; 91};
83 92
93void init_disasm_tables();
84instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned int bits, bool interrupt); 94instruction_context decode(std::uint_fast32_t flags, unsigned int pc, unsigned int bits, bool interrupt);
diff --git a/main.cpp b/main.cpp
index 7a8d161..4fec1f4 100644
--- a/main.cpp
+++ b/main.cpp
@@ -6,10 +6,12 @@
6#include <optional> 6#include <optional>
7#include <utility> 7#include <utility>
8 8
9#include "infra/sim.h"
9#include "isa/checker.h" 10#include "isa/checker.h"
10#include "programs/programs.h" 11#include "programs/programs.h"
12#include "uarch/core.h"
11 13
12int load_program(checker &checker, const std::uint8_t *program) { 14int load_program(core &core, const std::uint8_t *program) {
13 bool seen_non_leader = false; 15 bool seen_non_leader = false;
14 bool comment = false; 16 bool comment = false;
15 unsigned int field = 0; 17 unsigned int field = 0;
@@ -31,8 +33,10 @@ int load_program(checker &checker, const std::uint8_t *program) {
31 address = ((b1 & 0077) << 6) | *program++; 33 address = ((b1 & 0077) << 6) | *program++;
32 } else if ((b1 & 0300) == 0000) { 34 } else if ((b1 & 0300) == 0000) {
33 seen_non_leader = true; 35 seen_non_leader = true;
34 if (data.has_value()) 36 if (data.has_value()) {
35 checker.mem.store(data->first, data->second); 37 core.checker.mem.store(data->first, data->second);
38 core.mem.store(data->first, data->second);
39 }
36 auto a = field | address++; 40 auto a = field | address++;
37 auto d = ((b1 & 0077) << 6) | *program++; 41 auto d = ((b1 & 0077) << 6) | *program++;
38 data = std::make_pair(a, d); 42 data = std::make_pair(a, d);
@@ -57,12 +61,14 @@ int main(int argc, const char *argv[]) {
57 return 1; 61 return 1;
58 } 62 }
59 63
64 init_disasm_tables();
65
60 iomodel system; 66 iomodel system;
61 checker checker(system); 67 core core(system);
62 68
63 for (--argc, ++argv; argc; --argc, ++argv) { 69 for (--argc, ++argv; argc; --argc, ++argv) {
64 if (auto program = programs.find(*argv); program != programs.end()) { 70 if (auto program = programs.find(*argv); program != programs.end()) {
65 if (auto err = load_program(checker, program->second)) 71 if (auto err = load_program(core, program->second))
66 return err; 72 return err;
67 } else { 73 } else {
68 std::ifstream fh(*argv); 74 std::ifstream fh(*argv);
@@ -70,12 +76,21 @@ int main(int argc, const char *argv[]) {
70 } 76 }
71 } 77 }
72 78
73 while (!checker.done()) { 79 std::ofstream pt("bug.pt");
74// if (!checker.ctlregs[HALTED]) 80 infra::pt::ptfile = &pt;
75// std::cout << fmt::format("\t{:9} {:04o}\n", system.time, checker.pc); 81
76 checker.execute(); 82 while (!core.checker.done()) {
83// if (!checker.ctlregs[HALTED]) {
84// if (checker.inst.final_address.has_value())
85// std::cout << fmt::format("{:05o} {:01o} {:04o} {:04o} {:005o}\n", checker.pc, checker.link, checker.acc, checker.mq, *checker.inst.final_address);
86// else
87// std::cout << fmt::format("{:05o} {:01o} {:04o} {:04o} \n", checker.pc, checker.link, checker.acc, checker.mq);
88// }
89 infra::sim::advance();
77 } 90 }
78 91
92 pt << fmt::format("# icount={} cycles={} ipc={:.04}\n", core.checker.icount, infra::sim::now, (float)core.checker.icount / (float)infra::sim::now);
93
79// std::ofstream fh("trace.evt"); 94// std::ofstream fh("trace.evt");
80// system.write_evt(fh); 95// system.write_evt(fh);
81 96
diff --git a/nanosim b/nanosim
Subproject f795e6c7224c0cdeedb0c2a7bccc8cae8991315 Subproject 3c43115056a1622d97de05fbc56c38e2013cfc1
diff --git a/programs/queue.pal b/programs/queue.pal
index 89a1fea..7d4cce7 100644
--- a/programs/queue.pal
+++ b/programs/queue.pal
@@ -7,12 +7,15 @@ INTRET, 0
7 7
8*010 8*010
9 9
10HEAD, 7777 / because preincrement 10IHEAD, 7777 / because preincrement
11TAIL, 7777 11ITAIL, 7777
12
13OHEAD, 7777 / because preincrement
14OTAIL, 7777
12 15
13*100 16*100
14 17
15TTBUSY, 0 18OBUSY, 0
16 19
17*200 20*200
18 21
@@ -20,24 +23,23 @@ TTBUSY, 0
20 KIE 23 KIE
21 ION 24 ION
22LOOP, CLA 25LOOP, CLA
23 TAD TTBUSY 26 TAD ITAIL
24 SZA
25 JMP LOOP
26 TAD TAIL
27 CMA IAC 27 CMA IAC
28 TAD HEAD 28 TAD IHEAD
29 SNA 29 SNA
30 JMP LOOP 30 JMP LOOP
31 CLA 31 CLA
32 CDF 0010 32 CDF 0010
33 TAD I TAIL 33 TAD I ITAIL
34 CDF 0020
35 DCA I OHEAD
34 CDF 0000 36 CDF 0000
35 IOF / critical section 37 IOF / critical section
36 TPC 38 TAD OBUSY
37 CLA IAC 39 SNA
40 TFL
38 ION 41 ION
39 DCA TTBUSY / end critical section 42 JMP LOOP / end critical section
40 JMP LOOP
41 43
42*400 44*400
43 45
@@ -47,13 +49,26 @@ GOTINT, DCA SAVEA
47 DCA SAVEF 49 DCA SAVEF
48 TSF 50 TSF
49 JMP KBIN 51 JMP KBIN
50 DCA TTBUSY
51 TCF 52 TCF
53 CLA
54 DCA OBUSY
55 TAD OTAIL
56 CMA IAC
57 TAD OHEAD
58 SNA
59 JMP KBIN
60 CLA
61 CDF 0020
62 TAD I OTAIL
63 CDF 0000
64 TPC
65 CLA IAC
66 DCA OBUSY
52KBIN, KSF 67KBIN, KSF
53 JMP RETINT 68 JMP RETINT
54 KRB 69 KRB
55 CDF 0010 70 CDF 0010
56 DCA I HEAD 71 DCA I IHEAD
57 CDF 0000 72 CDF 0000
58RETINT, CLA 73RETINT, CLA
59 TAD SAVEF 74 TAD SAVEF
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}
diff --git a/uarch/core.h b/uarch/core.h
new file mode 100644
index 0000000..0f9be74
--- /dev/null
+++ b/uarch/core.h
@@ -0,0 +1,74 @@
1#pragma once
2
3#include <array>
4
5#include "infra/pipetrace.h"
6#include "infra/port.h"
7#include "io/model.h"
8#include "isa/checker.h"
9#include "isa/isa.h"
10
11struct core;
12
13struct fetch_bundle {
14 infra::transaction tr;
15 unsigned int gen;
16 unsigned int pc;
17 unsigned int word;
18};
19
20struct fetch_restart {
21 infra::transaction tr;
22 unsigned int new_gen;
23 unsigned int new_pc;
24};
25
26struct fetch_stage : public infra::sim {
27 core &c;
28
29 unsigned int gen = 0;
30 unsigned int pc;
31 bool didrestart = false;
32
33 fetch_stage(core &c);
34
35 void clock();
36};
37
38struct decode_stage : public infra::sim {
39 core &c;
40
41 unsigned int gen = 0;
42
43 bool interrupt = false;
44
45 unsigned int acc;
46 unsigned int link;
47 unsigned int mq;
48 unsigned int pc;
49 std::array<uint_fast32_t, NUM_CTLREGS> ctlregs;
50 std::uint64_t icount;
51 instruction_context inst;
52
53 decode_stage(core &c);
54
55 void clock();
56};
57
58struct core {
59 iomodel &system;
60 funcchecker checker;
61 funcmem mem;
62
63 infra::port<fetch_bundle> fetch_bundlep;
64 std::optional<fetch_restart> fetch_restarto;
65
66 // Construction order is execution order within a cycle, so this list should be back-to-front (for zero-cycle restarts)
67 decode_stage decode{*this};
68 fetch_stage fetch{*this};
69
70 core(iomodel &model)
71 : system(model)
72 , checker(model)
73 { }
74};