summaryrefslogtreecommitdiff
path: root/src/main/scala/Chisel/Mem.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/scala/Chisel/Mem.scala')
-rw-r--r--src/main/scala/Chisel/Mem.scala99
1 files changed, 99 insertions, 0 deletions
diff --git a/src/main/scala/Chisel/Mem.scala b/src/main/scala/Chisel/Mem.scala
new file mode 100644
index 00000000..87f717b6
--- /dev/null
+++ b/src/main/scala/Chisel/Mem.scala
@@ -0,0 +1,99 @@
+// See LICENSE for license details.
+
+package Chisel
+import Builder.pushCommand
+
+object Mem {
+ @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): Mem[T] = apply(size, t)
+
+ /** Creates a combinational-read, sequential-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] = {
+ val mt = t.cloneType
+ val mem = new Mem(mt, size)
+ pushCommand(DefMemory(mem, mt, size, Node(mt._parent.get.clock))) // TODO multi-clock
+ mem
+ }
+}
+
+sealed abstract class MemBase[T <: Data](t: T, val length: Int) extends HasId with VecLike[T] {
+ // 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(idx: Int): T = apply(UInt(idx))
+
+ /** Creates a read accessor into the memory with dynamic addressing. See the
+ * class documentation of the memory for more detailed information.
+ */
+ def apply(idx: UInt): T =
+ pushCommand(DefAccessor(t.cloneType, Node(this), NO_DIR, idx.ref)).id
+
+ def read(idx: UInt): T = apply(idx)
+
+ /** Creates a write accessor into the memory.
+ *
+ * @param idx memory element index to write into
+ * @param data new data to write
+ */
+ def write(idx: UInt, data: T): Unit = apply(idx) := data
+
+ /** Creates a masked write accessor into the memory.
+ *
+ * @param idx memory element index to write into
+ * @param data new data to write
+ * @param mask write mask as a Vec of Bool: a write to the Vec element in
+ * memory is only performed if the corresponding mask index is true.
+ *
+ * @note this is only allowed if the memory's element data type is a Vec
+ */
+ def write(idx: UInt, data: T, mask: Vec[Bool]) (implicit evidence: T <:< Vec[_]): Unit = {
+ // REVIEW TODO: error checking to detect zip length mismatch?
+
+ val accessor = apply(idx).asInstanceOf[Vec[Data]]
+ for (((cond, port), datum) <- mask zip accessor zip data.asInstanceOf[Vec[Data]])
+ when (cond) { port := datum }
+ }
+}
+
+/** A combinational-read, sequential-write memory.
+ *
+ * Writes take effect on the rising clock edge after the request. Reads are
+ * combinational (requests will return data on the same cycle).
+ * Read-after-write hazards are not an issue.
+ */
+sealed class Mem[T <: Data](t: T, length: Int) extends MemBase(t, length)
+
+object SeqMem {
+ @deprecated("SeqMem argument order should be size, t; this will be removed by the official release", "chisel3")
+ def apply[T <: Data](t: T, size: Int): SeqMem[T] = apply(size, t)
+
+ /** Creates a sequential-read, sequential-write [[SeqMem]].
+ *
+ * @param size number of elements in the memory
+ * @param t data type of memory element
+ */
+ def apply[T <: Data](size: Int, t: T): SeqMem[T] = {
+ val mt = t.cloneType
+ val mem = new SeqMem(mt, size)
+ pushCommand(DefSeqMemory(mem, mt, size, Node(mt._parent.get.clock))) // TODO multi-clock
+ mem
+ }
+}
+
+/** A sequential-read, sequential-write memory.
+ *
+ * Writes take effect on the rising clock edge after the request. Reads return
+ * data on the rising edge after the request. Read-after-write behavior (when
+ * a read and write to the same address are requested on the same cycle) is
+ * undefined.
+ */
+sealed class SeqMem[T <: Data](t: T, n: Int) extends MemBase[T](t, n) {
+ def read(addr: UInt, enable: Bool): T =
+ read(Mux(enable, addr, Poison(addr)))
+}