diff options
| author | Andrew Waterman | 2016-10-05 15:32:23 -0700 |
|---|---|---|
| committer | Andrew Waterman | 2016-10-05 16:05:20 -0700 |
| commit | 7981c6d9e6d25fb27b25e1427794775c9f934a09 (patch) | |
| tree | cae7aed020df89f3923044475c2ad6b4cb9ed4c6 /chiselFrontend | |
| parent | 0878b7a7d30038797e3711ad2d44ab0bc753bab1 (diff) | |
Use modulo addressing for dynamic Vec/Mem accesses
Static accesses are strictly checked.
Diffstat (limited to 'chiselFrontend')
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala | 14 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/core/Mem.scala | 8 |
2 files changed, 18 insertions, 4 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala index 5cec54c2..7b759493 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala @@ -9,7 +9,7 @@ import scala.language.experimental.macros import chisel3.internal._ import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl._ -import chisel3.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, VecTransform, SourceInfoTransform} +import chisel3.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, VecTransform, SourceInfoTransform, UnlocatableSourceInfo} /** An abstract class for data types that solely consist of (are an aggregate * of) other Data objects. @@ -113,6 +113,15 @@ object Vec { def do_fill[T <: Data](n: Int)(gen: => T)(implicit sourceInfo: SourceInfo): Vec[T] = apply(Seq.fill(n)(gen)) + + /** Truncate an index to implement modulo-power-of-2 addressing. */ + private[core] def truncateIndex(idx: UInt, n: Int)(implicit sourceInfo: SourceInfo): UInt = { + val w = BigInt(n-1).bitLength + if (n <= 1) UInt(0) + else if (idx.width.known && idx.width.get <= w) idx + else if (idx.width.known) idx(w-1,0) + else Wire(UInt(width = w), init = idx) + } } /** A vector (array) of [[Data]] elements. Provides hardware versions of various @@ -178,7 +187,8 @@ sealed class Vec[T <: Data] private (gen: T, val length: Int) def apply(idx: UInt): T = { Binding.checkSynthesizable(idx ,s"'idx' ($idx)") val port = sample_element.chiselCloneType - port.setRef(this, idx) //TODO(twigg): This is a bit too magical + val i = Vec.truncateIndex(idx, length)(UnlocatableSourceInfo) + port.setRef(this, i) // Bind each element of port to being whatever the base type is // Using the head element as the sample_element diff --git a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala index b24d463a..9cd5a4d8 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala @@ -38,7 +38,10 @@ sealed abstract class MemBase[T <: Data](t: T, val length: Int) extends HasId wi /** Creates a read accessor into the memory with static addressing. See the * class documentation of the memory for more detailed information. */ - def apply(idx: Int): T = apply(UInt(idx)) + def apply(idx: Int): T = { + require(idx >= 0 && idx < length) + apply(UInt(idx)) + } /** Creates a read/write accessor into the memory with dynamic addressing. * See the class documentation of the memory for more detailed information. @@ -85,10 +88,11 @@ sealed abstract class MemBase[T <: Data](t: T, val length: Int) extends HasId wi private def makePort(sourceInfo: SourceInfo, idx: UInt, dir: MemPortDirection): T = { Binding.checkSynthesizable(idx, s"'idx' ($idx)") + val i = Vec.truncateIndex(idx, length)(sourceInfo) val port = pushCommand( DefMemPort(sourceInfo, - t.chiselCloneType, Node(this), dir, idx.ref, Node(idx._parent.get.clock)) + t.chiselCloneType, Node(this), dir, i.ref, Node(i._parent.get.clock)) ).id // Bind each element of port to being a MemoryPort Binding.bind(port, MemoryPortBinder(Builder.forcedModule), "Error: Fresh t") |
