summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJack Koenig2019-04-23 16:24:19 -0700
committerGitHub2019-04-23 16:24:19 -0700
commit9bef2461e55c724354f20bce0d32c7f5e6ac45ff (patch)
treec0db6362db710d8069d5b7e147d6b65486d632ea
parent32acdcf63ab74e7d47d7600f2211a72dd19280c3 (diff)
Change size of memories from Int to BigInt (#1076)
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala4
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Mem.scala40
-rw-r--r--chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala4
-rw-r--r--src/test/scala/chiselTests/Mem.scala37
4 files changed, 75 insertions, 10 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala
index 51b45828..64148170 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala
@@ -89,9 +89,9 @@ trait VecFactory extends SourceInfoDoc {
}
/** Truncate an index to implement modulo-power-of-2 addressing. */
- private[core] def truncateIndex(idx: UInt, n: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = { // scalastyle:ignore line.size.limit
+ private[core] def truncateIndex(idx: UInt, n: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = { // scalastyle:ignore line.size.limit
// scalastyle:off if.brace
- val w = BigInt(n-1).bitLength
+ val w = (n-1).bitLength
if (n <= 1) 0.U
else if (idx.width.known && idx.width.get <= w) idx
else if (idx.width.known) idx(w-1,0)
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala
index f9211ee7..d9fab09a 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala
@@ -14,6 +14,11 @@ object Mem {
// scalastyle:off line.size.limit
@chiselRuntimeDeprecated
@deprecated("Mem argument order should be size, t; this will be removed by the official release", "chisel3")
+ def apply[T <: Data](t: T, size: BigInt)(implicit compileOptions: CompileOptions): Mem[T] = do_apply(size, t)(UnlocatableSourceInfo, compileOptions)
+
+ // scalastyle:off line.size.limit
+ @chiselRuntimeDeprecated
+ @deprecated("Mem argument order should be size, t; this will be removed by the official release", "chisel3")
def apply[T <: Data](t: T, size: Int)(implicit compileOptions: CompileOptions): Mem[T] = do_apply(size, t)(UnlocatableSourceInfo, compileOptions)
/** Creates a combinational/asynchronous-read, sequential/synchronous-write [[Mem]].
@@ -21,10 +26,17 @@ object Mem {
* @param size number of elements in the memory
* @param t data type of memory element
*/
+ def apply[T <: Data](size: BigInt, t: T): Mem[T] = macro MemTransform.apply[T]
+
+ /** Creates a combinational/asynchronous-read, sequential/synchronous-write [[Mem]].
+ *
+ * @param size number of elements in the memory
+ * @param t data type of memory element
+ */
def apply[T <: Data](size: Int, t: T): Mem[T] = macro MemTransform.apply[T]
/** @group SourceInfoTransformMacro */
- def do_apply[T <: Data](size: Int, t: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Mem[T] = {
+ def do_apply[T <: Data](size: BigInt, t: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Mem[T] = {
if (compileOptions.declaredTypeMustBeUnbound) {
requireIsChiselType(t, "memory type")
}
@@ -35,16 +47,21 @@ object Mem {
}
}
-sealed abstract class MemBase[T <: Data](t: T, val length: Int) extends HasId with NamedComponent with SourceInfoDoc {
+sealed abstract class MemBase[T <: Data](t: T, val length: BigInt) extends HasId with NamedComponent with SourceInfoDoc {
// REVIEW TODO: make accessors (static/dynamic, read/write) combinations consistent.
/** Creates a read accessor into the memory with static addressing. See the
* class documentation of the memory for more detailed information.
*/
+ def apply(x: BigInt): T = macro SourceInfoTransform.xArg
+
+ /** Creates a read accessor into the memory with static addressing. See the
+ * class documentation of the memory for more detailed information.
+ */
def apply(x: Int): T = macro SourceInfoTransform.xArg
/** @group SourceInfoTransformMacro */
- def do_apply(idx: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = {
+ def do_apply(idx: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = {
require(idx >= 0 && idx < length)
apply(idx.asUInt)
}
@@ -123,11 +140,15 @@ sealed abstract class MemBase[T <: Data](t: T, val length: Int) extends HasId wi
* @note when multiple conflicting writes are performed on a Mem element, the
* result is undefined (unlike Vec, where the last assignment wins)
*/
-sealed class Mem[T <: Data] private (t: T, length: Int) extends MemBase(t, length)
+sealed class Mem[T <: Data] private (t: T, length: BigInt) extends MemBase(t, length)
object SyncReadMem {
@chiselRuntimeDeprecated
@deprecated("SeqMem/SyncReadMem argument order should be size, t; this will be removed by the official release", "chisel3")
+ def apply[T <: Data](t: T, size: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SyncReadMem[T] = do_apply(size, t)
+
+ @chiselRuntimeDeprecated
+ @deprecated("SeqMem/SyncReadMem argument order should be size, t; this will be removed by the official release", "chisel3")
def apply[T <: Data](t: T, size: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SyncReadMem[T] = do_apply(size, t)
/** Creates a sequential/synchronous-read, sequential/synchronous-write [[SyncReadMem]].
@@ -135,10 +156,17 @@ object SyncReadMem {
* @param size number of elements in the memory
* @param t data type of memory element
*/
+ def apply[T <: Data](size: BigInt, t: T): SyncReadMem[T] = macro MemTransform.apply[T]
+
+ /** Creates a sequential/synchronous-read, sequential/synchronous-write [[SyncReadMem]].
+ *
+ * @param size number of elements in the memory
+ * @param t data type of memory element
+ */
def apply[T <: Data](size: Int, t: T): SyncReadMem[T] = macro MemTransform.apply[T]
/** @group SourceInfoTransformMacro */
- def do_apply[T <: Data](size: Int, t: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SyncReadMem[T] = {
+ def do_apply[T <: Data](size: BigInt, t: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SyncReadMem[T] = {
if (compileOptions.declaredTypeMustBeUnbound) {
requireIsChiselType(t, "memory type")
}
@@ -159,7 +187,7 @@ object SyncReadMem {
* @note when multiple conflicting writes are performed on a Mem element, the
* result is undefined (unlike Vec, where the last assignment wins)
*/
-sealed class SyncReadMem[T <: Data] private (t: T, n: Int) extends MemBase[T](t, n) {
+sealed class SyncReadMem[T <: Data] private (t: T, n: BigInt) extends MemBase[T](t, n) {
def read(x: UInt, en: Bool): T = macro SourceInfoTransform.xEnArg
/** @group SourceInfoTransformMacro */
diff --git a/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala
index 0b0d1871..7854efdb 100644
--- a/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala
+++ b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala
@@ -269,8 +269,8 @@ case class DefInvalid(sourceInfo: SourceInfo, arg: Arg) extends Command
case class DefWire(sourceInfo: SourceInfo, id: Data) extends Definition
case class DefReg(sourceInfo: SourceInfo, id: Data, clock: Arg) extends Definition
case class DefRegInit(sourceInfo: SourceInfo, id: Data, clock: Arg, reset: Arg, init: Arg) extends Definition
-case class DefMemory(sourceInfo: SourceInfo, id: HasId, t: Data, size: Int) extends Definition
-case class DefSeqMemory(sourceInfo: SourceInfo, id: HasId, t: Data, size: Int) extends Definition
+case class DefMemory(sourceInfo: SourceInfo, id: HasId, t: Data, size: BigInt) extends Definition
+case class DefSeqMemory(sourceInfo: SourceInfo, id: HasId, t: Data, size: BigInt) extends Definition
case class DefMemPort[T <: Data](sourceInfo: SourceInfo, id: T, source: Node, dir: MemPortDirection, index: Arg, clock: Arg) extends Definition
case class DefInstance(sourceInfo: SourceInfo, id: BaseModule, ports: Seq[Port]) extends Definition
case class WhenBegin(sourceInfo: SourceInfo, pred: Arg) extends Command
diff --git a/src/test/scala/chiselTests/Mem.scala b/src/test/scala/chiselTests/Mem.scala
index 60835d49..176ea5e7 100644
--- a/src/test/scala/chiselTests/Mem.scala
+++ b/src/test/scala/chiselTests/Mem.scala
@@ -44,6 +44,34 @@ class SyncReadMemWithZeroWidthTester extends BasicTester {
}
}
+// TODO this can't actually simulate with FIRRTL behavioral mems
+class HugeSMemTester(size: BigInt) extends BasicTester {
+ val (cnt, _) = Counter(true.B, 5)
+ val mem = SyncReadMem(size, UInt(8.W))
+ val rdata = mem.read(cnt - 1.U, cnt =/= 0.U)
+
+ switch (cnt) {
+ is (0.U) { mem.write(cnt, 3.U) }
+ is (1.U) { mem.write(cnt, 2.U) }
+ is (2.U) { assert(rdata === 3.U) }
+ is (3.U) { assert(rdata === 2.U) }
+ is (4.U) { stop() }
+ }
+}
+class HugeCMemTester(size: BigInt) extends BasicTester {
+ val (cnt, _) = Counter(true.B, 5)
+ val mem = Mem(size, UInt(8.W))
+ val rdata = mem.read(cnt)
+
+ switch (cnt) {
+ is (0.U) { mem.write(cnt, 3.U) }
+ is (1.U) { mem.write(cnt, 2.U) }
+ is (2.U) { assert(rdata === 3.U) }
+ is (3.U) { assert(rdata === 2.U) }
+ is (4.U) { stop() }
+ }
+}
+
class MemorySpec extends ChiselPropSpec {
property("Mem of Vec should work") {
assertTesterPasses { new MemVecTester }
@@ -56,4 +84,13 @@ class MemorySpec extends ChiselPropSpec {
property("SyncReadMem should work with zero width entry") {
assertTesterPasses { new SyncReadMemWithZeroWidthTester }
}
+
+ property("Massive memories should be emitted in Verilog") {
+ val addrWidth = 65
+ val size = BigInt(1) << addrWidth
+ val smem = compile(new HugeSMemTester(size))
+ smem should include (s"reg /* sparse */ [7:0] mem [0:$addrWidth'd${size-1}];")
+ val cmem = compile(new HugeCMemTester(size))
+ cmem should include (s"reg /* sparse */ [7:0] mem [0:$addrWidth'd${size-1}];")
+ }
}