xref: /XiangShan/src/main/scala/xiangshan/backend/fu/Fence.scala (revision 8891a219bbc84f568e1d134854d8d5ed86d6d560)
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 xiangshan._
23import utils._
24import utility._
25import xiangshan.ExceptionNO.illegalInstr
26
27class FenceToSbuffer extends Bundle {
28  val flushSb = Output(Bool())
29  val sbIsEmpty = Input(Bool())
30}
31
32class Fence(implicit p: Parameters) extends FunctionUnit {
33
34  val sfence = IO(Output(new SfenceBundle))
35  val fencei = IO(Output(Bool()))
36  val toSbuffer = IO(new FenceToSbuffer)
37  val disableSfence = IO(Input(Bool()))
38
39  val (valid, src1) = (
40    io.in.valid,
41    io.in.bits.src(0)
42  )
43
44  val s_idle :: s_wait :: s_tlb :: s_icache :: s_fence :: s_nofence :: Nil = Enum(6)
45
46  val state = RegInit(s_idle)
47  /* fsm
48   * s_idle    : init state, send sbflush
49   * s_wait  : send sbflush, wait for sbEmpty
50   * s_tlb   : flush tlb, just hold one cycle
51   * s_icache: flush icache, just hold one cycle
52   * s_fence : do nothing, for timing optimiaztion
53   * s_nofence: do nothing , for Svinval extension
54   */
55
56  val sbuffer = toSbuffer.flushSb
57  val sbEmpty = toSbuffer.sbIsEmpty
58  val uop = RegEnable(io.in.bits.uop, io.in.fire)
59  val func = uop.ctrl.fuOpType
60
61  // NOTE: icache & tlb & sbuffer must receive flush signal at any time
62  sbuffer      := state === s_wait && !(func === FenceOpType.sfence && disableSfence)
63  fencei       := state === s_icache
64  sfence.valid := state === s_tlb && !disableSfence
65  sfence.bits.rs1  := uop.ctrl.imm(4, 0) === 0.U
66  sfence.bits.rs2  := uop.ctrl.imm(9, 5) === 0.U
67  sfence.bits.flushPipe := uop.ctrl.flushPipe
68  XSError(sfence.valid && uop.ctrl.lsrc(0) =/= uop.ctrl.imm(4, 0), "lsrc0 is passed by imm\n")
69  XSError(sfence.valid && uop.ctrl.lsrc(1) =/= uop.ctrl.imm(9, 5), "lsrc1 is passed by imm\n")
70  sfence.bits.addr := RegEnable(io.in.bits.src(0), io.in.fire)
71  sfence.bits.asid := RegEnable(io.in.bits.src(1), io.in.fire)
72
73  when (state === s_idle && io.in.valid) { state := s_wait }
74  when (state === s_wait && func === FenceOpType.fencei && sbEmpty) { state := s_icache }
75  when (state === s_wait && func === FenceOpType.sfence && (sbEmpty || disableSfence)) { state := s_tlb }
76  when (state === s_wait && func === FenceOpType.fence  && sbEmpty) { state := s_fence }
77  when (state === s_wait && func === FenceOpType.nofence  && sbEmpty) { state := s_nofence }
78  when (state =/= s_idle && state =/= s_wait) { state := s_idle }
79
80  io.in.ready := state === s_idle
81  io.out.valid := state =/= s_idle && state =/= s_wait
82  io.out.bits.data := DontCare
83  io.out.bits.uop := uop
84  io.out.bits.uop.cf.exceptionVec(illegalInstr) := func === FenceOpType.sfence && disableSfence
85
86  XSDebug(io.in.valid, p"In(${io.in.valid} ${io.in.ready}) state:${state} Inpc:0x${Hexadecimal(io.in.bits.uop.cf.pc)} InrobIdx:${io.in.bits.uop.robIdx}\n")
87  XSDebug(state =/= s_idle, p"state:${state} sbuffer(flush:${sbuffer} empty:${sbEmpty}) fencei:${fencei} sfence:${sfence}\n")
88  XSDebug(io.out.valid, p" Out(${io.out.valid} ${io.out.ready}) state:${state} Outpc:0x${Hexadecimal(io.out.bits.uop.cf.pc)} OutrobIdx:${io.out.bits.uop.robIdx}\n")
89
90  assert(!(io.out.valid && io.out.bits.uop.ctrl.rfWen))
91  assert(!io.out.valid || io.out.ready, "when fence is out valid, out ready should always be true")
92}
93