Fence.scala 2.6 KB
Newer Older
L
LinJiawei 已提交
1
package xiangshan.backend.fu
A
Allen 已提交
2 3 4 5 6

import chisel3._
import chisel3.util._
import xiangshan._
import utils._
7
import xiangshan.backend.FenceOpType
A
Allen 已提交
8

L
LinJiawei 已提交
9 10 11 12 13
class FenceToSbuffer extends XSBundle {
  val flushSb = Output(Bool())
  val sbIsEmpty = Input(Bool())
}

Z
ZhangZifei 已提交
14 15 16 17
// class Fence extends FunctionUnit(FuConfig(
  // /*FuType.fence, 1, 0, writeIntRf = false, writeFpRf = false, hasRedirect = false,*/ latency = UncertainLatency()
// )){
class Fence extends FunctionUnit{ // TODO: check it
L
LinJiawei 已提交
18 19 20 21 22

  val sfence = IO(Output(new SfenceBundle))
  val fencei = IO(Output(Bool()))
  val toSbuffer = IO(new FenceToSbuffer)

23
  val (valid, src1) = (
L
LinJiawei 已提交
24
    io.in.valid,
25
    io.in.bits.src(0)
L
LinJiawei 已提交
26
  )
A
Allen 已提交
27

28 29 30 31 32 33 34 35 36
  val s_idle :: s_wait :: s_tlb :: s_icache :: s_fence :: Nil = Enum(5)
  val state = RegInit(s_idle)
  /* fsm
   * s_idle    : init state, send sbflush
   * s_wait  : send sbflush, wait for sbEmpty
   * s_tlb   : flush tlb, just hold one cycle
   * s_icache: flush icache, just hold one cycle
   * s_fence : do nothing, for timing optimiaztion
   */
A
Allen 已提交
37

L
LinJiawei 已提交
38 39
  val sbuffer = toSbuffer.flushSb
  val sbEmpty = toSbuffer.sbIsEmpty
40 41 42 43
  val uop = RegEnable(io.in.bits.uop, io.in.fire())
  val func = uop.ctrl.fuOpType
  val lsrc1 = uop.ctrl.lsrc1
  val lsrc2 = uop.ctrl.lsrc2
L
LinJiawei 已提交
44

45
  // NOTE: icache & tlb & sbuffer must receive flush signal at any time
46 47 48 49 50 51
  sbuffer      := state === s_wait
  fencei       := state === s_icache
  sfence.valid := state === s_tlb
  sfence.bits.rs1  := lsrc1 === 0.U
  sfence.bits.rs2  := lsrc2 === 0.U
  sfence.bits.addr := RegEnable(src1, io.in.fire())
52

53 54 55 56 57 58 59 60
  when (state === s_idle && valid) { state := s_wait }
  when (state === s_wait && func === FenceOpType.fencei && sbEmpty) { state := s_icache }
  when (state === s_wait && func === FenceOpType.sfence && sbEmpty) { state := s_tlb }
  when (state === s_wait && func === FenceOpType.fence  && sbEmpty) { state := s_fence }
  when (state =/= s_idle && state =/= s_wait) { state := s_idle }

  io.in.ready := state === s_idle
  io.out.valid := state =/= s_idle && state =/= s_wait
61
  io.out.bits.data := DontCare
62
  io.out.bits.uop := uop
Z
ZhangZifei 已提交
63

64 65 66
  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")
  XSDebug(state =/= s_idle, p"state:${state} sbuffer(flush:${sbuffer} empty:${sbEmpty}) fencei:${fencei} sfence:${sfence}\n")
  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 69
  assert(!(io.out.valid && io.out.bits.uop.ctrl.rfWen))
  assert(!io.out.valid || io.out.ready, "when fence is out valid, out ready should always be true")
Z
ZhangZifei 已提交
70
}