summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala70
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Bits.scala149
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Data.scala143
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Module.scala2
-rw-r--r--src/main/scala/chisel3/package.scala45
-rw-r--r--src/main/scala/chisel3/util/Decoupled.scala14
-rw-r--r--src/test/scala/chiselTests/Module.scala2
-rw-r--r--src/test/scala/chiselTests/MultiAssign.scala19
-rw-r--r--src/test/scala/chiselTests/Reg.scala18
9 files changed, 284 insertions, 178 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala
index a453d5e0..1b49e163 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala
@@ -14,9 +14,9 @@ import chisel3.internal.sourceinfo.{SourceInfo, DeprecatedSourceInfo, VecTransfo
/** 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(_ + _)
+sealed abstract class Aggregate extends Data {
+ private[chisel3] def cloneTypeWidth(width: Width): this.type = cloneType
+ private[chisel3] def width: Width = flatten.map(_.width).reduce(_ + _)
}
object Vec {
@@ -105,28 +105,40 @@ object Vec {
* 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] {
+ extends Aggregate 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
+ /**
+ * sample_element 'tracks' all changes to the elements of self.
+ * For consistency, sample_element is always used for creating dynamically
+ * indexed ports and outputing the FIRRTL type.
+ *
+ * Needed specifically for the case when the Vec is length 0.
+ */
+ private[core] val sample_element: T = gen
+
+ // allElements current includes sample_element
+ // This is somewhat weird although I think the best course of action here is
+ // to deprecate allElements in favor of dispatched functions to Data or
+ // a pattern matched recursive descent
+ private[chisel3] final def allElements: Seq[Element] =
+ (sample_element +: self).flatMap(_.allElements)
/** 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
+ 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 := that.asInstanceOf[Data]
-
- override def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = that match {
- case _: Vec[_] => this connect that
- case _ => this badConnect that
- }
+ def <> (that: Vec[T])(implicit sourceInfo: SourceInfo): Unit = this bulkConnect that.asInstanceOf[Data]
/** Strong bulk connect, assigning elements in this Vec from elements in a Seq.
*
@@ -144,9 +156,17 @@ sealed class Vec[T <: Data] private (gen: => T, val length: Int)
/** Creates a dynamically indexed read or write accessor into the array.
*/
def apply(idx: UInt): T = {
- val x = gen
- x.setRef(this, idx)
- x
+ Binding.checkSynthesizable(idx ,s"'idx' ($idx)")
+ val port = sample_element.cloneType
+ port.setRef(this, idx) //TODO(twigg): This is a bit too magical
+
+ // Bind each element of port to being whatever the base type is
+ // Using the head element as the sample_element
+ for((port_elem, model_elem) <- port.allElements zip sample_element.allElements) {
+ port_elem.binding = model_elem.binding
+ }
+
+ port
}
/** Creates a statically indexed read or write accessor into the array.
@@ -162,8 +182,7 @@ sealed class Vec[T <: Data] private (gen: => T, val length: Int)
override def cloneType: this.type =
Vec(length, gen).asInstanceOf[this.type]
- private val t = gen
- private[chisel3] def toType: String = s"${t.toType}[$length]"
+ private[chisel3] def toType: String = s"${sample_element.toType}[$length]"
private[chisel3] lazy val flatten: IndexedSeq[Bits] =
(0 until length).flatMap(i => this.apply(i).flatten)
@@ -256,7 +275,7 @@ trait VecLike[T <: Data] extends collection.IndexedSeq[T] with HasId {
* 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) {
+class Bundle extends Aggregate {
private val _namespace = Builder.globalNamespace.child
// TODO: replace with better defined FIRRTL weak-connect operator
@@ -272,13 +291,6 @@ class Bundle extends Aggregate(NO_DIR) {
* 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:_*)
@@ -333,7 +345,7 @@ class Bundle extends Aggregate(NO_DIR) {
}
private[chisel3] def toType = {
def eltPort(elt: Data): String = {
- val flipStr = if (elt.isFlip) "flip " else ""
+ val flipStr: String = if(Data.isFlipped(elt)) "flip " else ""
s"${flipStr}${elt.getRef.name} : ${elt.toType}"
}
s"{${namedElts.reverse.map(e => eltPort(e._2)).mkString(", ")}}"
@@ -343,6 +355,8 @@ class Bundle extends Aggregate(NO_DIR) {
namedElts += name -> elt
private[chisel3] override def _onModuleClose: Unit = // scalastyle:ignore method.name
for ((name, elt) <- namedElts) { elt.setRef(this, _namespace.name(name)) }
+
+ private[chisel3] final def allElements: Seq[Element] = namedElts.flatMap(_._2.allElements)
override def cloneType : this.type = {
// If the user did not provide a cloneType method, try invoking one of
@@ -373,5 +387,5 @@ class Bundle extends Aggregate(NO_DIR) {
}
private[core] object Bundle {
- val keywords = List("flip", "asInput", "asOutput", "cloneType", "toBits", "newType")
+ val keywords = List("flip", "asInput", "asOutput", "cloneType", "toBits")
}
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala
index e6a4be71..b18a43d9 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala
@@ -14,13 +14,35 @@ import chisel3.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)
+abstract class Element(private[core] val width: Width) extends Data {
+ /**
+ * Elements can actually be bound to the hardware graph and thus must store
+ * that binding information.
+ */
+ private[this] var _binding: Binding = UnboundBinding(None)
+ // Define setter/getter pairing
+ // Can only bind something that has not yet been bound.
+ private[core] def binding_=(target: Binding): Unit = _binding match {
+ case UnboundBinding(_) => {
+ _binding = target
+ _binding
+ }
+ case _ => throw Binding.AlreadyBoundException(_binding.toString)
+ // Other checks should have caught this.
+ }
+ private[core] def binding = _binding
+
+ /** Return the binding for some bits. */
+ def dir: Direction = binding.direction.get
+
+ private[chisel3] final def allElements: Seq[Element] = Seq(this)
+}
/** 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) {
+sealed abstract class Bits(width: Width, override val litArg: Option[LitArg])
+ extends Element(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
@@ -31,8 +53,6 @@ sealed abstract class Bits(dirArg: Direction, width: Width, override val litArg:
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
@@ -52,7 +72,7 @@ sealed abstract class Bits(dirArg: Direction, width: Width, override val litArg:
case KnownWidth(x) => require(x >= n, s"Can't head($n) for width $x < $n")
case UnknownWidth() =>
}
- binop(sourceInfo, UInt(width = n), HeadOp, n)
+ binop(sourceInfo, UInt(Width(n)), HeadOp, n)
}
/** Returns the specified bit on this wire as a [[Bool]], statically
@@ -67,6 +87,7 @@ sealed abstract class Bits(dirArg: Direction, width: Width, override val litArg:
if (isLit()) {
Bool(((litValue() >> x.toInt) & 1) == 1)
} else {
+ Binding.checkSynthesizable(this, s"'this' ($this)")
pushOp(DefPrim(sourceInfo, Bool(), BitsExtractOp, this.ref, ILit(x), ILit(x)))
}
}
@@ -108,7 +129,8 @@ sealed abstract class Bits(dirArg: Direction, width: Width, override val litArg:
if (isLit()) {
UInt((litValue >> y) & ((BigInt(1) << w) - 1), w)
} else {
- pushOp(DefPrim(sourceInfo, UInt(width = w), BitsExtractOp, this.ref, ILit(x), ILit(y)))
+ Binding.checkSynthesizable(this, s"'this' ($this)")
+ pushOp(DefPrim(sourceInfo, UInt(Width(w)), BitsExtractOp, this.ref, ILit(x), ILit(y)))
}
}
@@ -118,17 +140,28 @@ sealed abstract class Bits(dirArg: Direction, width: Width, override val litArg:
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 =
+ private[core] def unop[T <: Data](sourceInfo: SourceInfo, dest: T, op: PrimOp): T = {
+ Binding.checkSynthesizable(this, s"'this' ($this)")
pushOp(DefPrim(sourceInfo, dest, op, this.ref))
- private[core] def binop[T <: Data](sourceInfo: SourceInfo, dest: T, op: PrimOp, other: BigInt): T =
+ }
+ private[core] def binop[T <: Data](sourceInfo: SourceInfo, dest: T, op: PrimOp, other: BigInt): T = {
+ Binding.checkSynthesizable(this, s"'this' ($this)")
pushOp(DefPrim(sourceInfo, dest, op, this.ref, ILit(other)))
- private[core] def binop[T <: Data](sourceInfo: SourceInfo, dest: T, op: PrimOp, other: Bits): T =
+ }
+ private[core] def binop[T <: Data](sourceInfo: SourceInfo, dest: T, op: PrimOp, other: Bits): T = {
+ Binding.checkSynthesizable(this, s"'this' ($this)")
+ Binding.checkSynthesizable(other, s"'other' ($other)")
pushOp(DefPrim(sourceInfo, dest, op, this.ref, other.ref))
-
- private[core] def compop(sourceInfo: SourceInfo, op: PrimOp, other: Bits): Bool =
+ }
+ private[core] def compop(sourceInfo: SourceInfo, op: PrimOp, other: Bits): Bool = {
+ Binding.checkSynthesizable(this, s"'this' ($this)")
+ Binding.checkSynthesizable(other, s"'other' ($other)")
pushOp(DefPrim(sourceInfo, Bool(), op, this.ref, other.ref))
- private[core] def redop(sourceInfo: SourceInfo, op: PrimOp): Bool =
+ }
+ private[core] def redop(sourceInfo: SourceInfo, op: PrimOp): Bool = {
+ Binding.checkSynthesizable(this, s"'this' ($this)")
pushOp(DefPrim(sourceInfo, Bool(), op, this.ref))
+ }
/** Returns this wire zero padded up to the specified width.
*
@@ -356,19 +389,19 @@ abstract trait Num[T <: Data] {
/** 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[core] def toType = s"UInt$width"
+sealed class UInt private[core] (width: Width, lit: Option[ULit] = None)
+ extends Bits(width, lit) with Num[UInt] {
- override private[chisel3] def fromInt(value: BigInt, width: Int): this.type =
- UInt(value, width).asInstanceOf[this.type]
+ if (lit != None) {
+ this.binding = LitBinding()
- override def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = that match {
- case _: UInt => this connect that
- case _ => this badConnect that
}
+ private[chisel3] override def cloneTypeWidth(w: Width): this.type =
+ new UInt(w).asInstanceOf[this.type]
+ private[chisel3] def toType = s"UInt$width"
+
+ override private[chisel3] def fromInt(value: BigInt, width: Int): this.type =
+ UInt(value, width).asInstanceOf[this.type]
// TODO: refactor to share documentation with Num or add independent scaladoc
final def unary_- (): UInt = macro SourceInfoTransform.noArg
@@ -442,7 +475,7 @@ sealed class UInt private[core] (dir: Direction, width: Width, lit: Option[ULit]
final def unary_! () : Bool = macro SourceInfoTransform.noArg
- def do_unary_! (implicit sourceInfo: SourceInfo) : Bool = this === Bits(0)
+ def do_unary_! (implicit sourceInfo: SourceInfo) : Bool = this === UInt(0, 1)
override def do_<< (that: Int)(implicit sourceInfo: SourceInfo): UInt =
binop(sourceInfo, UInt(this.width + that), ShiftLeftOp, that)
@@ -484,12 +517,11 @@ sealed class UInt private[core] (dir: Direction, width: Width, lit: Option[ULit]
// 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())
-
+ def apply(): UInt = apply(Width())
+ /** Create a UInt port with specified width. */
+ def apply(width: Width): UInt = new UInt(width)
+ /** Create a UInt with a specified width - compatibility with Chisel2. */
+ def apply(dummy: Option[Direction] = None, width: Int): UInt = apply(Width(width))
/** Create a UInt literal with inferred width. */
def apply(value: BigInt): UInt = apply(value, Width())
/** Create a UInt literal with fixed width. */
@@ -497,16 +529,13 @@ private[core] sealed trait UIntFactory {
/** 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))
+ val result = new UInt(lit.width, Some(lit))
+ // Bind result to being an Literal
+// result.binding = LitBinding()
+ result
}
private def parse(n: String) = {
@@ -533,16 +562,12 @@ private[core] sealed trait UIntFactory {
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[chisel3] def toType = s"SInt$width"
+sealed class SInt private (width: Width, lit: Option[SLit] = None)
+ extends Bits(width, lit) with Num[SInt] {
- override def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = that match {
- case _: SInt => this connect that
- case _ => this badConnect that
- }
+ private[chisel3] override def cloneTypeWidth(w: Width): this.type =
+ new SInt(w).asInstanceOf[this.type]
+ private[chisel3] def toType = s"SInt$width"
override private[chisel3] def fromInt(value: BigInt, width: Int): this.type =
SInt(value, width).asInstanceOf[this.type]
@@ -639,25 +664,24 @@ sealed class SInt private (dir: Direction, width: Width, lit: Option[SLit] = Non
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())
+ def apply(): SInt = apply(Width())
+ /** Create a SInt type or port with fixed width. */
+ def apply(width: Int): SInt = apply(Width(width))
+ /** Create an SInt type with specified width. */
+ def apply(width: Width): SInt = new SInt(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))
+ val result = new SInt(lit.width, Some(lit))
+ // Bind result to being an Literal
+ result.binding = LitBinding()
+ result
}
}
@@ -665,10 +689,10 @@ object SInt {
// 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 = {
+sealed class Bool(lit: Option[ULit] = None) extends UInt(Width(1), lit) {
+ private[chisel3] override def cloneTypeWidth(w: Width): this.type = {
require(!w.known || w.get == 1)
- new Bool(dir).asInstanceOf[this.type]
+ new Bool().asInstanceOf[this.type]
}
override private[chisel3] def fromInt(value: BigInt, width: Int): this.type = {
@@ -709,11 +733,11 @@ sealed class Bool(dir: Direction, lit: Option[ULit] = None) extends UInt(dir, Wi
object Bool {
/** Creates an empty Bool.
*/
- def apply(dir: Direction = NO_DIR): Bool = new Bool(dir)
+ def apply(): Bool = new Bool()
/** Creates Bool literal.
*/
- def apply(x: Boolean): Bool = new Bool(NO_DIR, Some(ULit(if (x) 1 else 0, Width(1))))
+ def apply(x: Boolean): Bool = new Bool(Some(ULit(if (x) 1 else 0, Width(1))))
}
object Mux {
@@ -742,6 +766,9 @@ object Mux {
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}")
+ Binding.checkSynthesizable(cond, s"'cond' ($cond)")
+ Binding.checkSynthesizable(con, s"'con' ($con)")
+ Binding.checkSynthesizable(alt, s"'alt' ($alt)")
val d = alt.cloneTypeWidth(con.width max alt.width)
pushOp(DefPrim(sourceInfo, d, MultiplexOp, cond.ref, con.ref, alt.ref))
}
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala
index fcdc86bb..4cc66cb5 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/Data.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/Data.scala
@@ -13,18 +13,69 @@ 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 }
+object Direction {
+ object Input extends Direction("input") { override def flip: Direction = Output }
+ object Output extends Direction("output") { override def flip: Direction = Input }
+}
@deprecated("debug doesn't do anything in Chisel3 as no pruning happens in the frontend", "chisel3")
object debug { // scalastyle:ignore object.name
def apply (arg: Data): Data = arg
}
-/** Mixing in this trait flips the direction of an Aggregate. */
-trait Flipped extends Data {
- this.overrideDirection(_.flip, !_)
+object DataMirror {
+ def widthOf(target: Data): Width = target.width
+}
+
+/**
+* Input, Output, and Flipped are used to define the directions of Module IOs.
+*
+* Note that they do not currently call target to be a newType or cloneType.
+* This is nominally for performance reasons to avoid too many extra copies when
+* something is flipped multiple times.
+*
+* Thus, an error will be thrown if these are used on bound Data
+*/
+object Input {
+ def apply[T<:Data](target: T): T =
+ Binding.bind(target, InputBinder, "Error: Cannot set as input ")
+}
+object Output {
+ def apply[T<:Data](target: T): T =
+ Binding.bind(target, OutputBinder, "Error: Cannot set as output ")
+}
+object Flipped {
+ def apply[T<:Data](target: T): T =
+ Binding.bind(target, FlippedBinder, "Error: Cannot flip ")
+}
+
+object Data {
+ /**
+ * This function returns true if the FIRRTL type of this Data should be flipped
+ * relative to other nodes.
+ *
+ * Note that the current scheme only applies Flip to Elements or Vec chains of
+ * Elements.
+ *
+ * A Bundle is never marked flip, instead preferring its root fields to be marked
+ *
+ * The Vec check is due to the fact that flip must be factored out of the vec, ie:
+ * must have flip field: Vec(UInt) instead of field: Vec(flip UInt)
+ */
+ private[chisel3] def isFlipped(target: Data): Boolean = target match {
+ case (element: Element) => element.binding.direction == Some(Direction.Input)
+ case (vec: Vec[Data @unchecked]) => isFlipped(vec.sample_element)
+ case (bundle: Bundle) => false
+ }
+
+ implicit class AddDirectionToData[T<:Data](val target: T) extends AnyVal {
+ @deprecated("Input(Data) should be used over Data.asInput", "gchisel")
+ def asInput: T = Input(target)
+ @deprecated("Output(Data) should be used over Data.asOutput", "gchisel")
+ def asOutput: T = Output(target)
+ @deprecated("Flipped(Data) should be used over Data.flip", "gchisel")
+ def flip(): T = Flipped(target)
+ }
}
/** This forms the root of the type system for wire data types. The data value
@@ -32,41 +83,45 @@ trait Flipped extends Data {
* 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, !_)
+abstract class Data extends HasId {
+ // Return ALL elements at root of this type.
+ // Contasts with flatten, which returns just Bits
+ private[chisel3] def allElements: Seq[Element]
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[chisel3] def connect(that: Data)(implicit sourceInfo: SourceInfo): Unit = {
+ Binding.checkSynthesizable(this, s"'this' ($this)")
+ Binding.checkSynthesizable(that, s"'that' ($that)")
+ try {
+ MonoConnect.connect(sourceInfo, this, that, Builder.forcedModule)
+ } catch {
+ case MonoConnect.MonoConnectException(message) =>
+ throwException(
+ s"Connection between sink ($this) and source ($that) failed @$message"
+ )
+ }
+ }
+ private[chisel3] def bulkConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = {
+ Binding.checkSynthesizable(this, s"'this' ($this)")
+ Binding.checkSynthesizable(that, s"'that' ($that)")
+ try {
+ BiConnect.connect(sourceInfo, this, that, Builder.forcedModule)
+ } catch {
+ case BiConnect.BiConnectException(message) =>
+ throwException(
+ s"Connection between left ($this) and source ($that) failed @$message"
+ )
+ }
+ }
+ private[chisel3] def lref: Node = Node(this)
private[chisel3] def ref: Arg = if (isLit) litArg.get else lref
- private[core] def cloneTypeWidth(width: Width): this.type
+ private[chisel3] def cloneTypeWidth(width: Width): this.type
private[chisel3] 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
+ final def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = this connect that
+ final def <> (that: Data)(implicit sourceInfo: SourceInfo): Unit = this bulkConnect that
def litArg(): Option[LitArg] = None
def litValue(): BigInt = litArg.get.num
def isLit(): Boolean = litArg.isDefined
@@ -134,28 +189,34 @@ object Wire {
def do_apply[T <: Data](t: T, init: T)(implicit sourceInfo: SourceInfo): T = {
val x = Reg.makeType(t, null.asInstanceOf[T], init)
+
+ // Bind each element of x to being a Wire
+ Binding.bind(x, WireBinder(Builder.forcedModule), "Error: t")
+
pushCommand(DefWire(sourceInfo, x))
pushCommand(DefInvalid(sourceInfo, x.ref))
if (init != null) {
+ Binding.checkSynthesizable(init, s"'init' ($init)")
x := init
}
+
x
}
}
object Clock {
- def apply(dir: Direction = NO_DIR): Clock = new Clock(dir)
+ def apply(): Clock = new Clock
}
// TODO: Document this.
-sealed class Clock(dirArg: Direction) extends Element(dirArg, Width(1)) {
- def cloneType: this.type = Clock(dirArg).asInstanceOf[this.type]
+sealed class Clock extends Element(Width(1)) {
+ def cloneType: this.type = Clock().asInstanceOf[this.type]
private[chisel3] override def flatten: IndexedSeq[Bits] = IndexedSeq()
- private[core] def cloneTypeWidth(width: Width): this.type = cloneType
+ private[chisel3] def cloneTypeWidth(width: Width): this.type = cloneType
private[chisel3] def toType = "Clock"
- override def := (that: Data)(implicit sourceInfo: SourceInfo): Unit = that match {
- case _: Clock => this connect that
- case _ => this badConnect that
+ override def connect (that: Data)(implicit sourceInfo: SourceInfo): Unit = that match {
+ case _: Clock => super.connect(that)(sourceInfo)
+ case _ => super.badConnect(that)(sourceInfo)
}
}
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Module.scala b/chiselFrontend/src/main/scala/chisel3/core/Module.scala
index 40102cd6..e8474e39 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/Module.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/Module.scala
@@ -91,7 +91,7 @@ extends HasId {
private[core] val _namespace = Builder.globalNamespace.child
private[chisel3] val _commands = ArrayBuffer[Command]()
- private[code] val _ids = ArrayBuffer[HasId]()
+ private[core] val _ids = ArrayBuffer[HasId]()
Builder.currentModule = Some(this)
/** Name of the instance. */
diff --git a/src/main/scala/chisel3/package.scala b/src/main/scala/chisel3/package.scala
index 35bbd1c4..71ec0e92 100644
--- a/src/main/scala/chisel3/package.scala
+++ b/src/main/scala/chisel3/package.scala
@@ -3,15 +3,21 @@ package object chisel3 {
import internal.firrtl.Width
import internal.sourceinfo.{SourceInfo, SourceInfoTransform}
-
- implicit class fromBigIntToLiteral(val x: BigInt) extends AnyVal {
- def U: UInt = UInt(x, Width())
- def S: SInt = SInt(x, Width())
import util.BitPat
type Direction = chisel3.core.Direction
+ object Input {
+ def apply[T<:Data](target: T): T = chisel3.core.Input(target)
+ }
+ object Output {
+ def apply[T<:Data](target: T): T = chisel3.core.Output(target)
+ }
+ object Flipped {
+ def apply[T<:Data](target: T): T = chisel3.core.Flipped(target)
+ }
+
type Data = chisel3.core.Data
val Wire = chisel3.core.Wire
val Clock = chisel3.core.Clock
@@ -63,30 +69,24 @@ package object chisel3 {
*
* Also provides .asBool to scala.Boolean and .asUInt to String
*
- * Note that, for stylistic reasons, one hould avoid extracting immediately
+ * Note that, for stylistic reasons, one should avoid extracting immediately
* after this call using apply, ie. 0.asUInt(1)(0) due to potential for
* confusion (the 1 is a bit length and the 0 is a bit extraction position).
* Prefer storing the result and then extracting from it.
*/
- implicit class addLiteraltoScalaInt(val target: Int) extends AnyVal {
- def asUInt() = UInt.Lit(target)
- def asSInt() = SInt.Lit(target)
- def asUInt(width: Int) = UInt.Lit(target, width)
- def asSInt(width: Int) = SInt.Lit(target, width)
-
- // These were recently added to chisel2/3 but are not to be used internally
- @deprecated("asUInt should be used over U", "gchisel")
- def U() = UInt.Lit(target)
- @deprecated("asSInt should be used over S", "gchisel")
- def S() = SInt.Lit(target)
- @deprecated("asUInt should be used over U", "gchisel")
- def U(width: Int) = UInt.Lit(target, width)
- @deprecated("asSInt should be used over S", "gchisel")
- def S(width: Int) = SInt.Lit(target, width)
- }
implicit class fromIntToLiteral(val x: Int) extends AnyVal {
def U: UInt = UInt(BigInt(x), Width())
def S: SInt = SInt(BigInt(x), Width())
+
+ def asUInt() = UInt(x, Width())
+ def asSInt() = SInt(x, Width())
+ def asUInt(width: Int) = UInt(x, width)
+ def asSInt(width: Int) = SInt(x, width)
+ }
+
+ implicit class fromBigIntToLiteral(val x: BigInt) extends AnyVal {
+ def U: UInt = UInt(x, Width())
+ def S: SInt = SInt(x, Width())
}
implicit class fromStringToLiteral(val x: String) extends AnyVal {
def U: UInt = UInt(x)
@@ -104,4 +104,7 @@ package object chisel3 {
def do_!= (that: BitPat)(implicit sourceInfo: SourceInfo): Bool = that != x
def do_=/= (that: BitPat)(implicit sourceInfo: SourceInfo): Bool = that =/= x
}
+
+ val INPUT = chisel3.core.Direction.Input
+ val OUTPUT = chisel3.core.Direction.Output
}
diff --git a/src/main/scala/chisel3/util/Decoupled.scala b/src/main/scala/chisel3/util/Decoupled.scala
index 73f58ed4..4a6b72e9 100644
--- a/src/main/scala/chisel3/util/Decoupled.scala
+++ b/src/main/scala/chisel3/util/Decoupled.scala
@@ -12,8 +12,8 @@ class DecoupledIO[+T <: Data](gen: T) extends Bundle
{
val ready = Input(Bool())
val valid = Output(Bool())
- val bits = Output(gen.newType)
- override protected def cloneType: this.type = DecoupledIO(gen).asInstanceOf[this.type]
+ val bits = Output(gen.cloneType)
+ override def cloneType: this.type = DecoupledIO(gen).asInstanceOf[this.type]
}
object DecoupledIO {
@@ -30,7 +30,7 @@ object DecoupledIO {
* @return dat.
*/
def enq(dat: T): T = {
- target.valid := true.asBool
+ target.valid := Bool(true)
target.bits := dat
dat
}
@@ -38,7 +38,7 @@ object DecoupledIO {
/** Indicate no enqueue occurs. Valid is set to false, and all bits are set to zero.
*/
def noenq(): Unit = {
- target.valid := false.asBool
+ target.valid := Bool(false)
target.bits := target.bits.fromBits(0.asUInt)
}
@@ -48,17 +48,17 @@ object DecoupledIO {
* @return the data for this device,
*/
def deq(): T = {
- target.ready := true.asBool
+ target.ready := Bool(true)
target.bits
}
/** Indicate no dequeue occurs. Ready is set to false
*/
def nodeq(): Unit = {
- target.ready := false.asBool
+ target.ready := Bool(false)
}
}
- override def cloneType: this.type = { new DeqIO(gen).asInstanceOf[this.type]; }
+// override def cloneType: this.type = { DeqIO(gen).asInstanceOf[this.type]; }
}
object EnqIO {
diff --git a/src/test/scala/chiselTests/Module.scala b/src/test/scala/chiselTests/Module.scala
index 7c0bc40e..f1608d5b 100644
--- a/src/test/scala/chiselTests/Module.scala
+++ b/src/test/scala/chiselTests/Module.scala
@@ -41,7 +41,7 @@ class ModuleVecTester(c: ModuleVec) extends Tester(c) {
class ModuleWire extends Module {
val io = IO(new SimpleIO)
- val inc = Wire(Module(new PlusOne).io.newType)
+ val inc = Wire(Module(new PlusOne).io.cloneType)
inc.in := io.in
io.out := inc.out
}
diff --git a/src/test/scala/chiselTests/MultiAssign.scala b/src/test/scala/chiselTests/MultiAssign.scala
index d5e9b998..fc6c5edc 100644
--- a/src/test/scala/chiselTests/MultiAssign.scala
+++ b/src/test/scala/chiselTests/MultiAssign.scala
@@ -12,29 +12,30 @@ class LastAssignTester() extends BasicTester {
val cnt = Counter(2)
val test = Wire(UInt(width=4))
- assert(test === UInt.Lit(7)) // allow read references before assign references
+ assert(test === 7.U) // allow read references before assign references
- test := UInt.Lit(13)
- assert(test === UInt.Lit(7)) // output value should be position-independent
+ test := 13.U
+ assert(test === 7.U) // output value should be position-independent
- test := UInt.Lit(7)
- assert(test === UInt.Lit(7)) // this obviously should work
+ test := 7.U
+ assert(test === 7.U) // this obviously should work
- when(cnt.value === UInt.Lit(1)) {
+ when(cnt.value === 1.U) {
stop()
}
}
class ReassignmentTester() extends BasicTester {
- val test = UInt.Lit(15)
- test := UInt.Lit(7)
+ val test = 15.U
+ test := 7.U
}
class MultiAssignSpec extends ChiselFlatSpec {
"The last assignment" should "be used when multiple assignments happen" in {
assertTesterPasses{ new LastAssignTester }
}
- "Reassignments to non-wire types" should "be disallowed" in {
+ intercept[chisel3.internal.ChiselException] {
+// "Reassignments to non-wire types" should "be disallowed" in {
assertTesterFails{ new ReassignmentTester }
}
}
diff --git a/src/test/scala/chiselTests/Reg.scala b/src/test/scala/chiselTests/Reg.scala
index 391dd7de..0caf6315 100644
--- a/src/test/scala/chiselTests/Reg.scala
+++ b/src/test/scala/chiselTests/Reg.scala
@@ -16,20 +16,20 @@ class RegSpec extends ChiselFlatSpec {
"A Reg" should "be of the same type and width as outType, if specified" in {
class RegOutTypeWidthTester extends BasicTester {
- val reg = Reg(t=UInt(width=2), next=UInt(width=3), init=UInt(20))
- reg.width.get should be (2)
+ val reg = Reg(t=UInt(width=2), next=Wire(UInt(width=3)), init=UInt(20))
+ reg.getWidth should be (2)
}
elaborate{ new RegOutTypeWidthTester }
}
"A Reg" should "be of unknown width if outType is not specified and width is not forced" in {
class RegUnknownWidthTester extends BasicTester {
- val reg1 = Reg(next=UInt(width=3), init=UInt(20))
- reg1.width.known should be (false)
- val reg2 = Reg(init=UInt(20))
- reg2.width.known should be (false)
- val reg3 = Reg(next=UInt(width=3), init=UInt(width=5))
- reg3.width.known should be (false)
+ val reg1 = Reg(next=Wire(UInt(width=3)), init=20.U)
+ DataMirror.widthOf(reg1).known should be (false)
+ val reg2 = Reg(init=20.U)
+ DataMirror.widthOf(reg2).known should be (false)
+ val reg3 = Reg(next=Wire(UInt(width=3)), init=5.U)
+ DataMirror.widthOf(reg3).known should be (false)
}
elaborate { new RegUnknownWidthTester }
}
@@ -37,7 +37,7 @@ class RegSpec extends ChiselFlatSpec {
"A Reg" should "be of width of init if outType and next are missing and init is a literal of forced width" in {
class RegForcedWidthTester extends BasicTester {
val reg2 = Reg(init=UInt(20, width=7))
- reg2.width.get should be (7)
+ reg2.getWidth should be (7)
}
elaborate{ new RegForcedWidthTester }
}