xref: /XiangShan/src/main/scala/xiangshan/backend/exu/ExeUnit.scala (revision 5668a921eb594c3ea72da43594b3fb54e05959a3)
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.exu
18
19
20import chipsalliance.rocketchip.config.Parameters
21import chisel3._
22import chisel3.experimental.hierarchy.{Definition, instantiable, public}
23import chisel3.util._
24import utils._
25import xiangshan._
26import xiangshan.backend.Std
27import xiangshan.backend.fu.fpu.{FMA, FPUSubModule}
28import xiangshan.backend.fu.{CSR, FUWithRedirect, Fence, FenceToSbuffer}
29
30class FenceIO(implicit p: Parameters) extends XSBundle {
31  val sfence = Output(new SfenceBundle)
32  val fencei = Output(Bool())
33  val sbuffer = new FenceToSbuffer
34}
35
36@instantiable
37class ExeUnit(config: ExuConfig)(implicit p: Parameters) extends Exu(config) {
38
39  val disableSfence = WireInit(false.B)
40  val csr_frm = WireInit(frm.getOrElse(0.U(3.W)))
41
42  val hasRedirect = config.fuConfigs.zip(functionUnits).filter(_._1.hasRedirect).map(_._2)
43  println(s"${functionUnits} ${hasRedirect} hasRedirect: ${hasRedirect.length}")
44  if (hasRedirect.nonEmpty) {
45    require(hasRedirect.length <= 1)
46    io.out.bits.redirectValid := hasRedirect.head.asInstanceOf[FUWithRedirect].redirectOutValid
47    io.out.bits.redirect := hasRedirect.head.asInstanceOf[FUWithRedirect].redirectOut
48  }
49
50  if (config.fuConfigs.contains(csrCfg)) {
51    val csr = functionUnits.collectFirst{
52      case c: CSR => c
53    }.get
54    csr.csrio <> csrio.get
55    disableSfence := csr.csrio.disableSfence
56    csr_frm := csr.csrio.fpu.frm
57    // setup skip for hpm CSR read
58    io.out.bits.debug.isPerfCnt := RegNext(csr.csrio.isPerfCnt) // TODO: this is dirty
59  }
60
61  if (config.fuConfigs.contains(fenceCfg)) {
62    val fence = functionUnits.collectFirst{
63      case f: Fence => f
64    }.get
65    fenceio.get.sfence <> fence.sfence
66    fenceio.get.fencei <> fence.fencei
67    fenceio.get.sbuffer <> fence.toSbuffer
68    fence.io.out.ready := true.B
69    fence.disableSfence := disableSfence
70  }
71
72  val fpModules = functionUnits.zip(config.fuConfigs.zipWithIndex).filter(_._1.isInstanceOf[FPUSubModule])
73  if (fpModules.nonEmpty) {
74    // frm is from csr/frm (from CSR) or instr_rm (from instruction decoding)
75    val fpSubModules = fpModules.map(_._1.asInstanceOf[FPUSubModule])
76    fpSubModules.foreach(mod => {
77      val instr_rm = mod.io.in.bits.uop.ctrl.fpu.rm
78      mod.rm := Mux(instr_rm =/= 7.U, instr_rm, csr_frm)
79    })
80    // fflags is selected by arbSelReg
81    require(config.hasFastUopOut, "non-fast not implemented")
82    val fflagsSel = fpModules.map{ case (fu, (cfg, i)) =>
83      val fflagsValid = arbSelReg(i)
84      val fflags = fu.asInstanceOf[FPUSubModule].fflags
85      val fflagsBits = if (cfg.fastImplemented) fflags else RegNext(fflags)
86      (fflagsValid, fflagsBits)
87    }
88    io.out.bits.fflags := Mux1H(fflagsSel.map(_._1), fflagsSel.map(_._2))
89  }
90
91  val fmaModules = functionUnits.filter(_.isInstanceOf[FMA]).map(_.asInstanceOf[FMA])
92  if (fmaModules.nonEmpty) {
93    require(fmaModules.length == 1)
94    fmaModules.head.midResult <> fmaMid.get
95  }
96
97  if (config.fuConfigs.contains(stdCfg)) {
98    val std = functionUnits.collectFirst {
99      case s: Std => s
100    }.get
101    stData.get.valid := std.io.out.valid
102    stData.get.bits.uop := std.io.out.bits.uop
103    stData.get.bits.data := std.io.out.bits.data
104    io.out.valid := false.B
105    io.out.bits := DontCare
106  }
107
108  if (config.readIntRf) {
109    val in = io.fromInt
110    val out = io.out
111    XSDebug(in.valid, p"fromInt(${in.valid} ${in.ready}) toInt(${out.valid} ${out.ready})\n")
112    XSDebug(io.redirect.valid, p"Redirect:(${io.redirect.valid}) robIdx:${io.redirect.bits.robIdx}\n")
113    XSDebug(in.valid, p"src1:${Hexadecimal(in.bits.src(0))} src2:${Hexadecimal(in.bits.src(1))} " +
114      p"func:${Binary(in.bits.uop.ctrl.fuOpType)} pc:${Hexadecimal(in.bits.uop.cf.pc)} robIdx:${in.bits.uop.robIdx}\n")
115    XSDebug(out.valid, p"out res:${Hexadecimal(out.bits.data)} robIdx:${out.bits.uop.robIdx}\n")
116  }
117
118}
119
120class AluExeUnit(implicit p: Parameters) extends ExeUnit(AluExeUnitCfg)
121class JumpCSRExeUnit(implicit p: Parameters) extends ExeUnit(JumpCSRExeUnitCfg)
122class JumpExeUnit(implicit p: Parameters) extends ExeUnit(JumpExeUnitCfg)
123class StdExeUnit(implicit p: Parameters) extends ExeUnit(StdExeUnitCfg)
124class FmacExeUnit(implicit p: Parameters) extends ExeUnit(FmacExeUnitCfg)
125class FmiscExeUnit(implicit p: Parameters) extends ExeUnit(FmiscExeUnitCfg)
126
127object ExeUnitDef {
128  def apply(cfg: ExuConfig)(implicit p: Parameters): Definition[ExeUnit] = {
129    cfg match {
130      case JumpExeUnitCfg => Definition(new JumpExeUnit)
131      case AluExeUnitCfg => Definition(new AluExeUnit)
132      case MulDivExeUnitCfg => Definition(new MulDivExeUnit)
133      case JumpCSRExeUnitCfg => Definition(new JumpCSRExeUnit)
134      case FmacExeUnitCfg => Definition(new FmacExeUnit)
135      case FmiscExeUnitCfg => Definition(new FmiscExeUnit)
136      case StdExeUnitCfg => Definition(new StdExeUnit)
137      case _ => {
138        println(s"cannot generate exeUnit from $cfg")
139        null
140      }
141    }
142  }
143}
144
145