1/*************************************************************************************** 2* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3* 4* XiangShan is licensed under Mulan PSL v2. 5* You can use this software according to the terms and conditions of the Mulan PSL v2. 6* You may obtain a copy of Mulan PSL v2 at: 7* http://license.coscl.org.cn/MulanPSL2 8* 9* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 10* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 11* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 12* 13* See the Mulan PSL v2 for more details. 14***************************************************************************************/ 15 16package xiangshan.backend.fu 17 18import chipsalliance.rocketchip.config.Parameters 19import chisel3._ 20import chisel3.util._ 21import xiangshan._ 22import utils._ 23 24class FenceToSbuffer extends Bundle { 25 val flushSb = Output(Bool()) 26 val sbIsEmpty = Input(Bool()) 27} 28 29class Fence(implicit p: Parameters) extends FunctionUnit with HasExceptionNO { 30 31 val sfence = IO(Output(new SfenceBundle)) 32 val fencei = IO(Output(Bool())) 33 val toSbuffer = IO(new FenceToSbuffer) 34 val disableSfence = IO(Input(Bool())) 35 36 val (valid, src1) = ( 37 io.in.valid, 38 io.in.bits.src(0) 39 ) 40 41 val s_idle :: s_wait :: s_tlb :: s_icache :: s_fence :: Nil = Enum(5) 42 val state = RegInit(s_idle) 43 /* fsm 44 * s_idle : init state, send sbflush 45 * s_wait : send sbflush, wait for sbEmpty 46 * s_tlb : flush tlb, just hold one cycle 47 * s_icache: flush icache, just hold one cycle 48 * s_fence : do nothing, for timing optimiaztion 49 */ 50 51 val sbuffer = toSbuffer.flushSb 52 val sbEmpty = toSbuffer.sbIsEmpty 53 val uop = RegEnable(io.in.bits.uop, io.in.fire()) 54 val func = uop.ctrl.fuOpType 55 56 // NOTE: icache & tlb & sbuffer must receive flush signal at any time 57 sbuffer := state === s_wait && !(func === FenceOpType.sfence && disableSfence) 58 fencei := state === s_icache 59 sfence.valid := state === s_tlb && !disableSfence 60 sfence.bits.rs1 := uop.ctrl.lsrc(0) === 0.U 61 sfence.bits.rs2 := uop.ctrl.lsrc(1) === 0.U 62 sfence.bits.addr := RegEnable(src1, io.in.fire()) 63 64 when (state === s_idle && valid) { state := s_wait } 65 when (state === s_wait && func === FenceOpType.fencei && sbEmpty) { state := s_icache } 66 when (state === s_wait && func === FenceOpType.sfence && (sbEmpty || disableSfence)) { state := s_tlb } 67 when (state === s_wait && func === FenceOpType.fence && sbEmpty) { state := s_fence } 68 when (state =/= s_idle && state =/= s_wait) { state := s_idle } 69 70 io.in.ready := state === s_idle 71 io.out.valid := state =/= s_idle && state =/= s_wait 72 io.out.bits.data := DontCare 73 io.out.bits.uop := uop 74 io.out.bits.uop.cf.exceptionVec(illegalInstr) := uop.cf.exceptionVec(illegalInstr) || (func === FenceOpType.sfence && disableSfence) 75 76 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") 77 XSDebug(state =/= s_idle, p"state:${state} sbuffer(flush:${sbuffer} empty:${sbEmpty}) fencei:${fencei} sfence:${sfence}\n") 78 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") 79 80 assert(!(io.out.valid && io.out.bits.uop.ctrl.rfWen)) 81 assert(!io.out.valid || io.out.ready, "when fence is out valid, out ready should always be true") 82} 83