diff options
| author | mergify[bot] | 2022-04-19 02:29:00 +0000 |
|---|---|---|
| committer | GitHub | 2022-04-19 02:29:00 +0000 |
| commit | 70da39e140e96a9302a94864f077529e02596ef5 (patch) | |
| tree | a7fa6a52fe7bb2cdd84840b13a8b0bceec64aad0 | |
| parent | 9ff8ca7d3f4f71b1e42a136d1465da43baf7085b (diff) | |
Allow creating memories without an implicit clock (#2494) (#2495)
Fixes #2470
(cherry picked from commit 44165a259bb16733a41798edca6b554b13f1d54a)
Co-authored-by: Kevin Laeufer <laeufer@cs.berkeley.edu>
| -rw-r--r-- | core/src/main/scala/chisel3/Mem.scala | 10 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/Mem.scala | 52 |
2 files changed, 58 insertions, 4 deletions
diff --git a/core/src/main/scala/chisel3/Mem.scala b/core/src/main/scala/chisel3/Mem.scala index 36984a3a..d6ab9c4b 100644 --- a/core/src/main/scala/chisel3/Mem.scala +++ b/core/src/main/scala/chisel3/Mem.scala @@ -56,7 +56,9 @@ sealed abstract class MemBase[T <: Data](val t: T, val length: BigInt) with SourceInfoDoc { _parent.foreach(_.addId(this)) - private val clockInst: Clock = Builder.forcedClock + // if the memory is created in a scope with an implicit clock (-> clockInst is defined), we will perform checks that + // ensure memory ports are created with the same clock unless explicitly specified to use a different clock + private val clockInst: Option[Clock] = Builder.currentClock protected def clockWarning(sourceInfo: Option[SourceInfo]): Unit = { // Turn into pretty String if possible, if not, Builder.deprecated will find one via stack trace @@ -132,7 +134,7 @@ sealed abstract class MemBase[T <: Data](val t: T, val length: BigInt) implicit sourceInfo: SourceInfo, compileOptions: CompileOptions ): T = { - if (warn && clock != clockInst) { + if (warn && clockInst.isDefined && clock != clockInst.get) { clockWarning(Some(sourceInfo)) } makePort(sourceInfo, idx, dir, clock) @@ -164,7 +166,7 @@ sealed abstract class MemBase[T <: Data](val t: T, val length: BigInt) )( implicit compileOptions: CompileOptions ): Unit = { - if (warn && clock != clockInst) { + if (warn && clockInst.isDefined && clock != clockInst.get) { clockWarning(None) } implicit val sourceInfo = UnlocatableSourceInfo @@ -223,7 +225,7 @@ sealed abstract class MemBase[T <: Data](val t: T, val length: BigInt) compileOptions: CompileOptions ): Unit = { implicit val sourceInfo = UnlocatableSourceInfo - if (warn && clock != clockInst) { + if (warn && clockInst.isDefined && clock != clockInst.get) { clockWarning(None) } val accessor = makePort(sourceInfo, idx, MemPortDirection.WRITE, clock).asInstanceOf[Vec[Data]] diff --git a/src/test/scala/chiselTests/Mem.scala b/src/test/scala/chiselTests/Mem.scala index 4dcb1ad4..c5fcc6b1 100644 --- a/src/test/scala/chiselTests/Mem.scala +++ b/src/test/scala/chiselTests/Mem.scala @@ -3,6 +3,7 @@ package chiselTests import chisel3._ +import chisel3.stage.ChiselStage import chisel3.util._ import chisel3.testers.BasicTester @@ -141,6 +142,52 @@ class MemBundleTester extends BasicTester { } } +private class TrueDualPortMemoryIO(val addrW: Int, val dataW: Int) extends Bundle { + require(addrW > 0, "address width must be greater than 0") + require(dataW > 0, "data width must be greater than 0") + + val clka = Input(Clock()) + val ena = Input(Bool()) + val wea = Input(Bool()) + val addra = Input(UInt(addrW.W)) + val dia = Input(UInt(dataW.W)) + val doa = Output(UInt(dataW.W)) + + val clkb = Input(Clock()) + val enb = Input(Bool()) + val web = Input(Bool()) + val addrb = Input(UInt(addrW.W)) + val dib = Input(UInt(dataW.W)) + val dob = Output(UInt(dataW.W)) +} + +private class TrueDualPortMemory(addrW: Int, dataW: Int) extends RawModule { + val io = IO(new TrueDualPortMemoryIO(addrW, dataW)) + val ram = SyncReadMem(1 << addrW, UInt(dataW.W)) + + // Port a + withClock(io.clka) { + io.doa := DontCare + when(io.ena) { + when(io.wea) { + ram(io.addra) := io.dia + } + io.doa := ram(io.addra) + } + } + + // Port b + withClock(io.clkb) { + io.dob := DontCare + when(io.enb) { + when(io.web) { + ram(io.addrb) := io.dib + } + io.dob := ram(io.addrb) + } + } +} + class MemorySpec extends ChiselPropSpec { property("Mem of Vec should work") { assertTesterPasses { new MemVecTester } @@ -186,4 +233,9 @@ class MemorySpec extends ChiselPropSpec { |} |""".stripMargin should compile } + + property("memories in modules without implicit clock should compile without warning or error") { + val stage = new ChiselStage + stage.emitVerilog(new TrueDualPortMemory(4, 32)) + } } |
