xref: /XiangShan/src/main/scala/xiangshan/backend/issue/DataArray.scala (revision 8891a219bbc84f568e1d134854d8d5ed86d6d560)
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.issue
18
19import org.chipsalliance.cde.config.Parameters
20import chisel3._
21import chisel3.util._
22import xiangshan._
23import utils._
24import utility._
25import xiangshan.backend.decode.{ImmUnion, Imm_LUI_LOAD, Imm_U}
26import xiangshan.backend.exu.ExuConfig
27
28class DataArrayReadIO(numEntries: Int, numSrc: Int, dataBits: Int)(implicit p: Parameters) extends XSBundle {
29  val addr = Input(UInt(numEntries.W))
30  val data = Vec(numSrc, Output(UInt(dataBits.W)))
31}
32
33class DataArrayWriteIO(numEntries: Int, numSrc: Int, dataBits: Int)(implicit p: Parameters) extends XSBundle {
34  val enable = Input(Bool())
35  val mask   = Vec(numSrc, Input(Bool()))
36  val addr   = Input(UInt(numEntries.W))
37  val data   = Vec(numSrc, Input(UInt(dataBits.W)))
38}
39
40class DataArrayMultiWriteIO(numEntries: Int, numSrc: Int, dataBits: Int)(implicit p: Parameters) extends XSBundle {
41  val enable = Input(Bool())
42  val addr   = Vec(numSrc, Input(UInt(numEntries.W)))
43  val data   = Input(UInt(dataBits.W))
44}
45
46class DataArrayDelayedWriteIO(numEntries: Int, numSrc: Int, dataBits: Int)(implicit p: Parameters) extends XSBundle {
47  val mask = Vec(numSrc, Input(Bool()))
48  val addr = Input(UInt(numEntries.W))
49  val data = Vec(numSrc, Input(UInt(dataBits.W)))
50}
51
52class DataArrayIO(params: RSParams)(implicit p: Parameters) extends XSBundle {
53  val read = Vec(params.numDeq + 1, new DataArrayReadIO(params.numEntries, params.numSrc, params.dataBits))
54  val write = Vec(params.numEnq, new DataArrayWriteIO(params.numEntries, params.numSrc, params.dataBits))
55  val multiWrite = Vec(params.numWakeup, new DataArrayMultiWriteIO(params.numEntries, params.numSrc, params.dataBits))
56  val delayedWrite = if (params.delayedSrc) Vec(params.numEnq, new DataArrayDelayedWriteIO(params.numEntries, params.numSrc, params.dataBits)) else null
57  val partialWrite = if (params.hasMidState) Vec(params.numDeq, new DataArrayWriteIO(params.numEntries, params.numSrc - 1, params.dataBits)) else null
58}
59
60class DataArray(params: RSParams)(implicit p: Parameters) extends XSModule {
61  val io = IO(new DataArrayIO(params))
62
63  for (i <- 0 until params.numSrc) {
64    val delayedWen = if (params.delayedSrc) io.delayedWrite.map(_.mask(i)) else Seq()
65    val delayedWaddr = if (params.delayedSrc) io.delayedWrite.map(_.addr) else Seq()
66    val delayedWdata = if (params.delayedSrc) io.delayedWrite.map(_.data(i)) else Seq()
67
68    val partialWen = if (i < 2 && params.hasMidState) io.partialWrite.map(w => RegNext(w.enable)) else Seq()
69    val partialWaddr = if (i < 2 && params.hasMidState) io.partialWrite.map(w => RegEnable(w.addr, w.enable)) else Seq()
70    val partialWdata = if (i < 2 && params.hasMidState) io.partialWrite.map(w => RegEnable(w.data(i), w.enable)) else Seq()
71
72    val wen = io.write.map(w => w.enable && w.mask(i)) ++ io.multiWrite.map(_.enable) ++ delayedWen ++ partialWen
73    val waddr = io.write.map(_.addr) ++ io.multiWrite.map(_.addr(i)) ++ delayedWaddr ++ partialWaddr
74    val wdata = io.write.map(_.data(i)) ++ io.multiWrite.map(_.data) ++ delayedWdata ++ partialWdata
75
76    val dataModule = Module(new AsyncRawDataModuleTemplate(UInt(params.dataBits.W), params.numEntries, io.read.length, wen.length))
77    dataModule.io.rvec := VecInit(io.read.map(_.addr))
78    io.read.map(_.data(i)).zip(dataModule.io.rdata).foreach{ case (d, r) => d := r }
79    dataModule.io.wen := wen
80    dataModule.io.wvec := waddr
81    dataModule.io.wdata := wdata
82
83    if (i < 2 && params.hasMidState) {
84      for (r <- io.read) {
85        val addr_match = partialWaddr.map(addr => (addr & r.addr).asUInt.orR)
86        val bypass = partialWen.zip(addr_match).map(p => p._1 && p._2)
87        when (VecInit(bypass).asUInt.orR) {
88          r.data(i) := Mux1H(bypass, partialWdata)
89        }
90      }
91    }
92
93    for (i <- 0 until params.numEntries) {
94      val w = VecInit(wen.indices.map(j => dataModule.io.wen(j) && dataModule.io.wvec(j)(i)))
95      XSError(RegNext(PopCount(w) > 1.U), s"why not OH $i?")
96      when(PopCount(w) > 1.U) {
97        XSDebug("ERROR: RS DataArray write overlap!\n")
98      }
99    }
100  }
101
102}
103
104class ImmExtractor(numSrc: Int, dataBits: Int)(implicit p: Parameters) extends XSModule {
105  val io = IO(new Bundle {
106    val uop = Input(new MicroOp)
107    val data_in = Vec(numSrc, Input(UInt(dataBits.W)))
108    val data_out = Vec(numSrc, Output(UInt(dataBits.W)))
109  })
110  io.data_out := io.data_in
111}
112
113class JumpImmExtractor(implicit p: Parameters) extends ImmExtractor(2, 64) {
114  val jump_pc = IO(Input(UInt(VAddrBits.W)))
115  val jalr_target = IO(Input(UInt(VAddrBits.W)))
116
117  when (SrcType.isPc(io.uop.ctrl.srcType(0))) {
118    io.data_out(0) := SignExt(jump_pc, XLEN)
119  }
120  // when src1 is reg (like sfence's asid) do not let data_out(1) be the jalr_target
121  when (SrcType.isPcOrImm(io.uop.ctrl.srcType(1))) {
122    io.data_out(1) := jalr_target
123  }
124}
125
126class AluImmExtractor(implicit p: Parameters) extends ImmExtractor(2, 64) {
127  when (SrcType.isImm(io.uop.ctrl.srcType(1))) {
128    val imm32 = Mux(io.uop.ctrl.selImm === SelImm.IMM_U,
129      ImmUnion.U.toImm32(io.uop.ctrl.imm),
130      ImmUnion.I.toImm32(io.uop.ctrl.imm)
131    )
132    io.data_out(1) := SignExt(imm32, XLEN)
133  }
134}
135
136class MduImmExtractor(implicit p: Parameters) extends ImmExtractor(2, 64) {
137  when (SrcType.isImm(io.uop.ctrl.srcType(1))) {
138    val imm32 = ImmUnion.I.toImm32(io.uop.ctrl.imm)
139    io.data_out(1) := SignExt(imm32, XLEN)
140  }
141}
142
143class LoadImmExtractor(implicit p: Parameters) extends ImmExtractor(1, 64) {
144  when (SrcType.isImm(io.uop.ctrl.srcType(0))) {
145    io.data_out(0) := SignExt(Imm_LUI_LOAD().getLuiImm(io.uop), XLEN)
146  }
147}
148
149object ImmExtractor {
150  def apply(params: RSParams, uop: MicroOp, data_in: Vec[UInt], pc: Option[UInt], target: Option[UInt])
151           (implicit p: Parameters): Vec[UInt] = {
152    val immExt = if (params.isJump) {
153      val ext = Module(new JumpImmExtractor)
154      ext.jump_pc := pc.get
155      ext.jalr_target := target.get
156      ext
157    }
158    else if (params.isAlu) { Module(new AluImmExtractor) }
159    else if (params.isMul) { Module(new MduImmExtractor) }
160    else if (params.isLoad) { Module(new LoadImmExtractor) }
161    else { Module(new ImmExtractor(params.numSrc, params.dataBits)) }
162    immExt.io.uop := uop
163    immExt.io.data_in := data_in
164    immExt.io.data_out
165  }
166}
167