Skip to content

Commit

Permalink
[ftq] Cleanup generation of flush signals
Browse files Browse the repository at this point in the history
Previously, flush signals from erets were sent too early. This
commit fixes and simplifies that logic by marking ERET insts
as flush_on_commit.

This should also make future optimizations in splitting up
is_unique and flush_on_commit easier. (Currently is_unique <=>
flush_on_commit)
  • Loading branch information
jerryz123 committed Feb 11, 2019
1 parent 04c289d commit 3539c8b
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 31 deletions.
5 changes: 3 additions & 2 deletions src/main/scala/common/consts.scala
Original file line number Diff line number Diff line change
Expand Up @@ -259,8 +259,9 @@ trait ScalarOpConstants
val uopFSQRT_S = 103.U(UOPC_SZ.W)
val uopFSQRT_D = 104.U(UOPC_SZ.W)

val uopSYSTEM = 105.U(UOPC_SZ.W) // pass uop down the CSR pipeline and let it handle it
val uopSFENCE = 106.U(UOPC_SZ.W)
val uopWFI = 105.U(UOPC_SZ.W) // pass uop down the CSR pipeline
val uopERET = 106.U(UOPC_SZ.W) // pass uop down the CSR pipeline, also is ERET
val uopSFENCE = 107.U(UOPC_SZ.W)

