diff options
Diffstat (limited to 'chiselFrontend/src/main/scala/chisel3')
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/Aggregate.scala (renamed from chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala) | 33 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/Annotation.scala (renamed from chiselFrontend/src/main/scala/chisel3/core/Annotation.scala) | 5 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/Assert.scala (renamed from chiselFrontend/src/main/scala/chisel3/core/Assert.scala) | 2 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/Attach.scala (renamed from chiselFrontend/src/main/scala/chisel3/core/Attach.scala) | 6 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/Bits.scala (renamed from chiselFrontend/src/main/scala/chisel3/core/Bits.scala) | 948 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/BlackBox.scala (renamed from chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala) | 157 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/Clock.scala (renamed from chiselFrontend/src/main/scala/chisel3/core/Clock.scala) | 6 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/CompileOptions.scala (renamed from chiselFrontend/src/main/scala/chisel3/core/CompileOptions.scala) | 6 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/Data.scala (renamed from chiselFrontend/src/main/scala/chisel3/core/Data.scala) | 167 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/Mem.scala (renamed from chiselFrontend/src/main/scala/chisel3/core/Mem.scala) | 3 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/Module.scala | 365 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/MultiClock.scala (renamed from chiselFrontend/src/main/scala/chisel3/core/MultiClock.scala) | 2 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/Mux.scala (renamed from chiselFrontend/src/main/scala/chisel3/core/Mux.scala) | 5 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/Printable.scala (renamed from chiselFrontend/src/main/scala/chisel3/core/Printable.scala) | 3 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/Printf.scala (renamed from chiselFrontend/src/main/scala/chisel3/core/Printf.scala) | 2 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/RawModule.scala (renamed from chiselFrontend/src/main/scala/chisel3/core/RawModule.scala) | 14 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/Reg.scala (renamed from chiselFrontend/src/main/scala/chisel3/core/Reg.scala) | 31 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/SeqUtils.scala (renamed from chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala) | 3 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/StrongEnum.scala (renamed from chiselFrontend/src/main/scala/chisel3/core/StrongEnum.scala) | 21 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/When.scala (renamed from chiselFrontend/src/main/scala/chisel3/core/When.scala) | 2 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/core/Module.scala | 355 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/core/package.scala | 420 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/experimental/package.scala | 84 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/internal/BiConnect.scala (renamed from chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala) | 8 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/internal/Binding.scala (renamed from chiselFrontend/src/main/scala/chisel3/core/Binding.scala) | 30 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/internal/Builder.scala | 25 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/internal/Error.scala | 4 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/internal/MonoConnect.scala (renamed from chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala) | 8 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala | 4 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/package.scala | 359 |
30 files changed, 1879 insertions, 1199 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/Aggregate.scala index 7e3920eb..0db55344 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala +++ b/chiselFrontend/src/main/scala/chisel3/Aggregate.scala @@ -1,16 +1,17 @@ // See LICENSE for license details. -package chisel3.core +package chisel3 import scala.collection.immutable.ListMap -import scala.collection.mutable.{ArrayBuffer, HashSet, LinkedHashMap} +import scala.collection.mutable.{HashSet, LinkedHashMap} import scala.language.experimental.macros +import chisel3.experimental.BaseModule +import chisel3.experimental.BundleLiteralException import chisel3.internal._ import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl._ import chisel3.internal.sourceinfo._ -import chisel3.SourceInfoDoc class AliasedAggregateFieldException(message: String) extends ChiselException(message) @@ -18,7 +19,7 @@ class AliasedAggregateFieldException(message: String) extends ChiselException(me * of) other Data objects. */ sealed abstract class Aggregate extends Data { - private[chisel3] override def bind(target: Binding, parentDirection: SpecifiedDirection) { + private[chisel3] override def bind(target: Binding, parentDirection: SpecifiedDirection) { // scalastyle:ignore cyclomatic.complexity line.size.limit binding = target val resolvedDirection = SpecifiedDirection.fromParent(parentDirection, specifiedDirection) @@ -36,7 +37,7 @@ sealed abstract class Aggregate extends Data { case Some(dir) => dir case None => val childWithDirections = getElements zip getElements.map(_.direction) - throw Binding.MixedDirectionAggregateException( + throw MixedDirectionAggregateException( s"Aggregate '$this' can't have elements that are both directioned and undirectioned: $childWithDirections") } } @@ -48,7 +49,7 @@ sealed abstract class Aggregate extends Data { def getElements: Seq[Data] private[chisel3] def width: Width = getElements.map(_.width).foldLeft(0.W)(_ + _) - private[core] def legacyConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = { + private[chisel3] def legacyConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = { // If the source is a DontCare, generate a DefInvalid for the sink, // otherwise, issue a Connect. if (that == DontCare) { @@ -61,7 +62,7 @@ sealed abstract class Aggregate extends Data { override def do_asUInt(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = { SeqUtils.do_asUInt(flatten.map(_.asUInt())) } - private[core] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, + private[chisel3] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Unit = { var i = 0 val bits = WireDefault(UInt(this.width), that) // handles width padding @@ -93,7 +94,7 @@ trait VecFactory extends SourceInfoDoc { } /** Truncate an index to implement modulo-power-of-2 addressing. */ - private[core] def truncateIndex(idx: UInt, n: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = { // scalastyle:ignore line.size.limit + private[chisel3] def truncateIndex(idx: UInt, n: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = { // scalastyle:ignore line.size.limit // scalastyle:off if.brace val w = (n-1).bitLength if (n <= 1) 0.U @@ -104,7 +105,6 @@ trait VecFactory extends SourceInfoDoc { } } -object Vec extends VecFactory // scalastyle:off line.size.limit /** A vector (array) of [[Data]] elements. Provides hardware versions of various * collection transformation functions found in software array implementations. @@ -133,14 +133,14 @@ object Vec extends VecFactory * - Vecs, unlike classes in Scala's collection library, are propagated intact to FIRRTL as a vector type, which may make debugging easier */ // scalastyle:on line.size.limit -sealed class Vec[T <: Data] private[core] (gen: => T, val length: Int) +sealed class Vec[T <: Data] private[chisel3] (gen: => T, val length: Int) extends Aggregate with VecLike[T] { override def toString: String = { val elementType = sample_element.cloneType s"$elementType[$length]$bindingToString" } - private[core] override def typeEquivalent(that: Data): Boolean = that match { + private[chisel3] override def typeEquivalent(that: Data): Boolean = that match { case that: Vec[T] => this.length == that.length && (this.sample_element typeEquivalent that.sample_element) @@ -439,7 +439,7 @@ abstract class Record(private[chisel3] implicit val compileOptions: CompileOptio try { super.bind(target, parentDirection) } catch { // nasty compatibility mode shim, where anything flies - case e: Binding.MixedDirectionAggregateException if !compileOptions.dontAssumeDirectionality => + case e: MixedDirectionAggregateException if !compileOptions.dontAssumeDirectionality => val resolvedDirection = SpecifiedDirection.fromParent(parentDirection, specifiedDirection) direction = resolvedDirection match { case SpecifiedDirection.Unspecified => ActualDirection.Bidirectional(ActualDirection.Default) @@ -570,7 +570,7 @@ abstract class Record(private[chisel3] implicit val compileOptions: CompileOptio /** Name for Pretty Printing */ def className: String = this.getClass.getSimpleName - private[core] override def typeEquivalent(that: Data): Boolean = that match { + private[chisel3] override def typeEquivalent(that: Data): Boolean = that match { case that: Record => this.getClass == that.getClass && this.elements.size == that.elements.size && @@ -627,7 +627,12 @@ trait IgnoreSeqInBundle { } class AutoClonetypeException(message: String) extends ChiselException(message) -class BundleLiteralException(message: String) extends ChiselException(message) + +package experimental { + + class BundleLiteralException(message: String) extends ChiselException(message) + +} /** Base class for data types defined as a bundle of other data types. * diff --git a/chiselFrontend/src/main/scala/chisel3/core/Annotation.scala b/chiselFrontend/src/main/scala/chisel3/Annotation.scala index b7e82f63..506ec282 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Annotation.scala +++ b/chiselFrontend/src/main/scala/chisel3/Annotation.scala @@ -1,12 +1,13 @@ // See LICENSE for license details. -package chisel3.core +package chisel3.experimental import scala.language.existentials import chisel3.internal.{Builder, InstanceId} +import chisel3.{CompileOptions, Data} import firrtl.Transform -import firrtl.annotations.{Annotation, CircuitName, ComponentName, ModuleName} +import firrtl.annotations.Annotation import firrtl.transforms.{DontTouchAnnotation, NoDedupAnnotation} /** Interface for Annotations in Chisel diff --git a/chiselFrontend/src/main/scala/chisel3/core/Assert.scala b/chiselFrontend/src/main/scala/chisel3/Assert.scala index 054222c3..af58bce6 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Assert.scala +++ b/chiselFrontend/src/main/scala/chisel3/Assert.scala @@ -1,6 +1,6 @@ // See LICENSE for license details. -package chisel3.core +package chisel3 import scala.reflect.macros.blackbox.Context import scala.language.experimental.macros diff --git a/chiselFrontend/src/main/scala/chisel3/core/Attach.scala b/chiselFrontend/src/main/scala/chisel3/Attach.scala index 5fb89b18..1ceba7c2 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Attach.scala +++ b/chiselFrontend/src/main/scala/chisel3/Attach.scala @@ -1,11 +1,11 @@ // See LICENSE for license details. -package chisel3.core +package chisel3.experimental import chisel3.internal._ import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl._ -import chisel3.internal.sourceinfo.{SourceInfo} +import chisel3.internal.sourceinfo.SourceInfo object attach { // scalastyle:ignore object.name // Exceptions that can be generated by attach @@ -14,7 +14,7 @@ object attach { // scalastyle:ignore object.name AttachException(": Conditional attach is not allowed!") // Actual implementation - private[core] def impl(elts: Seq[Analog], contextModule: RawModule)(implicit sourceInfo: SourceInfo): Unit = { + private[chisel3] def impl(elts: Seq[Analog], contextModule: RawModule)(implicit sourceInfo: SourceInfo): Unit = { if (Builder.whenDepth != 0) throw ConditionalAttachException // TODO Check that references are valid and can be attached diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/Bits.scala index b18b27e5..2a8e8d1e 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala +++ b/chiselFrontend/src/main/scala/chisel3/Bits.scala @@ -1,10 +1,11 @@ // See LICENSE for license details. -package chisel3.core +package chisel3 import scala.language.experimental.macros import collection.mutable +import chisel3.experimental.{FixedPoint, RawModule} import chisel3.internal._ import chisel3.internal.Builder.{pushCommand, pushOp} import chisel3.internal.firrtl._ @@ -30,7 +31,7 @@ abstract class Element extends Data { direction = ActualDirection.fromSpecified(resolvedDirection) } - private[core] override def topBindingOpt: Option[TopBinding] = super.topBindingOpt match { + private[chisel3] override def topBindingOpt: Option[TopBinding] = super.topBindingOpt match { // Translate Bundle lit bindings to Element lit bindings case Some(BundleLitBinding(litMap)) => litMap.get(this) match { case Some(litArg) => Some(ElementLitBinding(litArg)) @@ -39,13 +40,13 @@ abstract class Element extends Data { case topBindingOpt => topBindingOpt } - private[core] def litArgOption: Option[LitArg] = topBindingOpt match { + private[chisel3] def litArgOption: Option[LitArg] = topBindingOpt match { case Some(ElementLitBinding(litArg)) => Some(litArg) case _ => None } override def litOption: Option[BigInt] = litArgOption.map(_.num) - private[core] def litIsForcedWidth: Option[Boolean] = litArgOption.map(_.forcedWidth) + private[chisel3] def litIsForcedWidth: Option[Boolean] = litArgOption.map(_.forcedWidth) // provide bits-specific literal handling functionality here override private[chisel3] def ref: Arg = topBindingOpt match { @@ -57,7 +58,7 @@ abstract class Element extends Data { case _ => super.ref } - private[core] def legacyConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = { + private[chisel3] def legacyConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = { // If the source is a DontCare, generate a DefInvalid for the sink, // otherwise, issue a Connect. if (that == DontCare) { @@ -107,7 +108,7 @@ sealed abstract class Bits(private[chisel3] val width: Width) extends Element wi // Arguments against: generates down to a FIRRTL UInt anyways // Only used for in a few cases, hopefully to be removed - private[core] def cloneTypeWidth(width: Width): this.type + private[chisel3] def cloneTypeWidth(width: Width): this.type def cloneType: this.type = cloneTypeWidth(width) @@ -240,25 +241,25 @@ sealed abstract class Bits(private[chisel3] val width: Width) extends Element wi final def do_apply(x: BigInt, y: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = apply(castToInt(x, "High index"), castToInt(y, "Low index")) - private[core] def unop[T <: Data](sourceInfo: SourceInfo, dest: T, op: PrimOp): T = { + private[chisel3] def unop[T <: Data](sourceInfo: SourceInfo, dest: T, op: PrimOp): T = { requireIsHardware(this, "bits operated on") pushOp(DefPrim(sourceInfo, dest, op, this.ref)) } - private[core] def binop[T <: Data](sourceInfo: SourceInfo, dest: T, op: PrimOp, other: BigInt): T = { + private[chisel3] def binop[T <: Data](sourceInfo: SourceInfo, dest: T, op: PrimOp, other: BigInt): T = { requireIsHardware(this, "bits operated on") 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[chisel3] def binop[T <: Data](sourceInfo: SourceInfo, dest: T, op: PrimOp, other: Bits): T = { requireIsHardware(this, "bits operated on") requireIsHardware(other, "bits operated on") pushOp(DefPrim(sourceInfo, dest, op, this.ref, other.ref)) } - private[core] def compop(sourceInfo: SourceInfo, op: PrimOp, other: Bits): Bool = { + private[chisel3] def compop(sourceInfo: SourceInfo, op: PrimOp, other: Bits): Bool = { requireIsHardware(this, "bits operated on") requireIsHardware(other, "bits operated on") pushOp(DefPrim(sourceInfo, Bool(), op, this.ref, other.ref)) } - private[core] def redop(sourceInfo: SourceInfo, op: PrimOp): Bool = { + private[chisel3] def redop(sourceInfo: SourceInfo, op: PrimOp): Bool = { requireIsHardware(this, "bits operated on") pushOp(DefPrim(sourceInfo, Bool(), op, this.ref)) } @@ -639,7 +640,7 @@ abstract trait Num[T <: Data] { * @define expandingWidth @note The width of the returned $coll is `width of this` + `1`. * @define constantWidth @note The width of the returned $coll is unchanged, i.e., `width of this`. */ -sealed class UInt private[core] (width: Width) extends Bits(width) with Num[UInt] { +sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[UInt] { override def toString: String = { val bindingString = litOption match { case Some(value) => s"($value)" @@ -648,10 +649,10 @@ sealed class UInt private[core] (width: Width) extends Bits(width) with Num[UInt s"UInt$width$bindingString" } - private[core] override def typeEquivalent(that: Data): Boolean = + private[chisel3] override def typeEquivalent(that: Data): Boolean = that.isInstanceOf[UInt] && this.width == that.width - private[core] override def cloneTypeWidth(w: Width): this.type = + private[chisel3] override def cloneTypeWidth(w: Width): this.type = new UInt(w).asInstanceOf[this.type] // TODO: refactor to share documentation with Num or add independent scaladoc @@ -916,7 +917,7 @@ sealed class UInt private[core] (width: Width) extends Bits(width) with Num[UInt } } - private[core] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, + private[chisel3] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Unit = { this := that.asUInt } @@ -926,7 +927,7 @@ sealed class UInt private[core] (width: Width) extends Bits(width) with Num[UInt } // This is currently a factory because both Bits and UInt inherit it. -trait UIntFactory { +trait UIntFactoryBase { /** Create a UInt type with inferred width. */ def apply(): UInt = apply(Width()) /** Create a UInt port with specified width. */ @@ -950,9 +951,6 @@ trait UIntFactory { } } -object UInt extends UIntFactory -object Bits extends UIntFactory - /** A data type for signed integers, represented as a binary bitvector. Defines arithmetic operations between other * integer types. * @@ -961,7 +959,7 @@ object Bits extends UIntFactory * @define expandingWidth @note The width of the returned $coll is `width of this` + `1`. * @define constantWidth @note The width of the returned $coll is unchanged, i.e., `width of this`. */ -sealed class SInt private[core] (width: Width) extends Bits(width) with Num[SInt] { +sealed class SInt private[chisel3] (width: Width) extends Bits(width) with Num[SInt] { override def toString: String = { val bindingString = litOption match { case Some(value) => s"($value)" @@ -970,10 +968,10 @@ sealed class SInt private[core] (width: Width) extends Bits(width) with Num[SInt s"SInt$width$bindingString" } - private[core] override def typeEquivalent(that: Data): Boolean = + private[chisel3] override def typeEquivalent(that: Data): Boolean = this.getClass == that.getClass && this.width == that.width // TODO: should this be true for unspecified widths? - private[core] override def cloneTypeWidth(w: Width): this.type = + private[chisel3] override def cloneTypeWidth(w: Width): this.type = new SInt(w).asInstanceOf[this.type] /** Unary negation (expanding width) @@ -1177,12 +1175,12 @@ sealed class SInt private[core] (width: Width) extends Bits(width) with Num[SInt } } - private[core] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) { + private[chisel3] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) { this := that.asSInt } } -trait SIntFactory { +trait SIntFactoryBase { /** Create an SInt type with inferred width. */ def apply(): SInt = apply(Width()) /** Create a SInt type or port with fixed width. */ @@ -1205,7 +1203,7 @@ trait SIntFactory { } } -object SInt extends SIntFactory +object SInt extends SIntFactoryBase sealed trait Reset extends Element with ToBoolable @@ -1225,7 +1223,7 @@ sealed class Bool() extends UInt(1.W) with Reset { s"Bool$bindingString" } - private[core] override def cloneTypeWidth(w: Width): this.type = { + private[chisel3] override def cloneTypeWidth(w: Width): this.type = { require(!w.known || w.get == 1) new Bool().asInstanceOf[this.type] } @@ -1285,7 +1283,7 @@ sealed class Bool() extends UInt(1.W) with Reset { * * @param that a hardware $coll * @return the lgocial or of this $coll and `that` - * @note this is equivalent to [[Bool!.|(that:chisel3\.core\.Bool)* Bool.|)]] + * @note this is equivalent to [[Bool!.|(that:chisel3\.Bool)* Bool.|)]] * @group Logical */ def || (that: Bool): Bool = macro SourceInfoTransform.thatArg @@ -1297,7 +1295,7 @@ sealed class Bool() extends UInt(1.W) with Reset { * * @param that a hardware $coll * @return the lgocial and of this $coll and `that` - * @note this is equivalent to [[Bool!.&(that:chisel3\.core\.Bool)* Bool.&]] + * @note this is equivalent to [[Bool!.&(that:chisel3\.Bool)* Bool.&]] * @group Logical */ def && (that: Bool): Bool = macro SourceInfoTransform.thatArg @@ -1312,7 +1310,7 @@ sealed class Bool() extends UInt(1.W) with Reset { def do_asClock(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Clock = pushOp(DefPrim(sourceInfo, Clock(), AsClockOp, ref)) } -trait BoolFactory { +trait BoolFactoryBase { /** Creates an empty Bool. */ def apply(): Bool = new Bool() @@ -1327,482 +1325,510 @@ trait BoolFactory { } } -object Bool extends BoolFactory - -//scalastyle:off number.of.methods -/** A sealed class representing a fixed point number that has a bit width and a binary point The width and binary point - * may be inferred. - * - * IMPORTANT: The API provided here is experimental and may change in the future. - * - * @param width bit width of the fixed point number - * @param binaryPoint the position of the binary point with respect to the right most bit of the width currently this - * should be positive but it is hoped to soon support negative points and thus use this field as a - * simple exponent - * @define coll [[FixedPoint]] - * @define numType $coll - * @define expandingWidth @note The width of the returned $coll is `width of this` + `1`. - * @define constantWidth @note The width of the returned $coll is unchanged, i.e., `width of this`. - */ -sealed class FixedPoint private (width: Width, val binaryPoint: BinaryPoint) - extends Bits(width) with Num[FixedPoint] { - override def toString: String = { - val bindingString = litToDoubleOption match { - case Some(value) => s"($value)" - case _ => bindingToString - } - s"FixedPoint$width$binaryPoint$bindingString" - } - - private[core] override def typeEquivalent(that: Data): Boolean = that match { - case that: FixedPoint => this.width == that.width && this.binaryPoint == that.binaryPoint // TODO: should this be true for unspecified widths? - case _ => false - } - - private[core] override def cloneTypeWidth(w: Width): this.type = - new FixedPoint(w, binaryPoint).asInstanceOf[this.type] - - override def connect (that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): Unit = that match { - case _: FixedPoint|DontCare => super.connect(that) - case _ => this badConnect that - } - - /** Convert to a [[scala.Option]] of [[scala.Boolean]] */ - def litToDoubleOption: Option[Double] = litOption.map { intVal => - val multiplier = math.pow(2, binaryPoint.get) - intVal.toDouble / multiplier - } - - /** Convert to a [[scala.Option]] */ - def litToDouble: Double = litToDoubleOption.get - - - /** Unary negation (expanding width) - * - * @return a hardware $coll equal to zero minus this $coll - * $expandingWidth - * @group Arithmetic - */ - final def unary_- (): FixedPoint = macro SourceInfoTransform.noArg +object Bool extends BoolFactoryBase - /** Unary negation (constant width) +package experimental { + //scalastyle:off number.of.methods + /** A sealed class representing a fixed point number that has a bit width and a binary point The width and binary point + * may be inferred. * - * @return a hardware $coll equal to zero minus `this` shifted right by one - * $constantWidth - * @group Arithmetic - */ - final def unary_-% (): FixedPoint = macro SourceInfoTransform.noArg - - /** @group SourceInfoTransformMacro */ - def unary_- (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = FixedPoint.fromBigInt(0) - this - /** @group SourceInfoTransformMacro */ - def unary_-% (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = FixedPoint.fromBigInt(0) -% this - - /** add (default - no growth) operator */ - override def do_+ (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = - this +% that - /** subtract (default - no growth) operator */ - override def do_- (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = - this -% that - override def do_* (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = - binop(sourceInfo, FixedPoint(this.width + that.width, this.binaryPoint + that.binaryPoint), TimesOp, that) - override def do_/ (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = - throwException(s"division is illegal on FixedPoint types") - override def do_% (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = - throwException(s"mod is illegal on FixedPoint types") - - - /** Multiplication operator + * IMPORTANT: The API provided here is experimental and may change in the future. * - * @param that a hardware [[UInt]] - * @return the product of this $coll and `that` - * $sumWidth - * $singleCycleMul - * @group Arithmetic + * @param width bit width of the fixed point number + * @param binaryPoint the position of the binary point with respect to the right most bit of the width currently this + * should be positive but it is hoped to soon support negative points and thus use this field as a + * simple exponent + * @define coll [[FixedPoint]] + * @define numType $coll + * @define expandingWidth @note The width of the returned $coll is `width of this` + `1`. + * @define constantWidth @note The width of the returned $coll is unchanged, i.e., `width of this`. */ - final def * (that: UInt): FixedPoint = macro SourceInfoTransform.thatArg - /** @group SourceInfoTransformMacro */ - def do_* (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = - binop(sourceInfo, FixedPoint(this.width + that.width, binaryPoint), TimesOp, that) + sealed class FixedPoint private(width: Width, val binaryPoint: BinaryPoint) + extends Bits(width) with Num[FixedPoint] { + import FixedPoint.Implicits._ + + override def toString: String = { + val bindingString = litToDoubleOption match { + case Some(value) => s"($value)" + case _ => bindingToString + } + s"FixedPoint$width$binaryPoint$bindingString" + } - /** Multiplication operator - * - * @param that a hardware [[SInt]] - * @return the product of this $coll and `that` - * $sumWidth - * $singleCycleMul - * @group Arithmetic - */ - final def * (that: SInt): FixedPoint = macro SourceInfoTransform.thatArg - /** @group SourceInfoTransformMacro */ - def do_* (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = - binop(sourceInfo, FixedPoint(this.width + that.width, binaryPoint), TimesOp, that) + private[chisel3] override def typeEquivalent(that: Data): Boolean = that match { + case that: FixedPoint => this.width == that.width && this.binaryPoint == that.binaryPoint // TODO: should this be true for unspecified widths? + case _ => false + } - /** Addition operator (expanding width) - * - * @param that a hardware $coll - * @return the sum of this $coll and `that` - * $maxWidthPlusOne - * @group Arithmetic - */ - final def +& (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + private[chisel3] override def cloneTypeWidth(w: Width): this.type = + new FixedPoint(w, binaryPoint).asInstanceOf[this.type] - /** Addition operator (constant width) - * - * @param that a hardware $coll - * @return the sum of this $coll and `that` shifted right by one - * $maxWidth - * @group Arithmetic - */ - final def +% (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + override def connect(that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): Unit = that match { + case _: FixedPoint|DontCare => super.connect(that) + case _ => this badConnect that + } - /** Subtraction operator (increasing width) - * - * @param that a hardware $coll - * @return the difference of this $coll less `that` - * $maxWidthPlusOne - * @group Arithmetic - */ - final def -& (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + /** Convert to a [[scala.Option]] of [[scala.Boolean]] */ + def litToDoubleOption: Option[Double] = litOption.map { intVal => + val multiplier = math.pow(2, binaryPoint.get) + intVal.toDouble / multiplier + } - /** Subtraction operator (constant width) - * - * @param that a hardware $coll - * @return the difference of this $coll less `that` shifted right by one - * $maxWidth - * @group Arithmetic - */ - final def -% (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + /** Convert to a [[scala.Option]] */ + def litToDouble: Double = litToDoubleOption.get + + + /** Unary negation (expanding width) + * + * @return a hardware $coll equal to zero minus this $coll + * $expandingWidth + * @group Arithmetic + */ + final def unary_- (): FixedPoint = macro SourceInfoTransform.noArg + + /** Unary negation (constant width) + * + * @return a hardware $coll equal to zero minus `this` shifted right by one + * $constantWidth + * @group Arithmetic + */ + final def unary_-% (): FixedPoint = macro SourceInfoTransform.noArg + + /** @group SourceInfoTransformMacro */ + def unary_- (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = FixedPoint.fromBigInt(0) - this + /** @group SourceInfoTransformMacro */ + def unary_-% (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = FixedPoint.fromBigInt(0) -% this + + /** add (default - no growth) operator */ + override def do_+ (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + this +% that + /** subtract (default - no growth) operator */ + override def do_- (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + this -% that + override def do_* (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + binop(sourceInfo, FixedPoint(this.width + that.width, this.binaryPoint + that.binaryPoint), TimesOp, that) + override def do_/ (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + throwException(s"division is illegal on FixedPoint types") + override def do_% (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + throwException(s"mod is illegal on FixedPoint types") + + + /** Multiplication operator + * + * @param that a hardware [[UInt]] + * @return the product of this $coll and `that` + * $sumWidth + * $singleCycleMul + * @group Arithmetic + */ + final def * (that: UInt): FixedPoint = macro SourceInfoTransform.thatArg + /** @group SourceInfoTransformMacro */ + def do_* (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + binop(sourceInfo, FixedPoint(this.width + that.width, binaryPoint), TimesOp, that) + + /** Multiplication operator + * + * @param that a hardware [[SInt]] + * @return the product of this $coll and `that` + * $sumWidth + * $singleCycleMul + * @group Arithmetic + */ + final def * (that: SInt): FixedPoint = macro SourceInfoTransform.thatArg + /** @group SourceInfoTransformMacro */ + def do_* (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + binop(sourceInfo, FixedPoint(this.width + that.width, binaryPoint), TimesOp, that) + + /** Addition operator (expanding width) + * + * @param that a hardware $coll + * @return the sum of this $coll and `that` + * $maxWidthPlusOne + * @group Arithmetic + */ + final def +& (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + + /** Addition operator (constant width) + * + * @param that a hardware $coll + * @return the sum of this $coll and `that` shifted right by one + * $maxWidth + * @group Arithmetic + */ + final def +% (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + + /** Subtraction operator (increasing width) + * + * @param that a hardware $coll + * @return the difference of this $coll less `that` + * $maxWidthPlusOne + * @group Arithmetic + */ + final def -& (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + + /** Subtraction operator (constant width) + * + * @param that a hardware $coll + * @return the difference of this $coll less `that` shifted right by one + * $maxWidth + * @group Arithmetic + */ + final def -% (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + + /** @group SourceInfoTransformMacro */ + def do_+& (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = { + (this.width, that.width, this.binaryPoint, that.binaryPoint) match { + case (KnownWidth(thisWidth), KnownWidth(thatWidth), KnownBinaryPoint(thisBP), KnownBinaryPoint(thatBP)) => + val thisIntWidth = thisWidth - thisBP + val thatIntWidth = thatWidth - thatBP + val newBinaryPoint = thisBP max thatBP + val newWidth = (thisIntWidth max thatIntWidth) + newBinaryPoint + 1 + binop(sourceInfo, FixedPoint(newWidth.W, newBinaryPoint.BP), AddOp, that) + case _ => + val newBinaryPoint = this.binaryPoint max that.binaryPoint + binop(sourceInfo, FixedPoint(UnknownWidth(), newBinaryPoint), AddOp, that) + } + } - /** @group SourceInfoTransformMacro */ - def do_+& (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = { - (this.width, that.width, this.binaryPoint, that.binaryPoint) match { - case (KnownWidth(thisWidth), KnownWidth(thatWidth), KnownBinaryPoint(thisBP), KnownBinaryPoint(thatBP)) => - val thisIntWidth = thisWidth - thisBP - val thatIntWidth = thatWidth - thatBP - val newBinaryPoint = thisBP max thatBP - val newWidth = (thisIntWidth max thatIntWidth) + newBinaryPoint + 1 - binop(sourceInfo, FixedPoint(newWidth.W, newBinaryPoint.BP), AddOp, that) - case _ => - val newBinaryPoint = this.binaryPoint max that.binaryPoint - binop(sourceInfo, FixedPoint(UnknownWidth(), newBinaryPoint), AddOp, that) + /** @group SourceInfoTransformMacro */ + def do_+% (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + (this +& that).tail(1).asFixedPoint(this.binaryPoint max that.binaryPoint) + /** @group SourceInfoTransformMacro */ + def do_-& (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = { + (this.width, that.width, this.binaryPoint, that.binaryPoint) match { + case (KnownWidth(thisWidth), KnownWidth(thatWidth), KnownBinaryPoint(thisBP), KnownBinaryPoint(thatBP)) => + val thisIntWidth = thisWidth - thisBP + val thatIntWidth = thatWidth - thatBP + val newBinaryPoint = thisBP max thatBP + val newWidth = (thisIntWidth max thatIntWidth) + newBinaryPoint + 1 + binop(sourceInfo, FixedPoint(newWidth.W, newBinaryPoint.BP), SubOp, that) + case _ => + val newBinaryPoint = this.binaryPoint max that.binaryPoint + binop(sourceInfo, FixedPoint(UnknownWidth(), newBinaryPoint), SubOp, that) + } } - } - /** @group SourceInfoTransformMacro */ - def do_+% (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = - (this +& that).tail(1).asFixedPoint(this.binaryPoint max that.binaryPoint) - /** @group SourceInfoTransformMacro */ - def do_-& (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = { - (this.width, that.width, this.binaryPoint, that.binaryPoint) match { - case (KnownWidth(thisWidth), KnownWidth(thatWidth), KnownBinaryPoint(thisBP), KnownBinaryPoint(thatBP)) => - val thisIntWidth = thisWidth - thisBP - val thatIntWidth = thatWidth - thatBP - val newBinaryPoint = thisBP max thatBP - val newWidth = (thisIntWidth max thatIntWidth) + newBinaryPoint + 1 - binop(sourceInfo, FixedPoint(newWidth.W, newBinaryPoint.BP), SubOp, that) + /** @group SourceInfoTransformMacro */ + def do_-% (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + (this -& that).tail(1).asFixedPoint(this.binaryPoint max that.binaryPoint) + + /** Bitwise and operator + * + * @param that a hardware $coll + * @return the bitwise and of this $coll and `that` + * $maxWidth + * @group Bitwise + */ + final def & (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + + /** Bitwise or operator + * + * @param that a hardware $coll + * @return the bitwise or of this $coll and `that` + * $maxWidth + * @group Bitwise + */ + final def | (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + + /** Bitwise exclusive or (xor) operator + * + * @param that a hardware $coll + * @return the bitwise xor of this $coll and `that` + * $maxWidth + * @group Bitwise + */ + final def ^ (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + + /** @group SourceInfoTransformMacro */ + def do_& (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + throwException(s"And is illegal between $this and $that") + /** @group SourceInfoTransformMacro */ + def do_| (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + throwException(s"Or is illegal between $this and $that") + /** @group SourceInfoTransformMacro */ + def do_^ (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + throwException(s"Xor is illegal between $this and $that") + + final def setBinaryPoint(that: Int): FixedPoint = macro SourceInfoTransform.thatArg + + /** @group SourceInfoTransformMacro */ + def do_setBinaryPoint(that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = this.binaryPoint match { + case KnownBinaryPoint(value) => + binop(sourceInfo, FixedPoint(this.width + (that - value), KnownBinaryPoint(that)), SetBinaryPoint, that) case _ => - val newBinaryPoint = this.binaryPoint max that.binaryPoint - binop(sourceInfo, FixedPoint(UnknownWidth(), newBinaryPoint), SubOp, that) + binop(sourceInfo, FixedPoint(UnknownWidth(), KnownBinaryPoint(that)), SetBinaryPoint, that) } - } - - /** @group SourceInfoTransformMacro */ - def do_-% (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = - (this -& that).tail(1).asFixedPoint(this.binaryPoint max that.binaryPoint) - - /** Bitwise and operator - * - * @param that a hardware $coll - * @return the bitwise and of this $coll and `that` - * $maxWidth - * @group Bitwise - */ - final def & (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg - /** Bitwise or operator - * - * @param that a hardware $coll - * @return the bitwise or of this $coll and `that` - * $maxWidth - * @group Bitwise - */ - final def | (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg - - /** Bitwise exclusive or (xor) operator - * - * @param that a hardware $coll - * @return the bitwise xor of this $coll and `that` - * $maxWidth - * @group Bitwise - */ - final def ^ (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg - - /** @group SourceInfoTransformMacro */ - def do_& (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = - throwException(s"And is illegal between $this and $that") - /** @group SourceInfoTransformMacro */ - def do_| (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = - throwException(s"Or is illegal between $this and $that") - /** @group SourceInfoTransformMacro */ - def do_^ (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = - throwException(s"Xor is illegal between $this and $that") + /** @group SourceInfoTransformMacro */ + def do_unary_~ (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + throwException(s"Not is illegal on $this") + + // TODO(chick): Consider comparison with UInt and SInt + override def do_< (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, LessOp, that) + override def do_> (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, GreaterOp, that) + override def do_<= (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, LessEqOp, that) + override def do_>= (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, GreaterEqOp, that) + + final def != (that: FixedPoint): Bool = macro SourceInfoTransform.thatArg + + /** Dynamic not equals operator + * + * @param that a hardware $coll + * @return a hardware [[Bool]] asserted if this $coll is not equal to `that` + * @group Comparison + */ + final def =/= (that: FixedPoint): Bool = macro SourceInfoTransform.thatArg + + /** Dynamic equals operator + * + * @param that a hardware $coll + * @return a hardware [[Bool]] asserted if this $coll is equal to `that` + * @group Comparison + */ + final def === (that: FixedPoint): Bool = macro SourceInfoTransform.thatArg + + /** @group SourceInfoTransformMacro */ + def do_!= (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, NotEqualOp, that) + /** @group SourceInfoTransformMacro */ + def do_=/= (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, NotEqualOp, that) + /** @group SourceInfoTransformMacro */ + def do_=== (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, EqualOp, that) + + def do_abs(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = { + // TODO: remove this once we have CompileOptions threaded through the macro system. + import chisel3.ExplicitCompileOptions.NotStrict + Mux(this < 0.F(0.BP), 0.F(0.BP) - this, this) + } - final def setBinaryPoint(that: Int): FixedPoint = macro SourceInfoTransform.thatArg + override def do_<< (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + binop(sourceInfo, FixedPoint(this.width + that, this.binaryPoint), ShiftLeftOp, validateShiftAmount(that)) + override def do_<< (that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + (this << castToInt(that, "Shift amount")).asFixedPoint(this.binaryPoint) + override def do_<< (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + binop(sourceInfo, FixedPoint(this.width.dynamicShiftLeft(that.width), this.binaryPoint), DynamicShiftLeftOp, that) + override def do_>> (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + binop(sourceInfo, FixedPoint(this.width.shiftRight(that), this.binaryPoint), ShiftRightOp, validateShiftAmount(that)) + override def do_>> (that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + (this >> castToInt(that, "Shift amount")).asFixedPoint(this.binaryPoint) + override def do_>> (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + binop(sourceInfo, FixedPoint(this.width, this.binaryPoint), DynamicShiftRightOp, that) + + override def do_asUInt(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = pushOp(DefPrim(sourceInfo, UInt(this.width), AsUIntOp, ref)) + override def do_asSInt(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = pushOp(DefPrim(sourceInfo, SInt(this.width), AsSIntOp, ref)) + + override def do_asFixedPoint(binaryPoint: BinaryPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = { + binaryPoint match { + case KnownBinaryPoint(value) => + val iLit = ILit(value) + pushOp(DefPrim(sourceInfo, FixedPoint(width, binaryPoint), AsFixedPointOp, ref, iLit)) + case _ => + throwException(s"cannot call $this.asFixedPoint(binaryPoint=$binaryPoint), you must specify a known binaryPoint") + } + } - /** @group SourceInfoTransformMacro */ - def do_setBinaryPoint(that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = this.binaryPoint match { - case KnownBinaryPoint(value) => - binop(sourceInfo, FixedPoint(this.width + (that - value), KnownBinaryPoint(that)), SetBinaryPoint, that) - case _ => - binop(sourceInfo, FixedPoint(UnknownWidth(), KnownBinaryPoint(that)), SetBinaryPoint, that) + private[chisel3] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) { + // TODO: redefine as just asFixedPoint on that, where FixedPoint.asFixedPoint just works. + this := (that match { + case fp: FixedPoint => fp.asSInt.asFixedPoint(this.binaryPoint) + case _ => that.asFixedPoint(this.binaryPoint) + }) + } + //TODO(chick): Consider "convert" as an arithmetic conversion to UInt/SInt } - /** @group SourceInfoTransformMacro */ - def do_unary_~ (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = - throwException(s"Not is illegal on $this") - - // TODO(chick): Consider comparison with UInt and SInt - override def do_< (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, LessOp, that) - override def do_> (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, GreaterOp, that) - override def do_<= (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, LessEqOp, that) - override def do_>= (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, GreaterEqOp, that) - - final def != (that: FixedPoint): Bool = macro SourceInfoTransform.thatArg - - /** Dynamic not equals operator - * - * @param that a hardware $coll - * @return a hardware [[Bool]] asserted if this $coll is not equal to `that` - * @group Comparison + /** Use PrivateObject to force users to specify width and binaryPoint by name */ - final def =/= (that: FixedPoint): Bool = macro SourceInfoTransform.thatArg + sealed trait PrivateType + private case object PrivateObject extends PrivateType - /** Dynamic equals operator - * - * @param that a hardware $coll - * @return a hardware [[Bool]] asserted if this $coll is equal to `that` - * @group Comparison + /** + * Factory and convenience methods for the FixedPoint class + * IMPORTANT: The API provided here is experimental and may change in the future. */ - final def === (that: FixedPoint): Bool = macro SourceInfoTransform.thatArg - - /** @group SourceInfoTransformMacro */ - def do_!= (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, NotEqualOp, that) - /** @group SourceInfoTransformMacro */ - def do_=/= (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, NotEqualOp, that) - /** @group SourceInfoTransformMacro */ - def do_=== (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, EqualOp, that) + object FixedPoint { - def do_abs(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = { - // TODO: remove this once we have CompileOptions threaded through the macro system. - import chisel3.core.ExplicitCompileOptions.NotStrict - Mux(this < 0.F(0.BP), 0.F(0.BP) - this, this) - } + import FixedPoint.Implicits._ + /** Create an FixedPoint type with inferred width. */ + def apply(): FixedPoint = apply(Width(), BinaryPoint()) - override def do_<< (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = - binop(sourceInfo, FixedPoint(this.width + that, this.binaryPoint), ShiftLeftOp, validateShiftAmount(that)) - override def do_<< (that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = - (this << castToInt(that, "Shift amount")).asFixedPoint(this.binaryPoint) - override def do_<< (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = - binop(sourceInfo, FixedPoint(this.width.dynamicShiftLeft(that.width), this.binaryPoint), DynamicShiftLeftOp, that) - override def do_>> (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = - binop(sourceInfo, FixedPoint(this.width.shiftRight(that), this.binaryPoint), ShiftRightOp, validateShiftAmount(that)) - override def do_>> (that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = - (this >> castToInt(that, "Shift amount")).asFixedPoint(this.binaryPoint) - override def do_>> (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = - binop(sourceInfo, FixedPoint(this.width, this.binaryPoint), DynamicShiftRightOp, that) + /** Create an FixedPoint type or port with fixed width. */ + @chiselRuntimeDeprecated + @deprecated("Use FixedPoint(width: Width, binaryPoint: BinaryPoint) example FixedPoint(16.W, 8.BP)", "chisel3") + def apply(width: Int, binaryPoint: Int): FixedPoint = apply(Width(width), BinaryPoint(binaryPoint)) - override def do_asUInt(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = pushOp(DefPrim(sourceInfo, UInt(this.width), AsUIntOp, ref)) - override def do_asSInt(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = pushOp(DefPrim(sourceInfo, SInt(this.width), AsSIntOp, ref)) + /** Create an FixedPoint type or port with fixed width. */ + def apply(width: Width, binaryPoint: BinaryPoint): FixedPoint = new FixedPoint(width, binaryPoint) - override def do_asFixedPoint(binaryPoint: BinaryPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = { - binaryPoint match { - case KnownBinaryPoint(value) => - val iLit = ILit(value) - pushOp(DefPrim(sourceInfo, FixedPoint(width, binaryPoint), AsFixedPointOp, ref, iLit)) - case _ => - throwException(s"cannot call $this.asFixedPoint(binaryPoint=$binaryPoint), you must specify a known binaryPoint") + /** Create an FixedPoint literal with inferred width from BigInt. + * Use PrivateObject to force users to specify width and binaryPoint by name + */ + def fromBigInt(value: BigInt, width: Width, binaryPoint: BinaryPoint): FixedPoint = { + apply(value, width, binaryPoint) } - } - - private[core] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) { - // TODO: redefine as just asFixedPoint on that, where FixedPoint.asFixedPoint just works. - this := (that match { - case fp: FixedPoint => fp.asSInt.asFixedPoint(this.binaryPoint) - case _ => that.asFixedPoint(this.binaryPoint) - }) - } - //TODO(chick): Consider "convert" as an arithmetic conversion to UInt/SInt -} - -/** Use PrivateObject to force users to specify width and binaryPoint by name - */ -sealed trait PrivateType -private case object PrivateObject extends PrivateType - -/** - * Factory and convenience methods for the FixedPoint class - * IMPORTANT: The API provided here is experimental and may change in the future. - */ -object FixedPoint { - /** Create an FixedPoint type with inferred width. */ - def apply(): FixedPoint = apply(Width(), BinaryPoint()) - - /** Create an FixedPoint type or port with fixed width. */ - @chiselRuntimeDeprecated - @deprecated("Use FixedPoint(width: Width, binaryPoint: BinaryPoint) example FixedPoint(16.W, 8.BP)", "chisel3") - def apply(width: Int, binaryPoint: Int): FixedPoint = apply(Width(width), BinaryPoint(binaryPoint)) - - /** Create an FixedPoint type or port with fixed width. */ - def apply(width: Width, binaryPoint: BinaryPoint): FixedPoint = new FixedPoint(width, binaryPoint) - - /** Create an FixedPoint literal with inferred width from BigInt. - * Use PrivateObject to force users to specify width and binaryPoint by name - */ - def fromBigInt(value: BigInt, width: Width, binaryPoint: BinaryPoint): FixedPoint = { - apply(value, width, binaryPoint) - } - /** Create an FixedPoint literal with inferred width from BigInt. - * Use PrivateObject to force users to specify width and binaryPoint by name - */ - def fromBigInt(value: BigInt, binaryPoint: BinaryPoint = 0.BP): FixedPoint = { - apply(value, Width(), binaryPoint) - } - /** Create an FixedPoint literal with inferred width from BigInt. - * Use PrivateObject to force users to specify width and binaryPoint by name - */ - def fromBigInt(value: BigInt, width: Int, binaryPoint: Int): FixedPoint = - if(width == -1) { - apply(value, Width(), BinaryPoint(binaryPoint)) + /** Create an FixedPoint literal with inferred width from BigInt. + * Use PrivateObject to force users to specify width and binaryPoint by name + */ + def fromBigInt(value: BigInt, binaryPoint: BinaryPoint = 0.BP): FixedPoint = { + apply(value, Width(), binaryPoint) } - else { - apply(value, Width(width), BinaryPoint(binaryPoint)) + /** Create an FixedPoint literal with inferred width from BigInt. + * Use PrivateObject to force users to specify width and binaryPoint by name + */ + def fromBigInt(value: BigInt, width: Int, binaryPoint: Int): FixedPoint = + if(width == -1) { + apply(value, Width(), BinaryPoint(binaryPoint)) + } + else { + apply(value, Width(width), BinaryPoint(binaryPoint)) + } + /** Create an FixedPoint literal with inferred width from Double. + * Use PrivateObject to force users to specify width and binaryPoint by name + */ + @chiselRuntimeDeprecated + @deprecated("use fromDouble(value: Double, width: Width, binaryPoint: BinaryPoint)", "chisel3") + def fromDouble(value: Double, dummy: PrivateType = PrivateObject, + width: Int = -1, binaryPoint: Int = 0): FixedPoint = { + fromBigInt( + toBigInt(value, binaryPoint), width = width, binaryPoint = binaryPoint + ) + } + /** Create an FixedPoint literal with inferred width from Double. + * Use PrivateObject to force users to specify width and binaryPoint by name + */ + def fromDouble(value: Double, width: Width, binaryPoint: BinaryPoint): FixedPoint = { + fromBigInt( + toBigInt(value, binaryPoint.get), width = width, binaryPoint = binaryPoint + ) } - /** Create an FixedPoint literal with inferred width from Double. - * Use PrivateObject to force users to specify width and binaryPoint by name - */ - @chiselRuntimeDeprecated - @deprecated("use fromDouble(value: Double, width: Width, binaryPoint: BinaryPoint)", "chisel3") - def fromDouble(value: Double, dummy: PrivateType = PrivateObject, - width: Int = -1, binaryPoint: Int = 0): FixedPoint = { - fromBigInt( - toBigInt(value, binaryPoint), width = width, binaryPoint = binaryPoint - ) - } - /** Create an FixedPoint literal with inferred width from Double. - * Use PrivateObject to force users to specify width and binaryPoint by name - */ - def fromDouble(value: Double, width: Width, binaryPoint: BinaryPoint): FixedPoint = { - fromBigInt( - toBigInt(value, binaryPoint.get), width = width, binaryPoint = binaryPoint - ) - } - /** Create an FixedPoint port with specified width and binary position. */ - def apply(value: BigInt, width: Width, binaryPoint: BinaryPoint): FixedPoint = { - val lit = FPLit(value, width, binaryPoint) - val newLiteral = new FixedPoint(lit.width, lit.binaryPoint) - // Ensure we have something capable of generating a name. - lit.bindLitArg(newLiteral) - } + /** Create an FixedPoint port with specified width and binary position. */ + def apply(value: BigInt, width: Width, binaryPoint: BinaryPoint): FixedPoint = { + val lit = FPLit(value, width, binaryPoint) + val newLiteral = new FixedPoint(lit.width, lit.binaryPoint) + // Ensure we have something capable of generating a name. + lit.bindLitArg(newLiteral) + } - /** - * How to create a bigint from a double with a specific binaryPoint - * @param x a double value - * @param binaryPoint a binaryPoint that you would like to use - * @return - */ - def toBigInt(x: Double, binaryPoint : Int): BigInt = { - val multiplier = math.pow(2,binaryPoint ) - val result = BigInt(math.round(x * multiplier)) - result - } + /** + * How to create a bigint from a double with a specific binaryPoint + * @param x a double value + * @param binaryPoint a binaryPoint that you would like to use + * @return + */ + def toBigInt(x: Double, binaryPoint: Int): BigInt = { + val multiplier = math.pow(2, binaryPoint) + val result = BigInt(math.round(x * multiplier)) + result + } - /** - * converts a bigInt with the given binaryPoint into the double representation - * @param i a bigint - * @param binaryPoint the implied binaryPoint of @i - * @return - */ - def toDouble(i: BigInt, binaryPoint : Int): Double = { - val multiplier = math.pow(2,binaryPoint) - val result = i.toDouble / multiplier - result - } + /** + * converts a bigInt with the given binaryPoint into the double representation + * @param i a bigint + * @param binaryPoint the implied binaryPoint of @i + * @return + */ + def toDouble(i: BigInt, binaryPoint: Int): Double = { + val multiplier = math.pow(2, binaryPoint) + val result = i.toDouble / multiplier + result + } -} + object Implicits { -/** Data type for representing bidirectional bitvectors of a given width - * - * Analog support is limited to allowing wiring up of Verilog BlackBoxes with bidirectional (inout) - * pins. There is currently no support for reading or writing of Analog types within Chisel code. - * - * Given that Analog is bidirectional, it is illegal to assign a direction to any Analog type. It - * is legal to "flip" the direction (since Analog can be a member of aggregate types) which has no - * effect. - * - * Analog types are generally connected using the bidirectional [[attach]] mechanism, but also - * support limited bulkconnect `<>`. Analog types are only allowed to be bulk connected *once* in a - * given module. This is to prevent any surprising consequences of last connect semantics. - * - * @note This API is experimental and subject to change - */ -final class Analog private (private[chisel3] val width: Width) extends Element { - require(width.known, "Since Analog is only for use in BlackBoxes, width must be known") + // implicit class fromDoubleToLiteral(val double: Double) extends AnyVal { + implicit class fromDoubleToLiteral(double: Double) { + @deprecated("Use notation <double>.F(<binary_point>.BP) instead", "chisel3") + def F(binaryPoint: Int): FixedPoint = FixedPoint.fromDouble(double, binaryPoint = binaryPoint) - override def toString: String = { - s"Analog$width$bindingToString" - } + def F(binaryPoint: BinaryPoint): FixedPoint = { + FixedPoint.fromDouble(double, Width(), binaryPoint) + } - private[core] override def typeEquivalent(that: Data): Boolean = - that.isInstanceOf[Analog] && this.width == that.width + def F(width: Width, binaryPoint: BinaryPoint): FixedPoint = { + FixedPoint.fromDouble(double, width, binaryPoint) + } + } - override def litOption: Option[BigInt] = None + // implicit class fromIntToBinaryPoint(val int: Int) extends AnyVal { + implicit class fromIntToBinaryPoint(int: Int) { + def BP: BinaryPoint = BinaryPoint(int) // scalastyle:ignore method.name + } - def cloneType: this.type = new Analog(width).asInstanceOf[this.type] + } - // Used to enforce single bulk connect of Analog types, multi-attach is still okay - // Note that this really means 1 bulk connect per Module because a port can - // be connected in the parent module as well - private[core] val biConnectLocs = mutable.Map.empty[RawModule, SourceInfo] + } + /** Data type for representing bidirectional bitvectors of a given width + * + * Analog support is limited to allowing wiring up of Verilog BlackBoxes with bidirectional (inout) + * pins. There is currently no support for reading or writing of Analog types within Chisel code. + * + * Given that Analog is bidirectional, it is illegal to assign a direction to any Analog type. It + * is legal to "flip" the direction (since Analog can be a member of aggregate types) which has no + * effect. + * + * Analog types are generally connected using the bidirectional [[attach]] mechanism, but also + * support limited bulkconnect `<>`. Analog types are only allowed to be bulk connected *once* in a + * given module. This is to prevent any surprising consequences of last connect semantics. + * + * @note This API is experimental and subject to change + */ + final class Analog private (private[chisel3] val width: Width) extends Element { + require(width.known, "Since Analog is only for use in BlackBoxes, width must be known") - // Define setter/getter pairing - // Analog can only be bound to Ports and Wires (and Unbound) - private[chisel3] override def bind(target: Binding, parentDirection: SpecifiedDirection) { - SpecifiedDirection.fromParent(parentDirection, specifiedDirection) match { - case SpecifiedDirection.Unspecified | SpecifiedDirection.Flip => - case x => throwException(s"Analog may not have explicit direction, got '$x'") - } - val targetTopBinding = target match { - case target: TopBinding => target - case ChildBinding(parent) => parent.topBinding - // See https://github.com/freechipsproject/chisel3/pull/946 - case SampleElementBinding(parent) => parent.topBinding + override def toString: String = { + s"Analog$width$bindingToString" } - // Analog counts as different directions based on binding context - targetTopBinding match { - case WireBinding(_) => direction = ActualDirection.Unspecified // internal wire - case PortBinding(_) => direction = ActualDirection.Bidirectional(ActualDirection.Default) - case x => throwException(s"Analog can only be Ports and Wires, not '$x'") + private[chisel3] override def typeEquivalent(that: Data): Boolean = + that.isInstanceOf[Analog] && this.width == that.width + + override def litOption: Option[BigInt] = None + + def cloneType: this.type = new Analog(width).asInstanceOf[this.type] + + // Used to enforce single bulk connect of Analog types, multi-attach is still okay + // Note that this really means 1 bulk connect per Module because a port can + // be connected in the parent module as well + private[chisel3] val biConnectLocs = mutable.Map.empty[RawModule, SourceInfo] + + // Define setter/getter pairing + // Analog can only be bound to Ports and Wires (and Unbound) + private[chisel3] override def bind(target: Binding, parentDirection: SpecifiedDirection) { + SpecifiedDirection.fromParent(parentDirection, specifiedDirection) match { + case SpecifiedDirection.Unspecified | SpecifiedDirection.Flip => + case x => throwException(s"Analog may not have explicit direction, got '$x'") + } + val targetTopBinding = target match { + case target: TopBinding => target + case ChildBinding(parent) => parent.topBinding + // See https://github.com/freechipsproject/chisel3/pull/946 + case SampleElementBinding(parent) => parent.topBinding + } + + // Analog counts as different directions based on binding context + targetTopBinding match { + case WireBinding(_) => direction = ActualDirection.Unspecified // internal wire + case PortBinding(_) => direction = ActualDirection.Bidirectional(ActualDirection.Default) + case x => throwException(s"Analog can only be Ports and Wires, not '$x'") + } + binding = target } - binding = target - } - override def do_asUInt(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = - throwException("Analog does not support asUInt") + override def do_asUInt(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + throwException("Analog does not support asUInt") - private[core] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, - compileOptions: CompileOptions): Unit = { - throwException("Analog does not support connectFromBits") - } + private[chisel3] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions): Unit = { + throwException("Analog does not support connectFromBits") + } - final def toPrintable: Printable = PString("Analog") -} -/** Object that provides factory methods for [[Analog]] objects - * - * @note This API is experimental and subject to change - */ -object Analog { - def apply(width: Width): Analog = new Analog(width) + final def toPrintable: Printable = PString("Analog") + } + /** Object that provides factory methods for [[Analog]] objects + * + * @note This API is experimental and subject to change + */ + object Analog { + def apply(width: Width): Analog = new Analog(width) + } } diff --git a/chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala b/chiselFrontend/src/main/scala/chisel3/BlackBox.scala index e8dc2bfe..f29962d7 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala +++ b/chiselFrontend/src/main/scala/chisel3/BlackBox.scala @@ -1,89 +1,98 @@ // See LICENSE for license details. -package chisel3.core +package chisel3 +import chisel3.experimental.{BaseModule, Param} +import chisel3.internal.BaseBlackBox import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl._ import chisel3.internal.throwException import chisel3.internal.sourceinfo.{SourceInfo, UnlocatableSourceInfo} -/** Parameters for BlackBoxes */ -sealed abstract class Param -case class IntParam(value: BigInt) extends Param -case class DoubleParam(value: Double) extends Param -case class StringParam(value: String) extends Param -/** Unquoted String */ -case class RawParam(value: String) extends Param +package internal { -abstract class BaseBlackBox extends BaseModule + private[chisel3] abstract class BaseBlackBox extends BaseModule -/** 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. - * - * A variant of BlackBox, this has a more consistent naming scheme in allowing - * multiple top-level IO and does not drop the top prefix. - * - * @example - * Some design require a differential input clock to clock the all design. - * With the xilinx FPGA for example, a Verilog template named IBUFDS must be - * integrated to use differential input: - * {{{ - * IBUFDS #(.DIFF_TERM("TRUE"), - * .IOSTANDARD("DEFAULT")) ibufds ( - * .IB(ibufds_IB), - * .I(ibufds_I), - * .O(ibufds_O) - * ); - * }}} - * - * To instantiate it, a BlackBox can be used like following: - * {{{ - * import chisel3._ - * import chisel3.experimental._ - * - * // Example with Xilinx differential buffer IBUFDS - * class IBUFDS extends ExtModule(Map("DIFF_TERM" -> "TRUE", // Verilog parameters - * "IOSTANDARD" -> "DEFAULT" - * )) { - * val O = IO(Output(Clock())) - * val I = IO(Input(Clock())) - * val IB = IO(Input(Clock())) - * } - * }}} - * @note The parameters API is experimental and may change - */ -abstract class ExtModule(val params: Map[String, Param] = Map.empty[String, Param]) extends BaseBlackBox { - private[core] override def generateComponent(): Component = { - require(!_closed, "Can't generate module more than once") - _closed = true - - val names = nameIds(classOf[ExtModule]) - - // Name ports based on reflection - for (port <- getModulePorts) { - require(names.contains(port), s"Unable to name port $port in $this") - port.setRef(ModuleIO(this, _namespace.name(names(port)))) - } +} - // All suggestions are in, force names to every node. - // While BlackBoxes are not supposed to have an implementation, we still need to call - // _onModuleClose on all nodes (for example, Aggregates use it for recursive naming). - for (id <- getIds) { - id._onModuleClose +package experimental { + + /** Parameters for BlackBoxes */ + sealed abstract class Param + case class IntParam(value: BigInt) extends Param + case class DoubleParam(value: Double) extends Param + case class StringParam(value: String) extends Param + /** Unquoted String */ + case class RawParam(value: String) extends Param + + /** 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. + * + * A variant of BlackBox, this has a more consistent naming scheme in allowing + * multiple top-level IO and does not drop the top prefix. + * + * @example + * Some design require a differential input clock to clock the all design. + * With the xilinx FPGA for example, a Verilog template named IBUFDS must be + * integrated to use differential input: + * {{{ + * IBUFDS #(.DIFF_TERM("TRUE"), + * .IOSTANDARD("DEFAULT")) ibufds ( + * .IB(ibufds_IB), + * .I(ibufds_I), + * .O(ibufds_O) + * ); + * }}} + * + * To instantiate it, a BlackBox can be used like following: + * {{{ + * import chisel3._ + * import chisel3.experimental._ + * + * // Example with Xilinx differential buffer IBUFDS + * class IBUFDS extends ExtModule(Map("DIFF_TERM" -> "TRUE", // Verilog parameters + * "IOSTANDARD" -> "DEFAULT" + * )) { + * val O = IO(Output(Clock())) + * val I = IO(Input(Clock())) + * val IB = IO(Input(Clock())) + * } + * }}} + * @note The parameters API is experimental and may change + */ + abstract class ExtModule(val params: Map[String, Param] = Map.empty[String, Param]) extends BaseBlackBox { + private[chisel3] override def generateComponent(): Component = { + require(!_closed, "Can't generate module more than once") + _closed = true + + val names = nameIds(classOf[ExtModule]) + + // Name ports based on reflection + for (port <- getModulePorts) { + require(names.contains(port), s"Unable to name port $port in $this") + port.setRef(ModuleIO(this, _namespace.name(names(port)))) + } + + // All suggestions are in, force names to every node. + // While BlackBoxes are not supposed to have an implementation, we still need to call + // _onModuleClose on all nodes (for example, Aggregates use it for recursive naming). + for (id <- getIds) { + id._onModuleClose + } + + val firrtlPorts = getModulePorts map {port => Port(port, port.specifiedDirection)} + val component = DefBlackBox(this, name, firrtlPorts, SpecifiedDirection.Unspecified, params) + _component = Some(component) + component } - val firrtlPorts = getModulePorts map {port => Port(port, port.specifiedDirection)} - val component = DefBlackBox(this, name, firrtlPorts, SpecifiedDirection.Unspecified, params) - _component = Some(component) - component - } - - private[core] def initializeInParent(parentCompileOptions: CompileOptions): Unit = { - implicit val sourceInfo = UnlocatableSourceInfo + private[chisel3] def initializeInParent(parentCompileOptions: CompileOptions): Unit = { + implicit val sourceInfo = UnlocatableSourceInfo - for (x <- getModulePorts) { - pushCommand(DefInvalid(sourceInfo, x.ref)) + for (x <- getModulePorts) { + pushCommand(DefInvalid(sourceInfo, x.ref)) + } } } } @@ -129,7 +138,7 @@ abstract class BlackBox(val params: Map[String, Param] = Map.empty[String, Param // Allow access to bindings from the compatibility package protected def _compatIoPortBound() = portsContains(io) // scalastyle:ignore method.name - private[core] override def generateComponent(): Component = { + private[chisel3] override def generateComponent(): Component = { _compatAutoWrapPorts() // pre-IO(...) compatibility hack // Restrict IO to just io, clock, and reset @@ -164,7 +173,7 @@ abstract class BlackBox(val params: Map[String, Param] = Map.empty[String, Param component } - private[core] def initializeInParent(parentCompileOptions: CompileOptions): Unit = { + private[chisel3] def initializeInParent(parentCompileOptions: CompileOptions): Unit = { for ((_, port) <- io.elements) { pushCommand(DefInvalid(UnlocatableSourceInfo, port.ref)) } diff --git a/chiselFrontend/src/main/scala/chisel3/core/Clock.scala b/chiselFrontend/src/main/scala/chisel3/Clock.scala index 364ac5aa..7e530cdf 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Clock.scala +++ b/chiselFrontend/src/main/scala/chisel3/Clock.scala @@ -1,6 +1,6 @@ // See LICENSE for license details. -package chisel3.core +package chisel3 import chisel3.internal.Builder.{pushOp} import chisel3.internal.firrtl._ @@ -17,7 +17,7 @@ sealed class Clock(private[chisel3] val width: Width = Width(1)) extends Element def cloneType: this.type = Clock().asInstanceOf[this.type] - private[core] def typeEquivalent(that: Data): Boolean = + private[chisel3] def typeEquivalent(that: Data): Boolean = this.getClass == that.getClass override def connect(that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): Unit = that match { // scalastyle:ignore line.size.limit @@ -31,7 +31,7 @@ sealed class Clock(private[chisel3] val width: Width = Width(1)) extends Element def toPrintable: Printable = PString("CLOCK") override def do_asUInt(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): UInt = pushOp(DefPrim(sourceInfo, UInt(this.width), AsUIntOp, ref)) // scalastyle:ignore line.size.limit - private[core] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, + private[chisel3] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Unit = { this := that } diff --git a/chiselFrontend/src/main/scala/chisel3/core/CompileOptions.scala b/chiselFrontend/src/main/scala/chisel3/CompileOptions.scala index a2f94e51..33a41b72 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/CompileOptions.scala +++ b/chiselFrontend/src/main/scala/chisel3/CompileOptions.scala @@ -1,6 +1,6 @@ // See LICENSE for license details. -package chisel3.core +package chisel3 import scala.language.experimental.macros import scala.reflect.macros.blackbox.Context @@ -29,7 +29,7 @@ object CompileOptions { def materialize_impl(c: Context): c.Tree = { import c.universe._ - q"_root_.chisel3.core.ExplicitCompileOptions.Strict" + q"_root_.chisel3.ExplicitCompileOptions.Strict" } } @@ -53,7 +53,6 @@ object ExplicitCompileOptions { // Collection of "not strict" connection compile options. // These provide compatibility with existing code. - // import chisel3.core.ExplicitCompileOptions.NotStrict implicit val NotStrict = new CompileOptionsClass ( connectFieldsMustMatch = false, declaredTypeMustBeUnbound = false, @@ -64,7 +63,6 @@ object ExplicitCompileOptions { ) // Collection of "strict" connection compile options, preferred for new code. - // import chisel3.core.ExplicitCompileOptions.Strict implicit val Strict = new CompileOptionsClass ( connectFieldsMustMatch = true, declaredTypeMustBeUnbound = true, diff --git a/chiselFrontend/src/main/scala/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/Data.scala index 3ce79786..7534c01a 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Data.scala +++ b/chiselFrontend/src/main/scala/chisel3/Data.scala @@ -1,15 +1,14 @@ // See LICENSE for license details. -package chisel3.core +package chisel3 import scala.language.experimental.macros +import chisel3.experimental.{Analog, DataMirror, FixedPoint} +import chisel3.internal.Builder.pushCommand import chisel3.internal._ -import chisel3.internal.Builder.{pushCommand, pushOp} import chisel3.internal.firrtl._ import chisel3.internal.sourceinfo.{SourceInfo, SourceInfoTransform, UnlocatableSourceInfo, DeprecatedSourceInfo} -import chisel3.SourceInfoDoc -import chisel3.core.BiConnect.DontCareCantBeSink /** User-specified directions. */ @@ -117,39 +116,42 @@ object debug { // scalastyle:ignore object.name def apply (arg: Data): Data = arg } -/** Experimental hardware construction reflection API - */ -object DataMirror { - def widthOf(target: Data): Width = target.width - def specifiedDirectionOf(target: Data): SpecifiedDirection = target.specifiedDirection - def directionOf(target: Data): ActualDirection = { - requireIsHardware(target, "node requested directionality on") - target.direction - } +package experimental { - // Returns the top-level module ports - // TODO: maybe move to something like Driver or DriverUtils, since this is mainly for interacting - // with compiled artifacts (vs. elaboration-time reflection)? - def modulePorts(target: BaseModule): Seq[(String, Data)] = target.getChiselPorts - - // Returns all module ports with underscore-qualified names - def fullModulePorts(target: BaseModule): Seq[(String, Data)] = { - def getPortNames(name: String, data: Data): Seq[(String, Data)] = Seq(name -> data) ++ (data match { - case _: Element => Seq() - case r: Record => r.elements.toSeq flatMap { case (eltName, elt) => getPortNames(s"${name}_${eltName}", elt) } - case v: Vec[_] => v.zipWithIndex flatMap { case (elt, index) => getPortNames(s"${name}_${index}", elt) } - }) - modulePorts(target).flatMap { case (name, data) => - getPortNames(name, data).toList + /** Experimental hardware construction reflection API + */ + object DataMirror { + def widthOf(target: Data): Width = target.width + def specifiedDirectionOf(target: Data): SpecifiedDirection = target.specifiedDirection + def directionOf(target: Data): ActualDirection = { + requireIsHardware(target, "node requested directionality on") + target.direction + } + + // Returns the top-level module ports + // TODO: maybe move to something like Driver or DriverUtils, since this is mainly for interacting + // with compiled artifacts (vs. elaboration-time reflection)? + def modulePorts(target: BaseModule): Seq[(String, Data)] = target.getChiselPorts + + // Returns all module ports with underscore-qualified names + def fullModulePorts(target: BaseModule): Seq[(String, Data)] = { + def getPortNames(name: String, data: Data): Seq[(String, Data)] = Seq(name -> data) ++ (data match { + case _: Element => Seq() + case r: Record => r.elements.toSeq flatMap { case (eltName, elt) => getPortNames(s"${name}_${eltName}", elt) } + case v: Vec[_] => v.zipWithIndex flatMap { case (elt, index) => getPortNames(s"${name}_${index}", elt) } + }) + modulePorts(target).flatMap { case (name, data) => + getPortNames(name, data).toList + } } - } - // Internal reflection-style APIs, subject to change and removal whenever. - object internal { // scalastyle:ignore object.name - def isSynthesizable(target: Data): Boolean = target.isSynthesizable - // For those odd cases where you need to care about object reference and uniqueness - def chiselTypeClone[T<:Data](target: Data): T = { - target.cloneTypeFull.asInstanceOf[T] + // Internal reflection-style APIs, subject to change and removal whenever. + object internal { // scalastyle:ignore object.name + def isSynthesizable(target: Data): Boolean = target.isSynthesizable + // For those odd cases where you need to care about object reference and uniqueness + def chiselTypeClone[T<:Data](target: Data): T = { + target.cloneTypeFull.asInstanceOf[T] + } } } } @@ -161,7 +163,7 @@ object DataMirror { * - Otherwise: fail */ //scalastyle:off cyclomatic.complexity -private[core] object cloneSupertype { +private[chisel3] object cloneSupertype { def apply[T <: Data](elts: Seq[T], createdType: String)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = { require(!elts.isEmpty, s"can't create $createdType with no inputs") @@ -277,12 +279,12 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { // sc // Note that the actual direction of this node can differ from child and parent specifiedDirection. private var _specifiedDirection: SpecifiedDirection = SpecifiedDirection.Unspecified private[chisel3] def specifiedDirection: SpecifiedDirection = _specifiedDirection - private[core] def specifiedDirection_=(direction: SpecifiedDirection) = { + private[chisel3] def specifiedDirection_=(direction: SpecifiedDirection) = { if (_specifiedDirection != SpecifiedDirection.Unspecified) { this match { // Anything flies in compatibility mode case t: Record if !t.compileOptions.dontAssumeDirectionality => - case _ => throw Binding.RebindingException(s"Attempted reassignment of user-specified direction to $this") + case _ => throw RebindingException(s"Attempted reassignment of user-specified direction to $this") } } _specifiedDirection = direction @@ -292,7 +294,7 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { // sc * the compatibility layer where, at the elements, Flip is Input and unspecified is Output. * DO NOT USE OUTSIDE THIS PURPOSE. THIS OPERATION IS DANGEROUS! */ - private[core] def _assignCompatibilityExplicitDirection: Unit = { // scalastyle:off method.name + private[chisel3] def _assignCompatibilityExplicitDirection: Unit = { // scalastyle:off method.name (this, _specifiedDirection) match { case (_: Analog, _) => // nothing to do case (_, SpecifiedDirection.Unspecified) => _specifiedDirection = SpecifiedDirection.Output @@ -306,29 +308,29 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { // sc // perform checks in Chisel, where more informative error messages are possible. private var _binding: Option[Binding] = None // Only valid after node is bound (synthesizable), crashes otherwise - protected[core] def binding: Option[Binding] = _binding + protected[chisel3] def binding: Option[Binding] = _binding protected def binding_=(target: Binding) { if (_binding.isDefined) { - throw Binding.RebindingException(s"Attempted reassignment of binding to $this") + throw RebindingException(s"Attempted reassignment of binding to $this") } _binding = Some(target) } // Similar to topBindingOpt except it explicitly excludes SampleElements which are bound but not // hardware - private[core] final def isSynthesizable: Boolean = _binding.map { + private[chisel3] final def isSynthesizable: Boolean = _binding.map { case ChildBinding(parent) => parent.isSynthesizable case _: TopBinding => true case _: SampleElementBinding[_] => false }.getOrElse(false) - private[core] def topBindingOpt: Option[TopBinding] = _binding.flatMap { + private[chisel3] def topBindingOpt: Option[TopBinding] = _binding.flatMap { case ChildBinding(parent) => parent.topBindingOpt case bindingVal: TopBinding => Some(bindingVal) case SampleElementBinding(parent) => parent.topBindingOpt } - private[core] def topBinding: TopBinding = topBindingOpt.get + private[chisel3] def topBinding: TopBinding = topBindingOpt.get /** Binds this node to the hardware graph. * parentDirection is the direction of the parent node, or Unspecified (default) if the target @@ -345,9 +347,9 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { // sc private var _direction: Option[ActualDirection] = None private[chisel3] def direction: ActualDirection = _direction.get - private[core] def direction_=(actualDirection: ActualDirection) { + private[chisel3] def direction_=(actualDirection: ActualDirection) { if (_direction.isDefined) { - throw Binding.RebindingException(s"Attempted reassignment of resolved direction to $this") + throw RebindingException(s"Attempted reassignment of resolved direction to $this") } _direction = Some(actualDirection) } @@ -378,7 +380,7 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { // sc // TODO: refactor away this, this is outside the scope of Data private[chisel3] def allElements: Seq[Element] - private[core] def badConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = + private[chisel3] def badConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = throwException(s"cannot connect ${this} and ${that}") private[chisel3] def connect(that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): Unit = { // scalastyle:ignore line.size.limit if (connectCompileOptions.checkSynthesizable) { @@ -391,7 +393,7 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { // sc try { MonoConnect.connect(sourceInfo, connectCompileOptions, this, that, Builder.forcedUserModule) } catch { - case MonoConnect.MonoConnectException(message) => + case MonoConnectException(message) => throwException( s"Connection between sink ($this) and source ($that) failed @$message" ) @@ -407,13 +409,13 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { // sc (this.topBinding, that.topBinding) match { case (_: ReadOnlyBinding, _: ReadOnlyBinding) => throwException(s"Both $this and $that are read-only") // DontCare cannot be a sink (LHS) - case (_: DontCareBinding, _) => throw DontCareCantBeSink + case (_: DontCareBinding, _) => throw BiConnect.DontCareCantBeSink case _ => // fine } try { BiConnect.connect(sourceInfo, connectCompileOptions, this, that, Builder.forcedUserModule) } catch { - case BiConnect.BiConnectException(message) => + case BiConnectException(message) => throwException( s"Connection between left ($this) and source ($that) failed @$message" ) @@ -426,7 +428,7 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { // sc /** Whether this Data has the same model ("data type") as that Data. * Data subtypes should overload this with checks against their own type. */ - private[core] def typeEquivalent(that: Data): Boolean + private[chisel3] def typeEquivalent(that: Data): Boolean // Internal API: returns a ref that can be assigned to, if consistent with the binding private[chisel3] def lref: Node = { @@ -450,7 +452,7 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { // sc } private[chisel3] def width: Width - private[core] def legacyConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit + private[chisel3] def legacyConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit /** Internal API; Chisel users should look at chisel3.chiselTypeOf(...). * @@ -547,7 +549,7 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { // sc /** Assigns this node from Bits type. Internal implementation for asTypeOf. */ - private[core] def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, + private[chisel3] def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Unit /** Reinterpret cast to UInt. @@ -608,8 +610,23 @@ trait WireFactory { * }}} * */ -object Wire extends WireFactory +object Wire extends WireFactory { + @chiselRuntimeDeprecated + @deprecated("Wire(init=init) is deprecated, use WireDefault(init) instead", "chisel3") + def apply[T <: Data](dummy: Int = 0, init: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = + WireDefault(init) + + @chiselRuntimeDeprecated + @deprecated("Wire(t, init) is deprecated, use WireDefault(t, init) instead", "chisel3") + def apply[T <: Data](t: T, init: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = + WireDefault(t, init) + + @chiselRuntimeDeprecated + @deprecated("Wire(t, init) is deprecated, use WireDefault(t, init) instead", "chisel3") + def apply[T <: Data](t: T, init: DontCare.type)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = + WireDefault(t, init) +} /** Utility for constructing hardware wires with a default connection * @@ -710,33 +727,35 @@ object WireDefault { } } -/** RHS (source) for Invalidate API. - * Causes connection logic to emit a DefInvalid when connected to an output port (or wire). - */ -private[chisel3] object DontCare extends Element { - // This object should be initialized before we execute any user code that refers to it, - // otherwise this "Chisel" object will end up on the UserModule's id list. - // We make it private to chisel3 so it has to be accessed through the package object. +package internal { + /** RHS (source) for Invalidate API. + * Causes connection logic to emit a DefInvalid when connected to an output port (or wire). + */ + private[chisel3] object InternalDontCare extends Element { + // This object should be initialized before we execute any user code that refers to it, + // otherwise this "Chisel" object will end up on the UserModule's id list. + // We make it private to chisel3 so it has to be accessed through the package object. - private[chisel3] override val width: Width = UnknownWidth() + private[chisel3] override val width: Width = UnknownWidth() - bind(DontCareBinding(), SpecifiedDirection.Output) - override def cloneType: this.type = DontCare + bind(DontCareBinding(), SpecifiedDirection.Output) + override def cloneType: this.type = DontCare - override def toString: String = "DontCare()" + override def toString: String = "DontCare()" - override def litOption: Option[BigInt] = None + override def litOption: Option[BigInt] = None - def toPrintable: Printable = PString("DONTCARE") + def toPrintable: Printable = PString("DONTCARE") - private[core] def connectFromBits(that: chisel3.core.Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Unit = { // scalastyle:ignore line.size.limit - Builder.error("connectFromBits: DontCare cannot be a connection sink (LHS)") - } + private[chisel3] def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Unit = { // scalastyle:ignore line.size.limit + Builder.error("connectFromBits: DontCare cannot be a connection sink (LHS)") + } - def do_asUInt(implicit sourceInfo: chisel3.internal.sourceinfo.SourceInfo, compileOptions: CompileOptions): chisel3.core.UInt = { // scalastyle:ignore line.size.limit - Builder.error("DontCare does not have a UInt representation") - 0.U + def do_asUInt(implicit sourceInfo: chisel3.internal.sourceinfo.SourceInfo, compileOptions: CompileOptions): UInt = { // scalastyle:ignore line.size.limit + Builder.error("DontCare does not have a UInt representation") + 0.U + } + // DontCare's only match themselves. + private[chisel3] def typeEquivalent(that: Data): Boolean = that == DontCare } - // DontCare's only match themselves. - private[core] def typeEquivalent(that: chisel3.core.Data): Boolean = that == DontCare } diff --git a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala b/chiselFrontend/src/main/scala/chisel3/Mem.scala index d44178ad..c64c0e35 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala +++ b/chiselFrontend/src/main/scala/chisel3/Mem.scala @@ -1,6 +1,6 @@ // See LICENSE for license details. -package chisel3.core +package chisel3 import scala.language.experimental.macros @@ -8,7 +8,6 @@ import chisel3.internal._ import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl._ import chisel3.internal.sourceinfo.{SourceInfo, SourceInfoTransform, UnlocatableSourceInfo, MemTransform} -import chisel3.SourceInfoDoc object Mem { // scalastyle:off line.size.limit diff --git a/chiselFrontend/src/main/scala/chisel3/Module.scala b/chiselFrontend/src/main/scala/chisel3/Module.scala new file mode 100644 index 00000000..8a11b0a6 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/Module.scala @@ -0,0 +1,365 @@ +// See LICENSE for license details. + +package chisel3 + +import scala.collection.immutable.ListMap +import scala.collection.mutable.{ArrayBuffer, HashMap} +import scala.collection.JavaConversions._ +import scala.language.experimental.macros + +import java.util.IdentityHashMap + +import chisel3.internal._ +import chisel3.internal.Builder._ +import chisel3.internal.firrtl._ +import chisel3.internal.sourceinfo.{InstTransform, SourceInfo} +import chisel3.experimental.BaseModule + +import _root_.firrtl.annotations.{CircuitName, ModuleName} + +object Module extends SourceInfoDoc { + /** A wrapper method that all Module instantiations must be wrapped in + * (necessary to help Chisel track internal state). + * + * @param bc the Module being created + * + * @return the input module `m` with Chisel metadata properly set + */ + def apply[T <: BaseModule](bc: => T): T = macro InstTransform.apply[T] + + /** @group SourceInfoTransformMacro */ + def do_apply[T <: BaseModule](bc: => T) + (implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions): T = { + if (Builder.readyForModuleConstr) { + throwException("Error: Called Module() twice without instantiating a Module." + + sourceInfo.makeMessage(" See " + _)) + } + Builder.readyForModuleConstr = true + + val parent = Builder.currentModule + val whenDepth: Int = Builder.whenDepth + + // Save then clear clock and reset to prevent leaking scope, must be set again in the Module + val (saveClock, saveReset) = (Builder.currentClock, Builder.currentReset) + Builder.currentClock = None + Builder.currentReset = None + + // Execute the module, this has the following side effects: + // - set currentModule + // - unset readyForModuleConstr + // - reset whenDepth to 0 + // - set currentClockAndReset + val module: T = bc // bc is actually evaluated here + + if (Builder.whenDepth != 0) { + throwException("Internal Error! when() scope depth is != 0, this should have been caught!") + } + if (Builder.readyForModuleConstr) { + throwException("Error: attempted to instantiate a Module, but nothing happened. " + + "This is probably due to rewrapping a Module instance with Module()." + + sourceInfo.makeMessage(" See " + _)) + } + Builder.currentModule = parent // Back to parent! + Builder.whenDepth = whenDepth + Builder.currentClock = saveClock // Back to clock and reset scope + Builder.currentReset = saveReset + + val component = module.generateComponent() + Builder.components += component + + // Handle connections at enclosing scope + if(!Builder.currentModule.isEmpty) { + pushCommand(DefInstance(sourceInfo, module, component.ports)) + module.initializeInParent(compileOptions) + } + module + } + + /** Returns the implicit Clock */ + def clock: Clock = Builder.forcedClock + /** Returns the implicit Reset */ + def reset: Reset = Builder.forcedReset + /** Returns the current Module */ + def currentModule: Option[BaseModule] = Builder.currentModule +} + +package experimental { + + object IO { + /** Constructs a port for the current Module + * + * This must wrap the datatype used to set the io field of any Module. + * i.e. All concrete modules must have defined io in this form: + * [lazy] val io[: io type] = IO(...[: io type]) + * + * Items in [] are optional. + * + * The granted iodef must be a chisel type and not be bound to hardware. + * + * Also registers a Data as a port, also performing bindings. Cannot be called once ports are + * requested (so that all calls to ports will return the same information). + * Internal API. + */ + def apply[T<:Data](iodef: T): T = { + val module = Module.currentModule.get // Impossible to fail + require(!module.isClosed, "Can't add more ports after module close") + requireIsChiselType(iodef, "io type") + + // Clone the IO so we preserve immutability of data types + val iodefClone = try { + iodef.cloneTypeFull + } catch { + // For now this is going to be just a deprecation so we don't suddenly break everyone's code + case e: AutoClonetypeException => + Builder.deprecated(e.getMessage, Some(s"${iodef.getClass}")) + iodef + } + module.bindIoInPlace(iodefClone) + iodefClone + } + } +} + +package internal { + import chisel3.experimental.{BaseModule, MultiIOModule} + + object BaseModule { + private[chisel3] class ClonePorts (elts: Data*)(implicit compileOptions: CompileOptions) extends Record { + val elements = ListMap(elts.map(d => d.instanceName -> d.cloneTypeFull): _*) + def apply(field: String) = elements(field) + override def cloneType = (new ClonePorts(elts: _*)).asInstanceOf[this.type] + } + + private[chisel3] def cloneIORecord(proto: BaseModule)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): ClonePorts = { + require(proto.isClosed, "Can't clone a module before module close") + val clonePorts = new ClonePorts(proto.getModulePorts: _*) + clonePorts.bind(WireBinding(Builder.forcedUserModule)) + val cloneInstance = new DefInstance(sourceInfo, proto, proto._component.get.ports) { + override def name = clonePorts.getRef.name + } + pushCommand(cloneInstance) + if (!compileOptions.explicitInvalidate) { + pushCommand(DefInvalid(sourceInfo, clonePorts.ref)) + } + if (proto.isInstanceOf[MultiIOModule]) { + clonePorts("clock") := Module.clock + clonePorts("reset") := Module.reset + } + clonePorts + } + } +} + +package experimental { + + /** Abstract base class for Modules, an instantiable organizational unit for RTL. + */ + // TODO: seal this? + abstract class BaseModule extends HasId { + // + // Builder Internals - this tracks which Module RTL construction belongs to. + // + if (!Builder.readyForModuleConstr) { + throwException("Error: attempted to instantiate a Module without wrapping it in Module().") + } + readyForModuleConstr = false + + Builder.currentModule = Some(this) + Builder.whenDepth = 0 + + // + // Module Construction Internals + // + protected var _closed = false + + /** Internal check if a Module is closed */ + private[chisel3] def isClosed = _closed + + // Fresh Namespace because in Firrtl, Modules namespaces are disjoint with the global namespace + private[chisel3] val _namespace = Namespace.empty + private val _ids = ArrayBuffer[HasId]() + private[chisel3] def addId(d: HasId) { + require(!_closed, "Can't write to module after module close") + _ids += d + } + protected def getIds = { + require(_closed, "Can't get ids before module close") + _ids.toSeq + } + + private val _ports = new ArrayBuffer[Data]() + // getPorts unfortunately already used for tester compatibility + protected[chisel3] def getModulePorts = { + require(_closed, "Can't get ports before module close") + _ports.toSeq + } + + // These methods allow checking some properties of ports before the module is closed, + // mainly for compatibility purposes. + protected def portsContains(elem: Data): Boolean = _ports contains elem + protected def portsSize: Int = _ports.size + + /** Generates the FIRRTL Component (Module or Blackbox) of this Module. + * Also closes the module so no more construction can happen inside. + */ + private[chisel3] def generateComponent(): Component + + /** Sets up this module in the parent context + */ + private[chisel3] def initializeInParent(parentCompileOptions: CompileOptions): Unit + + // + // Chisel Internals + // + /** Desired name of this module. Override this to give this module a custom, perhaps parametric, + * name. + */ + def desiredName: String = this.getClass.getName.split('.').last + + /** Legalized name of this module. */ + final lazy val name = try { + Builder.globalNamespace.name(desiredName) + } catch { + case e: NullPointerException => throwException( + s"Error: desiredName of ${this.getClass.getName} is null. Did you evaluate 'name' before all values needed by desiredName were available?", e) // scalastyle:ignore line.size.limit + case t: Throwable => throw t + } + + /** Returns a FIRRTL ModuleName that references this object + * @note Should not be called until circuit elaboration is complete + */ + final def toNamed: ModuleName = ModuleName(this.name, CircuitName(this.circuitName)) + + /** + * Internal API. Returns a list of this module's generated top-level ports as a map of a String + * (FIRRTL name) to the IO object. Only valid after the module is closed. + * + * Note: for BlackBoxes (but not ExtModules), this returns the contents of the top-level io + * object, consistent with what is emitted in FIRRTL. + * + * TODO: Use SeqMap/VectorMap when those data structures become available. + */ + private[chisel3] def getChiselPorts: Seq[(String, Data)] = { + require(_closed, "Can't get ports before module close") + _component.get.ports.map { port => + (port.id.getRef.asInstanceOf[ModuleIO].name, port.id) + } + } + + /** Called at the Module.apply(...) level after this Module has finished elaborating. + * Returns a map of nodes -> names, for named nodes. + * + * Helper method. + */ + protected def nameIds(rootClass: Class[_]): HashMap[HasId, String] = { + val names = new HashMap[HasId, String]() + + def name(node: HasId, name: String) { + // First name takes priority, like suggestName + // TODO: DRYify with suggestName + if (!names.contains(node)) { + names.put(node, name) + } + } + + /** Scala generates names like chisel3$util$Queue$$ram for private vals + * This extracts the part after $$ for names like this and leaves names + * without $$ unchanged + */ + def cleanName(name: String): String = name.split("""\$\$""").lastOption.getOrElse(name) + + for (m <- getPublicFields(rootClass)) { + Builder.nameRecursively(cleanName(m.getName), m.invoke(this), name) + } + + names + } + + /** Compatibility function. Allows Chisel2 code which had ports without the IO wrapper to + * compile under Bindings checks. Does nothing in non-compatibility mode. + * + * Should NOT be used elsewhere. This API will NOT last. + * + * TODO: remove this, perhaps by removing Bindings checks in compatibility mode. + */ + def _compatAutoWrapPorts() {} // scalastyle:ignore method.name + + // + // BaseModule User API functions + // + @deprecated("Use chisel3.experimental.annotate instead", "3.1") + protected def annotate(annotation: ChiselAnnotation): Unit = { + Builder.annotations += annotation + } + + /** Chisel2 code didn't require the IO(...) wrapper and would assign a Chisel type directly to + * io, then do operations on it. This binds a Chisel type in-place (mutably) as an IO. + */ + protected def _bindIoInPlace(iodef: Data): Unit = { // scalastyle:ignore method.name + // Compatibility code: Chisel2 did not require explicit direction on nodes + // (unspecified treated as output, and flip on nothing was input). + // This sets assigns the explicit directions required by newer semantics on + // Bundles defined in compatibility mode. + // This recursively walks the tree, and assigns directions if no explicit + // direction given by upper-levels (override Input / Output) AND element is + // directly inside a compatibility Bundle determined by compile options. + def assignCompatDir(data: Data, insideCompat: Boolean): Unit = { + data match { + case data: Element if insideCompat => data._assignCompatibilityExplicitDirection + case data: Element => // Not inside a compatibility Bundle, nothing to be done + case data: Aggregate => data.specifiedDirection match { + // Recurse into children to ensure explicit direction set somewhere + case SpecifiedDirection.Unspecified | SpecifiedDirection.Flip => data match { + case record: Record => + val compatRecord = !record.compileOptions.dontAssumeDirectionality + record.getElements.foreach(assignCompatDir(_, compatRecord)) + case vec: Vec[_] => + vec.getElements.foreach(assignCompatDir(_, insideCompat)) + } + case SpecifiedDirection.Input | SpecifiedDirection.Output => // forced assign, nothing to do + } + } + } + assignCompatDir(iodef, false) + + iodef.bind(PortBinding(this)) + _ports += iodef + } + /** Private accessor for _bindIoInPlace */ + private[chisel3] def bindIoInPlace(iodef: Data): Unit = _bindIoInPlace(iodef) + + /** + * This must wrap the datatype used to set the io field of any Module. + * i.e. All concrete modules must have defined io in this form: + * [lazy] val io[: io type] = IO(...[: io type]) + * + * Items in [] are optional. + * + * The granted iodef must be a chisel type and not be bound to hardware. + * + * Also registers a Data as a port, also performing bindings. Cannot be called once ports are + * requested (so that all calls to ports will return the same information). + * Internal API. + * + * TODO(twigg): Specifically walk the Data definition to call out which nodes + * are problematic. + */ + protected def IO[T<:Data](iodef: T): T = chisel3.experimental.IO.apply(iodef) // scalastyle:ignore method.name + + // + // Internal Functions + // + + /** Keep component for signal names */ + private[chisel3] var _component: Option[Component] = None + + /** Signal name (for simulation). */ + override def instanceName: String = + if (_parent == None) name else _component match { + case None => getRef.name + case Some(c) => getRef fullName c + } + + } +} diff --git a/chiselFrontend/src/main/scala/chisel3/core/MultiClock.scala b/chiselFrontend/src/main/scala/chisel3/MultiClock.scala index aaa03d78..239e745a 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/MultiClock.scala +++ b/chiselFrontend/src/main/scala/chisel3/MultiClock.scala @@ -1,6 +1,6 @@ // See LICENSE for license details. -package chisel3.core +package chisel3 import chisel3.internal._ diff --git a/chiselFrontend/src/main/scala/chisel3/core/Mux.scala b/chiselFrontend/src/main/scala/chisel3/Mux.scala index 7dd1b98b..960424bf 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Mux.scala +++ b/chiselFrontend/src/main/scala/chisel3/Mux.scala @@ -1,15 +1,14 @@ // See LICENSE for license details. -package chisel3.core +package chisel3 import scala.language.experimental.macros import chisel3.internal._ -import chisel3.internal.Builder.{pushOp} +import chisel3.internal.Builder.pushOp import chisel3.internal.sourceinfo.{SourceInfo, MuxTransform} import chisel3.internal.firrtl._ import chisel3.internal.firrtl.PrimOp._ -import chisel3.SourceInfoDoc object Mux extends SourceInfoDoc { /** Creates a mux, whose output is one of the inputs depending on the diff --git a/chiselFrontend/src/main/scala/chisel3/core/Printable.scala b/chiselFrontend/src/main/scala/chisel3/Printable.scala index c724f682..7add9166 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Printable.scala +++ b/chiselFrontend/src/main/scala/chisel3/Printable.scala @@ -1,9 +1,8 @@ // See LICENSE for license details. -package chisel3.core +package chisel3 import chisel3.internal.firrtl.Component -import chisel3.internal.HasId import scala.collection.mutable diff --git a/chiselFrontend/src/main/scala/chisel3/core/Printf.scala b/chiselFrontend/src/main/scala/chisel3/Printf.scala index 5c2f89e9..b80d5eb5 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Printf.scala +++ b/chiselFrontend/src/main/scala/chisel3/Printf.scala @@ -1,6 +1,6 @@ // See LICENSE for license details. -package chisel3.core +package chisel3 import scala.language.experimental.macros diff --git a/chiselFrontend/src/main/scala/chisel3/core/RawModule.scala b/chiselFrontend/src/main/scala/chisel3/RawModule.scala index b224d9a3..14a7a584 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/RawModule.scala +++ b/chiselFrontend/src/main/scala/chisel3/RawModule.scala @@ -1,15 +1,15 @@ // See LICENSE for license details. -package chisel3.core +package chisel3.experimental import scala.collection.mutable.{ArrayBuffer, HashMap} import scala.collection.JavaConversions._ import scala.language.experimental.macros +import chisel3._ import chisel3.internal._ import chisel3.internal.Builder._ import chisel3.internal.firrtl._ -import chisel3.internal.firrtl.{Command => _, _} import chisel3.internal.sourceinfo.UnlocatableSourceInfo /** Abstract base class for Modules that contain Chisel RTL. @@ -56,7 +56,7 @@ abstract class RawModule(implicit moduleCompileOptions: CompileOptions) } - private[core] override def generateComponent(): Component = { // scalastyle:ignore cyclomatic.complexity + private[chisel3] override def generateComponent(): Component = { // scalastyle:ignore cyclomatic.complexity require(!_closed, "Can't generate module more than once") _closed = true @@ -121,7 +121,7 @@ abstract class RawModule(implicit moduleCompileOptions: CompileOptions) component } - private[core] def initializeInParent(parentCompileOptions: CompileOptions): Unit = { + private[chisel3] def initializeInParent(parentCompileOptions: CompileOptions): Unit = { implicit val sourceInfo = UnlocatableSourceInfo if (!parentCompileOptions.explicitInvalidate) { @@ -149,7 +149,7 @@ abstract class MultiIOModule(implicit moduleCompileOptions: CompileOptions) Builder.currentClock = Some(clock) Builder.currentReset = Some(reset) - private[core] override def initializeInParent(parentCompileOptions: CompileOptions): Unit = { + private[chisel3] override def initializeInParent(parentCompileOptions: CompileOptions): Unit = { implicit val sourceInfo = UnlocatableSourceInfo super.initializeInParent(parentCompileOptions) @@ -221,7 +221,7 @@ abstract class LegacyModule(implicit moduleCompileOptions: CompileOptions) } } - private[core] override def generateComponent(): Component = { + private[chisel3] override def generateComponent(): Component = { _compatAutoWrapPorts() // pre-IO(...) compatibility hack // Restrict IO to just io, clock, and reset @@ -233,7 +233,7 @@ abstract class LegacyModule(implicit moduleCompileOptions: CompileOptions) super.generateComponent() } - private[core] override def initializeInParent(parentCompileOptions: CompileOptions): Unit = { + private[chisel3] override def initializeInParent(parentCompileOptions: CompileOptions): Unit = { // Don't generate source info referencing parents inside a module, since this interferes with // module de-duplication in FIRRTL emission. implicit val sourceInfo = UnlocatableSourceInfo diff --git a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala b/chiselFrontend/src/main/scala/chisel3/Reg.scala index 747fad73..2f26f516 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Reg.scala +++ b/chiselFrontend/src/main/scala/chisel3/Reg.scala @@ -1,13 +1,13 @@ // See LICENSE for license details. -package chisel3.core +package chisel3 import scala.language.experimental.macros import chisel3.internal._ import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl._ -import chisel3.internal.sourceinfo.{SourceInfo} +import chisel3.internal.sourceinfo.SourceInfo /** Utility for constructing hardware registers * @@ -45,6 +45,33 @@ object Reg { pushCommand(DefReg(sourceInfo, reg, clock)) reg } + + @chiselRuntimeDeprecated + @deprecated("Use Reg(t), RegNext(next, [init]) or RegInit([t], init) instead", "chisel3") + def apply[T <: Data](t: T = null, next: T = null, init: T = null) + (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = { + if (t ne null) { + val reg = if (init ne null) { + RegInit(t, init) + } else { + Reg(t) + } + if (next ne null) { + reg := next + } + reg + } else if (next ne null) { + if (init ne null) { + RegNext(next, init) + } else { + RegNext(next) + } + } else if (init ne null) { + RegInit(init) + } else { + throwException("cannot infer type") + } + } } object RegNext { diff --git a/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala b/chiselFrontend/src/main/scala/chisel3/SeqUtils.scala index f15fb178..28f753b1 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala +++ b/chiselFrontend/src/main/scala/chisel3/SeqUtils.scala @@ -1,7 +1,8 @@ // See LICENSE for license details. -package chisel3.core +package chisel3 +import chisel3.experimental.FixedPoint import chisel3.internal.throwException import scala.language.experimental.macros diff --git a/chiselFrontend/src/main/scala/chisel3/core/StrongEnum.scala b/chiselFrontend/src/main/scala/chisel3/StrongEnum.scala index 63f7a8a0..b37ba703 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/StrongEnum.scala +++ b/chiselFrontend/src/main/scala/chisel3/StrongEnum.scala @@ -1,15 +1,16 @@ // See LICENSE for license details. -package chisel3.core +package chisel3.experimental import scala.language.experimental.macros import scala.reflect.macros.blackbox.Context import scala.collection.mutable +import chisel3._ import chisel3.internal.Builder.pushOp import chisel3.internal.firrtl.PrimOp._ import chisel3.internal.firrtl._ import chisel3.internal.sourceinfo._ -import chisel3.internal.{Builder, InstanceId, throwException} +import chisel3.internal.{Binding, Builder, ChildBinding, ConstrainedBinding, InstanceId, throwException} import firrtl.annotations._ @@ -86,7 +87,7 @@ abstract class EnumType(private val factory: EnumFactory, selfAnnotating: Boolea override def cloneType: this.type = factory().asInstanceOf[this.type] - private[core] def compop(sourceInfo: SourceInfo, op: PrimOp, other: EnumType): Bool = { + private[chisel3] def compop(sourceInfo: SourceInfo, op: PrimOp, other: EnumType): Bool = { requireIsHardware(this, "bits operated on") requireIsHardware(other, "bits operated on") @@ -97,12 +98,12 @@ abstract class EnumType(private val factory: EnumFactory, selfAnnotating: Boolea pushOp(DefPrim(sourceInfo, Bool(), op, this.ref, other.ref)) } - private[core] override def typeEquivalent(that: Data): Boolean = { + private[chisel3] override def typeEquivalent(that: Data): Boolean = { this.getClass == that.getClass && this.factory == that.asInstanceOf[EnumType].factory } - private[core] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, + private[chisel3] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Unit = { this := factory.apply(that.asUInt) } @@ -152,7 +153,7 @@ abstract class EnumType(private val factory: EnumFactory, selfAnnotating: Boolea } } - private[core] def bindToLiteral(num: BigInt, w: Width): Unit = { + private[chisel3] def bindToLiteral(num: BigInt, w: Width): Unit = { val lit = ULit(num, w) lit.bindLitArg(this) } @@ -223,7 +224,7 @@ abstract class EnumFactory { } private var id: BigInt = 0 - private[core] var width: Width = 0.W + private[chisel3] var width: Width = 0.W private case class EnumRecord(inst: Type, name: String) private val enum_records = mutable.ArrayBuffer.empty[EnumRecord] @@ -232,9 +233,9 @@ abstract class EnumFactory { private def enumValues = enum_records.map(_.inst.litValue()).toSeq private def enumInstances = enum_records.map(_.inst).toSeq - private[core] val enumTypeName = getClass.getName.init + private[chisel3] val enumTypeName = getClass.getName.init - private[core] def globalAnnotation: EnumDefChiselAnnotation = + private[chisel3] def globalAnnotation: EnumDefChiselAnnotation = EnumDefChiselAnnotation(enumTypeName, (enumNames, enumValues).zipped.toMap) def getWidth: Int = width.get @@ -304,7 +305,7 @@ abstract class EnumFactory { } -private[core] object EnumMacros { +private[chisel3] object EnumMacros { def ValImpl(c: Context) : c.Tree = { // scalastyle:off method.name import c.universe._ val names = getNames(c) diff --git a/chiselFrontend/src/main/scala/chisel3/core/When.scala b/chiselFrontend/src/main/scala/chisel3/When.scala index 78fc0fc5..50e13a1f 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/When.scala +++ b/chiselFrontend/src/main/scala/chisel3/When.scala @@ -1,6 +1,6 @@ // See LICENSE for license details. -package chisel3.core +package chisel3 import scala.language.experimental.macros diff --git a/chiselFrontend/src/main/scala/chisel3/core/Module.scala b/chiselFrontend/src/main/scala/chisel3/core/Module.scala deleted file mode 100644 index 5cd48a6a..00000000 --- a/chiselFrontend/src/main/scala/chisel3/core/Module.scala +++ /dev/null @@ -1,355 +0,0 @@ -// See LICENSE for license details. - -package chisel3.core - -import scala.collection.immutable.ListMap -import scala.collection.mutable.{ArrayBuffer, HashMap} -import scala.collection.JavaConversions._ -import scala.language.experimental.macros - -import java.util.IdentityHashMap - -import chisel3.internal._ -import chisel3.internal.Builder._ -import chisel3.internal.firrtl._ -import chisel3.internal.sourceinfo.{InstTransform, SourceInfo} -import chisel3.SourceInfoDoc - -import _root_.firrtl.annotations.{CircuitName, ModuleName} - -object Module extends SourceInfoDoc { - /** A wrapper method that all Module instantiations must be wrapped in - * (necessary to help Chisel track internal state). - * - * @param bc the Module being created - * - * @return the input module `m` with Chisel metadata properly set - */ - def apply[T <: BaseModule](bc: => T): T = macro InstTransform.apply[T] - - /** @group SourceInfoTransformMacro */ - def do_apply[T <: BaseModule](bc: => T) - (implicit sourceInfo: SourceInfo, - compileOptions: CompileOptions): T = { - if (Builder.readyForModuleConstr) { - throwException("Error: Called Module() twice without instantiating a Module." + - sourceInfo.makeMessage(" See " + _)) - } - Builder.readyForModuleConstr = true - - val parent = Builder.currentModule - val whenDepth: Int = Builder.whenDepth - - // Save then clear clock and reset to prevent leaking scope, must be set again in the Module - val (saveClock, saveReset) = (Builder.currentClock, Builder.currentReset) - Builder.currentClock = None - Builder.currentReset = None - - // Execute the module, this has the following side effects: - // - set currentModule - // - unset readyForModuleConstr - // - reset whenDepth to 0 - // - set currentClockAndReset - val module: T = bc // bc is actually evaluated here - - if (Builder.whenDepth != 0) { - throwException("Internal Error! when() scope depth is != 0, this should have been caught!") - } - if (Builder.readyForModuleConstr) { - throwException("Error: attempted to instantiate a Module, but nothing happened. " + - "This is probably due to rewrapping a Module instance with Module()." + - sourceInfo.makeMessage(" See " + _)) - } - Builder.currentModule = parent // Back to parent! - Builder.whenDepth = whenDepth - Builder.currentClock = saveClock // Back to clock and reset scope - Builder.currentReset = saveReset - - val component = module.generateComponent() - Builder.components += component - - // Handle connections at enclosing scope - if(!Builder.currentModule.isEmpty) { - pushCommand(DefInstance(sourceInfo, module, component.ports)) - module.initializeInParent(compileOptions) - } - module - } - - /** Returns the implicit Clock */ - def clock: Clock = Builder.forcedClock - /** Returns the implicit Reset */ - def reset: Reset = Builder.forcedReset - /** Returns the current Module */ - def currentModule: Option[BaseModule] = Builder.currentModule -} - -object IO { - /** Constructs a port for the current Module - * - * This must wrap the datatype used to set the io field of any Module. - * i.e. All concrete modules must have defined io in this form: - * [lazy] val io[: io type] = IO(...[: io type]) - * - * Items in [] are optional. - * - * The granted iodef must be a chisel type and not be bound to hardware. - * - * Also registers a Data as a port, also performing bindings. Cannot be called once ports are - * requested (so that all calls to ports will return the same information). - * Internal API. - */ - def apply[T<:Data](iodef: T): T = { - val module = Module.currentModule.get // Impossible to fail - require(!module.isClosed, "Can't add more ports after module close") - requireIsChiselType(iodef, "io type") - - // Clone the IO so we preserve immutability of data types - val iodefClone = try { - iodef.cloneTypeFull - } catch { - // For now this is going to be just a deprecation so we don't suddenly break everyone's code - case e: AutoClonetypeException => - Builder.deprecated(e.getMessage, Some(s"${iodef.getClass}")) - iodef - } - module.bindIoInPlace(iodefClone) - iodefClone - } -} - -object BaseModule { - private[chisel3] class ClonePorts (elts: Data*)(implicit compileOptions: CompileOptions) extends Record { - val elements = ListMap(elts.map(d => d.instanceName -> d.cloneTypeFull): _*) - def apply(field: String) = elements(field) - override def cloneType = (new ClonePorts(elts: _*)).asInstanceOf[this.type] - } - - private[chisel3] def cloneIORecord(proto: BaseModule)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): ClonePorts = { - require(proto.isClosed, "Can't clone a module before module close") - val clonePorts = new ClonePorts(proto.getModulePorts: _*) - clonePorts.bind(WireBinding(Builder.forcedUserModule)) - val cloneInstance = new DefInstance(sourceInfo, proto, proto._component.get.ports) { - override def name = clonePorts.getRef.name - } - pushCommand(cloneInstance) - if (!compileOptions.explicitInvalidate) { - pushCommand(DefInvalid(sourceInfo, clonePorts.ref)) - } - if (proto.isInstanceOf[MultiIOModule]) { - clonePorts("clock") := Module.clock - clonePorts("reset") := Module.reset - } - clonePorts - } -} - -/** Abstract base class for Modules, an instantiable organizational unit for RTL. - */ -// TODO: seal this? -abstract class BaseModule extends HasId { - // - // Builder Internals - this tracks which Module RTL construction belongs to. - // - if (!Builder.readyForModuleConstr) { - throwException("Error: attempted to instantiate a Module without wrapping it in Module().") - } - readyForModuleConstr = false - - Builder.currentModule = Some(this) - Builder.whenDepth = 0 - - // - // Module Construction Internals - // - protected var _closed = false - - /** Internal check if a Module is closed */ - private[core] def isClosed = _closed - - // Fresh Namespace because in Firrtl, Modules namespaces are disjoint with the global namespace - private[core] val _namespace = Namespace.empty - private val _ids = ArrayBuffer[HasId]() - private[chisel3] def addId(d: HasId) { - require(!_closed, "Can't write to module after module close") - _ids += d - } - protected def getIds = { - require(_closed, "Can't get ids before module close") - _ids.toSeq - } - - private val _ports = new ArrayBuffer[Data]() - // getPorts unfortunately already used for tester compatibility - protected def getModulePorts = { - require(_closed, "Can't get ports before module close") - _ports.toSeq - } - - // These methods allow checking some properties of ports before the module is closed, - // mainly for compatibility purposes. - protected def portsContains(elem: Data): Boolean = _ports contains elem - protected def portsSize: Int = _ports.size - - /** Generates the FIRRTL Component (Module or Blackbox) of this Module. - * Also closes the module so no more construction can happen inside. - */ - private[core] def generateComponent(): Component - - /** Sets up this module in the parent context - */ - private[core] def initializeInParent(parentCompileOptions: CompileOptions): Unit - - // - // Chisel Internals - // - /** Desired name of this module. Override this to give this module a custom, perhaps parametric, - * name. - */ - def desiredName: String = this.getClass.getName.split('.').last - - /** Legalized name of this module. */ - final lazy val name = try { - Builder.globalNamespace.name(desiredName) - } catch { - case e: NullPointerException => throwException( - s"Error: desiredName of ${this.getClass.getName} is null. Did you evaluate 'name' before all values needed by desiredName were available?", e) // scalastyle:ignore line.size.limit - case t: Throwable => throw t - } - - /** Returns a FIRRTL ModuleName that references this object - * @note Should not be called until circuit elaboration is complete - */ - final def toNamed: ModuleName = ModuleName(this.name, CircuitName(this.circuitName)) - - /** - * Internal API. Returns a list of this module's generated top-level ports as a map of a String - * (FIRRTL name) to the IO object. Only valid after the module is closed. - * - * Note: for BlackBoxes (but not ExtModules), this returns the contents of the top-level io - * object, consistent with what is emitted in FIRRTL. - * - * TODO: Use SeqMap/VectorMap when those data structures become available. - */ - private[core] def getChiselPorts: Seq[(String, Data)] = { - require(_closed, "Can't get ports before module close") - _component.get.ports.map { port => - (port.id.getRef.asInstanceOf[ModuleIO].name, port.id) - } - } - - /** Called at the Module.apply(...) level after this Module has finished elaborating. - * Returns a map of nodes -> names, for named nodes. - * - * Helper method. - */ - protected def nameIds(rootClass: Class[_]): HashMap[HasId, String] = { - val names = new HashMap[HasId, String]() - - def name(node: HasId, name: String) { - // First name takes priority, like suggestName - // TODO: DRYify with suggestName - if (!names.contains(node)) { - names.put(node, name) - } - } - - /** Scala generates names like chisel3$util$Queue$$ram for private vals - * This extracts the part after $$ for names like this and leaves names - * without $$ unchanged - */ - def cleanName(name: String): String = name.split("""\$\$""").lastOption.getOrElse(name) - - for (m <- getPublicFields(rootClass)) { - Builder.nameRecursively(cleanName(m.getName), m.invoke(this), name) - } - - names - } - - /** Compatibility function. Allows Chisel2 code which had ports without the IO wrapper to - * compile under Bindings checks. Does nothing in non-compatibility mode. - * - * Should NOT be used elsewhere. This API will NOT last. - * - * TODO: remove this, perhaps by removing Bindings checks in compatibility mode. - */ - def _compatAutoWrapPorts() {} // scalastyle:ignore method.name - - // - // BaseModule User API functions - // - @deprecated("Use chisel3.experimental.annotate instead", "3.1") - protected def annotate(annotation: ChiselAnnotation): Unit = { - Builder.annotations += annotation - } - - /** Chisel2 code didn't require the IO(...) wrapper and would assign a Chisel type directly to - * io, then do operations on it. This binds a Chisel type in-place (mutably) as an IO. - */ - protected def _bindIoInPlace(iodef: Data): Unit = { // scalastyle:ignore method.name - // Compatibility code: Chisel2 did not require explicit direction on nodes - // (unspecified treated as output, and flip on nothing was input). - // This sets assigns the explicit directions required by newer semantics on - // Bundles defined in compatibility mode. - // This recursively walks the tree, and assigns directions if no explicit - // direction given by upper-levels (override Input / Output) AND element is - // directly inside a compatibility Bundle determined by compile options. - def assignCompatDir(data: Data, insideCompat: Boolean): Unit = { - data match { - case data: Element if insideCompat => data._assignCompatibilityExplicitDirection - case data: Element => // Not inside a compatibility Bundle, nothing to be done - case data: Aggregate => data.specifiedDirection match { - // Recurse into children to ensure explicit direction set somewhere - case SpecifiedDirection.Unspecified | SpecifiedDirection.Flip => data match { - case record: Record => - val compatRecord = !record.compileOptions.dontAssumeDirectionality - record.getElements.foreach(assignCompatDir(_, compatRecord)) - case vec: Vec[_] => - vec.getElements.foreach(assignCompatDir(_, insideCompat)) - } - case SpecifiedDirection.Input | SpecifiedDirection.Output => // forced assign, nothing to do - } - } - } - assignCompatDir(iodef, false) - - iodef.bind(PortBinding(this)) - _ports += iodef - } - /** Private accessor for _bindIoInPlace */ - private[core] def bindIoInPlace(iodef: Data): Unit = _bindIoInPlace(iodef) - - /** - * This must wrap the datatype used to set the io field of any Module. - * i.e. All concrete modules must have defined io in this form: - * [lazy] val io[: io type] = IO(...[: io type]) - * - * Items in [] are optional. - * - * The granted iodef must be a chisel type and not be bound to hardware. - * - * Also registers a Data as a port, also performing bindings. Cannot be called once ports are - * requested (so that all calls to ports will return the same information). - * Internal API. - * - * TODO(twigg): Specifically walk the Data definition to call out which nodes - * are problematic. - */ - protected def IO[T<:Data](iodef: T): T = chisel3.core.IO.apply(iodef) // scalastyle:ignore method.name - - // - // Internal Functions - // - - /** Keep component for signal names */ - private[chisel3] var _component: Option[Component] = None - - /** Signal name (for simulation). */ - override def instanceName: String = - if (_parent == None) name else _component match { - case None => getRef.name - case Some(c) => getRef fullName c - } - -} diff --git a/chiselFrontend/src/main/scala/chisel3/core/package.scala b/chiselFrontend/src/main/scala/chisel3/core/package.scala index 46db337b..ac69ca33 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/package.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/package.scala @@ -1,133 +1,293 @@ // See LICENSE for license details. -package chisel3 { - import internal.Builder - - package object core { - import internal.firrtl.{Width, BinaryPoint} - - /** - * These implicit classes allow one to convert scala.Int|scala.BigInt to - * Chisel.UInt|Chisel.SInt by calling .asUInt|.asSInt on them, respectively. - * The versions .asUInt(width)|.asSInt(width) are also available to explicitly - * mark a width for the new literal. - * - * Also provides .asBool to scala.Boolean and .asUInt to String - * - * 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. - * - * Implementation note: the empty parameter list (like `U()`) is necessary to prevent - * interpreting calls that have a non-Width parameter as a chained apply, otherwise things like - * `0.asUInt(16)` (instead of `16.W`) compile without error and produce undesired results. - */ - implicit class fromBigIntToLiteral(bigint: BigInt) { - /** Int to Bool conversion, allowing compact syntax like 1.B and 0.B - */ - def B: Bool = bigint match { // scalastyle:ignore method.name - case bigint if bigint == 0 => Bool.Lit(false) - case bigint if bigint == 1 => Bool.Lit(true) - case bigint => Builder.error(s"Cannot convert $bigint to Bool, must be 0 or 1"); Bool.Lit(false) - } - /** Int to UInt conversion, recommended style for constants. - */ - def U: UInt = UInt.Lit(bigint, Width()) // scalastyle:ignore method.name - /** Int to SInt conversion, recommended style for constants. - */ - def S: SInt = SInt.Lit(bigint, Width()) // scalastyle:ignore method.name - /** Int to UInt conversion with specified width, recommended style for constants. - */ - def U(width: Width): UInt = UInt.Lit(bigint, width) // scalastyle:ignore method.name - /** Int to SInt conversion with specified width, recommended style for constants. - */ - def S(width: Width): SInt = SInt.Lit(bigint, width) // scalastyle:ignore method.name - - /** Int to UInt conversion, recommended style for variables. - */ - def asUInt(): UInt = UInt.Lit(bigint, Width()) - /** Int to SInt conversion, recommended style for variables. - */ - def asSInt(): SInt = SInt.Lit(bigint, Width()) - /** Int to UInt conversion with specified width, recommended style for variables. - */ - def asUInt(width: Width): UInt = UInt.Lit(bigint, width) - /** Int to SInt conversion with specified width, recommended style for variables. - */ - def asSInt(width: Width): SInt = SInt.Lit(bigint, width) - } - - implicit class fromIntToLiteral(int: Int) extends fromBigIntToLiteral(int) - implicit class fromLongToLiteral(long: Long) extends fromBigIntToLiteral(long) - - implicit class fromStringToLiteral(str: String) { - /** String to UInt parse, recommended style for constants. - */ - def U: UInt = str.asUInt() // scalastyle:ignore method.name - /** String to UInt parse with specified width, recommended style for constants. - */ - def U(width: Width): UInt = str.asUInt(width) // scalastyle:ignore method.name - - /** String to UInt parse, recommended style for variables. - */ - def asUInt(): UInt = { - val bigInt = parse(str) - UInt.Lit(bigInt, Width(bigInt.bitLength max 1)) - } - /** String to UInt parse with specified width, recommended style for variables. - */ - def asUInt(width: Width): UInt = UInt.Lit(parse(str), width) - - protected 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) - } - } - - implicit class fromBooleanToLiteral(boolean: Boolean) { - /** Boolean to Bool conversion, recommended style for constants. - */ - def B: Bool = Bool.Lit(boolean) // scalastyle:ignore method.name - - /** Boolean to Bool conversion, recommended style for variables. - */ - def asBool(): Bool = Bool.Lit(boolean) - } - - //scalastyle:off method.name - implicit class fromDoubleToLiteral(double: Double) { - @deprecated("Use notation <double>.F(<binary_point>.BP) instead", "chisel3") - def F(binaryPoint: Int): FixedPoint = FixedPoint.fromDouble(double, binaryPoint = binaryPoint) - def F(binaryPoint: BinaryPoint): FixedPoint = { - FixedPoint.fromDouble(double, Width(), binaryPoint) - } - def F(width: Width, binaryPoint: BinaryPoint): FixedPoint = { - FixedPoint.fromDouble(double, width, binaryPoint) - } - } - - implicit class fromIntToWidth(int: Int) { - def W: Width = Width(int) // scalastyle:ignore method.name - } - - implicit class fromIntToBinaryPoint(int: Int) { - def BP: BinaryPoint = BinaryPoint(int) // scalastyle:ignore method.name - } - - // These provide temporary compatibility for those who foolishly imported from chisel3.core - @deprecated("Avoid importing from chisel3.core, these are not public APIs and may change at any time. " + - " Use chisel3.experimental.RawModule instead.", "since the beginning of time") - type UserModule = chisel3.core.RawModule - @deprecated("Avoid importing from chisel3.core, these are not public APIs and may change at any time. " + - "Use chisel3.experimental.MultiIOModule instead.", "since the beginning of time") - type ImplicitModule = chisel3.core.MultiIOModule - } +package chisel3 + +package object core { + + /** + * These definitions exist to deal with those clients that relied on chisel3.core + * They will be deprecated in the future. + */ + @deprecated("Use the version in chisel3._", "3.3") + val CompileOptions = chisel3.CompileOptions + + @deprecated("Use the version in chisel3._", "3.3") + val Input = chisel3.Input + @deprecated("Use the version in chisel3._", "3.3") + val Output = chisel3.Output + @deprecated("Use the version in chisel3._", "3.3") + val Flipped = chisel3.Flipped + @deprecated("Use the version in chisel3._", "3.3") + val chiselTypeOf = chisel3.chiselTypeOf + + @deprecated("Use the version in chisel3._", "3.3") + type Data = chisel3.Data + + @deprecated("Use the version in chisel3._", "3.3") + val WireDefault = chisel3.WireDefault + + @deprecated("Use the version in chisel3._", "3.3") + val Clock = chisel3.Clock + @deprecated("Use the version in chisel3._", "3.3") + type Clock = chisel3.Clock + + @deprecated("Use the version in chisel3._", "3.3") + type Reset = chisel3.Reset + + @deprecated("Use the version in chisel3._", "3.3") + type Aggregate = chisel3.Aggregate + + @deprecated("Use the version in chisel3._", "3.3") + val Vec = chisel3.Vec + @deprecated("Use the version in chisel3._", "3.3") + val VecInit = chisel3.VecInit + @deprecated("Use the version in chisel3._", "3.3") + type Vec[T <: Data] = chisel3.Vec[T] + @deprecated("Use the version in chisel3._", "3.3") + type VecLike[T <: Data] = chisel3.VecLike[T] + @deprecated("Use the version in chisel3._", "3.3") + type Bundle = chisel3.Bundle + @deprecated("Use the version in chisel3._", "3.3") + type IgnoreSeqInBundle = chisel3.IgnoreSeqInBundle + @deprecated("Use the version in chisel3._", "3.3") + type Record = chisel3.Record + + @deprecated("Use the version in chisel3._", "3.3") + val assert = chisel3.assert + + @deprecated("Use the version in chisel3._", "3.3") + type Element = chisel3.Element + @deprecated("Use the version in chisel3._", "3.3") + type Bits = chisel3.Bits + + // These provide temporary compatibility for those who foolishly imported from chisel3.core + @deprecated("Avoid importing from chisel3.core, these are not public APIs and may change at any time. " + + " Use chisel3.experimental.RawModule instead.", "since the beginning of time") + type RawModule = chisel3.experimental.RawModule + @deprecated("Avoid importing from chisel3.core, these are not public APIs and may change at any time. " + + "Use chisel3.experimental.MultiIOModule instead.", "since the beginning of time") + type MultiIOModule = chisel3.experimental.MultiIOModule + @deprecated("Avoid importing from chisel3.core, these are not public APIs and may change at any time. " + + " Use chisel3.experimental.RawModule instead.", "since the beginning of time") + type UserModule = chisel3.experimental.RawModule + @deprecated("Avoid importing from chisel3.core, these are not public APIs and may change at any time. " + + "Use chisel3.experimental.MultiIOModule instead.", "since the beginning of time") + type ImplicitModule = chisel3.experimental.MultiIOModule + + @deprecated("Use the version in chisel3._", "3.3") + val Bits = chisel3.Bits + @deprecated("Use the version in chisel3._", "3.3") + type Num[T <: chisel3.Data] = chisel3.Num[T] + @deprecated("Use the version in chisel3._", "3.3") + type UInt = chisel3.UInt + @deprecated("Use the version in chisel3._", "3.3") + val UInt = chisel3.UInt + @deprecated("Use the version in chisel3._", "3.3") + type SInt = chisel3.SInt + @deprecated("Use the version in chisel3._", "3.3") + val SInt = chisel3.SInt + @deprecated("Use the version in chisel3._", "3.3") + type Bool = chisel3.Bool + @deprecated("Use the version in chisel3._", "3.3") + val Bool = chisel3.Bool + @deprecated("Use the version in chisel3._", "3.3") + val Mux = chisel3.Mux + + @deprecated("Use the version in chisel3._", "3.3") + type BlackBox = chisel3.BlackBox + + @deprecated("Use the version in chisel3._", "3.3") + val Mem = chisel3.Mem + @deprecated("Use the version in chisel3._", "3.3") + type MemBase[T <: chisel3.Data] = chisel3.MemBase[T] + @deprecated("Use the version in chisel3._", "3.3") + type Mem[T <: chisel3.Data] = chisel3.Mem[T] + @deprecated("Use the version in chisel3._", "3.3") + val SyncReadMem = chisel3.SyncReadMem + @deprecated("Use the version in chisel3._", "3.3") + type SyncReadMem[T <: chisel3.Data] = chisel3.SyncReadMem[T] + + @deprecated("Use the version in chisel3._", "3.3") + val Module = chisel3.Module + @deprecated("Use the version in chisel3._", "3.3") + type Module = chisel3.Module + + @deprecated("Use the version in chisel3._", "3.3") + val printf = chisel3.printf + + @deprecated("Use the version in chisel3._", "3.3") + val RegNext = chisel3.RegNext + @deprecated("Use the version in chisel3._", "3.3") + val RegInit = chisel3.RegInit + @deprecated("Use the version in chisel3._", "3.3") + val Reg = chisel3.Reg + + @deprecated("Use the version in chisel3._", "3.3") + val when = chisel3.when + @deprecated("Use the version in chisel3._", "3.3") + type WhenContext = chisel3.WhenContext + + @deprecated("Use the version in chisel3._", "3.3") + type Printable = chisel3.Printable + @deprecated("Use the version in chisel3._", "3.3") + val Printable = chisel3.Printable + @deprecated("Use the version in chisel3._", "3.3") + type Printables = chisel3.Printables + @deprecated("Use the version in chisel3._", "3.3") + val Printables = chisel3.Printables + @deprecated("Use the version in chisel3._", "3.3") + type PString = chisel3.PString + @deprecated("Use the version in chisel3._", "3.3") + val PString = chisel3.PString + @deprecated("Use the version in chisel3._", "3.3") + type FirrtlFormat = chisel3.FirrtlFormat + @deprecated("Use the version in chisel3._", "3.3") + val FirrtlFormat = chisel3.FirrtlFormat + @deprecated("Use the version in chisel3._", "3.3") + type Decimal = chisel3.Decimal + @deprecated("Use the version in chisel3._", "3.3") + val Decimal = chisel3.Decimal + @deprecated("Use the version in chisel3._", "3.3") + type Hexadecimal = chisel3.Hexadecimal + val Hexadecimal = chisel3.Hexadecimal + @deprecated("Use the version in chisel3._", "3.3") + type Binary = chisel3.Binary + @deprecated("Use the version in chisel3._", "3.3") + val Binary = chisel3.Binary + @deprecated("Use the version in chisel3._", "3.3") + type Character = chisel3.Character + @deprecated("Use the version in chisel3._", "3.3") + val Character = chisel3.Character + @deprecated("Use the version in chisel3._", "3.3") + type Name = chisel3.Name + @deprecated("Use the version in chisel3._", "3.3") + val Name = chisel3.Name + @deprecated("Use the version in chisel3._", "3.3") + type FullName = chisel3.FullName + @deprecated("Use the version in chisel3._", "3.3") + val FullName = chisel3.FullName + @deprecated("Use the version in chisel3._", "3.3") + val Percent = chisel3.Percent + + @deprecated("Use the version in chisel3.experimental._", "3.3") + type Param = chisel3.experimental.Param + @deprecated("Use the version in chisel3.experimental._", "3.3") + type IntParam = chisel3.experimental.IntParam + @deprecated("Use the version in chisel3.experimental._", "3.3") + val IntParam = chisel3.experimental.IntParam + @deprecated("Use the version in chisel3.experimental._", "3.3") + type DoubleParam = chisel3.experimental.DoubleParam + @deprecated("Use the version in chisel3.experimental._", "3.3") + val DoubleParam = chisel3.experimental.DoubleParam + @deprecated("Use the version in chisel3.experimental._", "3.3") + type StringParam = chisel3.experimental.StringParam + @deprecated("Use the version in chisel3.experimental._", "3.3") + val StringParam = chisel3.experimental.StringParam + @deprecated("Use the version in chisel3.experimental._", "3.3") + type RawParam = chisel3.experimental.RawParam + @deprecated("Use the version in chisel3.experimental._", "3.3") + val RawParam = chisel3.experimental.RawParam + + @deprecated("Use the version in chisel3.experimental._", "3.3") + type Analog = chisel3.experimental.Analog + @deprecated("Use the version in chisel3.experimental._", "3.3") + val Analog = chisel3.experimental.Analog + + @deprecated("Use the version in chisel3._", "3.3") + implicit class fromIntToWidth(int: Int) extends chisel3.fromIntToWidth(int) + + @deprecated("Use the version in chisel3.experimental._", "3.3") + val attach = chisel3.experimental.attach + + @deprecated("Use the version in chisel3.experimental._", "3.3") + type EnumType = chisel3.experimental.EnumType + @deprecated("Use the version in chisel3.experimental._", "3.3") + type EnumFactory = chisel3.experimental.EnumFactory + @deprecated("Use the version in chisel3.experimental._", "3.3") + val EnumAnnotations = chisel3.experimental.EnumAnnotations + + @deprecated("Use the version in chisel3._", "3.3") + val withClockAndReset = chisel3.withClockAndReset + @deprecated("Use the version in chisel3._", "3.3") + val withClock = chisel3.withClock + @deprecated("Use the version in chisel3._", "3.3") + val withReset = chisel3.withReset + + @deprecated("Use the version in chisel3.experimental._", "3.3") + val dontTouch = chisel3.experimental.dontTouch + + @deprecated("Use the version in chisel3.experimental._", "3.3") + type BaseModule = chisel3.experimental.BaseModule + @deprecated("Use the version in chisel3.experimental._", "3.3") + type ExtModule = chisel3.experimental.ExtModule + + @deprecated("Use the version in chisel3.experimental._", "3.3") + val IO = chisel3.experimental.IO + + @deprecated("Use the version in chisel3.experimental._", "3.3") + type FixedPoint = chisel3.experimental.FixedPoint + @deprecated("Use the version in chisel3.experimental._", "3.3") + val FixedPoint = chisel3.experimental.FixedPoint + @deprecated("Use the version in chisel3.experimental._", "3.3") + implicit class fromDoubleToLiteral(double: Double) extends experimental.FixedPoint.Implicits.fromDoubleToLiteral(double) + @deprecated("Use the version in chisel3.experimental._", "3.3") + implicit class fromIntToBinaryPoint(int: Int) extends experimental.FixedPoint.Implicits.fromIntToBinaryPoint(int) + + @deprecated("Use the version in chisel3.experimental._", "3.3") + type ChiselAnnotation = chisel3.experimental.ChiselAnnotation + @deprecated("Use the version in chisel3.experimental._", "3.3") + val ChiselAnnotation = chisel3.experimental.ChiselAnnotation + @deprecated("Use the version in chisel3.experimental._", "3.3") + type RunFirrtlTransform = chisel3.experimental.RunFirrtlTransform + + @deprecated("Use the version in chisel3.experimental._", "3.3") + val annotate = chisel3.experimental.annotate + + @deprecated("Use the version in chisel3.experimental._", "3.3") + val DataMirror = chisel3.experimental.DataMirror + @deprecated("Use the version in chisel3._", "3.3") + type ActualDirection = chisel3.ActualDirection + @deprecated("Use the version in chisel3._", "3.3") + val ActualDirection = chisel3.ActualDirection + + @deprecated("Use the version in chisel3.internal._", "3.3") + val requireIsHardware = chisel3.internal.requireIsHardware + @deprecated("Use the version in chisel3.internal._", "3.3") + val requireIsChiselType = chisel3.internal.requireIsChiselType + @deprecated("Use the version in chisel3.internal._", "3.3") + val BiConnect = chisel3.internal.BiConnect + @deprecated("Use the version in chisel3.internal._", "3.3") + val MonoConnect = chisel3.internal.MonoConnect + @deprecated("Use the version in chisel3.internal._", "3.3") + val BindingDirection = chisel3.internal.BindingDirection + @deprecated("Use the version in chisel3.internal._", "3.3") + type Binding = chisel3.internal.Binding + @deprecated("Use the version in chisel3.internal._", "3.3") + type TopBinding = chisel3.internal.TopBinding + @deprecated("Use the version in chisel3.internal._", "3.3") + type UnconstrainedBinding = chisel3.internal.UnconstrainedBinding + @deprecated("Use the version in chisel3.internal._", "3.3") + type ConstrainedBinding = chisel3.internal.ConstrainedBinding + @deprecated("Use the version in chisel3.internal._", "3.3") + type ReadOnlyBinding = chisel3.internal.ReadOnlyBinding + @deprecated("Use the version in chisel3.internal._", "3.3") + type OpBinding = chisel3.internal.OpBinding + @deprecated("Use the version in chisel3.internal._", "3.3") + type MemoryPortBinding = chisel3.internal.MemoryPortBinding + @deprecated("Use the version in chisel3.internal._", "3.3") + type PortBinding = chisel3.internal.PortBinding + @deprecated("Use the version in chisel3.internal._", "3.3") + type RegBinding = chisel3.internal.RegBinding + @deprecated("Use the version in chisel3.internal._", "3.3") + type WireBinding = chisel3.internal.WireBinding + @deprecated("Use the version in chisel3.internal._", "3.3") + type ChildBinding = chisel3.internal.ChildBinding + @deprecated("Use the version in chisel3.internal._", "3.3") + type DontCareBinding = chisel3.internal.DontCareBinding + @deprecated("Use the version in chisel3.internal._", "3.3") + type LitBinding = chisel3.internal.LitBinding + @deprecated("Use the version in chisel3.internal._", "3.3") + type ElementLitBinding = chisel3.internal.ElementLitBinding + @deprecated("Use the version in chisel3.internal._", "3.3") + type BundleLitBinding = chisel3.internal.BundleLitBinding } diff --git a/chiselFrontend/src/main/scala/chisel3/experimental/package.scala b/chiselFrontend/src/main/scala/chisel3/experimental/package.scala new file mode 100644 index 00000000..7d57970d --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/experimental/package.scala @@ -0,0 +1,84 @@ +// See LICENSE for license details. + +package chisel3 + +/** Package for experimental features, which may have their API changed, be removed, etc. + * + * Because its contents won't necessarily have the same level of stability and support as + * non-experimental, you must explicitly import this package to use its contents. + */ +package object experimental { // scalastyle:ignore object.name + import scala.language.implicitConversions + import chisel3.internal.BaseModule + + // Implicit conversions for BlackBox Parameters + implicit def fromIntToIntParam(x: Int): IntParam = IntParam(BigInt(x)) + implicit def fromLongToIntParam(x: Long): IntParam = IntParam(BigInt(x)) + implicit def fromBigIntToIntParam(x: BigInt): IntParam = IntParam(x) + implicit def fromDoubleToDoubleParam(x: Double): DoubleParam = DoubleParam(x) + implicit def fromStringToStringParam(x: String): StringParam = StringParam(x) + + type ChiselEnum = EnumFactory + + @deprecated("Use the version in chisel3._", "chisel3.2") + val withClockAndReset = chisel3.withClockAndReset + @deprecated("Use the version in chisel3._", "chisel3.2") + val withClock = chisel3.withClock + @deprecated("Use the version in chisel3._", "chisel3.2") + val withReset = chisel3.withReset + + // Rocket Chip-style clonemodule + + /** A record containing the results of CloneModuleAsRecord + * The apply method is retrieves the element with the supplied name. + */ + type ClonePorts = BaseModule.ClonePorts + + object CloneModuleAsRecord { + /** Clones an existing module and returns a record of all its top-level ports. + * Each element of the record is named with a string matching the + * corresponding port's name and shares the port's type. + * @example {{{ + * val q1 = Module(new Queue(UInt(32.W), 2)) + * val q2_io = CloneModuleAsRecord(q1)("io").asInstanceOf[q1.io.type] + * q2_io.enq <> q1.io.deq + * }}} + */ + def apply(proto: BaseModule)(implicit sourceInfo: chisel3.internal.sourceinfo.SourceInfo, compileOptions: CompileOptions): ClonePorts = { // scalastyle:ignore line.size.limit + BaseModule.cloneIORecord(proto) + } + } + + val requireIsHardware = chisel3.internal.requireIsHardware + val requireIsChiselType = chisel3.internal.requireIsChiselType + type Direction = ActualDirection + val Direction = ActualDirection + + implicit class ChiselRange(val sc: StringContext) extends AnyVal { + import chisel3.internal.firrtl.NumericBound + + import scala.language.experimental.macros + + /** Specifies a range using mathematical range notation. Variables can be interpolated using + * standard string interpolation syntax. + * @example {{{ + * UInt(range"[0, 2)") + * UInt(range"[0, \$myInt)") + * UInt(range"[0, \${myInt + 2})") + * }}} + */ + def range(args: Any*): (NumericBound[Int], NumericBound[Int]) = macro chisel3.internal.RangeTransform.apply + } + + class dump extends chisel3.internal.naming.dump // scalastyle:ignore class.name + class treedump extends chisel3.internal.naming.treedump // scalastyle:ignore class.name + class chiselName extends chisel3.internal.naming.chiselName // scalastyle:ignore class.name + + object BundleLiterals { + implicit class AddBundleLiteralConstructor[T <: Bundle](x: T) { + def Lit(elems: (T => (Data, Data))*): T = { + x._makeLit(elems: _*) + } + } + } +} diff --git a/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala b/chiselFrontend/src/main/scala/chisel3/internal/BiConnect.scala index b1f9bcb5..e122f13a 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/BiConnect.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/BiConnect.scala @@ -1,8 +1,9 @@ // See LICENSE for license details. -package chisel3.core +package chisel3.internal -import chisel3.internal.ChiselException +import chisel3._ +import chisel3.experimental.{Analog, BaseModule, RawModule, attach} import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl.{Connect, DefInvalid} import scala.language.experimental.macros @@ -22,10 +23,9 @@ import chisel3.internal.sourceinfo._ * */ -object BiConnect { +private[chisel3] object BiConnect { // scalastyle:off method.name public.methods.have.type // These are all the possible exceptions that can be thrown. - case class BiConnectException(message: String) extends ChiselException(message) // These are from element-level connection def BothDriversException = BiConnectException(": Both Left and Right are drivers") diff --git a/chiselFrontend/src/main/scala/chisel3/core/Binding.scala b/chiselFrontend/src/main/scala/chisel3/internal/Binding.scala index e30b91ec..34de36a3 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Binding.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/Binding.scala @@ -1,27 +1,11 @@ // See LICENSE for license details. -package chisel3.core +package chisel3.internal -import chisel3.internal.ChiselException -import chisel3.internal.Builder.{forcedModule} +import chisel3._ +import chisel3.experimental.{BaseModule, RawModule} import chisel3.internal.firrtl.LitArg -object Binding { - class BindingException(message: String) extends ChiselException(message) - /** A function expected a Chisel type but got a hardware object - */ - case class ExpectedChiselTypeException(message: String) extends BindingException(message) - /**A function expected a hardware object but got a Chisel type - */ - case class ExpectedHardwareException(message: String) extends BindingException(message) - /** An aggregate had a mix of specified and unspecified directionality children - */ - case class MixedDirectionAggregateException(message: String) extends BindingException(message) - /** Attempted to re-bind an already bound (directionality or hardware) object - */ - case class RebindingException(message: String) extends BindingException(message) -} - /** Requires that a node is hardware ("bound") */ object requireIsHardware { @@ -32,7 +16,7 @@ object requireIsHardware { } if (!node.isSynthesizable) { val prefix = if (msg.nonEmpty) s"$msg " else "" - throw Binding.ExpectedHardwareException(s"$prefix'$node' must be hardware, " + + throw ExpectedHardwareException(s"$prefix'$node' must be hardware, " + "not a bare Chisel type. Perhaps you forgot to wrap it in Wire(_) or IO(_)?") } } @@ -43,13 +27,13 @@ object requireIsHardware { object requireIsChiselType { def apply(node: Data, msg: String = ""): Unit = if (node.isSynthesizable) { val prefix = if (msg.nonEmpty) s"$msg " else "" - throw Binding.ExpectedChiselTypeException(s"$prefix'$node' must be a Chisel type, not hardware") + throw ExpectedChiselTypeException(s"$prefix'$node' must be a Chisel type, not hardware") } } // Element only direction used for the Binding system only. -sealed abstract class BindingDirection -object BindingDirection { +private[chisel3] sealed abstract class BindingDirection +private[chisel3] object BindingDirection { /** Internal type or wire */ case object Internal extends BindingDirection diff --git a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala index d825f39d..664813f7 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala @@ -3,10 +3,11 @@ package chisel3.internal import scala.util.DynamicVariable -import scala.collection.mutable.{ArrayBuffer, HashMap} +import scala.collection.mutable.ArrayBuffer import chisel3._ -import core._ -import firrtl._ +import chisel3.experimental._ +import chisel3.internal.firrtl._ +import chisel3.internal.naming._ import _root_.firrtl.annotations.{CircuitName, ComponentName, ModuleName, Named} private[chisel3] class Namespace(keywords: Set[String]) { @@ -186,7 +187,7 @@ private[chisel3] class DynamicContext() { var currentClock: Option[Clock] = None var currentReset: Option[Reset] = None val errors = new ErrorLog - val namingStack = new internal.naming.NamingStack + val namingStack = new NamingStack } //scalastyle:off number.of.methods @@ -204,7 +205,7 @@ private[chisel3] object Builder { private def initializeSingletons(): Unit = { // This used to contain: // val dummy = core.DontCare - // but this would occasionally produce hangs dues to static initialization deadlock + // but this would occasionally produce hangs due to static initialization deadlock // when Builder initialization collided with chisel3.package initialization of the DontCare value. // See: // http://ternarysearch.blogspot.com/2013/07/static-initialization-deadlock.html @@ -212,14 +213,14 @@ private[chisel3] object Builder { // https://stackoverflow.com/questions/28631656/runnable-thread-state-but-in-object-wait } - def namingStackOption: Option[internal.naming.NamingStack] = dynamicContextVar.value.map(_.namingStack) + def namingStackOption: Option[NamingStack] = dynamicContextVar.value.map(_.namingStack) def idGen: IdGen = chiselContext.value.idGen def globalNamespace: Namespace = dynamicContext.globalNamespace def components: ArrayBuffer[Component] = dynamicContext.components def annotations: ArrayBuffer[ChiselAnnotation] = dynamicContext.annotations - def namingStack: internal.naming.NamingStack = dynamicContext.namingStack + def namingStack: NamingStack = dynamicContext.namingStack def currentModule: Option[BaseModule] = dynamicContextVar.value match { case Some(dyanmicContext) => dynamicContext.currentModule @@ -366,19 +367,19 @@ private[chisel3] object Builder { * objects. */ object DynamicNamingStack { - def pushContext(): internal.naming.NamingContextInterface = { + def pushContext(): NamingContextInterface = { Builder.namingStackOption match { case Some(namingStack) => namingStack.pushContext() - case None => internal.naming.DummyNamer + case None => DummyNamer } } - def popReturnContext[T <: Any](prefixRef: T, until: internal.naming.NamingContextInterface): T = { + def popReturnContext[T <: Any](prefixRef: T, until: NamingContextInterface): T = { until match { - case internal.naming.DummyNamer => + case DummyNamer => require(Builder.namingStackOption.isEmpty, "Builder context must remain stable throughout a chiselName-annotated function invocation") - case context: internal.naming.NamingContext => + case context: NamingContext => require(Builder.namingStackOption.isDefined, "Builder context must remain stable throughout a chiselName-annotated function invocation") Builder.namingStackOption.get.popContext(prefixRef, context) diff --git a/chiselFrontend/src/main/scala/chisel3/internal/Error.scala b/chiselFrontend/src/main/scala/chisel3/internal/Error.scala index 59f32542..91d9d7de 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/Error.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/Error.scala @@ -4,8 +4,6 @@ package chisel3.internal import scala.collection.mutable.{ArrayBuffer, LinkedHashMap} -import chisel3.core._ - class ChiselException(message: String, cause: Throwable = null) extends Exception(message, cause) { val blacklistPackages = Set("chisel3", "scala", "java", "sun", "sbt") @@ -126,7 +124,7 @@ private[chisel3] class ErrorLog { "java.", "scala.", "chisel3.internal.", - "chisel3.core.", + "chisel3.experimental.", "chisel3.package$" // for some compatibility / deprecated types ) !chiselPrefixes.filter(className.startsWith(_)).isEmpty diff --git a/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala b/chiselFrontend/src/main/scala/chisel3/internal/MonoConnect.scala index 6a4ae9bf..91f1bfd8 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/MonoConnect.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/MonoConnect.scala @@ -1,8 +1,9 @@ // See LICENSE for license details. -package chisel3.core +package chisel3.internal -import chisel3.internal.ChiselException +import chisel3._ +import chisel3.experimental.{BaseModule, EnumType, FixedPoint, RawModule, UnsafeEnum} import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl.{Connect, DefInvalid} import scala.language.experimental.macros @@ -32,10 +33,9 @@ import chisel3.internal.sourceinfo.SourceInfo * - Is a port of the current module or submodule of the current module */ -object MonoConnect { +private[chisel3] object MonoConnect { // scalastyle:off method.name public.methods.have.type // These are all the possible exceptions that can be thrown. - case class MonoConnectException(message: String) extends ChiselException(message) // These are from element-level connection def UnreadableSourceException = MonoConnectException(": Source is unreadable from current module.") diff --git a/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala index 7854efdb..2cb4d092 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala @@ -3,9 +3,9 @@ package chisel3.internal.firrtl import chisel3._ -import core._ import chisel3.internal._ -import chisel3.internal.sourceinfo.{SourceInfo, NoSourceInfo} +import chisel3.internal.sourceinfo.SourceInfo +import chisel3.experimental.{BaseModule, ChiselAnnotation, Param, RawModule} // scalastyle:off number.of.types diff --git a/chiselFrontend/src/main/scala/chisel3/package.scala b/chiselFrontend/src/main/scala/chisel3/package.scala new file mode 100644 index 00000000..d6c590b4 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/package.scala @@ -0,0 +1,359 @@ +// See LICENSE for license details. + +package object chisel3 { // scalastyle:ignore package.object.name + import internal.firrtl.{Port, Width} + import internal.sourceinfo.{SourceInfo, VecTransform} + import internal.{Builder, chiselRuntimeDeprecated} + + import scala.language.implicitConversions + + /** + * These implicit classes allow one to convert scala.Int|scala.BigInt to + * Chisel.UInt|Chisel.SInt by calling .asUInt|.asSInt on them, respectively. + * The versions .asUInt(width)|.asSInt(width) are also available to explicitly + * mark a width for the new literal. + * + * Also provides .asBool to scala.Boolean and .asUInt to String + * + * 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. + * + * Implementation note: the empty parameter list (like `U()`) is necessary to prevent + * interpreting calls that have a non-Width parameter as a chained apply, otherwise things like + * `0.asUInt(16)` (instead of `16.W`) compile without error and produce undesired results. + */ + implicit class fromBigIntToLiteral(bigint: BigInt) { + /** Int to Bool conversion, allowing compact syntax like 1.B and 0.B + */ + def B: Bool = bigint match { // scalastyle:ignore method.name + case bigint if bigint == 0 => Bool.Lit(false) + case bigint if bigint == 1 => Bool.Lit(true) + case bigint => Builder.error(s"Cannot convert $bigint to Bool, must be 0 or 1"); Bool.Lit(false) + } + /** Int to UInt conversion, recommended style for constants. + */ + def U: UInt = UInt.Lit(bigint, Width()) // scalastyle:ignore method.name + /** Int to SInt conversion, recommended style for constants. + */ + def S: SInt = SInt.Lit(bigint, Width()) // scalastyle:ignore method.name + /** Int to UInt conversion with specified width, recommended style for constants. + */ + def U(width: Width): UInt = UInt.Lit(bigint, width) // scalastyle:ignore method.name + /** Int to SInt conversion with specified width, recommended style for constants. + */ + def S(width: Width): SInt = SInt.Lit(bigint, width) // scalastyle:ignore method.name + + /** Int to UInt conversion, recommended style for variables. + */ + def asUInt(): UInt = UInt.Lit(bigint, Width()) + /** Int to SInt conversion, recommended style for variables. + */ + def asSInt(): SInt = SInt.Lit(bigint, Width()) + /** Int to UInt conversion with specified width, recommended style for variables. + */ + def asUInt(width: Width): UInt = UInt.Lit(bigint, width) + /** Int to SInt conversion with specified width, recommended style for variables. + */ + def asSInt(width: Width): SInt = SInt.Lit(bigint, width) + } + + implicit class fromIntToLiteral(int: Int) extends fromBigIntToLiteral(int) + implicit class fromLongToLiteral(long: Long) extends fromBigIntToLiteral(long) + + implicit class fromStringToLiteral(str: String) { + /** String to UInt parse, recommended style for constants. + */ + def U: UInt = str.asUInt() // scalastyle:ignore method.name + /** String to UInt parse with specified width, recommended style for constants. + */ + def U(width: Width): UInt = str.asUInt(width) // scalastyle:ignore method.name + + /** String to UInt parse, recommended style for variables. + */ + def asUInt(): UInt = { + val bigInt = parse(str) + UInt.Lit(bigInt, Width(bigInt.bitLength max 1)) + } + /** String to UInt parse with specified width, recommended style for variables. + */ + def asUInt(width: Width): UInt = UInt.Lit(parse(str), width) + + protected 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) + } + } + + implicit class fromBooleanToLiteral(boolean: Boolean) { + /** Boolean to Bool conversion, recommended style for constants. + */ + def B: Bool = Bool.Lit(boolean) // scalastyle:ignore method.name + + /** Boolean to Bool conversion, recommended style for variables. + */ + def asBool(): Bool = Bool.Lit(boolean) + } + + // Fixed Point is experimental for now, but we alias the implicit conversion classes here + // to minimize disruption with existing code. + implicit class fromDoubleToLiteral(double: Double) extends experimental.FixedPoint.Implicits.fromDoubleToLiteral(double) + implicit class fromIntToBinaryPoint(int: Int) extends experimental.FixedPoint.Implicits.fromIntToBinaryPoint(int) + + implicit class fromIntToWidth(int: Int) { + def W: Width = Width(int) // scalastyle:ignore method.name + } + + val WireInit = WireDefault + + implicit class AddDirectionToData[T<:Data](target: T) { + @chiselRuntimeDeprecated + @deprecated("Input(Data) should be used over Data.asInput", "chisel3") + def asInput(implicit compileOptions: CompileOptions): T = Input(target) + + @chiselRuntimeDeprecated + @deprecated("Output(Data) should be used over Data.asOutput", "chisel3") + def asOutput(implicit compileOptions: CompileOptions): T = Output(target) + + @chiselRuntimeDeprecated + @deprecated("Flipped(Data) should be used over Data.flip", "chisel3") + def flip()(implicit compileOptions: CompileOptions): T = Flipped(target) + } + + implicit class fromBitsable[T <: Data](data: T) { + + @chiselRuntimeDeprecated + @deprecated("fromBits is deprecated, use asTypeOf instead", "chisel3") + def fromBits(that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = { + that.asTypeOf(data) + } + } + + implicit class cloneTypeable[T <: Data](target: T) { + @chiselRuntimeDeprecated + @deprecated("chiselCloneType is deprecated, use chiselTypeOf(...) to get the Chisel Type of a hardware object", "chisel3") // scalastyle:ignore line.size.limit + def chiselCloneType: T = { + target.cloneTypeFull.asInstanceOf[T] + } + } + + object Vec extends VecFactory { + import scala.language.experimental.macros + + @chiselRuntimeDeprecated + @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)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): chisel3.Vec[T] = + apply(n, gen) + + @chiselRuntimeDeprecated + @deprecated("Vec.fill(n)(gen) is deprecated, use VecInit(Seq.fill(n)(gen)) instead", "chisel3") + def fill[T <: Data](n: Int)(gen: => T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): chisel3.Vec[T] = + apply(Seq.fill(n)(gen)) + + def apply[T <: Data](elts: Seq[T]): chisel3.Vec[T] = macro VecTransform.apply_elts + @chiselRuntimeDeprecated + @deprecated("Vec(elts) is deprecated, use VecInit(elts) instead", "chisel3") + def do_apply[T <: Data](elts: Seq[T])(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): chisel3.Vec[T] = + chisel3.VecInit(elts) + + def apply[T <: Data](elt0: T, elts: T*): chisel3.Vec[T] = macro VecTransform.apply_elt0 + @chiselRuntimeDeprecated + @deprecated("Vec(elt0, ...) is deprecated, use VecInit(elt0, ...) instead", "chisel3") + def do_apply[T <: Data](elt0: T, elts: T*) + (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): chisel3.Vec[T] = + VecInit(elt0 +: elts.toSeq) + + def tabulate[T <: Data](n: Int)(gen: (Int) => T): chisel3.Vec[T] = macro VecTransform.tabulate + @chiselRuntimeDeprecated + @deprecated("Vec.tabulate(n)(gen) is deprecated, use VecInit.tabulate(n)(gen) instead", "chisel3") + def do_tabulate[T <: Data](n: Int)(gen: (Int) => T) + (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): chisel3.Vec[T] = + chisel3.VecInit.tabulate(n)(gen) + } + + // Some possible regex replacements for the literal specifier deprecation: + // (note: these are not guaranteed to handle all edge cases! check all replacements!) + // Bool\((true|false)\) + // => $1.B + // UInt\(width\s*=\s*(\d+|[_a-zA-Z][_0-9a-zA-Z]*)\) + // => UInt($1.W) + // (UInt|SInt|Bits).width\((\d+|[_a-zA-Z][_0-9a-zA-Z]*)\) + // => $1($2.W) + // (U|S)Int\((-?\d+|0[xX][0-9a-fA-F]+)\) + // => $2.$1 + // UInt\((\d+|0[xX][0-9a-fA-F]+),\s*(?:width\s*=)?\s*(\d+|[_a-zA-Z][_0-9a-zA-Z]*)\) + // => $1.U($2.W) + // (UInt|SInt|Bool)\(([_a-zA-Z][_0-9a-zA-Z]*)\) + // => $2.as$1 + // (UInt|SInt)\(([_a-zA-Z][_0-9a-zA-Z]*),\s*(?:width\s*=)?\s*(\d+|[_a-zA-Z][_0-9a-zA-Z]*)\) + // => $2.as$1($3.W) + + /** This contains literal constructor factory methods that are deprecated as of Chisel3. + * These will be removed very soon. It's recommended you port your code ASAP. + */ + trait UIntFactory extends UIntFactoryBase { + /** Create a UInt literal with inferred width. */ + @chiselRuntimeDeprecated + @deprecated("use n.U", "chisel3, will be removed by end of 2017") + def apply(n: String): UInt = n.asUInt + + /** Create a UInt literal with fixed width. */ + @chiselRuntimeDeprecated + @deprecated("use n.U(width.W)", "chisel3, will be removed by end of 2017") + def apply(n: String, width: Int): UInt = n.asUInt(width.W) + + /** Create a UInt literal with specified width. */ + @chiselRuntimeDeprecated + @deprecated("use value.U(width)", "chisel3, will be removed by end of 2017") + def apply(value: BigInt, width: Width): UInt = value.asUInt(width) + + /** Create a UInt literal with fixed width. */ + @chiselRuntimeDeprecated + @deprecated("use value.U(width.W)", "chisel3, will be removed by end of 2017") + def apply(value: BigInt, width: Int): UInt = value.asUInt(width.W) + + /** Create a UInt literal with inferred width.- compatibility with Chisel2. */ + @chiselRuntimeDeprecated + @deprecated("use value.U", "chisel3, will be removed by end of 2017") + def apply(value: BigInt): UInt = value.asUInt + + /** Create a UInt with a specified width */ + @chiselRuntimeDeprecated + @deprecated("use UInt(width.W)", "chisel3, will be removed by end of 2017") + def width(width: Int): UInt = apply(width.W) + + /** Create a UInt port with specified width. */ + @chiselRuntimeDeprecated + @deprecated("use UInt(width)", "chisel3, will be removed by end of 2017") + def width(width: Width): UInt = apply(width) + } + + /** This contains literal constructor factory methods that are deprecated as of Chisel3. + * These will be removed very soon. It's recommended you move your code soon. + */ + trait SIntFactory extends SIntFactoryBase { + /** Create a SInt type or port with fixed width. */ + @chiselRuntimeDeprecated + @deprecated("use SInt(width.W)", "chisel3, will be removed by end of 2017") + def width(width: Int): SInt = apply(width.W) + + /** Create an SInt type with specified width. */ + @chiselRuntimeDeprecated + @deprecated("use SInt(width)", "chisel3, will be removed by end of 2017") + def width(width: Width): SInt = apply(width) + + /** Create an SInt literal with inferred width. */ + @chiselRuntimeDeprecated + @deprecated("use value.S", "chisel3, will be removed by end of 2017") + def apply(value: BigInt): SInt = value.asSInt + + /** Create an SInt literal with fixed width. */ + @chiselRuntimeDeprecated + @deprecated("use value.S(width.W)", "chisel3, will be removed by end of 2017") + def apply(value: BigInt, width: Int): SInt = value.asSInt(width.W) + + /** Create an SInt literal with specified width. */ + @chiselRuntimeDeprecated + @deprecated("use value.S(width)", "chisel3, will be removed by end of 2017") + def apply(value: BigInt, width: Width): SInt = value.asSInt(width) + + @chiselRuntimeDeprecated + @deprecated("use value.S", "chisel3, will be removed by end of 2017") + def Lit(value: BigInt): SInt = value.asSInt // scalastyle:ignore method.name + + @chiselRuntimeDeprecated + @deprecated("use value.S(width)", "chisel3, will be removed by end of 2017") + def Lit(value: BigInt, width: Int): SInt = value.asSInt(width.W) // scalastyle:ignore method.name + } + + /** This contains literal constructor factory methods that are deprecated as of Chisel3. + * These will be removed very soon. It's recommended you move your code soon. + */ + trait BoolFactory extends BoolFactoryBase { + /** Creates Bool literal. + */ + @chiselRuntimeDeprecated + @deprecated("use x.B", "chisel3, will be removed by end of 2017") + def apply(x: Boolean): Bool = x.B + } + + object Bits extends UIntFactory + object UInt extends UIntFactory + object SInt extends SIntFactory + object Bool extends BoolFactory + + type InstanceId = internal.InstanceId + + @deprecated("Use 'SyncReadMem'", "chisel3") + val SeqMem = chisel3.SyncReadMem + @deprecated("Use 'SyncReadMem'", "chisel3") + type SeqMem[T <: Data] = SyncReadMem[T] + + type Module = chisel3.experimental.LegacyModule + + /** Implicit for custom Printable string interpolator */ + implicit class PrintableHelper(val sc: StringContext) extends AnyVal { + /** Custom string interpolator for generating Printables: p"..." + * Will call .toString on any non-Printable arguments (mimicking s"...") + */ + def p(args: Any*): Printable = { + sc.checkLengths(args) // Enforce sc.parts.size == pargs.size + 1 + val pargs: Seq[Option[Printable]] = args map { + case p: Printable => Some(p) + case d: Data => Some(d.toPrintable) + case any => for { + v <- Option(any) // Handle null inputs + str = v.toString + if !str.isEmpty // Handle empty Strings + } yield PString(str) + } + val parts = sc.parts map StringContext.treatEscapes + // Zip sc.parts and pargs together ito flat Seq + // eg. Seq(sc.parts(0), pargs(0), sc.parts(1), pargs(1), ...) + val seq = for { // append None because sc.parts.size == pargs.size + 1 + (literal, arg) <- parts zip (pargs :+ None) + optPable <- Seq(Some(PString(literal)), arg) + pable <- optPable // Remove Option[_] + } yield pable + Printables(seq) + } + } + + implicit def string2Printable(str: String): Printable = PString(str) + + type ChiselException = internal.ChiselException + + // Debugger/Tester access to internal Chisel data structures and methods. + def getDataElements(a: Aggregate): Seq[Element] = { + a.allElements + } + def getModulePorts(m: Module): Seq[Port] = m.getPorts + // Invalidate API - a DontCare element for explicit assignment to outputs, + // indicating the signal is intentionally not driven. + val DontCare = chisel3.internal.InternalDontCare + + class BindingException(message: String) extends ChiselException(message) + /** A function expected a Chisel type but got a hardware object + */ + case class ExpectedChiselTypeException(message: String) extends BindingException(message) + /**A function expected a hardware object but got a Chisel type + */ + case class ExpectedHardwareException(message: String) extends BindingException(message) + /** An aggregate had a mix of specified and unspecified directionality children + */ + case class MixedDirectionAggregateException(message: String) extends BindingException(message) + /** Attempted to re-bind an already bound (directionality or hardware) object + */ + case class RebindingException(message: String) extends BindingException(message) + // Connection exceptions. + case class BiConnectException(message: String) extends ChiselException(message) + case class MonoConnectException(message: String) extends ChiselException(message) +} |
