summaryrefslogtreecommitdiff
path: root/chiselFrontend/src/main/scala/chisel3
diff options
context:
space:
mode:
authorJim Lawson2016-06-20 11:08:46 -0700
committerJim Lawson2016-06-20 11:08:46 -0700
commitd408d73a171535bd7c2ba9d0037c194022b8a62f (patch)
tree81885a99ec56e89532bc3fa338f22b163dcc4d1f /chiselFrontend/src/main/scala/chisel3
parentb5a534914795d9d17f4dfe623525f1b804e4c60f (diff)
Rename chisel3 package.
Diffstat (limited to 'chiselFrontend/src/main/scala/chisel3')
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala377
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Assert.scala73
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Bits.scala756
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala55
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Data.scala156
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Mem.scala134
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Module.scala119
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Printf.scala36
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Reg.scala71
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala59
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/When.scala59
-rw-r--r--chiselFrontend/src/main/scala/chisel3/internal/Builder.scala129
-rw-r--r--chiselFrontend/src/main/scala/chisel3/internal/Error.scala91
-rw-r--r--chiselFrontend/src/main/scala/chisel3/internal/SourceInfo.scala51
-rw-r--r--chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala190
15 files changed, 2356 insertions, 0 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala
new file mode 100644
index 00000000..38a42fea
--- /dev/null
+++ b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala
@@ -0,0 +1,377 @@
+// See LICENSE for license details.
+
+package chisel.core
+
+import scala.collection.immutable.ListMap
+import scala.collection.mutable.{ArrayBuffer, HashSet, LinkedHashMap}
+import scala.language.experimental.macros
+
+import chisel.internal._
+import chisel.internal.Builder.pushCommand
+import chisel.internal.firrtl._
+import chisel.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, VecTransform, SourceInfoTransform}
+
+/** An abstract class for data types that solely consist of (are an aggregate
+ * of) other Data objects.
+ */
+sealed abstract class Aggregate(dirArg: Direction) extends Data(dirArg) {
+ private[core] def cloneTypeWidth(width: Width): this.type = cloneType
+ def width: Width = flatten.map(_.width).reduce(_ + _)
+}
+
+object Vec {
+ /** Creates a new [[Vec]] with `n` entries of the specified data type.
+ *
+ * @note elements are NOT assigned by default and have no value
+ */
+ def apply[T <: Data](n: Int, gen: T): Vec[T] = new Vec(gen.cloneType, n)
+
+ @deprecated("Vec argument order should be size, t; this will be removed by the official release", "chisel3")
+ def apply[T <: Data](gen: T, n: Int): Vec[T] = new Vec(gen.cloneType, n)
+
+ /** Creates a new [[Vec]] composed of elements of the input Seq of [[Data]]
+ * nodes.
+ *
+ * @note input elements should be of the same type (this is checked at the
+ * FIRRTL level, but not at the Scala / Chisel level)
+ * @note the width of all output elements is the width of the largest input
+ * element
+ * @note output elements are connected from the input elements
+ */
+ def apply[T <: Data](elts: Seq[T]): Vec[T] = macro VecTransform.apply_elts
+
+ def do_apply[T <: Data](elts: Seq[T])(implicit sourceInfo: SourceInfo): Vec[T] = {
+ // REVIEW TODO: this should be removed in favor of the apply(elts: T*)
+ // varargs constructor, which is more in line with the style of the Scala
+ // collection API. However, a deprecation phase isn't possible, since
+ // changing apply(elt0, elts*) to apply(elts*) causes a function collision
+ // with apply(Seq) after type erasure. Workarounds by either introducing a
+ // DummyImplicit or additional type parameter will break some code.
+ require(!elts.isEmpty)
+ val width = elts.map(_.width).reduce(_ max _)
+ val vec = Wire(new Vec(elts.head.cloneTypeWidth(width), elts.length))
+ for ((v, e) <- vec zip elts)
+ v := e
+ vec
+ }
+
+ /** Creates a new [[Vec]] composed of the input [[Data]] nodes.
+ *
+ * @note input elements should be of the same type (this is checked at the
+ * FIRRTL level, but not at the Scala / Chisel level)
+ * @note the width of all output elements is the width of the largest input
+ * element
+ * @note output elements are connected from the input elements
+ */
+ def apply[T <: Data](elt0: T, elts: T*): Vec[T] = macro VecTransform.apply_elt0
+
+ def do_apply[T <: Data](elt0: T, elts: T*)(implicit sourceInfo: SourceInfo): Vec[T] =
+ apply(elt0 +: elts.toSeq)
+
+ /** Creates a new [[Vec]] of length `n` composed of the results of the given
+ * function applied over a range of integer values starting from 0.
+ *
+ * @param n number of elements in the vector (the function is applied from
+ * 0 to `n-1`)
+ * @param gen function that takes in an Int (the index) and returns a
+ * [[Data]] that becomes the output element
+ */
+ def tabulate[T <: Data](n: Int)(gen: (Int) => T): Vec[T] = macro VecTransform.tabulate
+
+ def do_tabulate[T <: Data](n: Int)(gen: (Int) => T)(implicit sourceInfo: SourceInfo): Vec[T] =
+ apply((0 until n).map(i => gen(i)))
+
+ /** Creates a new [[Vec]] of length `n` composed of the result of the given
+ * function repeatedly applied.
+ *
+ * @param n number of elements (amd the number of times the function is
+ * called)
+ * @param gen function that generates the [[Data]] that becomes the output
+ * element
+ */
+ def fill[T <: Data](n: Int)(gen: => T): Vec[T] = macro VecTransform.fill
+
+ def do_fill[T <: Data](n: Int)(gen: => T)(implicit sourceInfo: SourceInfo): Vec[T] =
+ apply(Seq.fill(n)(gen))
+}
+
+/** A vector (array) of [[Data]] elements. Provides hardware versions of various
+ * collection transformation functions found in software array implementations.
+ *
+ * @tparam T type of elements
+ * @note when multiple conflicting assignments are performed on a Vec element,
+ * the last one takes effect (unlike Mem, where the result is undefined)
+ * @note Vecs, unlike classes in Scala's collection library, are propagated
+ * intact to FIRRTL as a vector type, which may make debugging easier
+ */
+sealed class Vec[T <: Data] private (gen: => T, val length: Int)
+ extends Aggregate(gen.dir) with VecLike[T] {
+ // Note: the constructor takes a gen() function instead of a Seq to enforce
+ // that all elements must be the same and because it makes FIRRTL generation
+ // simpler.
+
+ private val self = IndexedSeq.fill(length)(gen)
+
+ override def <> (that: Data)(implicit sourceInfo: SourceInfo): Unit = this := that
+
+ /** Strong bulk connect, assigning elements in this Vec from elements in a Seq.
+ *
+ * @note the length of this Vec must match the length of the input Seq
+ */
+ def <> (that: Seq[T])(implicit sourceInfo: SourceInfo): Unit = this := that
+
+ // TODO: eliminate once assign(Seq) isn't ambiguous with assign(Data) since Vec extends Seq and Data
+ def <> (that: Vec[T])(implicit sourceInfo: SourceInfo): Unit = this := that.asInstanceOf[Data]
+
+ override def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = that match {
+ case _: Vec[_] => this connect that
+ case _ => this badConnect that
+ }
+
+ /** Strong bulk connect, assigning elements in this Vec from elements in a Seq.
+ *
+ * @note the length of this Vec must match the length of the input Seq
+ */
+ def := (that: Seq[T])(implicit sourceInfo: SourceInfo): Unit = {
+ require(this.length == that.length)
+ for ((a, b) <- this zip that)
+ a := b
+ }
+
+ // TODO: eliminate once assign(Seq) isn't ambiguous with assign(Data) since Vec extends Seq and Data
+ def := (that: Vec[T])(implicit sourceInfo: SourceInfo): Unit = this connect that
+
+ /** Creates a dynamically indexed read or write accessor into the array.
+ */
+ def apply(idx: UInt): T = {
+ val x = gen
+ x.setRef(this, idx)
+ x
+ }
+
+ /** Creates a statically indexed read or write accessor into the array.
+ */
+ def apply(idx: Int): T = self(idx)
+
+ @deprecated("Use Vec.apply instead", "chisel3")
+ def read(idx: UInt): T = apply(idx)
+
+ @deprecated("Use Vec.apply instead", "chisel3")
+ def write(idx: UInt, data: T): Unit = apply(idx).:=(data)(DeprecatedSourceInfo)
+
+ override def cloneType: this.type =
+ Vec(length, gen).asInstanceOf[this.type]
+
+ private val t = gen
+ private[chisel] def toType: String = s"${t.toType}[$length]"
+ private[chisel] lazy val flatten: IndexedSeq[Bits] =
+ (0 until length).flatMap(i => this.apply(i).flatten)
+
+ for ((elt, i) <- self zipWithIndex)
+ elt.setRef(this, i)
+}
+
+/** A trait for [[Vec]]s containing common hardware generators for collection
+ * operations.
+ */
+trait VecLike[T <: Data] extends collection.IndexedSeq[T] with HasId {
+ def apply(idx: UInt): T
+
+ // IndexedSeq has its own hashCode/equals that we must not use
+ override def hashCode: Int = super[HasId].hashCode
+ override def equals(that: Any): Boolean = super[HasId].equals(that)
+
+ @deprecated("Use Vec.apply instead", "chisel3")
+ def read(idx: UInt): T
+
+ @deprecated("Use Vec.apply instead", "chisel3")
+ def write(idx: UInt, data: T): Unit
+
+ /** Outputs true if p outputs true for every element.
+ */
+ def forall(p: T => Bool): Bool = macro SourceInfoTransform.pArg
+
+ def do_forall(p: T => Bool)(implicit sourceInfo: SourceInfo): Bool =
+ (this map p).fold(Bool(true))(_ && _)
+
+ /** Outputs true if p outputs true for at least one element.
+ */
+ def exists(p: T => Bool): Bool = macro SourceInfoTransform.pArg
+
+ def do_exists(p: T => Bool)(implicit sourceInfo: SourceInfo): Bool =
+ (this map p).fold(Bool(false))(_ || _)
+
+ /** Outputs true if the vector contains at least one element equal to x (using
+ * the === operator).
+ */
+ def contains(x: T)(implicit ev: T <:< UInt): Bool = macro VecTransform.contains
+
+ def do_contains(x: T)(implicit sourceInfo: SourceInfo, ev: T <:< UInt): Bool =
+ this.exists(_ === x)
+
+ /** Outputs the number of elements for which p is true.
+ */
+ def count(p: T => Bool): UInt = macro SourceInfoTransform.pArg
+
+ def do_count(p: T => Bool)(implicit sourceInfo: SourceInfo): UInt =
+ SeqUtils.count(this map p)
+
+ /** Helper function that appends an index (literal value) to each element,
+ * useful for hardware generators which output an index.
+ */
+ private def indexWhereHelper(p: T => Bool) = this map p zip (0 until length).map(i => UInt(i))
+
+ /** Outputs the index of the first element for which p outputs true.
+ */
+ def indexWhere(p: T => Bool): UInt = macro SourceInfoTransform.pArg
+
+ def do_indexWhere(p: T => Bool)(implicit sourceInfo: SourceInfo): UInt =
+ SeqUtils.priorityMux(indexWhereHelper(p))
+
+ /** Outputs the index of the last element for which p outputs true.
+ */
+ def lastIndexWhere(p: T => Bool): UInt = macro SourceInfoTransform.pArg
+
+ def do_lastIndexWhere(p: T => Bool)(implicit sourceInfo: SourceInfo): UInt =
+ SeqUtils.priorityMux(indexWhereHelper(p).reverse)
+
+ /** Outputs the index of the element for which p outputs true, assuming that
+ * the there is exactly one such element.
+ *
+ * The implementation may be more efficient than a priority mux, but
+ * incorrect results are possible if there is not exactly one true element.
+ *
+ * @note the assumption that there is only one element for which p outputs
+ * true is NOT checked (useful in cases where the condition doesn't always
+ * hold, but the results are not used in those cases)
+ */
+ def onlyIndexWhere(p: T => Bool): UInt = macro SourceInfoTransform.pArg
+
+ def do_onlyIndexWhere(p: T => Bool)(implicit sourceInfo: SourceInfo): UInt =
+ SeqUtils.oneHotMux(indexWhereHelper(p))
+}
+
+/** Base class for data types defined as a bundle of other data types.
+ *
+ * Usage: extend this class (either as an anonymous or named class) and define
+ * members variables of [[Data]] subtypes to be elements in the Bundle.
+ */
+class Bundle extends Aggregate(NO_DIR) {
+ private val _namespace = Builder.globalNamespace.child
+
+ // TODO: replace with better defined FIRRTL weak-connect operator
+ /** Connect elements in this Bundle to elements in `that` on a best-effort
+ * (weak) basis, matching by type, orientation, and name.
+ *
+ * @note unconnected elements will NOT generate errors or warnings
+ *
+ * @example
+ * {{{
+ * // Pass through wires in this module's io to those mySubModule's io,
+ * // matching by type, orientation, and name, and ignoring extra wires.
+ * mySubModule.io <> io
+ * }}}
+ */
+ override def <> (that: Data)(implicit sourceInfo: SourceInfo): Unit = that match {
+ case _: Bundle => this bulkConnect that
+ case _ => this badConnect that
+ }
+
+ // TODO: replace with better defined FIRRTL strong-connect operator
+ override def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = this <> that
+
+ lazy val elements: ListMap[String, Data] = ListMap(namedElts:_*)
+
+ /** Returns a best guess at whether a field in this Bundle is a user-defined
+ * Bundle element without looking at type signatures.
+ */
+ private def isBundleField(m: java.lang.reflect.Method) =
+ m.getParameterTypes.isEmpty &&
+ !java.lang.reflect.Modifier.isStatic(m.getModifiers) &&
+ !(Bundle.keywords contains m.getName) && !(m.getName contains '$')
+
+ /** Returns a field's contained user-defined Bundle element if it appears to
+ * be one, otherwise returns None.
+ */
+ private def getBundleField(m: java.lang.reflect.Method): Option[Data] = {
+ if (isBundleField(m) &&
+ (classOf[Data].isAssignableFrom(m.getReturnType) ||
+ classOf[Option[_]].isAssignableFrom(m.getReturnType))) {
+ m.invoke(this) match {
+ case d: Data =>
+ Some(d)
+ case o: Option[_] =>
+ o.getOrElse(None) match {
+ case d: Data =>
+ Some(d)
+ case _ => None
+ }
+ case _ => None
+ }
+ } else {
+ None
+ }
+ }
+
+ /** Returns a list of elements in this Bundle.
+ */
+ private[core] lazy val namedElts = {
+ val nameMap = LinkedHashMap[String, Data]()
+ val seen = HashSet[Data]()
+ for (m <- getClass.getMethods.sortWith(_.getName < _.getName)) {
+ getBundleField(m) match {
+ case Some(d) =>
+ if (nameMap contains m.getName) {
+ require(nameMap(m.getName) eq d)
+ } else if (!seen(d)) {
+ nameMap(m.getName) = d; seen += d
+ }
+ case None =>
+ }
+ }
+ ArrayBuffer(nameMap.toSeq:_*) sortWith {case ((an, a), (bn, b)) => (a._id > b._id) || ((a eq b) && (an > bn))}
+ }
+ private[chisel] def toType = {
+ def eltPort(elt: Data): String = {
+ val flipStr = if (elt.isFlip) "flip " else ""
+ s"${flipStr}${elt.getRef.name} : ${elt.toType}"
+ }
+ s"{${namedElts.reverse.map(e => eltPort(e._2)).mkString(", ")}}"
+ }
+ private[chisel] lazy val flatten = namedElts.flatMap(_._2.flatten)
+ private[core] def addElt(name: String, elt: Data): Unit =
+ namedElts += name -> elt
+ private[chisel] override def _onModuleClose: Unit = // scalastyle:ignore method.name
+ for ((name, elt) <- namedElts) { elt.setRef(this, _namespace.name(name)) }
+
+ override def cloneType : this.type = {
+ // If the user did not provide a cloneType method, try invoking one of
+ // the following constructors, not all of which necessarily exist:
+ // - A zero-parameter constructor
+ // - A one-paramater constructor, with null as the argument
+ // - A one-parameter constructor for a nested Bundle, with the enclosing
+ // parent Module as the argument
+ val constructor = this.getClass.getConstructors.head
+ try {
+ val args = Seq.fill(constructor.getParameterTypes.size)(null)
+ constructor.newInstance(args:_*).asInstanceOf[this.type]
+ } catch {
+ case e: java.lang.reflect.InvocationTargetException if e.getCause.isInstanceOf[java.lang.NullPointerException] =>
+ try {
+ constructor.newInstance(_parent.get).asInstanceOf[this.type]
+ } catch {
+ 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
+ }
+ case _: java.lang.reflect.InvocationTargetException | _: java.lang.IllegalArgumentException =>
+ Builder.error(s"Parameterized Bundle ${this.getClass} needs cloneType method")
+ this
+ }
+ }
+}
+
+private[core] object Bundle {
+ val keywords = List("flip", "asInput", "asOutput", "cloneType", "toBits")
+}
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Assert.scala b/chiselFrontend/src/main/scala/chisel3/core/Assert.scala
new file mode 100644
index 00000000..00cb00f4
--- /dev/null
+++ b/chiselFrontend/src/main/scala/chisel3/core/Assert.scala
@@ -0,0 +1,73 @@
+// See LICENSE for license details.
+
+package chisel.core
+
+import scala.reflect.macros.blackbox.Context
+import scala.language.experimental.macros
+
+import chisel.internal._
+import chisel.internal.Builder.pushCommand
+import chisel.internal.firrtl._
+import chisel.internal.sourceinfo.SourceInfo
+
+object assert { // scalastyle:ignore object.name
+ /** Checks for a condition to be valid in the circuit at all times. If the
+ * condition evaluates to false, the circuit simulation stops with an error.
+ *
+ * Does not fire when in reset (defined as the encapsulating Module's
+ * reset). If your definition of reset is not the encapsulating Module's
+ * reset, you will need to gate this externally.
+ *
+ * May be called outside of a Module (like defined in a function), so
+ * functions using assert make the standard Module assumptions (single clock
+ * and single reset).
+ *
+ * @param cond condition, assertion fires (simulation fails) when false
+ * @param message optional message to print when the assertion fires
+ *
+ * @note currently cannot be used in core Chisel / libraries because macro
+ * defs need to be compiled first and the SBT project is not set up to do
+ * that
+ */
+ // Macros currently can't take default arguments, so we need two functions to emulate defaults.
+ def apply(cond: Bool, message: String)(implicit sourceInfo: SourceInfo): Unit = macro apply_impl_msg
+ def apply(cond: Bool)(implicit sourceInfo: SourceInfo): Unit = macro apply_impl
+
+ def apply_impl_msg(c: Context)(cond: c.Tree, message: c.Tree)(sourceInfo: c.Tree): c.Tree = {
+ import c.universe._
+ val p = c.enclosingPosition
+ val condStr = s"${p.source.file.name}:${p.line} ${p.lineContent.trim}"
+ val apply_impl_do = symbolOf[this.type].asClass.module.info.member(TermName("apply_impl_do"))
+ q"$apply_impl_do($cond, $condStr, _root_.scala.Some($message))($sourceInfo)"
+ }
+
+ def apply_impl(c: Context)(cond: c.Tree)(sourceInfo: c.Tree): c.Tree = {
+ import c.universe._
+ val p = c.enclosingPosition
+ val condStr = s"${p.source.file.name}:${p.line} ${p.lineContent.trim}"
+ val apply_impl_do = symbolOf[this.type].asClass.module.info.member(TermName("apply_impl_do"))
+ q"$apply_impl_do($cond, $condStr, _root_.scala.None)($sourceInfo)"
+ }
+
+ def apply_impl_do(cond: Bool, line: String, message: Option[String])(implicit sourceInfo: SourceInfo) {
+ when (!(cond || Builder.dynamicContext.currentModule.get.reset)) {
+ message match {
+ case Some(str) => printf.printfWithoutReset(s"Assertion failed: $str\n at $line\n")
+ case None => printf.printfWithoutReset(s"Assertion failed\n at $line\n")
+ }
+ pushCommand(Stop(sourceInfo, Node(Builder.dynamicContext.currentModule.get.clock), 1))
+ }
+ }
+
+ /** An elaboration-time assertion, otherwise the same as the above run-time
+ * assertion. */
+ def apply(cond: Boolean, message: => String) {
+ Predef.assert(cond, message)
+ }
+
+ /** A workaround for default-value overloading problems in Scala, just
+ * 'assert(cond, "")' */
+ def apply(cond: Boolean) {
+ Predef.assert(cond, "")
+ }
+}
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala
new file mode 100644
index 00000000..38e71f8d
--- /dev/null
+++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala
@@ -0,0 +1,756 @@
+// See LICENSE for license details.
+
+package chisel.core
+
+import scala.language.experimental.macros
+
+import chisel.internal._
+import chisel.internal.Builder.pushOp
+import chisel.internal.firrtl._
+import chisel.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, SourceInfoTransform, SourceInfoWhiteboxTransform,
+ UIntTransform, MuxTransform}
+import chisel.internal.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)
+
+/** A data type for values represented by a single bitvector. Provides basic
+ * bitwise operations.
+ */
+sealed abstract class Bits(dirArg: Direction, width: Width, override val litArg: Option[LitArg])
+ extends Element(dirArg, width) {
+ // TODO: perhaps make this concrete?
+ // Arguments for: self-checking code (can't do arithmetic on bits)
+ // Arguments against: generates down to a FIRRTL UInt anyways
+
+ private[chisel] def fromInt(x: BigInt, w: Int): this.type
+
+ private[chisel] def flatten: IndexedSeq[Bits] = IndexedSeq(this)
+
+ def cloneType: this.type = cloneTypeWidth(width)
+
+ override def <> (that: Data)(implicit sourceInfo: SourceInfo): Unit = this := that
+
+ final def tail(n: Int): UInt = macro SourceInfoTransform.nArg
+ final def head(n: Int): UInt = macro SourceInfoTransform.nArg
+
+ def do_tail(n: Int)(implicit sourceInfo: SourceInfo): 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(sourceInfo, UInt(width = w), TailOp, n)
+ }
+
+
+ def do_head(n: Int)(implicit sourceInfo: SourceInfo): UInt = {
+ width match {
+ case KnownWidth(x) => require(x >= n, s"Can't head($n) for width $x < $n")
+ case UnknownWidth() =>
+ }
+ binop(sourceInfo, UInt(width = n), HeadOp, n)
+ }
+
+ /** Returns the specified bit on this wire as a [[Bool]], statically
+ * addressed.
+ */
+ final def apply(x: BigInt): Bool = macro SourceInfoTransform.xArg
+
+ final def do_apply(x: BigInt)(implicit sourceInfo: SourceInfo): Bool = {
+ if (x < 0) {
+ Builder.error(s"Negative bit indices are illegal (got $x)")
+ }
+ if (isLit()) {
+ Bool(((litValue() >> x.toInt) & 1) == 1)
+ } else {
+ pushOp(DefPrim(sourceInfo, Bool(), BitsExtractOp, this.ref, ILit(x), ILit(x)))
+ }
+ }
+
+ /** Returns the specified bit on this wire as a [[Bool]], statically
+ * addressed.
+ *
+ * @note convenience method allowing direct use of Ints without implicits
+ */
+ final def apply(x: Int): Bool = macro SourceInfoTransform.xArg
+
+ final def do_apply(x: Int)(implicit sourceInfo: SourceInfo): Bool = apply(BigInt(x))
+
+ /** Returns the specified bit on this wire as a [[Bool]], dynamically
+ * addressed.
+ */
+ final def apply(x: UInt): Bool = macro SourceInfoTransform.xArg
+
+ final def do_apply(x: UInt)(implicit sourceInfo: SourceInfo): Bool = {
+ (this >> x)(0)
+ }
+
+ /** Returns a subset of bits on this wire from `hi` to `lo` (inclusive),
+ * statically addressed.
+ *
+ * @example
+ * {{{
+ * myBits = 0x5 = 0b101
+ * myBits(1,0) => 0b01 // extracts the two least significant bits
+ * }}}
+ */
+ final def apply(x: Int, y: Int): UInt = macro SourceInfoTransform.xyArg
+
+ final def do_apply(x: Int, y: Int)(implicit sourceInfo: SourceInfo): UInt = {
+ if (x < y || y < 0) {
+ Builder.error(s"Invalid bit range ($x,$y)")
+ }
+ val w = x - y + 1
+ if (isLit()) {
+ UInt((litValue >> y) & ((BigInt(1) << w) - 1), w)
+ } else {
+ pushOp(DefPrim(sourceInfo, UInt(width = w), BitsExtractOp, this.ref, ILit(x), ILit(y)))
+ }
+ }
+
+ // REVIEW TODO: again, is this necessary? Or just have this and use implicits?
+ final def apply(x: BigInt, y: BigInt): UInt = macro SourceInfoTransform.xyArg
+
+ final def do_apply(x: BigInt, y: BigInt)(implicit sourceInfo: SourceInfo): UInt =
+ apply(x.toInt, y.toInt)
+
+ private[core] def unop[T <: Data](sourceInfo: SourceInfo, dest: T, op: PrimOp): T =
+ pushOp(DefPrim(sourceInfo, dest, op, this.ref))
+ private[core] def binop[T <: Data](sourceInfo: SourceInfo, dest: T, op: PrimOp, other: BigInt): T =
+ pushOp(DefPrim(sourceInfo, dest, op, this.ref, ILit(other)))
+ private[core] def binop[T <: Data](sourceInfo: SourceInfo, dest: T, op: PrimOp, other: Bits): T =
+ pushOp(DefPrim(sourceInfo, dest, op, this.ref, other.ref))
+
+ private[core] def compop(sourceInfo: SourceInfo, op: PrimOp, other: Bits): Bool =
+ pushOp(DefPrim(sourceInfo, Bool(), op, this.ref, other.ref))
+ private[core] def redop(sourceInfo: SourceInfo, op: PrimOp): Bool =
+ pushOp(DefPrim(sourceInfo, Bool(), op, this.ref))
+
+ /** Returns this wire zero padded up to the specified width.
+ *
+ * @note for SInts only, this does sign extension
+ */
+ final def pad(that: Int): this.type = macro SourceInfoTransform.thatArg
+
+ def do_pad(that: Int)(implicit sourceInfo: SourceInfo): this.type =
+ binop(sourceInfo, cloneTypeWidth(this.width max Width(that)), PadOp, that)
+
+ /** Returns this wire bitwise-inverted. */
+ final def unary_~ (): Bits = macro SourceInfoWhiteboxTransform.noArg
+
+ def do_unary_~ (implicit sourceInfo: SourceInfo): Bits
+
+
+ /** Shift left operation */
+ // REVIEW TODO: redundant
+ // REVIEW TODO: should these return this.type or Bits?
+ final def << (that: BigInt): Bits = macro SourceInfoWhiteboxTransform.thatArg
+
+ def do_<< (that: BigInt)(implicit sourceInfo: SourceInfo): Bits
+
+ /** Returns this wire statically left shifted by the specified amount,
+ * inserting zeros into the least significant bits.
+ *
+ * The width of the output is `other` larger than the input.
+ */
+ final def << (that: Int): Bits = macro SourceInfoWhiteboxTransform.thatArg
+
+ def do_<< (that: Int)(implicit sourceInfo: SourceInfo): Bits
+
+ /** Returns this wire dynamically left shifted by the specified amount,
+ * inserting zeros into the least significant bits.
+ *
+ * The width of the output is `pow(2, width(other))` larger than the input.
+ */
+ final def << (that: UInt): Bits = macro SourceInfoWhiteboxTransform.thatArg
+
+ def do_<< (that: UInt)(implicit sourceInfo: SourceInfo): Bits
+
+ /** Shift right operation */
+ // REVIEW TODO: redundant
+ final def >> (that: BigInt): Bits = macro SourceInfoWhiteboxTransform.thatArg
+
+ def do_>> (that: BigInt)(implicit sourceInfo: SourceInfo): Bits
+
+ /** Returns this wire statically right shifted by the specified amount,
+ * inserting zeros into the most significant bits.
+ *
+ * The width of the output is the same as the input.
+ */
+ final def >> (that: Int): Bits = macro SourceInfoWhiteboxTransform.thatArg
+
+ def do_>> (that: Int)(implicit sourceInfo: SourceInfo): Bits
+
+ /** Returns this wire dynamically right shifted by the specified amount,
+ * inserting zeros into the most significant bits.
+ *
+ * The width of the output is the same as the input.
+ */
+ final def >> (that: UInt): Bits = macro SourceInfoWhiteboxTransform.thatArg
+
+ def do_>> (that: UInt)(implicit sourceInfo: SourceInfo): Bits
+
+ /** Returns the contents of this wire as a [[Vec]] of [[Bool]]s.
+ */
+ final def toBools(): Seq[Bool] = macro SourceInfoTransform.noArg
+
+ def toBools(implicit sourceInfo: SourceInfo): Seq[Bool] =
+ Seq.tabulate(this.getWidth)(i => this(i))
+
+ /** Reinterpret cast to a SInt.
+ *
+ * @note value not guaranteed to be preserved: for example, an UInt of width
+ * 3 and value 7 (0b111) would become a SInt with value -1
+ */
+ final def asSInt(): SInt = macro SourceInfoTransform.noArg
+
+ def do_asSInt(implicit sourceInfo: SourceInfo): SInt
+
+ /** Reinterpret cast to an UInt.
+ *
+ * @note value not guaranteed to be preserved: for example, a SInt of width
+ * 3 and value -1 (0b111) would become an UInt with value 7
+ */
+ final def asUInt(): UInt = macro SourceInfoTransform.noArg
+
+ def do_asUInt(implicit sourceInfo: SourceInfo): UInt
+
+ /** Reinterpret cast to Bits. */
+ final def asBits(): Bits = macro SourceInfoTransform.noArg
+
+ def do_asBits(implicit sourceInfo: SourceInfo): Bits = asUInt()
+
+ @deprecated("Use asSInt, which makes the reinterpret cast more explicit", "chisel3")
+ final def toSInt(): SInt = do_asSInt(DeprecatedSourceInfo)
+ @deprecated("Use asUInt, which makes the reinterpret cast more explicit", "chisel3")
+ final def toUInt(): UInt = do_asUInt(DeprecatedSourceInfo)
+
+ final def toBool(): Bool = macro SourceInfoTransform.noArg
+
+ def do_toBool(implicit sourceInfo: SourceInfo): Bool = {
+ width match {
+ case KnownWidth(1) => this(0)
+ case _ => throwException(s"can't covert UInt<$width> to Bool")
+ }
+ }
+
+ /** Returns this wire concatenated with `other`, where this wire forms the
+ * most significant part and `other` forms the least significant part.
+ *
+ * The width of the output is sum of the inputs.
+ */
+ final def ## (that: Bits): UInt = macro SourceInfoTransform.thatArg
+
+ def do_## (that: Bits)(implicit sourceInfo: SourceInfo): UInt = {
+ val w = this.width + that.width
+ pushOp(DefPrim(sourceInfo, UInt(w), ConcatOp, this.ref, that.ref))
+ }
+
+ @deprecated("Use asBits, which makes the reinterpret cast more explicit and actually returns Bits", "chisel3")
+ override def toBits: UInt = do_asUInt(DeprecatedSourceInfo)
+
+ override def do_fromBits(that: Bits)(implicit sourceInfo: SourceInfo): this.type = {
+ val res = Wire(this, null).asInstanceOf[this.type]
+ res := that
+ res
+ }
+}
+
+/** Provides a set of operations to create UInt types and literals.
+ * Identical in functionality to the UInt companion object.
+ */
+object Bits extends UIntFactory
+
+// REVIEW TODO: Further discussion needed on what Num actually is.
+/** Abstract trait defining operations available on numeric-like wire data
+ * types.
+ */
+abstract trait Num[T <: Data] {
+ // def << (b: T): T
+ // def >> (b: T): T
+ //def unary_-(): T
+
+ // REVIEW TODO: double check ops conventions against FIRRTL
+
+ /** Outputs the sum of `this` and `b`. The resulting width is the max of the
+ * operands plus 1 (should not overflow).
+ */
+ final def + (that: T): T = macro SourceInfoTransform.thatArg
+
+ def do_+ (that: T)(implicit sourceInfo: SourceInfo): T
+
+ /** Outputs the product of `this` and `b`. The resulting width is the sum of
+ * the operands.
+ *
+ * @note can generate a single-cycle multiplier, which can result in
+ * significant cycle time and area costs
+ */
+ final def * (that: T): T = macro SourceInfoTransform.thatArg
+
+ def do_* (that: T)(implicit sourceInfo: SourceInfo): T
+
+ /** Outputs the quotient of `this` and `b`.
+ *
+ * TODO: full rules
+ */
+ final def / (that: T): T = macro SourceInfoTransform.thatArg
+
+ def do_/ (that: T)(implicit sourceInfo: SourceInfo): T
+
+ final def % (that: T): T = macro SourceInfoTransform.thatArg
+
+ def do_% (that: T)(implicit sourceInfo: SourceInfo): T
+
+ /** Outputs the difference of `this` and `b`. The resulting width is the max
+ * of the operands plus 1 (should not overflow).
+ */
+ final def - (that: T): T = macro SourceInfoTransform.thatArg
+
+ def do_- (that: T)(implicit sourceInfo: SourceInfo): T
+
+ /** Outputs true if `this` < `b`.
+ */
+ final def < (that: T): Bool = macro SourceInfoTransform.thatArg
+
+ def do_< (that: T)(implicit sourceInfo: SourceInfo): Bool
+
+ /** Outputs true if `this` <= `b`.
+ */
+ final def <= (that: T): Bool = macro SourceInfoTransform.thatArg
+
+ def do_<= (that: T)(implicit sourceInfo: SourceInfo): Bool
+
+ /** Outputs true if `this` > `b`.
+ */
+ final def > (that: T): Bool = macro SourceInfoTransform.thatArg
+
+ def do_> (that: T)(implicit sourceInfo: SourceInfo): Bool
+
+ /** Outputs true if `this` >= `b`.
+ */
+ final def >= (that: T): Bool = macro SourceInfoTransform.thatArg
+
+ def do_>= (that: T)(implicit sourceInfo: SourceInfo): Bool
+
+ /** Outputs the minimum of `this` and `b`. The resulting width is the max of
+ * the operands.
+ */
+ final def min(that: T): T = macro SourceInfoTransform.thatArg
+
+ def do_min(that: T)(implicit sourceInfo: SourceInfo): T =
+ Mux(this < that, this.asInstanceOf[T], that)
+
+ /** Outputs the maximum of `this` and `b`. The resulting width is the max of
+ * the operands.
+ */
+ final def max(that: T): T = macro SourceInfoTransform.thatArg
+
+ def do_max(that: T)(implicit sourceInfo: SourceInfo): T =
+ Mux(this < that, that, this.asInstanceOf[T])
+}
+
+/** A data type for unsigned integers, represented as a binary bitvector.
+ * Defines arithmetic operations between other integer types.
+ */
+sealed class UInt private[core] (dir: Direction, width: Width, lit: Option[ULit] = None)
+ extends Bits(dir, width, lit) with Num[UInt] {
+ private[core] override def cloneTypeWidth(w: Width): this.type =
+ new UInt(dir, w).asInstanceOf[this.type]
+ private[chisel] def toType = s"UInt$width"
+
+ override private[chisel] def fromInt(value: BigInt, width: Int): this.type =
+ UInt(value, width).asInstanceOf[this.type]
+
+ override def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = that match {
+ case _: UInt => this connect that
+ case _ => this badConnect that
+ }
+
+ // TODO: refactor to share documentation with Num or add independent scaladoc
+ final def unary_- (): UInt = macro SourceInfoTransform.noArg
+ final def unary_-% (): UInt = macro SourceInfoTransform.noArg
+
+ def do_unary_- (implicit sourceInfo: SourceInfo) : UInt = UInt(0) - this
+ def do_unary_-% (implicit sourceInfo: SourceInfo): UInt = UInt(0) -% this
+
+ override def do_+ (that: UInt)(implicit sourceInfo: SourceInfo): UInt = this +% that
+ override def do_- (that: UInt)(implicit sourceInfo: SourceInfo): UInt = this -% that
+ override def do_/ (that: UInt)(implicit sourceInfo: SourceInfo): UInt =
+ binop(sourceInfo, UInt(this.width), DivideOp, that)
+ override def do_% (that: UInt)(implicit sourceInfo: SourceInfo): UInt =
+ binop(sourceInfo, UInt(this.width), RemOp, that)
+ override def do_* (that: UInt)(implicit sourceInfo: SourceInfo): UInt =
+ binop(sourceInfo, UInt(this.width + that.width), TimesOp, that)
+
+ final def * (that: SInt): SInt = macro SourceInfoTransform.thatArg
+ def do_* (that: SInt)(implicit sourceInfo: SourceInfo): SInt = that * this
+
+ final def +& (that: UInt): UInt = macro SourceInfoTransform.thatArg
+ final def +% (that: UInt): UInt = macro SourceInfoTransform.thatArg
+ final def -& (that: UInt): UInt = macro SourceInfoTransform.thatArg
+ final def -% (that: UInt): UInt = macro SourceInfoTransform.thatArg
+
+ def do_+& (that: UInt)(implicit sourceInfo: SourceInfo): UInt =
+ binop(sourceInfo, UInt((this.width max that.width) + 1), AddOp, that)
+ def do_+% (that: UInt)(implicit sourceInfo: SourceInfo): UInt =
+ (this +& that).tail(1)
+ def do_-& (that: UInt)(implicit sourceInfo: SourceInfo): UInt =
+ binop(sourceInfo, UInt((this.width max that.width) + 1), SubOp, that)
+ def do_-% (that: UInt)(implicit sourceInfo: SourceInfo): UInt =
+ (this -& that).tail(1)
+
+ final def & (that: UInt): UInt = macro SourceInfoTransform.thatArg
+ final def | (that: UInt): UInt = macro SourceInfoTransform.thatArg
+ final def ^ (that: UInt): UInt = macro SourceInfoTransform.thatArg
+
+ def do_& (that: UInt)(implicit sourceInfo: SourceInfo): UInt =
+ binop(sourceInfo, UInt(this.width max that.width), BitAndOp, that)
+ def do_| (that: UInt)(implicit sourceInfo: SourceInfo): UInt =
+ binop(sourceInfo, UInt(this.width max that.width), BitOrOp, that)
+ def do_^ (that: UInt)(implicit sourceInfo: SourceInfo): UInt =
+ binop(sourceInfo, UInt(this.width max that.width), BitXorOp, that)
+
+ /** Returns this wire bitwise-inverted. */
+ def do_unary_~ (implicit sourceInfo: SourceInfo): UInt =
+ unop(sourceInfo, UInt(width = width), BitNotOp)
+
+ // REVIEW TODO: Can this be defined on Bits?
+ final def orR(): Bool = macro SourceInfoTransform.noArg
+ final def andR(): Bool = macro SourceInfoTransform.noArg
+ final def xorR(): Bool = macro SourceInfoTransform.noArg
+
+ def do_orR(implicit sourceInfo: SourceInfo): Bool = this != UInt(0)
+ def do_andR(implicit sourceInfo: SourceInfo): Bool = ~this === UInt(0)
+ def do_xorR(implicit sourceInfo: SourceInfo): Bool = redop(sourceInfo, XorReduceOp)
+
+ override def do_< (that: UInt)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, LessOp, that)
+ override def do_> (that: UInt)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, GreaterOp, that)
+ override def do_<= (that: UInt)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, LessEqOp, that)
+ override def do_>= (that: UInt)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, GreaterEqOp, that)
+
+ final def != (that: UInt): Bool = macro SourceInfoTransform.thatArg
+ final def =/= (that: UInt): Bool = macro SourceInfoTransform.thatArg
+ final def === (that: UInt): Bool = macro SourceInfoTransform.thatArg
+
+ def do_!= (that: UInt)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, NotEqualOp, that)
+ def do_=/= (that: UInt)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, NotEqualOp, that)
+ def do_=== (that: UInt)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, EqualOp, that)
+
+ final def unary_! () : Bool = macro SourceInfoTransform.noArg
+
+ def do_unary_! (implicit sourceInfo: SourceInfo) : Bool = this === Bits(0)
+
+ override def do_<< (that: Int)(implicit sourceInfo: SourceInfo): UInt =
+ binop(sourceInfo, UInt(this.width + that), ShiftLeftOp, that)
+ override def do_<< (that: BigInt)(implicit sourceInfo: SourceInfo): UInt =
+ this << that.toInt
+ override def do_<< (that: UInt)(implicit sourceInfo: SourceInfo): UInt =
+ binop(sourceInfo, UInt(this.width.dynamicShiftLeft(that.width)), DynamicShiftLeftOp, that)
+ override def do_>> (that: Int)(implicit sourceInfo: SourceInfo): UInt =
+ binop(sourceInfo, UInt(this.width.shiftRight(that)), ShiftRightOp, that)
+ override def do_>> (that: BigInt)(implicit sourceInfo: SourceInfo): UInt =
+ this >> that.toInt
+ override def do_>> (that: UInt)(implicit sourceInfo: SourceInfo): UInt =
+ binop(sourceInfo, UInt(this.width), DynamicShiftRightOp, that)
+
+ final def bitSet(off: UInt, dat: Bool): UInt = macro UIntTransform.bitset
+
+ def do_bitSet(off: UInt, dat: Bool)(implicit sourceInfo: SourceInfo): UInt = {
+ val bit = UInt(1, 1) << off
+ Mux(dat, this | bit, ~(~this | bit))
+ }
+
+ /** Returns this UInt as a [[SInt]] with an additional zero in the MSB.
+ */
+ // TODO: this eventually will be renamed as toSInt, once the existing toSInt
+ // completes its deprecation phase.
+ final def zext(): SInt = macro SourceInfoTransform.noArg
+ def do_zext(implicit sourceInfo: SourceInfo): SInt =
+ pushOp(DefPrim(sourceInfo, SInt(width + 1), ConvertOp, ref))
+
+ /** Returns this UInt as a [[SInt]], without changing width or bit value. The
+ * SInt is not guaranteed to have the same value (for example, if the MSB is
+ * high, it will be interpreted as a negative value).
+ */
+ override def do_asSInt(implicit sourceInfo: SourceInfo): SInt =
+ pushOp(DefPrim(sourceInfo, SInt(width), AsSIntOp, ref))
+ override def do_asUInt(implicit sourceInfo: SourceInfo): UInt = this
+}
+
+// This is currently a factory because both Bits and UInt inherit it.
+private[core] sealed trait UIntFactory {
+ /** Create a UInt type with inferred width. */
+ def apply(): UInt = apply(NO_DIR, Width())
+ /** Create a UInt type or port with fixed width. */
+ def apply(dir: Direction = NO_DIR, width: Int): UInt = apply(dir, Width(width))
+ /** Create a UInt port with inferred width. */
+ def apply(dir: Direction): UInt = apply(dir, Width())
+
+ /** Create a UInt literal with inferred width. */
+ def apply(value: BigInt): UInt = apply(value, Width())
+ /** Create a UInt literal with fixed width. */
+ def apply(value: BigInt, width: Int): UInt = apply(value, Width(width))
+ /** Create a UInt literal with inferred width. */
+ def apply(n: String): UInt = apply(parse(n), parsedWidth(n))
+ /** Create a UInt literal with fixed width. */
+ def apply(n: String, width: Int): UInt = apply(parse(n), width)
+
+ /** Create a UInt type with specified width. */
+ def apply(width: Width): UInt = apply(NO_DIR, width)
+ /** Create a UInt port with specified width. */
+ def apply(dir: Direction, width: Width): UInt = new UInt(dir, width)
+ /** Create a UInt literal with specified width. */
+ def apply(value: BigInt, width: Width): UInt = {
+ val lit = ULit(value, width)
+ new UInt(NO_DIR, lit.width, Some(lit))
+ }
+
+ private def parse(n: String) = {
+ val (base, num) = n.splitAt(1)
+ val radix = base match {
+ case "x" | "h" => 16
+ case "d" => 10
+ case "o" => 8
+ case "b" => 2
+ case _ => Builder.error(s"Invalid base $base"); 2
+ }
+ BigInt(num.filterNot(_ == '_'), radix)
+ }
+
+ private def parsedWidth(n: String) =
+ if (n(0) == 'b') {
+ Width(n.length-1)
+ } else if (n(0) == 'h') {
+ Width((n.length-1) * 4)
+ } else {
+ Width()
+ }
+}
+
+object UInt extends UIntFactory
+
+sealed class SInt private (dir: Direction, width: Width, lit: Option[SLit] = None)
+ extends Bits(dir, width, lit) with Num[SInt] {
+ private[core] override def cloneTypeWidth(w: Width): this.type =
+ new SInt(dir, w).asInstanceOf[this.type]
+ private[chisel] def toType = s"SInt$width"
+
+ override def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = that match {
+ case _: SInt => this connect that
+ case _ => this badConnect that
+ }
+
+ override private[chisel] def fromInt(value: BigInt, width: Int): this.type =
+ SInt(value, width).asInstanceOf[this.type]
+
+ final def unary_- (): SInt = macro SourceInfoTransform.noArg
+ final def unary_-% (): SInt = macro SourceInfoTransform.noArg
+
+ def unary_- (implicit sourceInfo: SourceInfo): SInt = SInt(0) - this
+ def unary_-% (implicit sourceInfo: SourceInfo): SInt = SInt(0) -% this
+
+ /** add (default - no growth) operator */
+ override def do_+ (that: SInt)(implicit sourceInfo: SourceInfo): SInt =
+ this +% that
+ /** subtract (default - no growth) operator */
+ override def do_- (that: SInt)(implicit sourceInfo: SourceInfo): SInt =
+ this -% that
+ override def do_* (that: SInt)(implicit sourceInfo: SourceInfo): SInt =
+ binop(sourceInfo, SInt(this.width + that.width), TimesOp, that)
+ override def do_/ (that: SInt)(implicit sourceInfo: SourceInfo): SInt =
+ binop(sourceInfo, SInt(this.width), DivideOp, that)
+ override def do_% (that: SInt)(implicit sourceInfo: SourceInfo): SInt =
+ binop(sourceInfo, SInt(this.width), RemOp, that)
+
+ final def * (that: UInt): SInt = macro SourceInfoTransform.thatArg
+ def do_* (that: UInt)(implicit sourceInfo: SourceInfo): SInt =
+ binop(sourceInfo, SInt(this.width + that.width), TimesOp, that)
+
+ /** add (width +1) operator */
+ final def +& (that: SInt): SInt = macro SourceInfoTransform.thatArg
+ /** add (no growth) operator */
+ final def +% (that: SInt): SInt = macro SourceInfoTransform.thatArg
+ /** subtract (width +1) operator */
+ final def -& (that: SInt): SInt = macro SourceInfoTransform.thatArg
+ /** subtract (no growth) operator */
+ final def -% (that: SInt): SInt = macro SourceInfoTransform.thatArg
+
+ def do_+& (that: SInt)(implicit sourceInfo: SourceInfo): SInt =
+ binop(sourceInfo, SInt((this.width max that.width) + 1), AddOp, that)
+ def do_+% (that: SInt)(implicit sourceInfo: SourceInfo): SInt =
+ (this +& that).tail(1).asSInt
+ def do_-& (that: SInt)(implicit sourceInfo: SourceInfo): SInt =
+ binop(sourceInfo, SInt((this.width max that.width) + 1), SubOp, that)
+ def do_-% (that: SInt)(implicit sourceInfo: SourceInfo): SInt =
+ (this -& that).tail(1).asSInt
+
+ final def & (that: SInt): SInt = macro SourceInfoTransform.thatArg
+ final def | (that: SInt): SInt = macro SourceInfoTransform.thatArg
+ final def ^ (that: SInt): SInt = macro SourceInfoTransform.thatArg
+
+ def do_& (that: SInt)(implicit sourceInfo: SourceInfo): SInt =
+ binop(sourceInfo, UInt(this.width max that.width), BitAndOp, that).asSInt
+ def do_| (that: SInt)(implicit sourceInfo: SourceInfo): SInt =
+ binop(sourceInfo, UInt(this.width max that.width), BitOrOp, that).asSInt
+ def do_^ (that: SInt)(implicit sourceInfo: SourceInfo): SInt =
+ binop(sourceInfo, UInt(this.width max that.width), BitXorOp, that).asSInt
+
+ /** Returns this wire bitwise-inverted. */
+ def do_unary_~ (implicit sourceInfo: SourceInfo): SInt =
+ unop(sourceInfo, UInt(width = width), BitNotOp).asSInt
+
+ override def do_< (that: SInt)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, LessOp, that)
+ override def do_> (that: SInt)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, GreaterOp, that)
+ override def do_<= (that: SInt)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, LessEqOp, that)
+ override def do_>= (that: SInt)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, GreaterEqOp, that)
+
+ final def != (that: SInt): Bool = macro SourceInfoTransform.thatArg
+ final def =/= (that: SInt): Bool = macro SourceInfoTransform.thatArg
+ final def === (that: SInt): Bool = macro SourceInfoTransform.thatArg
+
+ def do_!= (that: SInt)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, NotEqualOp, that)
+ def do_=/= (that: SInt)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, NotEqualOp, that)
+ def do_=== (that: SInt)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, EqualOp, that)
+
+ final def abs(): UInt = macro SourceInfoTransform.noArg
+
+ def do_abs(implicit sourceInfo: SourceInfo): UInt = Mux(this < SInt(0), (-this).asUInt, this.asUInt)
+
+ override def do_<< (that: Int)(implicit sourceInfo: SourceInfo): SInt =
+ binop(sourceInfo, SInt(this.width + that), ShiftLeftOp, that)
+ override def do_<< (that: BigInt)(implicit sourceInfo: SourceInfo): SInt =
+ this << that.toInt
+ override def do_<< (that: UInt)(implicit sourceInfo: SourceInfo): SInt =
+ binop(sourceInfo, SInt(this.width.dynamicShiftLeft(that.width)), DynamicShiftLeftOp, that)
+ override def do_>> (that: Int)(implicit sourceInfo: SourceInfo): SInt =
+ binop(sourceInfo, SInt(this.width.shiftRight(that)), ShiftRightOp, that)
+ override def do_>> (that: BigInt)(implicit sourceInfo: SourceInfo): SInt =
+ this >> that.toInt
+ override def do_>> (that: UInt)(implicit sourceInfo: SourceInfo): SInt =
+ binop(sourceInfo, SInt(this.width), DynamicShiftRightOp, that)
+
+ override def do_asUInt(implicit sourceInfo: SourceInfo): UInt = pushOp(DefPrim(sourceInfo, UInt(this.width), AsUIntOp, ref))
+ override def do_asSInt(implicit sourceInfo: SourceInfo): SInt = this
+}
+
+object SInt {
+ /** Create an SInt type with inferred width. */
+ def apply(): SInt = apply(NO_DIR, Width())
+ /** Create an SInt type or port with fixed width. */
+ def apply(dir: Direction = NO_DIR, width: Int): SInt = apply(dir, Width(width))
+ /** Create an SInt port with inferred width. */
+ def apply(dir: Direction): SInt = apply(dir, Width())
+
+ /** Create an SInt literal with inferred width. */
+ def apply(value: BigInt): SInt = apply(value, Width())
+ /** Create an SInt literal with fixed width. */
+ def apply(value: BigInt, width: Int): SInt = apply(value, Width(width))
+
+ /** Create an SInt type with specified width. */
+ def apply(width: Width): SInt = new SInt(NO_DIR, width)
+ /** Create an SInt port with specified width. */
+ def apply(dir: Direction, width: Width): SInt = new SInt(dir, width)
+ /** Create an SInt literal with specified width. */
+ def apply(value: BigInt, width: Width): SInt = {
+ val lit = SLit(value, width)
+ new SInt(NO_DIR, lit.width, Some(lit))
+ }
+}
+
+// REVIEW TODO: Why does this extend UInt and not Bits? Does defining airth
+// operations on a Bool make sense?
+/** A data type for booleans, defined as a single bit indicating true or false.
+ */
+sealed class Bool(dir: Direction, lit: Option[ULit] = None) extends UInt(dir, Width(1), lit) {
+ private[core] override def cloneTypeWidth(w: Width): this.type = {
+ require(!w.known || w.get == 1)
+ new Bool(dir).asInstanceOf[this.type]
+ }
+
+ override private[chisel] def fromInt(value: BigInt, width: Int): this.type = {
+ require((value == 0 || value == 1) && width == 1)
+ Bool(value == 1).asInstanceOf[this.type]
+ }
+
+ // REVIEW TODO: Why does this need to exist and have different conventions
+ // than Bits?
+ final def & (that: Bool): Bool = macro SourceInfoTransform.thatArg
+ final def | (that: Bool): Bool = macro SourceInfoTransform.thatArg
+ final def ^ (that: Bool): Bool = macro SourceInfoTransform.thatArg
+
+ def do_& (that: Bool)(implicit sourceInfo: SourceInfo): Bool =
+ binop(sourceInfo, Bool(), BitAndOp, that)
+ def do_| (that: Bool)(implicit sourceInfo: SourceInfo): Bool =
+ binop(sourceInfo, Bool(), BitOrOp, that)
+ def do_^ (that: Bool)(implicit sourceInfo: SourceInfo): Bool =
+ binop(sourceInfo, Bool(), BitXorOp, that)
+
+ /** Returns this wire bitwise-inverted. */
+ override def do_unary_~ (implicit sourceInfo: SourceInfo): Bool =
+ unop(sourceInfo, Bool(), BitNotOp)
+
+ /** Outputs the logical OR of two Bools.
+ */
+ def || (that: Bool): Bool = macro SourceInfoTransform.thatArg
+
+ def do_|| (that: Bool)(implicit sourceInfo: SourceInfo): Bool = this | that
+
+ /** Outputs the logical AND of two Bools.
+ */
+ def && (that: Bool): Bool = macro SourceInfoTransform.thatArg
+
+ def do_&& (that: Bool)(implicit sourceInfo: SourceInfo): Bool = this & that
+}
+
+object Bool {
+ /** Creates an empty Bool.
+ */
+ def apply(dir: Direction = NO_DIR): Bool = new Bool(dir)
+
+ /** Creates Bool literal.
+ */
+ def apply(x: Boolean): Bool = new Bool(NO_DIR, Some(ULit(if (x) 1 else 0, Width(1))))
+}
+
+object Mux {
+ /** Creates a mux, whose output is one of the inputs depending on the
+ * value of the condition.
+ *
+ * @param cond condition determining the input to choose
+ * @param con the value chosen when `cond` is true
+ * @param alt the value chosen when `cond` is false
+ * @example
+ * {{{
+ * val muxOut = Mux(data_in === UInt(3), UInt(3, 4), UInt(0, 4))
+ * }}}
+ */
+ def apply[T <: Data](cond: Bool, con: T, alt: T): T = macro MuxTransform.apply[T]
+
+ def do_apply[T <: Data](cond: Bool, con: T, alt: T)(implicit sourceInfo: SourceInfo): T =
+ (con, alt) match {
+ // Handle Mux(cond, UInt, Bool) carefully so that the concrete type is UInt
+ case (c: Bool, a: Bool) => doMux(cond, c, a).asInstanceOf[T]
+ 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]
+ case _ => doAggregateMux(cond, con, alt)
+ }
+
+ private def doMux[T <: Data](cond: Bool, con: T, alt: T)(implicit sourceInfo: SourceInfo): 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(sourceInfo, d, MultiplexOp, cond.ref, con.ref, alt.ref))
+ }
+
+ private def doAggregateMux[T <: Data](cond: Bool, con: T, alt: T)(implicit sourceInfo: SourceInfo): T = {
+ require(con.getClass == alt.getClass, s"can't Mux between ${con.getClass} and ${alt.getClass}")
+ 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/chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala b/chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala
new file mode 100644
index 00000000..2126ebce
--- /dev/null
+++ b/chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala
@@ -0,0 +1,55 @@
+// See LICENSE for license details.
+
+package chisel.core
+
+import chisel.internal.Builder.pushCommand
+import chisel.internal.firrtl.{ModuleIO, DefInvalid}
+import chisel.internal.sourceinfo.SourceInfo
+
+/** Defines a black box, which is a module that can be referenced from within
+ * Chisel, but is not defined in the emitted Verilog. Useful for connecting
+ * to RTL modules defined outside Chisel.
+ *
+ * @example
+ * {{{
+ * ... to be written once a spec is finalized ...
+ * }}}
+ */
+// REVIEW TODO: make Verilog parameters part of the constructor interface?
+abstract class BlackBox extends Module {
+ // Don't bother taking override_clock|reset, clock/reset locked out anyway
+ // TODO: actually implement this.
+ def setVerilogParameters(s: String): Unit = {}
+
+ // The body of a BlackBox is empty, the real logic happens in firrtl/Emitter.scala
+ // Bypass standard clock, reset, io port declaration by flattening io
+ // TODO(twigg): ? Really, overrides are bad, should extend BaseModule....
+ override private[core] def ports = io.elements.toSeq
+
+ // Do not do reflective naming of internal signals, just name io
+ override private[core] def setRefs(): this.type = {
+ for ((name, port) <- ports) {
+ port.setRef(ModuleIO(this, _namespace.name(name)))
+ }
+ // setRef is not called on the actual io.
+ // There is a risk of user improperly attempting to connect directly with io
+ // Long term solution will be to define BlackBox IO differently as part of
+ // it not descending from the (current) Module
+ this
+ }
+
+ // Don't setup clock, reset
+ // Cann't invalide io in one bunch, must invalidate each part separately
+ override private[core] def setupInParent(implicit sourceInfo: SourceInfo): this.type = _parent match {
+ case Some(p) => {
+ // Just init instance inputs
+ for((_,port) <- ports) pushCommand(DefInvalid(sourceInfo, port.ref))
+ this
+ }
+ case None => this
+ }
+
+ // Using null is horrible but these signals SHOULD NEVER be used:
+ override val clock = null
+ override val reset = null
+}
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala
new file mode 100644
index 00000000..cae38144
--- /dev/null
+++ b/chiselFrontend/src/main/scala/chisel3/core/Data.scala
@@ -0,0 +1,156 @@
+// See LICENSE for license details.
+
+package chisel.core
+
+import scala.language.experimental.macros
+
+import chisel.internal._
+import chisel.internal.Builder.pushCommand
+import chisel.internal.firrtl._
+import chisel.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, UnlocatableSourceInfo, WireTransform, SourceInfoTransform}
+
+sealed abstract class Direction(name: String) {
+ override def toString: String = name
+ def flip: Direction
+}
+object INPUT extends Direction("input") { override def flip: Direction = OUTPUT }
+object OUTPUT extends Direction("output") { override def flip: Direction = INPUT }
+object NO_DIR extends Direction("?") { override def flip: Direction = NO_DIR }
+
+/** Mixing in this trait flips the direction of an Aggregate. */
+trait Flipped extends Data {
+ this.overrideDirection(_.flip, !_)
+}
+
+/** This forms the root of the type system for wire data types. The data value
+ * must be representable as some number (need not be known at Chisel compile
+ * time) of bits, and must have methods to pack / unpack structured data to /
+ * from bits.
+ */
+abstract class Data(dirArg: Direction) extends HasId {
+ def dir: Direction = dirVar
+
+ // Sucks this is mutable state, but cloneType doesn't take a Direction arg
+ private var isFlipVar = dirArg == INPUT
+ private var dirVar = dirArg
+ private[core] def isFlip = isFlipVar
+
+ private[core] def overrideDirection(newDir: Direction => Direction,
+ newFlip: Boolean => Boolean): this.type = {
+ this.isFlipVar = newFlip(this.isFlipVar)
+ for (field <- this.flatten)
+ (field: Data).dirVar = newDir((field: Data).dirVar)
+ this
+ }
+ def asInput: this.type = cloneType.overrideDirection(_ => INPUT, _ => true)
+ def asOutput: this.type = cloneType.overrideDirection(_ => OUTPUT, _ => false)
+ def flip(): this.type = cloneType.overrideDirection(_.flip, !_)
+
+ private[core] def badConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit =
+ throwException(s"cannot connect ${this} and ${that}")
+ private[core] def connect(that: Data)(implicit sourceInfo: SourceInfo): Unit =
+ pushCommand(Connect(sourceInfo, this.lref, that.ref))
+ private[core] def bulkConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit =
+ pushCommand(BulkConnect(sourceInfo, this.lref, that.lref))
+ private[core] def lref: Node = Node(this)
+ private[chisel] def ref: Arg = if (isLit) litArg.get else lref
+ private[core] def cloneTypeWidth(width: Width): this.type
+ private[chisel] def toType: String
+
+ def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = this badConnect that
+
+ def <> (that: Data)(implicit sourceInfo: SourceInfo): Unit = this badConnect that
+
+ def cloneType: this.type
+ def litArg(): Option[LitArg] = None
+ def litValue(): BigInt = litArg.get.num
+ def isLit(): Boolean = litArg.isDefined
+
+ def width: Width
+ final def getWidth: Int = width.get
+
+ // While this being in the Data API doesn't really make sense (should be in
+ // Aggregate, right?) this is because of an implementation limitation:
+ // cloneWithDirection, which is private and defined here, needs flatten to
+ // set element directionality.
+ // Related: directionality is mutable state. A possible solution for both is
+ // to define directionality relative to the container, but these parent links
+ // currently don't exist (while this information may be available during
+ // FIRRTL emission, it would break directionality querying from Chisel, which
+ // does get used).
+ private[chisel] def flatten: IndexedSeq[Bits]
+
+ /** Creates an new instance of this type, unpacking the input Bits into
+ * structured data.
+ *
+ * This performs the inverse operation of toBits.
+ *
+ * @note does NOT assign to the object this is called on, instead creates
+ * and returns a NEW object (useful in a clone-and-assign scenario)
+ * @note does NOT check bit widths, may drop bits during assignment
+ * @note what fromBits assigs to must have known widths
+ */
+ def fromBits(that: Bits): this.type = macro SourceInfoTransform.thatArg
+
+ def do_fromBits(that: Bits)(implicit sourceInfo: SourceInfo): this.type = {
+ var i = 0
+ val wire = Wire(this.cloneType)
+ val bits =
+ if (that.width.known && that.width.get >= wire.width.get) {
+ that
+ } else {
+ Wire(that.cloneTypeWidth(wire.width), init = that)
+ }
+ for (x <- wire.flatten) {
+ x := bits(i + x.getWidth-1, i)
+ i += x.getWidth
+ }
+ wire.asInstanceOf[this.type]
+ }
+
+ /** Packs the value of this object as plain Bits.
+ *
+ * This performs the inverse operation of fromBits(Bits).
+ */
+ @deprecated("Use asBits, which makes the reinterpret cast more explicit and actually returns Bits", "chisel3")
+ def toBits(): UInt = SeqUtils.do_asUInt(this.flatten)(DeprecatedSourceInfo)
+}
+
+object Wire {
+ def apply[T <: Data](t: T): T = macro WireTransform.apply[T]
+
+ // No source info since Scala macros don't yet support named / default arguments.
+ def apply[T <: Data](dummy: Int = 0, init: T): T =
+ do_apply(null.asInstanceOf[T], init)(UnlocatableSourceInfo)
+
+ // No source info since Scala macros don't yet support named / default arguments.
+ def apply[T <: Data](t: T, init: T): T =
+ do_apply(t, init)(UnlocatableSourceInfo)
+
+ def do_apply[T <: Data](t: T, init: T)(implicit sourceInfo: SourceInfo): T = {
+ val x = Reg.makeType(t, null.asInstanceOf[T], init)
+ pushCommand(DefWire(sourceInfo, x))
+ pushCommand(DefInvalid(sourceInfo, x.ref))
+ if (init != null) {
+ x := init
+ }
+ x
+ }
+}
+
+object Clock {
+ def apply(dir: Direction = NO_DIR): Clock = new Clock(dir)
+}
+
+// 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[Bits] = IndexedSeq()
+ private[core] def cloneTypeWidth(width: Width): this.type = cloneType
+ private[chisel] def toType = "Clock"
+
+ override def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = that match {
+ case _: Clock => this connect that
+ case _ => this badConnect that
+ }
+}
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala
new file mode 100644
index 00000000..a2df2910
--- /dev/null
+++ b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala
@@ -0,0 +1,134 @@
+// See LICENSE for license details.
+
+package chisel.core
+
+import scala.language.experimental.macros
+
+import chisel.internal._
+import chisel.internal.Builder.pushCommand
+import chisel.internal.firrtl._
+import chisel.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, UnlocatableSourceInfo, MemTransform}
+
+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] = do_apply(size, t)(UnlocatableSourceInfo)
+
+ /** 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] = macro MemTransform.apply[T]
+
+ def do_apply[T <: Data](size: Int, t: T)(implicit sourceInfo: SourceInfo): Mem[T] = {
+ val mt = t.cloneType
+ val mem = new Mem(mt, size)
+ pushCommand(DefMemory(sourceInfo, mem, mt, size)) // 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/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(UnlocatableSourceInfo, 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 read(idx: UInt): T = makePort(UnlocatableSourceInfo, 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 = {
+ implicit val sourceInfo = UnlocatableSourceInfo
+ makePort(UnlocatableSourceInfo, idx, MemPortDirection.WRITE) := 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: Seq[Bool]) (implicit evidence: T <:< Vec[_]): Unit = {
+ implicit val sourceInfo = UnlocatableSourceInfo
+ val accessor = makePort(sourceInfo, 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(sourceInfo: SourceInfo, idx: UInt, dir: MemPortDirection): T =
+ pushCommand(DefMemPort(sourceInfo,
+ t.cloneType, Node(this), dir, idx.ref, Node(idx._parent.get.clock))).id
+}
+
+/** 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.
+ *
+ * @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](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] = do_apply(size, t)(DeprecatedSourceInfo)
+
+ /** 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] = macro MemTransform.apply[T]
+
+ def do_apply[T <: Data](size: Int, t: T)(implicit sourceInfo: SourceInfo): SeqMem[T] = {
+ val mt = t.cloneType
+ val mem = new SeqMem(mt, size)
+ pushCommand(DefSeqMemory(sourceInfo, mem, mt, size)) // 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.
+ *
+ * @note when multiple conflicting writes are performed on a Mem element, the
+ * 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 = {
+ implicit val sourceInfo = UnlocatableSourceInfo
+ val a = Wire(UInt())
+ when (enable) { a := addr }
+ read(a)
+ }
+}
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Module.scala b/chiselFrontend/src/main/scala/chisel3/core/Module.scala
new file mode 100644
index 00000000..1de3efe5
--- /dev/null
+++ b/chiselFrontend/src/main/scala/chisel3/core/Module.scala
@@ -0,0 +1,119 @@
+// See LICENSE for license details.
+
+package chisel.core
+
+import scala.collection.mutable.{ArrayBuffer, HashSet}
+import scala.language.experimental.macros
+
+import chisel.internal._
+import chisel.internal.Builder.pushCommand
+import chisel.internal.Builder.dynamicContext
+import chisel.internal.firrtl._
+import chisel.internal.sourceinfo.{SourceInfo, InstTransform, UnlocatableSourceInfo}
+
+object Module {
+ /** A wrapper method that all Module instantiations must be wrapped in
+ * (necessary to help Chisel track internal state).
+ *
+ * @param m the Module being created
+ *
+ * @return the input module `m` with Chisel metadata properly set
+ */
+ def apply[T <: Module](bc: => T): T = macro InstTransform.apply[T]
+
+ def do_apply[T <: Module](bc: => T)(implicit sourceInfo: SourceInfo): T = {
+ // Don't generate source info referencing parents inside a module, sincce this interferes with
+ // module de-duplication in FIRRTL emission.
+ val childSourceInfo = UnlocatableSourceInfo
+
+ val parent = dynamicContext.currentModule
+ val m = bc.setRefs()
+ m._commands.prepend(DefInvalid(childSourceInfo, m.io.ref)) // init module outputs
+ dynamicContext.currentModule = parent
+ val ports = m.computePorts
+ Builder.components += Component(m, m.name, ports, m._commands)
+ pushCommand(DefInstance(sourceInfo, m, ports))
+ m.setupInParent(childSourceInfo)
+ }
+}
+
+/** Abstract base class for Modules, which behave much like Verilog modules.
+ * These may contain both logic and state which are written in the Module
+ * body (constructor).
+ *
+ * @note Module instantiations must be wrapped in a Module() call.
+ */
+abstract class Module(
+ override_clock: Option[Clock]=None, override_reset: Option[Bool]=None)
+extends HasId {
+ // _clock and _reset can be clock and reset in these 2ary constructors
+ // once chisel2 compatibility issues are resolved
+ def this(_clock: Clock) = this(Option(_clock), None)
+ def this(_reset: Bool) = this(None, Option(_reset))
+ def this(_clock: Clock, _reset: Bool) = this(Option(_clock), Option(_reset))
+
+ private[core] val _namespace = Builder.globalNamespace.child
+ private[chisel] val _commands = ArrayBuffer[Command]()
+ private[core] val _ids = ArrayBuffer[HasId]()
+ dynamicContext.currentModule = Some(this)
+
+ /** Name of the instance. */
+ val name = Builder.globalNamespace.name(getClass.getName.split('.').last)
+
+ /** IO for this Module. At the Scala level (pre-FIRRTL transformations),
+ * connections in and out of a Module may only go through `io` elements.
+ */
+ def io: Bundle
+ val clock = Clock(INPUT)
+ val reset = Bool(INPUT)
+
+ private[chisel] def addId(d: HasId) { _ids += d }
+
+ private[core] def ports: Seq[(String,Data)] = Vector(
+ ("clk", clock), ("reset", reset), ("io", io)
+ )
+
+ private[core] def computePorts = for((name, port) <- ports) yield {
+ val bundleDir = if (port.isFlip) INPUT else OUTPUT
+ Port(port, if (port.dir == NO_DIR) bundleDir else port.dir)
+ }
+
+ private[core] def setupInParent(implicit sourceInfo: SourceInfo): this.type = {
+ _parent match {
+ case Some(p) => {
+ pushCommand(DefInvalid(sourceInfo, io.ref)) // init instance inputs
+ clock := override_clock.getOrElse(p.clock)
+ reset := override_reset.getOrElse(p.reset)
+ this
+ }
+ case None => this
+ }
+ }
+
+ private[core] def setRefs(): this.type = {
+ for ((name, port) <- ports) {
+ port.setRef(ModuleIO(this, _namespace.name(name)))
+ }
+
+ // Suggest names to nodes using runtime reflection
+ val valNames = HashSet[String](getClass.getDeclaredFields.map(_.getName):_*)
+ def isPublicVal(m: java.lang.reflect.Method) =
+ m.getParameterTypes.isEmpty && valNames.contains(m.getName)
+ val methods = getClass.getMethods.sortWith(_.getName > _.getName)
+ for (m <- methods; if isPublicVal(m)) m.invoke(this) match {
+ case (id: HasId) => id.suggestName(m.getName)
+ case _ =>
+ }
+
+ // For Module instances we haven't named, suggest the name of the Module
+ _ids foreach {
+ case m: Module => m.suggestName(m.name)
+ case _ =>
+ }
+
+ // All suggestions are in, force names to every node.
+ _ids.foreach(_.forceName(default="T", _namespace))
+ _ids.foreach(_._onModuleClose)
+ this
+ }
+}
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Printf.scala b/chiselFrontend/src/main/scala/chisel3/core/Printf.scala
new file mode 100644
index 00000000..a7970816
--- /dev/null
+++ b/chiselFrontend/src/main/scala/chisel3/core/Printf.scala
@@ -0,0 +1,36 @@
+// See LICENSE for license details.
+
+package chisel.core
+
+import scala.language.experimental.macros
+
+import chisel.internal._
+import chisel.internal.Builder.pushCommand
+import chisel.internal.firrtl._
+import chisel.internal.sourceinfo.SourceInfo
+
+object printf { // scalastyle:ignore object.name
+ /** Prints a message in simulation.
+ *
+ * Does not fire when in reset (defined as the encapsulating Module's
+ * reset). If your definition of reset is not the encapsulating Module's
+ * reset, you will need to gate this externally.
+ *
+ * May be called outside of a Module (like defined in a function), so
+ * functions using printf make the standard Module assumptions (single clock
+ * and single reset).
+ *
+ * @param fmt printf format string
+ * @param data format string varargs containing data to print
+ */
+ def apply(fmt: String, data: Bits*)(implicit sourceInfo: SourceInfo) {
+ when (!(Builder.dynamicContext.currentModule.get.reset)) {
+ printfWithoutReset(fmt, data:_*)
+ }
+ }
+
+ private[core] def printfWithoutReset(fmt: String, data: Bits*)(implicit sourceInfo: SourceInfo) {
+ val clock = Builder.dynamicContext.currentModule.get.clock
+ pushCommand(Printf(sourceInfo, Node(clock), fmt, data.map((d: Bits) => d.ref)))
+ }
+}
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala
new file mode 100644
index 00000000..78461334
--- /dev/null
+++ b/chiselFrontend/src/main/scala/chisel3/core/Reg.scala
@@ -0,0 +1,71 @@
+// See LICENSE for license details.
+
+package chisel.core
+
+import chisel.internal._
+import chisel.internal.Builder.pushCommand
+import chisel.internal.firrtl._
+import chisel.internal.sourceinfo.{SourceInfo, UnlocatableSourceInfo}
+
+object Reg {
+ private[core] def makeType[T <: Data](t: T = null, next: T = null, init: T = null): T = {
+ if (t ne null) {
+ t.cloneType
+ } else if (next ne null) {
+ next.cloneTypeWidth(Width())
+ } else if (init ne null) {
+ init.litArg match {
+ // For e.g. Reg(init=UInt(0, k)), fix the Reg's width to k
+ case Some(lit) if lit.forcedWidth => init.cloneType
+ case _ => init.cloneTypeWidth(Width())
+ }
+ } else {
+ throwException("cannot infer type")
+ }
+ }
+
+ /** Creates a register with optional next and initialization values.
+ *
+ * @param t: data type for the register
+ * @param next: new value register is to be updated with every cycle (or
+ * empty to not update unless assigned to using the := operator)
+ * @param init: initialization value on reset (or empty for uninitialized,
+ * where the register value persists across a reset)
+ *
+ * @note this may result in a type error if called from a type parameterized
+ * function, since the Scala compiler isn't smart enough to know that null
+ * is a valid value. In those cases, you can either use the outType only Reg
+ * constructor or pass in `null.asInstanceOf[T]`.
+ */
+ def apply[T <: Data](t: T = null, next: T = null, init: T = null): T =
+ // Scala macros can't (yet) handle named or default arguments.
+ do_apply(t, next, init)(UnlocatableSourceInfo)
+
+ /** Creates a register without initialization (reset is ignored). Value does
+ * not change unless assigned to (using the := operator).
+ *
+ * @param outType: data type for the register
+ */
+ def apply[T <: Data](outType: T): T = Reg[T](outType, null.asInstanceOf[T], null.asInstanceOf[T])
+
+ def do_apply[T <: Data](t: T, next: T, init: T)(implicit sourceInfo: SourceInfo): T = {
+ // TODO: write this in a way that doesn't need nulls (bad Scala style),
+ // null.asInstanceOf[T], and two constructors. Using Option types are an
+ // option, but introduces cumbersome syntax (wrap everything in a Some()).
+ // Implicit conversions to Option (or similar) types were also considered,
+ // but Scala's type inferencer and implicit insertion isn't smart enough
+ // to resolve all use cases. If the type inferencer / implicit resolution
+ // system improves, this may be changed.
+ val x = makeType(t, next, init)
+ val clock = Node(x._parent.get.clock) // TODO multi-clock
+ if (init == null) {
+ pushCommand(DefReg(sourceInfo, x, clock))
+ } else {
+ pushCommand(DefRegInit(sourceInfo, x, clock, Node(x._parent.get.reset), init.ref))
+ }
+ if (next != null) {
+ x := next
+ }
+ x
+ }
+}
diff --git a/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala b/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala
new file mode 100644
index 00000000..e31119a5
--- /dev/null
+++ b/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala
@@ -0,0 +1,59 @@
+// See LICENSE for license details.
+
+package chisel.core
+
+import scala.language.experimental.macros
+
+import chisel.internal.sourceinfo.{SourceInfo, SourceInfoTransform}
+
+private[chisel] object SeqUtils {
+ /** Equivalent to Cat(r(n-1), ..., r(0)) */
+ def asUInt[T <: Bits](in: Seq[T]): UInt = macro SourceInfoTransform.inArg
+
+ def do_asUInt[T <: Bits](in: Seq[T])(implicit sourceInfo: SourceInfo): UInt = {
+ if (in.tail.isEmpty) {
+ in.head.asUInt
+ } else {
+ val left = asUInt(in.slice(0, in.length/2))
+ val right = asUInt(in.slice(in.length/2, in.length))
+ right ## left
+ }
+ }
+
+ /** Counts the number of true Bools in a Seq */
+ def count(in: Seq[Bool]): UInt = macro SourceInfoTransform.inArg
+
+ def do_count(in: Seq[Bool])(implicit sourceInfo: SourceInfo): UInt = {
+ if (in.size == 0) {
+ UInt(0)
+ } else if (in.size == 1) {
+ in.head
+ } else {
+ count(in.slice(0, in.size/2)) + (UInt(0) ## count(in.slice(in.size/2, in.size)))
+ }
+ }
+
+ /** Returns data value corresponding to first true predicate */
+ def priorityMux[T <: Data](in: Seq[(Bool, T)]): T = macro SourceInfoTransform.inArg
+
+ def do_priorityMux[T <: Data](in: Seq[(Bool, T)])(implicit sourceInfo: SourceInfo): T = {
+ if (in.size == 1) {
+ in.head._2
+ } else {
+ Mux(in.head._1, in.head._2, priorityMux(in.tail))
+ }
+ }
+
+ /** Returns data value corresponding to lone true predicate */
+ def oneHotMux[T <: Data](in: Iterable[(Bool, T)]): T = macro SourceInfoTransform.inArg
+
+ def do_oneHotMux[T <: Data](in: Iterable[(Bool, T)])(implicit sourceInfo: SourceInfo): T = {
+ if (in.tail.isEmpty) {
+ in.head._2
+ } else {
+ val masked = for ((s, i) <- in) yield Mux(s, i.toBits, Bits(0))
+ val width = in.map(_._2.width).reduce(_ max _)
+ in.head._2.cloneTypeWidth(width).fromBits(masked.reduceLeft(_|_))
+ }
+ }
+}
diff --git a/chiselFrontend/src/main/scala/chisel3/core/When.scala b/chiselFrontend/src/main/scala/chisel3/core/When.scala
new file mode 100644
index 00000000..5d484313
--- /dev/null
+++ b/chiselFrontend/src/main/scala/chisel3/core/When.scala
@@ -0,0 +1,59 @@
+// See LICENSE for license details.
+
+package chisel.core
+
+import scala.language.experimental.macros
+
+import chisel.internal._
+import chisel.internal.Builder.pushCommand
+import chisel.internal.firrtl._
+import chisel.internal.sourceinfo.{SourceInfo}
+
+object when { // scalastyle:ignore object.name
+ /** Create a `when` condition block, where whether a block of logic is
+ * executed or not depends on the conditional.
+ *
+ * @param cond condition to execute upon
+ * @param block logic that runs only if `cond` is true
+ *
+ * @example
+ * {{{
+ * when ( myData === UInt(3) ) {
+ * // Some logic to run when myData equals 3.
+ * } .elsewhen ( myData === UInt(1) ) {
+ * // Some logic to run when myData equals 1.
+ * } .otherwise {
+ * // Some logic to run when myData is neither 3 nor 1.
+ * }
+ * }}}
+ */
+ def apply(cond: Bool)(block: => Unit)(implicit sourceInfo: SourceInfo): WhenContext = {
+ new WhenContext(sourceInfo, cond, !cond, block)
+ }
+}
+
+/** 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.
+ */
+final class WhenContext(sourceInfo: SourceInfo, 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 (elseCond: Bool)(block: => Unit)(implicit sourceInfo: SourceInfo): WhenContext = {
+ new WhenContext(sourceInfo, 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)(implicit sourceInfo: SourceInfo): Unit =
+ new WhenContext(sourceInfo, prevCond, null, block)
+
+ pushCommand(WhenBegin(sourceInfo, cond.ref))
+ block
+ pushCommand(WhenEnd(sourceInfo))
+}
diff --git a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala
new file mode 100644
index 00000000..01628105
--- /dev/null
+++ b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala
@@ -0,0 +1,129 @@
+// See LICENSE for license details.
+
+package chisel.internal
+
+import scala.util.DynamicVariable
+import scala.collection.mutable.{ArrayBuffer, HashMap}
+
+import chisel._
+import core._
+import firrtl._
+
+private[chisel] class Namespace(parent: Option[Namespace], keywords: Set[String]) {
+ private val names = collection.mutable.HashMap[String, Long]()
+ for (keyword <- keywords)
+ names(keyword) = 1
+
+ private def rename(n: String): String = {
+ val index = names.getOrElse(n, 1L)
+ val tryName = s"${n}_${index}"
+ names(n) = index + 1
+ if (this contains tryName) rename(n) else tryName
+ }
+
+ def contains(elem: String): Boolean = {
+ names.contains(elem) || parent.map(_ contains elem).getOrElse(false)
+ }
+
+ def name(elem: String): String = {
+ if (this contains elem) {
+ name(rename(elem))
+ } else {
+ names(elem) = 1
+ elem
+ }
+ }
+
+ def child(kws: Set[String]): Namespace = new Namespace(Some(this), kws)
+ def child: Namespace = child(Set())
+}
+
+private[chisel] class IdGen {
+ private var counter = -1L
+ def next: Long = {
+ counter += 1
+ counter
+ }
+}
+
+private[chisel] trait HasId {
+ private[chisel] def _onModuleClose {} // scalastyle:ignore method.name
+ private[chisel] val _parent = Builder.dynamicContext.currentModule
+ _parent.foreach(_.addId(this))
+
+ private[chisel] val _id = Builder.idGen.next
+ override def hashCode: Int = _id.toInt
+ override def equals(that: Any): Boolean = that match {
+ case x: HasId => _id == x._id
+ case _ => false
+ }
+
+ // Facilities for 'suggesting' a name to this.
+ // Post-name hooks called to carry the suggestion to other candidates as needed
+ private var suggested_name: Option[String] = None
+ private val postname_hooks = scala.collection.mutable.ListBuffer.empty[String=>Unit]
+ // Only takes the first suggestion!
+ def suggestName(name: =>String): this.type = {
+ if(suggested_name.isEmpty) suggested_name = Some(name)
+ for(hook <- postname_hooks) { hook(name) }
+ this
+ }
+ private[chisel] def addPostnameHook(hook: String=>Unit): Unit = postname_hooks += hook
+
+ // Uses a namespace to convert suggestion into a true name
+ // Will not do any naming if the reference already assigned.
+ // (e.g. tried to suggest a name to part of a Bundle)
+ private[chisel] def forceName(default: =>String, namespace: Namespace): Unit =
+ if(_ref.isEmpty) {
+ val candidate_name = suggested_name.getOrElse(default)
+ val available_name = namespace.name(candidate_name)
+ setRef(Ref(available_name))
+ }
+
+ private var _ref: Option[Arg] = None
+ private[chisel] def setRef(imm: Arg): Unit = _ref = Some(imm)
+ private[chisel] def setRef(parent: HasId, name: String): Unit = setRef(Slot(Node(parent), name))
+ private[chisel] def setRef(parent: HasId, index: Int): Unit = setRef(Index(Node(parent), ILit(index)))
+ private[chisel] def setRef(parent: HasId, index: UInt): Unit = setRef(Index(Node(parent), index.ref))
+ private[chisel] def getRef: Arg = _ref.get
+}
+
+private[chisel] class DynamicContext {
+ val idGen = new IdGen
+ val globalNamespace = new Namespace(None, Set())
+ val components = ArrayBuffer[Component]()
+ var currentModule: Option[Module] = None
+ val errors = new ErrorLog
+}
+
+private[chisel] object Builder {
+ // All global mutable state must be referenced via dynamicContextVar!!
+ private val dynamicContextVar = new DynamicVariable[Option[DynamicContext]](None)
+
+ def dynamicContext: DynamicContext =
+ dynamicContextVar.value getOrElse (new DynamicContext)
+ def idGen: IdGen = dynamicContext.idGen
+ def globalNamespace: Namespace = dynamicContext.globalNamespace
+ def components: ArrayBuffer[Component] = dynamicContext.components
+
+ def pushCommand[T <: Command](c: T): T = {
+ dynamicContext.currentModule.foreach(_._commands += c)
+ c
+ }
+ def pushOp[T <: Data](cmd: DefPrim[T]): T = pushCommand(cmd).id
+
+ def errors: ErrorLog = dynamicContext.errors
+ def error(m: => String): Unit = errors.error(m)
+
+ def build[T <: Module](f: => T): Circuit = {
+ dynamicContextVar.withValue(Some(new DynamicContext)) {
+ errors.info("Elaborating design...")
+ val mod = f
+ mod.forceName(mod.name, globalNamespace)
+ errors.checkpoint()
+ errors.info("Done elaborating.")
+
+ Circuit(components.last.name, components)
+ }
+ }
+}
diff --git a/chiselFrontend/src/main/scala/chisel3/internal/Error.scala b/chiselFrontend/src/main/scala/chisel3/internal/Error.scala
new file mode 100644
index 00000000..f0481dc4
--- /dev/null
+++ b/chiselFrontend/src/main/scala/chisel3/internal/Error.scala
@@ -0,0 +1,91 @@
+// See LICENSE for license details.
+
+package chisel.internal
+
+import scala.collection.mutable.ArrayBuffer
+
+import chisel.core._
+
+class ChiselException(message: String, cause: Throwable) extends Exception(message, cause)
+
+private[chisel] object throwException {
+ def apply(s: String, t: Throwable = null): Nothing =
+ throw new ChiselException(s, t)
+}
+
+/** Records and reports runtime errors and warnings. */
+private[chisel] class ErrorLog {
+ def hasErrors: Boolean = errors.exists(_.isFatal)
+
+ /** Log an error message */
+ def error(m: => String): Unit =
+ errors += new Error(m, getUserLineNumber)
+
+ /** Log a warning message */
+ def warning(m: => String): Unit =
+ errors += new Warning(m, getUserLineNumber)
+
+ /** Emit an informational message */
+ def info(m: String): Unit =
+ println(new Info("[%2.3f] %s".format(elapsedTime/1e3, m), None)) // scalastyle:ignore regex
+
+ /** Prints error messages generated by Chisel at runtime. */
+ def report(): Unit = errors foreach println // scalastyle:ignore regex
+
+ /** Throw an exception if any errors have yet occurred. */
+ def checkpoint(): Unit = if(hasErrors) {
+ import Console._
+ throwException(errors.map(_ + "\n").reduce(_ + _) +
+ UNDERLINED + "CODE HAS " + errors.filter(_.isFatal).length + RESET +
+ UNDERLINED + " " + RED + "ERRORS" + RESET +
+ UNDERLINED + " and " + errors.filterNot(_.isFatal).length + RESET +
+ UNDERLINED + " " + YELLOW + "WARNINGS" + RESET)
+ }
+
+ private def findFirstUserFrame(stack: Array[StackTraceElement]): Option[StackTraceElement] = {
+ def isUserCode(ste: StackTraceElement): Boolean = {
+ def isUserModule(c: Class[_]): Boolean =
+ c != null && (c == classOf[Module] || isUserModule(c.getSuperclass))
+ isUserModule(Class.forName(ste.getClassName))
+ }
+
+ stack.indexWhere(isUserCode) match {
+ case x if x < 0 => None
+ case x => Some(stack(x))
+ }
+ }
+
+ private def getUserLineNumber =
+ findFirstUserFrame(Thread.currentThread().getStackTrace)
+
+ private val errors = ArrayBuffer[LogEntry]()
+
+ private val startTime = System.currentTimeMillis
+ private def elapsedTime: Long = System.currentTimeMillis - startTime
+}
+
+private abstract class LogEntry(msg: => String, line: Option[StackTraceElement]) {
+ def isFatal: Boolean = false
+ def format: String
+
+ override def toString: String = line match {
+ case Some(l) => s"${format} ${l.getFileName}:${l.getLineNumber}: ${msg} in class ${l.getClassName}"
+ case None => s"${format} ${msg}"
+ }
+
+ protected def tag(name: String, color: String): String =
+ s"[${color}${name}${Console.RESET}]"
+}
+
+private class Error(msg: => String, line: Option[StackTraceElement]) extends LogEntry(msg, line) {
+ override def isFatal: Boolean = true
+ def format: String = tag("error", Console.RED)
+}
+
+private class Warning(msg: => String, line: Option[StackTraceElement]) extends LogEntry(msg, line) {
+ def format: String = tag("warn", Console.YELLOW)
+}
+
+private class Info(msg: => String, line: Option[StackTraceElement]) extends LogEntry(msg, line) {
+ def format: String = tag("info", Console.MAGENTA)
+}
diff --git a/chiselFrontend/src/main/scala/chisel3/internal/SourceInfo.scala b/chiselFrontend/src/main/scala/chisel3/internal/SourceInfo.scala
new file mode 100644
index 00000000..c20bd130
--- /dev/null
+++ b/chiselFrontend/src/main/scala/chisel3/internal/SourceInfo.scala
@@ -0,0 +1,51 @@
+// See LICENSE for license details.
+
+// This file contains macros for adding source locators at the point of invocation.
+//
+// This is not part of coreMacros to disallow this macro from being implicitly invoked in Chisel
+// frontend (and generating source locators in Chisel core), which is almost certainly a bug.
+//
+// Note: While these functions and definitions are not private (macros can't be
+// private), these are NOT meant to be part of the public API (yet) and no
+// forward compatibility guarantees are made.
+// A future revision may stabilize the source locator API to allow library
+// writers to append source locator information at the point of a library
+// function invocation.
+
+package chisel.internal.sourceinfo
+
+import scala.language.experimental.macros
+import scala.reflect.macros.blackbox.Context
+
+/** Abstract base class for generalized source information.
+ */
+sealed trait SourceInfo
+
+sealed trait NoSourceInfo extends SourceInfo
+
+/** For when source info can't be generated because of a technical limitation, like for Reg because
+ * Scala macros don't support named or default arguments.
+ */
+case object UnlocatableSourceInfo extends NoSourceInfo
+
+/** For when source info isn't generated because the function is deprecated and we're lazy.
+ */
+case object DeprecatedSourceInfo extends NoSourceInfo
+
+/** For FIRRTL lines from a Scala source line.
+ */
+case class SourceLine(filename: String, line: Int, col: Int) extends SourceInfo
+
+/** Provides a macro that returns the source information at the invocation point.
+ */
+object SourceInfoMacro {
+ def generate_source_info(c: Context): c.Tree = {
+ import c.universe._
+ val p = c.enclosingPosition
+ q"_root_.chisel.internal.sourceinfo.SourceLine(${p.source.file.name}, ${p.line}, ${p.column})"
+ }
+}
+
+object SourceInfo {
+ implicit def materialize: SourceInfo = macro SourceInfoMacro.generate_source_info
+}
diff --git a/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala
new file mode 100644
index 00000000..70e9938b
--- /dev/null
+++ b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala
@@ -0,0 +1,190 @@
+// See LICENSE for license details.
+
+package chisel.internal.firrtl
+
+import chisel._
+import core._
+import chisel.internal._
+import chisel.internal.sourceinfo.{SourceInfo, NoSourceInfo}
+
+case class PrimOp(val name: String) {
+ override def toString: String = name
+}
+
+object PrimOp {
+ val AddOp = PrimOp("add")
+ val SubOp = PrimOp("sub")
+ val TailOp = PrimOp("tail")
+ val HeadOp = PrimOp("head")
+ val TimesOp = PrimOp("mul")
+ val DivideOp = PrimOp("div")
+ val RemOp = PrimOp("rem")
+ val ShiftLeftOp = PrimOp("shl")
+ val ShiftRightOp = PrimOp("shr")
+ val DynamicShiftLeftOp = PrimOp("dshl")
+ val DynamicShiftRightOp = PrimOp("dshr")
+ val BitAndOp = PrimOp("and")
+ val BitOrOp = PrimOp("or")
+ val BitXorOp = PrimOp("xor")
+ val BitNotOp = PrimOp("not")
+ val ConcatOp = PrimOp("cat")
+ val BitsExtractOp = PrimOp("bits")
+ val LessOp = PrimOp("lt")
+ val LessEqOp = PrimOp("leq")
+ val GreaterOp = PrimOp("gt")
+ val GreaterEqOp = PrimOp("geq")
+ val EqualOp = PrimOp("eq")
+ val PadOp = PrimOp("pad")
+ val NotEqualOp = PrimOp("neq")
+ val NegOp = PrimOp("neg")
+ val MultiplexOp = PrimOp("mux")
+ val XorReduceOp = PrimOp("xorr")
+ val ConvertOp = PrimOp("cvt")
+ val AsUIntOp = PrimOp("asUInt")
+ val AsSIntOp = PrimOp("asSInt")
+}
+
+abstract class Arg {
+ def fullName(ctx: Component): String = name
+ def name: String
+}
+
+case class Node(id: HasId) extends Arg {
+ override def fullName(ctx: Component): String = id.getRef.fullName(ctx)
+ def name: String = id.getRef.name
+}
+
+abstract class LitArg(val num: BigInt, widthArg: Width) extends Arg {
+ private[chisel] def forcedWidth = widthArg.known
+ private[chisel] def width: Width = if (forcedWidth) widthArg else Width(minWidth)
+
+ protected def minWidth: Int
+ if (forcedWidth) {
+ require(widthArg.get >= minWidth,
+ s"The literal value ${num} was elaborated with a specificed width of ${widthArg.get} bits, but at least ${minWidth} bits are required.")
+ }
+}
+
+case class ILit(n: BigInt) extends Arg {
+ def name: String = n.toString
+}
+
+case class ULit(n: BigInt, w: Width) extends LitArg(n, w) {
+ def name: String = "UInt" + width + "(\"h0" + num.toString(16) + "\")"
+ def minWidth: Int = 1 max n.bitLength
+
+ require(n >= 0, s"UInt literal ${n} is negative")
+}
+
+case class SLit(n: BigInt, w: Width) extends LitArg(n, w) {
+ def name: String = {
+ val unsigned = if (n < 0) (BigInt(1) << width.get) + n else n
+ s"asSInt(${ULit(unsigned, width).name})"
+ }
+ def minWidth: Int = 1 + n.bitLength
+}
+
+case class Ref(name: String) extends Arg
+case class ModuleIO(mod: Module, name: String) extends Arg {
+ override def fullName(ctx: Component): String =
+ if (mod eq ctx.id) name else s"${mod.getRef.name}.$name"
+}
+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: Arg) extends Arg {
+ def name: String = s"[$value]"
+ override def fullName(ctx: Component): String = s"${imm.fullName(ctx)}[${value.fullName(ctx)}]"
+}
+
+object Width {
+ def apply(x: Int): Width = KnownWidth(x)
+ def apply(): Width = UnknownWidth()
+}
+
+sealed abstract class Width {
+ type W = Int
+ def max(that: Width): Width = this.op(that, _ max _)
+ def + (that: Width): Width = this.op(that, _ + _)
+ def + (that: Int): Width = this.op(this, (a, b) => a + that)
+ def shiftRight(that: Int): Width = this.op(this, (a, b) => 0 max (a - that))
+ def dynamicShiftLeft(that: Width): Width =
+ this.op(that, (a, b) => a + (1 << b) - 1)
+
+ def known: Boolean
+ def get: W
+ protected def op(that: Width, f: (W, W) => W): Width
+}
+
+sealed case class UnknownWidth() extends Width {
+ def known: Boolean = false
+ def get: Int = None.get
+ def op(that: Width, f: (W, W) => W): Width = this
+ override def toString: String = ""
+}
+
+sealed case class KnownWidth(value: Int) extends Width {
+ require(value >= 0)
+ def known: Boolean = true
+ def get: Int = value
+ def op(that: Width, f: (W, W) => W): Width = that match {
+ case KnownWidth(x) => KnownWidth(f(value, x))
+ case _ => that
+ }
+ override def toString: String = s"<${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 {
+ def sourceInfo: SourceInfo
+}
+abstract class Definition extends Command {
+ def id: HasId
+ def name: String = id.getRef.name
+}
+case class DefPrim[T <: Data](sourceInfo: SourceInfo, id: T, op: PrimOp, args: Arg*) extends Definition
+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 DefMemPort[T <: Data](sourceInfo: SourceInfo, id: T, source: Node, dir: MemPortDirection, index: Arg, clock: Arg) extends Definition
+case class DefInstance(sourceInfo: SourceInfo, id: Module, ports: Seq[Port]) extends Definition
+case class WhenBegin(sourceInfo: SourceInfo, pred: Arg) extends Command
+case class WhenEnd(sourceInfo: SourceInfo) extends Command
+case class Connect(sourceInfo: SourceInfo, loc: Node, exp: Arg) extends Command
+case class BulkConnect(sourceInfo: SourceInfo, loc1: Node, loc2: Node) extends Command
+case class ConnectInit(sourceInfo: SourceInfo, loc: Node, exp: Arg) extends Command
+case class Stop(sourceInfo: SourceInfo, clk: Arg, ret: Int) extends Command
+case class Component(id: Module, name: String, ports: Seq[Port], commands: Seq[Command]) extends Arg
+case class Port(id: Data, dir: Direction)
+case class Printf(sourceInfo: SourceInfo, clk: Arg, formatIn: String, ids: Seq[Arg]) extends Command {
+ require(formatIn.forall(c => c.toInt > 0 && c.toInt < 128), "format strings must comprise non-null ASCII values")
+ def format: String = {
+ def escaped(x: Char) = {
+ require(x.toInt >= 0)
+ if (x == '"' || x == '\\') {
+ s"\\${x}"
+ } else if (x == '\n') {
+ "\\n"
+ } else {
+ require(x.toInt >= 32) // TODO \xNN once FIRRTL issue #59 is resolved
+ x
+ }
+ }
+ formatIn.map(escaped _).mkString
+ }
+}
+
+case class Circuit(name: String, components: Seq[Component])