xref: /XiangShan/src/main/scala/xiangshan/backend/rename/CompressUnit.scala (revision b720b0cd6c9c77ec4fddf067662248c19fb09348)
1/***************************************************************************************
2* Copyright (c) 2024 Beijing Institute of Open Source Chip (BOSC)
3* Copyright (c) 2020-2024 Institute of Computing Technology, Chinese Academy of Sciences
4* Copyright (c) 2020-2021 Peng Cheng Laboratory
5*
6* XiangShan is licensed under Mulan PSL v2.
7* You can use this software according to the terms and conditions of the Mulan PSL v2.
8* You may obtain a copy of Mulan PSL v2 at:
9*          http://license.coscl.org.cn/MulanPSL2
10*
11* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
12* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
13* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
14*
15* See the Mulan PSL v2 for more details.
16*
17*
18* Acknowledgement
19*
20* This implementation is inspired by several key papers:
21* [1] Fernando Latorre, Grigorios Magklis, Jose González, Pedro Chaparro, and Antonio González. "[Crob: implementing a
22* large instruction window through compression.](https://doi.org/10.1007/978-3-642-19448-1_7)" Transactions on
23* High-Performance Embedded Architectures and Compilers III: 115-134. Berlin, Heidelberg: Springer Berlin Heidelberg.
24* 2011.
25***************************************************************************************/
26
27package xiangshan.backend.rename
28
29import org.chipsalliance.cde.config.Parameters
30import chisel3.Bundle
31import xiangshan.backend.Bundles.DecodedInst
32import xiangshan.XSModule
33import chisel3._
34import chisel3.util._
35import freechips.rocketchip.rocket.DecodeLogic
36import xiangshan._
37
38class CompressUnit(implicit p: Parameters) extends XSModule{
39  val io = IO(new Bundle {
40    val in = Vec(RenameWidth, Flipped(Valid(new DecodedInst)))
41    val out = new Bundle {
42      val needRobFlags = Vec(RenameWidth, Output(Bool()))
43      val instrSizes = Vec(RenameWidth, Output(UInt(log2Ceil(RenameWidth + 1).W)))
44      val masks = Vec(RenameWidth, Output(UInt(RenameWidth.W)))
45      val canCompressVec = Vec(RenameWidth, Output(Bool()))
46    }
47  })
48
49  val noExc = io.in.map(in => !in.bits.exceptionVec.asUInt.orR && !TriggerAction.isDmode(in.bits.trigger))
50  val uopCanCompress = io.in.map(_.bits.canRobCompress)
51  val canCompress = io.in.zip(noExc).zip(uopCanCompress).map { case ((in, noExc), canComp) =>
52    in.valid && !CommitType.isFused(in.bits.commitType) && in.bits.lastUop && noExc && canComp
53  }
54
55  val compressTable = (0 until 1 << RenameWidth).map { case keyCandidate =>
56    // padding 0s at each side for convenience
57    val key = 0 +: (0 until RenameWidth).map(idx => (keyCandidate >> idx) & 1) :+ 0
58    // count 1s on the left side of key (including itself)
59    def cntL(idx: Int): Int = (if (key(idx - 1) == 1) cntL(idx - 1) else 0) + key(idx)
60    // count 1s on the right side of key (including itself)
61    def cntR(idx: Int): Int = (if (key(idx + 1) == 1) cntR(idx + 1) else 0) + key(idx)
62    // the last instruction among consecutive rob-compressed instructions is marked
63    val needRobs = (0 until RenameWidth).map(idx => ~(key.tail(idx) & key.tail(idx + 1)) & 1)
64    // how many instructions are rob-compressed with this instruction (including itself)
65    val uopSizes = (1 to RenameWidth).map(idx => if (key(idx) == 0) 1 else cntL(idx) + cntR(idx) - 1)
66    // which instructions are rob-compressed with this instruction
67    val masks = uopSizes.zip(1 to RenameWidth).map { case (size, idx) => // compress masks
68      if (key(idx) == 0) Seq.fill(RenameWidth)(0).updated(idx - 1, 1)
69      else Seq.fill(RenameWidth)(0).patch(idx - cntL(idx), Seq.fill(size)(1), size)
70    }
71
72    println("[Rename.Compress]" +
73      " i: "        + keyCandidate +
74      " key: "      + key.tail.dropRight(1) +
75      " needRobs: " + needRobs +
76      " uopSizes: " + uopSizes +
77      " masks: "    + masks.map(_.map(_.toBinaryString).reduce(_ + _))
78    )
79
80    val keyBitPat = BitPat(keyCandidate.U)
81    val needRobBitPats = needRobs.map(x => BitPat(x.U))
82    val uopSizeBitPats = uopSizes.map(x => BitPat(x.U))
83    val maskBitPats = masks.map(m => BitPat(m.foldRight(0)(_ | _ << 1).U))
84
85    (keyBitPat -> (needRobBitPats ++ uopSizeBitPats ++ maskBitPats))
86  }
87
88  val default = Seq.fill(3 * RenameWidth)(BitPat.N())
89  val decoder = DecodeLogic(VecInit(canCompress).asUInt, default, compressTable)
90  (io.out.needRobFlags ++ io.out.instrSizes ++ io.out.masks).zip(decoder).foreach {
91    case (sink, source) => sink := source
92  }
93  io.out.canCompressVec := VecInit(canCompress)
94}
95