summaryrefslogtreecommitdiff
path: root/chiselFrontend
diff options
context:
space:
mode:
authorAndrew Waterman2016-10-05 15:32:23 -0700
committerAndrew Waterman2016-10-05 16:05:20 -0700
commit7981c6d9e6d25fb27b25e1427794775c9f934a09 (patch)
treecae7aed020df89f3923044475c2ad6b4cb9ed4c6 /chiselFrontend
parent0878b7a7d30038797e3711ad2d44ab0bc753bab1 (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.scala14
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Mem.scala8
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")