diff options
Diffstat (limited to '')
| -rw-r--r-- | uarch/core.cpp | 55 | ||||
| -rw-r--r-- | uarch/core.h | 27 |
2 files changed, 63 insertions, 19 deletions
diff --git a/uarch/core.cpp b/uarch/core.cpp index 34f422a..8b2db9b 100644 --- a/uarch/core.cpp +++ b/uarch/core.cpp | |||
| @@ -25,21 +25,38 @@ void fetch_stage::clock() { | |||
| 25 | gen = r.new_gen; | 25 | gen = r.new_gen; |
| 26 | pc = r.new_pc; | 26 | pc = r.new_pc; |
| 27 | didrestart = true; | 27 | didrestart = true; |
| 28 | outstandingfill = false; | ||
| 28 | c.fetch_restarto.reset(); | 29 | c.fetch_restarto.reset(); |
| 29 | } | 30 | } |
| 30 | 31 | ||
| 32 | if (c.fetch_mem_responsep.can_read()) { | ||
| 33 | auto r = c.fetch_mem_responsep.read(); | ||
| 34 | cache.handle_response(r); | ||
| 35 | } | ||
| 36 | |||
| 31 | if (c.fetch_bundlep.can_write()) { | 37 | if (c.fetch_bundlep.can_write()) { |
| 32 | fetch_bundle b; | 38 | fetch_bundle b; |
| 33 | b.tr = infra::pt::toplevel(); | 39 | if (auto t = cache.fetchline(b.data, pc); t.has_value()) { |
| 34 | b.gen = gen; | 40 | b.tr = infra::pt::toplevel(); |
| 35 | b.pc = pc; | 41 | b.gen = gen; |
| 36 | b.word = c.mem.fetch(pc); | 42 | b.pc = pc; |
| 37 | if (didrestart) | 43 | if (didrestart) |
| 38 | infra::pt::event(b.tr, ">", now-1, ""); | 44 | infra::pt::event(b.tr, ">", now-1, ""); |
| 39 | pte(b.tr, "F"); | 45 | pte(b.tr, "F", fmt::format("pc={:05o}", b.pc)); |
| 40 | c.fetch_bundlep.write(std::move(b)); | 46 | c.fetch_bundlep.write(std::move(b)); |
| 41 | pc = (pc & 070000) | ((pc + 1) & 007777); | 47 | pc = (pc & 070000) | (((pc & ~memory::LINE_BYTE_OFFSET_MASK) + memory::LINE_BYTES) & 007777); |
| 42 | didrestart = false; | 48 | didrestart = false; |
| 49 | outstandingfill = false; | ||
| 50 | } | ||
| 51 | } | ||
| 52 | |||
| 53 | if (!outstandingfill && c./*fetch_*/mem_commandp.can_write() && !cache.probe(pc)) { | ||
| 54 | memory::dram::command fr; | ||
| 55 | fr.transaction = infra::pt::toplevel(); | ||
| 56 | fr.line_address = pc >> memory::LINE_BYTES_LOG2; | ||
| 57 | fr.responsep = &c.fetch_mem_responsep; | ||
| 58 | c./*fetch_*/mem_commandp.write(std::move(fr)); | ||
| 59 | outstandingfill = true; | ||
| 43 | } | 60 | } |
| 44 | } | 61 | } |
| 45 | 62 | ||
| @@ -47,28 +64,31 @@ void decode_stage::clock() { | |||
| 47 | bool progress = ctlregs[HALTED]; | 64 | bool progress = ctlregs[HALTED]; |
| 48 | 65 | ||
| 49 | if (!ctlregs[HALTED] && c.fetch_bundlep.can_read()) { | 66 | if (!ctlregs[HALTED] && c.fetch_bundlep.can_read()) { |
| 50 | auto b = c.fetch_bundlep.read(); | 67 | auto b = c.fetch_bundlep.peek(); |
| 51 | 68 | ||
| 52 | if (b.gen != gen) | 69 | if (b.gen != gen) |
| 53 | goto bail_out; | 70 | goto bail_out; |
| 54 | 71 | ||
| 55 | if (b.pc != pc) { | 72 | if ((b.pc >> memory::LINE_BYTES_LOG2) != (pc >> memory::LINE_BYTES_LOG2)) { |
| 56 | pte(b.tr, "~"); | 73 | pte(b.tr, "~"); |
| 57 | fetch_restart r; | 74 | fetch_restart r; |
| 58 | r.tr = b.tr; | 75 | r.tr = b.tr; |
| 59 | r.new_gen = ++gen; | 76 | r.new_gen = ++gen; |
| 60 | r.new_pc = pc; | 77 | r.new_pc = pc; |
| 61 | c.fetch_restarto = std::move(r); | 78 | c.fetch_restarto = std::move(r); |
| 79 | c.fetch_bundlep.discard(); | ||
| 62 | goto bail_out; | 80 | goto bail_out; |
| 63 | } | 81 | } |
| 64 | 82 | ||
| 65 | progress = true; | 83 | progress = true; |
| 66 | 84 | ||
| 67 | pte(b.tr, "E"); | 85 | auto tr = infra::pt::child(b.tr); |
| 86 | |||
| 87 | pte(tr, "E"); | ||
| 68 | 88 | ||
| 69 | inst = decode(ctlregs[FLAGS], | 89 | inst = decode(ctlregs[FLAGS], |
| 70 | pc, | 90 | pc, |
| 71 | c.mem.fetch(pc), | 91 | b.data[pc & memory::LINE_BYTE_OFFSET_MASK], |
| 72 | interrupt); | 92 | interrupt); |
| 73 | auto next_pc = inst.next_pc; | 93 | auto next_pc = inst.next_pc; |
| 74 | 94 | ||
| @@ -84,7 +104,7 @@ void decode_stage::clock() { | |||
| 84 | assert(!inst.need_autoinc_store); | 104 | assert(!inst.need_autoinc_store); |
| 85 | } | 105 | } |
| 86 | 106 | ||
| 87 | pte(b.tr, "", inst.disasm()); | 107 | pte(tr, "", inst.disasm()); |
| 88 | 108 | ||
| 89 | if (inst.need_exec_load) | 109 | if (inst.need_exec_load) |
| 90 | inst.data = c.mem.fetch(inst.final_address.value()); | 110 | inst.data = c.mem.fetch(inst.final_address.value()); |
| @@ -114,6 +134,9 @@ void decode_stage::clock() { | |||
| 114 | 134 | ||
| 115 | assert(inst.next_pc == next_pc || inst.possibly_redirects); | 135 | assert(inst.next_pc == next_pc || inst.possibly_redirects); |
| 116 | pc = inst.next_pc; | 136 | pc = inst.next_pc; |
| 137 | |||
| 138 | if ((b.pc >> memory::LINE_BYTES_LOG2) != (pc >> memory::LINE_BYTES_LOG2)) | ||
| 139 | c.fetch_bundlep.discard(); | ||
| 117 | } | 140 | } |
| 118 | bail_out: | 141 | bail_out: |
| 119 | 142 | ||
| @@ -125,7 +148,7 @@ bail_out: | |||
| 125 | 148 | ||
| 126 | c.checker.execute(); | 149 | c.checker.execute(); |
| 127 | assert(c.checker.icount == icount); | 150 | assert(c.checker.icount == icount); |
| 128 | std::cerr << fmt::format("icount={:} pc={:05o} checkerpc={:05o}\n", icount, pc, c.checker.pc); | 151 | // std::cerr << fmt::format("icount={:} pc={:05o} checkerpc={:05o}\n", icount, pc, c.checker.pc); |
| 129 | assert(pc == c.checker.pc); | 152 | assert(pc == c.checker.pc); |
| 130 | assert(acc == c.checker.acc); | 153 | assert(acc == c.checker.acc); |
| 131 | assert(link == c.checker.link); | 154 | assert(link == c.checker.link); |
diff --git a/uarch/core.h b/uarch/core.h index 0f9be74..a6772f3 100644 --- a/uarch/core.h +++ b/uarch/core.h | |||
| @@ -2,11 +2,14 @@ | |||
| 2 | 2 | ||
| 3 | #include <array> | 3 | #include <array> |
| 4 | 4 | ||
| 5 | #include "infra/arbiter.h" | ||
| 5 | #include "infra/pipetrace.h" | 6 | #include "infra/pipetrace.h" |
| 6 | #include "infra/port.h" | 7 | #include "infra/port.h" |
| 7 | #include "io/model.h" | 8 | #include "io/model.h" |
| 8 | #include "isa/checker.h" | 9 | #include "isa/checker.h" |
| 9 | #include "isa/isa.h" | 10 | #include "isa/isa.h" |
| 11 | #include "memory/cache.h" | ||
| 12 | #include "memory/dram.h" | ||
| 10 | 13 | ||
| 11 | struct core; | 14 | struct core; |
| 12 | 15 | ||
| @@ -14,7 +17,7 @@ struct fetch_bundle { | |||
| 14 | infra::transaction tr; | 17 | infra::transaction tr; |
| 15 | unsigned int gen; | 18 | unsigned int gen; |
| 16 | unsigned int pc; | 19 | unsigned int pc; |
| 17 | unsigned int word; | 20 | memory::line data; |
| 18 | }; | 21 | }; |
| 19 | 22 | ||
| 20 | struct fetch_restart { | 23 | struct fetch_restart { |
| @@ -26,9 +29,12 @@ struct fetch_restart { | |||
| 26 | struct fetch_stage : public infra::sim { | 29 | struct fetch_stage : public infra::sim { |
| 27 | core &c; | 30 | core &c; |
| 28 | 31 | ||
| 32 | memory::inline_cache<8, 2> cache; | ||
| 33 | |||
| 29 | unsigned int gen = 0; | 34 | unsigned int gen = 0; |
| 30 | unsigned int pc; | 35 | unsigned int pc; |
| 31 | bool didrestart = false; | 36 | bool didrestart = false; |
| 37 | bool outstandingfill = false; | ||
| 32 | 38 | ||
| 33 | fetch_stage(core &c); | 39 | fetch_stage(core &c); |
| 34 | 40 | ||
| @@ -49,6 +55,7 @@ struct decode_stage : public infra::sim { | |||
| 49 | std::array<uint_fast32_t, NUM_CTLREGS> ctlregs; | 55 | std::array<uint_fast32_t, NUM_CTLREGS> ctlregs; |
| 50 | std::uint64_t icount; | 56 | std::uint64_t icount; |
| 51 | instruction_context inst; | 57 | instruction_context inst; |
| 58 | bool outstandingfill = false; | ||
| 52 | 59 | ||
| 53 | decode_stage(core &c); | 60 | decode_stage(core &c); |
| 54 | 61 | ||
| @@ -58,11 +65,20 @@ struct decode_stage : public infra::sim { | |||
| 58 | struct core { | 65 | struct core { |
| 59 | iomodel &system; | 66 | iomodel &system; |
| 60 | funcchecker checker; | 67 | funcchecker checker; |
| 61 | funcmem mem; | ||
| 62 | 68 | ||
| 69 | memory::dram mem{12}; | ||
| 70 | infra::port<memory::dram::command> mem_commandp; | ||
| 71 | |||
| 72 | infra::priority_arbiter<memory::dram::command, 2> mem_command_arb; | ||
| 73 | |||
| 74 | infra::port<memory::dram::command> fetch_mem_commandp; | ||
| 75 | infra::port<memory::dram::response> fetch_mem_responsep; | ||
| 63 | infra::port<fetch_bundle> fetch_bundlep; | 76 | infra::port<fetch_bundle> fetch_bundlep; |
| 64 | std::optional<fetch_restart> fetch_restarto; | 77 | std::optional<fetch_restart> fetch_restarto; |
| 65 | 78 | ||
| 79 | infra::port<memory::dram::command> decode_mem_commandp; | ||
| 80 | infra::port<memory::dram::response> decode_mem_responsep; | ||
| 81 | |||
| 66 | // Construction order is execution order within a cycle, so this list should be back-to-front (for zero-cycle restarts) | 82 | // 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}; | 83 | decode_stage decode{*this}; |
| 68 | fetch_stage fetch{*this}; | 84 | fetch_stage fetch{*this}; |
| @@ -70,5 +86,10 @@ struct core { | |||
| 70 | core(iomodel &model) | 86 | core(iomodel &model) |
| 71 | : system(model) | 87 | : system(model) |
| 72 | , checker(model) | 88 | , checker(model) |
| 73 | { } | 89 | { |
| 90 | mem.commandp = &mem_commandp; | ||
| 91 | mem_command_arb.outp = &mem_commandp; | ||
| 92 | mem_command_arb.peerp[0] = &decode_mem_commandp; | ||
| 93 | mem_command_arb.peerp[1] = &fetch_mem_commandp; | ||
| 94 | } | ||
| 74 | }; | 95 | }; |
