xref: /XiangShan/src/main/scala/xiangshan/backend/fu/Fence.scala (revision c6d439803a044ea209139672b25e35fe8d7f4aa0)
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
29// class Fence extends FunctionUnit(FuConfig(
30  // /*FuType.fence, 1, 0, writeIntRf = false, writeFpRf = false, hasRedirect = false,*/ latency = UncertainLatency()
31// )){
32class Fence(implicit p: Parameters) extends FunctionUnit{ // TODO: check it
33
34  val sfence = IO(Output(new SfenceBundle))
35  val fencei = IO(Output(Bool()))
36  val toSbuffer = IO(new FenceToSbuffer)
37
38  val (valid, src1) = (
39    io.in.valid,
40    io.in.bits.src(0)
41  )
42
43  val s_idle :: s_wait :: s_tlb :: s_icache :: s_fence :: Nil = Enum(5)
44  val state = RegInit(s_idle)
45  /* fsm
46   * s_idle    : init state, send sbflush
47   * s_wait  : send sbflush, wait for sbEmpty
48   * s_tlb   : flush tlb, just hold one cycle
49   * s_icache: flush icache, just hold one cycle
50   * s_fence : do nothing, for timing optimiaztion
51   */
52
53  val sbuffer = toSbuffer.flushSb
54  val sbEmpty = toSbuffer.sbIsEmpty
55  val uop = RegEnable(io.in.bits.uop, io.in.fire())
56  val func = uop.ctrl.fuOpType
57
58  // NOTE: icache & tlb & sbuffer must receive flush signal at any time
59  sbuffer      := state === s_wait
60  fencei       := state === s_icache
61  sfence.valid := state === s_tlb
62  sfence.bits.rs1  := uop.ctrl.lsrc(0) === 0.U
63  sfence.bits.rs2  := uop.ctrl.lsrc(1) === 0.U
64  sfence.bits.addr := RegEnable(src1, io.in.fire())
65
66  when (state === s_idle && valid) { state := s_wait }
67  when (state === s_wait && func === FenceOpType.fencei && sbEmpty) { state := s_icache }
68  when (state === s_wait && func === FenceOpType.sfence && sbEmpty) { state := s_tlb }
69  when (state === s_wait && func === FenceOpType.fence  && sbEmpty) { state := s_fence }
70  when (state =/= s_idle && state =/= s_wait) { state := s_idle }
71
72  io.in.ready := state === s_idle
73  io.out.valid := state =/= s_idle && state =/= s_wait
74  io.out.bits.data := DontCare
75  io.out.bits.uop := uop
76
77  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")
78  XSDebug(state =/= s_idle, p"state:${state} sbuffer(flush:${sbuffer} empty:${sbEmpty}) fencei:${fencei} sfence:${sfence}\n")
79  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")
80
81  assert(!(io.out.valid && io.out.bits.uop.ctrl.rfWen))
82  assert(!io.out.valid || io.out.ready, "when fence is out valid, out ready should always be true")
83}
84