1package xiangshan.backend.fu 2 3import chipsalliance.rocketchip.config.Parameters 4import chisel3._ 5import chisel3.util._ 6import xiangshan._ 7import utils._ 8 9class FenceToSbuffer extends Bundle { 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(implicit p: Parameters) 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 43 // NOTE: icache & tlb & sbuffer must receive flush signal at any time 44 sbuffer := state === s_wait 45 fencei := state === s_icache 46 sfence.valid := state === s_tlb 47 sfence.bits.rs1 := uop.ctrl.lsrc(0) === 0.U 48 sfence.bits.rs2 := uop.ctrl.lsrc(1) === 0.U 49 sfence.bits.addr := RegEnable(src1, io.in.fire()) 50 51 when (state === s_idle && valid) { state := s_wait } 52 when (state === s_wait && func === FenceOpType.fencei && sbEmpty) { state := s_icache } 53 when (state === s_wait && func === FenceOpType.sfence && sbEmpty) { state := s_tlb } 54 when (state === s_wait && func === FenceOpType.fence && sbEmpty) { state := s_fence } 55 when (state =/= s_idle && state =/= s_wait) { state := s_idle } 56 57 io.in.ready := state === s_idle 58 io.out.valid := state =/= s_idle && state =/= s_wait 59 io.out.bits.data := DontCare 60 io.out.bits.uop := uop 61 62 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") 63 XSDebug(state =/= s_idle, p"state:${state} sbuffer(flush:${sbuffer} empty:${sbEmpty}) fencei:${fencei} sfence:${sfence}\n") 64 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") 65 66 assert(!(io.out.valid && io.out.bits.uop.ctrl.rfWen)) 67 assert(!io.out.valid || io.out.ready, "when fence is out valid, out ready should always be true") 68} 69