xref: /XiangShan/src/main/scala/xiangshan/backend/fu/Fence.scala (revision b6262ab36fd0bd3e6e6788f01741f204340624a4)
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 chisel3._
20import chisel3.util._
21import org.chipsalliance.cde.config.Parameters
22import utility.XSDebug
23import xiangshan.ExceptionNO.{illegalInstr, virtualInstr}
24import xiangshan._
25
26class FenceIO(implicit p: Parameters) extends XSBundle {
27  val sfence = Output(new SfenceBundle)
28  val fencei = Output(Bool())
29  val sbuffer = new FenceToSbuffer
30  val disableSfence = Input(Bool())
31  val disableHfenceg = Input(Bool())
32  val disableHfencev = Input(Bool())
33  val virtMode = Input(Bool())
34}
35
36class FenceToSbuffer extends Bundle {
37  val flushSb = Output(Bool())
38  val sbIsEmpty = Input(Bool())
39}
40
41class Fence(cfg: FuConfig)(implicit p: Parameters) extends FuncUnit(cfg) {
42
43  val sfence = io.fenceio.get.sfence
44  val fencei = io.fenceio.get.fencei
45  val toSbuffer = io.fenceio.get.sbuffer
46  val disableSfence = io.fenceio.get.disableSfence
47  val disableHfenceg = io.fenceio.get.disableHfenceg
48  val disableHfencev = io.fenceio.get.disableHfencev
49  val virtMode = io.fenceio.get.virtMode
50  val (valid, src1) = (
51    io.in.valid,
52    io.in.bits.data.src(0)
53  )
54
55  val s_idle :: s_wait :: s_tlb :: s_icache :: s_fence :: s_nofence :: Nil = Enum(6)
56
57  val state = RegInit(s_idle)
58  /* fsm
59   * s_idle    : init state, send sbflush
60   * s_wait  : send sbflush, wait for sbEmpty
61   * s_tlb   : flush tlb, just hold one cycle
62   * s_icache: flush icache, just hold one cycle
63   * s_fence : do nothing, for timing optimiaztion
64   * s_nofence: do nothing , for Svinval extension
65   */
66
67  val sbuffer = toSbuffer.flushSb
68  val sbEmpty = toSbuffer.sbIsEmpty
69  val uop = RegEnable(io.in.bits, io.in.fire)
70  val func = uop.ctrl.fuOpType
71
72  // NOTE: icache & tlb & sbuffer must receive flush signal at any time
73  sbuffer      := state === s_wait && !(func === FenceOpType.sfence && disableSfence)
74  fencei       := state === s_icache
75  sfence.valid := state === s_tlb && ((!disableSfence && func === FenceOpType.sfence) || (!disableHfencev && func === FenceOpType.hfence_v) || (!disableHfenceg && func === FenceOpType.hfence_g))
76  sfence.bits.rs1  := uop.data.imm(4, 0) === 0.U
77  sfence.bits.rs2  := uop.data.imm(9, 5) === 0.U
78  sfence.bits.flushPipe := uop.ctrl.flushPipe.get
79  sfence.bits.hv := !disableHfencev && func === FenceOpType.hfence_v
80  sfence.bits.hg := !disableHfenceg && func === FenceOpType.hfence_g
81  sfence.bits.addr := RegEnable(io.in.bits.data.src(0), io.in.fire)
82  sfence.bits.id   := RegEnable(io.in.bits.data.src(1), io.in.fire)
83
84  when (state === s_idle && io.in.valid) { state := s_wait }
85  when (state === s_wait && func === FenceOpType.fencei && sbEmpty) { state := s_icache }
86  when (state === s_wait && ((func === FenceOpType.sfence && (sbEmpty || disableSfence))
87    || (func === FenceOpType.hfence_g && (sbEmpty || disableHfenceg))
88    || (func === FenceOpType.hfence_v && (sbEmpty || disableHfencev)))) { state := s_tlb }
89  when (state === s_wait && func === FenceOpType.fence  && sbEmpty) { state := s_fence }
90  when (state === s_wait && func === FenceOpType.nofence  && sbEmpty) { state := s_nofence }
91  when (state =/= s_idle && state =/= s_wait) { state := s_idle }
92
93  val illegalsfence = func === FenceOpType.sfence && disableSfence
94  val illegalhfenceg = func === FenceOpType.hfence_g && disableHfenceg
95  val illegalhfencev = func === FenceOpType.hfence_v && disableHfencev
96  val raiseEX_II = (illegalsfence || illegalhfenceg || illegalhfencev) && !virtMode
97  val raiseEX_VI = (illegalsfence || illegalhfenceg || illegalhfencev) && virtMode
98
99  io.in.ready := state === s_idle
100  io.out.valid := state =/= s_idle && state =/= s_wait
101  io.out.bits.res.data := 0.U
102  io.out.bits.ctrl.robIdx := uop.ctrl.robIdx
103  io.out.bits.res.pc.get := uop.data.pc.get
104  io.out.bits.ctrl.pdest := uop.ctrl.pdest
105  io.out.bits.ctrl.flushPipe.get := uop.ctrl.flushPipe.get
106  io.out.bits.ctrl.exceptionVec.get := 0.U.asTypeOf(io.out.bits.ctrl.exceptionVec.get)
107  io.out.bits.ctrl.exceptionVec.get(illegalInstr) := raiseEX_II
108  io.out.bits.ctrl.exceptionVec.get(virtualInstr) := raiseEX_VI
109  io.out.bits.perfDebugInfo := io.in.bits.perfDebugInfo
110
111  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")
112  XSDebug(state =/= s_idle, p"state:${state} sbuffer(flush:${sbuffer} empty:${sbEmpty}) fencei:${fencei} sfence:${sfence}\n")
113  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")
114
115  assert(!io.out.valid || io.out.ready, "when fence is out valid, out ready should always be true")
116}
117