xref: /XiangShan/src/main/scala/xiangshan/backend/datapath/WbFuBusyTable.scala (revision f7063a43ab34da917ba6c670d21871314340c550)
1package xiangshan.backend.datapath
2
3import scala.collection.Seq
4import org.chipsalliance.cde.config.Parameters
5import chisel3._
6import chisel3.util._
7import freechips.rocketchip.diplomacy.{LazyModule, LazyModuleImp}
8import utility._
9import utils.OptionWrapper
10import xiangshan._
11import xiangshan.backend._
12import xiangshan.backend.datapath.WbConfig._
13import xiangshan.backend.exu.ExeUnitParams
14import xiangshan.backend.implicitCast._
15
16class WbFuBusyTable(bp: BackendParams)(implicit  p: Parameters) extends LazyModule {
17  override def shouldBeInlined: Boolean = false
18  implicit val params: BackendParams = bp
19  lazy val module = new WbFuBusyTableImp(this)
20}
21
22class WbFuBusyTableImp(override val wrapper: WbFuBusyTable)(implicit  p: Parameters, params: BackendParams) extends LazyModuleImp(wrapper) {
23  val io = IO(new WbFuBusyTableIO)
24
25  private val intSchdBusyTable = io.in.intSchdBusyTable
26  private val vfSchdBusyTable = io.in.vfSchdBusyTable
27  private val memSchdBusyTable = io.in.memSchdBusyTable
28  private val intRespRead = io.out.intRespRead
29  private val vfRespRead = io.out.vfRespRead
30  private val memRespRead = io.out.memRespRead
31  private val intAllWbConflictFlag = io.out.wbConflictRead.flatten.flatten.map(_.intConflict)
32  private val vfAllWbConflictFlag = io.out.wbConflictRead.flatten.flatten.map(_.vfConflict)
33
34  private val intAllBusyTable = (intSchdBusyTable ++ vfSchdBusyTable ++ memSchdBusyTable).flatten.map(_.intWbBusyTable)
35  private val vfAllBusyTable = (intSchdBusyTable ++ vfSchdBusyTable ++ memSchdBusyTable).flatten.map(_.vfWbBusyTable)
36  private val intAllDeqRespSet = (intSchdBusyTable ++ vfSchdBusyTable ++ memSchdBusyTable).flatten.map(_.intDeqRespSet)
37  private val vfAllDeqRespSet = (intSchdBusyTable ++ vfSchdBusyTable ++ memSchdBusyTable).flatten.map(_.vfDeqRespSet)
38  private val intAllRespRead = (intRespRead ++ vfRespRead ++ memRespRead).flatten.map(_.intWbBusyTable)
39  private val vfAllRespRead = (intRespRead ++ vfRespRead ++ memRespRead).flatten.map(_.vfWbBusyTable)
40
41  private val allExuParams = params.allExuParams
42  private val intAllBusyTableWithParms = intAllBusyTable.zip(allExuParams).toSeq
43  private val vfAllBusyTableWithParms = vfAllBusyTable.zip(allExuParams).toSeq
44  private val intAllDeqRespSetWithParms = intAllDeqRespSet.zip(allExuParams).toSeq
45  private val vfAllDeqRespSetWithParms = vfAllDeqRespSet.zip(allExuParams).toSeq
46
47  private val intWbLatencyMax = params.getIntWBExeGroup.map { case (portId, seq) => (portId, seq.map(_.intLatencyValMax).max, seq.forall(_.intLatencyCertain)) }
48  private val vfWbLatencyMax = params.getVfWBExeGroup.map { case (portId, seq) => (portId, seq.map(_.vfLatencyValMax).max, seq.forall(_.vfLatencyCertain)) }
49  private val intWbBusyTable: Map[Int, Option[UInt]] = intWbLatencyMax.map { case (portId, latMax, latCertain) => (portId, OptionWrapper(latCertain, Wire(UInt((latMax + 1).W)))) }.toMap
50  private val vfWbBusyTable = vfWbLatencyMax.map { case (portId, latMax, latCertain) => (portId, OptionWrapper(latCertain, Wire(UInt((latMax + 1).W)))) }.toMap
51  private val intConflict: Map[Int, Option[Bool]] = intWbLatencyMax.map { case (portId, latMax, latCertain) => (portId, OptionWrapper(latCertain, Reg(Bool()))) }.toMap
52  private val vfConflict = vfWbLatencyMax.map { case (portId, latMax, latCertain) => (portId, OptionWrapper(latCertain, Reg(Bool()))) }.toMap
53
54  def hitWbPort[T <: Data](source: Option[T], p: ExeUnitParams, portId: Int, isInt: Boolean) = {
55    if(isInt){
56      p.wbPortConfigs.collectFirst { case x : IntWB => x.port }.getOrElse(-1) == portId && source.nonEmpty
57    } else {
58      p.wbPortConfigs.collectFirst { case x : VfWB => x.port }.getOrElse(-1) == portId && source.nonEmpty
59    }
60  }
61
62  def writeBusyTable(wtBusyTable: Map[Int, Option[UInt]], busyTableWithParams: Seq[(Option[UInt], ExeUnitParams)], isInt: Boolean) = {
63    wtBusyTable.foreach { case (portId, busyTable) =>
64      if (busyTable.nonEmpty) {
65        busyTable.get := busyTableWithParams.filter { case (busyTable, p) => hitWbPort(busyTable, p, portId, isInt) }.map(_._1.get).reduce(_ | _)
66      }
67    }
68  }
69
70  def writeConflict(wtConflict: Map[Int, Option[Bool]], deqRespSetWithParams: Seq[(Option[UInt], ExeUnitParams)], isInt: Boolean) = {
71    wtConflict.foreach { case (portId, conflict) =>
72      if (conflict.nonEmpty) {
73        val deqRespSel = deqRespSetWithParams.filter { case (deqRespSet, p) => hitWbPort(deqRespSet, p, portId, isInt) }.map(_._1.get)
74        val width = deqRespSel.map(x => x.getWidth).max
75        val deqRespSelUnify = deqRespSel.map(x => x.asTypeOf(UInt(width.W))).toSeq
76        conflict.get := (0 until width).map{ case i =>
77          OnesMoreThan(deqRespSelUnify.map(x => x(i)), 2)
78        }.reduce(_ | _)
79      }
80    }
81  }
82
83  def readRes[T <: Data](sink: IndexedSeq[Option[T]], source: Map[Int, Option[T]], isInt: Boolean) = {
84    for(i <- 0 until sink.size) {
85      if(sink(i).nonEmpty) {
86        sink(i).get := source.map { case (portId, src) =>
87          if(hitWbPort(src, allExuParams(i), portId, isInt)) {
88            src.get.asTypeOf(sink(i).get).asUInt
89          } else {
90            0.U.asTypeOf(sink(i).get).asUInt
91          }
92        }.reduce(_ | _)
93      }
94    }
95  }
96
97
98
99  //per wbPort fuBusyTable
100  writeBusyTable(intWbBusyTable, intAllBusyTableWithParms, true)
101  writeBusyTable(vfWbBusyTable, vfAllBusyTableWithParms, false)
102  //per wbPort conflict
103  writeConflict(intConflict, intAllDeqRespSetWithParms, true)
104  writeConflict(vfConflict, vfAllDeqRespSetWithParms, false)
105  //read wbPort fuBusyTable to per exe
106  readRes(intAllRespRead, intWbBusyTable, true)
107  readRes(vfAllRespRead, vfWbBusyTable, false)
108  //read wbPort conflict to dataPath
109  readRes(intAllWbConflictFlag, intConflict, true)
110  readRes(vfAllWbConflictFlag, vfConflict, false)
111
112}
113
114class WbFuBusyTableIO(implicit p: Parameters, params: BackendParams) extends XSBundle {
115  val in = new Bundle {
116    val intSchdBusyTable = MixedVec(params.intSchdParams.get.issueBlockParams.map(x => Input(x.genWbFuBusyTableWriteBundle)))
117    val vfSchdBusyTable = MixedVec(params.vfSchdParams.get.issueBlockParams.map(x => Input(x.genWbFuBusyTableWriteBundle)))
118    val memSchdBusyTable = MixedVec(params.memSchdParams.get.issueBlockParams.map(x => Input(x.genWbFuBusyTableWriteBundle)))
119  }
120  val out = new Bundle {
121    val intRespRead = MixedVec(params.intSchdParams.get.issueBlockParams.map(x => Output(x.genWbFuBusyTableReadBundle)))
122    val vfRespRead = MixedVec(params.vfSchdParams.get.issueBlockParams.map(x => Output(x.genWbFuBusyTableReadBundle)))
123    val memRespRead = MixedVec(params.memSchdParams.get.issueBlockParams.map(x => Output(x.genWbFuBusyTableReadBundle)))
124    val wbConflictRead = MixedVec(params.allSchdParams.map(x => MixedVec(x.issueBlockParams.map(x => Output(x.genWbConflictBundle())))))
125  }
126}