xref: /XiangShan/src/main/scala/xiangshan/backend/rob/ExceptionGen.scala (revision c01e75b55fbe706c21954429f2ec968cbc61a2cc)
1780712aaSxiaofeibao-xjtu/***************************************************************************************
2780712aaSxiaofeibao-xjtu * Copyright (c) 2020-2021 Institute of Computing Technology, Chinese Academy of Sciences
3780712aaSxiaofeibao-xjtu * Copyright (c) 2020-2021 Peng Cheng Laboratory
4780712aaSxiaofeibao-xjtu *
5780712aaSxiaofeibao-xjtu * XiangShan is licensed under Mulan PSL v2.
6780712aaSxiaofeibao-xjtu * You can use this software according to the terms and conditions of the Mulan PSL v2.
7780712aaSxiaofeibao-xjtu * You may obtain a copy of Mulan PSL v2 at:
8780712aaSxiaofeibao-xjtu *          http://license.coscl.org.cn/MulanPSL2
9780712aaSxiaofeibao-xjtu *
10780712aaSxiaofeibao-xjtu * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
11780712aaSxiaofeibao-xjtu * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
12780712aaSxiaofeibao-xjtu * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
13780712aaSxiaofeibao-xjtu *
14780712aaSxiaofeibao-xjtu * See the Mulan PSL v2 for more details.
15780712aaSxiaofeibao-xjtu ***************************************************************************************/
16780712aaSxiaofeibao-xjtu
17780712aaSxiaofeibao-xjtupackage xiangshan.backend.rob
18780712aaSxiaofeibao-xjtu
19780712aaSxiaofeibao-xjtuimport org.chipsalliance.cde.config.Parameters
20780712aaSxiaofeibao-xjtuimport chisel3._
21780712aaSxiaofeibao-xjtuimport chisel3.util._
22780712aaSxiaofeibao-xjtuimport difftest._
23780712aaSxiaofeibao-xjtuimport freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp}
24780712aaSxiaofeibao-xjtuimport utility._
25780712aaSxiaofeibao-xjtuimport utils._
26780712aaSxiaofeibao-xjtuimport xiangshan._
27780712aaSxiaofeibao-xjtuimport xiangshan.backend.BackendParams
28780712aaSxiaofeibao-xjtuimport xiangshan.backend.Bundles.{DynInst, ExceptionInfo, ExuOutput}
29780712aaSxiaofeibao-xjtuimport xiangshan.backend.fu.{FuConfig, FuType}
30780712aaSxiaofeibao-xjtuimport xiangshan.frontend.FtqPtr
31780712aaSxiaofeibao-xjtuimport xiangshan.mem.{LqPtr, LsqEnqIO, SqPtr}
32780712aaSxiaofeibao-xjtuimport xiangshan.backend.Bundles.{DynInst, ExceptionInfo, ExuOutput}
33780712aaSxiaofeibao-xjtuimport xiangshan.backend.ctrlblock.{DebugLSIO, DebugLsInfo, LsTopdownInfo}
34780712aaSxiaofeibao-xjtuimport xiangshan.backend.fu.vector.Bundles.VType
35780712aaSxiaofeibao-xjtuimport xiangshan.backend.rename.SnapshotGenerator
36780712aaSxiaofeibao-xjtu
37780712aaSxiaofeibao-xjtuclass ExceptionGen(params: BackendParams)(implicit p: Parameters) extends XSModule with HasCircularQueuePtrHelper {
38780712aaSxiaofeibao-xjtu  val io = IO(new Bundle {
39780712aaSxiaofeibao-xjtu    val redirect = Input(Valid(new Redirect))
40780712aaSxiaofeibao-xjtu    val flush = Input(Bool())
41780712aaSxiaofeibao-xjtu    val enq = Vec(RenameWidth, Flipped(ValidIO(new RobExceptionInfo)))
42780712aaSxiaofeibao-xjtu    // csr + load + store + varith + vload + vstore
43780712aaSxiaofeibao-xjtu    val wb = Vec(params.numException, Flipped(ValidIO(new RobExceptionInfo)))
44780712aaSxiaofeibao-xjtu    val out = ValidIO(new RobExceptionInfo)
45780712aaSxiaofeibao-xjtu    val state = ValidIO(new RobExceptionInfo)
46780712aaSxiaofeibao-xjtu  })
47780712aaSxiaofeibao-xjtu
48780712aaSxiaofeibao-xjtu  val wbExuParams = params.allExuParams.filter(_.exceptionOut.nonEmpty)
49780712aaSxiaofeibao-xjtu
50780712aaSxiaofeibao-xjtu  def getOldest(valid: Seq[Bool], bits: Seq[RobExceptionInfo]): RobExceptionInfo = {
51780712aaSxiaofeibao-xjtu    def getOldest_recursion(valid: Seq[Bool], bits: Seq[RobExceptionInfo]): (Seq[Bool], Seq[RobExceptionInfo]) = {
52780712aaSxiaofeibao-xjtu      assert(valid.length == bits.length)
53780712aaSxiaofeibao-xjtu      if (valid.length == 1) {
54780712aaSxiaofeibao-xjtu        (valid, bits)
55780712aaSxiaofeibao-xjtu      } else if (valid.length == 2) {
56780712aaSxiaofeibao-xjtu        val res = Seq.fill(2)(Wire(ValidIO(chiselTypeOf(bits(0)))))
57780712aaSxiaofeibao-xjtu        for (i <- res.indices) {
58780712aaSxiaofeibao-xjtu          res(i).valid := valid(i)
59780712aaSxiaofeibao-xjtu          res(i).bits := bits(i)
60780712aaSxiaofeibao-xjtu        }
61c0355297SAnzooooo        val oldest = Mux(
62c0355297SAnzooooo          !valid(1) || (valid(0) && (isAfter(bits(1).robIdx, bits(0).robIdx) || ((bits(1).robIdx === bits(0).robIdx) && bits(1).vuopIdx > bits(0).vuopIdx))),
63c0355297SAnzooooo          res(0),
64c0355297SAnzooooo          res(1)
65c0355297SAnzooooo        )
66780712aaSxiaofeibao-xjtu        (Seq(oldest.valid), Seq(oldest.bits))
67780712aaSxiaofeibao-xjtu      } else {
68780712aaSxiaofeibao-xjtu        val left = getOldest_recursion(valid.take(valid.length / 2), bits.take(valid.length / 2))
69780712aaSxiaofeibao-xjtu        val right = getOldest_recursion(valid.drop(valid.length / 2), bits.drop(valid.length / 2))
70780712aaSxiaofeibao-xjtu        getOldest_recursion(left._1 ++ right._1, left._2 ++ right._2)
71780712aaSxiaofeibao-xjtu      }
72780712aaSxiaofeibao-xjtu    }
73780712aaSxiaofeibao-xjtu    getOldest_recursion(valid, bits)._2.head
74780712aaSxiaofeibao-xjtu  }
75780712aaSxiaofeibao-xjtu
76780712aaSxiaofeibao-xjtu
77780712aaSxiaofeibao-xjtu  val currentValid = RegInit(false.B)
78780712aaSxiaofeibao-xjtu  val current = Reg(new RobExceptionInfo)
79780712aaSxiaofeibao-xjtu
80780712aaSxiaofeibao-xjtu  // orR the exceptionVec
81780712aaSxiaofeibao-xjtu  val lastCycleFlush = RegNext(io.flush)
823e8a0170SXuan Hu  val enq_s0_valid = VecInit(io.enq.map(e => e.valid && e.bits.has_exception && !lastCycleFlush))
833e8a0170SXuan Hu  val enq_s0_bits = WireInit(VecInit(io.enq.map(_.bits)))
843e8a0170SXuan Hu  enq_s0_bits zip io.enq foreach { case (sink, source) =>
853e8a0170SXuan Hu    sink.flushPipe := source.bits.flushPipe && !source.bits.hasException
863e8a0170SXuan Hu  }
87780712aaSxiaofeibao-xjtu
88780712aaSxiaofeibao-xjtu  // s0: compare wb in 6 groups
89780712aaSxiaofeibao-xjtu  val csr_wb = io.wb.zip(wbExuParams).filter(_._2.fuConfigs.filter(t => t.isCsr).nonEmpty).map(_._1)
90780712aaSxiaofeibao-xjtu  val load_wb = io.wb.zip(wbExuParams).filter(_._2.fuConfigs.filter(_.fuType == FuType.ldu).nonEmpty).map(_._1)
91780712aaSxiaofeibao-xjtu  val store_wb = io.wb.zip(wbExuParams).filter(_._2.fuConfigs.filter(t => t.isSta || t.fuType == FuType.mou).nonEmpty).map(_._1)
92780712aaSxiaofeibao-xjtu  val varith_wb = io.wb.zip(wbExuParams).filter(_._2.fuConfigs.filter(_.isVecArith).nonEmpty).map(_._1)
93985804e6SXuan Hu  val vls_wb = io.wb.zip(wbExuParams).filter(_._2.fuConfigs.exists(x => FuType.FuTypeOrR(x.fuType, FuType.vecMem))).map(_._1)
94780712aaSxiaofeibao-xjtu
95985804e6SXuan Hu  val writebacks = Seq(csr_wb, load_wb, store_wb, varith_wb, vls_wb)
96780712aaSxiaofeibao-xjtu  val in_wb_valids = writebacks.map(_.map(w => w.valid && w.bits.has_exception && !lastCycleFlush))
97780712aaSxiaofeibao-xjtu  val wb_valid = in_wb_valids.zip(writebacks).map { case (valid, wb) =>
98780712aaSxiaofeibao-xjtu    valid.zip(wb.map(_.bits)).map { case (v, bits) => v && !(bits.robIdx.needFlush(io.redirect) || io.flush) }.reduce(_ || _)
99780712aaSxiaofeibao-xjtu  }
100780712aaSxiaofeibao-xjtu  val wb_bits = in_wb_valids.zip(writebacks).map { case (valid, wb) => getOldest(valid, wb.map(_.bits))}
101780712aaSxiaofeibao-xjtu
102780712aaSxiaofeibao-xjtu  val s0_out_valid = wb_valid.map(x => RegNext(x))
103780712aaSxiaofeibao-xjtu  val s0_out_bits = wb_bits.zip(wb_valid).map{ case(b, v) => RegEnable(b, v)}
104780712aaSxiaofeibao-xjtu
105780712aaSxiaofeibao-xjtu  // s1: compare last six and current flush
106780712aaSxiaofeibao-xjtu  val s1_valid = VecInit(s0_out_valid.zip(s0_out_bits).map{ case (v, b) => v && !(b.robIdx.needFlush(io.redirect) || io.flush) })
107780712aaSxiaofeibao-xjtu  val s1_out_bits = RegEnable(getOldest(s0_out_valid, s0_out_bits), s1_valid.asUInt.orR)
108780712aaSxiaofeibao-xjtu  val s1_out_valid = RegNext(s1_valid.asUInt.orR)
109780712aaSxiaofeibao-xjtu
1103e8a0170SXuan Hu  val enq_s1_valid = RegNext(enq_s0_valid.asUInt.orR && !io.redirect.valid && !io.flush)
1113e8a0170SXuan Hu  val enq_s1_bits: RobExceptionInfo = RegEnable(ParallelPriorityMux(enq_s0_valid, enq_s0_bits), enq_s0_valid.asUInt.orR && !io.redirect.valid && !io.flush)
112780712aaSxiaofeibao-xjtu
113780712aaSxiaofeibao-xjtu  // s2: compare the input exception with the current one
114780712aaSxiaofeibao-xjtu  // priorities:
115780712aaSxiaofeibao-xjtu  // (1) system reset
116780712aaSxiaofeibao-xjtu  // (2) current is valid: flush, remain, merge, update
117780712aaSxiaofeibao-xjtu  // (3) current is not valid: s1 or enq
118780712aaSxiaofeibao-xjtu  val current_flush = current.robIdx.needFlush(io.redirect) || io.flush
119780712aaSxiaofeibao-xjtu  val s1_flush = s1_out_bits.robIdx.needFlush(io.redirect) || io.flush
120a8c570daSAnzooooo
121a8c570daSAnzooooo  val isVecUpdate = s1_out_bits.vstart < current.vstart || !current.vstartEn
122780712aaSxiaofeibao-xjtu  when (currentValid) {
123780712aaSxiaofeibao-xjtu    when (current_flush) {
124780712aaSxiaofeibao-xjtu      currentValid := Mux(s1_flush, false.B, s1_out_valid)
125780712aaSxiaofeibao-xjtu    }
126780712aaSxiaofeibao-xjtu    when (s1_out_valid && !s1_flush) {
127780712aaSxiaofeibao-xjtu      when (isAfter(current.robIdx, s1_out_bits.robIdx)) {
128780712aaSxiaofeibao-xjtu        current := s1_out_bits
129*c01e75b5SZiyue Zhang        // s1 is older than current and caused by wb, set current.isEnqExcp to false
130*c01e75b5SZiyue Zhang        current.isEnqExcp := false.B
131780712aaSxiaofeibao-xjtu      }.elsewhen (current.robIdx === s1_out_bits.robIdx) {
132a8c570daSAnzooooo        current.exceptionVec := Mux(isVecUpdate, s1_out_bits.exceptionVec, current.exceptionVec)
13319870d35SXuan Hu        current.hasException := Mux(isVecUpdate, s1_out_bits.hasException, current.hasException)
134c0355297SAnzooooo        current.flushPipe := (s1_out_bits.flushPipe || current.flushPipe) && !s1_out_bits.exceptionVec.asUInt.orR
135780712aaSxiaofeibao-xjtu        current.replayInst := s1_out_bits.replayInst || current.replayInst
136780712aaSxiaofeibao-xjtu        current.singleStep := s1_out_bits.singleStep || current.singleStep
13719870d35SXuan Hu        current.trigger   := Mux(isVecUpdate, s1_out_bits.trigger,    current.trigger)
138a8c570daSAnzooooo        current.vstart    := Mux(isVecUpdate, s1_out_bits.vstart,     current.vstart)
13919870d35SXuan Hu        current.vstartEn  := Mux(isVecUpdate, s1_out_bits.vstartEn,   current.vstartEn)
14019870d35SXuan Hu        current.isVecLoad := Mux(isVecUpdate, s1_out_bits.isVecLoad,  current.isVecLoad)
14119870d35SXuan Hu        current.isVlm     := Mux(isVecUpdate, s1_out_bits.isVlm,      current.isVlm)
14219870d35SXuan Hu        current.isStrided := Mux(isVecUpdate, s1_out_bits.isStrided,  current.isStrided)
14319870d35SXuan Hu        current.isIndexed := Mux(isVecUpdate, s1_out_bits.isIndexed,  current.isIndexed)
14419870d35SXuan Hu        current.isWhole   := Mux(isVecUpdate, s1_out_bits.isWhole,    current.isWhole)
14519870d35SXuan Hu        current.nf        := Mux(isVecUpdate, s1_out_bits.nf,         current.nf)
14619870d35SXuan Hu        current.vsew      := Mux(isVecUpdate, s1_out_bits.vsew,       current.vsew)
14719870d35SXuan Hu        current.veew      := Mux(isVecUpdate, s1_out_bits.veew,       current.veew)
14819870d35SXuan Hu        current.vlmul     := Mux(isVecUpdate, s1_out_bits.vlmul,      current.vlmul)
149*c01e75b5SZiyue Zhang        // current has a new exception caused by wb, set current.isEnqExcp to false
15011bd888fSXuan Hu        current.isEnqExcp := false.B
151ec6936cbSXuan Hu      }
152*c01e75b5SZiyue Zhang    }
153780712aaSxiaofeibao-xjtu  }.elsewhen (s1_out_valid && !s1_flush) {
154780712aaSxiaofeibao-xjtu    currentValid := true.B
155780712aaSxiaofeibao-xjtu    current := s1_out_bits
15611bd888fSXuan Hu    current.isEnqExcp := false.B
1573e8a0170SXuan Hu  }.elsewhen (enq_s1_valid && !(io.redirect.valid || io.flush)) {
158780712aaSxiaofeibao-xjtu    currentValid := true.B
1593e8a0170SXuan Hu    current := enq_s1_bits
16011bd888fSXuan Hu    current.isEnqExcp := true.B
161780712aaSxiaofeibao-xjtu  }
162780712aaSxiaofeibao-xjtu
1633e8a0170SXuan Hu  io.out.valid   := s1_out_valid || enq_s1_valid && enq_s1_bits.can_writeback
1643e8a0170SXuan Hu  io.out.bits    := Mux(s1_out_valid, s1_out_bits, enq_s1_bits)
165780712aaSxiaofeibao-xjtu  io.state.valid := currentValid
166780712aaSxiaofeibao-xjtu  io.state.bits  := current
167780712aaSxiaofeibao-xjtu
168780712aaSxiaofeibao-xjtu}
169