xref: /XiangShan/src/main/scala/xiangshan/backend/rename/BusyTable.scala (revision cd365d4ca1205723617d915c8588e09b1ecb1819)
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.rename
18
19import chipsalliance.rocketchip.config.Parameters
20import chisel3._
21import chisel3.util._
22import xiangshan._
23import utils._
24
25class BusyTableReadIO(implicit p: Parameters) extends XSBundle {
26  val req = Input(UInt(PhyRegIdxWidth.W))
27  val resp = Output(Bool())
28}
29
30class BusyTable(numReadPorts: Int, numWritePorts: Int)(implicit p: Parameters) extends XSModule {
31  val io = IO(new Bundle() {
32    // set preg state to busy
33    val allocPregs = Vec(RenameWidth, Flipped(ValidIO(UInt(PhyRegIdxWidth.W))))
34    // set preg state to ready (write back regfile + rob walk)
35    val wbPregs = Vec(numWritePorts, Flipped(ValidIO(UInt(PhyRegIdxWidth.W))))
36    // read preg state
37    val read = Vec(numReadPorts, new BusyTableReadIO)
38  })
39
40  val table = RegInit(0.U(NRPhyRegs.W))
41
42  def reqVecToMask(rVec: Vec[Valid[UInt]]): UInt = {
43    ParallelOR(rVec.map(v => Mux(v.valid, UIntToOH(v.bits), 0.U)))
44  }
45
46  val wbMask = reqVecToMask(io.wbPregs)
47  val allocMask = reqVecToMask(io.allocPregs)
48
49  val tableAfterWb = table & (~wbMask).asUInt
50  val tableAfterAlloc = tableAfterWb | allocMask
51
52  io.read.map(r => r.resp := !table(r.req))
53
54  table := tableAfterAlloc
55
56  XSDebug(p"table    : ${Binary(table)}\n")
57  XSDebug(p"tableNext: ${Binary(tableAfterAlloc)}\n")
58  XSDebug(p"allocMask: ${Binary(allocMask)}\n")
59  XSDebug(p"wbMask   : ${Binary(wbMask)}\n")
60  for (i <- 0 until NRPhyRegs) {
61    XSDebug(table(i), "%d is busy\n", i.U)
62  }
63
64  XSPerfAccumulate("busy_count", PopCount(table))
65  val perfinfo = IO(new Bundle(){
66    val perfEvents = Output(new PerfEventsBundle(4))
67  })
68  val perfEvents = Seq(
69    ("std_freelist_1/4_valid          ", (PopCount(table) < (NRPhyRegs.U/4.U))                                             ),
70    ("std_freelist_2/4_valid          ", (PopCount(table) > (NRPhyRegs.U/4.U)) & (PopCount(table) <= (NRPhyRegs.U/2.U))    ),
71    ("std_freelist_3/4_valid          ", (PopCount(table) > (NRPhyRegs.U/2.U)) & (PopCount(table) <= (NRPhyRegs.U*3.U/4.U))),
72    ("std_freelist_4/4_valid          ", (PopCount(table) > (NRPhyRegs.U*3.U/4.U))                                         ),
73  )
74
75  for (((perf_out,(perf_name,perf)),i) <- perfinfo.perfEvents.perf_events.zip(perfEvents).zipWithIndex) {
76    perf_out.incr_step := RegNext(perf)
77  }
78}
79