From 73faecdc3b68e7fdacd4c95f2fdeda671edeb235 Mon Sep 17 00:00:00 2001 From: Xuan Hu Date: Thu, 22 Dec 2022 22:38:09 +0800 Subject: [PATCH] RegFile: add vector regfile --- src/main/scala/xiangshan/Parameters.scala | 6 + .../scala/xiangshan/backend/Scheduler.scala | 18 +-- .../xiangshan/backend/regfile/Regfile.scala | 107 +++++++++++++++--- 3 files changed, 105 insertions(+), 26 deletions(-) diff --git a/src/main/scala/xiangshan/Parameters.scala b/src/main/scala/xiangshan/Parameters.scala index 58ecec5c4..02186b853 100644 --- a/src/main/scala/xiangshan/Parameters.scala +++ b/src/main/scala/xiangshan/Parameters.scala @@ -129,6 +129,8 @@ case class XSCoreParameters EnableLoadFastWakeUp: Boolean = true, // NOTE: not supported now, make it false IssQueSize: Int = 16, NRPhyRegs: Int = 192, + IntPhyRegs: Int = 192, + VfPhyRegs: Int = 192, LoadQueueSize: Int = 80, LoadQueueNWriteBanks: Int = 8, StoreQueueSize: Int = 64, @@ -373,6 +375,10 @@ trait HasXSParameter { val EnableLoadFastWakeUp = coreParams.EnableLoadFastWakeUp val NRPhyRegs = coreParams.NRPhyRegs val PhyRegIdxWidth = log2Up(NRPhyRegs) + val IntPhyRegs = coreParams.IntPhyRegs + val VfPhyRegs = coreParams.VfPhyRegs + val IntPregIdxWidth = log2Up(IntPhyRegs) + val VfPregIdxWidth = log2Up(VfPhyRegs) val RobSize = coreParams.RobSize val IntRefCounterWidth = log2Ceil(RobSize) val LoadQueueSize = coreParams.LoadQueueSize diff --git a/src/main/scala/xiangshan/backend/Scheduler.scala b/src/main/scala/xiangshan/backend/Scheduler.scala index c8dade4d2..2fda3c2c5 100644 --- a/src/main/scala/xiangshan/backend/Scheduler.scala +++ b/src/main/scala/xiangshan/backend/Scheduler.scala @@ -27,7 +27,7 @@ import xiangshan.backend.dispatch.Dispatch2Rs import xiangshan.backend.exu.ExuConfig import xiangshan.backend.fu.FuConfig import xiangshan.backend.issue.{BaseReservationStationWrapper, RSParams, RSMod} -import xiangshan.backend.regfile.{Regfile, RfReadPort} +import xiangshan.backend.regfile.{IntRegFile, VfRegFile, RfReadPort} import xiangshan.backend.rename.{BusyTable, BusyTableReadIO} import xiangshan.mem.{LsqEnqCtrl, LsqEnqIO, MemWaitUpdateReq, SqPtr} import chisel3.ExcitingUtils @@ -272,11 +272,11 @@ class SchedulerImp(outer: Scheduler) extends LazyModuleImp(outer) with HasXSPara // special ports for RS that needs to read from other schedulers // In: read response from other schedulers // Out: read request to other schedulers - val intRfReadIn = if (!outer.hasIntRf && outer.numIntRfReadPorts > 0) Some(Vec(outer.numIntRfReadPorts, Flipped(new RfReadPort(XLEN)))) else None - val intRfReadOut = if (outer.outIntRfReadPorts > 0) Some(Vec(outer.outIntRfReadPorts, new RfReadPort(XLEN))) else None - val fpRfReadIn = if (!outer.hasFpRf && outer.numFpRfReadPorts > 0) Some(Vec(outer.numFpRfReadPorts, Flipped(new RfReadPort(XLEN)))) else None + val intRfReadIn = if (!outer.hasIntRf && outer.numIntRfReadPorts > 0) Some(Vec(outer.numIntRfReadPorts, Flipped(new RfReadPort(XLEN, IntPregIdxWidth)))) else None + val intRfReadOut = if (outer.outIntRfReadPorts > 0) Some(Vec(outer.outIntRfReadPorts, new RfReadPort(XLEN, IntPregIdxWidth))) else None + val fpRfReadIn = if (!outer.hasFpRf && outer.numFpRfReadPorts > 0) Some(Vec(outer.numFpRfReadPorts, Flipped(new RfReadPort(VLEN, VfPregIdxWidth)))) else None val fpStateReadIn = if (!outer.hasFpRf && outer.numFpRfReadPorts > 0) Some(Vec(outer.numFpRfReadPorts, Flipped(new BusyTableReadIO))) else None - val fpRfReadOut = if (outer.outFpRfReadPorts > 0) Some(Vec(outer.outFpRfReadPorts, new RfReadPort(XLEN))) else None + val fpRfReadOut = if (outer.outFpRfReadPorts > 0) Some(Vec(outer.outFpRfReadPorts, new RfReadPort(VLEN, VfPregIdxWidth))) else None val fpStateReadOut = if (outer.outFpRfReadPorts > 0) Some(Vec(outer.outFpRfReadPorts, new BusyTableReadIO)) else None val loadFastMatch = if (numLoadPorts > 0) Some(Vec(numLoadPorts, Output(UInt(exuParameters.LduCnt.W)))) else None val loadFastImm = if (numLoadPorts > 0) Some(Vec(numLoadPorts, Output(UInt(12.W)))) else None @@ -396,12 +396,14 @@ class SchedulerImp(outer: Scheduler) extends LazyModuleImp(outer) with HasXSPara val debugRead = if (isInt) io.extra.debug_int_rat else io.extra.debug_fp_rat if (isInt) { val wen = wbPorts.map(wb =>wb.valid && wb.bits.uop.ctrl.rfWen) - Regfile(NRPhyRegs, readIntRf, wen, waddr, wdata, true, debugRead = Some(debugRead)) + IntRegFile(IntPhyRegs, readIntRf, wen, waddr, wdata, debugReadAddr = Some(debugRead)) } else { // For floating-point function units, every instruction writes either int or fp regfile. - val wen = wbPorts.map(_.valid) - Regfile(NRPhyRegs, readFpRf, wen, waddr, wdata, false, debugRead = Some(debugRead)) + // Multi-wen for each regfile + val wen = Seq.fill(VLEN/XLEN)(wbPorts.map(_.valid)) + val widenWdata = wdata.map(ZeroExt(_, VLEN)) + VfRegFile(VfPhyRegs, VLEN/XLEN, readFpRf, wen, waddr, widenWdata, debugReadAddr = Some(debugRead)) } } diff --git a/src/main/scala/xiangshan/backend/regfile/Regfile.scala b/src/main/scala/xiangshan/backend/regfile/Regfile.scala index ec6633807..e860f8476 100644 --- a/src/main/scala/xiangshan/backend/regfile/Regfile.scala +++ b/src/main/scala/xiangshan/backend/regfile/Regfile.scala @@ -22,14 +22,14 @@ import chisel3.experimental.ExtModule import chisel3.util._ import xiangshan._ -class RfReadPort(len: Int)(implicit p: Parameters) extends XSBundle { - val addr = Input(UInt(PhyRegIdxWidth.W)) +class RfReadPort(len: Int, width: Int)(implicit p: Parameters) extends XSBundle { + val addr = Input(UInt(width.W)) val data = Output(UInt(len.W)) } -class RfWritePort(len: Int)(implicit p: Parameters) extends XSBundle { +class RfWritePort(len: Int, width: Int)(implicit p: Parameters) extends XSBundle { val wen = Input(Bool()) - val addr = Input(UInt(PhyRegIdxWidth.W)) + val addr = Input(UInt(width.W)) val data = Input(UInt(len.W)) } @@ -38,12 +38,13 @@ class Regfile numReadPorts: Int, numWritePorts: Int, hasZero: Boolean, - len: Int + len: Int, + width: Int, )(implicit p: Parameters) extends XSModule { val io = IO(new Bundle() { - val readPorts = Vec(numReadPorts, new RfReadPort(len)) - val writePorts = Vec(numWritePorts, new RfWritePort(len)) - val debug_rports = Vec(32, new RfReadPort(len)) + val readPorts = Vec(numReadPorts, new RfReadPort(len, width)) + val writePorts = Vec(numWritePorts, new RfWritePort(len, width)) + val debug_rports = Vec(32, new RfReadPort(len, width)) }) println("Regfile: size:" + NRPhyRegs + " read: " + numReadPorts + " write: " + numWritePorts) @@ -67,14 +68,14 @@ class Regfile object Regfile { def apply( - numEntries: Int, - raddr: Seq[UInt], - wen: Seq[Bool], - waddr: Seq[UInt], - wdata: Seq[UInt], - hasZero: Boolean, - withReset: Boolean = false, - debugRead: Option[Seq[UInt]] = None + numEntries : Int, + raddr : Seq[UInt], + wen : Seq[Bool], + waddr : Seq[UInt], + wdata : Seq[UInt], + hasZero : Boolean, + withReset : Boolean = false, + debugReadAddr: Option[Seq[UInt]] = None, )(implicit p: Parameters): Seq[UInt] = { val numReadPorts = raddr.length val numWritePorts = wen.length @@ -82,11 +83,15 @@ object Regfile { require(wen.length == wdata.length) val dataBits = wdata.map(_.getWidth).min require(wdata.map(_.getWidth).min == wdata.map(_.getWidth).max, s"dataBits != $dataBits") - val regfile = Module(new Regfile(numReadPorts, numWritePorts, hasZero, dataBits)) + val addrBits = waddr.map(_.getWidth).min + require(waddr.map(_.getWidth).min == waddr.map(_.getWidth).max, s"addrBits != $addrBits") + + val regfile = Module(new Regfile(numReadPorts, numWritePorts, hasZero, dataBits, addrBits)) val rdata = regfile.io.readPorts.zip(raddr).map { case (rport, addr) => rport.addr := addr rport.data } + regfile.io.writePorts.zip(wen).zip(waddr).zip(wdata).foreach{ case (((wport, en), addr), data) => wport.wen := en wport.addr := addr @@ -111,10 +116,76 @@ object Regfile { } } regfile.io.debug_rports := DontCare - val debug_rdata = regfile.io.debug_rports.zip(debugRead.getOrElse(Seq())).map { case (rport, addr) => + val debug_rdata = regfile.io.debug_rports.zip(debugReadAddr.getOrElse(Seq())).map { case (rport, addr) => rport.addr := addr rport.data } rdata ++ debug_rdata } } + +object IntRegFile { + def apply( + numEntries : Int, + raddr : Seq[UInt], + wen : Seq[Bool], + waddr : Seq[UInt], + wdata : Seq[UInt], + withReset : Boolean = false, + debugReadAddr: Option[Seq[UInt]] = None, + )(implicit p: Parameters): Seq[UInt] = { + Regfile( + numEntries, raddr, wen, waddr, wdata, + hasZero = true, withReset, debugReadAddr) + } +} + +object VfRegFile { + def apply( + numEntries : Int, + splitNum : Int, + raddr : Seq[UInt], + wen : Seq[Seq[Bool]], + waddr : Seq[UInt], + wdata : Seq[UInt], + withReset : Boolean = false, + debugReadAddr: Option[Seq[UInt]] = None, + )(implicit p: Parameters) : Seq[UInt] = { + require(splitNum >= 1, "splitNum should be no less than 1") + require(splitNum == wen.length, "splitNum should be equal to length of wen vec") + if (splitNum == 1) { + Regfile(numEntries, raddr, wen.head, waddr, wdata, + hasZero = false, withReset, debugReadAddr) + } + + val dataWidth = 64 + val numReadPorts = raddr.length + debugReadAddr.getOrElse(Seq()).length + require(splitNum > 1 && wdata.head.getWidth == dataWidth * splitNum) + val wdataVec = Wire(Vec(splitNum, Vec(wdata.length, UInt(dataWidth.W)))) + var rdataVec = Wire(Vec(splitNum, Vec(numReadPorts, UInt(dataWidth.W)))) + for (i <- 0 until splitNum) { + wdataVec(i) := wdata.map(_((i + 1) * dataWidth - 1, i * dataWidth)) + rdataVec(i) := Regfile(numEntries, raddr, wen(i), waddr, wdataVec(i), + hasZero = false, withReset, debugReadAddr) + } + val rdata = Wire(Vec(numReadPorts, UInt(wdata.head.getWidth.W))) + for (i <- 0 until rdata.length) { + rdata(i) := Cat(rdataVec.map(_(i))) + } + rdata + } + +// // for dummy usage +// def apply( +// numEntries : Int, +// raddr : Vec[UInt], +// wen : Vec[Bool], +// waddr : Vec[UInt], +// wdata : Vec[UInt], +// withReset : Boolean = false, +// debugReadAddr: Option[Vec[UInt]] = None, +// )(implicit p: Parameters) : Unit = { +// Regfile(numEntries, raddr, wen, waddr, wdata, +// hasZero = false, withReset, debugReadAddr) +// } +} -- GitLab