diff options
| author | Julian Blake Kongslie | 2022-11-19 16:29:27 -0800 |
|---|---|---|
| committer | Julian Blake Kongslie | 2022-11-19 16:29:27 -0800 |
| commit | fdb61389099cee41b86c25c3d1ddb660b509e5fa (patch) | |
| tree | 00ebbec2b5a3398ea71442d5cd124a64bd61d80a /uarch/core.cpp | |
| parent | Multi-word fetch bundles and icache with realistic dram latency (diff) | |
| download | biggolf-fdb61389099cee41b86c25c3d1ddb660b509e5fa.tar.xz | |
Pipelined microarchitecture, which even almost works!
Includes such horrors as the "unstore" operation for undoing
autoincremented addresses on instructions subsequently found to be
bogus.
Diffstat (limited to '')
| -rw-r--r-- | uarch/core.cpp | 348 |
1 files changed, 275 insertions, 73 deletions
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 | ||
| 11 | decode_stage::decode_stage(core &c) | 11 | decode_stage::decode_stage(core &c) |
| 12 | : c(c) | 12 | : c(c) |
| 13 | , pc(c.checker.pc) | ||
| 14 | , icount(c.checker.icount) | ||
| 15 | { } | ||
| 16 | |||
| 17 | indir_stage::indir_stage(core &c) | ||
| 18 | : c(c) | ||
| 19 | { } | ||
| 20 | |||
| 21 | exec_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 | ||
| 21 | void fetch_stage::clock() { | 30 | void 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 | ||
| 63 | void decode_stage::clock() { | 71 | void 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 | |||
| 148 | void 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) | 206 | void 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 | |||
| 141 | bail_out: | 332 | bail_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 | } |
