diff options
Diffstat (limited to 'chiselFrontend/src')
13 files changed, 289 insertions, 180 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala index de7af462..9bbf9d0e 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala @@ -123,10 +123,10 @@ object Vec { /** Truncate an index to implement modulo-power-of-2 addressing. */ private[core] def truncateIndex(idx: UInt, n: Int)(implicit sourceInfo: SourceInfo): UInt = { val w = BigInt(n-1).bitLength - if (n <= 1) UInt(0) + if (n <= 1) 0.U else if (idx.width.known && idx.width.get <= w) idx else if (idx.width.known) idx(w-1,0) - else (idx | UInt(0, w))(w-1,0) + else (idx | 0.U(w.W))(w-1,0) } } @@ -225,7 +225,7 @@ sealed class Vec[T <: Data] private (gen: => T, val length: Int) private[chisel3] lazy val flatten: IndexedSeq[Bits] = (0 until length).flatMap(i => this.apply(i).flatten) - for ((elt, i) <- self zipWithIndex) + for ((elt, i) <- self.zipWithIndex) elt.setRef(this, i) /** Default "pretty-print" implementation @@ -249,7 +249,7 @@ trait VecLike[T <: Data] extends collection.IndexedSeq[T] with HasId { // IndexedSeq has its own hashCode/equals that we must not use override def hashCode: Int = super[HasId].hashCode override def equals(that: Any): Boolean = super[HasId].equals(that) - + @deprecated("Use Vec.apply instead", "chisel3") def read(idx: UInt): T @@ -261,14 +261,14 @@ trait VecLike[T <: Data] extends collection.IndexedSeq[T] with HasId { def forall(p: T => Bool): Bool = macro SourceInfoTransform.pArg def do_forall(p: T => Bool)(implicit sourceInfo: SourceInfo): Bool = - (this map p).fold(Bool(true))(_ && _) + (this map p).fold(true.B)(_ && _) /** Outputs true if p outputs true for at least one element. */ def exists(p: T => Bool): Bool = macro SourceInfoTransform.pArg def do_exists(p: T => Bool)(implicit sourceInfo: SourceInfo): Bool = - (this map p).fold(Bool(false))(_ || _) + (this map p).fold(false.B)(_ || _) /** Outputs true if the vector contains at least one element equal to x (using * the === operator). @@ -288,7 +288,7 @@ trait VecLike[T <: Data] extends collection.IndexedSeq[T] with HasId { /** Helper function that appends an index (literal value) to each element, * useful for hardware generators which output an index. */ - private def indexWhereHelper(p: T => Bool) = this map p zip (0 until length).map(i => UInt(i)) + private def indexWhereHelper(p: T => Bool) = this map p zip (0 until length).map(i => i.asUInt) /** Outputs the index of the first element for which p outputs true. */ @@ -388,7 +388,7 @@ class Bundle extends Aggregate { private[chisel3] lazy val flatten = namedElts.flatMap(_._2.flatten) private[chisel3] override def _onModuleClose: Unit = // scalastyle:ignore method.name for ((name, elt) <- namedElts) { elt.setRef(this, _namespace.name(name)) } - + private[chisel3] final def allElements: Seq[Element] = namedElts.flatMap(_._2.allElements) override def cloneType : this.type = { diff --git a/chiselFrontend/src/main/scala/chisel3/core/Binding.scala b/chiselFrontend/src/main/scala/chisel3/core/Binding.scala index 467cb4eb..3dfde7c2 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Binding.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Binding.scala @@ -140,10 +140,9 @@ object Binding { } } - /** Diagnose a binding error caused by a missing IO() wrapper. - * @param element the element triggering the binding error. - * @return true if the element is a member of the module's io but ioDefined is false. - */ + // Diagnose a binding error caused by a missing IO() wrapper. + // element is the element triggering the binding error. + // Returns true if the element is a member of the module's io but ioDefined is false. def isMissingIOWrapper(element: Element): Boolean = { element._parent match { case None => false diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala index 4a09c70e..035ac213 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala @@ -54,8 +54,6 @@ sealed abstract class Bits(width: Width, override val litArg: Option[LitArg]) // Arguments for: self-checking code (can't do arithmetic on bits) // Arguments against: generates down to a FIRRTL UInt anyways - private[chisel3] def fromInt(x: BigInt, w: Int): this.type - private[chisel3] def flatten: IndexedSeq[Bits] = IndexedSeq(this) def cloneType: this.type = cloneTypeWidth(width) @@ -92,7 +90,7 @@ sealed abstract class Bits(width: Width, override val litArg: Option[LitArg]) Builder.error(s"Negative bit indices are illegal (got $x)") } if (isLit()) { - Bool(((litValue() >> x.toInt) & 1) == 1) + (((litValue() >> x.toInt) & 1) == 1).asBool } else { Binding.checkSynthesizable(this, s"'this' ($this)") pushOp(DefPrim(sourceInfo, Bool(), BitsExtractOp, this.ref, ILit(x), ILit(x))) @@ -134,7 +132,7 @@ sealed abstract class Bits(width: Width, override val litArg: Option[LitArg]) } val w = x - y + 1 if (isLit()) { - UInt((litValue >> y) & ((BigInt(1) << w) - 1), w) + ((litValue >> y) & ((BigInt(1) << w) - 1)).asUInt(w.W) } else { Binding.checkSynthesizable(this, s"'this' ($this)") pushOp(DefPrim(sourceInfo, UInt(Width(w)), BitsExtractOp, this.ref, ILit(x), ILit(y))) @@ -304,11 +302,6 @@ sealed abstract class Bits(width: Width, override val litArg: Option[LitArg]) final def toPrintable: Printable = Decimal(this) } -/** Provides a set of operations to create UInt types and literals. - * Identical in functionality to the UInt companion object. - */ -object Bits extends UIntFactory - // REVIEW TODO: Further discussion needed on what Num actually is. /** Abstract trait defining operations available on numeric-like wire data * types. @@ -407,15 +400,12 @@ sealed class UInt private[core] (width: Width, lit: Option[ULit] = None) new UInt(w).asInstanceOf[this.type] private[chisel3] def toType = s"UInt$width" - override private[chisel3] def fromInt(value: BigInt, width: Int): this.type = - UInt(value, width).asInstanceOf[this.type] - // TODO: refactor to share documentation with Num or add independent scaladoc final def unary_- (): UInt = macro SourceInfoTransform.noArg final def unary_-% (): UInt = macro SourceInfoTransform.noArg - def do_unary_- (implicit sourceInfo: SourceInfo) : UInt = UInt(0) - this - def do_unary_-% (implicit sourceInfo: SourceInfo): UInt = UInt(0) -% this + def do_unary_- (implicit sourceInfo: SourceInfo) : UInt = 0.U - this + def do_unary_-% (implicit sourceInfo: SourceInfo): UInt = 0.U -% this override def do_+ (that: UInt)(implicit sourceInfo: SourceInfo): UInt = this +% that override def do_- (that: UInt)(implicit sourceInfo: SourceInfo): UInt = this -% that @@ -463,8 +453,8 @@ sealed class UInt private[core] (width: Width, lit: Option[ULit] = None) final def andR(): Bool = macro SourceInfoTransform.noArg final def xorR(): Bool = macro SourceInfoTransform.noArg - def do_orR(implicit sourceInfo: SourceInfo): Bool = this != UInt(0) - def do_andR(implicit sourceInfo: SourceInfo): Bool = ~this === UInt(0) + def do_orR(implicit sourceInfo: SourceInfo): Bool = this != 0.U + def do_andR(implicit sourceInfo: SourceInfo): Bool = ~this === 0.U def do_xorR(implicit sourceInfo: SourceInfo): Bool = redop(sourceInfo, XorReduceOp) override def do_< (that: UInt)(implicit sourceInfo: SourceInfo): Bool = compop(sourceInfo, LessOp, that) @@ -483,7 +473,7 @@ sealed class UInt private[core] (width: Width, lit: Option[ULit] = None) final def unary_! () : Bool = macro SourceInfoTransform.noArg - def do_unary_! (implicit sourceInfo: SourceInfo) : Bool = this === UInt(0, 1) + def do_unary_! (implicit sourceInfo: SourceInfo) : Bool = this === 0.U(1.W) override def do_<< (that: Int)(implicit sourceInfo: SourceInfo): UInt = binop(sourceInfo, UInt(this.width + that), ShiftLeftOp, that) @@ -501,7 +491,7 @@ sealed class UInt private[core] (width: Width, lit: Option[ULit] = None) final def bitSet(off: UInt, dat: Bool): UInt = macro UIntTransform.bitset def do_bitSet(off: UInt, dat: Bool)(implicit sourceInfo: SourceInfo): UInt = { - val bit = UInt(1, 1) << off + val bit = 1.U(1.W) << off Mux(dat, this | bit, ~(~this | bit)) } @@ -532,31 +522,14 @@ sealed class UInt private[core] (width: Width, lit: Option[ULit] = None) } // This is currently a factory because both Bits and UInt inherit it. -private[core] sealed trait UIntFactory { +trait UIntFactory { /** Create a UInt type with inferred width. */ def apply(): UInt = apply(Width()) /** Create a UInt port with specified width. */ def apply(width: Width): UInt = new UInt(width) - /** Create a UInt with a specified width - compatibility with Chisel2. */ - def width(width: Int): UInt = apply(Width(width)) - /** Create a UInt port with specified width. */ - def width(width: Width): UInt = new UInt(width) - /** Create a UInt literal with fixed width. */ - def apply(value: BigInt, width: Int): UInt = Lit(value, Width(width)) - /** Create a UInt literal with inferred width. */ - def apply(n: String): UInt = Lit(n) - /** Create a UInt literal with fixed width. */ - def apply(n: String, width: Int): UInt = Lit(parse(n), width) - /** Create a UInt literal with specified width. */ - def apply(value: BigInt, width: Width): UInt = Lit(value, width) - def Lit(value: BigInt, width: Int): UInt = Lit(value, Width(width)) - /** Create a UInt literal with inferred width. */ - def Lit(value: BigInt): UInt = Lit(value, Width()) - def Lit(n: String): UInt = Lit(parse(n), parsedWidth(n)) - /** Create a UInt literal with fixed width. */ - def Lit(n: String, width: Int): UInt = Lit(parse(n), width) + /** Create a UInt literal with specified width. */ - def Lit(value: BigInt, width: Width): UInt = { + protected[chisel3] def Lit(value: BigInt, width: Width): UInt = { val lit = ULit(value, width) val result = new UInt(lit.width, Some(lit)) // Bind result to being an Literal @@ -564,63 +537,31 @@ private[core] sealed trait UIntFactory { result } - /** Create a UInt with a specified width - compatibility with Chisel2. */ - // NOTE: This resolves UInt(width = 32) - def apply(dir: Option[Direction] = None, width: Int): UInt = apply(Width(width)) - /** Create a UInt literal with inferred width.- compatibility with Chisel2. */ - def apply(value: BigInt): UInt = apply(value, Width()) - /** Create a UInt with a specified direction and width - compatibility with Chisel2. */ - def apply(dir: Direction, width: Int): UInt = apply(dir, Width(width)) - /** Create a UInt with a specified direction, but unspecified width - compatibility with Chisel2. */ - def apply(dir: Direction): UInt = apply(dir, Width()) - def apply(dir: Direction, wWidth: Width): UInt = { - val result = apply(wWidth) - dir match { - case Direction.Input => Input(result) - case Direction.Output => Output(result) - case Direction.Unspecified => result - } + /** Create a UInt with the specified range */ + def apply(range: Range): UInt = { + apply(range.getWidth) } - - private def parse(n: String) = { - val (base, num) = n.splitAt(1) - val radix = base match { - case "x" | "h" => 16 - case "d" => 10 - case "o" => 8 - case "b" => 2 - case _ => Builder.error(s"Invalid base $base"); 2 - } - BigInt(num.filterNot(_ == '_'), radix) + /** Create a UInt with the specified range */ + def apply(range: (NumericBound[Int], NumericBound[Int])): UInt = { + apply(KnownUIntRange(range._1, range._2)) } - - private def parsedWidth(n: String) = - if (n(0) == 'b') { - Width(n.length-1) - } else if (n(0) == 'h') { - Width((n.length-1) * 4) - } else { - Width() - } } object UInt extends UIntFactory +object Bits extends UIntFactory -sealed class SInt private (width: Width, lit: Option[SLit] = None) +sealed class SInt private[core] (width: Width, lit: Option[SLit] = None) extends Bits(width, lit) with Num[SInt] { private[core] override def cloneTypeWidth(w: Width): this.type = new SInt(w).asInstanceOf[this.type] private[chisel3] def toType = s"SInt$width" - override private[chisel3] def fromInt(value: BigInt, width: Int): this.type = - SInt(value, width).asInstanceOf[this.type] - final def unary_- (): SInt = macro SourceInfoTransform.noArg final def unary_-% (): SInt = macro SourceInfoTransform.noArg - def unary_- (implicit sourceInfo: SourceInfo): SInt = SInt(0) - this - def unary_-% (implicit sourceInfo: SourceInfo): SInt = SInt(0) -% this + def unary_- (implicit sourceInfo: SourceInfo): SInt = 0.S - this + def unary_-% (implicit sourceInfo: SourceInfo): SInt = 0.S -% this /** add (default - no growth) operator */ override def do_+ (that: SInt)(implicit sourceInfo: SourceInfo): SInt = @@ -688,7 +629,7 @@ sealed class SInt private (width: Width, lit: Option[SLit] = None) final def abs(): UInt = macro SourceInfoTransform.noArg - def do_abs(implicit sourceInfo: SourceInfo): UInt = Mux(this < SInt(0), (-this).asUInt, this.asUInt) + def do_abs(implicit sourceInfo: SourceInfo): UInt = Mux(this < 0.S, (-this).asUInt, this.asUInt) override def do_<< (that: Int)(implicit sourceInfo: SourceInfo): SInt = binop(sourceInfo, SInt(this.width + that), ShiftLeftOp, that) @@ -710,66 +651,43 @@ sealed class SInt private (width: Width, lit: Option[SLit] = None) } } -object SInt { +trait SIntFactory { /** Create an SInt type with inferred width. */ def apply(): SInt = apply(Width()) /** Create a SInt type or port with fixed width. */ def apply(width: Width): SInt = new SInt(width) - /** Create a SInt type or port with fixed width. */ - def width(width: Int): SInt = apply(Width(width)) - /** Create an SInt type with specified width. */ - def width(width: Width): SInt = new SInt(width) - - /** Create an SInt literal with inferred width. */ - def apply(value: BigInt): SInt = Lit(value) - /** Create an SInt literal with fixed width. */ - def apply(value: BigInt, width: Int): SInt = Lit(value, width) - /** Create an SInt literal with specified width. */ - def apply(value: BigInt, width: Width): SInt = Lit(value, width) + /** Create a SInt with the specified range */ + def apply(range: Range): SInt = { + apply(range.getWidth) + } + /** Create a SInt with the specified range */ + def apply(range: (NumericBound[Int], NumericBound[Int])): SInt = { + apply(KnownSIntRange(range._1, range._2)) + } - def Lit(value: BigInt): SInt = Lit(value, Width()) - def Lit(value: BigInt, width: Int): SInt = Lit(value, Width(width)) /** Create an SInt literal with specified width. */ - def Lit(value: BigInt, width: Width): SInt = { - + protected[chisel3] def Lit(value: BigInt, width: Width): SInt = { val lit = SLit(value, width) val result = new SInt(lit.width, Some(lit)) // Bind result to being an Literal result.binding = LitBinding() result } - /** Create a SInt with a specified width - compatibility with Chisel2. */ - def apply(dir: Option[Direction] = None, width: Int): SInt = apply(Width(width)) - /** Create a SInt with a specified direction and width - compatibility with Chisel2. */ - def apply(dir: Direction, width: Int): SInt = apply(dir, Width(width)) - /** Create a SInt with a specified direction, but unspecified width - compatibility with Chisel2. */ - def apply(dir: Direction): SInt = apply(dir, Width()) - def apply(dir: Direction, wWidth: Width): SInt = { - val result = apply(wWidth) - dir match { - case Direction.Input => Input(result) - case Direction.Output => Output(result) - case Direction.Unspecified => result - } - } } +object SInt extends SIntFactory + // REVIEW TODO: Why does this extend UInt and not Bits? Does defining airth // operations on a Bool make sense? /** A data type for booleans, defined as a single bit indicating true or false. */ -sealed class Bool(lit: Option[ULit] = None) extends UInt(Width(1), lit) { +sealed class Bool(lit: Option[ULit] = None) extends UInt(1.W, lit) { private[core] override def cloneTypeWidth(w: Width): this.type = { require(!w.known || w.get == 1) new Bool().asInstanceOf[this.type] } - override private[chisel3] def fromInt(value: BigInt, width: Int): this.type = { - require((value == 0 || value == 1) && width == 1) - Bool(value == 1).asInstanceOf[this.type] - } - // REVIEW TODO: Why does this need to exist and have different conventions // than Bits? final def & (that: Bool): Bool = macro SourceInfoTransform.thatArg @@ -805,31 +723,23 @@ sealed class Bool(lit: Option[ULit] = None) extends UInt(Width(1), lit) { def do_asClock(implicit sourceInfo: SourceInfo): Clock = pushOp(DefPrim(sourceInfo, Clock(), AsClockOp, ref)) } -object Bool { +trait BoolFactory { /** Creates an empty Bool. */ def apply(): Bool = new Bool() /** Creates Bool literal. */ - def apply(x: Boolean): Bool = Lit(x) - def Lit(x: Boolean): Bool = { + protected[chisel3] def Lit(x: Boolean): Bool = { val result = new Bool(Some(ULit(if (x) 1 else 0, Width(1)))) // Bind result to being an Literal result.binding = LitBinding() result } - /** Create a UInt with a specified direction and width - compatibility with Chisel2. */ - def apply(dir: Direction): Bool = { - val result = apply() - dir match { - case Direction.Input => Input(result) - case Direction.Output => Output(result) - case Direction.Unspecified => result - } - } } +object Bool extends BoolFactory + object Mux { /** Creates a mux, whose output is one of the inputs depending on the * value of the condition. @@ -839,7 +749,7 @@ object Mux { * @param alt the value chosen when `cond` is false * @example * {{{ - * val muxOut = Mux(data_in === UInt(3), UInt(3, 4), UInt(0, 4)) + * val muxOut = Mux(data_in === 3.U, 3.U(4.W), 0.U(4.W)) * }}} */ def apply[T <: Data](cond: Bool, con: T, alt: T): T = macro MuxTransform.apply[T] @@ -900,10 +810,6 @@ sealed class FixedPoint private (width: Width, val binaryPoint: BinaryPoint, lit case _ => this badConnect that } - private[chisel3] def fromInt(value: BigInt, width: Int): this.type = { - throwException(s"Don't use $this.fromInt($value, $width): Use literal constructors instead") - } - final def unary_- (): FixedPoint = macro SourceInfoTransform.noArg final def unary_-% (): FixedPoint = macro SourceInfoTransform.noArg diff --git a/chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala b/chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala index 7fe429fa..85a57111 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/BlackBox.scala @@ -3,11 +3,20 @@ package chisel3.core import chisel3.internal.Builder.pushCommand -import chisel3.internal.firrtl.{ModuleIO, DefInvalid} +import chisel3.internal.firrtl._ +import chisel3.internal.throwException import chisel3.internal.sourceinfo.SourceInfo // TODO: remove this once we have CompileOptions threaded through the macro system. import chisel3.core.ExplicitCompileOptions.NotStrict +/** 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. @@ -16,12 +25,9 @@ import chisel3.core.ExplicitCompileOptions.NotStrict * {{{ * ... to be written once a spec is finalized ... * }}} + * @note The parameters API is experimental and may change */ -// REVIEW TODO: make Verilog parameters part of the constructor interface? -abstract class BlackBox extends Module { - // Don't bother taking override_clock|reset, clock/reset locked out anyway - // TODO: actually implement this. - def setVerilogParameters(s: String): Unit = {} +abstract class BlackBox(val params: Map[String, Param] = Map.empty[String, Param]) extends Module { // The body of a BlackBox is empty, the real logic happens in firrtl/Emitter.scala // Bypass standard clock, reset, io port declaration by flattening io diff --git a/chiselFrontend/src/main/scala/chisel3/core/ChiselAnnotation.scala b/chiselFrontend/src/main/scala/chisel3/core/ChiselAnnotation.scala new file mode 100644 index 00000000..73573bb1 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/core/ChiselAnnotation.scala @@ -0,0 +1,30 @@ +// See LICENSE for license details. + +package chisel3.core + +import chisel3.internal.InstanceId +import firrtl.Transform +import firrtl.annotations.{Annotation, CircuitName, ComponentName, ModuleName} + +/** + * This is a stand-in for the firrtl.Annotations.Annotation because at the time this annotation + * is created the component cannot be resolved, into a targetString. Resolution can only + * happen after the circuit is elaborated + * @param component A chisel thingy to be annotated, could be module, wire, reg, etc. + * @param transformClass A fully-qualified class name of the transformation pass + * @param value A string value to be used by the transformation pass + */ +case class ChiselAnnotation(component: InstanceId, transformClass: Class[_ <: Transform], value: String) { + def toFirrtl: Annotation = { + val circuitName = CircuitName(component.pathName.split("""\.""").head) + component match { + case m: Module => + Annotation( + ModuleName(m.name, circuitName), transformClass, value) + case _ => + Annotation( + ComponentName( + component.instanceName, ModuleName(component.parentModName, circuitName)), transformClass, value) + } + } +} diff --git a/chiselFrontend/src/main/scala/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala index 2f18e726..57ed0c59 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Data.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Data.scala @@ -258,7 +258,7 @@ abstract class Data extends HasId { * * This performs the inverse operation of fromBits(Bits). */ - @deprecated("Best alternative, .toUInt() or if Bits really needed, .toUInt().toBits()", "chisel3") + @deprecated("Best alternative, .asUInt()", "chisel3") def toBits(): UInt = SeqUtils.do_asUInt(this.flatten)(DeprecatedSourceInfo) /** Reinterpret cast to UInt. diff --git a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala index a43b19fe..1863e921 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala @@ -40,7 +40,7 @@ sealed abstract class MemBase[T <: Data](t: T, val length: Int) extends HasId wi */ def apply(idx: Int): T = { require(idx >= 0 && idx < length) - apply(UInt(idx)) + apply(idx.asUInt) } /** Creates a read/write accessor into the memory with dynamic addressing. diff --git a/chiselFrontend/src/main/scala/chisel3/core/Module.scala b/chiselFrontend/src/main/scala/chisel3/core/Module.scala index ca391091..76a3b240 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Module.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Module.scala @@ -14,7 +14,7 @@ object Module { /** A wrapper method that all Module instantiations must be wrapped in * (necessary to help Chisel track internal state). * - * @param m the Module being created + * @param bc the Module being created * * @return the input module `m` with Chisel metadata properly set */ @@ -41,8 +41,16 @@ object Module { sourceInfo.makeMessage(" See " + _)) } Builder.currentModule = parent // Back to parent! + val ports = m.computePorts - val component = Component(m, m.name, ports, m._commands) + // Blackbox inherits from Module so we have to match on it first TODO fix + val component = m match { + case bb: BlackBox => + DefBlackBox(bb, bb.name, ports, bb.params) + case mod: Module => + mod._commands.prepend(DefInvalid(childSourceInfo, mod.io.ref)) // init module outputs + DefModule(mod, mod.name, ports, mod._commands) + } m._component = Some(component) Builder.components += component // Avoid referencing 'parent' in top module @@ -77,6 +85,10 @@ extends HasId { iodef } + def annotate(annotation: ChiselAnnotation): Unit = { + Builder.annotations += annotation + } + private[core] var ioDefined: Boolean = false /** @@ -116,18 +128,9 @@ extends HasId { /** Legalized name of this module. */ final val name = Builder.globalNamespace.name(desiredName) - /** FIRRTL Module name */ - private var _modName: Option[String] = None - private[chisel3] def setModName(name: String) = _modName = Some(name) - def modName = _modName match { - case Some(name) => name - case None => throwException("modName should be called after circuit elaboration") - } - /** Keep component for signal names */ private[chisel3] var _component: Option[Component] = None - /** Signal name (for simulation). */ override def instanceName = if (_parent == None) name else _component match { diff --git a/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala b/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala index 558dea7a..e435860e 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/SeqUtils.scala @@ -25,12 +25,12 @@ private[chisel3] object SeqUtils { } } - /** Outputs the number of elements that === Bool(true). + /** Outputs the number of elements that === true.B. */ def count(in: Seq[Bool]): UInt = macro SourceInfoTransform.inArg def do_count(in: Seq[Bool])(implicit sourceInfo: SourceInfo): UInt = in.size match { - case 0 => UInt(0) + case 0 => 0.U case 1 => in.head case n => count(in take n/2) +& count(in drop n/2) } @@ -57,7 +57,7 @@ private[chisel3] object SeqUtils { if (in.tail.isEmpty) { in.head._2 } else { - val masked = for ((s, i) <- in) yield Mux(s, i.asUInt, UInt(0)) + val masked = for ((s, i) <- in) yield Mux(s, i.asUInt, 0.U) val width = in.map(_._2.width).reduce(_ max _) in.head._2.cloneTypeWidth(width).fromBits(masked.reduceLeft(_|_)) } diff --git a/chiselFrontend/src/main/scala/chisel3/core/When.scala b/chiselFrontend/src/main/scala/chisel3/core/When.scala index 196e7903..7501ebb1 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/When.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/When.scala @@ -18,9 +18,9 @@ object when { // scalastyle:ignore object.name * * @example * {{{ - * when ( myData === UInt(3) ) { + * when ( myData === 3.U ) { * // Some logic to run when myData equals 3. - * } .elsewhen ( myData === UInt(1) ) { + * } .elsewhen ( myData === 1.U ) { * // Some logic to run when myData equals 1. * } .otherwise { * // Some logic to run when myData is neither 3 nor 1. diff --git a/chiselFrontend/src/main/scala/chisel3/core/package.scala b/chiselFrontend/src/main/scala/chisel3/core/package.scala new file mode 100644 index 00000000..87dca1f3 --- /dev/null +++ b/chiselFrontend/src/main/scala/chisel3/core/package.scala @@ -0,0 +1,104 @@ +package chisel3 { + import internal.Builder + + package object core { + import internal.firrtl.Width + + /** + * 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(val bigint: BigInt) { + /** 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(val int: Int) extends fromBigIntToLiteral(int) + implicit class fromLongToLiteral(val long: Long) extends fromBigIntToLiteral(long) + + implicit class fromStringToLiteral(val 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(val 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) + } + + implicit class fromDoubleToLiteral(val double: Double) { + def F(binaryPoint: Int): FixedPoint = FixedPoint.fromDouble(double, binaryPoint = binaryPoint) + } + + implicit class fromIntToWidth(val int: Int) { + def W: Width = Width(int) // scalastyle:ignore method.name + } + } +} diff --git a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala index 028ce628..7a77763b 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/Builder.scala @@ -108,23 +108,23 @@ private[chisel3] trait HasId extends InstanceId { private[chisel3] def getRef: Arg = _ref.get // Implementation of public methods. - def instanceName = _parent match { + def instanceName: String = _parent match { case Some(p) => p._component match { case Some(c) => getRef fullName c case None => throwException("signalName/pathName should be called after circuit elaboration") } case None => throwException("this cannot happen") } - def pathName = _parent match { + def pathName: String = _parent match { case None => instanceName case Some(p) => s"${p.pathName}.$instanceName" } - def parentPathName = _parent match { + def parentPathName: String = _parent match { case Some(p) => p.pathName case None => throwException(s"$instanceName doesn't have a parent") } - def parentModName = _parent match { - case Some(p) => p.modName + def parentModName: String = _parent match { + case Some(p) => p.name case None => throwException(s"$instanceName doesn't have a parent") } @@ -145,6 +145,7 @@ private[chisel3] class DynamicContext() { val idGen = new IdGen val globalNamespace = new Namespace(None, Set()) val components = ArrayBuffer[Component]() + val annotations = ArrayBuffer[ChiselAnnotation]() var currentModule: Option[Module] = None // Set by object Module.apply before calling class Module constructor // Used to distinguish between no Module() wrapping, multiple wrappings, and rewrapping @@ -161,6 +162,7 @@ private[chisel3] object Builder { def idGen: IdGen = dynamicContext.idGen def globalNamespace: Namespace = dynamicContext.globalNamespace def components: ArrayBuffer[Component] = dynamicContext.components + def annotations: ArrayBuffer[ChiselAnnotation] = dynamicContext.annotations def currentModule: Option[Module] = dynamicContext.currentModule def currentModule_=(target: Option[Module]): Unit = { @@ -181,7 +183,10 @@ private[chisel3] object Builder { // TODO(twigg): Ideally, binding checks and new bindings would all occur here // However, rest of frontend can't support this yet. def pushCommand[T <: Command](c: T): T = { - forcedModule._commands += c + forcedModule match { + case _: BlackBox => throwException("Cannot add hardware to a BlackBox") + case m => m._commands += c + } c } def pushOp[T <: Data](cmd: DefPrim[T]): T = { @@ -203,7 +208,7 @@ private[chisel3] object Builder { errors.checkpoint() errors.info("Done elaborating.") - Circuit(components.last.name, components) + Circuit(components.last.name, components, annotations.map(_.toFirrtl)) } } } diff --git a/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala index 0f866c27..50400034 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/firrtl/IR.scala @@ -7,6 +7,8 @@ import core._ import chisel3.internal._ import chisel3.internal.sourceinfo.{SourceInfo, NoSourceInfo} +import _root_.firrtl.annotations.Annotation + case class PrimOp(val name: String) { override def toString: String = name } @@ -64,7 +66,7 @@ abstract class LitArg(val num: BigInt, widthArg: Width) extends Arg { protected def minWidth: Int if (forcedWidth) { require(widthArg.get >= minWidth, - s"The literal value ${num} was elaborated with a specificed width of ${widthArg.get} bits, but at least ${minWidth} bits are required.") + s"The literal value ${num} was elaborated with a specified width of ${widthArg.get} bits, but at least ${minWidth} bits are required.") } } @@ -109,6 +111,54 @@ case class Index(imm: Arg, value: Arg) extends Arg { override def fullName(ctx: Component): String = s"${imm.fullName(ctx)}[${value.fullName(ctx)}]" } +sealed trait Bound +sealed trait NumericBound[T] extends Bound { + val value: T +} +sealed case class Open[T](value: T) extends NumericBound[T] +sealed case class Closed[T](value: T) extends NumericBound[T] + +sealed trait Range { + val min: Bound + val max: Bound + def getWidth: Width +} + +sealed trait KnownIntRange extends Range { + val min: NumericBound[Int] + val max: NumericBound[Int] + + require( (min, max) match { + case (Open(low_val), Open(high_val)) => low_val < high_val - 1 + case (Closed(low_val), Open(high_val)) => low_val < high_val + case (Open(low_val), Closed(high_val)) => low_val < high_val + case (Closed(low_val), Closed(high_val)) => low_val <= high_val + }) +} + +sealed case class KnownUIntRange(min: NumericBound[Int], max: NumericBound[Int]) extends KnownIntRange { + require (min.value >= 0) + + def getWidth: Width = max match { + case Open(v) => Width(BigInt(v - 1).bitLength.max(1)) + case Closed(v) => Width(BigInt(v).bitLength.max(1)) + } +} + +sealed case class KnownSIntRange(min: NumericBound[Int], max: NumericBound[Int]) extends KnownIntRange { + + val maxWidth = max match { + case Open(v) => Width(BigInt(v - 1).bitLength + 1) + case Closed(v) => Width(BigInt(v).bitLength + 1) + } + val minWidth = min match { + case Open(v) => Width(BigInt(v + 1).bitLength + 1) + case Closed(v) => Width(BigInt(v).bitLength + 1) + } + def getWidth: Width = maxWidth.max(minWidth) + +} + object Width { def apply(x: Int): Width = KnownWidth(x) def apply(): Width = UnknownWidth() @@ -215,8 +265,14 @@ case class Connect(sourceInfo: SourceInfo, loc: Node, exp: Arg) extends Command case class BulkConnect(sourceInfo: SourceInfo, loc1: Node, loc2: Node) extends Command case class ConnectInit(sourceInfo: SourceInfo, loc: Node, exp: Arg) extends Command case class Stop(sourceInfo: SourceInfo, clock: Arg, ret: Int) extends Command -case class Component(id: Module, name: String, ports: Seq[Port], commands: Seq[Command]) extends Arg case class Port(id: Data, dir: Direction) case class Printf(sourceInfo: SourceInfo, clock: Arg, pable: Printable) extends Command +abstract class Component extends Arg { + def id: Module + def name: String + def ports: Seq[Port] +} +case class DefModule(id: Module, name: String, ports: Seq[Port], commands: Seq[Command]) extends Component +case class DefBlackBox(id: Module, name: String, ports: Seq[Port], params: Map[String, Param]) extends Component -case class Circuit(name: String, components: Seq[Component]) +case class Circuit(name: String, components: Seq[Component], annotations: Seq[Annotation] = Seq.empty) |
