xref: /XiangShan/src/main/scala/xiangshan/backend/fu/Fence.scala (revision 2199a01c65d5a7bf503c4b40771336a50a6f1122)
1package xiangshan.backend.fu
2
3import chisel3._
4import chisel3.util._
5import xiangshan._
6import utils._
7import xiangshan.backend.FenceOpType
8
9class FenceToSbuffer extends XSBundle {
10  val flushSb = Output(Bool())
11  val sbIsEmpty = Input(Bool())
12}
13
14// class Fence extends FunctionUnit(FuConfig(
15  // /*FuType.fence, 1, 0, writeIntRf = false, writeFpRf = false, hasRedirect = false,*/ latency = UncertainLatency()
16// )){
17class Fence extends FunctionUnit{ // TODO: check it
18
19  val sfence = IO(Output(new SfenceBundle))
20  val fencei = IO(Output(Bool()))
21  val toSbuffer = IO(new FenceToSbuffer)
22
23  val (valid, src1) = (
24    io.in.valid,
25    io.in.bits.src(0)
26  )
27
28  val s_idle :: s_wait :: s_tlb :: s_icache :: s_fence :: Nil = Enum(5)
29  val state = RegInit(s_idle)
30  /* fsm
31   * s_idle    : init state, send sbflush
32   * s_wait  : send sbflush, wait for sbEmpty
33   * s_tlb   : flush tlb, just hold one cycle
34   * s_icache: flush icache, just hold one cycle
35   * s_fence : do nothing, for timing optimiaztion
36   */
37
38  val sbuffer = toSbuffer.flushSb
39  val sbEmpty = toSbuffer.sbIsEmpty
40  val uop = RegEnable(io.in.bits.uop, io.in.fire())
41  val func = uop.ctrl.fuOpType
42  val lsrc1 = uop.ctrl.lsrc1
43  val lsrc2 = uop.ctrl.lsrc2
44
45  // NOTE: icache & tlb & sbuffer must receive flush signal at any time
46  sbuffer      := state === s_wait
47  fencei       := state === s_icache
48  sfence.valid := state === s_tlb
49  sfence.bits.rs1  := lsrc1 === 0.U
50  sfence.bits.rs2  := lsrc2 === 0.U
51  sfence.bits.addr := RegEnable(src1, io.in.fire())
52
53  when (state === s_idle && valid) { state := s_wait }
54  when (state === s_wait && func === FenceOpType.fencei && sbEmpty) { state := s_icache }
55  when (state === s_wait && func === FenceOpType.sfence && sbEmpty) { state := s_tlb }
56  when (state === s_wait && func === FenceOpType.fence  && sbEmpty) { state := s_fence }
57  when (state =/= s_idle && state =/= s_wait) { state := s_idle }
58
59  io.in.ready := state === s_idle
60  io.out.valid := state =/= s_idle && state =/= s_wait
61  io.out.bits.data := DontCare
62  io.out.bits.uop := uop
63
64  XSDebug(valid, p"In(${io.in.valid} ${io.in.ready}) state:${state} Inpc:0x${Hexadecimal(io.in.bits.uop.cf.pc)} InroqIdx:${io.in.bits.uop.roqIdx}\n")
65  XSDebug(state =/= s_idle, p"state:${state} sbuffer(flush:${sbuffer} empty:${sbEmpty}) fencei:${fencei} sfence:${sfence}\n")
66  XSDebug(io.out.valid, p" Out(${io.out.valid} ${io.out.ready}) state:${state} Outpc:0x${Hexadecimal(io.out.bits.uop.cf.pc)} OutroqIdx:${io.out.bits.uop.roqIdx}\n")
67
68  assert(!(io.out.valid && io.out.bits.uop.ctrl.rfWen))
69  assert(!io.out.valid || io.out.ready, "when fence is out valid, out ready should always be true")
70}