xref: /XiangShan/src/main/scala/xiangshan/backend/fu/Fence.scala (revision 45a56a299b9533c4400bfe2945c10900485d9402)
1package xiangshan.backend.exu
2
3import chisel3._
4import chisel3.util._
5import xiangshan._
6import utils._
7import chisel3.util.experimental.BoringUtils
8
9import xiangshan.backend.MDUOpType
10
11class FenceExeUnit extends Exu(Exu.fenceExeUnitCfg) {
12  val (valid, src1, src2, uop, func, lsrc1, lsrc2) =
13    (io.in.valid, io.in.bits.src1, io.in.bits.src2, io.in.bits.uop, io.in.bits.uop.ctrl.fuOpType, io.in.bits.uop.ctrl.lsrc1, io.in.bits.uop.ctrl.lsrc2)
14
15  val s_req :: s_resp :: Nil = Enum(2)
16  val state = RegInit(s_req)
17
18  val sfence  = WireInit(0.U.asTypeOf(new SfenceBundle))
19  val sbuffer = WireInit(false.B)
20  val fencei  = WireInit(false.B)
21  val sbEmpty = WireInit(false.B)
22  BoringUtils.addSource(sbuffer, "FenceUnitSbufferFlush")
23  BoringUtils.addSource(sfence, "SfenceBundle")
24  // BoringUtils.addSource(fencei,  "FenceI") // TODO: uncomment it when merge icache
25  BoringUtils.addSink(sbEmpty, "SBufferEmpty")
26  // NOTE: icache & tlb & sbuffer must receive flush signal at any time
27  sbuffer      := valid && state === s_req && !sbEmpty
28  fencei       := valid && state === s_req && func === MDUOpType.fencei
29  sfence.valid := valid && state === s_req && func === MDUOpType.sfence
30  sfence.bits.rs1  := lsrc1 === 0.U
31  sfence.bits.rs2  := lsrc2 === 0.U
32  sfence.bits.addr := src1
33
34  switch (state) {
35    is (s_req) { // send all the flush at s_req
36      when (valid && (!sbEmpty || !io.out.ready)) { state := s_resp }
37    }
38    is (s_resp) { // wait for sbEmpty if send flush to sbuffer
39      when (sbEmpty && io.out.ready) { state := s_req }
40    }
41  }
42
43  assert(!(io.out.valid && io.out.bits.uop.ctrl.rfWen))
44  io.in.ready := state === s_req
45  io.out.valid := (state === s_resp && sbEmpty) || (state === s_req && sbEmpty && valid)
46  io.out.bits.data := DontCare
47  io.out.bits.uop := Mux(state === s_req, uop, RegEnable(uop, io.in.fire()))
48  io.out.bits.redirect <> DontCare
49  io.out.bits.redirectValid := false.B
50  io.out.bits.debug <> DontCare
51
52  XSDebug(valid || state=/=s_resp, p"In(${io.in.valid} ${io.in.ready}) Out(${io.out.valid} ${io.out.ready}) sbuffer(flush:${sbuffer} empty:${sbEmpty}) fencei:${fencei} sfence:${sfence} Inpc:0x${Hexadecimal(io.in.bits.uop.cf.pc)} InroqIdx:${io.in.bits.uop.roqIdx} Outpc:0x${Hexadecimal(io.out.bits.uop.cf.pc)} OutroqIdx:${io.out.bits.uop.roqIdx}\n")
53}