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, uop, func, lsrc1, lsrc2) = ( 24 io.in.valid, 25 io.in.bits.src(0), 26 io.in.bits.uop, 27 io.in.bits.uop.ctrl.fuOpType, 28 io.in.bits.uop.ctrl.lsrc1, 29 io.in.bits.uop.ctrl.lsrc2 30 ) 31 32 val s_sb :: s_tlb :: s_icache :: s_none :: Nil = Enum(4) 33 val state = RegInit(s_sb) 34 35 val sbuffer = toSbuffer.flushSb 36 val sbEmpty = toSbuffer.sbIsEmpty 37 38 // NOTE: icache & tlb & sbuffer must receive flush signal at any time 39 sbuffer := valid && state === s_sb && !sbEmpty 40 fencei := (state === s_icache && sbEmpty) || (state === s_sb && valid && sbEmpty && func === FenceOpType.fencei) 41 sfence.valid := (state === s_tlb && sbEmpty) || (state === s_sb && valid && sbEmpty && func === FenceOpType.sfence) 42 sfence.bits.rs1 := Mux(state === s_sb, lsrc1 === 0.U, RegEnable(lsrc1 === 0.U, io.in.fire())) 43 sfence.bits.rs2 := Mux(state === s_sb, lsrc2 === 0.U, RegEnable(lsrc2 === 0.U, io.in.fire())) 44 sfence.bits.addr := Mux(state === s_sb, src1, RegEnable(src1, io.in.fire())) 45 46 when (state === s_sb && valid && func === FenceOpType.fencei && !sbEmpty) { state := s_icache } 47 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 io.in.ready := state === s_sb 53 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())) 56 57 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 58 59 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") 60}