summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/main/resources/top.cpp8
-rw-r--r--src/main/scala/Chisel/Aggregate.scala23
-rw-r--r--src/main/scala/Chisel/BitPat.scala3
-rw-r--r--src/main/scala/Chisel/Bits.scala76
-rw-r--r--src/main/scala/Chisel/CoreUtil.scala6
-rw-r--r--src/main/scala/Chisel/Data.scala25
-rw-r--r--src/main/scala/Chisel/Driver.scala2
-rw-r--r--src/main/scala/Chisel/Main.scala8
-rw-r--r--src/main/scala/Chisel/Mem.scala41
-rw-r--r--src/main/scala/Chisel/Module.scala12
-rw-r--r--src/main/scala/Chisel/Reg.scala10
-rw-r--r--src/main/scala/Chisel/When.scala29
-rw-r--r--src/main/scala/Chisel/internal/Builder.scala7
-rw-r--r--src/main/scala/Chisel/internal/firrtl/Emitter.scala (renamed from src/main/scala/Chisel/firrtl/Emitter.scala)25
-rw-r--r--src/main/scala/Chisel/internal/firrtl/IR.scala (renamed from src/main/scala/Chisel/firrtl/IR.scala)35
-rw-r--r--src/main/scala/Chisel/testers/BasicTester.scala2
-rw-r--r--src/main/scala/Chisel/util/Arbiter.scala2
-rw-r--r--src/main/scala/Chisel/util/Decoupled.scala2
-rw-r--r--src/test/scala/chiselTests/When.scala60
19 files changed, 242 insertions, 134 deletions
diff --git a/src/main/resources/top.cpp b/src/main/resources/top.cpp
index 075d7085..8bfe2a99 100644
--- a/src/main/resources/top.cpp
+++ b/src/main/resources/top.cpp
@@ -44,10 +44,10 @@ int main(int argc, char** argv) {
top->reset = 0; // Deassert reset
}
if ((main_time % 10) == 1) {
- top->clock = 1; // Toggle clock
+ top->clk = 1; // Toggle clock
}
if ((main_time % 10) == 6) {
- top->clock = 0;
+ top->clk = 0;
}
top->eval(); // Evaluate model
#if VM_TRACE
@@ -69,10 +69,10 @@ int main(int argc, char** argv) {
vluint64_t end_time = main_time + 100;
while (main_time < end_time) {
if ((main_time % 10) == 1) {
- top->clock = 1; // Toggle clock
+ top->clk = 1; // Toggle clock
}
if ((main_time % 10) == 6) {
- top->clock = 0;
+ top->clk = 0;
}
top->eval(); // Evaluate model
#if VM_TRACE
diff --git a/src/main/scala/Chisel/Aggregate.scala b/src/main/scala/Chisel/Aggregate.scala
index 35b8b4e5..3df48052 100644
--- a/src/main/scala/Chisel/Aggregate.scala
+++ b/src/main/scala/Chisel/Aggregate.scala
@@ -7,7 +7,7 @@ import scala.collection.mutable.{ArrayBuffer, HashSet, LinkedHashMap}
import internal._
import internal.Builder.pushCommand
-import firrtl._
+import internal.firrtl._
/** An abstract class for data types that solely consist of (are an aggregate
* of) other Data objects.
@@ -103,21 +103,16 @@ sealed class Vec[T <: Data] private (gen: => T, val length: Int)
private val self = IndexedSeq.fill(length)(gen)
- override def <> (that: Data): Unit = that match {
- case _: Vec[_] => this bulkConnect that
- case _ => this badConnect that
- }
+ override def <> (that: Data): Unit = this := that
- /** Weak bulk connect, assigning elements in this Vec from elements in a Seq.
+ /** Strong bulk connect, assigning elements in this Vec from elements in a Seq.
*
- * @note length mismatches silently ignored
+ * @note the length of this Vec must match the length of the input Seq
*/
- def <> (that: Seq[T]): Unit =
- for ((a, b) <- this zip that)
- a <> b
+ def <> (that: Seq[T]): Unit = this := that
// TODO: eliminate once assign(Seq) isn't ambiguous with assign(Data) since Vec extends Seq and Data
- def <> (that: Vec[T]): Unit = this bulkConnect that
+ def <> (that: Vec[T]): Unit = this := that.asInstanceOf[Data]
override def := (that: Data): Unit = that match {
case _: Vec[_] => this connect that
@@ -141,7 +136,7 @@ sealed class Vec[T <: Data] private (gen: => T, val length: Int)
*/
def apply(idx: UInt): T = {
val x = gen
- pushCommand(DefAccessor(x, Node(this), NO_DIR, idx.ref))
+ x.setRef(this, idx)
x
}
@@ -156,7 +151,7 @@ sealed class Vec[T <: Data] private (gen: => T, val length: Int)
def write(idx: UInt, data: T): Unit = apply(idx) := data
override def cloneType: this.type =
- Vec(gen, length).asInstanceOf[this.type]
+ Vec(length, gen).asInstanceOf[this.type]
private val t = gen
private[Chisel] def toType: String = s"${t.toType}[$length]"
@@ -331,7 +326,7 @@ class Bundle extends Aggregate(NO_DIR) {
try {
constructor.newInstance(_parent.get).asInstanceOf[this.type]
} catch {
- case _: java.lang.reflect.InvocationTargetException =>
+ case _: java.lang.reflect.InvocationTargetException | _: java.lang.IllegalArgumentException =>
Builder.error(s"Parameterized Bundle ${this.getClass} needs cloneType method. You are probably using " +
"an anonymous Bundle object that captures external state and hence is un-cloneTypeable")
this
diff --git a/src/main/scala/Chisel/BitPat.scala b/src/main/scala/Chisel/BitPat.scala
index b4138992..a1bf1985 100644
--- a/src/main/scala/Chisel/BitPat.scala
+++ b/src/main/scala/Chisel/BitPat.scala
@@ -75,5 +75,6 @@ object BitPat {
sealed class BitPat(val value: BigInt, val mask: BigInt, width: Int) {
def getWidth: Int = width
def === (other: UInt): Bool = UInt(value) === (other & UInt(mask))
- def != (other: UInt): Bool = !(this === other)
+ def =/= (other: UInt): Bool = !(this === other)
+ def != (other: UInt): Bool = this =/= other
}
diff --git a/src/main/scala/Chisel/Bits.scala b/src/main/scala/Chisel/Bits.scala
index e001f864..b800644d 100644
--- a/src/main/scala/Chisel/Bits.scala
+++ b/src/main/scala/Chisel/Bits.scala
@@ -4,15 +4,13 @@ package Chisel
import internal._
import internal.Builder.pushOp
-import firrtl._
+import internal.firrtl._
import firrtl.PrimOp._
/** Element is a leaf data type: it cannot contain other Data objects. Example
* uses are for representing primitive data types, like integers and bits.
*/
-abstract class Element(dirArg: Direction, val width: Width) extends Data(dirArg) {
- private[Chisel] def flatten: IndexedSeq[UInt] = IndexedSeq(toBits)
-}
+abstract class Element(dirArg: Direction, val width: Width) extends Data(dirArg)
/** A data type for values represented by a single bitvector. Provides basic
* bitwise operations.
@@ -25,10 +23,30 @@ sealed abstract class Bits(dirArg: Direction, width: Width, override val litArg:
private[Chisel] def fromInt(x: BigInt): this.type
+ private[Chisel] def flatten: IndexedSeq[Bits] = IndexedSeq(this)
+
def cloneType: this.type = cloneTypeWidth(width)
override def <> (that: Data): Unit = this := that
+ def tail(n: Int): UInt = {
+ val w = width match {
+ case KnownWidth(x) =>
+ require(x >= n, s"Can't tail($n) for width $x < $n")
+ Width(x - n)
+ case UnknownWidth() => Width()
+ }
+ binop(UInt(width = w), TailOp, n)
+ }
+
+ def head(n: Int): UInt = {
+ width match {
+ case KnownWidth(x) => require(x >= n, s"Can't head($n) for width $x < $n")
+ case UnknownWidth() =>
+ }
+ binop(UInt(width = n), HeadOp, n)
+ }
+
/** Returns the specified bit on this wire as a [[Bool]], statically
* addressed.
*/
@@ -39,7 +57,7 @@ sealed abstract class Bits(dirArg: Direction, width: Width, override val litArg:
if (isLit()) {
Bool(((litValue() >> x.toInt) & 1) == 1)
} else {
- pushOp(DefPrim(Bool(), BitSelectOp, this.ref, ILit(x)))
+ pushOp(DefPrim(Bool(), BitsExtractOp, this.ref, ILit(x), ILit(x)))
}
}
@@ -92,9 +110,6 @@ sealed abstract class Bits(dirArg: Direction, width: Width, override val litArg:
private[Chisel] def redop(op: PrimOp): Bool =
pushOp(DefPrim(Bool(), op, this.ref))
- /** Returns this wire bitwise-inverted. */
- def unary_~ : this.type = unop(cloneTypeWidth(width), BitNotOp)
-
/** Returns this wire zero padded up to the specified width.
*
* @note for SInts only, this does sign extension
@@ -279,19 +294,22 @@ sealed class UInt private[Chisel] (dir: Direction, width: Width, lit: Option[ULi
def unary_-% : UInt = UInt(0) -% this
def +& (other: UInt): UInt = binop(UInt((this.width max other.width) + 1), AddOp, other)
def + (other: UInt): UInt = this +% other
- def +% (other: UInt): UInt = binop(UInt(this.width max other.width), AddModOp, other)
+ def +% (other: UInt): UInt = (this +& other) tail 1
def -& (other: UInt): UInt = binop(UInt((this.width max other.width) + 1), SubOp, other)
def - (other: UInt): UInt = this -% other
- def -% (other: UInt): UInt = binop(UInt(this.width max other.width), SubModOp, other)
+ def -% (other: UInt): UInt = (this -& other) tail 1
def * (other: UInt): UInt = binop(UInt(this.width + other.width), TimesOp, other)
def * (other: SInt): SInt = other * this
def / (other: UInt): UInt = binop(UInt(this.width), DivideOp, other)
- def % (other: UInt): UInt = binop(UInt(this.width), ModOp, other)
+ def % (other: UInt): UInt = binop(UInt(this.width), RemOp, other)
def & (other: UInt): UInt = binop(UInt(this.width max other.width), BitAndOp, other)
def | (other: UInt): UInt = binop(UInt(this.width max other.width), BitOrOp, other)
def ^ (other: UInt): UInt = binop(UInt(this.width max other.width), BitXorOp, other)
+ /** Returns this wire bitwise-inverted. */
+ def unary_~ : UInt = unop(UInt(width = width), BitNotOp)
+
// REVIEW TODO: Can this be defined on Bits?
def orR: Bool = this != UInt(0)
def andR: Bool = ~this === UInt(0)
@@ -321,6 +339,7 @@ sealed class UInt private[Chisel] (dir: Direction, width: Width, lit: Option[ULi
def === (that: BitPat): Bool = that === this
def != (that: BitPat): Bool = that != this
+ def =/= (that: BitPat): Bool = that =/= this
/** Returns this UInt as a [[SInt]] with an additional zero in the MSB.
*/
@@ -409,21 +428,24 @@ sealed class SInt private (dir: Direction, width: Width, lit: Option[SLit] = Non
/** add (default - no growth) operator */
def + (other: SInt): SInt = this +% other
/** add (no growth) operator */
- def +% (other: SInt): SInt = binop(SInt(this.width max other.width), AddModOp, other)
+ def +% (other: SInt): SInt = (this +& other).tail(1).asSInt
/** subtract (width +1) operator */
def -& (other: SInt): SInt = binop(SInt((this.width max other.width) + 1), SubOp, other)
/** subtract (default - no growth) operator */
def - (other: SInt): SInt = this -% other
/** subtract (no growth) operator */
- def -% (other: SInt): SInt = binop(SInt(this.width max other.width), SubModOp, other)
+ def -% (other: SInt): SInt = (this -& other).tail(1).asSInt
def * (other: SInt): SInt = binop(SInt(this.width + other.width), TimesOp, other)
def * (other: UInt): SInt = binop(SInt(this.width + other.width), TimesOp, other)
def / (other: SInt): SInt = binop(SInt(this.width), DivideOp, other)
- def % (other: SInt): SInt = binop(SInt(this.width), ModOp, other)
+ def % (other: SInt): SInt = binop(SInt(this.width), RemOp, other)
- def & (other: SInt): SInt = binop(SInt(this.width max other.width), BitAndOp, other)
- def | (other: SInt): SInt = binop(SInt(this.width max other.width), BitOrOp, other)
- def ^ (other: SInt): SInt = binop(SInt(this.width max other.width), BitXorOp, other)
+ def & (other: SInt): SInt = binop(UInt(this.width max other.width), BitAndOp, other).asSInt
+ def | (other: SInt): SInt = binop(UInt(this.width max other.width), BitOrOp, other).asSInt
+ def ^ (other: SInt): SInt = binop(UInt(this.width max other.width), BitXorOp, other).asSInt
+
+ /** Returns this wire bitwise-inverted. */
+ def unary_~ : SInt = unop(UInt(width = width), BitNotOp).asSInt
def < (other: SInt): Bool = compop(LessOp, other)
def > (other: SInt): Bool = compop(GreaterOp, other)
@@ -431,7 +453,7 @@ sealed class SInt private (dir: Direction, width: Width, lit: Option[SLit] = Non
def >= (other: SInt): Bool = compop(GreaterEqOp, other)
def != (other: SInt): Bool = compop(NotEqualOp, other)
def === (other: SInt): Bool = compop(EqualOp, other)
- def abs(): UInt = Mux(this < SInt(0), (-this).toUInt, this.toUInt)
+ def abs(): UInt = Mux(this < SInt(0), (-this).asUInt, this.asUInt)
def << (other: Int): SInt = binop(SInt(this.width + other), ShiftLeftOp, other)
def << (other: BigInt): SInt = this << other.toInt
@@ -489,6 +511,9 @@ sealed class Bool(dir: Direction, lit: Option[ULit] = None) extends UInt(dir, Wi
def | (other: Bool): Bool = binop(Bool(), BitOrOp, other)
def ^ (other: Bool): Bool = binop(Bool(), BitXorOp, other)
+ /** Returns this wire bitwise-inverted. */
+ override def unary_~ : Bool = unop(Bool(), BitNotOp)
+
/** Outputs the logical OR of two Bools.
*/
def || (that: Bool): Bool = this | that
@@ -526,21 +551,20 @@ object Mux {
case (c: UInt, a: Bool) => doMux(cond, c, a << 0).asInstanceOf[T]
case (c: Bool, a: UInt) => doMux(cond, c << 0, a).asInstanceOf[T]
case (c: Bits, a: Bits) => doMux(cond, c, a).asInstanceOf[T]
- // FIRRTL doesn't support Mux for aggregates, so use a when instead
- case _ => doWhen(cond, con, alt)
+ case _ => doAggregateMux(cond, con, alt)
}
- private def doMux[T <: Bits](cond: Bool, con: T, alt: T): T = {
+ private def doMux[T <: Data](cond: Bool, con: T, alt: T): T = {
require(con.getClass == alt.getClass, s"can't Mux between ${con.getClass} and ${alt.getClass}")
val d = alt.cloneTypeWidth(con.width max alt.width)
pushOp(DefPrim(d, MultiplexOp, cond.ref, con.ref, alt.ref))
}
- // This returns an lvalue, which it most definitely should not
- private def doWhen[T <: Data](cond: Bool, con: T, alt: T): T = {
+
+ private def doAggregateMux[T <: Data](cond: Bool, con: T, alt: T): T = {
require(con.getClass == alt.getClass, s"can't Mux between ${con.getClass} and ${alt.getClass}")
- val res = Wire(t = alt.cloneTypeWidth(con.width max alt.width), init = alt)
- when (cond) { res := con }
- res
+ for ((c, a) <- con.flatten zip alt.flatten)
+ require(c.width == a.width, "can't Mux between aggregates of different width")
+ doMux(cond, con, alt)
}
}
diff --git a/src/main/scala/Chisel/CoreUtil.scala b/src/main/scala/Chisel/CoreUtil.scala
index 7077c9c1..eed90410 100644
--- a/src/main/scala/Chisel/CoreUtil.scala
+++ b/src/main/scala/Chisel/CoreUtil.scala
@@ -4,7 +4,7 @@ package Chisel
import internal._
import internal.Builder.pushCommand
-import firrtl._
+import internal.firrtl._
object assert {
/** Checks for a condition to be valid in the circuit at all times. If the
@@ -43,13 +43,13 @@ object assert {
/** An elaboration-time assertion, otherwise the same as the above run-time
* assertion. */
def apply(cond: Boolean, message: String) {
- apply(Bool(cond), message)
+ Predef.assert(cond, message)
}
/** A workaround for default-value overloading problems in Scala, just
* 'assert(cond, "")' */
def apply(cond: Boolean) {
- apply(cond, "")
+ Predef.assert(cond, "")
}
}
diff --git a/src/main/scala/Chisel/Data.scala b/src/main/scala/Chisel/Data.scala
index f9b277e1..0ac3ee32 100644
--- a/src/main/scala/Chisel/Data.scala
+++ b/src/main/scala/Chisel/Data.scala
@@ -4,7 +4,7 @@ package Chisel
import internal._
import internal.Builder.pushCommand
-import firrtl._
+import internal.firrtl._
sealed abstract class Direction(name: String) {
override def toString: String = name
@@ -104,13 +104,22 @@ abstract class Data(dirArg: Direction) extends HasId {
}
object Wire {
- def apply[T <: Data](t: T = null, init: T = null): T = {
+ def apply[T <: Data](t: T): T =
+ makeWire(t, null.asInstanceOf[T])
+
+ def apply[T <: Data](dummy: Int = 0, init: T): T =
+ makeWire(null.asInstanceOf[T], init)
+
+ def apply[T <: Data](t: T, init: T): T =
+ makeWire(t, init)
+
+ private def makeWire[T <: Data](t: T, init: T): T = {
val x = Reg.makeType(t, null.asInstanceOf[T], init)
pushCommand(DefWire(x))
if (init != null) {
x := init
} else {
- x.flatten.foreach(e => e := e.fromInt(0))
+ pushCommand(DefInvalid(x.ref))
}
x
}
@@ -123,7 +132,7 @@ object Clock {
// TODO: Document this.
sealed class Clock(dirArg: Direction) extends Element(dirArg, Width(1)) {
def cloneType: this.type = Clock(dirArg).asInstanceOf[this.type]
- private[Chisel] override def flatten: IndexedSeq[UInt] = IndexedSeq()
+ private[Chisel] override def flatten: IndexedSeq[Bits] = IndexedSeq()
private[Chisel] def cloneTypeWidth(width: Width): this.type = cloneType
private[Chisel] def toType = "Clock"
@@ -132,11 +141,3 @@ sealed class Clock(dirArg: Direction) extends Element(dirArg, Width(1)) {
case _ => this badConnect that
}
}
-
-// TODO: check with FIRRTL specs, how much official implementation flexibility
-// is there?
-/** A source of garbage data, used to initialize Wires to a don't-care value. */
-private object Poison extends Command {
- def apply[T <: Data](t: T): T =
- pushCommand(DefPoison(t.cloneType)).id
-}
diff --git a/src/main/scala/Chisel/Driver.scala b/src/main/scala/Chisel/Driver.scala
index cd88c302..6a5e2095 100644
--- a/src/main/scala/Chisel/Driver.scala
+++ b/src/main/scala/Chisel/Driver.scala
@@ -6,7 +6,7 @@ import scala.sys.process._
import java.io._
import internal._
-import firrtl._
+import internal.firrtl._
trait BackendCompilationUtilities {
/** Create a temporary directory with the prefix name. Exists here because it doesn't in Java 6.
diff --git a/src/main/scala/Chisel/Main.scala b/src/main/scala/Chisel/Main.scala
new file mode 100644
index 00000000..23abc763
--- /dev/null
+++ b/src/main/scala/Chisel/Main.scala
@@ -0,0 +1,8 @@
+// See LICENSE for details
+
+package Chisel
+
+@deprecated("chiselMain doesn't exist in Chisel3", "3.0") object chiselMain {
+ def apply[T <: Module](args: Array[String], gen: () => T) =
+ Predef.assert(false)
+}
diff --git a/src/main/scala/Chisel/Mem.scala b/src/main/scala/Chisel/Mem.scala
index bd27a9c7..21284607 100644
--- a/src/main/scala/Chisel/Mem.scala
+++ b/src/main/scala/Chisel/Mem.scala
@@ -4,7 +4,7 @@ package Chisel
import internal._
import internal.Builder.pushCommand
-import firrtl._
+import internal.firrtl._
object Mem {
@deprecated("Mem argument order should be size, t; this will be removed by the official release", "chisel3")
@@ -18,7 +18,7 @@ object Mem {
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
+ pushCommand(DefMemory(mem, mt, size)) // TODO multi-clock
mem
}
}
@@ -31,20 +31,24 @@ sealed abstract class MemBase[T <: Data](t: T, val length: Int) extends HasId wi
*/
def apply(idx: Int): T = 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.
+ */
+ def apply(idx: UInt): T = makePort(idx, MemPortDirection.INFER)
+
/** 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)
+ def read(idx: UInt): T = makePort(idx, MemPortDirection.READ)
/** 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
+ def write(idx: UInt, data: T): Unit = {
+ makePort(idx, MemPortDirection.WRITE) := data
+ }
/** Creates a masked write accessor into the memory.
*
@@ -56,12 +60,18 @@ sealed abstract class MemBase[T <: Data](t: T, val length: Int) extends HasId wi
* @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]])
+ val accessor = makePort(idx, MemPortDirection.WRITE).asInstanceOf[Vec[Data]]
+ val dataVec = data.asInstanceOf[Vec[Data]]
+ if (accessor.length != dataVec.length)
+ Builder.error(s"Mem write data must contain ${accessor.length} elements (found ${dataVec.length})")
+ if (accessor.length != mask.length)
+ Builder.error(s"Mem write mask must contain ${accessor.length} elements (found ${mask.length})")
+ for (((cond, port), datum) <- mask zip accessor zip dataVec)
when (cond) { port := datum }
}
+
+ private def makePort(idx: UInt, dir: MemPortDirection): T =
+ pushCommand(DefMemPort(t.cloneType, Node(this), dir, idx.ref, Node(idx._parent.get.clock))).id
}
/** A combinational-read, sequential-write memory.
@@ -87,7 +97,7 @@ object SeqMem {
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
+ pushCommand(DefSeqMemory(mem, mt, size)) // TODO multi-clock
mem
}
}
@@ -103,6 +113,9 @@ object SeqMem {
* result is undefined (unlike Vec, where the last assignment wins)
*/
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)))
+ def read(addr: UInt, enable: Bool): T = {
+ val a = Wire(UInt())
+ when (enable) { a := addr }
+ read(a)
+ }
}
diff --git a/src/main/scala/Chisel/Module.scala b/src/main/scala/Chisel/Module.scala
index 05b7dc26..463c2f81 100644
--- a/src/main/scala/Chisel/Module.scala
+++ b/src/main/scala/Chisel/Module.scala
@@ -7,7 +7,7 @@ import scala.collection.mutable.{ArrayBuffer, HashSet}
import internal._
import internal.Builder.pushCommand
import internal.Builder.dynamicContext
-import firrtl._
+import internal.firrtl._
object Module {
/** A wrapper method that all Module instantiations must be wrapped in
@@ -20,16 +20,12 @@ object Module {
def apply[T <: Module](bc: => T): T = {
val parent = dynamicContext.currentModule
val m = bc.setRefs()
- // init module outputs
- m._commands prependAll (for (p <- m.io.flatten; if p.dir == OUTPUT)
- yield Connect(p.lref, p.fromInt(0).ref))
+ m._commands.prepend(DefInvalid(m.io.ref)) // init module outputs
dynamicContext.currentModule = parent
val ports = m.computePorts
Builder.components += Component(m, m.name, ports, m._commands)
pushCommand(DefInstance(m, ports))
- // init instance inputs
- for (p <- m.io.flatten; if p.dir == INPUT)
- p := p.fromInt(0)
+ pushCommand(DefInvalid(m.io.ref)) // init instance inputs
m.connectImplicitIOs()
}
}
@@ -60,7 +56,7 @@ abstract class Module(_clock: Clock = null, _reset: Bool = null) extends HasId {
private[Chisel] def ref = Builder.globalRefMap(this)
private[Chisel] def lref = ref
- private def ports = (clock, "clock") :: (reset, "reset") :: (io, "io") :: Nil
+ private def ports = (clock, "clk") :: (reset, "reset") :: (io, "io") :: Nil
private[Chisel] def computePorts = ports map { case (port, name) =>
val bundleDir = if (port.isFlip) INPUT else OUTPUT
diff --git a/src/main/scala/Chisel/Reg.scala b/src/main/scala/Chisel/Reg.scala
index 21415362..e69061c5 100644
--- a/src/main/scala/Chisel/Reg.scala
+++ b/src/main/scala/Chisel/Reg.scala
@@ -4,7 +4,7 @@ package Chisel
import internal._
import internal.Builder.pushCommand
-import firrtl._
+import internal.firrtl._
object Reg {
private[Chisel] def makeType[T <: Data](t: T = null, next: T = null, init: T = null): T = {
@@ -45,9 +45,11 @@ object Reg {
// to resolve all use cases. If the type inferencer / implicit resolution
// system improves, this may be changed.
val x = makeType(t, next, init)
- pushCommand(DefRegister(x, Node(x._parent.get.clock), Node(x._parent.get.reset))) // TODO multi-clock
- if (init != null) {
- pushCommand(ConnectInit(x.lref, init.ref))
+ val clock = Node(x._parent.get.clock) // TODO multi-clock
+ if (init == null) {
+ pushCommand(DefReg(x, clock))
+ } else {
+ pushCommand(DefRegInit(x, clock, Node(x._parent.get.reset), init.ref))
}
if (next != null) {
x := next
diff --git a/src/main/scala/Chisel/When.scala b/src/main/scala/Chisel/When.scala
index 7b8d60c2..5f6b02c5 100644
--- a/src/main/scala/Chisel/When.scala
+++ b/src/main/scala/Chisel/When.scala
@@ -4,7 +4,7 @@ package Chisel
import internal._
import internal.Builder.pushCommand
-import firrtl._
+import internal.firrtl._
object when { // scalastyle:ignore object.name
/** Create a `when` condition block, where whether a block of logic is
@@ -24,32 +24,33 @@ object when { // scalastyle:ignore object.name
* }
* }}}
*/
- def apply(cond: => Bool)(block: => Unit): WhenContext = {
- new WhenContext(cond)(block)
+ def apply(cond: Bool)(block: => Unit): WhenContext = {
+ new WhenContext(cond, !cond)(block)
}
}
-class WhenContext(cond: => Bool)(block: => Unit) {
+/** Internal mechanism for generating a when. Because of the way FIRRTL
+ * commands are emitted, generating a FIRRTL elsewhen or nested whens inside
+ * elses would be difficult. Instead, this keeps track of the negative of the
+ * previous conditions, so when an elsewhen or otherwise is used, it checks
+ * that both the condition is true and all the previous conditions have been
+ * false.
+ */
+class WhenContext(cond: Bool, prevCond: => Bool)(block: => Unit) {
/** This block of logic gets executed if above conditions have been false
* and this condition is true.
*/
- def elsewhen (cond: => Bool)(block: => Unit): WhenContext =
- doOtherwise(when(cond)(block))
+ def elsewhen (elseCond: Bool)(block: => Unit): WhenContext = {
+ new WhenContext(prevCond && elseCond, prevCond && !elseCond)(block)
+ }
/** This block of logic gets executed only if the above conditions were all
* false. No additional logic blocks may be appended past the `otherwise`.
*/
def otherwise(block: => Unit): Unit =
- doOtherwise(block)
+ new WhenContext(prevCond, null)(block)
pushCommand(WhenBegin(cond.ref))
block
pushCommand(WhenEnd())
-
- private def doOtherwise[T](block: => T): T = {
- pushCommand(WhenElse())
- val res = block
- pushCommand(WhenEnd())
- res
- }
}
diff --git a/src/main/scala/Chisel/internal/Builder.scala b/src/main/scala/Chisel/internal/Builder.scala
index 385e25a2..7e72b5e1 100644
--- a/src/main/scala/Chisel/internal/Builder.scala
+++ b/src/main/scala/Chisel/internal/Builder.scala
@@ -6,7 +6,7 @@ import scala.util.DynamicVariable
import scala.collection.mutable.{ArrayBuffer, HashMap}
import Chisel._
-import Chisel.firrtl._
+import Chisel.internal.firrtl._
private[Chisel] class Namespace(parent: Option[Namespace], keywords: Set[String]) {
private var i = 0L
@@ -50,7 +50,8 @@ private[Chisel] trait HasId {
private[Chisel] def setRef(imm: Arg) = _refMap.setRef(this, imm)
private[Chisel] def setRef(name: String) = _refMap.setRef(this, name)
private[Chisel] def setRef(parent: HasId, name: String) = _refMap.setField(parent, this, name)
- private[Chisel] def setRef(parent: HasId, index: Int) = _refMap.setIndex(parent, this, index)
+ private[Chisel] def setRef(parent: HasId, index: Int) = _refMap.setIndex(parent, this, ILit(index))
+ private[Chisel] def setRef(parent: HasId, index: UInt) = _refMap.setIndex(parent, this, index.ref)
private[Chisel] def getRef = _refMap(this)
}
@@ -66,7 +67,7 @@ class RefMap {
private[Chisel] def setField(parentid: HasId, id: HasId, name: String): Unit =
_refmap(id._id) = Slot(Node(parentid), name)
- private[Chisel] def setIndex(parentid: HasId, id: HasId, index: Int): Unit =
+ private[Chisel] def setIndex(parentid: HasId, id: HasId, index: Arg): Unit =
_refmap(id._id) = Index(Node(parentid), index)
def apply(id: HasId): Arg = _refmap(id._id)
diff --git a/src/main/scala/Chisel/firrtl/Emitter.scala b/src/main/scala/Chisel/internal/firrtl/Emitter.scala
index 1d0f4ddc..13d9fa8f 100644
--- a/src/main/scala/Chisel/firrtl/Emitter.scala
+++ b/src/main/scala/Chisel/internal/firrtl/Emitter.scala
@@ -1,6 +1,6 @@
// See LICENSE for license details.
-package Chisel.firrtl
+package Chisel.internal.firrtl
import Chisel._
private class Emitter(circuit: Circuit) {
@@ -11,16 +11,16 @@ private class Emitter(circuit: Circuit) {
private def emit(e: Command, ctx: Component): String = e match {
case e: DefPrim[_] => s"node ${e.name} = ${e.op.name}(${e.args.map(_.fullName(ctx)).reduce(_ + ", " + _)})"
case e: DefWire => s"wire ${e.name} : ${e.id.toType}"
- case e: DefPoison[_] => s"poison ${e.name} : ${e.id.toType}"
- case e: DefRegister => s"reg ${e.name} : ${e.id.toType}, ${e.clock.fullName(ctx)}, ${e.reset.fullName(ctx)}"
- case e: DefMemory => s"cmem ${e.name} : ${e.t.toType}[${e.size}], ${e.clock.fullName(ctx)}"
- case e: DefSeqMemory => s"smem ${e.name} : ${e.t.toType}[${e.size}], ${e.clock.fullName(ctx)}"
- case e: DefAccessor[_] => s"infer accessor ${e.name} = ${e.source.fullName(ctx)}[${e.index.fullName(ctx)}]"
- case e: Connect => s"${e.loc.fullName(ctx)} := ${e.exp.fullName(ctx)}"
- case e: BulkConnect => s"${e.loc1.fullName(ctx)} <> ${e.loc2.fullName(ctx)}"
- case e: ConnectInit => s"onreset ${e.loc.fullName(ctx)} := ${e.exp.fullName(ctx)}"
- case e: Stop => s"stop(${e.clk.fullName(ctx)}, ${e.ret})"
- case e: Printf => s"""printf(${e.clk.fullName(ctx)}, "${e.format}"${e.ids.map(_.fullName(ctx)).fold(""){_ + ", " + _}})"""
+ case e: DefReg => s"reg ${e.name} : ${e.id.toType}, ${e.clock.fullName(ctx)}"
+ case e: DefRegInit => s"reg ${e.name} : ${e.id.toType}, ${e.clock.fullName(ctx)} with : (reset => (${e.reset.fullName(ctx)}, ${e.init.fullName(ctx)}))"
+ case e: DefMemory => s"cmem ${e.name} : ${e.t.toType}[${e.size}]"
+ case e: DefSeqMemory => s"smem ${e.name} : ${e.t.toType}[${e.size}]"
+ case e: DefMemPort[_] => s"${e.dir} mport ${e.name} = ${e.source.fullName(ctx)}[${e.index.fullName(ctx)}], ${e.clock.fullName(ctx)}"
+ case e: Connect => s"${e.loc.fullName(ctx)} <= ${e.exp.fullName(ctx)}"
+ case e: BulkConnect => s"${e.loc1.fullName(ctx)} <- ${e.loc2.fullName(ctx)}"
+ case e: Stop => s"stop(${e.clk.fullName(ctx)}, UInt<1>(1), ${e.ret})"
+ case e: Printf => s"""printf(${e.clk.fullName(ctx)}, UInt<1>(1), "${e.format}"${e.ids.map(_.fullName(ctx)).fold(""){_ + ", " + _}})"""
+ case e: DefInvalid => s"${e.arg.fullName(ctx)} is invalid"
case e: DefInstance => {
val modName = moduleMap.getOrElse(e.id.name, e.id.name)
s"inst ${e.name} of $modName"
@@ -29,9 +29,6 @@ private class Emitter(circuit: Circuit) {
case w: WhenBegin =>
indent()
s"when ${w.pred.fullName(ctx)} :"
- case _: WhenElse =>
- indent()
- "else :"
case _: WhenEnd =>
unindent()
"skip"
diff --git a/src/main/scala/Chisel/firrtl/IR.scala b/src/main/scala/Chisel/internal/firrtl/IR.scala
index 8cc31b54..7bb273c0 100644
--- a/src/main/scala/Chisel/firrtl/IR.scala
+++ b/src/main/scala/Chisel/internal/firrtl/IR.scala
@@ -1,6 +1,6 @@
// See LICENSE for license details.
-package Chisel.firrtl
+package Chisel.internal.firrtl
import Chisel._
import Chisel.internal._
@@ -10,12 +10,12 @@ case class PrimOp(val name: String) {
object PrimOp {
val AddOp = PrimOp("add")
- val AddModOp = PrimOp("addw")
val SubOp = PrimOp("sub")
- val SubModOp = PrimOp("subw")
+ val TailOp = PrimOp("tail")
+ val HeadOp = PrimOp("head")
val TimesOp = PrimOp("mul")
val DivideOp = PrimOp("div")
- val ModOp = PrimOp("mod")
+ val RemOp = PrimOp("rem")
val ShiftLeftOp = PrimOp("shl")
val ShiftRightOp = PrimOp("shr")
val DynamicShiftLeftOp = PrimOp("dshl")
@@ -25,7 +25,6 @@ object PrimOp {
val BitXorOp = PrimOp("xor")
val BitNotOp = PrimOp("not")
val ConcatOp = PrimOp("cat")
- val BitSelectOp = PrimOp("bit")
val BitsExtractOp = PrimOp("bits")
val LessOp = PrimOp("lt")
val LessEqOp = PrimOp("leq")
@@ -90,9 +89,9 @@ case class Slot(imm: Node, name: String) extends Arg {
override def fullName(ctx: Component): String =
if (imm.fullName(ctx).isEmpty) name else s"${imm.fullName(ctx)}.${name}"
}
-case class Index(imm: Arg, value: Int) extends Arg {
+case class Index(imm: Arg, value: Arg) extends Arg {
def name: String = s"[$value]"
- override def fullName(ctx: Component): String = s"${imm.fullName(ctx)}[$value]"
+ override def fullName(ctx: Component): String = s"${imm.fullName(ctx)}[${value.fullName(ctx)}]"
}
object Width {
@@ -132,21 +131,31 @@ sealed case class KnownWidth(value: Int) extends Width {
override def toString: String = value.toString
}
+sealed abstract class MemPortDirection(name: String) {
+ override def toString: String = name
+}
+object MemPortDirection {
+ object READ extends MemPortDirection("read")
+ object WRITE extends MemPortDirection("write")
+ object RDWR extends MemPortDirection("rdwr")
+ object INFER extends MemPortDirection("infer")
+}
+
abstract class Command
abstract class Definition extends Command {
def id: HasId
def name: String = id.getRef.name
}
case class DefPrim[T <: Data](id: T, op: PrimOp, args: Arg*) extends Definition
+case class DefInvalid(arg: Arg) extends Command
case class DefWire(id: Data) extends Definition
-case class DefRegister(id: Data, clock: Arg, reset: Arg) extends Definition
-case class DefMemory(id: HasId, t: Data, size: Int, clock: Arg) extends Definition
-case class DefSeqMemory(id: HasId, t: Data, size: Int, clock: Arg) extends Definition
-case class DefAccessor[T <: Data](id: T, source: Node, direction: Direction, index: Arg) extends Definition
+case class DefReg(id: Data, clock: Arg) extends Definition
+case class DefRegInit(id: Data, clock: Arg, reset: Arg, init: Arg) extends Definition
+case class DefMemory(id: HasId, t: Data, size: Int) extends Definition
+case class DefSeqMemory(id: HasId, t: Data, size: Int) extends Definition
+case class DefMemPort[T <: Data](id: T, source: Node, dir: MemPortDirection, index: Arg, clock: Arg) extends Definition
case class DefInstance(id: Module, ports: Seq[Port]) extends Definition
-case class DefPoison[T <: Data](id: T) extends Definition
case class WhenBegin(pred: Arg) extends Command
-case class WhenElse() extends Command
case class WhenEnd() extends Command
case class Connect(loc: Node, exp: Arg) extends Command
case class BulkConnect(loc1: Node, loc2: Node) extends Command
diff --git a/src/main/scala/Chisel/testers/BasicTester.scala b/src/main/scala/Chisel/testers/BasicTester.scala
index 1079727c..6807a30e 100644
--- a/src/main/scala/Chisel/testers/BasicTester.scala
+++ b/src/main/scala/Chisel/testers/BasicTester.scala
@@ -5,7 +5,7 @@ import Chisel._
import internal._
import internal.Builder.pushCommand
-import firrtl._
+import internal.firrtl._
class BasicTester extends Module {
// The testbench has no IOs, rather it should communicate using printf, assert, and stop.
diff --git a/src/main/scala/Chisel/util/Arbiter.scala b/src/main/scala/Chisel/util/Arbiter.scala
index 119b9f5a..2747640f 100644
--- a/src/main/scala/Chisel/util/Arbiter.scala
+++ b/src/main/scala/Chisel/util/Arbiter.scala
@@ -7,7 +7,7 @@ package Chisel
/** An I/O bundle for the Arbiter */
class ArbiterIO[T <: Data](gen: T, n: Int) extends Bundle {
- val in = Vec(Decoupled(gen), n).flip
+ val in = Vec(n, Decoupled(gen)).flip
val out = Decoupled(gen)
val chosen = UInt(OUTPUT, log2Up(n))
}
diff --git a/src/main/scala/Chisel/util/Decoupled.scala b/src/main/scala/Chisel/util/Decoupled.scala
index b1505887..ca000af9 100644
--- a/src/main/scala/Chisel/util/Decoupled.scala
+++ b/src/main/scala/Chisel/util/Decoupled.scala
@@ -82,7 +82,7 @@ class Queue[T <: Data](gen: T, val entries: Int,
{
val io = new QueueIO(gen, entries)
- val ram = Mem(gen, entries)
+ val ram = Mem(entries, gen)
val enq_ptr = Counter(entries)
val deq_ptr = Counter(entries)
val maybe_full = Reg(init=Bool(false))
diff --git a/src/test/scala/chiselTests/When.scala b/src/test/scala/chiselTests/When.scala
new file mode 100644
index 00000000..b78e1c5a
--- /dev/null
+++ b/src/test/scala/chiselTests/When.scala
@@ -0,0 +1,60 @@
+// See LICENSE for license details.
+
+package chiselTests
+
+import org.scalatest._
+import Chisel._
+import Chisel.testers.BasicTester
+
+class WhenTester() extends BasicTester {
+ val cnt = Counter(4)
+ when(Bool(true)) { cnt.inc() }
+
+ val out = Wire(UInt(width=3))
+ when(cnt.value === UInt(0)) {
+ out := UInt(1)
+ } .elsewhen (cnt.value === UInt(1)) {
+ out := UInt(2)
+ } .elsewhen (cnt.value === UInt(2)) {
+ out := UInt(3)
+ } .otherwise {
+ out := UInt(0)
+ }
+
+ assert(out === cnt.value + UInt(1))
+
+ when(cnt.value === UInt(3)) {
+ stop()
+ }
+}
+
+class OverlappedWhenTester() extends BasicTester {
+ val cnt = Counter(4)
+ when(Bool(true)) { cnt.inc() }
+
+ val out = Wire(UInt(width=3))
+ when(cnt.value <= UInt(0)) {
+ out := UInt(1)
+ } .elsewhen (cnt.value <= UInt(1)) {
+ out := UInt(2)
+ } .elsewhen (cnt.value <= UInt(2)) {
+ out := UInt(3)
+ } .otherwise {
+ out := UInt(0)
+ }
+
+ assert(out === cnt.value + UInt(1))
+
+ when(cnt.value === UInt(3)) {
+ stop()
+ }
+}
+
+class WhenSpec extends ChiselFlatSpec {
+ "When, elsewhen, and otherwise with orthogonal conditions" should "work" in {
+ assert(execute{ new WhenTester })
+ }
+ "When, elsewhen, and otherwise with overlapped conditions" should "work" in {
+ assert(execute{ new OverlappedWhenTester })
+ }
+}