From 942825a38ff57b492ca386eec8e53a5461fd0ea8 Mon Sep 17 00:00:00 2001 From: Dolu1990 Date: Thu, 11 Jan 2024 10:51:24 +0100 Subject: [PATCH] latch regfile now use tristate --- .../naxriscv/compatibility/MultiportRam.scala | 1 + .../scala/naxriscv/misc/RegFilePlugin.scala | 70 ++++++++++++------- .../asic/{test_c.scala => NaxAsicGen.scala} | 34 +++++---- .../scala/naxriscv/platform/asic/Sky130.scala | 2 + .../naxriscv/platform/asic/test_rf.scala | 3 +- .../platform/tilelinkdemo/SocSim.scala | 2 +- 6 files changed, 69 insertions(+), 43 deletions(-) rename src/main/scala/naxriscv/platform/asic/{test_c.scala => NaxAsicGen.scala} (62%) diff --git a/src/main/scala/naxriscv/compatibility/MultiportRam.scala b/src/main/scala/naxriscv/compatibility/MultiportRam.scala index 21a6d595..887684e8 100644 --- a/src/main/scala/naxriscv/compatibility/MultiportRam.scala +++ b/src/main/scala/naxriscv/compatibility/MultiportRam.scala @@ -224,6 +224,7 @@ class MultiPortWritesSymplifier(onlyTagged : Boolean = false) extends PhaseMemBl for((reworked, old) <- (io.read, readsAsync).zipped){ + reworked.cmd.valid := True reworked.cmd.payload.assignFrom(old.address) wrapConsumers(typo, old, reworked.rsp) } diff --git a/src/main/scala/naxriscv/misc/RegFilePlugin.scala b/src/main/scala/naxriscv/misc/RegFilePlugin.scala index 17fd2e16..b3ae449e 100644 --- a/src/main/scala/naxriscv/misc/RegFilePlugin.scala +++ b/src/main/scala/naxriscv/misc/RegFilePlugin.scala @@ -21,12 +21,10 @@ case class RegFileWriteParameter(withReady : Boolean) case class RegFileIo( addressWidth: Int, dataWidth: Int, readsParameter: Seq[RegFileReadParameter], - writesParameter: Seq[RegFileWriteParameter], - bypasseCount: Int + writesParameter: Seq[RegFileWriteParameter] ) extends Bundle{ val writes = Vec(writesParameter.map(p => slave(RegFileWrite(addressWidth, dataWidth, p.withReady)))) val reads = Vec(readsParameter.map(p => slave(RegFileRead(addressWidth, dataWidth, p.withReady, 0, p.forceNoBypass)))) - val bypasses = Vec.fill(bypasseCount)(slave(RegFileBypass(addressWidth, dataWidth))) } //The bankCount is currently useless, but maybe uesefull in the future with execution units which can stall @@ -35,14 +33,13 @@ class RegFileAsync(addressWidth : Int, bankCount : Int, readsParameter : Seq[RegFileReadParameter], writesParameter : Seq[RegFileWriteParameter], - bypasseCount : Int, preferedWritePortForInit : Int, headZero : Boolean, allOne : Boolean, asyncReadBySyncReadRevertedClk : Boolean = false) extends Component { assert(!(allOne && headZero)) - val io = RegFileIo(addressWidth, dataWidth, readsParameter, writesParameter, bypasseCount) + val io = RegFileIo(addressWidth, dataWidth, readsParameter, writesParameter) val bankShift = log2Up(bankCount) val writePortCount = io.writes.count(!_.withReady) @@ -72,14 +69,6 @@ class RegFileAsync(addressWidth : Int, port.address := r.address >> bankShift r.data := port.data } - - val bypass = (!r.forceNoBypass && bypasseCount != 0) generate new Area{ - val hits = io.bypasses.map(b => b.valid && b.address === r.address) - val hitsValue = MuxOH.mux(hits, io.bypasses.map(_.data)) - when(hits.orR){ - r.data := hitsValue - } - } } val initPort = banks.head.writePort(preferedWritePortForInit) @@ -118,7 +107,6 @@ object RegFileAsyncSynth extends App{ bankCount = 1, readsParameter = Seq.fill(4)(RegFileReadParameter(withReady = false, forceNoBypass = false)), writesParameter = Seq.fill(1)(RegFileWriteParameter(withReady = false)), - bypasseCount = 0, preferedWritePortForInit = 0, headZero = true, allOne = false @@ -141,19 +129,23 @@ Artix 7 -> 375 Mhz 176 LUT 585 FF Artix 7 -> 538 Mhz 176 LUT 585 FF */ +class sky130_fd_sc_hd__dlxtp_1 extends BlackBox { + val Q = out Bool() + val D = in Bool() + val GATE = in Bool() +} class RegFileLatch(addressWidth : Int, dataWidth : Int, readsParameter : Seq[RegFileReadParameter], writesParameter : Seq[RegFileWriteParameter], - bypasseCount : Int, headZero : Boolean) extends Component { - val io = RegFileIo(addressWidth, dataWidth, readsParameter, writesParameter, bypasseCount) + val io = RegFileIo(addressWidth, dataWidth, readsParameter, writesParameter) io.reads.foreach(e => assert(!e.withReady)) io.writes.foreach(e => assert(!e.withReady)) - + val writeFrontend = new Area { @dontName val clock = ClockDomain.current.readClockWire val buffers = for (port <- io.writes) yield LatchWhen(port.data, clock) @@ -169,6 +161,15 @@ class RegFileLatch(addressWidth : Int, // val validReg = RegNext(mask.orR) val data = OhMux.or(maskReg, writeFrontend.buffers) } + +// val storages = Array.fill(dataWidth)(new sky130_fd_sc_hd__dlxtp_1) +// val GATE = !writeFrontend.clock && write.validReg +// for((s, i) <- storages.zipWithIndex){ +// s.D := write.data(i) +// s.GATE := GATE +// } +// val storage = storages.map(_.Q).toSeq.asBits + val storage = LatchWhen(write.data, !writeFrontend.clock && write.validReg) } @@ -176,15 +177,16 @@ class RegFileLatch(addressWidth : Int, val readLogic = for ((r, i) <- io.reads.zipWithIndex) yield new Area { var mem = latches.map(_.storage).toList if(headZero) mem = B(0, dataWidth bits) :: mem - r.data := mem.read(r.address) - val bypass = (!r.forceNoBypass && bypasseCount != 0) generate new Area { - val hits = io.bypasses.map(b => b.valid && b.address === r.address) - val hitsValue = MuxOH.or(hits, io.bypasses.map(_.data)) - when(hits.orR) { - r.data := hitsValue - } + val oh = UIntToOh(r.address) + val tri = Analog(Bits(dataWidth bits)) + mem.onMask(oh){ value => + tri := value } + r.data := tri + + +// r.data := mem.read(r.address) } } @@ -286,7 +288,6 @@ class RegFilePlugin(var spec : RegfileSpec, bankCount = bankCount, readsParameter = reads.map(e => RegFileReadParameter(withReady = e.withReady, e.forceNoBypass)), writesParameter = writeMerges.map(e => RegFileWriteParameter(withReady = false)).toList, - bypasseCount = bypasses.size, headZero = spec.x0AlwaysZero, preferedWritePortForInit = writeGroups.zipWithIndex.find(_._1._2.exists(_.port.getName().contains(preferedWritePortForInit))).get._2, allOne = allOne, @@ -298,7 +299,6 @@ class RegFilePlugin(var spec : RegfileSpec, dataWidth = dataWidth, readsParameter = reads.map(e => RegFileReadParameter(withReady = e.withReady, e.forceNoBypass)), writesParameter = writeMerges.map(e => RegFileWriteParameter(withReady = false)).toList, - bypasseCount = bypasses.size, headZero = spec.x0AlwaysZero ) @@ -312,7 +312,16 @@ class RegFilePlugin(var spec : RegfileSpec, (regfile.io.reads, reads).zipped.foreach(_ <> _) (regfile.io.writes, writeMerges.map(_.bus)).zipped.foreach(_ <> _) - (regfile.io.bypasses, bypasses).zipped.foreach(_ <> _) + val bypass = for(i <- 0 until regfile.io.readsParameter.size) { + val r = reads(i) + if(!r.forceNoBypass && bypasses.size != 0){ + val hits = bypasses.map(b => b.valid && b.address === r.address) + val hitsValue = MuxOH.mux(hits, bypasses.map(_.data)) + when(hits.orR) { + r.data := hitsValue + } + } + } //Used for tracing in verilator sim val writeEvents = Vec(writeMerges.map(e => CombInit(e.bus))) @@ -321,4 +330,11 @@ class RegFilePlugin(var spec : RegfileSpec, doc.property(writeEvents.getName() +"_count", writeEvents.size) doc.property(spec.getName() +"_PHYSICAL_DEPTH", physicalDepth) } +} + + +object LatchRegFilePlacer extends App{ + +// latches_17_storages_24 585.12 848.64 +// latches_17_storages_25 585.58 848.64 } \ No newline at end of file diff --git a/src/main/scala/naxriscv/platform/asic/test_c.scala b/src/main/scala/naxriscv/platform/asic/NaxAsicGen.scala similarity index 62% rename from src/main/scala/naxriscv/platform/asic/test_c.scala rename to src/main/scala/naxriscv/platform/asic/NaxAsicGen.scala index d9d51d5d..8fa63c71 100644 --- a/src/main/scala/naxriscv/platform/asic/test_c.scala +++ b/src/main/scala/naxriscv/platform/asic/NaxAsicGen.scala @@ -11,7 +11,15 @@ import spinal.core._ import spinal.lib._ import spinal.lib.eda.bench.Rtl -object test_c extends App{ +object NaxAsicGen extends App{ + var target = "asic" + + assert(new scopt.OptionParser[Unit]("NaxAsicGen") { + help("help").text("prints this usage text") + opt[Unit]("sky130") action { (v, c) => target = "sky130" } + }.parse(args, Unit).nonEmpty) + + LutInputs.set(4) def plugins = { val l = Config.plugins( @@ -41,24 +49,24 @@ object test_c extends App{ l.foreach{ case p : EmbeddedJtagPlugin => p.debugCd.load(ClockDomain.current.copy(reset = Bool().setName("debug_reset"))) -// case p: FetchCachePlugin => p.wayCount = 2; p.cacheSize = 4096; p.memDataWidth = 64 -// case p: DataCachePlugin => p.wayCount = 2; p.cacheSize = 4096; p.memDataWidth = 64 -// case p: BtbPlugin => p.entries = 64 -// case p: GSharePlugin => p.memBytes = 512 + case p: FetchCachePlugin => p.wayCount = 2; p.cacheSize = 4096; p.memDataWidth = 64 + case p: DataCachePlugin => p.wayCount = 2; p.cacheSize = 4096; p.memDataWidth = 64 + case p: BtbPlugin => p.entries = 64 + case p: GSharePlugin => p.memBytes = 512 - case p: FetchCachePlugin => p.wayCount = 1; p.cacheSize = 256; p.memDataWidth = 64 - case p: DataCachePlugin => p.wayCount = 1; p.cacheSize = 256; p.memDataWidth = 64 - case p: BtbPlugin => p.entries = 8 - case p: GSharePlugin => p.memBytes = 32 +// case p: FetchCachePlugin => p.wayCount = 1; p.cacheSize = 256; p.memDataWidth = 64 +// case p: DataCachePlugin => p.wayCount = 1; p.cacheSize = 256; p.memDataWidth = 64 +// case p: BtbPlugin => p.entries = 8 +// case p: GSharePlugin => p.memBytes = 32 case _ => } l } - val spinalConfig = SpinalConfig() -// val spinalConfig = SpinalSky130() - //spinalConfig.addTransformationPhase(new MultiPortWritesSymplifier) -// spinalConfig.addStandardMemBlackboxing(blackboxAllWhatsYouCan) + var spinalConfig = target match { + case "asic" => SpinalConfig() + case "sky130" => SpinalSky130() + } spinalConfig.generateVerilog(new NaxRiscv(plugins).setDefinitionName("nax")) diff --git a/src/main/scala/naxriscv/platform/asic/Sky130.scala b/src/main/scala/naxriscv/platform/asic/Sky130.scala index 5007338d..886945e9 100644 --- a/src/main/scala/naxriscv/platform/asic/Sky130.scala +++ b/src/main/scala/naxriscv/platform/asic/Sky130.scala @@ -1,5 +1,6 @@ package naxriscv.platform.asic +import naxriscv.compatibility.MultiPortWritesSymplifier import spinal.core._ import spinal.core.internals.{MemTopology, PhaseContext, PhaseMemBlackBoxingWithPolicy, PhaseNetlist} import spinal.lib._ @@ -15,6 +16,7 @@ object SpinalSky130{ } def apply() = { val c = SpinalConfig(mode = Verilog) + c.addTransformationPhase(new MultiPortWritesSymplifier) c.addStandardMemBlackboxing(blackboxPolicy) c.phasesInserters += { phases => val i = phases.lastIndexWhere(_.isInstanceOf[PhaseMemBlackBoxingWithPolicy]) diff --git a/src/main/scala/naxriscv/platform/asic/test_rf.scala b/src/main/scala/naxriscv/platform/asic/test_rf.scala index aafd6bf8..3ec34e02 100644 --- a/src/main/scala/naxriscv/platform/asic/test_rf.scala +++ b/src/main/scala/naxriscv/platform/asic/test_rf.scala @@ -19,9 +19,8 @@ object TestRfGen extends App { dataWidth = 2, readsParameter = List.fill(1)(RegFileReadParameter(false, false)), writesParameter = List.fill(1)(RegFileWriteParameter(false)), - bypasseCount = 0, headZero = false - ).setDefinitionName("top") + ).setDefinitionName("rf") } } } diff --git a/src/main/scala/naxriscv/platform/tilelinkdemo/SocSim.scala b/src/main/scala/naxriscv/platform/tilelinkdemo/SocSim.scala index 9929e0db..2655d643 100644 --- a/src/main/scala/naxriscv/platform/tilelinkdemo/SocSim.scala +++ b/src/main/scala/naxriscv/platform/tilelinkdemo/SocSim.scala @@ -74,7 +74,7 @@ object SocSim extends App { val sc = SimConfig sc.normalOptimisation - sc.withIVerilog +// sc.withIVerilog // sc.withFstWave sc.withConfig(SpinalConfig(defaultConfigForClockDomains = ClockDomainConfig(resetKind = ASYNC)).includeSimulation) // sc.addSimulatorFlag("--threads 1")