xref: /XiangShan/src/main/scala/xiangshan/backend/fu/Fence.scala (revision d0de7e4a4bcd4633260dda99dfedc2a5e543b8b4)
1c6d43980SLemover/***************************************************************************************
2c6d43980SLemover* Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3f320e0f0SYinan Xu* Copyright (c) 2020-2021 Peng Cheng Laboratory
4c6d43980SLemover*
5c6d43980SLemover* XiangShan is licensed under Mulan PSL v2.
6c6d43980SLemover* You can use this software according to the terms and conditions of the Mulan PSL v2.
7c6d43980SLemover* You may obtain a copy of Mulan PSL v2 at:
8c6d43980SLemover*          http://license.coscl.org.cn/MulanPSL2
9c6d43980SLemover*
10c6d43980SLemover* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11c6d43980SLemover* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12c6d43980SLemover* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13c6d43980SLemover*
14c6d43980SLemover* See the Mulan PSL v2 for more details.
15c6d43980SLemover***************************************************************************************/
16c6d43980SLemover
17e18c367fSLinJiaweipackage xiangshan.backend.fu
182f99f1bbSAllen
198891a219SYinan Xuimport org.chipsalliance.cde.config.Parameters
202f99f1bbSAllenimport chisel3._
212f99f1bbSAllenimport chisel3.util._
222f99f1bbSAllenimport xiangshan._
232f99f1bbSAllenimport utils._
243c02ee8fSwakafaimport utility._
25*d0de7e4aSpeixiaokunimport xiangshan.ExceptionNO.{illegalInstr, virtualInstr}
262f99f1bbSAllen
272225d46eSJiawei Linclass FenceToSbuffer extends Bundle {
282fdc488aSLinJiawei  val flushSb = Output(Bool())
292fdc488aSLinJiawei  val sbIsEmpty = Input(Bool())
302fdc488aSLinJiawei}
312fdc488aSLinJiawei
326ab6918fSYinan Xuclass Fence(implicit p: Parameters) extends FunctionUnit {
332fdc488aSLinJiawei
342fdc488aSLinJiawei  val sfence = IO(Output(new SfenceBundle))
352fdc488aSLinJiawei  val fencei = IO(Output(Bool()))
362fdc488aSLinJiawei  val toSbuffer = IO(new FenceToSbuffer)
37b37cea47SLemover  val disableSfence = IO(Input(Bool()))
38*d0de7e4aSpeixiaokun  val disableHfenceg = IO(Input(Bool()))
39*d0de7e4aSpeixiaokun  val disableHfencev = IO(Input(Bool()))
40*d0de7e4aSpeixiaokun  val virtMode = IO(Input(Bool()))
41af2f7849Shappy-lx  val (valid, src1) = (
42af2f7849Shappy-lx    io.in.valid,
43af2f7849Shappy-lx    io.in.bits.src(0)
44af2f7849Shappy-lx  )
45af2f7849Shappy-lx
46af2f7849Shappy-lx  val s_idle :: s_wait :: s_tlb :: s_icache :: s_fence :: s_nofence :: Nil = Enum(6)
47af2f7849Shappy-lx
48de39f54aSZhangZifei  val state = RegInit(s_idle)
49de39f54aSZhangZifei  /* fsm
50de39f54aSZhangZifei   * s_idle    : init state, send sbflush
51de39f54aSZhangZifei   * s_wait  : send sbflush, wait for sbEmpty
52de39f54aSZhangZifei   * s_tlb   : flush tlb, just hold one cycle
53de39f54aSZhangZifei   * s_icache: flush icache, just hold one cycle
54de39f54aSZhangZifei   * s_fence : do nothing, for timing optimiaztion
55af2f7849Shappy-lx   * s_nofence: do nothing , for Svinval extension
56de39f54aSZhangZifei   */
572f99f1bbSAllen
582fdc488aSLinJiawei  val sbuffer = toSbuffer.flushSb
592fdc488aSLinJiawei  val sbEmpty = toSbuffer.sbIsEmpty
60935edac4STang Haojin  val uop = RegEnable(io.in.bits.uop, io.in.fire)
61de39f54aSZhangZifei  val func = uop.ctrl.fuOpType
622fdc488aSLinJiawei
63b8f08ca0SZhangZifei  // NOTE: icache & tlb & sbuffer must receive flush signal at any time
64b37cea47SLemover  sbuffer      := state === s_wait && !(func === FenceOpType.sfence && disableSfence)
65de39f54aSZhangZifei  fencei       := state === s_icache
66*d0de7e4aSpeixiaokun  sfence.valid := state === s_tlb && ((!disableSfence && func === FenceOpType.sfence) || (!disableHfencev && func === FenceOpType.hfence_v) || (!disableHfenceg && func === FenceOpType.hfence_g))
67a020ce37SYinan Xu  sfence.bits.rs1  := uop.ctrl.imm(4, 0) === 0.U
68a020ce37SYinan Xu  sfence.bits.rs2  := uop.ctrl.imm(9, 5) === 0.U
69f1fe8698SLemover  sfence.bits.flushPipe := uop.ctrl.flushPipe
70*d0de7e4aSpeixiaokun  sfence.bits.hv := !disableHfencev && func === FenceOpType.hfence_v
71*d0de7e4aSpeixiaokun  sfence.bits.hg := !disableHfenceg && func === FenceOpType.hfence_g
72a020ce37SYinan Xu  XSError(sfence.valid && uop.ctrl.lsrc(0) =/= uop.ctrl.imm(4, 0), "lsrc0 is passed by imm\n")
73a020ce37SYinan Xu  XSError(sfence.valid && uop.ctrl.lsrc(1) =/= uop.ctrl.imm(9, 5), "lsrc1 is passed by imm\n")
74935edac4STang Haojin  sfence.bits.addr := RegEnable(io.in.bits.src(0), io.in.fire)
75935edac4STang Haojin  sfence.bits.asid := RegEnable(io.in.bits.src(1), io.in.fire)
76b8f08ca0SZhangZifei
77a020ce37SYinan Xu  when (state === s_idle && io.in.valid) { state := s_wait }
78de39f54aSZhangZifei  when (state === s_wait && func === FenceOpType.fencei && sbEmpty) { state := s_icache }
79*d0de7e4aSpeixiaokun  when (state === s_wait && ((func === FenceOpType.sfence && (sbEmpty || disableSfence))
80*d0de7e4aSpeixiaokun    || (func === FenceOpType.hfence_g && (sbEmpty || disableHfenceg))
81*d0de7e4aSpeixiaokun    || (func === FenceOpType.hfence_v && (sbEmpty || disableHfencev)))) { state := s_tlb }
82de39f54aSZhangZifei  when (state === s_wait && func === FenceOpType.fence  && sbEmpty) { state := s_fence }
83af2f7849Shappy-lx  when (state === s_wait && func === FenceOpType.nofence  && sbEmpty) { state := s_nofence }
84de39f54aSZhangZifei  when (state =/= s_idle && state =/= s_wait) { state := s_idle }
85de39f54aSZhangZifei
86de39f54aSZhangZifei  io.in.ready := state === s_idle
87de39f54aSZhangZifei  io.out.valid := state =/= s_idle && state =/= s_wait
88de39f54aSZhangZifei  io.out.bits.data := DontCare
89de39f54aSZhangZifei  io.out.bits.uop := uop
90*d0de7e4aSpeixiaokun  val illegalsfence = func === FenceOpType.sfence && disableSfence
91*d0de7e4aSpeixiaokun  val illegalhfenceg = func === FenceOpType.hfence_g && disableHfenceg
92*d0de7e4aSpeixiaokun  val illegalhfencev = func === FenceOpType.hfence_v && disableHfencev
93*d0de7e4aSpeixiaokun  io.out.bits.uop.cf.exceptionVec(illegalInstr) := (illegalsfence || illegalhfenceg || illegalhfencev) && !virtMode
94*d0de7e4aSpeixiaokun  io.out.bits.uop.cf.exceptionVec(virtualInstr) := (illegalsfence || illegalhfenceg || illegalhfencev) && virtMode
95de39f54aSZhangZifei
96a020ce37SYinan Xu  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")
97de39f54aSZhangZifei  XSDebug(state =/= s_idle, p"state:${state} sbuffer(flush:${sbuffer} empty:${sbEmpty}) fencei:${fencei} sfence:${sfence}\n")
989aca92b9SYinan Xu  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")
992f99f1bbSAllen
100b8f08ca0SZhangZifei  assert(!(io.out.valid && io.out.bits.uop.ctrl.rfWen))
101de39f54aSZhangZifei  assert(!io.out.valid || io.out.ready, "when fence is out valid, out ready should always be true")
1022f99f1bbSAllen}
103