xref: /XiangShan/src/main/scala/xiangshan/backend/rob/ExceptionGen.scala (revision 780712aa4d2ede8944b843c01f0a3ac94679530e)
1*780712aaSxiaofeibao-xjtu/***************************************************************************************
2*780712aaSxiaofeibao-xjtu * Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3*780712aaSxiaofeibao-xjtu * Copyright (c) 2020-2021 Peng Cheng Laboratory
4*780712aaSxiaofeibao-xjtu *
5*780712aaSxiaofeibao-xjtu * XiangShan is licensed under Mulan PSL v2.
6*780712aaSxiaofeibao-xjtu * You can use this software according to the terms and conditions of the Mulan PSL v2.
7*780712aaSxiaofeibao-xjtu * You may obtain a copy of Mulan PSL v2 at:
8*780712aaSxiaofeibao-xjtu *          http://license.coscl.org.cn/MulanPSL2
9*780712aaSxiaofeibao-xjtu *
10*780712aaSxiaofeibao-xjtu * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11*780712aaSxiaofeibao-xjtu * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12*780712aaSxiaofeibao-xjtu * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13*780712aaSxiaofeibao-xjtu *
14*780712aaSxiaofeibao-xjtu * See the Mulan PSL v2 for more details.
15*780712aaSxiaofeibao-xjtu ***************************************************************************************/
16*780712aaSxiaofeibao-xjtu
17*780712aaSxiaofeibao-xjtupackage xiangshan.backend.rob
18*780712aaSxiaofeibao-xjtu
19*780712aaSxiaofeibao-xjtuimport org.chipsalliance.cde.config.Parameters
20*780712aaSxiaofeibao-xjtuimport chisel3._
21*780712aaSxiaofeibao-xjtuimport chisel3.util._
22*780712aaSxiaofeibao-xjtuimport difftest._
23*780712aaSxiaofeibao-xjtuimport freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp}
24*780712aaSxiaofeibao-xjtuimport utility._
25*780712aaSxiaofeibao-xjtuimport utils._
26*780712aaSxiaofeibao-xjtuimport xiangshan._
27*780712aaSxiaofeibao-xjtuimport xiangshan.backend.BackendParams
28*780712aaSxiaofeibao-xjtuimport xiangshan.backend.Bundles.{DynInst, ExceptionInfo, ExuOutput}
29*780712aaSxiaofeibao-xjtuimport xiangshan.backend.fu.{FuConfig, FuType}
30*780712aaSxiaofeibao-xjtuimport xiangshan.frontend.FtqPtr
31*780712aaSxiaofeibao-xjtuimport xiangshan.mem.{LqPtr, LsqEnqIO, SqPtr}
32*780712aaSxiaofeibao-xjtuimport xiangshan.backend.Bundles.{DynInst, ExceptionInfo, ExuOutput}
33*780712aaSxiaofeibao-xjtuimport xiangshan.backend.ctrlblock.{DebugLSIO, DebugLsInfo, LsTopdownInfo}
34*780712aaSxiaofeibao-xjtuimport xiangshan.backend.fu.vector.Bundles.VType
35*780712aaSxiaofeibao-xjtuimport xiangshan.backend.rename.SnapshotGenerator
36*780712aaSxiaofeibao-xjtu
37*780712aaSxiaofeibao-xjtuclass ExceptionGen(params: BackendParams)(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelper {
38*780712aaSxiaofeibao-xjtu  val io = IO(new Bundle {
39*780712aaSxiaofeibao-xjtu    val redirect = Input(Valid(new Redirect))
40*780712aaSxiaofeibao-xjtu    val flush = Input(Bool())
41*780712aaSxiaofeibao-xjtu    val enq = Vec(RenameWidth, Flipped(ValidIO(new RobExceptionInfo)))
42*780712aaSxiaofeibao-xjtu    // csr + load + store + varith + vload + vstore
43*780712aaSxiaofeibao-xjtu    val wb = Vec(params.numException, Flipped(ValidIO(new RobExceptionInfo)))
44*780712aaSxiaofeibao-xjtu    val out = ValidIO(new RobExceptionInfo)
45*780712aaSxiaofeibao-xjtu    val state = ValidIO(new RobExceptionInfo)
46*780712aaSxiaofeibao-xjtu  })
47*780712aaSxiaofeibao-xjtu
48*780712aaSxiaofeibao-xjtu  val wbExuParams = params.allExuParams.filter(_.exceptionOut.nonEmpty)
49*780712aaSxiaofeibao-xjtu
50*780712aaSxiaofeibao-xjtu  def getOldest(valid: Seq[Bool], bits: Seq[RobExceptionInfo]): RobExceptionInfo = {
51*780712aaSxiaofeibao-xjtu    def getOldest_recursion(valid: Seq[Bool], bits: Seq[RobExceptionInfo]): (Seq[Bool], Seq[RobExceptionInfo]) = {
52*780712aaSxiaofeibao-xjtu      assert(valid.length == bits.length)
53*780712aaSxiaofeibao-xjtu      if (valid.length == 1) {
54*780712aaSxiaofeibao-xjtu        (valid, bits)
55*780712aaSxiaofeibao-xjtu      } else if (valid.length == 2) {
56*780712aaSxiaofeibao-xjtu        val res = Seq.fill(2)(Wire(ValidIO(chiselTypeOf(bits(0)))))
57*780712aaSxiaofeibao-xjtu        for (i <- res.indices) {
58*780712aaSxiaofeibao-xjtu          res(i).valid := valid(i)
59*780712aaSxiaofeibao-xjtu          res(i).bits := bits(i)
60*780712aaSxiaofeibao-xjtu        }
61*780712aaSxiaofeibao-xjtu        val oldest = Mux(!valid(1) || valid(0) && isAfter(bits(1).robIdx, bits(0).robIdx), res(0), res(1))
62*780712aaSxiaofeibao-xjtu        (Seq(oldest.valid), Seq(oldest.bits))
63*780712aaSxiaofeibao-xjtu      } else {
64*780712aaSxiaofeibao-xjtu        val left = getOldest_recursion(valid.take(valid.length / 2), bits.take(valid.length / 2))
65*780712aaSxiaofeibao-xjtu        val right = getOldest_recursion(valid.drop(valid.length / 2), bits.drop(valid.length / 2))
66*780712aaSxiaofeibao-xjtu        getOldest_recursion(left._1 ++ right._1, left._2 ++ right._2)
67*780712aaSxiaofeibao-xjtu      }
68*780712aaSxiaofeibao-xjtu    }
69*780712aaSxiaofeibao-xjtu    getOldest_recursion(valid, bits)._2.head
70*780712aaSxiaofeibao-xjtu  }
71*780712aaSxiaofeibao-xjtu
72*780712aaSxiaofeibao-xjtu
73*780712aaSxiaofeibao-xjtu  val currentValid = RegInit(false.B)
74*780712aaSxiaofeibao-xjtu  val current = Reg(new RobExceptionInfo)
75*780712aaSxiaofeibao-xjtu
76*780712aaSxiaofeibao-xjtu  // orR the exceptionVec
77*780712aaSxiaofeibao-xjtu  val lastCycleFlush = RegNext(io.flush)
78*780712aaSxiaofeibao-xjtu  val in_enq_valid = VecInit(io.enq.map(e => e.valid && e.bits.has_exception && !lastCycleFlush))
79*780712aaSxiaofeibao-xjtu
80*780712aaSxiaofeibao-xjtu  // s0: compare wb in 6 groups
81*780712aaSxiaofeibao-xjtu  val csr_wb = io.wb.zip(wbExuParams).filter(_._2.fuConfigs.filter(t => t.isCsr).nonEmpty).map(_._1)
82*780712aaSxiaofeibao-xjtu  val load_wb = io.wb.zip(wbExuParams).filter(_._2.fuConfigs.filter(_.fuType == FuType.ldu).nonEmpty).map(_._1)
83*780712aaSxiaofeibao-xjtu  val store_wb = io.wb.zip(wbExuParams).filter(_._2.fuConfigs.filter(t => t.isSta || t.fuType == FuType.mou).nonEmpty).map(_._1)
84*780712aaSxiaofeibao-xjtu  val varith_wb = io.wb.zip(wbExuParams).filter(_._2.fuConfigs.filter(_.isVecArith).nonEmpty).map(_._1)
85*780712aaSxiaofeibao-xjtu  val vload_wb = io.wb.zip(wbExuParams).filter(_._2.fuConfigs.filter(_.fuType == FuType.vldu).nonEmpty).map(_._1)
86*780712aaSxiaofeibao-xjtu  val vstore_wb = io.wb.zip(wbExuParams).filter(_._2.fuConfigs.filter(_.fuType == FuType.vstu).nonEmpty).map(_._1)
87*780712aaSxiaofeibao-xjtu
88*780712aaSxiaofeibao-xjtu  val writebacks = Seq(csr_wb, load_wb, store_wb, varith_wb, vload_wb, vstore_wb)
89*780712aaSxiaofeibao-xjtu  val in_wb_valids = writebacks.map(_.map(w => w.valid && w.bits.has_exception && !lastCycleFlush))
90*780712aaSxiaofeibao-xjtu  val wb_valid = in_wb_valids.zip(writebacks).map { case (valid, wb) =>
91*780712aaSxiaofeibao-xjtu    valid.zip(wb.map(_.bits)).map { case (v, bits) => v && !(bits.robIdx.needFlush(io.redirect) || io.flush) }.reduce(_ || _)
92*780712aaSxiaofeibao-xjtu  }
93*780712aaSxiaofeibao-xjtu  val wb_bits = in_wb_valids.zip(writebacks).map { case (valid, wb) => getOldest(valid, wb.map(_.bits))}
94*780712aaSxiaofeibao-xjtu
95*780712aaSxiaofeibao-xjtu  val s0_out_valid = wb_valid.map(x => RegNext(x))
96*780712aaSxiaofeibao-xjtu  val s0_out_bits = wb_bits.zip(wb_valid).map{ case(b, v) => RegEnable(b, v)}
97*780712aaSxiaofeibao-xjtu
98*780712aaSxiaofeibao-xjtu  // s1: compare last six and current flush
99*780712aaSxiaofeibao-xjtu  val s1_valid = VecInit(s0_out_valid.zip(s0_out_bits).map{ case (v, b) => v && !(b.robIdx.needFlush(io.redirect) || io.flush) })
100*780712aaSxiaofeibao-xjtu  val s1_out_bits = RegEnable(getOldest(s0_out_valid, s0_out_bits), s1_valid.asUInt.orR)
101*780712aaSxiaofeibao-xjtu  val s1_out_valid = RegNext(s1_valid.asUInt.orR)
102*780712aaSxiaofeibao-xjtu
103*780712aaSxiaofeibao-xjtu  val enq_valid = RegNext(in_enq_valid.asUInt.orR && !io.redirect.valid && !io.flush)
104*780712aaSxiaofeibao-xjtu  val enq_bits = RegEnable(ParallelPriorityMux(in_enq_valid, io.enq.map(_.bits)), in_enq_valid.asUInt.orR && !io.redirect.valid && !io.flush)
105*780712aaSxiaofeibao-xjtu
106*780712aaSxiaofeibao-xjtu  // s2: compare the input exception with the current one
107*780712aaSxiaofeibao-xjtu  // priorities:
108*780712aaSxiaofeibao-xjtu  // (1) system reset
109*780712aaSxiaofeibao-xjtu  // (2) current is valid: flush, remain, merge, update
110*780712aaSxiaofeibao-xjtu  // (3) current is not valid: s1 or enq
111*780712aaSxiaofeibao-xjtu  val current_flush = current.robIdx.needFlush(io.redirect) || io.flush
112*780712aaSxiaofeibao-xjtu  val s1_flush = s1_out_bits.robIdx.needFlush(io.redirect) || io.flush
113*780712aaSxiaofeibao-xjtu  when (currentValid) {
114*780712aaSxiaofeibao-xjtu    when (current_flush) {
115*780712aaSxiaofeibao-xjtu      currentValid := Mux(s1_flush, false.B, s1_out_valid)
116*780712aaSxiaofeibao-xjtu    }
117*780712aaSxiaofeibao-xjtu    when (s1_out_valid && !s1_flush) {
118*780712aaSxiaofeibao-xjtu      when (isAfter(current.robIdx, s1_out_bits.robIdx)) {
119*780712aaSxiaofeibao-xjtu        current := s1_out_bits
120*780712aaSxiaofeibao-xjtu      }.elsewhen (current.robIdx === s1_out_bits.robIdx) {
121*780712aaSxiaofeibao-xjtu        current.exceptionVec := (s1_out_bits.exceptionVec.asUInt | current.exceptionVec.asUInt).asTypeOf(ExceptionVec())
122*780712aaSxiaofeibao-xjtu        current.flushPipe := s1_out_bits.flushPipe || current.flushPipe
123*780712aaSxiaofeibao-xjtu        current.replayInst := s1_out_bits.replayInst || current.replayInst
124*780712aaSxiaofeibao-xjtu        current.singleStep := s1_out_bits.singleStep || current.singleStep
125*780712aaSxiaofeibao-xjtu        current.trigger := (s1_out_bits.trigger.asUInt | current.trigger.asUInt).asTypeOf(new TriggerCf)
126*780712aaSxiaofeibao-xjtu      }
127*780712aaSxiaofeibao-xjtu    }
128*780712aaSxiaofeibao-xjtu  }.elsewhen (s1_out_valid && !s1_flush) {
129*780712aaSxiaofeibao-xjtu    currentValid := true.B
130*780712aaSxiaofeibao-xjtu    current := s1_out_bits
131*780712aaSxiaofeibao-xjtu  }.elsewhen (enq_valid && !(io.redirect.valid || io.flush)) {
132*780712aaSxiaofeibao-xjtu    currentValid := true.B
133*780712aaSxiaofeibao-xjtu    current := enq_bits
134*780712aaSxiaofeibao-xjtu  }
135*780712aaSxiaofeibao-xjtu
136*780712aaSxiaofeibao-xjtu  io.out.valid   := s1_out_valid || enq_valid && enq_bits.can_writeback
137*780712aaSxiaofeibao-xjtu  io.out.bits    := Mux(s1_out_valid, s1_out_bits, enq_bits)
138*780712aaSxiaofeibao-xjtu  io.state.valid := currentValid
139*780712aaSxiaofeibao-xjtu  io.state.bits  := current
140*780712aaSxiaofeibao-xjtu
141*780712aaSxiaofeibao-xjtu}