diff options
Diffstat (limited to 'uarch/core.cpp')
| -rw-r--r-- | uarch/core.cpp | 84 |
1 files changed, 58 insertions, 26 deletions
diff --git a/uarch/core.cpp b/uarch/core.cpp index 12f8b5b..7304442 100644 --- a/uarch/core.cpp +++ b/uarch/core.cpp | |||
| @@ -74,9 +74,16 @@ void decode_stage::clock() { | |||
| 74 | pc = r.new_pc; | 74 | pc = r.new_pc; |
| 75 | interrupt |= r.interrupt; | 75 | interrupt |= r.interrupt; |
| 76 | icount = c.icount; | 76 | icount = c.icount; |
| 77 | speculative_stores_sent = r.stores_sent; | ||
| 77 | } | 78 | } |
| 78 | 79 | ||
| 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()) { | 80 | if (c.decode_store_completep.can_read()) { |
| 81 | ++stores_done; | ||
| 82 | assert((int)(speculative_stores_sent - stores_done) >= 0); | ||
| 83 | c.decode_store_completep.discard(); | ||
| 84 | } | ||
| 85 | |||
| 86 | if (speculative_stores_sent == stores_done && c.fetch_bundlep.can_read() && c.decode_mem_commandp.can_write() && c.indir_instp.can_write() && c.decode_to_exec_instp.can_write()) { | ||
| 80 | auto b = c.fetch_bundlep.peek(); | 87 | auto b = c.fetch_bundlep.peek(); |
| 81 | 88 | ||
| 82 | if (b.gen != c.gen) { | 89 | if (b.gen != c.gen) { |
| @@ -118,6 +125,9 @@ void decode_stage::clock() { | |||
| 118 | 125 | ||
| 119 | pc = i.inst.next_pc; | 126 | pc = i.inst.next_pc; |
| 120 | 127 | ||
| 128 | speculative_stores_sent += i.inst.need_autoinc_store; | ||
| 129 | speculative_stores_sent += i.inst.need_exec_store; | ||
| 130 | |||
| 121 | if (i.inst.need_indirect_load) { | 131 | if (i.inst.need_indirect_load) { |
| 122 | memory::dram::command fr; | 132 | memory::dram::command fr; |
| 123 | fr.transaction = i.tr; | 133 | fr.transaction = i.tr; |
| @@ -180,6 +190,7 @@ void indir_stage::clock() { | |||
| 180 | sr.mask.fill(false); | 190 | sr.mask.fill(false); |
| 181 | sr.mask[*i.inst.init_address & memory::LINE_BYTE_OFFSET_MASK] = true; | 191 | sr.mask[*i.inst.init_address & memory::LINE_BYTE_OFFSET_MASK] = true; |
| 182 | sr.write = true; | 192 | sr.write = true; |
| 193 | sr.responsep = &c.decode_store_completep; | ||
| 183 | c.indir_mem_store_commandp.write(std::move(sr)); | 194 | c.indir_mem_store_commandp.write(std::move(sr)); |
| 184 | } else { | 195 | } else { |
| 185 | pte(i.tr, "I"); | 196 | pte(i.tr, "I"); |
| @@ -207,6 +218,7 @@ void exec_stage::clock() { | |||
| 207 | c.restarto.reset(); | 218 | c.restarto.reset(); |
| 208 | 219 | ||
| 209 | std::optional<infra::transaction> restarttr; | 220 | std::optional<infra::transaction> restarttr; |
| 221 | std::optional<instruction_context> insto; | ||
| 210 | 222 | ||
| 211 | bool progress = ctlregs[HALTED]; | 223 | bool progress = ctlregs[HALTED]; |
| 212 | 224 | ||
| @@ -226,7 +238,9 @@ void exec_stage::clock() { | |||
| 226 | sr.mask.fill(false); | 238 | sr.mask.fill(false); |
| 227 | sr.mask[*i.inst.init_address & memory::LINE_BYTE_OFFSET_MASK] = true; | 239 | sr.mask[*i.inst.init_address & memory::LINE_BYTE_OFFSET_MASK] = true; |
| 228 | sr.write = true; | 240 | sr.write = true; |
| 241 | sr.responsep = &c.decode_store_completep; | ||
| 229 | c.exec_mem_commandp.write(std::move(sr)); | 242 | c.exec_mem_commandp.write(std::move(sr)); |
| 243 | stores_sent += 2; // Original store sent by Indir stage plus unstore here | ||
| 230 | } | 244 | } |
| 231 | c.decode_to_exec_instp.discard(); | 245 | c.decode_to_exec_instp.discard(); |
| 232 | } else if (i.icount == c.icount) { | 246 | } else if (i.icount == c.icount) { |
| @@ -247,7 +261,9 @@ void exec_stage::clock() { | |||
| 247 | sr.mask.fill(false); | 261 | sr.mask.fill(false); |
| 248 | sr.mask[*i.inst.init_address & memory::LINE_BYTE_OFFSET_MASK] = true; | 262 | sr.mask[*i.inst.init_address & memory::LINE_BYTE_OFFSET_MASK] = true; |
| 249 | sr.write = true; | 263 | sr.write = true; |
| 264 | sr.responsep = &c.decode_store_completep; | ||
| 250 | c.exec_mem_commandp.write(std::move(sr)); | 265 | c.exec_mem_commandp.write(std::move(sr)); |
| 266 | stores_sent += 2; // Original store sent by Indir stage plus unstore here | ||
| 251 | } | 267 | } |
| 252 | c.indir_to_exec_instp.discard(); | 268 | c.indir_to_exec_instp.discard(); |
| 253 | } else if (i.icount == c.icount) { | 269 | } else if (i.icount == c.icount) { |
| @@ -277,49 +293,58 @@ void exec_stage::clock() { | |||
| 277 | pte(i.tr, "", fmt::format("loaddata={:04o}", *i.inst.data)); | 293 | pte(i.tr, "", fmt::format("loaddata={:04o}", *i.inst.data)); |
| 278 | } | 294 | } |
| 279 | 295 | ||
| 296 | // We are committed to complete execution of this instruction this cycle. | ||
| 297 | |||
| 298 | insto = std::move(i.inst); | ||
| 299 | auto &inst = *insto; | ||
| 300 | |||
| 280 | pte(i.tr, "E"); | 301 | pte(i.tr, "E"); |
| 281 | progress = true; | 302 | progress = true; |
| 282 | 303 | ||
| 283 | assert(i.pc == pc); | 304 | assert(i.pc == pc); |
| 284 | 305 | ||
| 285 | auto next_pc = i.inst.next_pc; | 306 | auto next_pc = inst.next_pc; |
| 286 | 307 | ||
| 287 | if (i.inst.need_read_acc) | 308 | if (inst.need_autoinc_store) |
| 288 | i.inst.acc = acc; | 309 | ++stores_sent; // It was sent by Indir stage |
| 289 | if (i.inst.need_read_link) | 310 | if (inst.need_read_acc) |
| 290 | i.inst.link = link; | 311 | inst.acc = acc; |
| 291 | if (i.inst.need_read_mq) | 312 | if (inst.need_read_link) |
| 292 | i.inst.mq = mq; | 313 | inst.link = link; |
| 293 | if (i.inst.read_ctlreg.has_value()) | 314 | if (inst.need_read_mq) |
| 294 | i.inst.ctlval = ctlregs[*i.inst.read_ctlreg]; | 315 | inst.mq = mq; |
| 316 | if (inst.read_ctlreg.has_value()) | ||
| 317 | inst.ctlval = ctlregs[*inst.read_ctlreg]; | ||
| 295 | 318 | ||
| 296 | i.inst.execute(); | 319 | inst.execute(); |
| 297 | 320 | ||
| 298 | if (i.inst.need_write_acc) | 321 | if (inst.need_write_acc) |
| 299 | acc = i.inst.acc.value(); | 322 | acc = inst.acc.value(); |
| 300 | if (i.inst.need_write_link) | 323 | if (inst.need_write_link) |
| 301 | link = i.inst.link.value(); | 324 | link = inst.link.value(); |
| 302 | if (i.inst.need_write_mq) | 325 | if (inst.need_write_mq) |
| 303 | mq = i.inst.mq.value(); | 326 | mq = inst.mq.value(); |
| 304 | if (i.inst.write_ctlreg.has_value()) { | 327 | if (inst.write_ctlreg.has_value()) { |
| 305 | ctlregs[*i.inst.write_ctlreg] = i.inst.ctlval.value(); | 328 | ctlregs[*inst.write_ctlreg] = inst.ctlval.value(); |
| 306 | restarttr = i.tr; | 329 | restarttr = i.tr; |
| 307 | } | 330 | } |
| 308 | 331 | ||
| 309 | if (i.inst.need_exec_store) { | 332 | if (inst.need_exec_store) { |
| 310 | pte(i.tr, "", fmt::format("store={:05o} storedata={:04o}", *i.inst.final_address, *i.inst.data)); | 333 | pte(i.tr, "", fmt::format("store={:05o} storedata={:04o}", *inst.final_address, *inst.data)); |
| 311 | memory::dram::command sr; | 334 | memory::dram::command sr; |
| 312 | sr.transaction = i.tr; | 335 | sr.transaction = i.tr; |
| 313 | sr.line_address = *i.inst.final_address >> memory::LINE_BYTES_LOG2; | 336 | sr.line_address = *inst.final_address >> memory::LINE_BYTES_LOG2; |
| 314 | sr.data[*i.inst.final_address & memory::LINE_BYTE_OFFSET_MASK] = *i.inst.data; | 337 | sr.data[*inst.final_address & memory::LINE_BYTE_OFFSET_MASK] = *inst.data; |
| 315 | sr.mask.fill(false); | 338 | sr.mask.fill(false); |
| 316 | sr.mask[*i.inst.final_address & memory::LINE_BYTE_OFFSET_MASK] = true; | 339 | sr.mask[*inst.final_address & memory::LINE_BYTE_OFFSET_MASK] = true; |
| 317 | sr.write = true; | 340 | sr.write = true; |
| 341 | sr.responsep = &c.decode_store_completep; | ||
| 318 | c.exec_mem_commandp.write(std::move(sr)); | 342 | c.exec_mem_commandp.write(std::move(sr)); |
| 343 | ++stores_sent; | ||
| 319 | } | 344 | } |
| 320 | 345 | ||
| 321 | assert(i.inst.next_pc == next_pc || i.inst.possibly_redirects); | 346 | assert(inst.next_pc == next_pc || inst.possibly_redirects); |
| 322 | pc = i.inst.next_pc; | 347 | pc = inst.next_pc; |
| 323 | 348 | ||
| 324 | if (pc != next_pc) { | 349 | if (pc != next_pc) { |
| 325 | pte(i.tr, "", fmt::format("jump={:05o}", pc)); | 350 | pte(i.tr, "", fmt::format("jump={:05o}", pc)); |
| @@ -345,6 +370,7 @@ bail_out: | |||
| 345 | r.tr = *restarttr; | 370 | r.tr = *restarttr; |
| 346 | r.new_pc = pc; | 371 | r.new_pc = pc; |
| 347 | r.interrupt = interrupt; | 372 | r.interrupt = interrupt; |
| 373 | r.stores_sent = stores_sent; | ||
| 348 | gen = ++c.gen; | 374 | gen = ++c.gen; |
| 349 | c.restarto = std::move(r); | 375 | c.restarto = std::move(r); |
| 350 | } | 376 | } |
| @@ -356,6 +382,12 @@ bail_out: | |||
| 356 | assert(c.checker.icount == c.icount); | 382 | assert(c.checker.icount == c.icount); |
| 357 | // std::cerr << fmt::format("icount={:} pc={:05o} checkerpc={:05o}\n", c.icount, pc, c.checker.pc); | 383 | // std::cerr << fmt::format("icount={:} pc={:05o} checkerpc={:05o}\n", c.icount, pc, c.checker.pc); |
| 358 | assert(pc == c.checker.pc); | 384 | assert(pc == c.checker.pc); |
| 385 | |||
| 386 | if (insto.has_value()) { | ||
| 387 | auto &inst = *insto; | ||
| 388 | assert(inst == c.checker.inst); | ||
| 389 | } | ||
| 390 | |||
| 359 | assert(acc == c.checker.acc); | 391 | assert(acc == c.checker.acc); |
| 360 | assert(link == c.checker.link); | 392 | assert(link == c.checker.link); |
| 361 | assert(mq == c.checker.mq); | 393 | assert(mq == c.checker.mq); |