// The Bubble Instruction (Machine generated NOP)
// Insert (XOR x0,x0,x0) which is different from software compiler
Expand Down
19 changes: 14 additions & 5 deletions src/main/scala/exu/core.scala
Original file line number Diff line number Diff line change
Expand Up @@ -421,15 +421,26 @@ class BoomCore(implicit p: Parameters, edge: freechips.rocketchip.tilelink.TLEdg

// We must redirect the PC the cycle after playing the SFENCE game.
io.ifu.flush_take_pc := rob.io.flush.valid || RegNext(lsu.io.exe_resp.bits.sfence.valid)
io.ifu.flush_pc := RegNext(csr.io.evec)

// TODO FIX THIS HACK
// The below code works because of two quirks with the flush mechanism
// 1 ) All flush_on_commit instructions are also is_unique,
// In the future, this constraint will be relaxed.
// 2 ) We send out flush signals one cycle after the commit signal. We need to
// mux between one/two cycle delay for the following cases:
// ERETs are reported to the CSR two cycles before we send the flush
// Exceptions are reported to the CSR one cycle before we send the flush
// This discrepency should be resolved elsewhere.
io.ifu.flush_pc := Mux(RegNext(RegNext(csr.io.eret)),
RegNext(RegNext(csr.io.evec)),
RegNext(csr.io.evec))
io.ifu.com_ftq_idx := rob.io.com_xcpt.bits.ftq_idx

io.ifu.clear_fetchbuffer := br_unit.brinfo.mispredict ||
rob.io.flush.valid ||
io.ifu.sfence_take_pc

// TODO is sfence_take_pc correct? Can probably remove it.
io.ifu.flush_info.valid := rob.io.flush.valid || io.ifu.sfence_take_pc
io.ifu.flush_info.valid := rob.io.flush.valid
io.ifu.flush_info.bits := rob.io.flush.bits

// Tell the FTQ it can deallocate entries by passing youngest ftq_idx.
Expand Down Expand Up @@ -1147,8 +1158,6 @@ class BoomCore(implicit p: Parameters, edge: freechips.rocketchip.tilelink.TLEdg
rob.io.lsu_clr_bsy_rob_idx := lsu.io.lsu_clr_bsy_rob_idx
rob.io.lxcpt <> lsu.io.xcpt

rob.io.csr_eret := csr.io.eret

assert (!(csr.io.singleStep), "[core] single-step is unsupported.")

rob.io.bxcpt <> br_unit.xcpt
Expand Down
12 changes: 6 additions & 6 deletions src/main/scala/exu/decode.scala
Original file line number Diff line number Diff line change
Expand Up @@ -219,13 +219,13 @@ object XDecode extends DecodeConstants
CSRRCI -> List(Y, N, X, uopCSRRCI,IQT_INT, FU_CSR , RT_FIX, RT_PAS, RT_X , N, IS_I, N, N, N, N, N, M_X , MT_X , 0.U, N, N, N, N, N, Y, Y, CSR.C),

SFENCE_VMA->List(Y,N, X, uopSFENCE,IQT_MEM, FU_MEM , RT_X , RT_FIX, RT_FIX, N, IS_X, N, N, N, N, N, M_SFENCE,MT_X,0.U, N, N, N, N, N, Y, Y, CSR.N),
SCALL -> List(Y, N, X, uopSYSTEM,IQT_INT, FU_CSR , RT_X , RT_X , RT_X , N, IS_I, N, N, N, N, N, M_X , MT_X , 0.U, N, N, N, N, Y, Y, N, CSR.I),
SBREAK -> List(Y, N, X, uopSYSTEM,IQT_INT, FU_CSR , RT_X , RT_X , RT_X , N, IS_I, N, N, N, N, N, M_X , MT_X , 0.U, N, N, N, N, Y, Y, N, CSR.I),
SRET -> List(Y, N, X, uopSYSTEM,IQT_INT, FU_CSR , RT_X , RT_X , RT_X , N, IS_I, N, N, N, N, N, M_X , MT_X , 0.U, N, N, N, N, N, Y, N, CSR.I),
MRET -> List(Y, N, X, uopSYSTEM,IQT_INT, FU_CSR , RT_X , RT_X , RT_X , N, IS_I, N, N, N, N, N, M_X , MT_X , 0.U, N, N, N, N, N, Y, N, CSR.I),
DRET -> List(Y, N, X, uopSYSTEM,IQT_INT, FU_CSR , RT_X , RT_X , RT_X , N, IS_I, N, N, N, N, N, M_X , MT_X , 0.U, N, N, N, N, N, Y, N, CSR.I),
SCALL -> List(Y, N, X, uopERET ,IQT_INT, FU_CSR , RT_X , RT_X , RT_X , N, IS_I, N, N, N, N, N, M_X , MT_X , 0.U, N, N, N, N, Y, Y, Y, CSR.I),
SBREAK -> List(Y, N, X, uopERET ,IQT_INT, FU_CSR , RT_X , RT_X , RT_X , N, IS_I, N, N, N, N, N, M_X , MT_X , 0.U, N, N, N, N, Y, Y, Y, CSR.I),
SRET -> List(Y, N, X, uopERET ,IQT_INT, FU_CSR , RT_X , RT_X , RT_X , N, IS_I, N, N, N, N, N, M_X , MT_X , 0.U, N, N, N, N, N, Y, Y, CSR.I),
MRET -> List(Y, N, X, uopERET ,IQT_INT, FU_CSR , RT_X , RT_X , RT_X , N, IS_I, N, N, N, N, N, M_X , MT_X , 0.U, N, N, N, N, N, Y, Y, CSR.I),
DRET -> List(Y, N, X, uopERET ,IQT_INT, FU_CSR , RT_X , RT_X , RT_X , N, IS_I, N, N, N, N, N, M_X , MT_X , 0.U, N, N, N, N, N, Y, Y, CSR.I),

WFI -> List(Y, N, X, uopSYSTEM,IQT_INT, FU_CSR , RT_X , RT_X , RT_X , N, IS_X, N, N, N, N, N, M_X , MT_X , 0.U, N, N, N, N, N, Y, Y, CSR.I),
WFI -> List(Y, N, X, uopWFI ,IQT_INT, FU_CSR , RT_X , RT_X , RT_X , N, IS_X, N, N, N, N, N, M_X , MT_X , 0.U, N, N, N, N, N, Y, Y, CSR.I),

FENCE_I -> List(Y, N, X, uopNOP , IQT_INT, FU_X , RT_X , RT_X , RT_X , N, IS_X, N, N, N, N, Y, M_X , MT_X , 0.U, N, N, N, N, N, Y, Y, CSR.N),
FENCE -> List(Y, N, X, uopFENCE, IQT_INT, FU_MEM , RT_X , RT_X , RT_X , N, IS_X, N, Y, N, Y, N, M_X , MT_X , 0.U, N, N, N, N, N, Y, Y, CSR.N), // TODO PERF make fence higher performance
Expand Down
3 changes: 2 additions & 1 deletion src/main/scala/exu/fudecode.scala
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,8 @@ object CsrRRdDecode extends RRdDecodeConstants
BitPat(uopCSRRSI)-> List(BR_N , Y, N, N, FN_ADD , DW_XPR, OP1_ZERO, OP2_IMMC, IS_I, REN_1, CSR.S),
BitPat(uopCSRRCI)-> List(BR_N , Y, N, N, FN_ADD , DW_XPR, OP1_ZERO, OP2_IMMC, IS_I, REN_1, CSR.C),

BitPat(uopSYSTEM)-> List(BR_N , Y, N, N, FN_ADD , DW_XPR, OP1_ZERO, OP2_IMMC, IS_I, REN_0, CSR.I))
BitPat(uopWFI) -> List(BR_N , Y, N, N, FN_ADD , DW_XPR, OP1_ZERO, OP2_IMMC, IS_I, REN_0, CSR.I),
BitPat(uopERET) -> List(BR_N , Y, N, N, FN_ADD , DW_XPR, OP1_ZERO, OP2_IMMC, IS_I, REN_0, CSR.I))
}

