1/*************************************************************************************** 2* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences 3* Copyright (c) 2020-2021 Peng Cheng Laboratory 4* 5* XiangShan is licensed under Mulan PSL v2. 6* You can use this software according to the terms and conditions of the Mulan PSL v2. 7* You may obtain a copy of Mulan PSL v2 at: 8* http://license.coscl.org.cn/MulanPSL2 9* 10* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, 11* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, 12* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. 13* 14* See the Mulan PSL v2 for more details. 15***************************************************************************************/ 16 17package xiangshan.backend.fu 18 19import org.chipsalliance.cde.config.Parameters 20import chisel3._ 21import chisel3.util._ 22import utils._ 23import utility._ 24import xiangshan.ExceptionNO.{illegalInstr, virtualInstr} 25import xiangshan._ 26 27class FenceIO(implicit p: Parameters) extends XSBundle { 28 val sfence = Output(new SfenceBundle) 29 val fencei = Output(Bool()) 30 val sbuffer = new FenceToSbuffer 31 val disableSfence = Input(Bool()) 32 val disableHfenceg = Input(Bool()) 33 val disableHfencev = Input(Bool()) 34 val virtMode = Input(Bool()) 35} 36 37class FenceToSbuffer extends Bundle { 38 val flushSb = Output(Bool()) 39 val sbIsEmpty = Input(Bool()) 40} 41 42class Fence(cfg: FuConfig)(implicit p: Parameters) extends FuncUnit(cfg) { 43 44 val sfence = io.fenceio.get.sfence 45 val fencei = io.fenceio.get.fencei 46 val toSbuffer = io.fenceio.get.sbuffer 47 val disableSfence = io.fenceio.get.disableSfence 48 val disableHfenceg = io.fenceio.get.disableHfenceg 49 val disableHfencev = io.fenceio.get.disableHfencev 50 val virtMode = io.fenceio.get.virtMode 51 val (valid, src1) = ( 52 io.in.valid, 53 io.in.bits.data.src(0) 54 ) 55 56 val s_idle :: s_wait :: s_tlb :: s_icache :: s_fence :: s_nofence :: Nil = Enum(6) 57 58 val state = RegInit(s_idle) 59 /* fsm 60 * s_idle : init state, send sbflush 61 * s_wait : send sbflush, wait for sbEmpty 62 * s_tlb : flush tlb, just hold one cycle 63 * s_icache: flush icache, just hold one cycle 64 * s_fence : do nothing, for timing optimiaztion 65 * s_nofence: do nothing , for Svinval extension 66 */ 67 68 val sbuffer = toSbuffer.flushSb 69 val sbEmpty = toSbuffer.sbIsEmpty 70 val uop = RegEnable(io.in.bits, io.in.fire) 71 val func = uop.ctrl.fuOpType 72 73 // NOTE: icache & tlb & sbuffer must receive flush signal at any time 74 sbuffer := state === s_wait && !(func === FenceOpType.sfence && disableSfence) 75 fencei := state === s_icache 76 sfence.valid := state === s_tlb && ((!disableSfence && func === FenceOpType.sfence) || (!disableHfencev && func === FenceOpType.hfence_v) || (!disableHfenceg && func === FenceOpType.hfence_g)) 77 sfence.bits.rs1 := uop.data.imm(4, 0) === 0.U 78 sfence.bits.rs2 := uop.data.imm(9, 5) === 0.U 79 sfence.bits.flushPipe := uop.ctrl.flushPipe.get 80 sfence.bits.hv := !disableHfencev && func === FenceOpType.hfence_v 81 sfence.bits.hg := !disableHfenceg && func === FenceOpType.hfence_g 82 sfence.bits.addr := RegEnable(io.in.bits.data.src(0), io.in.fire) 83 sfence.bits.id := RegEnable(io.in.bits.data.src(1), io.in.fire) 84 85 when (state === s_idle && io.in.valid) { state := s_wait } 86 when (state === s_wait && func === FenceOpType.fencei && sbEmpty) { state := s_icache } 87 when (state === s_wait && ((func === FenceOpType.sfence && (sbEmpty || disableSfence)) 88 || (func === FenceOpType.hfence_g && (sbEmpty || disableHfenceg)) 89 || (func === FenceOpType.hfence_v && (sbEmpty || disableHfencev)))) { state := s_tlb } 90 when (state === s_wait && func === FenceOpType.fence && sbEmpty) { state := s_fence } 91 when (state === s_wait && func === FenceOpType.nofence && sbEmpty) { state := s_nofence } 92 when (state =/= s_idle && state =/= s_wait) { state := s_idle } 93 94 val illegalsfence = func === FenceOpType.sfence && disableSfence 95 val illegalhfenceg = func === FenceOpType.hfence_g && disableHfenceg 96 val illegalhfencev = func === FenceOpType.hfence_v && disableHfencev 97 val raiseEX_II = (illegalsfence || illegalhfenceg || illegalhfencev) && !virtMode 98 val raiseEX_VI = (illegalsfence || illegalhfenceg || illegalhfencev) && virtMode 99 100 io.in.ready := state === s_idle 101 io.out.valid := state =/= s_idle && state =/= s_wait 102 io.out.bits.res.data := 0.U 103 io.out.bits.ctrl.robIdx := uop.ctrl.robIdx 104 io.out.bits.res.pc.get := uop.data.pc.get 105 io.out.bits.ctrl.pdest := uop.ctrl.pdest 106 io.out.bits.ctrl.flushPipe.get := uop.ctrl.flushPipe.get 107 io.out.bits.ctrl.exceptionVec.get := 0.U.asTypeOf(io.out.bits.ctrl.exceptionVec.get) 108 io.out.bits.ctrl.exceptionVec.get(illegalInstr) := raiseEX_II 109 io.out.bits.ctrl.exceptionVec.get(virtualInstr) := raiseEX_VI 110 io.out.bits.perfDebugInfo := io.in.bits.perfDebugInfo 111 112 XSDebug(io.in.valid, p"In(${io.in.valid} ${io.in.ready}) state:${state} Inpc:0x${Hexadecimal(io.in.bits.data.pc.get)} InrobIdx:${io.in.bits.ctrl.robIdx}\n") 113 XSDebug(state =/= s_idle, p"state:${state} sbuffer(flush:${sbuffer} empty:${sbEmpty}) fencei:${fencei} sfence:${sfence}\n") 114 XSDebug(io.out.valid, p" Out(${io.out.valid} ${io.out.ready}) state:${state} Outpc:0x${Hexadecimal(io.out.bits.res.pc.get)} OutrobIdx:${io.out.bits.ctrl.robIdx}\n") 115 116 assert(!io.out.valid || io.out.ready, "when fence is out valid, out ready should always be true") 117} 118