xref: /XiangShan/src/main/scala/xiangshan/backend/regcache/RegCache.scala (revision f8b278aa7f5c894b2f00114935bd4d8edb8a885c)
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.regcache
18
19import org.chipsalliance.cde.config.Parameters
20import chisel3._
21import chisel3.util._
22import utils._
23import utility._
24import xiangshan._
25import xiangshan.backend.BackendParams
26
27class RegCache()(implicit p: Parameters, params: BackendParams) extends XSModule {
28
29  val io = IO(new RegCacheIO())
30
31  println(s"[RegCache] readPorts: ${params.getIntExuRCReadSize} + ${params.getMemExuRCReadSize}, " +
32    s"writePorts: ${params.getIntExuRCWriteSize} + ${params.getMemExuRCWriteSize}")
33
34  println(s"[RegCache] dataWidth: ${params.intSchdParams.get.rfDataWidth}, addrWidth: ${RegCacheIdxWidth}, tagWidth: ${params.intSchdParams.get.pregIdxWidth}")
35
36  require(RegCacheIdxWidth == (log2Up(IntRegCacheSize) + 1), "IntRegCache should be half of the whole RegCache")
37  require(RegCacheIdxWidth == (log2Up(MemRegCacheSize) + 1), "MemRegCache should be half of the whole RegCache")
38
39  private val IntRegCacheReadSize = params.getIntExuRCReadSize + params.getMemExuRCReadSize
40  private val IntRegCacheWriteSize = params.getIntExuRCWriteSize
41  private val MemRegCacheReadSize = params.getIntExuRCReadSize + params.getMemExuRCReadSize
42  private val MemRegCacheWriteSize = params.getMemExuRCWriteSize
43
44  val IntRegCache = Module(new RegCacheDataModule("IntRegCache", IntRegCacheSize, IntRegCacheReadSize, IntRegCacheWriteSize,
45                                                  params.intSchdParams.get.rfDataWidth, RegCacheIdxWidth - 1, params.intSchdParams.get.pregIdxWidth))
46
47  val MemRegCache = Module(new RegCacheDataModule("MemRegCache", MemRegCacheSize, MemRegCacheReadSize, MemRegCacheWriteSize,
48                                                  params.intSchdParams.get.rfDataWidth, RegCacheIdxWidth - 1, params.intSchdParams.get.pregIdxWidth))
49
50  val IntRegCacheAgeTimer = Module(new RegCacheAgeTimer(IntRegCacheSize, IntRegCacheReadSize, IntRegCacheWriteSize, RegCacheIdxWidth - 1))
51
52  val MemRegCacheAgeTimer = Module(new RegCacheAgeTimer(MemRegCacheSize, MemRegCacheReadSize, MemRegCacheWriteSize, RegCacheIdxWidth - 1))
53
54  val IntRegCacheRepRCIdx = RegCacheAgeDetector(IntRegCacheSize, IntRegCacheWriteSize, IntRegCacheAgeTimer.io.ageInfo)
55  val MemRegCacheRepRCIdx = RegCacheAgeDetector(MemRegCacheSize, MemRegCacheWriteSize, MemRegCacheAgeTimer.io.ageInfo)
56
57  IntRegCacheAgeTimer.io.validInfo := IntRegCache.io.validInfo
58  MemRegCacheAgeTimer.io.validInfo := MemRegCache.io.validInfo
59
60  io.readPorts
61  .lazyZip(IntRegCache.io.readPorts.lazyZip(MemRegCache.io.readPorts))
62  .lazyZip(IntRegCacheAgeTimer.io.readPorts.lazyZip(MemRegCacheAgeTimer.io.readPorts))
63  .foreach{ case (r_in, (r_int, r_mem), (r_int_at, r_mem_at)) =>
64    val in_addr = RegEnable(r_in.addr, r_in.ren)
65    val int_ren = GatedValidRegNext(r_in.ren & ~r_in.addr(RegCacheIdxWidth - 1))
66    val mem_ren = GatedValidRegNext(r_in.ren & r_in.addr(RegCacheIdxWidth - 1))
67    r_int.ren  := int_ren
68    r_mem.ren  := mem_ren
69    r_int.addr := in_addr(RegCacheIdxWidth - 2, 0)
70    r_mem.addr := in_addr(RegCacheIdxWidth - 2, 0)
71    r_in.data  := Mux(in_addr(RegCacheIdxWidth - 1), r_mem.data, r_int.data)
72    r_int_at.ren  := int_ren
73    r_mem_at.ren  := mem_ren
74    r_int_at.addr := in_addr(RegCacheIdxWidth - 2, 0)
75    r_mem_at.addr := in_addr(RegCacheIdxWidth - 2, 0)
76  }
77
78  val writePorts = Wire(chiselTypeOf(io.writePorts))
79
80  IntRegCache.io.writePorts.zip(writePorts.take(IntRegCacheWriteSize)).foreach{ case (w_int, w_in) =>
81    w_int.wen  := w_in.wen
82    w_int.addr := w_in.addr(RegCacheIdxWidth - 2, 0)
83    w_int.data := w_in.data
84    w_int.tag.foreach(_ := w_in.tag.get)
85  }
86
87  MemRegCache.io.writePorts.zip(writePorts.takeRight(MemRegCacheWriteSize)).foreach{ case (w_mem, w_in) =>
88    w_mem.wen  := w_in.wen
89    w_mem.addr := w_in.addr(RegCacheIdxWidth - 2, 0)
90    w_mem.data := w_in.data
91    w_mem.tag.foreach(_ := w_in.tag.get)
92  }
93
94  IntRegCacheAgeTimer.io.writePorts.zip(writePorts.take(IntRegCacheWriteSize)).foreach{ case (w_int, w_in) =>
95    w_int.wen  := w_in.wen
96    w_int.addr := w_in.addr(RegCacheIdxWidth - 2, 0)
97  }
98
99  MemRegCacheAgeTimer.io.writePorts.zip(writePorts.takeRight(MemRegCacheWriteSize)).foreach{ case (w_mem, w_in) =>
100    w_mem.wen  := w_in.wen
101    w_mem.addr := w_in.addr(RegCacheIdxWidth - 2, 0)
102  }
103
104  io.toWakeupQueueRCIdx.zipWithIndex.foreach{ case (rcIdx, i) =>
105    if (i < IntRegCacheWriteSize) {
106      rcIdx := Cat("b0".U, IntRegCacheRepRCIdx(i))
107    }
108    else {
109      rcIdx := Cat("b1".U, MemRegCacheRepRCIdx(i - IntRegCacheWriteSize))
110    }
111  }
112
113  val delayToWakeupQueueRCIdx = RegNextN(io.toWakeupQueueRCIdx, 3)
114  writePorts := io.writePorts
115  writePorts.zip(delayToWakeupQueueRCIdx).foreach{ case (w, rcIdx) =>
116    w.addr := rcIdx
117  }
118}
119
120class RegCacheIO()(implicit p: Parameters, params: BackendParams) extends XSBundle {
121
122  val readPorts = Vec(params.getIntExuRCReadSize + params.getMemExuRCReadSize,
123    new RCReadPort(params.intSchdParams.get.rfDataWidth, RegCacheIdxWidth))
124
125  val writePorts = Vec(params.getIntExuRCWriteSize + params.getMemExuRCWriteSize,
126    new RCWritePort(params.intSchdParams.get.rfDataWidth, RegCacheIdxWidth, params.intSchdParams.get.pregIdxWidth, params.debugEn))
127
128  val toWakeupQueueRCIdx = Vec(params.getIntExuRCWriteSize + params.getMemExuRCWriteSize,
129     Output(UInt(RegCacheIdxWidth.W)))
130}
131