object FpuRRdDecode extends RRdDecodeConstants
Expand Down
38 changes: 22 additions & 16 deletions src/main/scala/exu/rob.scala
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ class RobIo(

// Communicate exceptions to the CSRFile
val com_xcpt = Valid(new CommitExceptionSignals())
val csr_eret = Input(Bool())

// Let the CSRFile stall us (e.g., wfi).
val csr_stall = Input(Bool())
Expand Down Expand Up @@ -535,27 +534,34 @@ class Rob(
rob_head_vals.reduce(_|_) && PriorityMux(rob_head_vals, io.commit.uops.map{u => u.is_sys_pc2epc})

val refetch_inst = exception_thrown || insn_sys_pc2epc
io.com_xcpt.bits.ftq_idx := PriorityMux(rob_head_vals, io.commit.uops.map{u => u.ftq_idx})
io.com_xcpt.bits.edge_inst := PriorityMux(rob_head_vals, io.commit.uops.map{u => u.edge_inst})
io.com_xcpt.bits.is_rvc := PriorityMux(rob_head_vals, io.commit.uops.map{u => u.is_rvc})
io.com_xcpt.bits.pc_lob := PriorityMux(rob_head_vals, io.commit.uops.map{u => u.pc_lob})
val com_xcpt_uop = PriorityMux(rob_head_vals, io.commit.uops)
io.com_xcpt.bits.ftq_idx := com_xcpt_uop.ftq_idx
io.com_xcpt.bits.edge_inst := com_xcpt_uop.edge_inst
io.com_xcpt.bits.is_rvc := com_xcpt_uop.is_rvc
io.com_xcpt.bits.pc_lob := com_xcpt_uop.pc_lob

val flush_val =
exception_thrown ||
io.csr_eret ||
(Range(0,width).map{i => io.commit.valids(i) && io.commit.uops(i).flush_on_commit}).reduce(_|_)
val flush_commit_mask = Range(0,width).map{i => io.commit.valids(i) && io.commit.uops(i).flush_on_commit}
val flush_commit = flush_commit_mask.reduce(_|_)
val flush_val = exception_thrown || flush_commit

assert(!(PopCount(flush_commit_mask) > 1.U),
"[rob] Can't commit multiple flush_on_commit instructions on one cycle")

val flush_uop = Mux(exception_thrown, com_xcpt_uop, Mux1H(flush_commit_mask, io.commit.uops))

// delay a cycle for critical path considerations
io.flush.valid := RegNext(flush_val, init=false.B)
io.flush.bits.ftq_idx := RegNext(io.com_xcpt.bits.ftq_idx)
io.flush.bits.pc_lob := RegNext(io.com_xcpt.bits.pc_lob)
io.flush.bits.edge_inst := RegNext(io.com_xcpt.bits.edge_inst)
io.flush.bits.is_rvc := RegNext(io.com_xcpt.bits.is_rvc)
io.flush.bits.flush_typ :=
RegNext(FlushTypes.getType(flush_val, io.com_xcpt.valid, io.csr_eret, refetch_inst))
io.flush.bits.ftq_idx := RegNext(flush_uop.ftq_idx)
io.flush.bits.pc_lob := RegNext(flush_uop.pc_lob)
io.flush.bits.edge_inst := RegNext(flush_uop.edge_inst)
io.flush.bits.is_rvc := RegNext(flush_uop.is_rvc)
io.flush.bits.flush_typ := RegNext(FlushTypes.getType(flush_val,
exception_thrown && !is_mini_exception,
flush_commit && flush_uop.uopc === uopERET,
refetch_inst))

val com_lsu_misspec = RegNext(exception_thrown && io.com_xcpt.bits.cause === MINI_EXCEPTION_MEM_ORDERING)
assert (!(com_lsu_misspec && !io.flush.valid), "[rob] pipeline flush not be excercised during a LSU misspeculation")
assert (!(com_lsu_misspec && !io.flush.valid), "[rob] pipeline flush not be exercised during a LSU misspeculation")

// -----------------------------------------------
// FP Exceptions
Expand Down
3 changes: 2 additions & 1 deletion src/main/scala/ifu/fetchtargetqueue.scala
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,8 @@ class FetchTargetQueue(num_entries: Int)(implicit p: Parameters) extends BoomMod
- Mux(io.flush.bits.edge_inst, 2.U, 0.U))
com_pc_next := com_pc + Mux(io.flush.bits.is_rvc, 2.U, 4.U)

assert (RegNext(io.com_ftq_idx) === io.flush.bits.ftq_idx, "[ftq] this code depends on this assumption")
assert (!(io.flush.valid && RegNext(io.com_ftq_idx) =/= io.flush.bits.ftq_idx),
"[ftq] this code depends on this assumption")

//-------------------------------------------------------------
// **** Printfs ****
Expand Down

0 comments on commit 3539c8b

Please sign in to comment.