xref: /XiangShan/src/main/scala/xiangshan/backend/rename/CompressUnit.scala (revision 039cdc35f5f3b68b6295ec5ace90f22a77322e02)
1package xiangshan.backend.rename
2
3import org.chipsalliance.cde.config.Parameters
4import chisel3.Bundle
5import xiangshan.backend.Bundles.DecodedInst
6import xiangshan.XSModule
7import chisel3._
8import chisel3.util._
9import freechips.rocketchip.rocket.DecodeLogic
10import xiangshan._
11
12class CompressUnit(implicit p: Parameters) extends XSModule{
13  val io = IO(new Bundle {
14    val in = Vec(RenameWidth, Flipped(Valid(new DecodedInst)))
15    val out = new Bundle {
16      val needRobFlags = Vec(RenameWidth, Output(Bool()))
17      val instrSizes = Vec(RenameWidth, Output(UInt(log2Ceil(RenameWidth + 1).W)))
18      val masks = Vec(RenameWidth, Output(UInt(RenameWidth.W)))
19    }
20  })
21
22  val noExc = io.in.map(!_.bits.exceptionVec.asUInt.orR)
23  val uopCanCompress = io.in.map(_.bits.canRobCompress)
24  val canCompress = io.in.zip(noExc).zip(uopCanCompress).map { case ((in, noExc), canComp) =>
25    in.valid && !CommitType.isFused(in.bits.commitType) && in.bits.lastUop && noExc && canComp
26  }
27
28  val compressTable = (0 until 1 << RenameWidth).map { case keyCandidate =>
29    // padding 0s at each side for convenience
30    val key = 0 +: (0 until RenameWidth).map(idx => (keyCandidate >> idx) & 1) :+ 0
31    // count 1s on the left side of key (including itself)
32    def cntL(idx: Int): Int = (if (key(idx - 1) == 1) cntL(idx - 1) else 0) + key(idx)
33    // count 1s on the right side of key (including itself)
34    def cntR(idx: Int): Int = (if (key(idx + 1) == 1) cntR(idx + 1) else 0) + key(idx)
35    // the last instruction among consecutive rob-compressed instructions is marked
36    val needRobs = (0 until RenameWidth).map(idx => ~(key.tail(idx) & key.tail(idx + 1)) & 1)
37    // how many instructions are rob-compressed with this instruction (including itself)
38    val uopSizes = (1 to RenameWidth).map(idx => if (key(idx) == 0) 1 else cntL(idx) + cntR(idx) - 1)
39    // which instructions are rob-compressed with this instruction
40    val masks = uopSizes.zip(1 to RenameWidth).map { case (size, idx) => // compress masks
41      if (key(idx) == 0) Seq.fill(RenameWidth)(0).updated(idx - 1, 1)
42      else Seq.fill(RenameWidth)(0).patch(idx - cntL(idx), Seq.fill(size)(1), size)
43    }
44
45    println("[Rename.Compress]" +
46      " i: "        + keyCandidate +
47      " key: "      + key.tail.dropRight(1) +
48      " needRobs: " + needRobs +
49      " uopSizes: " + uopSizes +
50      " masks: "    + masks.map(_.map(_.toBinaryString).reduce(_ + _))
51    )
52
53    val keyBitPat = BitPat(keyCandidate.U)
54    val needRobBitPats = needRobs.map(x => BitPat(x.U))
55    val uopSizeBitPats = uopSizes.map(x => BitPat(x.U))
56    val maskBitPats = masks.map(m => BitPat(m.foldRight(0)(_ | _ << 1).U))
57
58    (keyBitPat -> (needRobBitPats ++ uopSizeBitPats ++ maskBitPats))
59  }
60
61  val default = Seq.fill(3 * RenameWidth)(BitPat.N())
62  val decoder = DecodeLogic(VecInit(canCompress).asUInt, default, compressTable)
63  (io.out.needRobFlags ++ io.out.instrSizes ++ io.out.masks).zip(decoder).foreach {
64    case (sink, source) => sink := source
65  }
66}
67