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