Fence.scala 2.7 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)

L
LinJiawei 已提交
23 24 25 26 27 28 29 30
  val (valid, src1, uop, func, lsrc1, lsrc2) = (
    io.in.valid,
    io.in.bits.src(0),
    io.in.bits.uop,
    io.in.bits.uop.ctrl.fuOpType,
    io.in.bits.uop.ctrl.lsrc1,
    io.in.bits.uop.ctrl.lsrc2
  )
A
Allen 已提交
31

32
  val s_sb :: s_tlb :: s_icache :: s_none :: Nil = Enum(4)
33
  val state = RegInit(s_sb)
A
Allen 已提交
34

L
LinJiawei 已提交
35 36 37
  val sbuffer = toSbuffer.flushSb
  val sbEmpty = toSbuffer.sbIsEmpty

38
  // NOTE: icache & tlb & sbuffer must receive flush signal at any time
39 40 41 42 43 44 45 46 47
  sbuffer      := valid && state === s_sb && !sbEmpty
  fencei       := (state === s_icache && sbEmpty) || (state === s_sb && valid && sbEmpty && func === FenceOpType.fencei)
  sfence.valid := (state === s_tlb && sbEmpty) || (state === s_sb && valid && sbEmpty && func === FenceOpType.sfence)
  sfence.bits.rs1  := Mux(state === s_sb, lsrc1 === 0.U, RegEnable(lsrc1 === 0.U, io.in.fire()))
  sfence.bits.rs2  := Mux(state === s_sb, lsrc2 === 0.U, RegEnable(lsrc2 === 0.U, io.in.fire()))
  sfence.bits.addr := Mux(state === s_sb, src1,          RegEnable(src1, io.in.fire()))

  when (state === s_sb && valid && func === FenceOpType.fencei && !sbEmpty) { state := s_icache }
  when (state === s_sb && valid && func === FenceOpType.sfence && !sbEmpty) { state := s_tlb }
48
  when (state === s_sb && valid && func === FenceOpType.fence  && !sbEmpty) { state := s_none }
49
  when (state =/= s_sb && sbEmpty) { state := s_sb }
50 51

  assert(!(io.out.valid && io.out.bits.uop.ctrl.rfWen))
52 53
  io.in.ready := state === s_sb
  io.out.valid := (state =/= s_sb && sbEmpty) || (state === s_sb && sbEmpty && valid)
54
  io.out.bits.data := DontCare
55
  io.out.bits.uop := Mux(state === s_sb, uop, RegEnable(uop, io.in.fire()))
Z
ZhangZifei 已提交
56

57 58 59
  assert(!(valid || state =/= s_sb) || io.out.ready) // NOTE: fence instr must be the first(only one) instr, so io.out.ready must be true

  XSDebug(valid || state=/=s_sb || io.out.valid, p"In(${io.in.valid} ${io.in.ready}) Out(${io.out.valid} ${io.out.ready}) state:${state} 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")
Z
ZhangZifei 已提交
60
}