summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authormergify[bot]2022-04-19 02:29:00 +0000
committerGitHub2022-04-19 02:29:00 +0000
commit70da39e140e96a9302a94864f077529e02596ef5 (patch)
treea7fa6a52fe7bb2cdd84840b13a8b0bceec64aad0
parent9ff8ca7d3f4f71b1e42a136d1465da43baf7085b (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.scala10
-rw-r--r--src/test/scala/chiselTests/Mem.scala52
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))
+ }
}