xref: /XiangShan/src/main/scala/xiangshan/backend/rename/Snapshot.scala (revision 8b33cd30e0034914b58520e0dc3c0c4b1aad6a03)
1package xiangshan.backend.rename
2
3import org.chipsalliance.cde.config.Parameters
4import chisel3._
5import chisel3.util._
6import utility.{CircularQueuePtr, HasCircularQueuePtrHelper, XSError}
7import xiangshan.{XSCoreParamsKey, XSModule}
8
9
10class SnapshotPtr(implicit p: Parameters) extends CircularQueuePtr[SnapshotPtr](
11  p => p(XSCoreParamsKey).RenameSnapshotNum
12)
13
14object SnapshotGenerator extends HasCircularQueuePtrHelper {
15  def apply[T <: Data](enqData: T, enq: Bool, deq: Bool, redirect: Bool, flushVec: Vec[Bool])(implicit p: Parameters): Vec[T] = {
16    val snapshotGen = Module(new SnapshotGenerator(enqData))
17    snapshotGen.io.enq := enq
18    snapshotGen.io.enqData := enqData
19    snapshotGen.io.deq := deq
20    snapshotGen.io.redirect := redirect
21    snapshotGen.io.flushVec := flushVec
22    snapshotGen.io.snapshots
23  }
24}
25
26class SnapshotGenerator[T <: Data](dataType: T)(implicit p: Parameters) extends XSModule
27  with HasCircularQueuePtrHelper {
28
29  class SnapshotGeneratorIO extends Bundle {
30    val enq = Input(Bool())
31    val enqData = Input(chiselTypeOf(dataType))
32    val deq = Input(Bool())
33    val redirect = Input(Bool())
34    val flushVec = Input(Vec(RenameSnapshotNum, Bool()))
35    val snapshots = Output(Vec(RenameSnapshotNum, chiselTypeOf(dataType)))
36    val enqPtr = Output(new SnapshotPtr)
37    val deqPtr = Output(new SnapshotPtr)
38    val valids = Output(Vec(RenameSnapshotNum, Bool()))
39  }
40
41  val io = IO(new SnapshotGeneratorIO)
42
43  val snapshots = Reg(Vec(RenameSnapshotNum, chiselTypeOf(dataType)))
44  val snptEnqPtr = RegInit(0.U.asTypeOf(new SnapshotPtr))
45  val snptDeqPtr = RegInit(0.U.asTypeOf(new SnapshotPtr))
46  val snptValids = RegInit(VecInit.fill(RenameSnapshotNum)(false.B))
47
48  io.snapshots := snapshots
49  io.enqPtr := snptEnqPtr
50  io.deqPtr := snptDeqPtr
51  io.valids := snptValids
52
53  when(!io.redirect && !isFull(snptEnqPtr, snptDeqPtr) && io.enq) {
54    snapshots(snptEnqPtr.value) := io.enqData
55    snptValids(snptEnqPtr.value) := true.B
56    snptEnqPtr := snptEnqPtr + 1.U
57  }
58  when(!io.redirect && io.deq) {
59    snptValids(snptDeqPtr.value) := false.B
60    snptDeqPtr := snptDeqPtr + 1.U
61  }
62  XSError(!io.redirect && io.deq && isEmpty(snptEnqPtr, snptDeqPtr), "snapshots should not be empty when dequeue!\n")
63
64  snptValids.zip(io.flushVec).foreach { case (valid, flush) =>
65    when(flush) { valid := false.B }
66  }
67  when((Cat(io.flushVec) & Cat(snptValids)).orR) {
68    val newEnqPtrCandidate = (0 until RenameSnapshotNum).map(snptDeqPtr + _.U)
69    val newEnqPtrQualified = Wire(Vec(RenameSnapshotNum, Bool()))
70    newEnqPtrQualified.head := !snptValids(newEnqPtrCandidate.head.value) || io.flushVec(newEnqPtrCandidate.head.value)
71    newEnqPtrQualified.tail zip newEnqPtrCandidate.tail.zip(newEnqPtrCandidate.drop(1)).map {
72      case (thiz, last) => snptValids(last.value) && (!snptValids(thiz.value) || io.flushVec(thiz.value))
73    } foreach (x => x._1 := x._2)
74    snptEnqPtr := MuxCase(newEnqPtrCandidate.last, newEnqPtrQualified.zip(newEnqPtrCandidate).dropRight(1))
75  }
76}
77