From 745e9b9261b3b4aad23d48c74b0ace905853e667 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Fri, 11 Dec 2020 16:43:36 -0800 Subject: [PATCH 1/2] Handle gemmini exceptions through the return value of gemmini instructions --- SPIKE.hash | 2 +- software/gemmini-rocc-tests | 2 +- src/main/scala/gemmini/Controller.scala | 56 +++++++++++++----------- src/main/scala/gemmini/FrontendTLB.scala | 32 ++++++++------ src/main/scala/gemmini/GemminiISA.scala | 2 + 5 files changed, 53 insertions(+), 41 deletions(-) diff --git a/SPIKE.hash b/SPIKE.hash index 1d05e3ee..df14dfbe 100644 --- a/SPIKE.hash +++ b/SPIKE.hash @@ -1 +1 @@ -8626fb144e019895767830d850deca7711773e5c +3db7a449d97bf40a101ef541089054e6af59d7df \ No newline at end of file diff --git a/software/gemmini-rocc-tests b/software/gemmini-rocc-tests index 89f9aef3..e7828585 160000 --- a/software/gemmini-rocc-tests +++ b/software/gemmini-rocc-tests @@ -1 +1 @@ -Subproject commit 89f9aef3b1f94cd27592ec07ee8a0e087045e999 +Subproject commit e78285855f254a7cec56ed9219d933226ea50260 diff --git a/src/main/scala/gemmini/Controller.scala b/src/main/scala/gemmini/Controller.scala index 4d06ab7e..5983e871 100644 --- a/src/main/scala/gemmini/Controller.scala +++ b/src/main/scala/gemmini/Controller.scala @@ -126,8 +126,6 @@ class GemminiModule[T <: Data: Arithmetic, U <: Data, V <: Data] implicit val edge = outer.node.edges.out.head val tlb = Module(new FrontendTLB(2, tlb_size, dma_maxbytes)) (tlb.io.clients zip outer.spad.module.io.tlb).foreach(t => t._1 <> t._2) - tlb.io.exp.flush_skip := false.B - tlb.io.exp.flush_retry := false.B io.ptw.head <> tlb.io.ptw /*io.ptw.head.req <> tlb.io.ptw.req @@ -137,7 +135,7 @@ class GemminiModule[T <: Data: Arithmetic, U <: Data, V <: Data] tlb.io.ptw.pmp := io.ptw.head.pmp tlb.io.ptw.customCSRs := io.ptw.head.customCSRs*/ - spad.module.io.flush := tlb.io.exp.flush() + spad.module.io.flush := tlb.io.exp.flush /* //========================================================================= @@ -181,7 +179,30 @@ class GemminiModule[T <: Data: Arithmetic, U <: Data, V <: Data] // Incoming commands and ROB val rob = Module(new ROB(new RoCCCommand, rob_entries, local_addr_t, meshRows*tileRows, meshColumns*tileColumns)) - val raw_cmd = Queue(io.cmd) + val raw_cmd_q = Module(new Queue(new RoCCCommand, 2)) + val fence_stall = io.cmd.bits.inst.funct === FENCE_CMD && io.busy + raw_cmd_q.io.enq.valid := io.cmd.valid && io.resp.ready && !fence_stall + raw_cmd_q.io.enq.bits := io.cmd.bits + + io.resp.valid := io.cmd.valid && raw_cmd_q.io.enq.ready && !fence_stall + io.resp.bits.rd := io.cmd.bits.inst.rd + io.resp.bits.data := 0.U + + io.cmd.ready := io.resp.ready && raw_cmd_q.io.enq.ready && !fence_stall + + // When TLB is busy with exception, don't enqueue new instructions, instead use RD to pass back exception info + when (tlb.io.exp.interrupt) { + io.cmd.ready := true.B + raw_cmd_q.io.enq.valid := false.B + io.resp.valid := io.cmd.valid + io.resp.bits.data := tlb.io.exp.vaddr + } + + tlb.io.exp.flush := io.cmd.fire() && io.cmd.bits.inst.funct === FLUSH_CMD + + + + val raw_cmd = raw_cmd_q.io.deq // val (compressed_cmd, compressor_busy) = InstCompressor(unrolled_cmd) // compressed_cmd.ready := false.B @@ -361,8 +382,8 @@ class GemminiModule[T <: Data: Arithmetic, U <: Data, V <: Data] rob_completed_arb.io.out.ready := true.B // Wire up global RoCC signals - io.busy := raw_cmd.valid || loop_unroller_busy || rob.io.busy || spad.module.io.busy - io.interrupt := tlb.io.exp.interrupt + io.busy := (raw_cmd.valid || loop_unroller_busy || rob.io.busy || spad.module.io.busy) && !tlb.io.exp.interrupt + io.interrupt := false.B rob.io.solitary_preload := ex_controller.io.solitary_preload @@ -415,32 +436,15 @@ class GemminiModule[T <: Data: Arithmetic, U <: Data, V <: Data] val risc_funct = unrolled_cmd.bits.inst.funct val is_flush = risc_funct === FLUSH_CMD + val is_fence = risc_funct === FENCE_CMD /* val is_load = (funct === LOAD_CMD) || (funct === CONFIG_CMD && config_cmd_type === CONFIG_LOAD) val is_store = (funct === STORE_CMD) || (funct === CONFIG_CMD && config_cmd_type === CONFIG_STORE) val is_ex = (funct === COMPUTE_AND_FLIP_CMD || funct === COMPUTE_AND_STAY_CMD || funct === PRELOAD_CMD) || (funct === CONFIG_CMD && config_cmd_type === CONFIG_EX) */ - - when (is_flush) { - // val skip = compressed_cmd.bits.rs1(0) - val skip = unrolled_cmd.bits.rs1(0) - tlb.io.exp.flush_skip := skip - tlb.io.exp.flush_retry := !skip - - // compressed_cmd.ready := true.B // TODO should we wait for an acknowledgement from the TLB? - unrolled_cmd.ready := true.B // TODO should we wait for an acknowledgement from the TLB? - } - - .otherwise { - rob.io.alloc.valid := true.B - - when(rob.io.alloc.fire()) { - // compressed_cmd.ready := true.B - unrolled_cmd.ready := true.B - } - } - + unrolled_cmd.ready := is_fence || is_flush || rob.io.alloc.ready + rob.io.alloc.valid := !is_flush && !is_fence } /* diff --git a/src/main/scala/gemmini/FrontendTLB.scala b/src/main/scala/gemmini/FrontendTLB.scala index 29ac0d2f..0660af4d 100644 --- a/src/main/scala/gemmini/FrontendTLB.scala +++ b/src/main/scala/gemmini/FrontendTLB.scala @@ -18,11 +18,12 @@ class DecoupledTLBReq(val lgMaxSize: Int)(implicit p: Parameters) extends CoreBu } class TLBExceptionIO extends Bundle { + // interrupt means we are stalling loads and stores until a gemmini_flush command is received val interrupt = Output(Bool()) - val flush_retry = Input(Bool()) - val flush_skip = Input(Bool()) + // vaddr of faulting inst. LSB indicates is_Store + val vaddr = Output(UInt(64.W)) - def flush(dummy: Int = 0): Bool = flush_retry || flush_skip + val flush = Input(Bool()) } @@ -33,7 +34,7 @@ class DecoupledTLB(entries: Int, maxSize: Int)(implicit edge: TLEdgeOut, p: Para val lgMaxSize = log2Ceil(maxSize) val io = new Bundle { - val req = Flipped(Valid(new DecoupledTLBReq(lgMaxSize))) + val req = Flipped(Decoupled(new DecoupledTLBReq(lgMaxSize))) val resp = new TLBResp val ptw = new TLBPTWIO @@ -41,7 +42,11 @@ class DecoupledTLB(entries: Int, maxSize: Int)(implicit edge: TLEdgeOut, p: Para } val interrupt = RegInit(false.B) + val interrupt_vaddr = Reg(UInt(64.W)) io.exp.interrupt := interrupt + io.exp.vaddr := interrupt_vaddr + + io.req.ready := !interrupt val tlb = Module(new TLB(false, lgMaxSize, TLBConfig(entries))) tlb.io.req.valid := io.req.valid @@ -49,7 +54,7 @@ class DecoupledTLB(entries: Int, maxSize: Int)(implicit edge: TLEdgeOut, p: Para io.resp := tlb.io.resp tlb.io.kill := false.B - tlb.io.sfence.valid := io.exp.flush() + tlb.io.sfence.valid := io.exp.flush tlb.io.sfence.bits.rs1 := false.B tlb.io.sfence.bits.rs2 := false.B tlb.io.sfence.bits.addr := DontCare @@ -57,13 +62,16 @@ class DecoupledTLB(entries: Int, maxSize: Int)(implicit edge: TLEdgeOut, p: Para io.ptw <> tlb.io.ptw tlb.io.ptw.status := io.req.bits.status - val exception = io.req.valid && Mux(io.req.bits.tlb_req.cmd === M_XRD, tlb.io.resp.pf.ld || tlb.io.resp.ae.ld, tlb.io.resp.pf.st || tlb.io.resp.ae.st) - when (exception) { interrupt := true.B } + val xcpt_ld = io.req.valid && (io.req.bits.tlb_req.cmd === M_XRD) && (tlb.io.resp.pf.ld || tlb.io.resp.ae.ld) + val xcpt_st = io.req.valid && (io.req.bits.tlb_req.cmd === M_XWR) && (tlb.io.resp.pf.st || tlb.io.resp.ae.st) + when (!interrupt && (xcpt_ld || xcpt_st)) { + interrupt := true.B + interrupt_vaddr := Cat(tlb.io.req.bits.vaddr >> 1, xcpt_st) + + } when (interrupt && tlb.io.sfence.fire()) { interrupt := false.B } - - assert(!io.exp.flush_retry || !io.exp.flush_skip, "TLB: flushing with both retry and skip at same time") } class FrontendTLBIO(implicit p: Parameters) extends CoreBundle { @@ -84,9 +92,7 @@ class FrontendTLB(nClients: Int, entries: Int, maxSize: Int) val lgMaxSize = log2Ceil(coreDataBytes) val tlbArb = Module(new RRArbiter(new DecoupledTLBReq(lgMaxSize), nClients)) val tlb = Module(new DecoupledTLB(entries, maxSize)) - tlb.io.req.valid := tlbArb.io.out.valid - tlb.io.req.bits := tlbArb.io.out.bits - tlbArb.io.out.ready := true.B + tlb.io.req <> tlbArb.io.out io.ptw <> tlb.io.ptw io.exp <> tlb.io.exp @@ -105,7 +111,7 @@ class FrontendTLB(nClients: Int, entries: Int, maxSize: Int) last_translated_vpn := req.bits.tlb_req.vaddr last_translated_ppn := tlb.io.resp.paddr } - when (io.exp.flush()) { + when (io.exp.flush) { last_translated_valid := false.B } diff --git a/src/main/scala/gemmini/GemminiISA.scala b/src/main/scala/gemmini/GemminiISA.scala index 91b30a21..b799f8ce 100644 --- a/src/main/scala/gemmini/GemminiISA.scala +++ b/src/main/scala/gemmini/GemminiISA.scala @@ -22,6 +22,8 @@ object GemminiISA { val LOAD3_CMD = 14.U + val FENCE_CMD = 127.U + // rs1[2:0] values val CONFIG_EX = 0.U val CONFIG_LOAD = 1.U From 3b92596e5375e36a258a6ec0c4a547c4ce1b9609 Mon Sep 17 00:00:00 2001 From: Jerry Zhao Date: Thu, 17 Dec 2020 10:15:09 -0800 Subject: [PATCH 2/2] Bump gemmini-rocc-tests --- software/gemmini-rocc-tests | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/software/gemmini-rocc-tests b/software/gemmini-rocc-tests index e7828585..bf934460 160000 --- a/software/gemmini-rocc-tests +++ b/software/gemmini-rocc-tests @@ -1 +1 @@ -Subproject commit e78285855f254a7cec56ed9219d933226ea50260 +Subproject commit bf934460b1addc96ebbf50ab4574a4dc46959703