diff options
| author | Jack Koenig | 2022-01-10 16:32:51 -0800 |
|---|---|---|
| committer | GitHub | 2022-01-10 16:32:51 -0800 |
| commit | 2b48fd15a7711dcd44334fbbc538667a102a581a (patch) | |
| tree | 4b4766347c3943d65c13e5de2d139b14821eec61 /core/src/main | |
| parent | 92e77a97af986629766ac9038f0ebc8ab9a48fa1 (diff) | |
| parent | bff8dc0738adafa1176f6959a33ad86f6373c558 (diff) | |
Merge pull request #2246 from chipsalliance/scalafmt
Add scalafmt configuration and apply it.
Diffstat (limited to 'core/src/main')
52 files changed, 3513 insertions, 2106 deletions
diff --git a/core/src/main/scala/chisel3/Aggregate.scala b/core/src/main/scala/chisel3/Aggregate.scala index db354e1f..15cdf428 100644 --- a/core/src/main/scala/chisel3/Aggregate.scala +++ b/core/src/main/scala/chisel3/Aggregate.scala @@ -3,7 +3,7 @@ package chisel3 import chisel3.experimental.VecLiterals.AddVecLiteralConstructor -import chisel3.experimental.dataview.{InvalidViewException, isView, reifySingleData} +import chisel3.experimental.dataview.{isView, reifySingleData, InvalidViewException} import scala.collection.immutable.{SeqMap, VectorMap} import scala.collection.mutable.{HashSet, LinkedHashMap} @@ -34,13 +34,16 @@ sealed abstract class Aggregate extends Data { // show groups of names of fields with duplicate id's // The sorts make the displayed order of fields deterministic and matching the order of occurrence in the Bundle. // It's a bit convoluted but happens rarely and makes the error message easier to understand - val dupNames = duplicates.toSeq.sortBy(_._id).map { duplicate => - b.elements - .collect { case x if x._2._id == duplicate._id => x } - .toSeq.sortBy(_._2._id) - .map(_._1).reverse - .mkString("(", ",", ")") - }.mkString(",") + val dupNames = duplicates.toSeq + .sortBy(_._id) + .map { duplicate => + b.elements.collect { case x if x._2._id == duplicate._id => x }.toSeq + .sortBy(_._2._id) + .map(_._1) + .reverse + .mkString("(", ",", ")") + } + .mkString(",") throw new AliasedAggregateFieldException( s"${b.className} contains aliased fields named ${dupNames}" ) @@ -59,9 +62,10 @@ sealed abstract class Aggregate extends Data { direction = ActualDirection.fromChildren(childDirections, resolvedDirection) match { case Some(dir) => dir case None => - val childWithDirections = getElements zip getElements.map(_.direction) + val childWithDirections = getElements.zip(getElements.map(_.direction)) throw MixedDirectionAggregateException( - s"Aggregate '$this' can't have elements that are both directioned and undirectioned: $childWithDirections") + s"Aggregate '$this' can't have elements that are both directioned and undirectioned: $childWithDirections" + ) } } @@ -76,7 +80,7 @@ sealed abstract class Aggregate extends Data { (accumulator, elt.litOption) match { case (Some(accumulator), Some(eltLit)) => val width = elt.width.get - val masked = ((BigInt(1) << width) - 1) & eltLit // also handles the negative case with two's complement + val masked = ((BigInt(1) << width) - 1) & eltLit // also handles the negative case with two's complement Some((accumulator << width) + masked) case (None, _) => None case (_, None) => None @@ -85,8 +89,7 @@ sealed abstract class Aggregate extends Data { topBindingOpt match { case Some(BundleLitBinding(_)) | Some(VecLitBinding(_)) => - getElements - .reverse + getElements.reverse .foldLeft[Option[BigInt]](Some(BigInt(0)))(shiftAdd) case _ => None } @@ -112,8 +115,12 @@ sealed abstract class Aggregate extends Data { SeqUtils.do_asUInt(flatten.map(_.asUInt())) } - private[chisel3] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, - compileOptions: CompileOptions): Unit = { + private[chisel3] override def connectFromBits( + that: Bits + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Unit = { var i = 0 val bits = if (that.isLit) that else WireDefault(UInt(this.width), that) // handles width padding for (x <- flatten) { @@ -132,6 +139,7 @@ sealed abstract class Aggregate extends Data { } trait VecFactory extends SourceInfoDoc { + /** Creates a new [[Vec]] with `n` entries of the specified data type. * * @note elements are NOT assigned by default and have no value @@ -144,12 +152,18 @@ trait VecFactory extends SourceInfoDoc { } /** Truncate an index to implement modulo-power-of-2 addressing. */ - private[chisel3] def truncateIndex(idx: UInt, n: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = { - val w = (n-1).bitLength + private[chisel3] def truncateIndex( + idx: UInt, + n: BigInt + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): UInt = { + val w = (n - 1).bitLength 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 | 0.U(w.W))(w-1,0) + else if (idx.width.known) idx(w - 1, 0) + else (idx | 0.U(w.W))(w - 1, 0) } } @@ -179,14 +193,14 @@ trait VecFactory extends SourceInfoDoc { * - when multiple conflicting assignments are performed on a Vec element, the last one takes effect (unlike Mem, where the result is undefined) * - Vecs, unlike classes in Scala's collection library, are propagated intact to FIRRTL as a vector type, which may make debugging easier */ -sealed class Vec[T <: Data] private[chisel3] (gen: => T, val length: Int) - extends Aggregate with VecLike[T] { +sealed class Vec[T <: Data] private[chisel3] (gen: => T, val length: Int) extends Aggregate with VecLike[T] { override def toString: String = { topBindingOpt match { case Some(VecLitBinding(vecLitBinding)) => - val contents = vecLitBinding.zipWithIndex.map { case ((data, lit), index) => - s"$index=$lit" + val contents = vecLitBinding.zipWithIndex.map { + case ((data, lit), index) => + s"$index=$lit" }.mkString(", ") s"${sample_element.cloneType}[$length]($contents)" case _ => stringAccessor(s"${sample_element.cloneType}[$length]") @@ -196,7 +210,7 @@ sealed class Vec[T <: Data] private[chisel3] (gen: => T, val length: Int) 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) + (this.sample_element.typeEquivalent(that.sample_element)) case _ => false } @@ -206,7 +220,7 @@ sealed class Vec[T <: Data] private[chisel3] (gen: => T, val length: Int) val resolvedDirection = SpecifiedDirection.fromParent(parentDirection, specifiedDirection) sample_element.bind(SampleElementBinding(this), resolvedDirection) - for (child <- getElements) { // assume that all children are the same + for (child <- getElements) { // assume that all children are the same child.bind(ChildBinding(this), resolvedDirection) } @@ -226,12 +240,12 @@ sealed class Vec[T <: Data] private[chisel3] (gen: => T, val length: Int) } /** - * sample_element 'tracks' all changes to the elements. - * For consistency, sample_element is always used for creating dynamically - * indexed ports and outputing the FIRRTL type. - * - * Needed specifically for the case when the Vec is length 0. - */ + * sample_element 'tracks' all changes to the elements. + * For consistency, sample_element is always used for creating dynamically + * indexed ports and outputing the FIRRTL type. + * + * Needed specifically for the case when the Vec is length 0. + */ private[chisel3] val sample_element: T = gen // allElements current includes sample_element @@ -245,29 +259,33 @@ sealed class Vec[T <: Data] private[chisel3] (gen: => T, val length: Int) * * @note the length of this Vec must match the length of the input Seq */ - def <> (that: Seq[T])(implicit sourceInfo: SourceInfo, moduleCompileOptions: CompileOptions): Unit = { + def <>(that: Seq[T])(implicit sourceInfo: SourceInfo, moduleCompileOptions: CompileOptions): Unit = { if (this.length != that.length) { Builder.error("Vec and Seq being bulk connected have different lengths!") } - for ((a, b) <- this zip that) + for ((a, b) <- this.zip(that)) a <> b } // TODO: eliminate once assign(Seq) isn't ambiguous with assign(Data) since Vec extends Seq and Data - def <> (that: Vec[T])(implicit sourceInfo: SourceInfo, moduleCompileOptions: CompileOptions): Unit = this bulkConnect that.asInstanceOf[Data] + def <>(that: Vec[T])(implicit sourceInfo: SourceInfo, moduleCompileOptions: CompileOptions): Unit = + this.bulkConnect(that.asInstanceOf[Data]) /** Strong bulk connect, assigning elements in this Vec from elements in a Seq. * * @note the length of this Vec must match the length of the input Seq */ - def := (that: Seq[T])(implicit sourceInfo: SourceInfo, moduleCompileOptions: CompileOptions): Unit = { - require(this.length == that.length, s"Cannot assign to a Vec of length ${this.length} from a Seq of different length ${that.length}") - for ((a, b) <- this zip that) + def :=(that: Seq[T])(implicit sourceInfo: SourceInfo, moduleCompileOptions: CompileOptions): Unit = { + require( + this.length == that.length, + s"Cannot assign to a Vec of length ${this.length} from a Seq of different length ${that.length}" + ) + for ((a, b) <- this.zip(that)) a := b } // TODO: eliminate once assign(Seq) isn't ambiguous with assign(Data) since Vec extends Seq and Data - def := (that: Vec[T])(implicit sourceInfo: SourceInfo, moduleCompileOptions: CompileOptions): Unit = this connect that + def :=(that: Vec[T])(implicit sourceInfo: SourceInfo, moduleCompileOptions: CompileOptions): Unit = this.connect(that) /** Creates a dynamically indexed read or write accessor into the array. */ @@ -284,8 +302,9 @@ sealed class Vec[T <: Data] private[chisel3] (gen: => T, val length: Int) // Views complicate things a bit, but views that correspond exactly to an identical Vec can just forward the // dynamic indexing to the target Vec // In theory, we could still do this forwarding if the sample element were different by deriving a DataView - case Some(target: Vec[T @unchecked]) if this.length == target.length && - this.sample_element.typeEquivalent(target.sample_element) => + case Some(target: Vec[T @unchecked]) + if this.length == target.length && + this.sample_element.typeEquivalent(target.sample_element) => return target.do_apply(p) case _ => throw InvalidViewException("Dynamic indexing of Views is not yet supported") } @@ -296,7 +315,7 @@ sealed class Vec[T <: Data] private[chisel3] (gen: => T, val length: Int) // Reconstruct the resolvedDirection (in Aggregate.bind), since it's not stored. // It may not be exactly equal to that value, but the results are the same. val reconstructedResolvedDirection = direction match { - case ActualDirection.Input => SpecifiedDirection.Input + case ActualDirection.Input => SpecifiedDirection.Input case ActualDirection.Output => SpecifiedDirection.Output case ActualDirection.Bidirectional(ActualDirection.Default) | ActualDirection.Unspecified => SpecifiedDirection.Unspecified @@ -331,7 +350,7 @@ sealed class Vec[T <: Data] private[chisel3] (gen: => T, val length: Int) def toPrintable: Printable = { val elts = if (length == 0) List.empty[Printable] - else self flatMap (e => List(e.toPrintable, PString(", "))) dropRight 1 + else self.flatMap(e => List(e.toPrintable, PString(", "))).dropRight(1) PString("Vec(") + Printables(elts) + PString(")") } @@ -354,14 +373,17 @@ sealed class Vec[T <: Data] private[chisel3] (gen: => T, val length: Int) */ def reduceTree(redOp: (T, T) => T, layerOp: (T) => T): T = macro VecTransform.reduceTree - def do_reduceTree(redOp: (T, T) => T, layerOp: (T) => T = (x: T) => x) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) : T = { + def do_reduceTree( + redOp: (T, T) => T, + layerOp: (T) => T = (x: T) => x + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): T = { require(!isEmpty, "Cannot apply reduction on a vec of size 0") - var curLayer : Seq[T] = this + var curLayer: Seq[T] = this while (curLayer.length > 1) { - curLayer = curLayer.grouped(2).map( x => - if (x.length == 1) layerOp(x(0)) else redOp(x(0), x(1)) - ).toSeq + curLayer = curLayer.grouped(2).map(x => if (x.length == 1) layerOp(x(0)) else redOp(x(0), x(1))).toSeq } curLayer(0) } @@ -380,16 +402,21 @@ sealed class Vec[T <: Data] private[chisel3] (gen: => T, val length: Int) * ) * }}} */ - private[chisel3] def _makeLit(elementInitializers: (Int, T)*)(implicit sourceInfo: SourceInfo, - compileOptions: CompileOptions): this.type = { + private[chisel3] def _makeLit( + elementInitializers: (Int, T)* + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): this.type = { def checkLiteralConstruction(): Unit = { - val dupKeys = elementInitializers.map { x => x._1 }.groupBy(x => x).flatMap { case (k, v) => - if (v.length > 1) { - Some(k, v.length) - } else { - None - } + val dupKeys = elementInitializers.map { x => x._1 }.groupBy(x => x).flatMap { + case (k, v) => + if (v.length > 1) { + Some(k, v.length) + } else { + None + } } if (dupKeys.nonEmpty) { throw new VecLiteralException( @@ -438,79 +465,96 @@ sealed class Vec[T <: Data] private[chisel3] (gen: => T, val length: Int) // Create the Vec literal binding from litArgs of arguments val vecLitLinkedMap = new mutable.LinkedHashMap[Data, LitArg]() - elementInitializers.sortBy { case (a, _) => a }.foreach { case (fieldIndex, value) => - val field = clone.apply(fieldIndex) - val fieldName = cloneFields.getOrElse(field, - throw new VecLiteralException(s"field $field (with value $value) is not a field," + - s" ensure the field is specified as a function returning a field on an object of class ${this.getClass}," + - s" eg '_.a' to select hypothetical bundle field 'a'") - ) - - val valueBinding = value.topBindingOpt match { - case Some(litBinding: LitBinding) => litBinding - case _ => throw new VecLiteralException(s"field $fieldIndex specified with non-literal value $value") - } + elementInitializers.sortBy { case (a, _) => a }.foreach { + case (fieldIndex, value) => + val field = clone.apply(fieldIndex) + val fieldName = cloneFields.getOrElse( + field, + throw new VecLiteralException( + s"field $field (with value $value) is not a field," + + s" ensure the field is specified as a function returning a field on an object of class ${this.getClass}," + + s" eg '_.a' to select hypothetical bundle field 'a'" + ) + ) - field match { // Get the litArg(s) for this field - case bitField: Bits => - if (!field.typeEquivalent(bitField)) { - throw new VecLiteralException( - s"VecLit: Literal specified at index $fieldIndex ($value) does not match Vec type $sample_element" - ) - } - if (bitField.getWidth > field.getWidth) { - throw new VecLiteralException( - s"VecLit: Literal specified at index $fieldIndex ($value) is too wide for Vec type $sample_element" - ) - } - val litArg = valueBinding match { - case ElementLitBinding(litArg) => litArg - case BundleLitBinding(litMap) => litMap.getOrElse(value, - throw new BundleLiteralException(s"Field $fieldName specified with unspecified value") - ) - case VecLitBinding(litMap) => litMap.getOrElse(value, - throw new VecLiteralException(s"Field $fieldIndex specified with unspecified value")) - } - val adjustedLitArg = litArg.cloneWithWidth(sample_element.width) - vecLitLinkedMap(bitField) = adjustedLitArg + val valueBinding = value.topBindingOpt match { + case Some(litBinding: LitBinding) => litBinding + case _ => throw new VecLiteralException(s"field $fieldIndex specified with non-literal value $value") + } - case recordField: Record => - if (!(recordField.typeEquivalent(value))) { - throw new VecLiteralException(s"field $fieldIndex $recordField specified with non-type-equivalent value $value") - } - // Copy the source BundleLitBinding with fields (keys) remapped to the clone - val remap = getMatchedFields(value, recordField).toMap - valueBinding.asInstanceOf[BundleLitBinding].litMap.map { case (valueField, valueValue) => - vecLitLinkedMap(remap(valueField)) = valueValue - } + field match { // Get the litArg(s) for this field + case bitField: Bits => + if (!field.typeEquivalent(bitField)) { + throw new VecLiteralException( + s"VecLit: Literal specified at index $fieldIndex ($value) does not match Vec type $sample_element" + ) + } + if (bitField.getWidth > field.getWidth) { + throw new VecLiteralException( + s"VecLit: Literal specified at index $fieldIndex ($value) is too wide for Vec type $sample_element" + ) + } + val litArg = valueBinding match { + case ElementLitBinding(litArg) => litArg + case BundleLitBinding(litMap) => + litMap.getOrElse( + value, + throw new BundleLiteralException(s"Field $fieldName specified with unspecified value") + ) + case VecLitBinding(litMap) => + litMap.getOrElse( + value, + throw new VecLiteralException(s"Field $fieldIndex specified with unspecified value") + ) + } + val adjustedLitArg = litArg.cloneWithWidth(sample_element.width) + vecLitLinkedMap(bitField) = adjustedLitArg + + case recordField: Record => + if (!(recordField.typeEquivalent(value))) { + throw new VecLiteralException( + s"field $fieldIndex $recordField specified with non-type-equivalent value $value" + ) + } + // Copy the source BundleLitBinding with fields (keys) remapped to the clone + val remap = getMatchedFields(value, recordField).toMap + valueBinding.asInstanceOf[BundleLitBinding].litMap.map { + case (valueField, valueValue) => + vecLitLinkedMap(remap(valueField)) = valueValue + } - case vecField: Vec[_] => - if (!(vecField typeEquivalent value)) { - throw new VecLiteralException(s"field $fieldIndex $vecField specified with non-type-equivalent value $value") - } - // Copy the source VecLitBinding with vecFields (keys) remapped to the clone - val remap = getMatchedFields(value, vecField).toMap - value.topBinding.asInstanceOf[VecLitBinding].litMap.map { case (valueField, valueValue) => - vecLitLinkedMap(remap(valueField)) = valueValue - } + case vecField: Vec[_] => + if (!(vecField.typeEquivalent(value))) { + throw new VecLiteralException( + s"field $fieldIndex $vecField specified with non-type-equivalent value $value" + ) + } + // Copy the source VecLitBinding with vecFields (keys) remapped to the clone + val remap = getMatchedFields(value, vecField).toMap + value.topBinding.asInstanceOf[VecLitBinding].litMap.map { + case (valueField, valueValue) => + vecLitLinkedMap(remap(valueField)) = valueValue + } - case enumField: EnumType => { - if (!(enumField typeEquivalent value)) { - throw new VecLiteralException(s"field $fieldIndex $enumField specified with non-type-equivalent enum value $value") - } - val litArg = valueBinding match { - case ElementLitBinding(litArg) => litArg - case _ => - throw new VecLiteralException(s"field $fieldIndex $enumField could not bematched with $valueBinding") + case enumField: EnumType => { + if (!(enumField.typeEquivalent(value))) { + throw new VecLiteralException( + s"field $fieldIndex $enumField specified with non-type-equivalent enum value $value" + ) + } + val litArg = valueBinding match { + case ElementLitBinding(litArg) => litArg + case _ => + throw new VecLiteralException(s"field $fieldIndex $enumField could not bematched with $valueBinding") + } + vecLitLinkedMap(field) = litArg } - vecLitLinkedMap(field) = litArg - } - case _ => throw new VecLiteralException(s"unsupported field $fieldIndex of type $field") - } + case _ => throw new VecLiteralException(s"unsupported field $fieldIndex of type $field") + } } - clone.bind(VecLitBinding(VectorMap(vecLitLinkedMap.toSeq:_*))) + clone.bind(VecLitBinding(VectorMap(vecLitLinkedMap.toSeq: _*))) clone } } @@ -519,7 +563,12 @@ object VecInit extends SourceInfoDoc { /** Gets the correct connect operation (directed hardware assign or bulk connect) for element in Vec. */ - private def getConnectOpFromDirectionality[T <: Data](proto: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): (T, T) => Unit = proto.direction match { + private def getConnectOpFromDirectionality[T <: Data]( + proto: T + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): (T, T) => Unit = proto.direction match { case ActualDirection.Input | ActualDirection.Output | ActualDirection.Unspecified => // When internal wires are involved, driver / sink must be specified explicitly, otherwise // the system is unable to infer which is driver / sink @@ -557,8 +606,8 @@ object VecInit extends SourceInfoDoc { val vec = Wire(Vec(elts.length, cloneSupertype(elts, "Vec"))) val op = getConnectOpFromDirectionality(vec.head) - - (vec zip elts).foreach{ x => + + (vec.zip(elts)).foreach { x => op(x._1, x._2) } vec @@ -589,7 +638,13 @@ object VecInit extends SourceInfoDoc { def tabulate[T <: Data](n: Int)(gen: (Int) => T): Vec[T] = macro VecTransform.tabulate /** @group SourceInfoTransformMacro */ - def do_tabulate[T <: Data](n: Int)(gen: (Int) => T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Vec[T] = + def do_tabulate[T <: Data]( + n: Int + )(gen: (Int) => T + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Vec[T] = apply((0 until n).map(i => gen(i))) /** Creates a new 2D [[Vec]] of length `n by m` composed of the results of the given @@ -604,24 +659,31 @@ object VecInit extends SourceInfoDoc { def tabulate[T <: Data](n: Int, m: Int)(gen: (Int, Int) => T): Vec[Vec[T]] = macro VecTransform.tabulate2D /** @group SourceInfoTransformMacro */ - def do_tabulate[T <: Data](n: Int, m: Int)(gen: (Int, Int) => T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Vec[Vec[T]] = { + def do_tabulate[T <: Data]( + n: Int, + m: Int + )(gen: (Int, Int) => T + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Vec[Vec[T]] = { // TODO make this lazy (requires LazyList and cross compilation, beyond the scope of this PR) val elts = Seq.tabulate(n, m)(gen) val flatElts = elts.flatten require(flatElts.nonEmpty, "Vec hardware values are not allowed to be empty") flatElts.foreach(requireIsHardware(_, "vec element")) - + val tpe = cloneSupertype(flatElts, "Vec.tabulate") val myVec = Wire(Vec(n, Vec(m, tpe))) val op = getConnectOpFromDirectionality(myVec.head.head) - for ( - (xs1D, ys1D) <- myVec zip elts; - (x, y) <- xs1D zip ys1D - ) { - op(x, y) + for { + (xs1D, ys1D) <- myVec.zip(elts) + (x, y) <- xs1D.zip(ys1D) + } { + op(x, y) } - myVec + myVec } /** Creates a new 3D [[Vec]] of length `n by m by p` composed of the results of the given @@ -633,39 +695,48 @@ object VecInit extends SourceInfoDoc { * @param gen function that takes in an Int (the index) and returns a * [[Data]] that becomes the output element */ - def tabulate[T <: Data](n: Int, m: Int, p: Int)(gen: (Int, Int, Int) => T): Vec[Vec[Vec[T]]] = macro VecTransform.tabulate3D + def tabulate[T <: Data](n: Int, m: Int, p: Int)(gen: (Int, Int, Int) => T): Vec[Vec[Vec[T]]] = + macro VecTransform.tabulate3D /** @group SourceInfoTransformMacro */ - def do_tabulate[T <: Data](n: Int, m: Int, p: Int)(gen: (Int, Int, Int) => T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Vec[Vec[Vec[T]]] = { - // TODO make this lazy (requires LazyList and cross compilation, beyond the scope of this PR) + def do_tabulate[T <: Data]( + n: Int, + m: Int, + p: Int + )(gen: (Int, Int, Int) => T + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Vec[Vec[Vec[T]]] = { + // TODO make this lazy (requires LazyList and cross compilation, beyond the scope of this PR) val elts = Seq.tabulate(n, m, p)(gen) val flatElts = elts.flatten.flatten require(flatElts.nonEmpty, "Vec hardware values are not allowed to be empty") flatElts.foreach(requireIsHardware(_, "vec element")) - + val tpe = cloneSupertype(flatElts, "Vec.tabulate") val myVec = Wire(Vec(n, Vec(m, Vec(p, tpe)))) val op = getConnectOpFromDirectionality(myVec.head.head.head) - - for ( - (xs2D, ys2D) <- myVec zip elts; - (xs1D, ys1D) <- xs2D zip ys2D; - (x, y) <- xs1D zip ys1D - ) { - op(x, y) + + for { + (xs2D, ys2D) <- myVec.zip(elts) + (xs1D, ys1D) <- xs2D.zip(ys2D) + (x, y) <- xs1D.zip(ys1D) + } { + op(x, y) } myVec } /** Creates a new [[Vec]] of length `n` composed of the result of the given - * function applied to an element of data type T. - * - * @param n number of elements in the vector - * @param gen function that takes in an element T and returns an output - * element of the same type - */ + * function applied to an element of data type T. + * + * @param n number of elements in the vector + * @param gen function that takes in an element T and returns an output + * element of the same type + */ def fill[T <: Data](n: Int)(gen: => T): Vec[T] = macro VecTransform.fill /** @group SourceInfoTransformMacro */ @@ -673,49 +744,71 @@ object VecInit extends SourceInfoDoc { apply(Seq.fill(n)(gen)) /** Creates a new 2D [[Vec]] of length `n by m` composed of the result of the given - * function applied to an element of data type T. - * - * @param n number of inner vectors (rows) in the outer vector - * @param m number of elements in each inner vector (column) - * @param gen function that takes in an element T and returns an output - * element of the same type - */ + * function applied to an element of data type T. + * + * @param n number of inner vectors (rows) in the outer vector + * @param m number of elements in each inner vector (column) + * @param gen function that takes in an element T and returns an output + * element of the same type + */ def fill[T <: Data](n: Int, m: Int)(gen: => T): Vec[Vec[T]] = macro VecTransform.fill2D /** @group SourceInfoTransformMacro */ - def do_fill[T <: Data](n: Int, m: Int)(gen: => T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Vec[Vec[T]] = { + def do_fill[T <: Data]( + n: Int, + m: Int + )(gen: => T + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Vec[Vec[T]] = { do_tabulate(n, m)((_, _) => gen) } /** Creates a new 3D [[Vec]] of length `n by m by p` composed of the result of the given - * function applied to an element of data type T. - * - * @param n number of 2D vectors inside outer vector - * @param m number of 1D vectors in each 2D vector - * @param p number of elements in each 1D vector - * @param gen function that takes in an element T and returns an output - * element of the same type - */ + * function applied to an element of data type T. + * + * @param n number of 2D vectors inside outer vector + * @param m number of 1D vectors in each 2D vector + * @param p number of elements in each 1D vector + * @param gen function that takes in an element T and returns an output + * element of the same type + */ def fill[T <: Data](n: Int, m: Int, p: Int)(gen: => T): Vec[Vec[Vec[T]]] = macro VecTransform.fill3D /** @group SourceInfoTransformMacro */ - def do_fill[T <: Data](n: Int, m: Int, p: Int)(gen: => T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Vec[Vec[Vec[T]]] = { + def do_fill[T <: Data]( + n: Int, + m: Int, + p: Int + )(gen: => T + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Vec[Vec[Vec[T]]] = { do_tabulate(n, m, p)((_, _, _) => gen) } - + /** Creates a new [[Vec]] of length `n` composed of the result of the given - * function applied to an element of data type T. - * - * @param start First element in the Vec - * @param len Lenth of elements in the Vec - * @param f Function that applies the element T from previous index and returns the output - * element to the next index - */ + * function applied to an element of data type T. + * + * @param start First element in the Vec + * @param len Lenth of elements in the Vec + * @param f Function that applies the element T from previous index and returns the output + * element to the next index + */ def iterate[T <: Data](start: T, len: Int)(f: (T) => T): Vec[T] = macro VecTransform.iterate - + /** @group SourceInfoTransformMacro */ - def do_iterate[T <: Data](start: T, len: Int)(f: (T) => T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Vec[T] = - apply(Seq.iterate(start, len)(f)) + def do_iterate[T <: Data]( + start: T, + len: Int + )(f: (T) => T + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Vec[T] = + apply(Seq.iterate(start, len)(f)) } /** A trait for [[Vec]]s containing common hardware generators for collection @@ -737,7 +830,7 @@ trait VecLike[T <: Data] extends IndexedSeq[T] with HasId with SourceInfoDoc { /** @group SourceInfoTransformMacro */ def do_forall(p: T => Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = - (this map p).fold(true.B)(_ && _) + (this.map(p)).fold(true.B)(_ && _) /** Outputs true if p outputs true for at least one element. */ @@ -745,7 +838,7 @@ trait VecLike[T <: Data] extends IndexedSeq[T] with HasId with SourceInfoDoc { /** @group SourceInfoTransformMacro */ def do_exists(p: T => Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = - (this map p).fold(false.B)(_ || _) + (this.map(p)).fold(false.B)(_ || _) /** Outputs true if the vector contains at least one element equal to x (using * the === operator). @@ -762,12 +855,12 @@ trait VecLike[T <: Data] extends IndexedSeq[T] with HasId with SourceInfoDoc { /** @group SourceInfoTransformMacro */ def do_count(p: T => Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = - SeqUtils.count(this map p) + SeqUtils.count(this.map(p)) /** Helper function that appends an index (literal value) to each element, * useful for hardware generators which output an index. */ - private def indexWhereHelper(p: T => Bool) = this map p zip (0 until length).map(i => i.asUInt) + 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. */ @@ -816,19 +909,19 @@ abstract class Record(private[chisel3] implicit val compileOptions: CompileOptio // identifier; however, Namespace sanitizes identifiers to make them legal for Firrtl/Verilog // which can cause collisions val _namespace = Namespace.empty - for ((name, elt) <- elements) { elt.setRef(this, _namespace.name(name, leadingDigitOk=true)) } + for ((name, elt) <- elements) { elt.setRef(this, _namespace.name(name, leadingDigitOk = true)) } } private[chisel3] override def bind(target: Binding, parentDirection: SpecifiedDirection): Unit = { try { super.bind(target, parentDirection) - } catch { // nasty compatibility mode shim, where anything flies + } catch { // nasty compatibility mode shim, where anything flies case e: MixedDirectionAggregateException if !compileOptions.dontAssumeDirectionality => val resolvedDirection = SpecifiedDirection.fromParent(parentDirection, specifiedDirection) direction = resolvedDirection match { case SpecifiedDirection.Unspecified => ActualDirection.Bidirectional(ActualDirection.Default) - case SpecifiedDirection.Flip => ActualDirection.Bidirectional(ActualDirection.Flipped) - case _ => ActualDirection.Bidirectional(ActualDirection.Default) + case SpecifiedDirection.Flip => ActualDirection.Bidirectional(ActualDirection.Flipped) + case _ => ActualDirection.Bidirectional(ActualDirection.Default) } } setElementRefs() @@ -861,67 +954,85 @@ abstract class Record(private[chisel3] implicit val compileOptions: CompileOptio val cloneFields = getRecursiveFields(clone, "(bundle root)").toMap // Create the Bundle literal binding from litargs of arguments - val bundleLitMap = elems.map { fn => fn(clone) }.flatMap { case (field, value) => - val fieldName = cloneFields.getOrElse(field, - throw new BundleLiteralException(s"field $field (with value $value) is not a field," + - s" ensure the field is specified as a function returning a field on an object of class ${this.getClass}," + - s" eg '_.a' to select hypothetical bundle field 'a'") - ) - val valueBinding = value.topBindingOpt match { - case Some(litBinding: LitBinding) => litBinding - case _ => throw new BundleLiteralException(s"field $fieldName specified with non-literal value $value") - } + val bundleLitMap = elems.map { fn => fn(clone) }.flatMap { + case (field, value) => + val fieldName = cloneFields.getOrElse( + field, + throw new BundleLiteralException( + s"field $field (with value $value) is not a field," + + s" ensure the field is specified as a function returning a field on an object of class ${this.getClass}," + + s" eg '_.a' to select hypothetical bundle field 'a'" + ) + ) + val valueBinding = value.topBindingOpt match { + case Some(litBinding: LitBinding) => litBinding + case _ => throw new BundleLiteralException(s"field $fieldName specified with non-literal value $value") + } - field match { // Get the litArg(s) for this field - case field: Bits => - if (field.getClass != value.getClass) { // TODO typeEquivalent is too strict because it checks width - throw new BundleLiteralException(s"Field $fieldName $field specified with non-type-equivalent value $value") - } - val litArg = valueBinding match { - case ElementLitBinding(litArg) => litArg - case BundleLitBinding(litMap) => litMap.getOrElse(value, - throw new BundleLiteralException(s"Field $fieldName specified with unspecified value") - ) - case VecLitBinding(litMap) => litMap.getOrElse(value, - throw new VecLiteralException(s"Vec literal $fieldName specified with out literal values") - ) + field match { // Get the litArg(s) for this field + case field: Bits => + if (field.getClass != value.getClass) { // TODO typeEquivalent is too strict because it checks width + throw new BundleLiteralException( + s"Field $fieldName $field specified with non-type-equivalent value $value" + ) + } + val litArg = valueBinding match { + case ElementLitBinding(litArg) => litArg + case BundleLitBinding(litMap) => + litMap.getOrElse( + value, + throw new BundleLiteralException(s"Field $fieldName specified with unspecified value") + ) + case VecLitBinding(litMap) => + litMap.getOrElse( + value, + throw new VecLiteralException(s"Vec literal $fieldName specified with out literal values") + ) - } - Seq(field -> litArg) + } + Seq(field -> litArg) - case field: Record => - if (!(field typeEquivalent value)) { - throw new BundleLiteralException(s"field $fieldName $field specified with non-type-equivalent value $value") - } - // Copy the source BundleLitBinding with fields (keys) remapped to the clone - val remap = getMatchedFields(value, field).toMap - value.topBinding.asInstanceOf[BundleLitBinding].litMap.map { case (valueField, valueValue) => - remap(valueField) -> valueValue - } + case field: Record => + if (!(field.typeEquivalent(value))) { + throw new BundleLiteralException( + s"field $fieldName $field specified with non-type-equivalent value $value" + ) + } + // Copy the source BundleLitBinding with fields (keys) remapped to the clone + val remap = getMatchedFields(value, field).toMap + value.topBinding.asInstanceOf[BundleLitBinding].litMap.map { + case (valueField, valueValue) => + remap(valueField) -> valueValue + } - case vecField: Vec[_] => - if (!(vecField typeEquivalent value)) { - throw new BundleLiteralException(s"field $fieldName $vecField specified with non-type-equivalent value $value") - } - // Copy the source BundleLitBinding with fields (keys) remapped to the clone - val remap = getMatchedFields(value, vecField).toMap - value.topBinding.asInstanceOf[VecLitBinding].litMap.map { case (valueField, valueValue) => - remap(valueField) -> valueValue - } + case vecField: Vec[_] => + if (!(vecField.typeEquivalent(value))) { + throw new BundleLiteralException( + s"field $fieldName $vecField specified with non-type-equivalent value $value" + ) + } + // Copy the source BundleLitBinding with fields (keys) remapped to the clone + val remap = getMatchedFields(value, vecField).toMap + value.topBinding.asInstanceOf[VecLitBinding].litMap.map { + case (valueField, valueValue) => + remap(valueField) -> valueValue + } - case field: EnumType => { - if (!(field typeEquivalent value)) { - throw new BundleLiteralException(s"field $fieldName $field specified with non-type-equivalent enum value $value") - } - val litArg = valueBinding match { - case ElementLitBinding(litArg) => litArg - case _ => - throw new BundleLiteralException(s"field $fieldName $field could not be matched with $valueBinding") + case field: EnumType => { + if (!(field.typeEquivalent(value))) { + throw new BundleLiteralException( + s"field $fieldName $field specified with non-type-equivalent enum value $value" + ) + } + val litArg = valueBinding match { + case ElementLitBinding(litArg) => litArg + case _ => + throw new BundleLiteralException(s"field $fieldName $field could not be matched with $valueBinding") + } + Seq(field -> litArg) } - Seq(field -> litArg) + case _ => throw new BundleLiteralException(s"unsupported field $fieldName of type $field") } - case _ => throw new BundleLiteralException(s"unsupported field $fieldName of type $field") - } } // don't convert to a Map yet to preserve duplicate keys @@ -952,8 +1063,9 @@ abstract class Record(private[chisel3] implicit val compileOptions: CompileOptio override def toString: String = { topBindingOpt match { case Some(BundleLitBinding(_)) => - val contents = elements.toList.reverse.map { case (name, data) => - s"$name=$data" + val contents = elements.toList.reverse.map { + case (name, data) => + s"$name=$data" }.mkString(", ") s"$className($contents)" case _ => stringAccessor(s"$className") @@ -968,10 +1080,12 @@ abstract class Record(private[chisel3] implicit val compileOptions: CompileOptio private[chisel3] override def typeEquivalent(that: Data): Boolean = that match { case that: Record => this.getClass == that.getClass && - this.elements.size == that.elements.size && - this.elements.forall{case (name, model) => - that.elements.contains(name) && - (that.elements(name) typeEquivalent model)} + this.elements.size == that.elements.size && + this.elements.forall { + case (name, model) => + that.elements.contains(name) && + (that.elements(name).typeEquivalent(model)) + } case _ => false } @@ -990,11 +1104,14 @@ abstract class Record(private[chisel3] implicit val compileOptions: CompileOptio private[chisel3] def toPrintableHelper(elts: Seq[(String, Data)]): Printable = { val xs = if (elts.isEmpty) List.empty[Printable] // special case because of dropRight below - else elts flatMap { case (name, data) => - List(PString(s"$name -> "), data.toPrintable, PString(", ")) - } dropRight 1 // Remove trailing ", " + else + elts.flatMap { + case (name, data) => + List(PString(s"$name -> "), data.toPrintable, PString(", ")) + }.dropRight(1) // Remove trailing ", " PString(s"$className(") + Printables(xs) + PString(")") } + /** Default "pretty-print" implementation * Analogous to printing a Map * Results in "`\$className(elt0.name -> elt0.value, ...)`" @@ -1060,15 +1177,18 @@ package experimental { * }}} */ abstract class Bundle(implicit compileOptions: CompileOptions) extends Record { - assert(_usingPlugin, "The Chisel compiler plugin is now required for compiling Chisel code. " + - "Please see https://github.com/chipsalliance/chisel3#build-your-own-chisel-projects." + assert( + _usingPlugin, + "The Chisel compiler plugin is now required for compiling Chisel code. " + + "Please see https://github.com/chipsalliance/chisel3#build-your-own-chisel-projects." ) override def className: String = this.getClass.getSimpleName match { - case name if name.startsWith("$anon$") => "AnonymousBundle" // fallback for anonymous Bundle case - case "" => "AnonymousBundle" // ditto, but on other platforms - case name => name + case name if name.startsWith("$anon$") => "AnonymousBundle" // fallback for anonymous Bundle case + case "" => "AnonymousBundle" // ditto, but on other platforms + case name => name } + /** The collection of [[Data]] * * Elements defined earlier in the Bundle are higher order upon @@ -1093,7 +1213,7 @@ abstract class Bundle(implicit compileOptions: CompileOptions) extends Record { getBundleField(m) match { case Some(d: Data) => requireIsChiselType(d) - + if (nameMap contains m.getName) { require(nameMap(m.getName) eq d) } else { @@ -1102,21 +1222,25 @@ abstract class Bundle(implicit compileOptions: CompileOptions) extends Record { case None => if (!ignoreSeq) { m.invoke(this) match { - case s: scala.collection.Seq[Any] if s.nonEmpty => s.head match { - // Ignore empty Seq() - case d: Data => throwException("Public Seq members cannot be used to define Bundle elements " + - s"(found public Seq member '${m.getName}'). " + - "Either use a Vec if all elements are of the same type, or MixedVec if the elements " + - "are of different types. If this Seq member is not intended to construct RTL, mix in the trait " + - "IgnoreSeqInBundle.") - case _ => // don't care about non-Data Seq - } + case s: scala.collection.Seq[Any] if s.nonEmpty => + s.head match { + // Ignore empty Seq() + case d: Data => + throwException( + "Public Seq members cannot be used to define Bundle elements " + + s"(found public Seq member '${m.getName}'). " + + "Either use a Vec if all elements are of the same type, or MixedVec if the elements " + + "are of different types. If this Seq member is not intended to construct RTL, mix in the trait " + + "IgnoreSeqInBundle." + ) + case _ => // don't care about non-Data Seq + } case _ => // not a Seq } } } } - VectorMap(nameMap.toSeq sortWith { case ((an, a), (bn, b)) => (a._id > b._id) || ((a eq b) && (an > bn)) }: _*) + VectorMap(nameMap.toSeq.sortWith { case ((an, a), (bn, b)) => (a._id > b._id) || ((a eq b) && (an > bn)) }: _*) } /** @@ -1145,10 +1269,10 @@ abstract class Bundle(implicit compileOptions: CompileOptions) extends Record { if (clone.elements(name) eq field) { throw new AutoClonetypeException( s"Automatically cloned $clone has field '$name' aliased with base $this." + - " In the future, this will be solved automatically by the compiler plugin." + - " For now, ensure Chisel types used in the Bundle definition are passed through constructor arguments," + - " or wrapped in Input(...), Output(...), or Flipped(...) if appropriate." + - " As a last resort, you can override cloneType manually." + " In the future, this will be solved automatically by the compiler plugin." + + " For now, ensure Chisel types used in the Bundle definition are passed through constructor arguments," + + " or wrapped in Input(...), Output(...), or Flipped(...) if appropriate." + + " As a last resort, you can override cloneType manually." ) } } @@ -1166,7 +1290,9 @@ abstract class Bundle(implicit compileOptions: CompileOptions) extends Record { * @note This is overridden by the compiler plugin (this implementation is never called) */ protected def _cloneTypeImpl: Bundle = { - throwException(s"Internal Error! This should have been implemented by the chisel3-plugin. Please file an issue against chisel3") + throwException( + s"Internal Error! This should have been implemented by the chisel3-plugin. Please file an issue against chisel3" + ) } /** Default "pretty-print" implementation @@ -1177,4 +1303,3 @@ abstract class Bundle(implicit compileOptions: CompileOptions) extends Record { */ override def toPrintable: Printable = toPrintableHelper(elements.toList.reverse) } - diff --git a/core/src/main/scala/chisel3/Annotation.scala b/core/src/main/scala/chisel3/Annotation.scala index 545ea480..e08557eb 100644 --- a/core/src/main/scala/chisel3/Annotation.scala +++ b/core/src/main/scala/chisel3/Annotation.scala @@ -15,6 +15,7 @@ import firrtl.transforms.{DontTouchAnnotation, NoDedupAnnotation} * Defines a conversion to a corresponding FIRRTL Annotation */ trait ChiselAnnotation { + /** Conversion to FIRRTL Annotation */ def toFirrtl: Annotation } @@ -54,7 +55,7 @@ object annotate { * m.io.out * } * - *class AdderTester extends Module + * class AdderTester extends Module * with ConstantPropagationTest { * val io = IO(new Bundle { * val a = Input(UInt(32.W)) @@ -73,12 +74,13 @@ object annotate { */ object doNotDedup { + /** Marks a module to be ignored in Dedup Transform in Firrtl * * @param module The module to be marked * @return Unmodified signal `module` */ - def apply[T <: RawModule](module: T)(implicit compileOptions: CompileOptions): Unit = { + def apply[T <: RawModule](module: T)(implicit compileOptions: CompileOptions): Unit = { annotate(new ChiselAnnotation { def toFirrtl = NoDedupAnnotation(module.toNamed) }) } } diff --git a/core/src/main/scala/chisel3/Attach.scala b/core/src/main/scala/chisel3/Attach.scala index 0e005690..5c9cfe53 100644 --- a/core/src/main/scala/chisel3/Attach.scala +++ b/core/src/main/scala/chisel3/Attach.scala @@ -43,4 +43,3 @@ object attach { } } } - diff --git a/core/src/main/scala/chisel3/Bits.scala b/core/src/main/scala/chisel3/Bits.scala index 5ab04d13..8a616d02 100644 --- a/core/src/main/scala/chisel3/Bits.scala +++ b/core/src/main/scala/chisel3/Bits.scala @@ -8,13 +8,11 @@ import chisel3.experimental.{FixedPoint, Interval} import chisel3.internal._ import chisel3.internal.Builder.pushOp import chisel3.internal.firrtl._ -import chisel3.internal.sourceinfo.{SourceInfo, SourceInfoTransform, SourceInfoWhiteboxTransform, - UIntTransform} +import chisel3.internal.sourceinfo.{SourceInfo, SourceInfoTransform, SourceInfoWhiteboxTransform, UIntTransform} import chisel3.internal.firrtl.PrimOp._ import _root_.firrtl.{ir => firrtlir} import _root_.firrtl.{constraint => firrtlconstraint} - /** Exists to unify common interfaces of [[Bits]] and [[Reset]]. * * @note This is a workaround because macros cannot override abstract methods. @@ -27,7 +25,10 @@ private[chisel3] sealed trait ToBoolable extends Element { */ final def asBool: Bool = macro SourceInfoWhiteboxTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def asBool(dummy: Int*): Bool = macro SourceInfoWhiteboxTransform.noArgDummy /** @group SourceInfoTransformMacro */ @@ -82,7 +83,7 @@ sealed abstract class Bits(private[chisel3] val width: Width) extends Element wi /** @group SourceInfoTransformMacro */ def do_head(n: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = { width match { - case KnownWidth(x) => require(x >= n, s"Can't head($n) for width $x < $n") + case KnownWidth(x) => require(x >= n, s"Can't head($n) for width $x < $n") case UnknownWidth() => } binop(sourceInfo, UInt(Width(n)), HeadOp, n) @@ -217,7 +218,7 @@ sealed abstract class Bits(private[chisel3] val width: Width) extends Element wi /** @group SourceInfoTransformMacro */ def do_pad(that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): this.type = this.width match { case KnownWidth(w) if w >= that => this - case _ => binop(sourceInfo, cloneTypeWidth(this.width max Width(that)), PadOp, that) + case _ => binop(sourceInfo, cloneTypeWidth(this.width.max(Width(that))), PadOp, that) } /** Bitwise inversion operator @@ -227,11 +228,14 @@ sealed abstract class Bits(private[chisel3] val width: Width) extends Element wi */ final def unary_~ : Bits = macro SourceInfoWhiteboxTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def unary_~(dummy: Int*): Bits = macro SourceInfoWhiteboxTransform.noArgDummy /** @group SourceInfoTransformMacro */ - def do_unary_~ (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits + def do_unary_~(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits /** Static left shift operator * @@ -242,10 +246,10 @@ sealed abstract class Bits(private[chisel3] val width: Width) extends Element wi */ // REVIEW TODO: redundant // REVIEW TODO: should these return this.type or Bits? - final def << (that: BigInt): Bits = macro SourceInfoWhiteboxTransform.thatArg + final def <<(that: BigInt): Bits = macro SourceInfoWhiteboxTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_<< (that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits + def do_<<(that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits /** Static left shift operator * @@ -254,10 +258,10 @@ sealed abstract class Bits(private[chisel3] val width: Width) extends Element wi * $sumWidthInt * @group Bitwise */ - final def << (that: Int): Bits = macro SourceInfoWhiteboxTransform.thatArg + final def <<(that: Int): Bits = macro SourceInfoWhiteboxTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_<< (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits + def do_<<(that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits /** Dynamic left shift operator * @@ -266,10 +270,10 @@ sealed abstract class Bits(private[chisel3] val width: Width) extends Element wi * @note The width of the returned $coll is `width of this + pow(2, width of that) - 1`. * @group Bitwise */ - final def << (that: UInt): Bits = macro SourceInfoWhiteboxTransform.thatArg + final def <<(that: UInt): Bits = macro SourceInfoWhiteboxTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_<< (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits + def do_<<(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits /** Static right shift operator * @@ -279,10 +283,10 @@ sealed abstract class Bits(private[chisel3] val width: Width) extends Element wi * @group Bitwise */ // REVIEW TODO: redundant - final def >> (that: BigInt): Bits = macro SourceInfoWhiteboxTransform.thatArg + final def >>(that: BigInt): Bits = macro SourceInfoWhiteboxTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_>> (that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits + def do_>>(that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits /** Static right shift operator * @@ -291,10 +295,10 @@ sealed abstract class Bits(private[chisel3] val width: Width) extends Element wi * $unchangedWidth * @group Bitwise */ - final def >> (that: Int): Bits = macro SourceInfoWhiteboxTransform.thatArg + final def >>(that: Int): Bits = macro SourceInfoWhiteboxTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_>> (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits + def do_>>(that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits /** Dynamic right shift operator * @@ -304,15 +308,18 @@ sealed abstract class Bits(private[chisel3] val width: Width) extends Element wi * $unchangedWidth * @group Bitwise */ - final def >> (that: UInt): Bits = macro SourceInfoWhiteboxTransform.thatArg + final def >>(that: UInt): Bits = macro SourceInfoWhiteboxTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_>> (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits + def do_>>(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits /** Returns the contents of this wire as a [[scala.collection.Seq]] of [[Bool]]. */ final def asBools: Seq[Bool] = macro SourceInfoTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def asBools(dummy: Int*): Seq[Bool] = macro SourceInfoWhiteboxTransform.noArgDummy /** @group SourceInfoTransformMacro */ @@ -326,7 +333,10 @@ sealed abstract class Bits(private[chisel3] val width: Width) extends Element wi */ final def asSInt: SInt = macro SourceInfoTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def asSInt(dummy: Int*): SInt = macro SourceInfoWhiteboxTransform.noArgDummy /** @group SourceInfoTransformMacro */ @@ -341,7 +351,12 @@ sealed abstract class Bits(private[chisel3] val width: Width) extends Element wi final def asFixedPoint(that: BinaryPoint): FixedPoint = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_asFixedPoint(that: BinaryPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = { + def do_asFixedPoint( + that: BinaryPoint + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): FixedPoint = { throwException(s"Cannot call .asFixedPoint on $this") } @@ -360,7 +375,7 @@ sealed abstract class Bits(private[chisel3] val width: Width) extends Element wi final def do_asBool(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = { width match { case KnownWidth(1) => this(0) - case _ => throwException(s"can't covert ${this.getClass.getSimpleName}$width to Bool") + case _ => throwException(s"can't covert ${this.getClass.getSimpleName}$width to Bool") } } @@ -371,10 +386,10 @@ sealed abstract class Bits(private[chisel3] val width: Width) extends Element wi * $sumWidth * @group Bitwise */ - final def ## (that: Bits): UInt = macro SourceInfoTransform.thatArg + final def ##(that: Bits): UInt = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_## (that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = { + def do_##(that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = { val w = this.width + that.width pushOp(DefPrim(sourceInfo, UInt(w), ConcatOp, this.ref, that.ref)) } @@ -401,7 +416,7 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U override def toString: String = { litOption match { case Some(value) => s"UInt$width($value)" - case _ => stringAccessor(s"UInt$width") + case _ => stringAccessor(s"UInt$width") } } @@ -420,7 +435,10 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U */ final def unary_- : UInt = macro SourceInfoTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def unary_-(dummy: Int*): UInt = macro SourceInfoTransform.noArgDummy /** Unary negation (constant width) @@ -431,21 +449,25 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U */ final def unary_-% : UInt = macro SourceInfoTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def unary_%(dummy: Int*): UInt = macro SourceInfoTransform.noArgDummy /** @group SourceInfoTransformMacro */ - def do_unary_- (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) : UInt = 0.U - this + def do_unary_-(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = 0.U - this + /** @group SourceInfoTransformMacro */ - def do_unary_-% (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = 0.U -% this + def do_unary_-%(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = 0.U -% this - override def do_+ (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = this +% that - override def do_- (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = this -% that - override def do_/ (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + override def do_+(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = this +% that + override def do_-(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = this -% that + override def do_/(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = binop(sourceInfo, UInt(this.width), DivideOp, that) - override def do_% (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = - binop(sourceInfo, UInt(this.width min that.width), RemOp, that) - override def do_* (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + override def do_%(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + binop(sourceInfo, UInt(this.width.min(that.width)), RemOp, that) + override def do_*(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = binop(sourceInfo, UInt(this.width + that.width), TimesOp, that) /** Multiplication operator @@ -456,9 +478,10 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U * $singleCycleMul * @group Arithmetic */ - final def * (that: SInt): SInt = macro SourceInfoTransform.thatArg + final def *(that: SInt): SInt = macro SourceInfoTransform.thatArg + /** @group SourceInfoTransformMacro */ - def do_* (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = that * this + def do_*(that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = that * this /** Addition operator (expanding width) * @@ -467,7 +490,7 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U * $maxWidthPlusOne * @group Arithmetic */ - final def +& (that: UInt): UInt = macro SourceInfoTransform.thatArg + final def +&(that: UInt): UInt = macro SourceInfoTransform.thatArg /** Addition operator (constant width) * @@ -476,7 +499,7 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U * $maxWidth * @group Arithmetic */ - final def +% (that: UInt): UInt = macro SourceInfoTransform.thatArg + final def +%(that: UInt): UInt = macro SourceInfoTransform.thatArg /** Subtraction operator (increasing width) * @@ -485,7 +508,7 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U * $maxWidthPlusOne * @group Arithmetic */ - final def -& (that: UInt): UInt = macro SourceInfoTransform.thatArg + final def -&(that: UInt): UInt = macro SourceInfoTransform.thatArg /** Subtraction operator (constant width) * @@ -494,20 +517,23 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U * $maxWidth * @group Arithmetic */ - final def -% (that: UInt): UInt = macro SourceInfoTransform.thatArg + final def -%(that: UInt): UInt = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_+& (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = - binop(sourceInfo, UInt((this.width max that.width) + 1), AddOp, that) + def do_+&(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + binop(sourceInfo, UInt((this.width.max(that.width)) + 1), AddOp, that) + /** @group SourceInfoTransformMacro */ - def do_+% (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + def do_+%(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = (this +& that).tail(1) + /** @group SourceInfoTransformMacro */ - def do_-& (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = - (this subtractAsSInt that).asUInt + def do_-&(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + (this.subtractAsSInt(that)).asUInt + /** @group SourceInfoTransformMacro */ - def do_-% (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = - (this subtractAsSInt that).tail(1) + def do_-%(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + (this.subtractAsSInt(that)).tail(1) /** Bitwise and operator * @@ -516,7 +542,7 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U * $maxWidth * @group Bitwise */ - final def & (that: UInt): UInt = macro SourceInfoTransform.thatArg + final def &(that: UInt): UInt = macro SourceInfoTransform.thatArg /** Bitwise or operator * @@ -525,7 +551,7 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U * $maxWidth * @group Bitwise */ - final def | (that: UInt): UInt = macro SourceInfoTransform.thatArg + final def |(that: UInt): UInt = macro SourceInfoTransform.thatArg /** Bitwise exclusive or (xor) operator * @@ -534,23 +560,25 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U * $maxWidth * @group Bitwise */ - final def ^ (that: UInt): UInt = macro SourceInfoTransform.thatArg + final def ^(that: UInt): UInt = macro SourceInfoTransform.thatArg // override def abs: UInt = macro SourceInfoTransform.noArgDummy def do_abs(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = this /** @group SourceInfoTransformMacro */ - def do_& (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = - binop(sourceInfo, UInt(this.width max that.width), BitAndOp, that) + def do_&(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + binop(sourceInfo, UInt(this.width.max(that.width)), BitAndOp, that) + /** @group SourceInfoTransformMacro */ - def do_| (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = - binop(sourceInfo, UInt(this.width max that.width), BitOrOp, that) + def do_|(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + binop(sourceInfo, UInt(this.width.max(that.width)), BitOrOp, that) + /** @group SourceInfoTransformMacro */ - def do_^ (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = - binop(sourceInfo, UInt(this.width max that.width), BitXorOp, that) + def do_^(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + binop(sourceInfo, UInt(this.width.max(that.width)), BitXorOp, that) /** @group SourceInfoTransformMacro */ - def do_unary_~ (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + def do_unary_~(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = unop(sourceInfo, UInt(width = width), BitNotOp) // REVIEW TODO: Can these be defined on Bits? @@ -561,7 +589,10 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U */ final def orR: Bool = macro SourceInfoTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def orR(dummy: Int*): Bool = macro SourceInfoTransform.noArgDummy /** And reduction operator @@ -571,7 +602,10 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U */ final def andR: Bool = macro SourceInfoTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def andR(dummy: Int*): Bool = macro SourceInfoTransform.noArgDummy /** Exclusive or (xor) reduction operator @@ -581,20 +615,29 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U */ final def xorR: Bool = macro SourceInfoTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def xorR(dummy: Int*): Bool = macro SourceInfoTransform.noArgDummy /** @group SourceInfoTransformMacro */ def do_orR(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = redop(sourceInfo, OrReduceOp) + /** @group SourceInfoTransformMacro */ def do_andR(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = redop(sourceInfo, AndReduceOp) + /** @group SourceInfoTransformMacro */ def do_xorR(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = redop(sourceInfo, XorReduceOp) - override def do_< (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, LessOp, that) - override def do_> (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, GreaterOp, that) - override def do_<= (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, LessEqOp, that) - override def do_>= (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, GreaterEqOp, that) + override def do_<(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + compop(sourceInfo, LessOp, that) + override def do_>(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + compop(sourceInfo, GreaterOp, that) + override def do_<=(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + compop(sourceInfo, LessEqOp, that) + override def do_>=(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + compop(sourceInfo, GreaterEqOp, that) /** Dynamic not equals operator * @@ -602,7 +645,7 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U * @return a hardware [[Bool]] asserted if this $coll is not equal to `that` * @group Comparison */ - final def =/= (that: UInt): Bool = macro SourceInfoTransform.thatArg + final def =/=(that: UInt): Bool = macro SourceInfoTransform.thatArg /** Dynamic equals operator * @@ -610,12 +653,15 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U * @return a hardware [[Bool]] asserted if this $coll is equal to `that` * @group Comparison */ - final def === (that: UInt): Bool = macro SourceInfoTransform.thatArg + final def ===(that: UInt): Bool = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_=/= (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, NotEqualOp, that) + def do_=/=(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + compop(sourceInfo, NotEqualOp, that) + /** @group SourceInfoTransformMacro */ - def do_=== (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, EqualOp, that) + def do_===(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + compop(sourceInfo, EqualOp, that) /** Unary not * @@ -624,70 +670,78 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U */ final def unary_! : Bool = macro SourceInfoTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") - final def unary_! (dummy: Int*): Bool = macro SourceInfoTransform.noArgDummy + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) + final def unary_!(dummy: Int*): Bool = macro SourceInfoTransform.noArgDummy /** @group SourceInfoTransformMacro */ - def do_unary_! (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) : Bool = this === 0.U(1.W) + def do_unary_!(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = this === 0.U(1.W) - override def do_<< (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + override def do_<<(that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = binop(sourceInfo, UInt(this.width + that), ShiftLeftOp, validateShiftAmount(that)) - override def do_<< (that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + override def do_<<(that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = this << castToInt(that, "Shift amount") - override def do_<< (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + override def do_<<(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = binop(sourceInfo, UInt(this.width.dynamicShiftLeft(that.width)), DynamicShiftLeftOp, that) - override def do_>> (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + override def do_>>(that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = binop(sourceInfo, UInt(this.width.shiftRight(that)), ShiftRightOp, validateShiftAmount(that)) - override def do_>> (that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + override def do_>>(that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = this >> castToInt(that, "Shift amount") - override def do_>> (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = + override def do_>>(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = binop(sourceInfo, UInt(this.width), DynamicShiftRightOp, that) /** - * Circular shift to the left - * @param that number of bits to rotate - * @return UInt of same width rotated left n bits - */ - final def rotateLeft(that: Int): UInt = macro SourceInfoWhiteboxTransform.thatArg + * Circular shift to the left + * @param that number of bits to rotate + * @return UInt of same width rotated left n bits + */ + final def rotateLeft(that: Int): UInt = macro SourceInfoWhiteboxTransform.thatArg def do_rotateLeft(n: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = width match { - case _ if (n == 0) => this + case _ if (n == 0) => this case KnownWidth(w) if (w <= 1) => this - case KnownWidth(w) if n >= w => do_rotateLeft(n % w) - case _ if (n < 0) => do_rotateRight(-n) - case _ => tail(n) ## head(n) + case KnownWidth(w) if n >= w => do_rotateLeft(n % w) + case _ if (n < 0) => do_rotateRight(-n) + case _ => tail(n) ## head(n) } /** - * Circular shift to the right - * @param that number of bits to rotate - * @return UInt of same width rotated right n bits - */ - final def rotateRight(that: Int): UInt = macro SourceInfoWhiteboxTransform.thatArg + * Circular shift to the right + * @param that number of bits to rotate + * @return UInt of same width rotated right n bits + */ + final def rotateRight(that: Int): UInt = macro SourceInfoWhiteboxTransform.thatArg def do_rotateRight(n: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = width match { - case _ if (n <= 0) => do_rotateLeft(-n) + case _ if (n <= 0) => do_rotateLeft(-n) case KnownWidth(w) if (w <= 1) => this - case KnownWidth(w) if n >= w => do_rotateRight(n % w) - case _ => this(n - 1, 0) ## (this >> n) + case KnownWidth(w) if n >= w => do_rotateRight(n % w) + case _ => this(n - 1, 0) ## (this >> n) } - final def rotateRight(that: UInt): UInt = macro SourceInfoWhiteboxTransform.thatArg + final def rotateRight(that: UInt): UInt = macro SourceInfoWhiteboxTransform.thatArg - private def dynamicShift(n: UInt, staticShift: (UInt,Int) => UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) : UInt = - n.asBools().zipWithIndex.foldLeft(this){ - case (in, (en, sh)) => Mux(en, staticShift(in, 1 << sh), in) + private def dynamicShift( + n: UInt, + staticShift: (UInt, Int) => UInt + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): UInt = + n.asBools().zipWithIndex.foldLeft(this) { + case (in, (en, sh)) => Mux(en, staticShift(in, 1 << sh), in) } def do_rotateRight(n: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = dynamicShift(n, _ rotateRight _) - final def rotateLeft(that: UInt): UInt = macro SourceInfoWhiteboxTransform.thatArg + final def rotateLeft(that: UInt): UInt = macro SourceInfoWhiteboxTransform.thatArg def do_rotateLeft(n: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = dynamicShift(n, _ rotateLeft _) - /** Conditionally set or clear a bit * * @param off a dynamic offset @@ -712,7 +766,10 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U */ final def zext: SInt = macro SourceInfoTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def zext(dummy: Int*): SInt = macro SourceInfoTransform.noArgDummy /** @group SourceInfoTransformMacro */ @@ -722,44 +779,58 @@ sealed class UInt private[chisel3] (width: Width) extends Bits(width) with Num[U override def do_asSInt(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = pushOp(DefPrim(sourceInfo, SInt(width), AsSIntOp, ref)) override def do_asUInt(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = this - override def do_asFixedPoint(binaryPoint: BinaryPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = { + 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") + throwException( + s"cannot call $this.asFixedPoint(binaryPoint=$binaryPoint), you must specify a known binaryPoint" + ) } } - override def do_asInterval(range: IntervalRange = IntervalRange.Unknown) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = { + override def do_asInterval( + range: IntervalRange = IntervalRange.Unknown + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Interval = { (range.lower, range.upper, range.binaryPoint) match { case (lx: firrtlconstraint.IsKnown, ux: firrtlconstraint.IsKnown, KnownBinaryPoint(bp)) => // No mechanism to pass open/close to firrtl so need to handle directly val l = lx match { - case firrtlir.Open(x) => x + BigDecimal(1) / BigDecimal(BigInt(1) << bp) + case firrtlir.Open(x) => x + BigDecimal(1) / BigDecimal(BigInt(1) << bp) case firrtlir.Closed(x) => x } val u = ux match { - case firrtlir.Open(x) => x - BigDecimal(1) / BigDecimal(BigInt(1) << bp) + case firrtlir.Open(x) => x - BigDecimal(1) / BigDecimal(BigInt(1) << bp) case firrtlir.Closed(x) => x } val minBI = (l * BigDecimal(BigInt(1) << bp)).setScale(0, BigDecimal.RoundingMode.FLOOR).toBigIntExact.get val maxBI = (u * BigDecimal(BigInt(1) << bp)).setScale(0, BigDecimal.RoundingMode.FLOOR).toBigIntExact.get pushOp(DefPrim(sourceInfo, Interval(range), AsIntervalOp, ref, ILit(minBI), ILit(maxBI), ILit(bp))) case _ => - throwException( - s"cannot call $this.asInterval($range), you must specify a known binaryPoint and range") + throwException(s"cannot call $this.asInterval($range), you must specify a known binaryPoint and range") } } - private[chisel3] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, - compileOptions: CompileOptions): Unit = { + private[chisel3] override def connectFromBits( + that: Bits + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Unit = { this := that.asUInt } private def subtractAsSInt(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = - binop(sourceInfo, SInt((this.width max that.width) + 1), SubOp, that) + binop(sourceInfo, SInt((this.width.max(that.width)) + 1), SubOp, that) } /** A data type for signed integers, represented as a binary bitvector. Defines arithmetic operations between other @@ -774,12 +845,12 @@ sealed class SInt private[chisel3] (width: Width) extends Bits(width) with Num[S override def toString: String = { litOption match { case Some(value) => s"SInt$width($value)" - case _ => stringAccessor(s"SInt$width") + case _ => stringAccessor(s"SInt$width") } } private[chisel3] override def typeEquivalent(that: Data): Boolean = - this.getClass == that.getClass && this.width == that.width // TODO: should this be true for unspecified widths? + this.getClass == that.getClass && this.width == that.width // TODO: should this be true for unspecified widths? private[chisel3] override def cloneTypeWidth(w: Width): this.type = new SInt(w).asInstanceOf[this.type] @@ -792,7 +863,10 @@ sealed class SInt private[chisel3] (width: Width) extends Bits(width) with Num[S */ final def unary_- : SInt = macro SourceInfoTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def unary_-(dummy: Int*): SInt = macro SourceInfoTransform.noArgDummy /** Unary negation (constant width) @@ -803,26 +877,31 @@ sealed class SInt private[chisel3] (width: Width) extends Bits(width) with Num[S */ final def unary_-% : SInt = macro SourceInfoTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def unary_-%(dummy: Int*): SInt = macro SourceInfoTransform.noArgDummy /** @group SourceInfoTransformMacro */ - def do_unary_- (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = 0.S - this + def do_unary_-(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = 0.S - this + /** @group SourceInfoTransformMacro */ - def do_unary_-% (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = 0.S -% this + def do_unary_-%(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = 0.S -% this /** add (default - no growth) operator */ - override def do_+ (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + override def do_+(that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = this +% that + /** subtract (default - no growth) operator */ - override def do_- (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + override def do_-(that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = this -% that - override def do_* (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + override def do_*(that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = binop(sourceInfo, SInt(this.width + that.width), TimesOp, that) - override def do_/ (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + override def do_/(that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = binop(sourceInfo, SInt(this.width + 1), DivideOp, that) - override def do_% (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = - binop(sourceInfo, SInt(this.width min that.width), RemOp, that) + override def do_%(that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + binop(sourceInfo, SInt(this.width.min(that.width)), RemOp, that) /** Multiplication operator * @@ -832,9 +911,10 @@ sealed class SInt private[chisel3] (width: Width) extends Bits(width) with Num[S * $singleCycleMul * @group Arithmetic */ - final def * (that: UInt): SInt = macro SourceInfoTransform.thatArg + final def *(that: UInt): SInt = macro SourceInfoTransform.thatArg + /** @group SourceInfoTransformMacro */ - def do_* (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = { + def do_*(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = { val thatToSInt = that.zext val result = binop(sourceInfo, SInt(this.width + thatToSInt.width), TimesOp, thatToSInt) result.tail(1).asSInt @@ -847,7 +927,7 @@ sealed class SInt private[chisel3] (width: Width) extends Bits(width) with Num[S * $maxWidthPlusOne * @group Arithmetic */ - final def +& (that: SInt): SInt = macro SourceInfoTransform.thatArg + final def +&(that: SInt): SInt = macro SourceInfoTransform.thatArg /** Addition operator (constant width) * @@ -856,7 +936,7 @@ sealed class SInt private[chisel3] (width: Width) extends Bits(width) with Num[S * $maxWidth * @group Arithmetic */ - final def +% (that: SInt): SInt = macro SourceInfoTransform.thatArg + final def +%(that: SInt): SInt = macro SourceInfoTransform.thatArg /** Subtraction operator (increasing width) * @@ -865,7 +945,7 @@ sealed class SInt private[chisel3] (width: Width) extends Bits(width) with Num[S * $maxWidthPlusOne * @group Arithmetic */ - final def -& (that: SInt): SInt = macro SourceInfoTransform.thatArg + final def -&(that: SInt): SInt = macro SourceInfoTransform.thatArg /** Subtraction operator (constant width) * @@ -874,19 +954,22 @@ sealed class SInt private[chisel3] (width: Width) extends Bits(width) with Num[S * $maxWidth * @group Arithmetic */ - final def -% (that: SInt): SInt = macro SourceInfoTransform.thatArg + final def -%(that: SInt): SInt = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_+& (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = - binop(sourceInfo, SInt((this.width max that.width) + 1), AddOp, that) + def do_+&(that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + binop(sourceInfo, SInt((this.width.max(that.width)) + 1), AddOp, that) + /** @group SourceInfoTransformMacro */ - def do_+% (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + def do_+%(that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = (this +& that).tail(1).asSInt + /** @group SourceInfoTransformMacro */ - def do_-& (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = - binop(sourceInfo, SInt((this.width max that.width) + 1), SubOp, that) + def do_-&(that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + binop(sourceInfo, SInt((this.width.max(that.width)) + 1), SubOp, that) + /** @group SourceInfoTransformMacro */ - def do_-% (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + def do_-%(that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = (this -& that).tail(1).asSInt /** Bitwise and operator @@ -896,7 +979,7 @@ sealed class SInt private[chisel3] (width: Width) extends Bits(width) with Num[S * $maxWidth * @group Bitwise */ - final def & (that: SInt): SInt = macro SourceInfoTransform.thatArg + final def &(that: SInt): SInt = macro SourceInfoTransform.thatArg /** Bitwise or operator * @@ -905,7 +988,7 @@ sealed class SInt private[chisel3] (width: Width) extends Bits(width) with Num[S * $maxWidth * @group Bitwise */ - final def | (that: SInt): SInt = macro SourceInfoTransform.thatArg + final def |(that: SInt): SInt = macro SourceInfoTransform.thatArg /** Bitwise exclusive or (xor) operator * @@ -914,26 +997,32 @@ sealed class SInt private[chisel3] (width: Width) extends Bits(width) with Num[S * $maxWidth * @group Bitwise */ - final def ^ (that: SInt): SInt = macro SourceInfoTransform.thatArg + final def ^(that: SInt): SInt = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_& (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = - binop(sourceInfo, UInt(this.width max that.width), BitAndOp, that).asSInt + def do_&(that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + binop(sourceInfo, UInt(this.width.max(that.width)), BitAndOp, that).asSInt + /** @group SourceInfoTransformMacro */ - def do_| (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = - binop(sourceInfo, UInt(this.width max that.width), BitOrOp, that).asSInt + def do_|(that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + binop(sourceInfo, UInt(this.width.max(that.width)), BitOrOp, that).asSInt + /** @group SourceInfoTransformMacro */ - def do_^ (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = - binop(sourceInfo, UInt(this.width max that.width), BitXorOp, that).asSInt + def do_^(that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + binop(sourceInfo, UInt(this.width.max(that.width)), BitXorOp, that).asSInt /** @group SourceInfoTransformMacro */ - def do_unary_~ (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + def do_unary_~(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = unop(sourceInfo, UInt(width = width), BitNotOp).asSInt - override def do_< (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, LessOp, that) - override def do_> (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, GreaterOp, that) - override def do_<= (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, LessEqOp, that) - override def do_>= (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, GreaterEqOp, that) + override def do_<(that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + compop(sourceInfo, LessOp, that) + override def do_>(that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + compop(sourceInfo, GreaterOp, that) + override def do_<=(that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + compop(sourceInfo, LessEqOp, that) + override def do_>=(that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + compop(sourceInfo, GreaterEqOp, that) /** Dynamic not equals operator * @@ -941,7 +1030,7 @@ sealed class SInt private[chisel3] (width: Width) extends Bits(width) with Num[S * @return a hardware [[Bool]] asserted if this $coll is not equal to `that` * @group Comparison */ - final def =/= (that: SInt): Bool = macro SourceInfoTransform.thatArg + final def =/=(that: SInt): Bool = macro SourceInfoTransform.thatArg /** Dynamic equals operator * @@ -949,12 +1038,15 @@ sealed class SInt private[chisel3] (width: Width) extends Bits(width) with Num[S * @return a hardware [[Bool]] asserted if this $coll is equal to `that` * @group Comparison */ - final def === (that: SInt): Bool = macro SourceInfoTransform.thatArg + final def ===(that: SInt): Bool = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_=/= (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, NotEqualOp, that) + def do_=/=(that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + compop(sourceInfo, NotEqualOp, that) + /** @group SourceInfoTransformMacro */ - def do_=== (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, EqualOp, that) + def do_===(that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + compop(sourceInfo, EqualOp, that) // final def abs(): UInt = macro SourceInfoTransform.noArgDummy @@ -962,42 +1054,55 @@ sealed class SInt private[chisel3] (width: Width) extends Bits(width) with Num[S Mux(this < 0.S, -this, this) } - override def do_<< (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + override def do_<<(that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = binop(sourceInfo, SInt(this.width + that), ShiftLeftOp, validateShiftAmount(that)) - override def do_<< (that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + override def do_<<(that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = this << castToInt(that, "Shift amount") - override def do_<< (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + override def do_<<(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = binop(sourceInfo, SInt(this.width.dynamicShiftLeft(that.width)), DynamicShiftLeftOp, that) - override def do_>> (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + override def do_>>(that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = binop(sourceInfo, SInt(this.width.shiftRight(that)), ShiftRightOp, validateShiftAmount(that)) - override def do_>> (that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + override def do_>>(that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = this >> castToInt(that, "Shift amount") - override def do_>> (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = + override def do_>>(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SInt = binop(sourceInfo, SInt(this.width), DynamicShiftRightOp, that) - override def do_asUInt(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = pushOp(DefPrim(sourceInfo, UInt(this.width), AsUIntOp, ref)) + 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 = this - override def do_asFixedPoint(binaryPoint: BinaryPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = { + 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") + throwException( + s"cannot call $this.asFixedPoint(binaryPoint=$binaryPoint), you must specify a known binaryPoint" + ) } } - override def do_asInterval(range: IntervalRange = IntervalRange.Unknown) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = { + override def do_asInterval( + range: IntervalRange = IntervalRange.Unknown + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Interval = { (range.lower, range.upper, range.binaryPoint) match { case (lx: firrtlconstraint.IsKnown, ux: firrtlconstraint.IsKnown, KnownBinaryPoint(bp)) => // No mechanism to pass open/close to firrtl so need to handle directly val l = lx match { - case firrtlir.Open(x) => x + BigDecimal(1) / BigDecimal(BigInt(1) << bp) + case firrtlir.Open(x) => x + BigDecimal(1) / BigDecimal(BigInt(1) << bp) case firrtlir.Closed(x) => x } val u = ux match { - case firrtlir.Open(x) => x - BigDecimal(1) / BigDecimal(BigInt(1) << bp) + case firrtlir.Open(x) => x - BigDecimal(1) / BigDecimal(BigInt(1) << bp) case firrtlir.Closed(x) => x } //TODO: (chick) Need to determine, what asInterval needs, and why it might need min and max as args -- CAN IT BE UNKNOWN? @@ -1006,21 +1111,29 @@ sealed class SInt private[chisel3] (width: Width) extends Bits(width) with Num[S val maxBI = (u * BigDecimal(BigInt(1) << bp)).setScale(0, BigDecimal.RoundingMode.FLOOR).toBigIntExact.get pushOp(DefPrim(sourceInfo, Interval(range), AsIntervalOp, ref, ILit(minBI), ILit(maxBI), ILit(bp))) case _ => - throwException( - s"cannot call $this.asInterval($range), you must specify a known binaryPoint and range") + throwException(s"cannot call $this.asInterval($range), you must specify a known binaryPoint and range") } } - private[chisel3] 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 } } sealed trait Reset extends Element with ToBoolable { + /** Casts this $coll to an [[AsyncReset]] */ final def asAsyncReset: AsyncReset = macro SourceInfoWhiteboxTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def asAsyncReset(dummy: Int*): AsyncReset = macro SourceInfoTransform.noArgDummy /** @group SourceInfoTransformMacro */ @@ -1049,10 +1162,16 @@ final class ResetType(private[chisel3] val width: Width = Width(1)) extends Elem /** Not really supported */ def toPrintable: Printable = PString("Reset") - override def do_asUInt(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): UInt = pushOp(DefPrim(sourceInfo, UInt(this.width), AsUIntOp, ref)) + override def do_asUInt(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): UInt = pushOp( + DefPrim(sourceInfo, UInt(this.width), AsUIntOp, ref) + ) - private[chisel3] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, - compileOptions: CompileOptions): Unit = { + private[chisel3] override def connectFromBits( + that: Bits + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Unit = { this := that } @@ -1091,11 +1210,17 @@ sealed class AsyncReset(private[chisel3] val width: Width = Width(1)) extends El /** Not really supported */ def toPrintable: Printable = PString("AsyncReset") - override def do_asUInt(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): UInt = pushOp(DefPrim(sourceInfo, UInt(this.width), AsUIntOp, ref)) + override def do_asUInt(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): UInt = pushOp( + DefPrim(sourceInfo, UInt(this.width), AsUIntOp, ref) + ) // TODO Is this right? - private[chisel3] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, - compileOptions: CompileOptions): Unit = { + private[chisel3] override def connectFromBits( + that: Bits + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Unit = { this := that.asBool.asAsyncReset } @@ -1121,7 +1246,7 @@ sealed class Bool() extends UInt(1.W) with Reset { override def toString: String = { litToBooleanOption match { case Some(value) => s"Bool($value)" - case _ => stringAccessor("Bool") + case _ => stringAccessor("Bool") } } @@ -1134,7 +1259,7 @@ sealed class Bool() extends UInt(1.W) with Reset { def litToBooleanOption: Option[Boolean] = litOption.map { case intVal if intVal == 1 => true case intVal if intVal == 0 => false - case intVal => throwException(s"Boolean with unexpected literal value $intVal") + case intVal => throwException(s"Boolean with unexpected literal value $intVal") } /** Convert to a [[scala.Boolean]] */ @@ -1149,7 +1274,7 @@ sealed class Bool() extends UInt(1.W) with Reset { * @return the bitwise and of this $coll and `that` * @group Bitwise */ - final def & (that: Bool): Bool = macro SourceInfoTransform.thatArg + final def &(that: Bool): Bool = macro SourceInfoTransform.thatArg /** Bitwise or operator * @@ -1157,7 +1282,7 @@ sealed class Bool() extends UInt(1.W) with Reset { * @return the bitwise or of this $coll and `that` * @group Bitwise */ - final def | (that: Bool): Bool = macro SourceInfoTransform.thatArg + final def |(that: Bool): Bool = macro SourceInfoTransform.thatArg /** Bitwise exclusive or (xor) operator * @@ -1165,20 +1290,22 @@ sealed class Bool() extends UInt(1.W) with Reset { * @return the bitwise xor of this $coll and `that` * @group Bitwise */ - final def ^ (that: Bool): Bool = macro SourceInfoTransform.thatArg + final def ^(that: Bool): Bool = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_& (that: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + def do_&(that: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = binop(sourceInfo, Bool(), BitAndOp, that) + /** @group SourceInfoTransformMacro */ - def do_| (that: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + def do_|(that: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = binop(sourceInfo, Bool(), BitOrOp, that) + /** @group SourceInfoTransformMacro */ - def do_^ (that: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + def do_^(that: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = binop(sourceInfo, Bool(), BitXorOp, that) /** @group SourceInfoTransformMacro */ - override def do_unary_~ (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + override def do_unary_~(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = unop(sourceInfo, Bool(), BitNotOp) /** Logical or operator @@ -1188,10 +1315,10 @@ sealed class Bool() extends UInt(1.W) with Reset { * @note this is equivalent to [[Bool!.|(that:chisel3\.Bool)* Bool.|)]] * @group Logical */ - def || (that: Bool): Bool = macro SourceInfoTransform.thatArg + def ||(that: Bool): Bool = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_|| (that: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = this | that + def do_||(that: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = this | that /** Logical and operator * @@ -1200,19 +1327,24 @@ sealed class Bool() extends UInt(1.W) with Reset { * @note this is equivalent to [[Bool!.&(that:chisel3\.Bool)* Bool.&]] * @group Logical */ - def && (that: Bool): Bool = macro SourceInfoTransform.thatArg + def &&(that: Bool): Bool = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_&& (that: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = this & that + def do_&&(that: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = this & that /** Reinterprets this $coll as a clock */ def asClock: Clock = macro SourceInfoTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) def asClock(dummy: Int*): Clock = macro SourceInfoTransform.noArgDummy /** @group SourceInfoTransformMacro */ - def do_asClock(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Clock = pushOp(DefPrim(sourceInfo, Clock(), AsClockOp, ref)) + def do_asClock(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Clock = pushOp( + DefPrim(sourceInfo, Clock(), AsClockOp, ref) + ) /** @group SourceInfoTransformMacro */ def do_asAsyncReset(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): AsyncReset = @@ -1261,6 +1393,7 @@ package experimental { */ def litToBigDecimal: BigDecimal = litToBigDecimalOption.get } + /** 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. * @@ -1275,28 +1408,32 @@ package experimental { * @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] with HasBinaryPoint { + sealed class FixedPoint private (width: Width, val binaryPoint: BinaryPoint) + extends Bits(width) + with Num[FixedPoint] + with HasBinaryPoint { override def toString: String = { litToDoubleOption match { case Some(value) => s"FixedPoint$width$binaryPoint($value)" - case _ => stringAccessor(s"FixedPoint$width$binaryPoint") + case _ => stringAccessor(s"FixedPoint$width$binaryPoint") } } 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 that: FixedPoint => + this.width == that.width && this.binaryPoint == that.binaryPoint // TODO: should this be true for unspecified widths? case _ => false } private[chisel3] 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 - } + override def connect(that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): Unit = + that match { + case _: FixedPoint | DontCare => super.connect(that) + case _ => this.badConnect(that) + } /** Unary negation (expanding width) * @@ -1306,7 +1443,10 @@ package experimental { */ final def unary_- : FixedPoint = macro SourceInfoTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def unary_-(dummy: Int*): FixedPoint = macro SourceInfoTransform.noArgDummy /** Unary negation (constant width) @@ -1316,28 +1456,34 @@ package experimental { * @group Arithmetic */ final def unary_-% : FixedPoint = macro SourceInfoTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def unary_-%(dummy: Int*): FixedPoint = macro SourceInfoTransform.noArgDummy /** @group SourceInfoTransformMacro */ - def do_unary_- (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = FixedPoint.fromBigInt(0) - this + def do_unary_-(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + FixedPoint.fromBigInt(0) - this + /** @group SourceInfoTransformMacro */ - def do_unary_-% (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = FixedPoint.fromBigInt(0) -% this + def do_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 = + 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 = + override def do_-(that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = this -% that - override def do_* (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + 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 = + 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 = + 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]] @@ -1346,9 +1492,10 @@ package experimental { * $singleCycleMul * @group Arithmetic */ - final def * (that: UInt): FixedPoint = macro SourceInfoTransform.thatArg + final def *(that: UInt): FixedPoint = macro SourceInfoTransform.thatArg + /** @group SourceInfoTransformMacro */ - def do_* (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + def do_*(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = binop(sourceInfo, FixedPoint(this.width + that.width, binaryPoint), TimesOp, that) /** Multiplication operator @@ -1359,9 +1506,10 @@ package experimental { * $singleCycleMul * @group Arithmetic */ - final def * (that: SInt): FixedPoint = macro SourceInfoTransform.thatArg + final def *(that: SInt): FixedPoint = macro SourceInfoTransform.thatArg + /** @group SourceInfoTransformMacro */ - def do_* (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + def do_*(that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = binop(sourceInfo, FixedPoint(this.width + that.width, binaryPoint), TimesOp, that) /** Addition operator (expanding width) @@ -1371,7 +1519,7 @@ package experimental { * $maxWidthPlusOne * @group Arithmetic */ - final def +& (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + final def +&(that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg /** Addition operator (constant width) * @@ -1380,7 +1528,7 @@ package experimental { * $maxWidth * @group Arithmetic */ - final def +% (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + final def +%(that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg /** Subtraction operator (increasing width) * @@ -1389,7 +1537,7 @@ package experimental { * $maxWidthPlusOne * @group Arithmetic */ - final def -& (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + final def -&(that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg /** Subtraction operator (constant width) * @@ -1398,44 +1546,45 @@ package experimental { * $maxWidth * @group Arithmetic */ - final def -% (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + final def -%(that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_+& (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = { + 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 + 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 + 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) + 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 = { + 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 + 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 + 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) + def do_-%(that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + (this -& that).tail(1).asFixedPoint(this.binaryPoint.max(that.binaryPoint)) /** Bitwise and operator * @@ -1444,7 +1593,7 @@ package experimental { * $maxWidth * @group Bitwise */ - final def & (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + final def &(that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg /** Bitwise or operator * @@ -1453,7 +1602,7 @@ package experimental { * $maxWidth * @group Bitwise */ - final def | (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + final def |(that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg /** Bitwise exclusive or (xor) operator * @@ -1462,38 +1611,45 @@ package experimental { * $maxWidth * @group Bitwise */ - final def ^ (that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg + final def ^(that: FixedPoint): FixedPoint = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_& (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + 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 = + 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 = + 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 _ => - binop(sourceInfo, FixedPoint(UnknownWidth(), KnownBinaryPoint(that)), SetBinaryPoint, that) - } + 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) + } /** @group SourceInfoTransformMacro */ - def do_unary_~ (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + def do_unary_~(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = throwException(s"Not is illegal on $this") - 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) + 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 + final def !=(that: FixedPoint): Bool = macro SourceInfoTransform.thatArg /** Dynamic not equals operator * @@ -1501,7 +1657,7 @@ package experimental { * @return a hardware [[Bool]] asserted if this $coll is not equal to `that` * @group Comparison */ - final def =/= (that: FixedPoint): Bool = macro SourceInfoTransform.thatArg + final def =/=(that: FixedPoint): Bool = macro SourceInfoTransform.thatArg /** Dynamic equals operator * @@ -1509,14 +1665,19 @@ package experimental { * @return a hardware [[Bool]] asserted if this $coll is equal to `that` * @group Comparison */ - final def === (that: FixedPoint): Bool = macro SourceInfoTransform.thatArg + final def ===(that: FixedPoint): Bool = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_!= (that: FixedPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, NotEqualOp, that) + 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) + 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_===(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. @@ -1524,59 +1685,88 @@ package experimental { Mux(this < 0.F(0.BP), 0.F(0.BP) - this, this) } - override def do_<< (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = + 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 = + 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 = + 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 = + 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 = + 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 = { + 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") + throwException( + s"cannot call $this.asFixedPoint(binaryPoint=$binaryPoint), you must specify a known binaryPoint" + ) } } - def do_asInterval(binaryPoint: BinaryPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = { - throwException(s"cannot call $this.asInterval(binaryPoint=$binaryPoint), you must specify a range") - } - - override def do_asInterval(range: IntervalRange = IntervalRange.Unknown) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = { - (range.lower, range.upper, range.binaryPoint) match { - case (lx: firrtlconstraint.IsKnown, ux: firrtlconstraint.IsKnown, KnownBinaryPoint(bp)) => - // No mechanism to pass open/close to firrtl so need to handle directly - val l = lx match { - case firrtlir.Open(x) => x + BigDecimal(1) / BigDecimal(BigInt(1) << bp) - case firrtlir.Closed(x) => x - } - val u = ux match { - case firrtlir.Open(x) => x - BigDecimal(1) / BigDecimal(BigInt(1) << bp) - case firrtlir.Closed(x) => x - } - val minBI = (l * BigDecimal(BigInt(1) << bp)).setScale(0, BigDecimal.RoundingMode.FLOOR).toBigIntExact.get - val maxBI = (u * BigDecimal(BigInt(1) << bp)).setScale(0, BigDecimal.RoundingMode.FLOOR).toBigIntExact.get - pushOp(DefPrim(sourceInfo, Interval(range), AsIntervalOp, ref, ILit(minBI), ILit(maxBI), ILit(bp))) - case _ => - throwException( - s"cannot call $this.asInterval($range), you must specify a known binaryPoint and range") + def do_asInterval( + binaryPoint: BinaryPoint + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Interval = { + throwException(s"cannot call $this.asInterval(binaryPoint=$binaryPoint), you must specify a range") + } + + override def do_asInterval( + range: IntervalRange = IntervalRange.Unknown + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Interval = { + (range.lower, range.upper, range.binaryPoint) match { + case (lx: firrtlconstraint.IsKnown, ux: firrtlconstraint.IsKnown, KnownBinaryPoint(bp)) => + // No mechanism to pass open/close to firrtl so need to handle directly + val l = lx match { + case firrtlir.Open(x) => x + BigDecimal(1) / BigDecimal(BigInt(1) << bp) + case firrtlir.Closed(x) => x + } + val u = ux match { + case firrtlir.Open(x) => x - BigDecimal(1) / BigDecimal(BigInt(1) << bp) + case firrtlir.Closed(x) => x + } + val minBI = (l * BigDecimal(BigInt(1) << bp)).setScale(0, BigDecimal.RoundingMode.FLOOR).toBigIntExact.get + val maxBI = (u * BigDecimal(BigInt(1) << bp)).setScale(0, BigDecimal.RoundingMode.FLOOR).toBigIntExact.get + pushOp(DefPrim(sourceInfo, Interval(range), AsIntervalOp, ref, ILit(minBI), ILit(maxBI), ILit(bp))) + case _ => + throwException(s"cannot call $this.asInterval($range), you must specify a known binaryPoint and range") + } } - } - private[chisel3] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) { + 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) @@ -1610,36 +1800,43 @@ package experimental { 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) { + if (width == -1) { apply(value, Width(), BinaryPoint(binaryPoint)) - } - else { + } 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 */ def fromDouble(value: Double, width: Width, binaryPoint: BinaryPoint): FixedPoint = { fromBigInt( - toBigInt(value, binaryPoint.get), width = width, binaryPoint = binaryPoint + toBigInt(value, binaryPoint.get), + width = width, + binaryPoint = binaryPoint ) } + /** Create an FixedPoint literal with inferred width from BigDecimal. * Use PrivateObject to force users to specify width and binaryPoint by name */ def fromBigDecimal(value: BigDecimal, width: Width, binaryPoint: BinaryPoint): FixedPoint = { fromBigInt( - toBigInt(value, binaryPoint.get), width = width, binaryPoint = binaryPoint + toBigInt(value, binaryPoint.get), + width = width, + binaryPoint = binaryPoint ) } @@ -1651,8 +1848,6 @@ package experimental { lit.bindLitArg(newLiteral) } - - object Implicits { implicit class fromDoubleToLiteral(double: Double) { @@ -1695,12 +1890,14 @@ package experimental { * @param range a range specifies min, max and binary point */ sealed class Interval private[chisel3] (val range: chisel3.internal.firrtl.IntervalRange) - extends Bits(range.getWidth) with Num[Interval] with HasBinaryPoint { + extends Bits(range.getWidth) + with Num[Interval] + with HasBinaryPoint { override def toString: String = { litOption match { case Some(value) => s"Interval$width($value)" - case _ => stringAccessor(s"Interval$width") + case _ => stringAccessor(s"Interval$width") } } @@ -1714,27 +1911,27 @@ package experimental { val int = """([+\-]?[0-9]\d*)""".r def dec2string(v: BigDecimal): String = v.toString match { case zdec1(x, y, z) => x + y - case zdec2(x, y) => x - case other => other + case zdec2(x, y) => x + case other => other } val lowerString = range.lower match { case firrtlir.Open(l) => s"(${dec2string(l)}, " case firrtlir.Closed(l) => s"[${dec2string(l)}, " case firrtlir.UnknownBound => s"[?, " - case _ => s"[?, " + case _ => s"[?, " } val upperString = range.upper match { case firrtlir.Open(u) => s"${dec2string(u)})" case firrtlir.Closed(u) => s"${dec2string(u)}]" case firrtlir.UnknownBound => s"?]" - case _ => s"?]" + case _ => s"?]" } val bounds = lowerString + upperString val pointString = range.binaryPoint match { - case KnownBinaryPoint(i) => "." + i.toString - case _ => "" + case KnownBinaryPoint(i) => "." + i.toString + case _ => "" } "Interval" + bounds + pointString } @@ -1746,19 +1943,25 @@ package experimental { override def connect(that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): Unit = { that match { - case _: Interval|DontCare => super.connect(that) - case _ => this badConnect that + case _: Interval | DontCare => super.connect(that) + case _ => this.badConnect(that) } } final def unary_- : Interval = macro SourceInfoTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def unary_-(dummy: Int*): Interval = macro SourceInfoTransform.noArgDummy final def unary_-% : Interval = macro SourceInfoTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def unary_-%(dummy: Int*): Interval = macro SourceInfoTransform.noArgDummy /** @group SourceInfoTransformMacro */ @@ -1772,6 +1975,7 @@ package experimental { /** add (default - growing) operator */ override def do_+(that: Interval)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = this +& that + /** subtract (default - growing) operator */ override def do_-(that: Interval)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = this -& that @@ -1785,10 +1989,13 @@ package experimental { /** add (width +1) operator */ final def +&(that: Interval): Interval = macro SourceInfoTransform.thatArg + /** add (no growth) operator */ final def +%(that: Interval): Interval = macro SourceInfoTransform.thatArg + /** subtract (width +1) operator */ final def -&(that: Interval): Interval = macro SourceInfoTransform.thatArg + /** subtract (no growth) operator */ final def -%(that: Interval): Interval = macro SourceInfoTransform.thatArg @@ -1859,21 +2066,28 @@ package experimental { } /** Returns this wire bitwise-inverted. */ - def do_unary_~ (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = + def do_unary_~(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = throwException(s"Not is illegal on $this") - override def do_< (that: Interval)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, LessOp, that) - override def do_> (that: Interval)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, GreaterOp, that) - override def do_<= (that: Interval)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, LessEqOp, that) - override def do_>= (that: Interval)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, GreaterEqOp, that) - - final def != (that: Interval): Bool = macro SourceInfoTransform.thatArg - final def =/= (that: Interval): Bool = macro SourceInfoTransform.thatArg - final def === (that: Interval): Bool = macro SourceInfoTransform.thatArg - - def do_!= (that: Interval)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, NotEqualOp, that) - def do_=/= (that: Interval)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, NotEqualOp, that) - def do_=== (that: Interval)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, EqualOp, that) + override def do_<(that: Interval)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + compop(sourceInfo, LessOp, that) + override def do_>(that: Interval)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + compop(sourceInfo, GreaterOp, that) + override def do_<=(that: Interval)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + compop(sourceInfo, LessEqOp, that) + override def do_>=(that: Interval)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + compop(sourceInfo, GreaterEqOp, that) + + final def !=(that: Interval): Bool = macro SourceInfoTransform.thatArg + final def =/=(that: Interval): Bool = macro SourceInfoTransform.thatArg + final def ===(that: Interval): Bool = macro SourceInfoTransform.thatArg + + def do_!=(that: Interval)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + compop(sourceInfo, NotEqualOp, that) + def do_=/=(that: Interval)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + compop(sourceInfo, NotEqualOp, that) + def do_===(that: Interval)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + compop(sourceInfo, EqualOp, that) // final def abs(): UInt = macro SourceInfoTransform.noArgDummy @@ -1881,24 +2095,24 @@ package experimental { Mux(this < Interval.Zero, (Interval.Zero - this), this) } - override def do_<< (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = + override def do_<<(that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = binop(sourceInfo, Interval(this.range << that), ShiftLeftOp, that) - override def do_<< (that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = + override def do_<<(that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = do_<<(that.toInt) - override def do_<< (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = { + override def do_<<(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = { binop(sourceInfo, Interval(this.range << that), DynamicShiftLeftOp, that) } - override def do_>> (that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = { + override def do_>>(that: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = { binop(sourceInfo, Interval(this.range >> that), ShiftRightOp, that) } - override def do_>> (that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = + override def do_>>(that: BigInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = do_>>(that.toInt) - override def do_>> (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = { + override def do_>>(that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = { binop(sourceInfo, Interval(this.range >> that), DynamicShiftRightOp, that) } @@ -1965,13 +2179,12 @@ package experimental { final def squeeze(that: IntervalRange): Interval = macro SourceInfoTransform.thatArg def do_squeeze(that: IntervalRange)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Interval = { val intervalLitOpt = Interval.getSmallestLegalLit(that) - val intervalLit = intervalLitOpt.getOrElse( + val intervalLit = intervalLitOpt.getOrElse( throwException(s"$this.squeeze($that) requires an Interval range with known lower and upper bounds") ) do_squeeze(intervalLit) } - /** * Wrap the value of this [[Interval]] into the range of a different Interval with a presumably smaller range. * Ignores binary point of argument @@ -2104,14 +2317,20 @@ package experimental { pushOp(DefPrim(sourceInfo, SInt(this.width), AsSIntOp, ref)) } - override def do_asFixedPoint(binaryPoint: BinaryPoint)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): FixedPoint = { + 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") + s"cannot call $this.asFixedPoint(binaryPoint=$binaryPoint), you must specify a known binaryPoint" + ) } } @@ -2132,8 +2351,12 @@ package experimental { throwException("fromBits INVALID for intervals") } - private[chisel3] override def connectFromBits(that: Bits) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) { + private[chisel3] override def connectFromBits( + that: Bits + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ) { this := that.asInterval(this.range) } } @@ -2146,6 +2369,7 @@ package experimental { * IMPORTANT: The API provided here is experimental and may change in the future. */ object Interval extends NumObject { + /** Create an Interval type with inferred width and binary point. */ def apply(): Interval = Interval(range"[?,?]") @@ -2153,7 +2377,7 @@ package experimental { def apply(binaryPoint: BinaryPoint): Interval = { val binaryPointString = binaryPoint match { case KnownBinaryPoint(value) => s"$value" - case _ => s"" + case _ => s"" } Interval(range"[?,?].$binaryPointString") } @@ -2201,27 +2425,39 @@ package experimental { /** Create an Interval literal with inferred width from Double. * Use PrivateObject to force users to specify width and binaryPoint by name */ - def fromDouble(value: Double, dummy: PrivateType = PrivateObject, - width: Width, binaryPoint: BinaryPoint): Interval = { + def fromDouble( + value: Double, + dummy: PrivateType = PrivateObject, + width: Width, + binaryPoint: BinaryPoint + ): Interval = { fromBigInt( - toBigInt(value, binaryPoint), width = width, binaryPoint = binaryPoint + toBigInt(value, binaryPoint), + width = width, + binaryPoint = binaryPoint ) } /** Create an Interval literal with inferred width from Double. * Use PrivateObject to force users to specify width and binaryPoint by name */ - def fromBigDecimal(value: Double, dummy: PrivateType = PrivateObject, - width: Width, binaryPoint: BinaryPoint): Interval = { + def fromBigDecimal( + value: Double, + dummy: PrivateType = PrivateObject, + width: Width, + binaryPoint: BinaryPoint + ): Interval = { fromBigInt( - toBigInt(value, binaryPoint), width = width, binaryPoint = binaryPoint + toBigInt(value, binaryPoint), + width = width, + binaryPoint = binaryPoint ) } protected[chisel3] def Lit(value: BigInt, width: Width, binaryPoint: BinaryPoint): Interval = { width match { case KnownWidth(w) => - if(value >= 0 && value.bitLength >= w || value < 0 && value.bitLength > w) { + if (value >= 0 && value.bitLength >= w || value < 0 && value.bitLength > w) { throw new ChiselException( s"Error literal interval value $value is too many bits for specified width $w" ) @@ -2243,7 +2479,7 @@ package experimental { case (firrtlir.Open(l), firrtlir.Closed(u)) => l < bigDecimal && bigDecimal <= u case (firrtlir.Open(l), firrtlir.Open(u)) => l < bigDecimal && bigDecimal < u } - if(! inRange) { + if (!inRange) { throw new ChiselException( s"Error literal interval value $bigDecimal is not contained in specified range $range" ) @@ -2338,9 +2574,7 @@ package experimental { } implicit class fromDoubleToLiteralInterval(double: Double) - extends fromBigDecimalToLiteralInterval(BigDecimal(double)) + extends fromBigDecimalToLiteralInterval(BigDecimal(double)) } } } - - diff --git a/core/src/main/scala/chisel3/BlackBox.scala b/core/src/main/scala/chisel3/BlackBox.scala index ec5de0cd..89c4ccd3 100644 --- a/core/src/main/scala/chisel3/BlackBox.scala +++ b/core/src/main/scala/chisel3/BlackBox.scala @@ -23,6 +23,7 @@ package experimental { 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 @@ -85,7 +86,7 @@ package experimental { closeUnboundIds(names) - val firrtlPorts = getModulePorts map {port => Port(port, port.specifiedDirection)} + val firrtlPorts = getModulePorts.map { port => Port(port, port.specifiedDirection) } val component = DefBlackBox(this, name, firrtlPorts, SpecifiedDirection.Unspecified, params) _component = Some(component) _component @@ -137,19 +138,24 @@ package experimental { * @note The parameters API is experimental and may change */ @nowarn("msg=class Port") // delete when Port becomes private -abstract class BlackBox(val params: Map[String, Param] = Map.empty[String, Param])(implicit compileOptions: CompileOptions) extends BaseBlackBox { +abstract class BlackBox( + val params: Map[String, Param] = Map.empty[String, Param] +)( + implicit compileOptions: CompileOptions) + extends BaseBlackBox { // Find a Record port named "io" for purposes of stripping the prefix private[chisel3] lazy val _io: Record = - this.findPort("io") - .collect { case r: Record => r } // Must be a Record - .getOrElse(null) // null handling occurs in generateComponent + this + .findPort("io") + .collect { case r: Record => r } // Must be a Record + .getOrElse(null) // null handling occurs in generateComponent // Allow access to bindings from the compatibility package protected def _compatIoPortBound() = portsContains(_io) private[chisel3] override def generateComponent(): Option[Component] = { - _compatAutoWrapPorts() // pre-IO(...) compatibility hack + _compatAutoWrapPorts() // pre-IO(...) compatibility hack // Restrict IO to just io, clock, and reset require(_io != null, "BlackBox must have a port named 'io' of type Record!") @@ -159,7 +165,7 @@ abstract class BlackBox(val params: Map[String, Param] = Map.empty[String, Param require(!_closed, "Can't generate module more than once") _closed = true - val namedPorts = _io.elements.toSeq.reverse // ListMaps are stored in reverse order + val namedPorts = _io.elements.toSeq.reverse // ListMaps are stored in reverse order // There is a risk of user improperly attempting to connect directly with io // Long term solution will be to define BlackBox IO differently as part of @@ -179,7 +185,7 @@ abstract class BlackBox(val params: Map[String, Param] = Map.empty[String, Param id._onModuleClose } - val firrtlPorts = namedPorts map {namedPort => Port(namedPort._2, namedPort._2.specifiedDirection)} + val firrtlPorts = namedPorts.map { namedPort => Port(namedPort._2, namedPort._2.specifiedDirection) } val component = DefBlackBox(this, name, firrtlPorts, _io.specifiedDirection, params) _component = Some(component) _component diff --git a/core/src/main/scala/chisel3/BoolFactory.scala b/core/src/main/scala/chisel3/BoolFactory.scala index 787f1e5e..1d96659f 100644 --- a/core/src/main/scala/chisel3/BoolFactory.scala +++ b/core/src/main/scala/chisel3/BoolFactory.scala @@ -4,14 +4,14 @@ package chisel3 import chisel3.internal.firrtl.{ULit, Width} - trait BoolFactory { + /** Creates an empty Bool. - */ + */ def apply(): Bool = new Bool() /** Creates Bool literal. - */ + */ protected[chisel3] def Lit(x: Boolean): Bool = { val result = new Bool() val lit = ULit(if (x) 1 else 0, Width(1)) diff --git a/core/src/main/scala/chisel3/Clock.scala b/core/src/main/scala/chisel3/Clock.scala index e4be6558..68174d7c 100644 --- a/core/src/main/scala/chisel3/Clock.scala +++ b/core/src/main/scala/chisel3/Clock.scala @@ -21,10 +21,11 @@ sealed class Clock(private[chisel3] val width: Width = Width(1)) extends Element private[chisel3] def typeEquivalent(that: Data): Boolean = this.getClass == that.getClass - override def connect(that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): Unit = that match { - case _: Clock => super.connect(that)(sourceInfo, connectCompileOptions) - case _ => super.badConnect(that)(sourceInfo) - } + override def connect(that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): Unit = + that match { + case _: Clock => super.connect(that)(sourceInfo, connectCompileOptions) + case _ => super.badConnect(that)(sourceInfo) + } override def litOption: Option[BigInt] = None @@ -34,14 +35,23 @@ sealed class Clock(private[chisel3] val width: Width = Width(1)) extends Element /** Returns the contents of the clock wire as a [[Bool]]. */ final def asBool: Bool = macro SourceInfoTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def asBool(dummy: Int*): Bool = macro SourceInfoTransform.noArgDummy def do_asBool(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = this.asUInt.asBool - override def do_asUInt(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): UInt = pushOp(DefPrim(sourceInfo, UInt(this.width), AsUIntOp, ref)) - private[chisel3] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, - compileOptions: CompileOptions): Unit = { + override def do_asUInt(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): UInt = pushOp( + DefPrim(sourceInfo, UInt(this.width), AsUIntOp, ref) + ) + private[chisel3] override def connectFromBits( + that: Bits + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Unit = { this := that.asBool.asClock } } diff --git a/core/src/main/scala/chisel3/CompileOptions.scala b/core/src/main/scala/chisel3/CompileOptions.scala index 3dcc25a8..db773d6e 100644 --- a/core/src/main/scala/chisel3/CompileOptions.scala +++ b/core/src/main/scala/chisel3/CompileOptions.scala @@ -36,7 +36,7 @@ object CompileOptions { } object ExplicitCompileOptions { - case class CompileOptionsClass ( + case class CompileOptionsClass( // Should Record connections require a strict match of fields. // If true and the same fields aren't present in both source and sink, a MissingFieldException, // MissingLeftFieldException, or MissingRightFieldException will be thrown. @@ -52,12 +52,12 @@ object ExplicitCompileOptions { // Require an explicit DontCare assignment to generate a firrtl DefInvalid val explicitInvalidate: Boolean, // Should the reset type of Module be a Bool or a Reset - val inferModuleReset: Boolean - ) extends CompileOptions + val inferModuleReset: Boolean) + extends CompileOptions // Collection of "not strict" connection compile options. // These provide compatibility with existing code. - implicit val NotStrict = new CompileOptionsClass ( + implicit val NotStrict = new CompileOptionsClass( connectFieldsMustMatch = false, declaredTypeMustBeUnbound = false, dontTryConnectionsSwapped = false, @@ -68,13 +68,13 @@ object ExplicitCompileOptions { ) // Collection of "strict" connection compile options, preferred for new code. - implicit val Strict = new CompileOptionsClass ( + implicit val Strict = new CompileOptionsClass( connectFieldsMustMatch = true, declaredTypeMustBeUnbound = true, dontTryConnectionsSwapped = true, dontAssumeDirectionality = true, checkSynthesizable = true, explicitInvalidate = true, - inferModuleReset = true + inferModuleReset = true ) } diff --git a/core/src/main/scala/chisel3/Data.scala b/core/src/main/scala/chisel3/Data.scala index 2bca5f98..9e9f5dbb 100644 --- a/core/src/main/scala/chisel3/Data.scala +++ b/core/src/main/scala/chisel3/Data.scala @@ -18,24 +18,28 @@ import scala.util.Try */ sealed abstract class SpecifiedDirection object SpecifiedDirection { + /** Default user direction, also meaning 'not-flipped' */ case object Unspecified extends SpecifiedDirection + /** Node and its children are forced as output */ case object Output extends SpecifiedDirection + /** Node and its children are forced as inputs */ case object Input extends SpecifiedDirection + /** Mainly for containers, children are flipped. */ case object Flip extends SpecifiedDirection def flip(dir: SpecifiedDirection): SpecifiedDirection = dir match { case Unspecified => Flip - case Flip => Unspecified - case Output => Input - case Input => Output + case Flip => Unspecified + case Output => Input + case Input => Output } /** Returns the effective SpecifiedDirection of this node given the parent's effective SpecifiedDirection @@ -43,13 +47,18 @@ object SpecifiedDirection { */ def fromParent(parentDirection: SpecifiedDirection, thisDirection: SpecifiedDirection): SpecifiedDirection = (parentDirection, thisDirection) match { - case (SpecifiedDirection.Output, _) => SpecifiedDirection.Output - case (SpecifiedDirection.Input, _) => SpecifiedDirection.Input + case (SpecifiedDirection.Output, _) => SpecifiedDirection.Output + case (SpecifiedDirection.Input, _) => SpecifiedDirection.Input case (SpecifiedDirection.Unspecified, thisDirection) => thisDirection - case (SpecifiedDirection.Flip, thisDirection) => SpecifiedDirection.flip(thisDirection) + case (SpecifiedDirection.Flip, thisDirection) => SpecifiedDirection.flip(thisDirection) } - private[chisel3] def specifiedDirection[T<:Data](source: T)(dir: SpecifiedDirection)(implicit compileOptions: CompileOptions): T = { + private[chisel3] def specifiedDirection[T <: Data]( + source: T + )(dir: SpecifiedDirection + )( + implicit compileOptions: CompileOptions + ): T = { if (compileOptions.checkSynthesizable) { requireIsChiselType(source) } @@ -67,6 +76,7 @@ object SpecifiedDirection { sealed abstract class ActualDirection object ActualDirection { + /** The object does not exist / is empty and hence has no direction */ case object Empty extends ActualDirection @@ -74,9 +84,11 @@ object ActualDirection { /** Undirectioned, struct-like */ case object Unspecified extends ActualDirection + /** Output element, or container with all outputs (even if forced) */ case object Output extends ActualDirection + /** Input element, or container with all inputs (even if forced) */ case object Input extends ActualDirection @@ -89,19 +101,21 @@ object ActualDirection { def fromSpecified(direction: SpecifiedDirection): ActualDirection = direction match { case SpecifiedDirection.Unspecified | SpecifiedDirection.Flip => ActualDirection.Unspecified - case SpecifiedDirection.Output => ActualDirection.Output - case SpecifiedDirection.Input => ActualDirection.Input + case SpecifiedDirection.Output => ActualDirection.Output + case SpecifiedDirection.Input => ActualDirection.Input } /** Determine the actual binding of a container given directions of its children. * Returns None in the case of mixed specified / unspecified directionality. */ - def fromChildren(childDirections: Set[ActualDirection], containerDirection: SpecifiedDirection): - Option[ActualDirection] = { - if (childDirections == Set()) { // Sadly, Scala can't do set matching + def fromChildren( + childDirections: Set[ActualDirection], + containerDirection: SpecifiedDirection + ): Option[ActualDirection] = { + if (childDirections == Set()) { // Sadly, Scala can't do set matching ActualDirection.fromSpecified(containerDirection) match { - case ActualDirection.Unspecified => Some(ActualDirection.Empty) // empty direction if relative / no direction - case dir => Some(dir) // use assigned direction if specified + case ActualDirection.Unspecified => Some(ActualDirection.Empty) // empty direction if relative / no direction + case dir => Some(dir) // use assigned direction if specified } } else if (childDirections == Set(ActualDirection.Unspecified)) { Some(ActualDirection.Unspecified) @@ -109,14 +123,20 @@ object ActualDirection { Some(ActualDirection.Input) } else if (childDirections == Set(ActualDirection.Output)) { Some(ActualDirection.Output) - } else if (childDirections subsetOf - Set(ActualDirection.Output, ActualDirection.Input, - ActualDirection.Bidirectional(ActualDirection.Default), - ActualDirection.Bidirectional(ActualDirection.Flipped))) { + } else if ( + childDirections.subsetOf( + Set( + ActualDirection.Output, + ActualDirection.Input, + ActualDirection.Bidirectional(ActualDirection.Default), + ActualDirection.Bidirectional(ActualDirection.Flipped) + ) + ) + ) { containerDirection match { case SpecifiedDirection.Unspecified => Some(ActualDirection.Bidirectional(ActualDirection.Default)) - case SpecifiedDirection.Flip => Some(ActualDirection.Bidirectional(ActualDirection.Flipped)) - case _ => throw new RuntimeException("Unexpected forced Input / Output") + case SpecifiedDirection.Flip => Some(ActualDirection.Bidirectional(ActualDirection.Flipped)) + case _ => throw new RuntimeException("Unexpected forced Input / Output") } } else { None @@ -130,7 +150,7 @@ package experimental { /** Experimental hardware construction reflection API */ object DataMirror { - def widthOf(target: Data): Width = target.width + 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") @@ -151,7 +171,7 @@ package experimental { * @param x First Chisel type * @param y Second Chisel type * @return true if the two Chisel types are equal. - **/ + */ def checkTypeEquivalence(x: Data, y: Data): Boolean = x.typeEquivalent(y) /** Returns the ports of a module @@ -210,11 +230,12 @@ package experimental { 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) } + 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 + modulePorts(target).flatMap { + case (name, data) => + getPortNames(name, data).toList } } @@ -222,7 +243,7 @@ package experimental { object internal { 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 = { + def chiselTypeClone[T <: Data](target: Data): T = { target.cloneTypeFull.asInstanceOf[T] } } @@ -236,48 +257,59 @@ package experimental { * - Otherwise: fail */ private[chisel3] object cloneSupertype { - def apply[T <: Data](elts: Seq[T], createdType: String)(implicit sourceInfo: SourceInfo, - compileOptions: CompileOptions): T = { + 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") val filteredElts = elts.filter(_ != DontCare) require(!filteredElts.isEmpty, s"can't create $createdType with only DontCare inputs") if (filteredElts.head.isInstanceOf[Bits]) { - val model: T = filteredElts reduce { (elt1: T, elt2: T) => ((elt1, elt2) match { - case (elt1: Bool, elt2: Bool) => elt1 - case (elt1: Bool, elt2: UInt) => elt2 // TODO: what happens with zero width UInts? - case (elt1: UInt, elt2: Bool) => elt1 // TODO: what happens with zero width UInts? - case (elt1: UInt, elt2: UInt) => - // TODO: perhaps redefine Widths to allow >= op? - if (elt1.width == (elt1.width max elt2.width)) elt1 else elt2 - case (elt1: SInt, elt2: SInt) => if (elt1.width == (elt1.width max elt2.width)) elt1 else elt2 - case (elt1: FixedPoint, elt2: FixedPoint) => { - (elt1.binaryPoint, elt2.binaryPoint, elt1.width, elt2.width) match { - case (KnownBinaryPoint(bp1), KnownBinaryPoint(bp2), KnownWidth(w1), KnownWidth(w2)) => - val maxBinaryPoint = bp1 max bp2 - val maxIntegerWidth = (w1 - bp1) max (w2 - bp2) - FixedPoint((maxIntegerWidth + maxBinaryPoint).W, (maxBinaryPoint).BP) - case (KnownBinaryPoint(bp1), KnownBinaryPoint(bp2), _, _) => - FixedPoint(Width(), (bp1 max bp2).BP) - case _ => FixedPoint() + val model: T = filteredElts.reduce { (elt1: T, elt2: T) => + ((elt1, elt2) match { + case (elt1: Bool, elt2: Bool) => elt1 + case (elt1: Bool, elt2: UInt) => elt2 // TODO: what happens with zero width UInts? + case (elt1: UInt, elt2: Bool) => elt1 // TODO: what happens with zero width UInts? + case (elt1: UInt, elt2: UInt) => + // TODO: perhaps redefine Widths to allow >= op? + if (elt1.width == (elt1.width.max(elt2.width))) elt1 else elt2 + case (elt1: SInt, elt2: SInt) => if (elt1.width == (elt1.width.max(elt2.width))) elt1 else elt2 + case (elt1: FixedPoint, elt2: FixedPoint) => { + (elt1.binaryPoint, elt2.binaryPoint, elt1.width, elt2.width) match { + case (KnownBinaryPoint(bp1), KnownBinaryPoint(bp2), KnownWidth(w1), KnownWidth(w2)) => + val maxBinaryPoint = bp1.max(bp2) + val maxIntegerWidth = (w1 - bp1).max(w2 - bp2) + FixedPoint((maxIntegerWidth + maxBinaryPoint).W, (maxBinaryPoint).BP) + case (KnownBinaryPoint(bp1), KnownBinaryPoint(bp2), _, _) => + FixedPoint(Width(), (bp1.max(bp2)).BP) + case _ => FixedPoint() + } } - } - case (elt1: Interval, elt2: Interval) => - val range = if(elt1.range.width == elt1.range.width.max(elt2.range.width)) elt1.range else elt2.range - Interval(range) - case (elt1, elt2) => - throw new AssertionError( - s"can't create $createdType with heterogeneous types ${elt1.getClass} and ${elt2.getClass}") - }).asInstanceOf[T] } + case (elt1: Interval, elt2: Interval) => + val range = if (elt1.range.width == elt1.range.width.max(elt2.range.width)) elt1.range else elt2.range + Interval(range) + case (elt1, elt2) => + throw new AssertionError( + s"can't create $createdType with heterogeneous types ${elt1.getClass} and ${elt2.getClass}" + ) + }).asInstanceOf[T] + } model.cloneTypeFull - } - else { + } else { for (elt <- filteredElts.tail) { - require(elt.getClass == filteredElts.head.getClass, - s"can't create $createdType with heterogeneous types ${filteredElts.head.getClass} and ${elt.getClass}") - require(elt typeEquivalent filteredElts.head, - s"can't create $createdType with non-equivalent types ${filteredElts.head} and ${elt}") + require( + elt.getClass == filteredElts.head.getClass, + s"can't create $createdType with heterogeneous types ${filteredElts.head.getClass} and ${elt.getClass}" + ) + require( + elt.typeEquivalent(filteredElts.head), + s"can't create $createdType with non-equivalent types ${filteredElts.head} and ${elt}" + ) } filteredElts.head.cloneTypeFull } @@ -288,14 +320,16 @@ private[chisel3] object cloneSupertype { private[chisel3] object getRecursiveFields { def apply(data: Data, path: String): Seq[(Data, String)] = data match { case data: Record => - data.elements.map { case (fieldName, fieldData) => - getRecursiveFields(fieldData, s"$path.$fieldName") + data.elements.map { + case (fieldName, fieldData) => + getRecursiveFields(fieldData, s"$path.$fieldName") }.fold(Seq(data -> path)) { _ ++ _ } case data: Vec[_] => - data.getElements.zipWithIndex.map { case (fieldData, fieldIndex) => - getRecursiveFields(fieldData, path = s"$path($fieldIndex)") + data.getElements.zipWithIndex.map { + case (fieldData, fieldIndex) => + getRecursiveFields(fieldData, path = s"$path($fieldIndex)") }.fold(Seq(data -> path)) { _ ++ _ } @@ -305,13 +339,15 @@ private[chisel3] object getRecursiveFields { def lazily(data: Data, path: String): Seq[(Data, String)] = data match { case data: Record => LazyList(data -> path) ++ - data.elements.view.flatMap { case (fieldName, fieldData) => - getRecursiveFields(fieldData, s"$path.$fieldName") + data.elements.view.flatMap { + case (fieldName, fieldData) => + getRecursiveFields(fieldData, s"$path.$fieldName") } case data: Vec[_] => LazyList(data -> path) ++ - data.getElements.view.zipWithIndex.flatMap { case (fieldData, fieldIndex) => - getRecursiveFields(fieldData, path = s"$path($fieldIndex)") + data.getElements.view.zipWithIndex.flatMap { + case (fieldData, fieldIndex) => + getRecursiveFields(fieldData, path = s"$path($fieldIndex)") } case data: Element => LazyList(data -> path) } @@ -322,21 +358,29 @@ private[chisel3] object getRecursiveFields { private[chisel3] object getMatchedFields { def apply(x: Data, y: Data): Seq[(Data, Data)] = (x, y) match { case (x: Element, y: Element) => - require(x typeEquivalent y) + require(x.typeEquivalent(y)) Seq(x -> y) case (x: Record, y: Record) => - (x.elements zip y.elements).map { case ((xName, xElt), (yName, yElt)) => - require(xName == yName) // assume fields returned in same, deterministic order - getMatchedFields(xElt, yElt) - }.fold(Seq(x -> y)) { - _ ++ _ - } + (x.elements + .zip(y.elements)) + .map { + case ((xName, xElt), (yName, yElt)) => + require(xName == yName) // assume fields returned in same, deterministic order + getMatchedFields(xElt, yElt) + } + .fold(Seq(x -> y)) { + _ ++ _ + } case (x: Vec[_], y: Vec[_]) => - (x.getElements zip y.getElements).map { case (xElt, yElt) => - getMatchedFields(xElt, yElt) - }.fold(Seq(x -> y)) { - _ ++ _ - } + (x.getElements + .zip(y.getElements)) + .map { + case (xElt, yElt) => + getMatchedFields(xElt, yElt) + } + .fold(Seq(x -> y)) { + _ ++ _ + } } } @@ -350,25 +394,25 @@ object chiselTypeOf { } /** -* Input, Output, and Flipped are used to define the directions of Module IOs. -* -* Note that they currently clone their source argument, including its bindings. -* -* Thus, an error will be thrown if these are used on bound Data -*/ + * Input, Output, and Flipped are used to define the directions of Module IOs. + * + * Note that they currently clone their source argument, including its bindings. + * + * Thus, an error will be thrown if these are used on bound Data + */ object Input { - def apply[T<:Data](source: T)(implicit compileOptions: CompileOptions): T = { + def apply[T <: Data](source: T)(implicit compileOptions: CompileOptions): T = { SpecifiedDirection.specifiedDirection(source)(SpecifiedDirection.Input) } } object Output { - def apply[T<:Data](source: T)(implicit compileOptions: CompileOptions): T = { + def apply[T <: Data](source: T)(implicit compileOptions: CompileOptions): T = { SpecifiedDirection.specifiedDirection(source)(SpecifiedDirection.Output) } } object Flipped { - def apply[T<:Data](source: T)(implicit compileOptions: CompileOptions): T = { + def apply[T <: Data](source: T)(implicit compileOptions: CompileOptions): T = { SpecifiedDirection.specifiedDirection(source)(SpecifiedDirection.flip(source.specifiedDirection)) } } @@ -386,8 +430,8 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { @deprecated("pending removal once all instances replaced", "chisel3") private[chisel3] def flatten: IndexedSeq[Element] = { this match { - case elt: Aggregate => elt.getElements.toIndexedSeq flatMap {_.flatten} - case elt: Element => IndexedSeq(elt) + case elt: Aggregate => elt.getElements.toIndexedSeq.flatMap { _.flatten } + case elt: Element => IndexedSeq(elt) case elt => throwException(s"Cannot flatten type ${elt.getClass}") } } @@ -396,13 +440,13 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { topBindingOpt match { // Ports are special in that the autoSeed will keep the first name, not the last name case Some(PortBinding(m)) if hasAutoSeed && Builder.currentModule.contains(m) => this - case _ => super.autoSeed(name) + case _ => super.autoSeed(name) } } // User-specified direction, local at this node only. // Note that the actual direction of this node can differ from child and parent specifiedDirection. - private var _specifiedDirection: SpecifiedDirection = SpecifiedDirection.Unspecified + private var _specifiedDirection: SpecifiedDirection = SpecifiedDirection.Unspecified private[chisel3] def specifiedDirection: SpecifiedDirection = _specifiedDirection private[chisel3] def specifiedDirection_=(direction: SpecifiedDirection) = { if (_specifiedDirection != SpecifiedDirection.Unspecified) { @@ -422,8 +466,8 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { private[chisel3] def _assignCompatibilityExplicitDirection: Unit = { (this, _specifiedDirection) match { case (_: Analog, _) => // nothing to do - case (_, SpecifiedDirection.Unspecified) => _specifiedDirection = SpecifiedDirection.Output - case (_, SpecifiedDirection.Flip) => _specifiedDirection = SpecifiedDirection.Input + case (_, SpecifiedDirection.Unspecified) => _specifiedDirection = SpecifiedDirection.Output + case (_, SpecifiedDirection.Flip) => _specifiedDirection = SpecifiedDirection.Input case (_, SpecifiedDirection.Input | SpecifiedDirection.Output) => // nothing to do } } @@ -503,16 +547,16 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { private[chisel3] def _bindingToString(topBindingOpt: TopBinding): String = topBindingOpt match { - case OpBinding(_, _) => "OpResult" - case MemoryPortBinding(_, _) => "MemPort" - case PortBinding(_) => "IO" - case RegBinding(_, _) => "Reg" - case WireBinding(_, _) => "Wire" - case DontCareBinding() => "(DontCare)" + case OpBinding(_, _) => "OpResult" + case MemoryPortBinding(_, _) => "MemPort" + case PortBinding(_) => "IO" + case RegBinding(_, _) => "Reg" + case WireBinding(_, _) => "Wire" + case DontCareBinding() => "(DontCare)" case ElementLitBinding(litArg) => "(unhandled literal)" - case BundleLitBinding(litMap) => "(unhandled bundle literal)" - case VecLitBinding(litMap) => "(unhandled vec literal)" - case _ => "" + case BundleLitBinding(litMap) => "(unhandled bundle literal)" + case VecLitBinding(litMap) => "(unhandled vec literal)" + case _ => "" } private[chisel3] def earlyName: String = Arg.earlyLocalName(this) @@ -526,13 +570,18 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { 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 = { + private[chisel3] def connect( + that: Data + )( + implicit sourceInfo: SourceInfo, + connectCompileOptions: CompileOptions + ): Unit = { if (connectCompileOptions.checkSynthesizable) { requireIsHardware(this, "data to be connected") requireIsHardware(that, "data to be connected") this.topBinding match { case _: ReadOnlyBinding => throwException(s"Cannot reassign to read-only $this") - case _ => // fine + case _ => // fine } try { MonoConnect.connect(sourceInfo, connectCompileOptions, this, that, Builder.referenceUserModule) @@ -543,10 +592,15 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { ) } } else { - this legacyConnect that + this.legacyConnect(that) } } - private[chisel3] def bulkConnect(that: Data)(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions): Unit = { + private[chisel3] def bulkConnect( + that: Data + )( + implicit sourceInfo: SourceInfo, + connectCompileOptions: CompileOptions + ): Unit = { if (connectCompileOptions.checkSynthesizable) { requireIsHardware(this, s"data to be bulk-connected") requireIsHardware(that, s"data to be bulk-connected") @@ -554,7 +608,7 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { case (_: ReadOnlyBinding, _: ReadOnlyBinding) => throwException(s"Both $this and $that are read-only") // DontCare cannot be a sink (LHS) case (_: DontCareBinding, _) => throw BiConnect.DontCareCantBeSink - case _ => // fine + case _ => // fine } try { BiConnect.connect(sourceInfo, connectCompileOptions, this, that, Builder.referenceUserModule) @@ -565,7 +619,7 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { ) } } else { - this legacyConnect that + this.legacyConnect(that) } } @@ -578,7 +632,8 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { val mod = topBindingOpt.flatMap(_.location) topBindingOpt match { case Some(tb: TopBinding) if (mod == Builder.currentModule) => - case Some(pb: PortBinding) if (mod.flatMap(Builder.retrieveParent(_,Builder.currentModule.get)) == Builder.currentModule) => + case Some(pb: PortBinding) + if (mod.flatMap(Builder.retrieveParent(_, Builder.currentModule.get)) == Builder.currentModule) => case Some(_: UnconstrainedBinding) => case _ => throwException(s"operand '$this' is not visible from the current module") @@ -593,7 +648,8 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { requireIsHardware(this) requireVisible() topBindingOpt match { - case Some(binding: ReadOnlyBinding) => throwException(s"internal error: attempted to generate LHS ref to ReadOnlyBinding $binding") + case Some(binding: ReadOnlyBinding) => + throwException(s"internal error: attempted to generate LHS ref to ReadOnlyBinding $binding") case Some(binding: TopBinding) => Node(this) case opt => throwException(s"internal error: unknown binding $opt in generating LHS ref") } @@ -622,12 +678,12 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { case Some(BundleLitBinding(litMap)) => litMap.get(this) match { case Some(litArg) => litArg - case _ => materializeWire() // FIXME FIRRTL doesn't have Bundle literal expressions + case _ => materializeWire() // FIXME FIRRTL doesn't have Bundle literal expressions } case Some(VecLitBinding(litMap)) => litMap.get(this) match { case Some(litArg) => litArg - case _ => materializeWire() // FIXME FIRRTL doesn't have Vec literal expressions + case _ => materializeWire() // FIXME FIRRTL doesn't have Vec literal expressions } case Some(DontCareBinding()) => materializeWire() // FIXME FIRRTL doesn't have a DontCare expression so materialize a Wire @@ -643,15 +699,14 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { } } - // Recursively set the parent of the start Data and any children (eg. in an Aggregate) private[chisel3] def setAllParents(parent: Option[BaseModule]): Unit = { def rec(data: Data): Unit = { data._parent = parent data match { - case _: Element => - case agg: Aggregate => - agg.getElements.foreach(rec) + case _: Element => + case agg: Aggregate => + agg.getElements.foreach(rec) } } rec(this) @@ -675,7 +730,7 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { * Directionality data is still preserved. */ private[chisel3] def cloneTypeFull: this.type = { - val clone = this.cloneType.asInstanceOf[this.type] // get a fresh object, without bindings + val clone = this.cloneType.asInstanceOf[this.type] // get a fresh object, without bindings // Only the top-level direction needs to be fixed up, cloneType should do the rest clone.specifiedDirection = specifiedDirection clone @@ -688,7 +743,7 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { * @param that the $coll to connect to * @group Connect */ - final def := (that: => Data)(implicit sourceInfo: SourceInfo, connectionCompileOptions: CompileOptions): Unit = { + final def :=(that: => Data)(implicit sourceInfo: SourceInfo, connectionCompileOptions: CompileOptions): Unit = { prefix(this) { this.connect(that)(sourceInfo, connectionCompileOptions) } @@ -701,7 +756,7 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { * @param that the $coll to connect to * @group Connect */ - final def <> (that: => Data)(implicit sourceInfo: SourceInfo, connectionCompileOptions: CompileOptions): Unit = { + final def <>(that: => Data)(implicit sourceInfo: SourceInfo, connectionCompileOptions: CompileOptions): Unit = { prefix(this) { this.bulkConnect(that)(sourceInfo, connectionCompileOptions) } @@ -709,32 +764,42 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { def isLit: Boolean = litOption.isDefined - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) def isLit(dummy: Int*): Boolean = isLit - /** - * If this is a literal that is representable as bits, returns the value as a BigInt. - * If not a literal, or not representable as bits (for example, is or contains Analog), returns None. - */ + * If this is a literal that is representable as bits, returns the value as a BigInt. + * If not a literal, or not representable as bits (for example, is or contains Analog), returns None. + */ def litOption: Option[BigInt] - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) def litOption(dummy: Int*): Option[BigInt] = litOption /** - * Returns the literal value if this is a literal that is representable as bits, otherwise crashes. - */ + * Returns the literal value if this is a literal that is representable as bits, otherwise crashes. + */ def litValue: BigInt = litOption.get - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) def litValue(dummy: Int*): BigInt = litValue /** Returns the width, in bits, if currently known. */ final def getWidth: Int = if (isWidthKnown) width.get else throwException(s"Width of $this is unknown!") + /** Returns whether the width is currently known. */ final def isWidthKnown: Boolean = width.known + /** Returns Some(width) if the width is known, else None. */ final def widthOption: Option[Int] = if (isWidthKnown) Some(getWidth) else None @@ -757,8 +822,12 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { /** Assigns this node from Bits type. Internal implementation for asTypeOf. */ - private[chisel3] def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, - compileOptions: CompileOptions): Unit + private[chisel3] def connectFromBits( + that: Bits + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Unit /** Reinterpret cast to UInt. * @@ -769,7 +838,10 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { */ final def asUInt: UInt = macro SourceInfoTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def asUInt(dummy: Int*): UInt = macro SourceInfoTransform.noArgDummy /** @group SourceInfoTransformMacro */ @@ -780,6 +852,7 @@ abstract class Data extends HasId with NamedComponent with SourceInfoDoc { } trait WireFactory { + /** Construct a [[Wire]] from a type template * @param t The template from which to construct this wire */ @@ -819,7 +892,6 @@ trait WireFactory { * // Width of w4.unknown is inferred * // Width of w4.known is set to 8 * }}} - * */ object Wire extends WireFactory @@ -884,7 +956,13 @@ object Wire extends WireFactory */ object WireDefault { - private def applyImpl[T <: Data](t: T, init: Data)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = { + private def applyImpl[T <: Data]( + t: T, + init: Data + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): T = { implicit val noSourceInfo = UnlocatableSourceInfo val x = Wire(t) requireIsHardware(init, "wire initializer") @@ -897,7 +975,13 @@ object WireDefault { * @param init The default connection to this [[Wire]], can only be [[DontCare]] * @note This is really just a specialized form of `apply[T <: Data](t: T, init: T): T` with [[DontCare]] as `init` */ - def apply[T <: Data](t: T, init: DontCare.type)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = { + def apply[T <: Data]( + t: T, + init: DontCare.type + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): T = { applyImpl(t, init) } @@ -941,7 +1025,12 @@ final case object DontCare extends Element { def toPrintable: Printable = PString("DONTCARE") - private[chisel3] def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Unit = { + private[chisel3] def connectFromBits( + that: Bits + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Unit = { Builder.error("connectFromBits: DontCare cannot be a connection sink (LHS)") } diff --git a/core/src/main/scala/chisel3/Element.scala b/core/src/main/scala/chisel3/Element.scala index bc006922..401f2bdf 100644 --- a/core/src/main/scala/chisel3/Element.scala +++ b/core/src/main/scala/chisel3/Element.scala @@ -14,8 +14,8 @@ import chisel3.internal._ */ abstract class Element extends Data { private[chisel3] final def allElements: Seq[Element] = Seq(this) - def widthKnown: Boolean = width.known - def name: String = getRef.name + def widthKnown: Boolean = width.known + def name: String = getRef.name private[chisel3] override def bind(target: Binding, parentDirection: SpecifiedDirection): Unit = { _parent.foreach(_.addId(this)) @@ -26,27 +26,30 @@ abstract class Element extends Data { 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)) - case _ => Some(DontCareBinding()) - } - case Some(VecLitBinding(litMap)) => litMap.get(this) match { - case Some(litArg) => Some(ElementLitBinding(litArg)) - case _ => Some(DontCareBinding()) - } - case Some(b @ AggregateViewBinding(viewMap, _)) => viewMap.get(this) match { - case Some(elt) => Some(ViewBinding(elt)) - case _ => throwException(s"Internal Error! $this missing from topBinding $b") - } + case Some(BundleLitBinding(litMap)) => + litMap.get(this) match { + case Some(litArg) => Some(ElementLitBinding(litArg)) + case _ => Some(DontCareBinding()) + } + case Some(VecLitBinding(litMap)) => + litMap.get(this) match { + case Some(litArg) => Some(ElementLitBinding(litArg)) + case _ => Some(DontCareBinding()) + } + case Some(b @ AggregateViewBinding(viewMap, _)) => + viewMap.get(this) match { + case Some(elt) => Some(ViewBinding(elt)) + case _ => throwException(s"Internal Error! $this missing from topBinding $b") + } case topBindingOpt => topBindingOpt } private[chisel3] def litArgOption: Option[LitArg] = topBindingOpt match { case Some(ElementLitBinding(litArg)) => Some(litArg) - case _ => None + case _ => None } - override def litOption: Option[BigInt] = litArgOption.map(_.num) + override def litOption: Option[BigInt] = litArgOption.map(_.num) private[chisel3] def litIsForcedWidth: Option[Boolean] = litArgOption.map(_.forcedWidth) private[chisel3] def legacyConnect(that: Data)(implicit sourceInfo: SourceInfo): Unit = { diff --git a/core/src/main/scala/chisel3/Mem.scala b/core/src/main/scala/chisel3/Mem.scala index aeacf052..ff5072ad 100644 --- a/core/src/main/scala/chisel3/Mem.scala +++ b/core/src/main/scala/chisel3/Mem.scala @@ -9,8 +9,7 @@ import firrtl.{ir => fir} import chisel3.internal._ import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl._ -import chisel3.internal.sourceinfo.{SourceInfo, SourceInfoTransform, UnlocatableSourceInfo, MemTransform} - +import chisel3.internal.sourceinfo.{MemTransform, SourceInfo, SourceInfoTransform, UnlocatableSourceInfo} object Mem { @@ -29,11 +28,17 @@ object Mem { def apply[T <: Data](size: Int, t: T): Mem[T] = macro MemTransform.apply[T] /** @group SourceInfoTransformMacro */ - def do_apply[T <: Data](size: BigInt, t: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Mem[T] = { + def do_apply[T <: Data]( + size: BigInt, + t: T + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Mem[T] = { if (compileOptions.declaredTypeMustBeUnbound) { requireIsChiselType(t, "memory type") } - val mt = t.cloneTypeFull + val mt = t.cloneTypeFull val mem = new Mem(mt, size) mt.bind(MemTypeBinding(mem)) pushCommand(DefMemory(sourceInfo, mem, mt, size)) @@ -45,7 +50,10 @@ object Mem { do_apply(BigInt(size), t)(sourceInfo, compileOptions) } -sealed abstract class MemBase[T <: Data](val t: T, val length: BigInt) extends HasId with NamedComponent with SourceInfoDoc { +sealed abstract class MemBase[T <: Data](val t: T, val length: BigInt) + extends HasId + with NamedComponent + with SourceInfoDoc { _parent.foreach(_.addId(this)) // REVIEW TODO: make accessors (static/dynamic, read/write) combinations consistent. @@ -107,7 +115,14 @@ sealed abstract class MemBase[T <: Data](val t: T, val length: BigInt) extends H * * @note this is only allowed if the memory's element data type is a Vec */ - def write(idx: UInt, data: T, mask: Seq[Bool]) (implicit evidence: T <:< Vec[_], compileOptions: CompileOptions): Unit = { + def write( + idx: UInt, + data: T, + mask: Seq[Bool] + )( + implicit evidence: T <:< Vec[_], + compileOptions: CompileOptions + ): Unit = { implicit val sourceInfo = UnlocatableSourceInfo val accessor = makePort(sourceInfo, idx, MemPortDirection.WRITE).asInstanceOf[Vec[Data]] val dataVec = data.asInstanceOf[Vec[Data]] @@ -117,17 +132,22 @@ sealed abstract class MemBase[T <: Data](val t: T, val length: BigInt) extends H if (accessor.length != mask.length) { Builder.error(s"Mem write mask must contain ${accessor.length} elements (found ${mask.length})") } - for (((cond, port), datum) <- mask zip accessor zip dataVec) - when (cond) { port := datum } + for (((cond, port), datum) <- mask.zip(accessor).zip(dataVec)) + when(cond) { port := datum } } - private def makePort(sourceInfo: SourceInfo, idx: UInt, dir: MemPortDirection)(implicit compileOptions: CompileOptions): T = { + private def makePort( + sourceInfo: SourceInfo, + idx: UInt, + dir: MemPortDirection + )( + implicit compileOptions: CompileOptions + ): T = { requireIsHardware(idx, "memory port index") val i = Vec.truncateIndex(idx, length)(sourceInfo, compileOptions) val port = pushCommand( - DefMemPort(sourceInfo, - t.cloneTypeFull, Node(this), dir, i.ref, Builder.forcedClock.ref) + DefMemPort(sourceInfo, t.cloneTypeFull, Node(this), dir, i.ref, Builder.forcedClock.ref) ).id // Bind each element of port to being a MemoryPort port.bind(MemoryPortBinding(Builder.forcedUserModule, Builder.currentWhen)) @@ -148,7 +168,6 @@ sealed class Mem[T <: Data] private (t: T, length: BigInt) extends MemBase(t, le object SyncReadMem { - type ReadUnderWrite = fir.ReadUnderWrite.Value val Undefined = fir.ReadUnderWrite.Undefined val ReadFirst = fir.ReadUnderWrite.Old @@ -171,11 +190,18 @@ object SyncReadMem { def apply[T <: Data](size: Int, t: T, ruw: ReadUnderWrite): SyncReadMem[T] = macro MemTransform.apply_ruw[T] /** @group SourceInfoTransformMacro */ - def do_apply[T <: Data](size: BigInt, t: T, ruw: ReadUnderWrite = Undefined)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SyncReadMem[T] = { + def do_apply[T <: Data]( + size: BigInt, + t: T, + ruw: ReadUnderWrite = Undefined + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): SyncReadMem[T] = { if (compileOptions.declaredTypeMustBeUnbound) { requireIsChiselType(t, "memory type") } - val mt = t.cloneTypeFull + val mt = t.cloneTypeFull val mem = new SyncReadMem(mt, size, ruw) mt.bind(MemTypeBinding(mem)) pushCommand(DefSeqMemory(sourceInfo, mem, mt, size, ruw)) @@ -184,12 +210,25 @@ object SyncReadMem { /** @group SourceInfoTransformMacro */ // Alternate signatures can't use default parameter values - def do_apply[T <: Data](size: Int, t: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SyncReadMem[T] = + def do_apply[T <: Data]( + size: Int, + t: T + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): SyncReadMem[T] = do_apply(BigInt(size), t)(sourceInfo, compileOptions) /** @group SourceInfoTransformMacro */ // Alternate signatures can't use default parameter values - def do_apply[T <: Data](size: Int, t: T, ruw: ReadUnderWrite)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SyncReadMem[T] = + def do_apply[T <: Data]( + size: Int, + t: T, + ruw: ReadUnderWrite + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): SyncReadMem[T] = do_apply(BigInt(size), t, ruw)(sourceInfo, compileOptions) } @@ -203,7 +242,8 @@ object SyncReadMem { * @note when multiple conflicting writes are performed on a Mem element, the * result is undefined (unlike Vec, where the last assignment wins) */ -sealed class SyncReadMem[T <: Data] private (t: T, n: BigInt, val readUnderWrite: SyncReadMem.ReadUnderWrite) extends MemBase[T](t, n) { +sealed class SyncReadMem[T <: Data] private (t: T, n: BigInt, val readUnderWrite: SyncReadMem.ReadUnderWrite) + extends MemBase[T](t, n) { def read(x: UInt, en: Bool): T = macro SourceInfoTransform.xEnArg /** @group SourceInfoTransformMacro */ @@ -211,14 +251,14 @@ sealed class SyncReadMem[T <: Data] private (t: T, n: BigInt, val readUnderWrite val a = Wire(UInt()) a := DontCare var port: Option[T] = None - when (enable) { + when(enable) { a := addr port = Some(super.do_read(a)) } port.get } - /** @group SourceInfoTransformMacro*/ + /** @group SourceInfoTransformMacro */ override def do_read(idx: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) = do_read(addr = idx, enable = true.B) // note: we implement do_read(addr) for SyncReadMem in terms of do_read(addr, en) in order to ensure that diff --git a/core/src/main/scala/chisel3/Module.scala b/core/src/main/scala/chisel3/Module.scala index 7ba24585..3611f5dd 100644 --- a/core/src/main/scala/chisel3/Module.scala +++ b/core/src/main/scala/chisel3/Module.scala @@ -15,6 +15,7 @@ import _root_.firrtl.annotations.{IsModule, ModuleName, ModuleTarget} import _root_.firrtl.AnnotationSeq object Module extends SourceInfoDoc { + /** A wrapper method that all Module instantiations must be wrapped in * (necessary to help Chisel track internal state). * @@ -25,12 +26,12 @@ object Module extends SourceInfoDoc { 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 = { + 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 " + _)) + throwException( + "Error: Called Module() twice without instantiating a Module." + + sourceInfo.makeMessage(" See " + _) + ) } Builder.readyForModuleConstr = true @@ -38,7 +39,7 @@ object Module extends SourceInfoDoc { val parentWhenStack = Builder.whenStack // Save then clear clock and reset to prevent leaking scope, must be set again in the Module - val (saveClock, saveReset) = (Builder.currentClock, Builder.currentReset) + val (saveClock, saveReset) = (Builder.currentClock, Builder.currentReset) val savePrefix = Builder.getPrefix Builder.clearPrefix() Builder.currentClock = None @@ -49,19 +50,21 @@ object Module extends SourceInfoDoc { // - unset readyForModuleConstr // - reset whenStack to be empty // - set currentClockAndReset - val module: T = bc // bc is actually evaluated here + 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 " + _)) + 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.whenStack = parentWhenStack - Builder.currentClock = saveClock // Back to clock and reset scope + Builder.currentClock = saveClock // Back to clock and reset scope Builder.currentReset = saveReset // Only add the component if the module generates one @@ -84,17 +87,22 @@ object Module extends SourceInfoDoc { /** 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 - private[chisel3] def do_pseudo_apply[T <: BaseModule](bc: => T) - (implicit sourceInfo: SourceInfo, - compileOptions: CompileOptions): T = { + private[chisel3] def do_pseudo_apply[T <: BaseModule]( + bc: => T + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): T = { val parent = Builder.currentModule - val module: T = bc // bc is actually evaluated here + val module: T = bc // bc is actually evaluated here module } @@ -150,12 +158,12 @@ abstract class Module(implicit moduleCompileOptions: CompileOptions) extends Raw } } - package experimental { import chisel3.internal.requireIsChiselType // Fix ambiguous import object IO { + /** Constructs a port for the current Module * * This must wrap the datatype used to set the io field of any Module. @@ -170,20 +178,21 @@ package experimental { * requested (so that all calls to ports will return the same information). * Internal API. */ - def apply[T<:Data](iodef: T): T = { + 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 - } + 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 } @@ -192,9 +201,10 @@ package experimental { package internal { import chisel3.experimental.BaseModule - import chisel3.experimental.hierarchy.{IsInstantiable, Proto, Clone} + import chisel3.experimental.hierarchy.{Clone, IsInstantiable, Proto} object BaseModule { + /** Represents a clone of an underlying object. This is used to support CloneModuleAsRecord and Instance/Definition. * * @note We don't actually "clone" anything in the traditional sense but is a placeholder so we lazily clone internal state @@ -217,7 +227,7 @@ package internal { } // Private internal class to serve as a _parent for Data in cloned ports - private[chisel3] class ModuleClone[T <: BaseModule] (val getProto: T) extends PseudoModule with IsClone[T] { + private[chisel3] class ModuleClone[T <: BaseModule](val getProto: T) extends PseudoModule with IsClone[T] { override def toString = s"ModuleClone(${getProto})" def getPorts = _portsRecord // ClonePorts that hold the bound ports for this module @@ -226,7 +236,7 @@ package internal { // This is necessary for correctly supporting .toTarget on a Module Clone. If it is made from the // Instance/Definition API, it should return an instanceTarget. If made from CMAR, it should return a // ModuleTarget. - private[chisel3] var _madeFromDefinition: Boolean = false + private[chisel3] var _madeFromDefinition: Boolean = false // Don't generate a component, but point to the one for the cloned Module private[chisel3] def generateComponent(): Option[Component] = { require(!_closed, "Can't generate module more than once") @@ -248,14 +258,14 @@ package internal { private[chisel3] def setRefAndPortsRef(namespace: Namespace): Unit = { val record = _portsRecord // Use .forceName to re-use default name resolving behavior - record.forceName(None, default=this.desiredName, namespace) + record.forceName(None, default = this.desiredName, namespace) // Now take the Ref that forceName set and convert it to the correct Arg val instName = record.getRef match { case Ref(name) => name - case bad => throwException(s"Internal Error! Cloned-module Record $record has unexpected ref $bad") + case bad => throwException(s"Internal Error! Cloned-module Record $record has unexpected ref $bad") } // Set both the record and the module to have the same instance name - record.setRef(ModuleCloneIO(getProto, instName), force=true) // force because we did .forceName first + record.setRef(ModuleCloneIO(getProto, instName), force = true) // force because we did .forceName first this.setRef(Ref(instName)) } } @@ -269,7 +279,9 @@ package internal { * @note In addition, the instance name of an InstanceClone is going to be the SAME as the proto, but this is not true * for ModuleClone. */ - private[chisel3] final class InstanceClone[T <: BaseModule] (val getProto: T, val instName: () => String) extends PseudoModule with IsClone[T] { + private[chisel3] final class InstanceClone[T <: BaseModule](val getProto: T, val instName: () => String) + extends PseudoModule + with IsClone[T] { override def toString = s"InstanceClone(${getProto})" // No addition components are generated private[chisel3] def generateComponent(): Option[Component] = None @@ -291,7 +303,7 @@ package internal { * target whose root is the Definition. This DefinitionClone is used to represent the root parent of the * InstanceClone (which represents the returned module). */ - private[chisel3] class DefinitionClone[T <: BaseModule] (val getProto: T) extends PseudoModule with IsClone[T] { + private[chisel3] class DefinitionClone[T <: BaseModule](val getProto: T) extends PseudoModule with IsClone[T] { override def toString = s"DefinitionClone(${getProto})" // No addition components are generated private[chisel3] def generateComponent(): Option[Component] = None @@ -313,13 +325,18 @@ package internal { * @note These are not true Data (the Record doesn't correspond to anything in the emitted * FIRRTL yet its elements *do*) so have some very specialized behavior. */ - private[chisel3] class ClonePorts (elts: Data*)(implicit compileOptions: CompileOptions) extends Record { + 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 = { + private[chisel3] def cloneIORecord( + proto: BaseModule + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): ClonePorts = { require(proto.isClosed, "Can't clone a module before module close") // Fake Module to serve as the _parent of the cloned ports // We make this before clonePorts because we want it to come up first in naming in @@ -353,11 +370,12 @@ package experimental { object BaseModule { implicit class BaseModuleExtensions[T <: BaseModule](b: T) { - import chisel3.experimental.hierarchy.{Instance, Definition} - def toInstance: Instance[T] = new Instance(Proto(b)) + import chisel3.experimental.hierarchy.{Definition, Instance} + def toInstance: Instance[T] = new Instance(Proto(b)) def toDefinition: Definition[T] = new Definition(Proto(b)) } } + /** Abstract base class for Modules, an instantiable organizational unit for RTL. */ // TODO: seal this? @@ -461,30 +479,34 @@ package experimental { val baseName = this.getClass.getName /* A sequence of string filters applied to the name */ - val filters: Seq[String => String] = Seq( - ((a: String) => raw"\$$+anon".r.replaceAllIn(a, "_Anon")) // Merge the "$$anon" name with previous name - ) + val filters: Seq[String => String] = + Seq(((a: String) => raw"\$$+anon".r.replaceAllIn(a, "_Anon")) // Merge the "$$anon" name with previous name + ) filters - .foldLeft(baseName){ case (str, filter) => filter(str) } // 1. Apply filters to baseName - .split("\\.|\\$") // 2. Split string at '.' or '$' - .filterNot(_.forall(_.isDigit)) // 3. Drop purely numeric names - .last // 4. Use the last name + .foldLeft(baseName) { case (str, filter) => filter(str) } // 1. Apply filters to baseName + .split("\\.|\\$") // 2. Split string at '.' or '$' + .filterNot(_.forall(_.isDigit)) // 3. Drop purely numeric names + .last // 4. Use the last name } /** Legalized name of this module. */ - final lazy val name = try { - // PseudoModules are not "true modules" and thus should share - // their original modules names without uniquification - this match { - case _: PseudoModule => desiredName - case _ => Builder.globalNamespace.name(desiredName) + final lazy val name = + try { + // PseudoModules are not "true modules" and thus should share + // their original modules names without uniquification + this match { + case _: PseudoModule => desiredName + case _ => 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 + ) + case t: Throwable => throw t } - } 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) - case t: Throwable => throw t - } /** Returns a FIRRTL ModuleName that references this object * @@ -497,8 +519,10 @@ package experimental { * @note Should not be called until circuit elaboration is complete */ final def toTarget: ModuleTarget = this match { - case m: internal.BaseModule.InstanceClone[_] => throwException(s"Internal Error! It's not legal to call .toTarget on an InstanceClone. $m") - case m: internal.BaseModule.DefinitionClone[_] => throwException(s"Internal Error! It's not legal to call .toTarget on an DefinitionClone. $m") + case m: internal.BaseModule.InstanceClone[_] => + throwException(s"Internal Error! It's not legal to call .toTarget on an InstanceClone. $m") + case m: internal.BaseModule.DefinitionClone[_] => + throwException(s"Internal Error! It's not legal to call .toTarget on an DefinitionClone. $m") case _ => ModuleTarget(this.circuitName, this.name) } @@ -514,10 +538,13 @@ package experimental { * the correct [[InstanceTarget]]s whenever using the Definition/Instance API. */ private[chisel3] def getTarget: IsModule = this match { - case m: internal.BaseModule.InstanceClone[_] if m._parent.nonEmpty => m._parent.get.getTarget.instOf(instanceName, name) - case m: internal.BaseModule.ModuleClone[_] if m._madeFromDefinition => m._parent.get.getTarget.instOf(instanceName, name) + case m: internal.BaseModule.InstanceClone[_] if m._parent.nonEmpty => + m._parent.get.getTarget.instOf(instanceName, name) + case m: internal.BaseModule.ModuleClone[_] if m._madeFromDefinition => + m._parent.get.getTarget.instOf(instanceName, name) // Without this, we get the wrong CircuitName for the Definition - case m: internal.BaseModule.DefinitionClone[_] if m._circuit.nonEmpty => ModuleTarget(this._circuit.get.circuitName, this.name) + case m: internal.BaseModule.DefinitionClone[_] if m._circuit.nonEmpty => + ModuleTarget(this._circuit.get.circuitName, this.name) case _ => this.toTarget } @@ -528,7 +555,7 @@ package experimental { final def toAbsoluteTarget: IsModule = { _parent match { case Some(parent) => parent.toAbsoluteTarget.instOf(this.instanceName, name) - case None => + case None => // FIXME Special handling for Views - evidence of "weirdness" of .toAbsoluteTarget // In theory, .toAbsoluteTarget should not be necessary, .toTarget combined with the // target disambiguation in FIRRTL's deduplication transform should ensure that .toTarget @@ -619,17 +646,19 @@ package experimental { 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 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 } - case SpecifiedDirection.Input | SpecifiedDirection.Output => // forced assign, nothing to do - } } } @@ -669,10 +698,12 @@ package experimental { /** 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 - } + if (_parent == None) name + else + _component match { + case None => getRef.name + case Some(c) => getRef.fullName(c) + } } } diff --git a/core/src/main/scala/chisel3/ModuleAspect.scala b/core/src/main/scala/chisel3/ModuleAspect.scala index a528fa72..471ab980 100644 --- a/core/src/main/scala/chisel3/ModuleAspect.scala +++ b/core/src/main/scala/chisel3/ModuleAspect.scala @@ -12,8 +12,9 @@ import chisel3.internal.{Builder, PseudoModule} * @param module Module for which this object is an aspect of * @param moduleCompileOptions */ -abstract class ModuleAspect private[chisel3] (module: RawModule) - (implicit moduleCompileOptions: CompileOptions) extends RawModule with PseudoModule { +abstract class ModuleAspect private[chisel3] (module: RawModule)(implicit moduleCompileOptions: CompileOptions) + extends RawModule + with PseudoModule { Builder.addAspect(module, this) @@ -23,4 +24,3 @@ abstract class ModuleAspect private[chisel3] (module: RawModule) override val _namespace = module._namespace } - diff --git a/core/src/main/scala/chisel3/MultiClock.scala b/core/src/main/scala/chisel3/MultiClock.scala index 6a745f14..e96946f5 100644 --- a/core/src/main/scala/chisel3/MultiClock.scala +++ b/core/src/main/scala/chisel3/MultiClock.scala @@ -7,6 +7,7 @@ import chisel3.internal._ import scala.language.experimental.macros object withClockAndReset { + /** Creates a new Clock and Reset scope * * @param clock the new implicit Clock @@ -32,13 +33,14 @@ object withClockAndReset { } object withClock { + /** Creates a new Clock scope * * @param clock the new implicit Clock * @param block the block of code to run with new implicit Clock * @return the result of the block */ - def apply[T](clock: Clock)(block: => T): T = { + def apply[T](clock: Clock)(block: => T): T = { // Save parentScope val parentClock = Builder.currentClock Builder.currentClock = Some(clock) @@ -50,6 +52,7 @@ object withClock { } object withReset { + /** Creates a new Reset scope * * @param reset the new implicit Reset @@ -67,4 +70,3 @@ object withReset { } } - diff --git a/core/src/main/scala/chisel3/Mux.scala b/core/src/main/scala/chisel3/Mux.scala index 00f2a717..df56182e 100644 --- a/core/src/main/scala/chisel3/Mux.scala +++ b/core/src/main/scala/chisel3/Mux.scala @@ -6,11 +6,12 @@ import scala.language.experimental.macros import chisel3.internal._ import chisel3.internal.Builder.pushOp -import chisel3.internal.sourceinfo.{SourceInfo, MuxTransform} +import chisel3.internal.sourceinfo.{MuxTransform, SourceInfo} import chisel3.internal.firrtl._ import chisel3.internal.firrtl.PrimOp._ object Mux extends SourceInfoDoc { + /** Creates a mux, whose output is one of the inputs depending on the * value of the condition. * @@ -25,13 +26,19 @@ object Mux extends SourceInfoDoc { def apply[T <: Data](cond: Bool, con: T, alt: T): T = macro MuxTransform.apply[T] /** @group SourceInfoTransformMacro */ - def do_apply[T <: Data](cond: Bool, con: T, alt: T)(implicit sourceInfo: SourceInfo, - compileOptions: CompileOptions): T = { + def do_apply[T <: Data]( + cond: Bool, + con: T, + alt: T + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): T = { requireIsHardware(cond, "mux condition") requireIsHardware(con, "mux true value") requireIsHardware(alt, "mux false value") val d = cloneSupertype(Seq(con, alt), "Mux") - val conRef = con match { // this matches chisel semantics (DontCare as object) to firrtl semantics (invalidate) + val conRef = con match { // this matches chisel semantics (DontCare as object) to firrtl semantics (invalidate) case DontCare => val dcWire = Wire(d) dcWire := DontCare diff --git a/core/src/main/scala/chisel3/Num.scala b/core/src/main/scala/chisel3/Num.scala index 219e18f4..c7e0721f 100644 --- a/core/src/main/scala/chisel3/Num.scala +++ b/core/src/main/scala/chisel3/Num.scala @@ -8,7 +8,6 @@ import chisel3.internal.firrtl.{BinaryPoint, KnownBinaryPoint} import scala.language.experimental.macros import chisel3.internal.sourceinfo.{SourceInfo, SourceInfoTransform} - // REVIEW TODO: Further discussion needed on what Num actually is. /** Abstract trait defining operations available on numeric-like hardware data types. @@ -43,10 +42,10 @@ trait Num[T <: Data] { * $maxWidth * @group Arithmetic */ - final def + (that: T): T = macro SourceInfoTransform.thatArg + final def +(that: T): T = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_+ (that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T + def do_+(that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T /** Multiplication operator * @@ -56,10 +55,10 @@ trait Num[T <: Data] { * $singleCycleMul * @group Arithmetic */ - final def * (that: T): T = macro SourceInfoTransform.thatArg + final def *(that: T): T = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_* (that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T + def do_*(that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T /** Division operator * @@ -69,10 +68,10 @@ trait Num[T <: Data] { * @todo full rules * @group Arithmetic */ - final def / (that: T): T = macro SourceInfoTransform.thatArg + final def /(that: T): T = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_/ (that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T + def do_/(that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T /** Modulo operator * @@ -81,10 +80,10 @@ trait Num[T <: Data] { * $singleCycleDiv * @group Arithmetic */ - final def % (that: T): T = macro SourceInfoTransform.thatArg + final def %(that: T): T = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_% (that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T + def do_%(that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T /** Subtraction operator * @@ -93,10 +92,10 @@ trait Num[T <: Data] { * $maxWidthPlusOne * @group Arithmetic */ - final def - (that: T): T = macro SourceInfoTransform.thatArg + final def -(that: T): T = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_- (that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T + def do_-(that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T /** Less than operator * @@ -104,10 +103,10 @@ trait Num[T <: Data] { * @return a hardware [[Bool]] asserted if this $coll is less than `that` * @group Comparison */ - final def < (that: T): Bool = macro SourceInfoTransform.thatArg + final def <(that: T): Bool = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_< (that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool + def do_<(that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool /** Less than or equal to operator * @@ -115,10 +114,10 @@ trait Num[T <: Data] { * @return a hardware [[Bool]] asserted if this $coll is less than or equal to `that` * @group Comparison */ - final def <= (that: T): Bool = macro SourceInfoTransform.thatArg + final def <=(that: T): Bool = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_<= (that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool + def do_<=(that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool /** Greater than operator * @@ -126,10 +125,10 @@ trait Num[T <: Data] { * @return a hardware [[Bool]] asserted if this $coll is greater than `that` * @group Comparison */ - final def > (that: T): Bool = macro SourceInfoTransform.thatArg + final def >(that: T): Bool = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_> (that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool + def do_>(that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool /** Greater than or equal to operator * @@ -137,10 +136,10 @@ trait Num[T <: Data] { * @return a hardware [[Bool]] asserted if this $coll is greather than or equal to `that` * @group Comparison */ - final def >= (that: T): Bool = macro SourceInfoTransform.thatArg + final def >=(that: T): Bool = macro SourceInfoTransform.thatArg /** @group SourceInfoTransformMacro */ - def do_>= (that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool + def do_>=(that: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool /** Absolute value operator * @@ -150,7 +149,10 @@ trait Num[T <: Data] { */ final def abs: T = macro SourceInfoTransform.noArg - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) final def abs(dummy: Int*): T = macro SourceInfoTransform.noArgDummy /** @group SourceInfoTransformMacro */ @@ -189,7 +191,6 @@ object Num extends NumObject * BigInts and Double and BigDecimal * For backwards compatibility this is used with FixedPoint and Interval objects * but is better used with the Num Object - * */ trait NumObject { val MaxBitsBigIntToBigDecimal = 108 @@ -254,7 +255,7 @@ trait NumObject { * @return */ def toDouble(i: BigInt, binaryPoint: Int): Double = { - if(i.bitLength >= 54) { + if (i.bitLength >= 54) { throw new ChiselException( s"BigInt $i with bitlength ${i.bitLength} is too big, precision lost with > $MaxBitsBigIntToDouble bits" ) @@ -275,7 +276,8 @@ trait NumObject { case KnownBinaryPoint(n) => toDouble(value, n) case x => throw new ChiselException(s"Error converting BigDecimal $value to BigInt, binary point must be known, not $x") - } } + } + } /** * converts a bigInt with the given binaryPoint into the BigDecimal representation @@ -284,7 +286,7 @@ trait NumObject { * @return */ def toBigDecimal(value: BigInt, binaryPoint: Int): BigDecimal = { - if(value.bitLength > MaxBitsBigIntToBigDecimal) { + if (value.bitLength > MaxBitsBigIntToBigDecimal) { throw new ChiselException( s"BigInt $value with bitlength ${value.bitLength} is too big, precision lost with > $MaxBitsBigIntToBigDecimal bits" ) diff --git a/core/src/main/scala/chisel3/Printable.scala b/core/src/main/scala/chisel3/Printable.scala index 006286f9..c477716b 100644 --- a/core/src/main/scala/chisel3/Printable.scala +++ b/core/src/main/scala/chisel3/Printable.scala @@ -6,10 +6,7 @@ import chisel3.internal.firrtl.Component import scala.collection.mutable -import java.util.{ - MissingFormatArgumentException, - UnknownFormatConversionException -} +import java.util.{MissingFormatArgumentException, UnknownFormatConversionException} /** Superclass of things that can be printed in the resulting circuit * @@ -47,17 +44,21 @@ import java.util.{ // Could be implemented by adding a new format specifier to Firrtl (eg. %m) // TODO Should we provide more functions like map and mkPrintable? sealed abstract class Printable { + /** Unpack into format String and a List of String arguments (identifiers) * @note This must be called after elaboration when Chisel nodes actually * have names */ def unpack(ctx: Component): (String, Iterable[String]) + /** Allow for appending Printables like Strings */ final def +(that: Printable): Printables = Printables(List(this, that)) + /** Allow for appending Strings to Printables */ final def +(that: String): Printables = Printables(List(this, PString(that))) } object Printable { + /** Pack standard printf fmt, args* style into Printable */ def pack(fmt: String, data: Data*): Printable = { @@ -68,11 +69,11 @@ object Printable { def errorMsg(index: Int) = s"""| fmt = "$fmt" | ${carrotAt(index)} - | data = ${data mkString ", "}""".stripMargin + | data = ${data.mkString(", ")}""".stripMargin def getArg(i: Int): Data = { if (!args.hasNext) { val msg = "has no matching argument!\n" + errorMsg(i) - // Exception wraps msg in s"Format Specifier '$msg'" + // Exception wraps msg in s"Format Specifier '$msg'" throw new MissingFormatArgumentException(msg) } args.next() @@ -85,14 +86,14 @@ object Printable { if (percent) { val arg = c match { case FirrtlFormat(x) => FirrtlFormat(x.toString, getArg(i)) - case 'n' => Name(getArg(i)) - case 'N' => FullName(getArg(i)) - case '%' => Percent + case 'n' => Name(getArg(i)) + case 'N' => FullName(getArg(i)) + case '%' => Percent case x => val msg = s"Illegal format specifier '$x'!\n" + errorMsg(i) throw new UnknownFormatConversionException(msg) } - pables += PString(str dropRight 1) // remove format % + pables += PString(str.dropRight(1)) // remove format % pables += arg str = "" percent = false @@ -105,9 +106,11 @@ object Printable { val msg = s"Trailing %\n" + errorMsg(fmt.size - 1) throw new UnknownFormatConversionException(msg) } - require(!args.hasNext, + require( + !args.hasNext, s"Too many arguments! More format specifier(s) expected!\n" + - errorMsg(fmt.size)) + errorMsg(fmt.size) + ) pables += PString(str) Printables(pables) @@ -117,15 +120,17 @@ object Printable { case class Printables(pables: Iterable[Printable]) extends Printable { require(pables.hasDefiniteSize, "Infinite-sized iterables are not supported!") final def unpack(ctx: Component): (String, Iterable[String]) = { - val (fmts, args) = pables.map(_ unpack ctx).unzip + val (fmts, args) = pables.map(_.unpack(ctx)).unzip (fmts.mkString, args.flatten) } } + /** Wrapper for printing Scala Strings */ case class PString(str: String) extends Printable { final def unpack(ctx: Component): (String, Iterable[String]) = - (str replaceAll ("%", "%%"), List.empty) + (str.replaceAll("%", "%%"), List.empty) } + /** Superclass for Firrtl format specifiers for Bits */ sealed abstract class FirrtlFormat(private[chisel3] val specifier: Char) extends Printable { def bits: Bits @@ -137,7 +142,7 @@ object FirrtlFormat { final val legalSpecifiers = List('d', 'x', 'b', 'c') def unapply(x: Char): Option[Char] = - Option(x) filter (x => legalSpecifiers contains x) + Option(x).filter(x => legalSpecifiers contains x) /** Helper for constructing Firrtl Formats * Accepts data to simplify pack @@ -152,26 +157,33 @@ object FirrtlFormat { case "x" => Hexadecimal(bits) case "b" => Binary(bits) case "c" => Character(bits) - case c => throw new Exception(s"Illegal format specifier '$c'!") + case c => throw new Exception(s"Illegal format specifier '$c'!") } } } + /** Format bits as Decimal */ case class Decimal(bits: Bits) extends FirrtlFormat('d') + /** Format bits as Hexidecimal */ case class Hexadecimal(bits: Bits) extends FirrtlFormat('x') + /** Format bits as Binary */ case class Binary(bits: Bits) extends FirrtlFormat('b') + /** Format bits as Character */ case class Character(bits: Bits) extends FirrtlFormat('c') + /** Put innermost name (eg. field of bundle) */ case class Name(data: Data) extends Printable { final def unpack(ctx: Component): (String, Iterable[String]) = (data.ref.name, List.empty) } + /** Put full name within parent namespace (eg. bundleName.field) */ case class FullName(data: Data) extends Printable { final def unpack(ctx: Component): (String, Iterable[String]) = (data.ref.fullName(ctx), List.empty) } + /** Represents escaped percents */ case object Percent extends Printable { final def unpack(ctx: Component): (String, Iterable[String]) = ("%%", List.empty) diff --git a/core/src/main/scala/chisel3/Printf.scala b/core/src/main/scala/chisel3/Printf.scala index be0146bb..bdcca8e1 100644 --- a/core/src/main/scala/chisel3/Printf.scala +++ b/core/src/main/scala/chisel3/Printf.scala @@ -12,10 +12,10 @@ import chisel3.internal.sourceinfo.SourceInfo * See apply methods for use */ object printf { + /** Helper for packing escape characters */ private[chisel3] def format(formatIn: String): String = { - require(formatIn forall (c => c.toInt > 0 && c.toInt < 128), - "format strings must comprise non-null ASCII values") + require(formatIn.forall(c => c.toInt > 0 && c.toInt < 128), "format strings must comprise non-null ASCII values") def escaped(x: Char) = { require(x.toInt >= 0, s"char ${x} to Int ${x.toInt} must be >= 0") if (x == '"' || x == '\\') { @@ -25,15 +25,18 @@ object printf { } else if (x == '\t') { "\\t" } else { - require(x.toInt >= 32, s"char ${x} to Int ${x.toInt} must be >= 32") // TODO \xNN once FIRRTL issue #59 is resolved + require( + x.toInt >= 32, + s"char ${x} to Int ${x.toInt} must be >= 32" + ) // TODO \xNN once FIRRTL issue #59 is resolved x } } - formatIn map escaped mkString "" + formatIn.map(escaped).mkString("") } /** Named class for [[printf]]s. */ - final class Printf private[chisel3](val pable: Printable) extends VerificationStatement + final class Printf private[chisel3] (val pable: Printable) extends VerificationStatement /** Prints a message in simulation * @@ -73,7 +76,8 @@ object printf { * @param data format string varargs containing data to print */ def apply(fmt: String, data: Bits*)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Printf = - apply(Printable.pack(fmt, data:_*)) + apply(Printable.pack(fmt, data: _*)) + /** Prints a message in simulation * * Prints a message every cycle. If defined within the scope of a [[when]] block, the message @@ -90,18 +94,29 @@ object printf { */ def apply(pable: Printable)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Printf = { var printfId: Printf = null - when (!Module.reset.asBool) { + when(!Module.reset.asBool) { printfId = printfWithoutReset(pable) } printfId } - private[chisel3] def printfWithoutReset(pable: Printable)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Printf = { + private[chisel3] def printfWithoutReset( + pable: Printable + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Printf = { val clock = Builder.forcedClock val printfId = new Printf(pable) pushCommand(chisel3.internal.firrtl.Printf(printfId, sourceInfo, clock.ref, pable)) printfId } - private[chisel3] def printfWithoutReset(fmt: String, data: Bits*)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Printf = - printfWithoutReset(Printable.pack(fmt, data:_*)) + private[chisel3] def printfWithoutReset( + fmt: String, + data: Bits* + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Printf = + printfWithoutReset(Printable.pack(fmt, data: _*)) } diff --git a/core/src/main/scala/chisel3/RawModule.scala b/core/src/main/scala/chisel3/RawModule.scala index e977d918..b81372d8 100644 --- a/core/src/main/scala/chisel3/RawModule.scala +++ b/core/src/main/scala/chisel3/RawModule.scala @@ -8,7 +8,7 @@ import scala.language.experimental.macros import scala.annotation.nowarn import chisel3.experimental.BaseModule import chisel3.internal._ -import chisel3.internal.BaseModule.{ModuleClone, InstanceClone} +import chisel3.internal.BaseModule.{InstanceClone, ModuleClone} import chisel3.internal.Builder._ import chisel3.internal.firrtl._ import chisel3.internal.sourceinfo.UnlocatableSourceInfo @@ -19,8 +19,7 @@ import _root_.firrtl.annotations.{IsModule, ModuleTarget} * multiple IO() declarations. */ @nowarn("msg=class Port") // delete when Port becomes private -abstract class RawModule(implicit moduleCompileOptions: CompileOptions) - extends BaseModule { +abstract class RawModule(implicit moduleCompileOptions: CompileOptions) extends BaseModule { // // RTL construction internals // @@ -49,19 +48,22 @@ abstract class RawModule(implicit moduleCompileOptions: CompileOptions) port._computeName(None, None).orElse(names.get(port)) match { case Some(name) => if (_namespace.contains(name)) { - Builder.error(s"""Unable to name port $port to "$name" in $this,""" + - " name is already taken by another port!") + Builder.error( + s"""Unable to name port $port to "$name" in $this,""" + + " name is already taken by another port!" + ) } port.setRef(ModuleIO(this, _namespace.name(name))) case None => - Builder.error(s"Unable to name port $port in $this, " + - "try making it a public field of the Module") + Builder.error( + s"Unable to name port $port in $this, " + + "try making it a public field of the Module" + ) port.setRef(ModuleIO(this, "<UNNAMED>")) } } } - private[chisel3] override def generateComponent(): Option[Component] = { require(!_closed, "Can't generate module more than once") _closed = true @@ -79,29 +81,29 @@ abstract class RawModule(implicit moduleCompileOptions: CompileOptions) // All suggestions are in, force names to every node. for (id <- getIds) { id match { - case id: ModuleClone[_] => id.setRefAndPortsRef(_namespace) // special handling + case id: ModuleClone[_] => id.setRefAndPortsRef(_namespace) // special handling case id: InstanceClone[_] => id.setAsInstanceRef() - case id: BaseModule => id.forceName(None, default=id.desiredName, _namespace) - case id: MemBase[_] => id.forceName(None, default="MEM", _namespace) - case id: stop.Stop => id.forceName(None, default="stop", _namespace) - case id: assert.Assert => id.forceName(None, default="assert", _namespace) - case id: assume.Assume => id.forceName(None, default="assume", _namespace) - case id: cover.Cover => id.forceName(None, default="cover", _namespace) - case id: printf.Printf => id.forceName(None, default="printf", _namespace) - case id: Data => + case id: BaseModule => id.forceName(None, default = id.desiredName, _namespace) + case id: MemBase[_] => id.forceName(None, default = "MEM", _namespace) + case id: stop.Stop => id.forceName(None, default = "stop", _namespace) + case id: assert.Assert => id.forceName(None, default = "assert", _namespace) + case id: assume.Assume => id.forceName(None, default = "assume", _namespace) + case id: cover.Cover => id.forceName(None, default = "cover", _namespace) + case id: printf.Printf => id.forceName(None, default = "printf", _namespace) + case id: Data => if (id.isSynthesizable) { id.topBinding match { case OpBinding(_, _) => - id.forceName(Some(""), default="T", _namespace) + id.forceName(Some(""), default = "T", _namespace) case MemoryPortBinding(_, _) => - id.forceName(None, default="MPORT", _namespace) + id.forceName(None, default = "MPORT", _namespace) case PortBinding(_) => - id.forceName(None, default="PORT", _namespace) + id.forceName(None, default = "PORT", _namespace) case RegBinding(_, _) => - id.forceName(None, default="REG", _namespace) + id.forceName(None, default = "REG", _namespace) case WireBinding(_, _) => - id.forceName(Some(""), default="WIRE", _namespace) - case _ => // don't name literals + id.forceName(Some(""), default = "WIRE", _namespace) + case _ => // don't name literals } } // else, don't name unbound types } @@ -110,19 +112,20 @@ abstract class RawModule(implicit moduleCompileOptions: CompileOptions) closeUnboundIds(names) - val firrtlPorts = getModulePorts map { port: Data => + val firrtlPorts = getModulePorts.map { port: Data => // Special case Vec to make FIRRTL emit the direction of its // element. // Just taking the Vec's specifiedDirection is a bug in cases like // Vec(Flipped()), since the Vec's specifiedDirection is // Unspecified. val direction = port match { - case v: Vec[_] => v.specifiedDirection match { - case SpecifiedDirection.Input => SpecifiedDirection.Input - case SpecifiedDirection.Output => SpecifiedDirection.Output - case SpecifiedDirection.Flip => SpecifiedDirection.flip(v.sample_element.specifiedDirection) - case SpecifiedDirection.Unspecified => v.sample_element.specifiedDirection - } + case v: Vec[_] => + v.specifiedDirection match { + case SpecifiedDirection.Input => SpecifiedDirection.Input + case SpecifiedDirection.Output => SpecifiedDirection.Output + case SpecifiedDirection.Flip => SpecifiedDirection.flip(v.sample_element.specifiedDirection) + case SpecifiedDirection.Unspecified => v.sample_element.specifiedDirection + } case _ => port.specifiedDirection } @@ -134,7 +137,7 @@ abstract class RawModule(implicit moduleCompileOptions: CompileOptions) // unless the client wants explicit control over their generation. val invalidateCommands = { if (!compileOptions.explicitInvalidate) { - getModulePorts map { port => DefInvalid(UnlocatableSourceInfo, port.ref) } + getModulePorts.map { port => DefInvalid(UnlocatableSourceInfo, port.ref) } } else { Seq() } @@ -204,13 +207,15 @@ package object internal { .map(_.forceFinalName("io")) .orElse { // Fallback if reflection fails, user can wrap in IO(...) - self.findPort("io") - .collect { case r: Record => r } - }.getOrElse(throwException( - s"Compatibility mode Module '$this' must have a 'val io' Bundle. " + - "If there is such a field and you still see this error, autowrapping has failed (sorry!). " + - "Please wrap the Bundle declaration in IO(...)." - )) + self.findPort("io").collect { case r: Record => r } + } + .getOrElse( + throwException( + s"Compatibility mode Module '$this' must have a 'val io' Bundle. " + + "If there is such a field and you still see this error, autowrapping has failed (sorry!). " + + "Please wrap the Bundle declaration in IO(...)." + ) + ) } /** Legacy Module class that restricts IOs to just io, clock, and reset, and provides a constructor @@ -221,15 +226,19 @@ package object internal { */ abstract class LegacyModule(implicit moduleCompileOptions: CompileOptions) extends Module { // Provide a non-deprecated constructor - def this(override_clock: Option[Clock] = None, override_reset: Option[Bool]=None) - (implicit moduleCompileOptions: CompileOptions) = { + def this( + override_clock: Option[Clock] = None, + override_reset: Option[Bool] = None + )( + implicit moduleCompileOptions: CompileOptions + ) = { this() this.override_clock = override_clock this.override_reset = override_reset } def this(_clock: Clock)(implicit moduleCompileOptions: CompileOptions) = this(Option(_clock), None)(moduleCompileOptions) - def this(_reset: Bool)(implicit moduleCompileOptions: CompileOptions) = + def this(_reset: Bool)(implicit moduleCompileOptions: CompileOptions) = this(None, Option(_reset))(moduleCompileOptions) def this(_clock: Clock, _reset: Bool)(implicit moduleCompileOptions: CompileOptions) = this(Option(_clock), Option(_reset))(moduleCompileOptions) @@ -240,12 +249,15 @@ package object internal { protected def _compatIoPortBound() = portsContains(_io) private[chisel3] override def generateComponent(): Option[Component] = { - _compatAutoWrapPorts() // pre-IO(...) compatibility hack + _compatAutoWrapPorts() // pre-IO(...) compatibility hack // Restrict IO to just io, clock, and reset require(_io != null, "Module must have io") require(portsContains(_io), "Module must have io wrapped in IO(...)") - require((portsContains(clock)) && (portsContains(reset)), "Internal error, module did not have clock or reset as IO") + require( + (portsContains(clock)) && (portsContains(reset)), + "Internal error, module did not have clock or reset as IO" + ) require(portsSize == 3, "Module must only have io, clock, and reset as IO") super.generateComponent() @@ -265,8 +277,10 @@ package object internal { * '''Do not use this class in user code'''. Use whichever `BlackBox` is imported by your wildcard * import (preferably `import chisel3._`). */ - abstract class LegacyBlackBox(params: Map[String, Param] = Map.empty[String, Param]) - (implicit moduleCompileOptions: CompileOptions) + abstract class LegacyBlackBox( + params: Map[String, Param] = Map.empty[String, Param] + )( + implicit moduleCompileOptions: CompileOptions) extends chisel3.BlackBox(params) { override private[chisel3] lazy val _io: Record = reflectivelyFindValIO(this) @@ -305,5 +319,6 @@ package object internal { * * @note this is a val instead of an object because of the need to wrap in Module(...) */ - private[chisel3] val ViewParent = Module.do_apply(new ViewParentAPI)(UnlocatableSourceInfo, ExplicitCompileOptions.Strict) + private[chisel3] val ViewParent = + Module.do_apply(new ViewParentAPI)(UnlocatableSourceInfo, ExplicitCompileOptions.Strict) } diff --git a/core/src/main/scala/chisel3/Reg.scala b/core/src/main/scala/chisel3/Reg.scala index 122c5ebd..204beb79 100644 --- a/core/src/main/scala/chisel3/Reg.scala +++ b/core/src/main/scala/chisel3/Reg.scala @@ -27,9 +27,9 @@ import chisel3.internal.sourceinfo.SourceInfo * // Width of r4.unknown is inferred * // Width of r4.known is set to 8 * }}} - * */ object Reg { + /** Construct a [[Reg]] from a type template with no initialization value (reset is ignored). * Value will not change unless the [[Reg]] is given a connection. * @param t The template from which to construct this wire @@ -74,6 +74,7 @@ object Reg { * }}} */ object RegNext { + /** Returns a register ''with an unset width'' connected to the signal `next` and with no reset value. */ def apply[T <: Data](next: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = { val model = (next match { @@ -94,7 +95,7 @@ object RegNext { case next: Bits => next.cloneTypeWidth(Width()) case next => next.cloneTypeFull }).asInstanceOf[T] - val reg = RegInit(model, init) // TODO: this makes NO sense + val reg = RegInit(model, init) // TODO: this makes NO sense requireIsHardware(next, "reg next") reg := next @@ -162,6 +163,7 @@ object RegNext { * }}} */ object RegInit { + /** Construct a [[Reg]] from a type template initialized to the specified value on reset * @param t The type template used to construct this [[Reg]] * @param init The value the [[Reg]] is initialized to on reset diff --git a/core/src/main/scala/chisel3/SIntFactory.scala b/core/src/main/scala/chisel3/SIntFactory.scala index b34c7dde..3fafacda 100644 --- a/core/src/main/scala/chisel3/SIntFactory.scala +++ b/core/src/main/scala/chisel3/SIntFactory.scala @@ -5,8 +5,10 @@ package chisel3 import chisel3.internal.firrtl.{IntervalRange, SLit, Width} 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) diff --git a/core/src/main/scala/chisel3/SeqUtils.scala b/core/src/main/scala/chisel3/SeqUtils.scala index 5c86efd3..b1136120 100644 --- a/core/src/main/scala/chisel3/SeqUtils.scala +++ b/core/src/main/scala/chisel3/SeqUtils.scala @@ -10,6 +10,7 @@ import chisel3.internal.sourceinfo._ import chisel3.internal.plugin.autoNameRecursively private[chisel3] object SeqUtils { + /** Concatenates the data elements of the input sequence, in sequence order, together. * The first element of the sequence forms the least significant bits, while the last element * in the sequence forms the most significant bits. @@ -27,10 +28,10 @@ private[chisel3] object SeqUtils { in.head.asUInt } else { val lo = autoNameRecursively("lo")(prefix("lo") { - asUInt(in.slice(0, in.length/2)) + asUInt(in.slice(0, in.length / 2)) }) val hi = autoNameRecursively("hi")(prefix("hi") { - asUInt(in.slice(in.length/2, in.length)) + asUInt(in.slice(in.length / 2, in.length)) }) hi ## lo } @@ -45,7 +46,7 @@ private[chisel3] object SeqUtils { case 0 => 0.U case 1 => in.head case n => - val sum = count(in take n/2) +& count(in drop n/2) + val sum = count(in.take(n / 2)) +& count(in.drop(n / 2)) sum(BigInt(n).bitLength - 1, 0) } @@ -54,8 +55,12 @@ private[chisel3] object SeqUtils { def priorityMux[T <: Data](in: Seq[(Bool, T)]): T = macro SourceInfoTransform.inArg /** @group SourceInfoTransformMacros */ - def do_priorityMux[T <: Data](in: Seq[(Bool, T)]) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = { + def do_priorityMux[T <: Data]( + in: Seq[(Bool, T)] + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): T = { if (in.size == 1) { in.head._2 } else { @@ -72,13 +77,16 @@ private[chisel3] object SeqUtils { def oneHotMux[T <: Data](in: Iterable[(Bool, T)]): T = macro SourceInfoTransform.inArg /** @group SourceInfoTransformMacros */ - def do_oneHotMux[T <: Data](in: Iterable[(Bool, T)]) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = { + def do_oneHotMux[T <: Data]( + in: Iterable[(Bool, T)] + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): T = { if (in.tail.isEmpty) { in.head._2 - } - else { - val output = cloneSupertype(in.toSeq map { _._2}, "oneHotMux") + } else { + val output = cloneSupertype(in.toSeq.map { _._2 }, "oneHotMux") def buildAndOrMultiplexor[TT <: Data](inputs: Iterable[(Bool, TT)]): T = { val masked = for ((s, i) <- inputs) yield Mux(s, i.asUInt, 0.U) @@ -89,8 +97,9 @@ private[chisel3] object SeqUtils { case _: SInt => // SInt's have to be managed carefully so sign extension works - val sInts: Iterable[(Bool, SInt)] = in.collect { case (s: Bool, f: SInt) => - (s, f.asTypeOf(output).asInstanceOf[SInt]) + val sInts: Iterable[(Bool, SInt)] = in.collect { + case (s: Bool, f: SInt) => + (s, f.asTypeOf(output).asInstanceOf[SInt]) } val masked = for ((s, i) <- sInts) yield Mux(s, i, 0.S) @@ -99,20 +108,20 @@ private[chisel3] object SeqUtils { case _: FixedPoint => val (sels, possibleOuts) = in.toSeq.unzip - val (intWidths, binaryPoints) = in.toSeq.map { case (_, o) => - val fo = o.asInstanceOf[FixedPoint] - require(fo.binaryPoint.known, "Mux1H requires width/binary points to be defined") - (fo.getWidth - fo.binaryPoint.get, fo.binaryPoint.get) + val (intWidths, binaryPoints) = in.toSeq.map { + case (_, o) => + val fo = o.asInstanceOf[FixedPoint] + require(fo.binaryPoint.known, "Mux1H requires width/binary points to be defined") + (fo.getWidth - fo.binaryPoint.get, fo.binaryPoint.get) }.unzip if (intWidths.distinct.length == 1 && binaryPoints.distinct.length == 1) { buildAndOrMultiplexor(in) - } - else { + } else { val maxIntWidth = intWidths.max val maxBP = binaryPoints.max val inWidthMatched = Seq.fill(intWidths.length)(Wire(FixedPoint((maxIntWidth + maxBP).W, maxBP.BP))) - inWidthMatched.zipWithIndex foreach { case (e, idx) => e := possibleOuts(idx).asInstanceOf[FixedPoint] } + inWidthMatched.zipWithIndex.foreach { case (e, idx) => e := possibleOuts(idx).asInstanceOf[FixedPoint] } buildAndOrMultiplexor(sels.zip(inWidthMatched)) } @@ -123,12 +132,12 @@ private[chisel3] object SeqUtils { val (sel, inData) = in.unzip val inElts = inData.map(_.asInstanceOf[Aggregate].getElements) // We want to iterate on the columns of inElts, so we transpose - out.getElements.zip(inElts.transpose).foreach { case (outElt, elts) => - outElt := oneHotMux(sel.zip(elts)) + out.getElements.zip(inElts.transpose).foreach { + case (outElt, elts) => + outElt := oneHotMux(sel.zip(elts)) } out.asInstanceOf[T] - } - else { + } else { throwException(s"Cannot Mux1H with aggregates with inferred widths") } diff --git a/core/src/main/scala/chisel3/StrongEnum.scala b/core/src/main/scala/chisel3/StrongEnum.scala index fa420e80..6f9cce55 100644 --- a/core/src/main/scala/chisel3/StrongEnum.scala +++ b/core/src/main/scala/chisel3/StrongEnum.scala @@ -10,11 +10,11 @@ import chisel3.internal.Builder.pushOp import chisel3.internal.firrtl.PrimOp._ import chisel3.internal.firrtl._ import chisel3.internal.sourceinfo._ -import chisel3.internal.{Binding, Builder, ChildBinding, ConstrainedBinding, InstanceId, throwException} +import chisel3.internal.{throwException, Binding, Builder, ChildBinding, ConstrainedBinding, InstanceId} import firrtl.annotations._ - object EnumAnnotations { + /** An annotation for strong enum instances that are ''not'' inside of Vecs * * @param target the enum instance being annotated @@ -31,7 +31,7 @@ object EnumAnnotations { /** An annotation for Vecs of strong enums. * * The ''fields'' parameter deserves special attention, since it may be difficult to understand. Suppose you create a the following Vec: - + * * {{{ * VecInit(new Bundle { * val e = MyEnum() @@ -47,13 +47,14 @@ object EnumAnnotations { * @param target the Vec being annotated * @param typeName the name of the enum's type (e.g. ''"mypackage.MyEnum"'') * @param fields a list of all chains of elements leading from the Vec instance to its inner enum fields. - * */ - case class EnumVecAnnotation(target: Named, typeName: String, fields: Seq[Seq[String]]) extends SingleTargetAnnotation[Named] { + case class EnumVecAnnotation(target: Named, typeName: String, fields: Seq[Seq[String]]) + extends SingleTargetAnnotation[Named] { def duplicate(n: Named): EnumVecAnnotation = this.copy(target = n) } - case class EnumVecChiselAnnotation(target: InstanceId, typeName: String, fields: Seq[Seq[String]]) extends ChiselAnnotation { + case class EnumVecChiselAnnotation(target: InstanceId, typeName: String, fields: Seq[Seq[String]]) + extends ChiselAnnotation { override def toFirrtl: EnumVecAnnotation = EnumVecAnnotation(target.toNamed, typeName, fields) } @@ -70,7 +71,6 @@ object EnumAnnotations { } import EnumAnnotations._ - abstract class EnumType(private val factory: EnumFactory, selfAnnotating: Boolean = true) extends Element { // Use getSimpleName instead of enumTypeName because for debugging purposes @@ -78,10 +78,11 @@ abstract class EnumType(private val factory: EnumFactory, selfAnnotating: Boolea // Enum annotation), and it's more consistent with Bundle printing. override def toString: String = { litOption match { - case Some(value) => factory.nameOfValue(value) match { - case Some(name) => s"${factory.getClass.getSimpleName.init}($value=$name)" - case None => stringAccessor(s"${factory.getClass.getSimpleName.init}($value=(invalid))") - } + case Some(value) => + factory.nameOfValue(value) match { + case Some(name) => s"${factory.getClass.getSimpleName.init}($value=$name)" + case None => stringAccessor(s"${factory.getClass.getSimpleName.init}($value=(invalid))") + } case _ => stringAccessor(s"${factory.getClass.getSimpleName.init}") } } @@ -92,7 +93,7 @@ abstract class EnumType(private val factory: EnumFactory, selfAnnotating: Boolea requireIsHardware(this, "bits operated on") requireIsHardware(other, "bits operated on") - if(!this.typeEquivalent(other)) { + if (!this.typeEquivalent(other)) { throwException(s"Enum types are not equivalent: ${this.enumTypeName}, ${other.enumTypeName}") } @@ -104,24 +105,34 @@ abstract class EnumType(private val factory: EnumFactory, selfAnnotating: Boolea this.factory == that.asInstanceOf[EnumType].factory } - private[chisel3] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, - compileOptions: CompileOptions): Unit = { + private[chisel3] override def connectFromBits( + that: Bits + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Unit = { this := factory.apply(that.asUInt) } - final def === (that: EnumType): Bool = macro SourceInfoTransform.thatArg - final def =/= (that: EnumType): Bool = macro SourceInfoTransform.thatArg - final def < (that: EnumType): Bool = macro SourceInfoTransform.thatArg - final def <= (that: EnumType): Bool = macro SourceInfoTransform.thatArg - final def > (that: EnumType): Bool = macro SourceInfoTransform.thatArg - final def >= (that: EnumType): Bool = macro SourceInfoTransform.thatArg - - def do_=== (that: EnumType)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, EqualOp, that) - def do_=/= (that: EnumType)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, NotEqualOp, that) - def do_< (that: EnumType)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, LessOp, that) - def do_> (that: EnumType)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, GreaterOp, that) - def do_<= (that: EnumType)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, LessEqOp, that) - def do_>= (that: EnumType)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, GreaterEqOp, that) + final def ===(that: EnumType): Bool = macro SourceInfoTransform.thatArg + final def =/=(that: EnumType): Bool = macro SourceInfoTransform.thatArg + final def <(that: EnumType): Bool = macro SourceInfoTransform.thatArg + final def <=(that: EnumType): Bool = macro SourceInfoTransform.thatArg + final def >(that: EnumType): Bool = macro SourceInfoTransform.thatArg + final def >=(that: EnumType): Bool = macro SourceInfoTransform.thatArg + + def do_===(that: EnumType)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + compop(sourceInfo, EqualOp, that) + def do_=/=(that: EnumType)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + compop(sourceInfo, NotEqualOp, that) + def do_<(that: EnumType)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + compop(sourceInfo, LessOp, that) + def do_>(that: EnumType)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + compop(sourceInfo, GreaterOp, that) + def do_<=(that: EnumType)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + compop(sourceInfo, LessEqOp, that) + def do_>=(that: EnumType)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = + compop(sourceInfo, GreaterEqOp, that) override def do_asUInt(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = pushOp(DefPrim(sourceInfo, UInt(width), AsUIntOp, ref)) @@ -151,21 +162,26 @@ abstract class EnumType(private val factory: EnumFactory, selfAnnotating: Boolea * @param u2 zero or more additional values to look for * @return a hardware [[Bool]] that indicates if this value matches any of the given values */ - final def isOneOf(u1: EnumType, u2: EnumType*)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool - = isOneOf(u1 +: u2.toSeq) + final def isOneOf( + u1: EnumType, + u2: EnumType* + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Bool = isOneOf(u1 +: u2.toSeq) def next(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): this.type = { if (litOption.isDefined) { val index = factory.all.indexOf(this) - if (index < factory.all.length-1) { + if (index < factory.all.length - 1) { factory.all(index + 1).asInstanceOf[this.type] } else { factory.all.head.asInstanceOf[this.type] } } else { - val enums_with_nexts = factory.all zip (factory.all.tail :+ factory.all.head) - val next_enum = SeqUtils.priorityMux(enums_with_nexts.map { case (e,n) => (this === e, n) } ) + val enums_with_nexts = factory.all.zip(factory.all.tail :+ factory.all.head) + val next_enum = SeqUtils.priorityMux(enums_with_nexts.map { case (e, n) => (this === e, n) }) next_enum.asInstanceOf[this.type] } } @@ -175,7 +191,10 @@ abstract class EnumType(private val factory: EnumFactory, selfAnnotating: Boolea lit.bindLitArg(this) } - override private[chisel3] def bind(target: Binding, parentDirection: SpecifiedDirection = SpecifiedDirection.Unspecified): Unit = { + override private[chisel3] def bind( + target: Binding, + parentDirection: SpecifiedDirection = SpecifiedDirection.Unspecified + ): Unit = { super.bind(target, parentDirection) // Make sure we only annotate hardware and not literals @@ -186,10 +205,11 @@ abstract class EnumType(private val factory: EnumFactory, selfAnnotating: Boolea // This function conducts a depth-wise search to find all enum-type fields within a vector or bundle (or vector of bundles) private def enumFields(d: Aggregate): Seq[Seq[String]] = d match { - case v: Vec[_] => v.sample_element match { - case b: Bundle => enumFields (b) - case _ => Seq () - } + case v: Vec[_] => + v.sample_element match { + case b: Bundle => enumFields(b) + case _ => Seq() + } case b: Bundle => b.elements.collect { case (name, e: EnumType) if this.typeEquivalent(e) => Seq(Seq(name)) @@ -205,10 +225,11 @@ abstract class EnumType(private val factory: EnumFactory, selfAnnotating: Boolea } d.binding match { - case Some(ChildBinding(parent)) => outerMostVec(parent) match { - case outer @ Some(_) => outer - case None => currentVecOpt - } + case Some(ChildBinding(parent)) => + outerMostVec(parent) match { + case outer @ Some(_) => outer + case None => currentVecOpt + } case _ => currentVecOpt } } @@ -216,7 +237,7 @@ abstract class EnumType(private val factory: EnumFactory, selfAnnotating: Boolea private def annotateEnum(): Unit = { val anno = outerMostVec() match { case Some(v) => EnumVecChiselAnnotation(v, enumTypeName, enumFields(v)) - case None => EnumComponentChiselAnnotation(this, enumTypeName) + case None => EnumComponentChiselAnnotation(this, enumTypeName) } if (!Builder.annotations.contains(anno)) { @@ -233,14 +254,13 @@ abstract class EnumType(private val factory: EnumFactory, selfAnnotating: Boolea def toPrintable: Printable = FullName(this) // TODO: Find a better pretty printer } - abstract class EnumFactory { class Type extends EnumType(this) object Type { def apply(): Type = EnumFactory.this.apply() } - private var id: BigInt = 0 + private var id: BigInt = 0 private[chisel3] var width: Width = 0.W private case class EnumRecord(inst: Type, name: String) @@ -255,7 +275,7 @@ abstract class EnumFactory { // Do all bitvectors of this Enum's width represent legal states? private[chisel3] def isTotal: Boolean = { (this.getWidth < 31) && // guard against Integer overflow - (enumRecords.size == (1 << this.getWidth)) + (enumRecords.size == (1 << this.getWidth)) } private[chisel3] def globalAnnotation: EnumDefChiselAnnotation = @@ -280,7 +300,7 @@ abstract class EnumFactory { enumRecords.append(EnumRecord(result, name)) - width = (1 max id.bitLength).W + width = (1.max(id.bitLength)).W id += 1 result @@ -302,11 +322,17 @@ abstract class EnumFactory { def apply(): Type = new Type - private def castImpl(n: UInt, warn: Boolean)(implicit sourceInfo: SourceInfo, connectionCompileOptions: CompileOptions): Type = { + private def castImpl( + n: UInt, + warn: Boolean + )( + implicit sourceInfo: SourceInfo, + connectionCompileOptions: CompileOptions + ): Type = { if (n.litOption.isDefined) { enumInstances.find(_.litValue == n.litValue) match { case Some(result) => result - case None => throwException(s"${n.litValue} is not a valid value for $enumTypeName") + case None => throwException(s"${n.litValue} is not a valid value for $enumTypeName") } } else if (!n.isWidthKnown) { throwException(s"Non-literal UInts being cast to $enumTypeName must have a defined width") @@ -314,7 +340,9 @@ abstract class EnumFactory { throwException(s"The UInt being cast to $enumTypeName is wider than $enumTypeName's width ($getWidth)") } else { if (warn && !this.isTotal) { - Builder.warning(s"Casting non-literal UInt to $enumTypeName. You can use $enumTypeName.safe to cast without this warning.") + Builder.warning( + s"Casting non-literal UInt to $enumTypeName. You can use $enumTypeName.safe to cast without this warning." + ) } val glue = Wire(new UnsafeEnum(width)) glue := n @@ -330,7 +358,8 @@ abstract class EnumFactory { * @param n the UInt to cast * @return the equivalent Enum to the value of the cast UInt */ - def apply(n: UInt)(implicit sourceInfo: SourceInfo, connectionCompileOptions: CompileOptions): Type = castImpl(n, warn = true) + def apply(n: UInt)(implicit sourceInfo: SourceInfo, connectionCompileOptions: CompileOptions): Type = + castImpl(n, warn = true) /** Safely cast an [[UInt]] to the type of this Enum * @@ -344,9 +373,8 @@ abstract class EnumFactory { } } - private[chisel3] object EnumMacros { - def ValImpl(c: Context) : c.Tree = { + def ValImpl(c: Context): c.Tree = { import c.universe._ // Much thanks to michael_s for this solution: @@ -375,7 +403,6 @@ private[chisel3] object EnumMacros { } } - // This is an enum type that can be connected directly to UInts. It is used as a "glue" to cast non-literal UInts // to enums. private[chisel3] class UnsafeEnum(override val width: Width) extends EnumType(UnsafeEnum, selfAnnotating = false) { diff --git a/core/src/main/scala/chisel3/UIntFactory.scala b/core/src/main/scala/chisel3/UIntFactory.scala index e0f3dc92..64127991 100644 --- a/core/src/main/scala/chisel3/UIntFactory.scala +++ b/core/src/main/scala/chisel3/UIntFactory.scala @@ -9,8 +9,10 @@ import firrtl.ir.{Closed, IntWidth, Open} // This is currently a factory because both Bits and UInt inherit it. 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) @@ -21,6 +23,7 @@ trait UIntFactory { // Bind result to being an Literal lit.bindLitArg(result) } + /** Create a UInt with the specified range, validate that range is effectively > 0 */ def apply(range: IntervalRange): UInt = { @@ -34,8 +37,8 @@ trait UIntFactory { } // because this is a UInt we don't have to take into account the lower bound - val newWidth = if(range.upperBound.isInstanceOf[IsKnown]) { - KnownWidth(Utils.getUIntWidth(range.maxAdjusted.get).max(1)) // max(1) handles range"[0,0]" + val newWidth = if (range.upperBound.isInstanceOf[IsKnown]) { + KnownWidth(Utils.getUIntWidth(range.maxAdjusted.get).max(1)) // max(1) handles range"[0,0]" } else { UnknownWidth() } diff --git a/core/src/main/scala/chisel3/VerificationStatement.scala b/core/src/main/scala/chisel3/VerificationStatement.scala index 23adc192..bfdfc26e 100644 --- a/core/src/main/scala/chisel3/VerificationStatement.scala +++ b/core/src/main/scala/chisel3/VerificationStatement.scala @@ -12,6 +12,7 @@ import chisel3.internal.sourceinfo.SourceInfo import scala.reflect.macros.blackbox object assert { + /** Checks for a condition to be valid in the circuit at all times. If the * condition evaluates to false, the circuit simulation stops with an error. * @@ -33,34 +34,62 @@ object assert { * that */ // Macros currently can't take default arguments, so we need two functions to emulate defaults. - def apply(cond: Bool, message: String, data: Bits*)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Assert = macro _applyMacroWithMessage - def apply(cond: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Assert = macro _applyMacroWithNoMessage + def apply( + cond: Bool, + message: String, + data: Bits* + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Assert = macro _applyMacroWithMessage + def apply(cond: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Assert = + macro _applyMacroWithNoMessage /** An elaboration-time assertion. Calls the built-in Scala assert function. */ def apply(cond: Boolean, message: => String): Unit = Predef.assert(cond, message) + /** An elaboration-time assertion. Calls the built-in Scala assert function. */ def apply(cond: Boolean): Unit = Predef.assert(cond, "") /** Named class for assertions. */ - final class Assert private[chisel3]() extends VerificationStatement + final class Assert private[chisel3] () extends VerificationStatement import VerificationStatement._ - def _applyMacroWithMessage(c: blackbox.Context)(cond: c.Tree, message: c.Tree, data: c.Tree*)(sourceInfo: c.Tree, compileOptions: c.Tree): c.Tree = { + def _applyMacroWithMessage( + c: blackbox.Context + )(cond: c.Tree, + message: c.Tree, + data: c.Tree* + )(sourceInfo: c.Tree, + compileOptions: c.Tree + ): c.Tree = { import c.universe._ val apply_impl_do = symbolOf[this.type].asClass.module.info.member(TermName("_applyWithSourceLine")) q"$apply_impl_do($cond, ${getLine(c)}, _root_.scala.Some($message), ..$data)($sourceInfo, $compileOptions)" } - def _applyMacroWithNoMessage(c: blackbox.Context)(cond: c.Tree)(sourceInfo: c.Tree, compileOptions: c.Tree): c.Tree = { + def _applyMacroWithNoMessage( + c: blackbox.Context + )(cond: c.Tree + )(sourceInfo: c.Tree, + compileOptions: c.Tree + ): c.Tree = { import c.universe._ val apply_impl_do = symbolOf[this.type].asClass.module.info.member(TermName("_applyWithSourceLine")) q"$apply_impl_do($cond, ${getLine(c)}, _root_.scala.None)($sourceInfo, $compileOptions)" } /** Used by our macros. Do not call directly! */ - def _applyWithSourceLine(cond: Bool, line: SourceLineInfo, message: Option[String], data: Bits*) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Assert = { + def _applyWithSourceLine( + cond: Bool, + line: SourceLineInfo, + message: Option[String], + data: Bits* + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Assert = { val id = new Assert() when(!Module.reset.asBool()) { Builder.pushCommand(Verification(id, Formal.Assert, sourceInfo, Module.clock.ref, cond.ref, "")) @@ -70,8 +99,8 @@ object assert { } } - object assume { + /** Assumes a condition to be valid in the circuit at all times. * Acts like an assertion in simulation and imposes a declarative * assumption on the state explored by formal tools. @@ -91,34 +120,62 @@ object assume { * @note See [[printf.apply(fmt:String* printf]] for format string documentation */ // Macros currently can't take default arguments, so we need two functions to emulate defaults. - def apply(cond: Bool, message: String, data: Bits*)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Assume = macro _applyMacroWithMessage - def apply(cond: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Assume = macro _applyMacroWithNoMessage + def apply( + cond: Bool, + message: String, + data: Bits* + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Assume = macro _applyMacroWithMessage + def apply(cond: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Assume = + macro _applyMacroWithNoMessage /** An elaboration-time assumption. Calls the built-in Scala assume function. */ def apply(cond: Boolean, message: => String): Unit = Predef.assume(cond, message) + /** An elaboration-time assumption. Calls the built-in Scala assume function. */ def apply(cond: Boolean): Unit = Predef.assume(cond, "") /** Named class for assumptions. */ - final class Assume private[chisel3]() extends VerificationStatement + final class Assume private[chisel3] () extends VerificationStatement import VerificationStatement._ - def _applyMacroWithMessage(c: blackbox.Context)(cond: c.Tree, message: c.Tree, data: c.Tree*)(sourceInfo: c.Tree, compileOptions: c.Tree): c.Tree = { + def _applyMacroWithMessage( + c: blackbox.Context + )(cond: c.Tree, + message: c.Tree, + data: c.Tree* + )(sourceInfo: c.Tree, + compileOptions: c.Tree + ): c.Tree = { import c.universe._ val apply_impl_do = symbolOf[this.type].asClass.module.info.member(TermName("_applyWithSourceLine")) q"$apply_impl_do($cond, ${getLine(c)}, _root_.scala.Some($message), ..$data)($sourceInfo, $compileOptions)" } - def _applyMacroWithNoMessage(c: blackbox.Context)(cond: c.Tree)(sourceInfo: c.Tree, compileOptions: c.Tree): c.Tree = { + def _applyMacroWithNoMessage( + c: blackbox.Context + )(cond: c.Tree + )(sourceInfo: c.Tree, + compileOptions: c.Tree + ): c.Tree = { import c.universe._ val apply_impl_do = symbolOf[this.type].asClass.module.info.member(TermName("_applyWithSourceLine")) q"$apply_impl_do($cond, ${getLine(c)}, _root_.scala.None)($sourceInfo, $compileOptions)" } /** Used by our macros. Do not call directly! */ - def _applyWithSourceLine(cond: Bool, line: SourceLineInfo, message: Option[String], data: Bits*) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Assume = { + def _applyWithSourceLine( + cond: Bool, + line: SourceLineInfo, + message: Option[String], + data: Bits* + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Assume = { val id = new Assume() when(!Module.reset.asBool()) { Builder.pushCommand(Verification(id, Formal.Assume, sourceInfo, Module.clock.ref, cond.ref, "")) @@ -128,8 +185,8 @@ object assume { } } - object cover { + /** Declares a condition to be covered. * At ever clock event, a counter is incremented iff the condition is active * and reset is inactive. @@ -146,29 +203,48 @@ object cover { * @param message a string describing the cover event */ // Macros currently can't take default arguments, so we need two functions to emulate defaults. - def apply(cond: Bool, message: String)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Cover = macro _applyMacroWithMessage - def apply(cond: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Cover = macro _applyMacroWithNoMessage + def apply(cond: Bool, message: String)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Cover = + macro _applyMacroWithMessage + def apply(cond: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Cover = + macro _applyMacroWithNoMessage /** Named class for cover statements. */ - final class Cover private[chisel3]() extends VerificationStatement + final class Cover private[chisel3] () extends VerificationStatement import VerificationStatement._ - def _applyMacroWithNoMessage(c: blackbox.Context)(cond: c.Tree)(sourceInfo: c.Tree, compileOptions: c.Tree): c.Tree = { + def _applyMacroWithNoMessage( + c: blackbox.Context + )(cond: c.Tree + )(sourceInfo: c.Tree, + compileOptions: c.Tree + ): c.Tree = { import c.universe._ val apply_impl_do = symbolOf[this.type].asClass.module.info.member(TermName("_applyWithSourceLine")) q"$apply_impl_do($cond, ${getLine(c)}, _root_.scala.None)($sourceInfo, $compileOptions)" } - def _applyMacroWithMessage(c: blackbox.Context)(cond: c.Tree, message: c.Tree)(sourceInfo: c.Tree, compileOptions: c.Tree): c.Tree = { + def _applyMacroWithMessage( + c: blackbox.Context + )(cond: c.Tree, + message: c.Tree + )(sourceInfo: c.Tree, + compileOptions: c.Tree + ): c.Tree = { import c.universe._ val apply_impl_do = symbolOf[this.type].asClass.module.info.member(TermName("_applyWithSourceLine")) q"$apply_impl_do($cond, ${getLine(c)}, _root_.scala.Some($message))($sourceInfo, $compileOptions)" } /** Used by our macros. Do not call directly! */ - def _applyWithSourceLine(cond: Bool, line: SourceLineInfo, message: Option[String]) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Cover = { + def _applyWithSourceLine( + cond: Bool, + line: SourceLineInfo, + message: Option[String] + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Cover = { val id = new Cover() when(!Module.reset.asBool()) { Builder.pushCommand(Verification(id, Formal.Cover, sourceInfo, Module.clock.ref, cond.ref, "")) @@ -178,30 +254,34 @@ object cover { } object stop { + /** Terminate execution, indicating success. * * @param message a string describing why the simulation was stopped */ def apply(message: String = "")(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Stop = { val stp = new Stop() - when (!Module.reset.asBool) { + when(!Module.reset.asBool) { pushCommand(Stop(stp, sourceInfo, Builder.forcedClock.ref, 0)) } stp } /** Terminate execution with a failure code. */ - @deprecated("Non-zero return codes are not well supported. Please use assert(false.B) if you want to indicate a failure.", "Chisel 3.5") + @deprecated( + "Non-zero return codes are not well supported. Please use assert(false.B) if you want to indicate a failure.", + "Chisel 3.5" + ) def apply(code: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Stop = { val stp = new Stop() - when (!Module.reset.asBool) { + when(!Module.reset.asBool) { pushCommand(Stop(stp, sourceInfo, Builder.forcedClock.ref, code)) } stp } /** Named class for [[stop]]s. */ - final class Stop private[chisel3]()extends VerificationStatement + final class Stop private[chisel3] () extends VerificationStatement } /** Base class for all verification statements: Assert, Assume, Cover, Stop and Printf. */ @@ -220,8 +300,16 @@ private object VerificationStatement { } // creates a printf to inform the user of a failed assertion or assumption - def failureMessage(kind: String, lineInfo: SourceLineInfo, cond: Bool, message: Option[String], data: Seq[Bits]) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) : Unit = { + def failureMessage( + kind: String, + lineInfo: SourceLineInfo, + cond: Bool, + message: Option[String], + data: Seq[Bits] + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Unit = { val (filename, line, content) = lineInfo val lineMsg = s"$filename:$line $content".replaceAll("%", "%%") val fmt = message match { @@ -230,7 +318,7 @@ private object VerificationStatement { case None => s"$kind failed\n at $lineMsg\n" } when(!cond) { - printf.printfWithoutReset(fmt, data:_*) + printf.printfWithoutReset(fmt, data: _*) } } } diff --git a/core/src/main/scala/chisel3/When.scala b/core/src/main/scala/chisel3/When.scala index ca383c0f..727d8d0c 100644 --- a/core/src/main/scala/chisel3/When.scala +++ b/core/src/main/scala/chisel3/When.scala @@ -9,6 +9,7 @@ import chisel3.internal.firrtl._ import chisel3.internal.sourceinfo.{SourceInfo, UnlocatableSourceInfo} object when { + /** Create a `when` condition block, where whether a block of logic is * executed or not depends on the conditional. * @@ -27,7 +28,13 @@ object when { * }}} */ - def apply(cond: => Bool)(block: => Any)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): WhenContext = { + def apply( + cond: => Bool + )(block: => Any + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): WhenContext = { new WhenContext(sourceInfo, Some(() => cond), block, 0, Nil) } @@ -44,7 +51,7 @@ object when { * } * } * }}} - * */ + */ def cond: Bool = { implicit val compileOptions = ExplicitCompileOptions.Strict implicit val sourceInfo = UnlocatableSourceInfo @@ -66,13 +73,12 @@ object when { * added by preprocessing the command queue. */ final class WhenContext private[chisel3] ( - sourceInfo: SourceInfo, - cond: Option[() => Bool], - block: => Any, + sourceInfo: SourceInfo, + cond: Option[() => Bool], + block: => Any, firrtlDepth: Int, // For capturing conditions from prior whens or elsewhens - altConds: List[() => Bool] -) { + altConds: List[() => Bool]) { @deprecated("Use when(...) { ... }, this should never have been public", "Chisel 3.4.2") def this(sourceInfo: SourceInfo, cond: Option[() => Bool], block: => Any, firrtlDepth: Int = 0) = @@ -87,8 +93,9 @@ final class WhenContext private[chisel3] ( val alt = altConds.foldRight(true.B) { case (c, acc) => acc & !c() } - cond.map(alt && _()) - .getOrElse(alt) + cond + .map(alt && _()) + .getOrElse(alt) } /** This block of logic gets executed if above conditions have been @@ -97,7 +104,13 @@ final class WhenContext private[chisel3] ( * declaration and assignment of the Bool node of the predicate in * the correct place. */ - def elsewhen (elseCond: => Bool)(block: => Any)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): WhenContext = { + def elsewhen( + elseCond: => Bool + )(block: => Any + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): WhenContext = { new WhenContext(sourceInfo, Some(() => elseCond), block, firrtlDepth + 1, cond ++: altConds) } @@ -113,26 +126,30 @@ final class WhenContext private[chisel3] ( def active: Boolean = scopeOpen - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) def active(dummy: Int*): Boolean = active /* * */ if (firrtlDepth > 0) { pushCommand(AltBegin(sourceInfo)) } - cond.foreach( c => pushCommand(WhenBegin(sourceInfo, c().ref)) ) + cond.foreach(c => pushCommand(WhenBegin(sourceInfo, c().ref))) Builder.pushWhen(this) try { scopeOpen = true block } catch { case _: scala.runtime.NonLocalReturnControl[_] => - throwException("Cannot exit from a when() block with a \"return\"!" + - " Perhaps you meant to use Mux or a Wire as a return value?" + throwException( + "Cannot exit from a when() block with a \"return\"!" + + " Perhaps you meant to use Mux or a Wire as a return value?" ) } scopeOpen = false Builder.popWhen() - cond.foreach(_ => pushCommand(WhenEnd(sourceInfo,firrtlDepth))) - if (cond.isEmpty) { pushCommand(OtherwiseEnd(sourceInfo,firrtlDepth)) } + cond.foreach(_ => pushCommand(WhenEnd(sourceInfo, firrtlDepth))) + if (cond.isEmpty) { pushCommand(OtherwiseEnd(sourceInfo, firrtlDepth)) } } diff --git a/core/src/main/scala/chisel3/aop/Aspect.scala b/core/src/main/scala/chisel3/aop/Aspect.scala index be9b8975..dd014357 100644 --- a/core/src/main/scala/chisel3/aop/Aspect.scala +++ b/core/src/main/scala/chisel3/aop/Aspect.scala @@ -12,10 +12,12 @@ import firrtl.AnnotationSeq * @tparam T Type of top-level module */ abstract class Aspect[T <: RawModule] extends Annotation with Unserializable with NoTargetAnnotation { + /** variable to save [[AnnotationSeq]] from [[chisel3.stage.phases.AspectPhase]] * to be used at [[chisel3.aop.injecting.InjectorAspect]], exposes annotations to [[chisel3.internal.DynamicContext]] */ private[aop] var annotationsInAspect: AnnotationSeq = Seq() + /** Convert this Aspect to a seq of FIRRTL annotation * @param top * @return diff --git a/core/src/main/scala/chisel3/dontTouch.scala b/core/src/main/scala/chisel3/dontTouch.scala index e679f1a4..dc998ff5 100644 --- a/core/src/main/scala/chisel3/dontTouch.scala +++ b/core/src/main/scala/chisel3/dontTouch.scala @@ -2,7 +2,7 @@ package chisel3 -import chisel3.experimental.{ChiselAnnotation, annotate, requireIsHardware} +import chisel3.experimental.{annotate, requireIsHardware, ChiselAnnotation} import firrtl.transforms.DontTouchAnnotation /** Marks that a signal is an optimization barrier to Chisel and the FIRRTL compiler. This has the effect of @@ -26,6 +26,7 @@ import firrtl.transforms.DontTouchAnnotation * dontTouch. */ object dontTouch { + /** Mark a signal as an optimization barrier to Chisel and FIRRTL. * * @note Requires the argument to be bound to hardware diff --git a/core/src/main/scala/chisel3/experimental/Analog.scala b/core/src/main/scala/chisel3/experimental/Analog.scala index e94bae2d..a366f0c3 100644 --- a/core/src/main/scala/chisel3/experimental/Analog.scala +++ b/core/src/main/scala/chisel3/experimental/Analog.scala @@ -5,7 +5,18 @@ package chisel3.experimental import chisel3.internal.firrtl.Width import chisel3.internal.sourceinfo.SourceInfo import chisel3.internal._ -import chisel3.{ActualDirection, Bits, CompileOptions, Data, Element, PString, Printable, RawModule, SpecifiedDirection, UInt} +import chisel3.{ + ActualDirection, + Bits, + CompileOptions, + Data, + Element, + PString, + Printable, + RawModule, + SpecifiedDirection, + UInt +} import scala.collection.mutable @@ -47,7 +58,7 @@ final class Analog private (private[chisel3] val width: Width) extends Element { _parent.foreach(_.addId(this)) SpecifiedDirection.fromParent(parentDirection, specifiedDirection) match { case SpecifiedDirection.Unspecified | SpecifiedDirection.Flip => - case x => throwException(s"Analog may not have explicit direction, got '$x'") + case x => throwException(s"Analog may not have explicit direction, got '$x'") } val targetTopBinding = target match { case target: TopBinding => target @@ -67,8 +78,12 @@ final class Analog private (private[chisel3] val width: Width) extends Element { override def do_asUInt(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): UInt = throwException("Analog does not support asUInt") - private[chisel3] override def connectFromBits(that: Bits)(implicit sourceInfo: SourceInfo, - compileOptions: CompileOptions): Unit = { + private[chisel3] override def connectFromBits( + that: Bits + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Unit = { throwException("Analog does not support connectFromBits") } diff --git a/core/src/main/scala/chisel3/experimental/Trace.scala b/core/src/main/scala/chisel3/experimental/Trace.scala index 2d965c7b..4ab615a5 100644 --- a/core/src/main/scala/chisel3/experimental/Trace.scala +++ b/core/src/main/scala/chisel3/experimental/Trace.scala @@ -18,7 +18,7 @@ import firrtl.transforms.DontTouchAllTargets * // get final reference of `a` Seq(ReferenceTarget("Dut", "Dut", Seq.empty, "a", Seq.empty)) * val firrtlReferenceOfDutA = finalTarget(annos)(dut.a) * }}} - * */ + */ object Trace { /** Trace a Instance name. */ @@ -49,8 +49,8 @@ object Trace { * @param chiselTarget original annotated target in Chisel, which should not be changed or renamed in FIRRTL. */ private case class TraceNameAnnotation[T <: CompleteTarget](target: T, chiselTarget: T) - extends SingleTargetAnnotation[T] - with DontTouchAllTargets { + extends SingleTargetAnnotation[T] + with DontTouchAllTargets { def duplicate(n: T): Annotation = this.copy(target = n) } @@ -64,6 +64,6 @@ object Trace { * This API can be used to gather all final reference to the signal or module which is marked by `traceName` */ def finalTargetMap(annos: AnnotationSeq): Map[CompleteTarget, Seq[CompleteTarget]] = annos.collect { - case TraceNameAnnotation(t, chiselTarget) => chiselTarget -> t - }.groupBy(_._1).map{case (k, v) => k -> v.map(_._2)} + case TraceNameAnnotation(t, chiselTarget) => chiselTarget -> t + }.groupBy(_._1).map { case (k, v) => k -> v.map(_._2) } } diff --git a/core/src/main/scala/chisel3/experimental/dataview/DataProduct.scala b/core/src/main/scala/chisel3/experimental/dataview/DataProduct.scala index 438f97b8..c6ebe604 100644 --- a/core/src/main/scala/chisel3/experimental/dataview/DataProduct.scala +++ b/core/src/main/scala/chisel3/experimental/dataview/DataProduct.scala @@ -3,7 +3,7 @@ package chisel3.experimental.dataview import chisel3.experimental.BaseModule -import chisel3.{Data, Vec, getRecursiveFields} +import chisel3.{getRecursiveFields, Data, Vec} import scala.annotation.implicitNotFound @@ -18,9 +18,12 @@ import scala.annotation.implicitNotFound * @tparam A Type that has elements of type [[Data]] * @see [[https://www.chisel-lang.org/chisel3/docs/explanations/dataview#dataproduct Detailed Documentation]] */ -@implicitNotFound("Could not find implicit value for DataProduct[${A}].\n" + - "Please see https://www.chisel-lang.org/chisel3/docs/explanations/dataview#dataproduct") +@implicitNotFound( + "Could not find implicit value for DataProduct[${A}].\n" + + "Please see https://www.chisel-lang.org/chisel3/docs/explanations/dataview#dataproduct" +) trait DataProduct[-A] { + /** Provides [[Data]] elements within some containing object * * @param a Containing object @@ -59,6 +62,7 @@ sealed trait LowPriorityDataProduct { * @note DataProduct implementations provided in this object are available in the implicit scope */ object DataProduct extends LowPriorityDataProduct { + /** [[DataProduct]] implementation for [[BaseModule]] */ implicit val userModuleDataProduct: DataProduct[BaseModule] = new DataProduct[BaseModule] { def dataIterator(a: BaseModule, path: String): Iterator[(Data, String)] = { @@ -78,19 +82,18 @@ object DataProduct extends LowPriorityDataProduct { } /** [[DataProduct]] implementation for any `Seq[A]` where `A` has an implementation of `DataProduct`. */ - implicit def seqDataProduct[A : DataProduct]: DataProduct[Seq[A]] = new DataProduct[Seq[A]] { + implicit def seqDataProduct[A: DataProduct]: DataProduct[Seq[A]] = new DataProduct[Seq[A]] { def dataIterator(a: Seq[A], path: String): Iterator[(Data, String)] = { val dpa = implicitly[DataProduct[A]] - a.iterator - .zipWithIndex - .flatMap { case (elt, idx) => + a.iterator.zipWithIndex.flatMap { + case (elt, idx) => dpa.dataIterator(elt, s"$path[$idx]") - } + } } } /** [[DataProduct]] implementation for any [[Tuple2]] where each field has an implementation of `DataProduct`. */ - implicit def tuple2DataProduct[A : DataProduct, B : DataProduct]: DataProduct[(A, B)] = new DataProduct[(A, B)] { + implicit def tuple2DataProduct[A: DataProduct, B: DataProduct]: DataProduct[(A, B)] = new DataProduct[(A, B)] { def dataIterator(tup: (A, B), path: String): Iterator[(Data, String)] = { val dpa = implicitly[DataProduct[A]] val dpb = implicitly[DataProduct[B]] @@ -100,7 +103,7 @@ object DataProduct extends LowPriorityDataProduct { } /** [[DataProduct]] implementation for any [[Tuple3]] where each field has an implementation of `DataProduct`. */ - implicit def tuple3DataProduct[A : DataProduct, B : DataProduct, C : DataProduct]: DataProduct[(A, B, C)] = + implicit def tuple3DataProduct[A: DataProduct, B: DataProduct, C: DataProduct]: DataProduct[(A, B, C)] = new DataProduct[(A, B, C)] { def dataIterator(tup: (A, B, C), path: String): Iterator[(Data, String)] = { val dpa = implicitly[DataProduct[A]] @@ -112,7 +115,12 @@ object DataProduct extends LowPriorityDataProduct { } /** [[DataProduct]] implementation for any [[Tuple4]] where each field has an implementation of `DataProduct`. */ - implicit def tuple4DataProduct[A : DataProduct, B : DataProduct, C : DataProduct, D : DataProduct]: DataProduct[(A, B, C, D)] = + implicit def tuple4DataProduct[ + A: DataProduct, + B: DataProduct, + C: DataProduct, + D: DataProduct + ]: DataProduct[(A, B, C, D)] = new DataProduct[(A, B, C, D)] { def dataIterator(tup: (A, B, C, D), path: String): Iterator[(Data, String)] = { val dpa = implicitly[DataProduct[A]] @@ -129,11 +137,12 @@ object DataProduct extends LowPriorityDataProduct { /** [[DataProduct]] implementation for any [[Tuple5]] where each field has an implementation of `DataProduct`. */ implicit def tuple5DataProduct[ - A : DataProduct, - B : DataProduct, - C : DataProduct, - D : DataProduct, - E : DataProduct]: DataProduct[(A, B, C, D, E)] = + A: DataProduct, + B: DataProduct, + C: DataProduct, + D: DataProduct, + E: DataProduct + ]: DataProduct[(A, B, C, D, E)] = new DataProduct[(A, B, C, D, E)] { def dataIterator(tup: (A, B, C, D, E), path: String): Iterator[(Data, String)] = { val dpa = implicitly[DataProduct[A]] @@ -152,12 +161,13 @@ object DataProduct extends LowPriorityDataProduct { /** [[DataProduct]] implementation for any [[Tuple6]] where each field has an implementation of `DataProduct`. */ implicit def tuple6DataProduct[ - A : DataProduct, - B : DataProduct, - C : DataProduct, - D : DataProduct, - E : DataProduct, - F : DataProduct]: DataProduct[(A, B, C, D, E, F)] = + A: DataProduct, + B: DataProduct, + C: DataProduct, + D: DataProduct, + E: DataProduct, + F: DataProduct + ]: DataProduct[(A, B, C, D, E, F)] = new DataProduct[(A, B, C, D, E, F)] { def dataIterator(tup: (A, B, C, D, E, F), path: String): Iterator[(Data, String)] = { val dpa = implicitly[DataProduct[A]] @@ -178,13 +188,14 @@ object DataProduct extends LowPriorityDataProduct { /** [[DataProduct]] implementation for any [[Tuple7]] where each field has an implementation of `DataProduct`. */ implicit def tuple7DataProduct[ - A : DataProduct, - B : DataProduct, - C : DataProduct, - D : DataProduct, - E : DataProduct, - F : DataProduct, - G : DataProduct]: DataProduct[(A, B, C, D, E, F, G)] = + A: DataProduct, + B: DataProduct, + C: DataProduct, + D: DataProduct, + E: DataProduct, + F: DataProduct, + G: DataProduct + ]: DataProduct[(A, B, C, D, E, F, G)] = new DataProduct[(A, B, C, D, E, F, G)] { def dataIterator(tup: (A, B, C, D, E, F, G), path: String): Iterator[(Data, String)] = { val dpa = implicitly[DataProduct[A]] @@ -207,14 +218,15 @@ object DataProduct extends LowPriorityDataProduct { /** [[DataProduct]] implementation for any [[Tuple8]] where each field has an implementation of `DataProduct`. */ implicit def tuple8DataProduct[ - A : DataProduct, - B : DataProduct, - C : DataProduct, - D : DataProduct, - E : DataProduct, - F : DataProduct, - G : DataProduct, - H : DataProduct]: DataProduct[(A, B, C, D, E, F, G, H)] = + A: DataProduct, + B: DataProduct, + C: DataProduct, + D: DataProduct, + E: DataProduct, + F: DataProduct, + G: DataProduct, + H: DataProduct + ]: DataProduct[(A, B, C, D, E, F, G, H)] = new DataProduct[(A, B, C, D, E, F, G, H)] { def dataIterator(tup: (A, B, C, D, E, F, G, H), path: String): Iterator[(Data, String)] = { val dpa = implicitly[DataProduct[A]] @@ -239,15 +251,16 @@ object DataProduct extends LowPriorityDataProduct { /** [[DataProduct]] implementation for any [[Tuple9]] where each field has an implementation of `DataProduct`. */ implicit def tuple9DataProduct[ - A : DataProduct, - B : DataProduct, - C : DataProduct, - D : DataProduct, - E : DataProduct, - F : DataProduct, - G : DataProduct, - H : DataProduct, - I : DataProduct]: DataProduct[(A, B, C, D, E, F, G, H, I)] = + A: DataProduct, + B: DataProduct, + C: DataProduct, + D: DataProduct, + E: DataProduct, + F: DataProduct, + G: DataProduct, + H: DataProduct, + I: DataProduct + ]: DataProduct[(A, B, C, D, E, F, G, H, I)] = new DataProduct[(A, B, C, D, E, F, G, H, I)] { def dataIterator(tup: (A, B, C, D, E, F, G, H, I), path: String): Iterator[(Data, String)] = { val dpa = implicitly[DataProduct[A]] @@ -274,16 +287,17 @@ object DataProduct extends LowPriorityDataProduct { /** [[DataProduct]] implementation for any [[Tuple9]] where each field has an implementation of `DataProduct`. */ implicit def tuple10DataProduct[ - A : DataProduct, - B : DataProduct, - C : DataProduct, - D : DataProduct, - E : DataProduct, - F : DataProduct, - G : DataProduct, - H : DataProduct, - I : DataProduct, - J : DataProduct]: DataProduct[(A, B, C, D, E, F, G, H, I, J)] = + A: DataProduct, + B: DataProduct, + C: DataProduct, + D: DataProduct, + E: DataProduct, + F: DataProduct, + G: DataProduct, + H: DataProduct, + I: DataProduct, + J: DataProduct + ]: DataProduct[(A, B, C, D, E, F, G, H, I, J)] = new DataProduct[(A, B, C, D, E, F, G, H, I, J)] { def dataIterator(tup: (A, B, C, D, E, F, G, H, I, J), path: String): Iterator[(Data, String)] = { val dpa = implicitly[DataProduct[A]] diff --git a/core/src/main/scala/chisel3/experimental/dataview/DataView.scala b/core/src/main/scala/chisel3/experimental/dataview/DataView.scala index c17a5574..7f20964d 100644 --- a/core/src/main/scala/chisel3/experimental/dataview/DataView.scala +++ b/core/src/main/scala/chisel3/experimental/dataview/DataView.scala @@ -11,7 +11,6 @@ import chisel3.ExplicitCompileOptions.Strict import scala.reflect.runtime.universe.WeakTypeTag import annotation.implicitNotFound - /** Mapping between a target type `T` and a view type `V` * * Enables calling `.viewAs[T]` on instances of the target type. @@ -41,9 +40,11 @@ import annotation.implicitNotFound * @see [[DataView$ object DataView]] for factory methods * @see [[PartialDataView object PartialDataView]] for defining non-total `DataViews` */ -@implicitNotFound("Could not find implicit value for DataView[${T}, ${V}].\n" + - "Please see https://www.chisel-lang.org/chisel3/docs/explanations/dataview") -sealed class DataView[T : DataProduct, V <: Data] private[chisel3] ( +@implicitNotFound( + "Could not find implicit value for DataView[${T}, ${V}].\n" + + "Please see https://www.chisel-lang.org/chisel3/docs/explanations/dataview" +) +sealed class DataView[T: DataProduct, V <: Data] private[chisel3] ( /** Function constructing an object of the View type from an object of the Target type */ private[chisel3] val mkView: T => V, /** Function that returns corresponding fields of the target and view */ @@ -51,8 +52,8 @@ sealed class DataView[T : DataProduct, V <: Data] private[chisel3] ( // Aliasing this with a def below to make the ScalaDoc show up for the field _total: Boolean )( - implicit private[chisel3] val sourceInfo: SourceInfo -) { + implicit private[chisel3] val sourceInfo: SourceInfo) { + /** Indicates if the mapping contains every field of the target */ def total: Boolean = _total @@ -89,15 +90,30 @@ sealed class DataView[T : DataProduct, V <: Data] private[chisel3] ( object DataView { /** Default factory method, alias for [[pairs]] */ - def apply[T : DataProduct, V <: Data](mkView: T => V, pairs: ((T, V) => (Data, Data))*)(implicit sourceInfo: SourceInfo): DataView[T, V] = + def apply[T: DataProduct, V <: Data]( + mkView: T => V, + pairs: ((T, V) => (Data, Data))* + )( + implicit sourceInfo: SourceInfo + ): DataView[T, V] = DataView.pairs(mkView, pairs: _*) /** Construct [[DataView]]s with pairs of functions from the target and view to corresponding fields */ - def pairs[T : DataProduct, V <: Data](mkView: T => V, pairs: ((T, V) => (Data, Data))*)(implicit sourceInfo: SourceInfo): DataView[T, V] = + def pairs[T: DataProduct, V <: Data]( + mkView: T => V, + pairs: ((T, V) => (Data, Data))* + )( + implicit sourceInfo: SourceInfo + ): DataView[T, V] = mapping(mkView: T => V, swizzle(pairs)) /** More general factory method for complex mappings */ - def mapping[T : DataProduct, V <: Data](mkView: T => V, mapping: (T, V) => Iterable[(Data, Data)])(implicit sourceInfo: SourceInfo): DataView[T, V] = + def mapping[T: DataProduct, V <: Data]( + mkView: T => V, + mapping: (T, V) => Iterable[(Data, Data)] + )( + implicit sourceInfo: SourceInfo + ): DataView[T, V] = new DataView[T, V](mkView, mapping, _total = true) /** Provides `invert` for invertible [[DataView]]s @@ -107,7 +123,7 @@ object DataView { * * @note [[PartialDataView]]s are **not** invertible and will result in an elaboration time exception */ - implicit class InvertibleDataView[T <: Data : WeakTypeTag, V <: Data : WeakTypeTag](view: DataView[T, V]) { + implicit class InvertibleDataView[T <: Data: WeakTypeTag, V <: Data: WeakTypeTag](view: DataView[T, V]) { def invert(mkView: V => T): DataView[V, T] = { // It would've been nice to make this a compiler error, but it's unclear how to make that work. // We tried having separate TotalDataView and PartialDataView and only defining inversion for @@ -143,7 +159,10 @@ object DataView { DataView[A, A](chiselTypeOf.apply, { case (x, y) => (x, y) }) /** Provides `DataView[Seq[A], Vec[B]]` for all `A` such that there exists `DataView[A, B]` */ - implicit def seqDataView[A : DataProduct, B <: Data](implicit dv: DataView[A, B], sourceInfo: SourceInfo): DataView[Seq[A], Vec[B]] = { + implicit def seqDataView[A: DataProduct, B <: Data]( + implicit dv: DataView[A, B], + sourceInfo: SourceInfo + ): DataView[Seq[A], Vec[B]] = { // TODO this would need a better way to determine the prototype for the Vec DataView.mapping[Seq[A], Vec[B]]( xs => Vec(xs.size, chiselTypeClone(xs.head.viewAs[B]))(sourceInfo, Strict), // xs.head is not correct in general @@ -151,223 +170,395 @@ object DataView { ) } - /** Provides implementations of [[DataView]] for [[Tuple2]] to [[HWTuple2]] */ - implicit def tuple2DataView[T1 : DataProduct, T2 : DataProduct, V1 <: Data, V2 <: Data]( - implicit v1: DataView[T1, V1], v2: DataView[T2, V2], sourceInfo: SourceInfo + /** Provides implementations of [[DataView]] for [[Tuple2]] to [[HWTuple2]] */ + implicit def tuple2DataView[T1: DataProduct, T2: DataProduct, V1 <: Data, V2 <: Data]( + implicit v1: DataView[T1, V1], + v2: DataView[T2, V2], + sourceInfo: SourceInfo ): DataView[(T1, T2), HWTuple2[V1, V2]] = DataView.mapping( - { case (a, b) => new HWTuple2(a.viewAs[V1].cloneType, b.viewAs[V2].cloneType)}, - { case ((a, b), hwt) => - Seq(a.viewAs[V1] -> hwt._1, - b.viewAs[V2] -> hwt._2) + { case (a, b) => new HWTuple2(a.viewAs[V1].cloneType, b.viewAs[V2].cloneType) }, + { + case ((a, b), hwt) => + Seq(a.viewAs[V1] -> hwt._1, b.viewAs[V2] -> hwt._2) } ) - /** Provides implementations of [[DataView]] for [[Tuple3]] to [[HWTuple3]] */ - implicit def tuple3DataView[ - T1 : DataProduct, T2 : DataProduct, T3 : DataProduct, - V1 <: Data, V2 <: Data, V3 <: Data - ]( - implicit v1: DataView[T1, V1], v2: DataView[T2, V2], v3: DataView[T3, V3], sourceInfo: SourceInfo + /** Provides implementations of [[DataView]] for [[Tuple3]] to [[HWTuple3]] */ + implicit def tuple3DataView[T1: DataProduct, T2: DataProduct, T3: DataProduct, V1 <: Data, V2 <: Data, V3 <: Data]( + implicit v1: DataView[T1, V1], + v2: DataView[T2, V2], + v3: DataView[T3, V3], + sourceInfo: SourceInfo ): DataView[(T1, T2, T3), HWTuple3[V1, V2, V3]] = DataView.mapping( - { case (a, b, c) => new HWTuple3(a.viewAs[V1].cloneType, b.viewAs[V2].cloneType, c.viewAs[V3].cloneType)}, - { case ((a, b, c), hwt) => - Seq(a.viewAs[V1] -> hwt._1, - b.viewAs[V2] -> hwt._2, - c.viewAs[V3] -> hwt._3) + { case (a, b, c) => new HWTuple3(a.viewAs[V1].cloneType, b.viewAs[V2].cloneType, c.viewAs[V3].cloneType) }, + { + case ((a, b, c), hwt) => + Seq(a.viewAs[V1] -> hwt._1, b.viewAs[V2] -> hwt._2, c.viewAs[V3] -> hwt._3) } ) - /** Provides implementations of [[DataView]] for [[Tuple4]] to [[HWTuple4]] */ + /** Provides implementations of [[DataView]] for [[Tuple4]] to [[HWTuple4]] */ implicit def tuple4DataView[ - T1 : DataProduct, T2 : DataProduct, T3 : DataProduct, T4 : DataProduct, - V1 <: Data, V2 <: Data, V3 <: Data, V4 <: Data + T1: DataProduct, + T2: DataProduct, + T3: DataProduct, + T4: DataProduct, + V1 <: Data, + V2 <: Data, + V3 <: Data, + V4 <: Data ]( - implicit v1: DataView[T1, V1], v2: DataView[T2, V2], v3: DataView[T3, V3], v4: DataView[T4, V4], sourceInfo: SourceInfo + implicit v1: DataView[T1, V1], + v2: DataView[T2, V2], + v3: DataView[T3, V3], + v4: DataView[T4, V4], + sourceInfo: SourceInfo ): DataView[(T1, T2, T3, T4), HWTuple4[V1, V2, V3, V4]] = DataView.mapping( - { case (a, b, c, d) => - new HWTuple4(a.viewAs[V1].cloneType, b.viewAs[V2].cloneType, c.viewAs[V3].cloneType, d.viewAs[V4].cloneType - )}, - { case ((a, b, c, d), hwt) => - Seq(a.viewAs[V1] -> hwt._1, - b.viewAs[V2] -> hwt._2, - c.viewAs[V3] -> hwt._3, - d.viewAs[V4] -> hwt._4) + { + case (a, b, c, d) => + new HWTuple4(a.viewAs[V1].cloneType, b.viewAs[V2].cloneType, c.viewAs[V3].cloneType, d.viewAs[V4].cloneType) + }, + { + case ((a, b, c, d), hwt) => + Seq(a.viewAs[V1] -> hwt._1, b.viewAs[V2] -> hwt._2, c.viewAs[V3] -> hwt._3, d.viewAs[V4] -> hwt._4) } ) - /** Provides implementations of [[DataView]] for [[Tuple5]] to [[HWTuple5]] */ + /** Provides implementations of [[DataView]] for [[Tuple5]] to [[HWTuple5]] */ implicit def tuple5DataView[ - T1 : DataProduct, T2 : DataProduct, T3 : DataProduct, T4 : DataProduct, T5 : DataProduct, - V1 <: Data, V2 <: Data, V3 <: Data, V4 <: Data, V5 <: Data + T1: DataProduct, + T2: DataProduct, + T3: DataProduct, + T4: DataProduct, + T5: DataProduct, + V1 <: Data, + V2 <: Data, + V3 <: Data, + V4 <: Data, + V5 <: Data ]( - implicit v1: DataView[T1, V1], v2: DataView[T2, V2], v3: DataView[T3, V3], v4: DataView[T4, V4], v5: DataView[T5, V5], sourceInfo: SourceInfo + implicit v1: DataView[T1, V1], + v2: DataView[T2, V2], + v3: DataView[T3, V3], + v4: DataView[T4, V4], + v5: DataView[T5, V5], + sourceInfo: SourceInfo ): DataView[(T1, T2, T3, T4, T5), HWTuple5[V1, V2, V3, V4, V5]] = { DataView.mapping( - { case tup: Tuple5[T1, T2, T3, T4, T5] => - val (a, b, c, d, e) = tup - new HWTuple5(a.viewAs[V1].cloneType, b.viewAs[V2].cloneType, c.viewAs[V3].cloneType, d.viewAs[V4].cloneType, - e.viewAs[V5].cloneType - ) + { + case tup: Tuple5[T1, T2, T3, T4, T5] => + val (a, b, c, d, e) = tup + new HWTuple5( + a.viewAs[V1].cloneType, + b.viewAs[V2].cloneType, + c.viewAs[V3].cloneType, + d.viewAs[V4].cloneType, + e.viewAs[V5].cloneType + ) }, - { case ((a, b, c, d, e), hwt) => - Seq(a.viewAs[V1] -> hwt._1, - b.viewAs[V2] -> hwt._2, - c.viewAs[V3] -> hwt._3, - d.viewAs[V4] -> hwt._4, - e.viewAs[V5] -> hwt._5) + { + case ((a, b, c, d, e), hwt) => + Seq( + a.viewAs[V1] -> hwt._1, + b.viewAs[V2] -> hwt._2, + c.viewAs[V3] -> hwt._3, + d.viewAs[V4] -> hwt._4, + e.viewAs[V5] -> hwt._5 + ) } ) } - /** Provides implementations of [[DataView]] for [[Tuple6]] to [[HWTuple6]] */ + /** Provides implementations of [[DataView]] for [[Tuple6]] to [[HWTuple6]] */ implicit def tuple6DataView[ - T1 : DataProduct, T2 : DataProduct, T3 : DataProduct, T4 : DataProduct, T5 : DataProduct, - T6 : DataProduct, - V1 <: Data, V2 <: Data, V3 <: Data, V4 <: Data, V5 <: Data, + T1: DataProduct, + T2: DataProduct, + T3: DataProduct, + T4: DataProduct, + T5: DataProduct, + T6: DataProduct, + V1 <: Data, + V2 <: Data, + V3 <: Data, + V4 <: Data, + V5 <: Data, V6 <: Data ]( - implicit v1: DataView[T1, V1], v2: DataView[T2, V2], v3: DataView[T3, V3], v4: DataView[T4, V4], - v5: DataView[T5, V5], v6: DataView[T6, V6], - sourceInfo: SourceInfo + implicit v1: DataView[T1, V1], + v2: DataView[T2, V2], + v3: DataView[T3, V3], + v4: DataView[T4, V4], + v5: DataView[T5, V5], + v6: DataView[T6, V6], + sourceInfo: SourceInfo ): DataView[(T1, T2, T3, T4, T5, T6), HWTuple6[V1, V2, V3, V4, V5, V6]] = DataView.mapping( - { case (a, b, c, d, e, f) => - new HWTuple6(a.viewAs[V1].cloneType, b.viewAs[V2].cloneType, c.viewAs[V3].cloneType, d.viewAs[V4].cloneType, - e.viewAs[V5].cloneType, f.viewAs[V6].cloneType - ) + { + case (a, b, c, d, e, f) => + new HWTuple6( + a.viewAs[V1].cloneType, + b.viewAs[V2].cloneType, + c.viewAs[V3].cloneType, + d.viewAs[V4].cloneType, + e.viewAs[V5].cloneType, + f.viewAs[V6].cloneType + ) }, - { case ((a, b, c, d, e, f), hwt) => - Seq(a.viewAs[V1] -> hwt._1, - b.viewAs[V2] -> hwt._2, - c.viewAs[V3] -> hwt._3, - d.viewAs[V4] -> hwt._4, - e.viewAs[V5] -> hwt._5, - f.viewAs[V6] -> hwt._6) + { + case ((a, b, c, d, e, f), hwt) => + Seq( + a.viewAs[V1] -> hwt._1, + b.viewAs[V2] -> hwt._2, + c.viewAs[V3] -> hwt._3, + d.viewAs[V4] -> hwt._4, + e.viewAs[V5] -> hwt._5, + f.viewAs[V6] -> hwt._6 + ) } ) - /** Provides implementations of [[DataView]] for [[Tuple7]] to [[HWTuple7]] */ + /** Provides implementations of [[DataView]] for [[Tuple7]] to [[HWTuple7]] */ implicit def tuple7DataView[ - T1 : DataProduct, T2 : DataProduct, T3 : DataProduct, T4 : DataProduct, T5 : DataProduct, - T6 : DataProduct, T7 : DataProduct, - V1 <: Data, V2 <: Data, V3 <: Data, V4 <: Data, V5 <: Data, - V6 <: Data, V7 <: Data + T1: DataProduct, + T2: DataProduct, + T3: DataProduct, + T4: DataProduct, + T5: DataProduct, + T6: DataProduct, + T7: DataProduct, + V1 <: Data, + V2 <: Data, + V3 <: Data, + V4 <: Data, + V5 <: Data, + V6 <: Data, + V7 <: Data ]( - implicit v1: DataView[T1, V1], v2: DataView[T2, V2], v3: DataView[T3, V3], v4: DataView[T4, V4], - v5: DataView[T5, V5], v6: DataView[T6, V6], v7: DataView[T7, V7], - sourceInfo: SourceInfo + implicit v1: DataView[T1, V1], + v2: DataView[T2, V2], + v3: DataView[T3, V3], + v4: DataView[T4, V4], + v5: DataView[T5, V5], + v6: DataView[T6, V6], + v7: DataView[T7, V7], + sourceInfo: SourceInfo ): DataView[(T1, T2, T3, T4, T5, T6, T7), HWTuple7[V1, V2, V3, V4, V5, V6, V7]] = DataView.mapping( - { case (a, b, c, d, e, f, g) => - new HWTuple7(a.viewAs[V1].cloneType, b.viewAs[V2].cloneType, c.viewAs[V3].cloneType, d.viewAs[V4].cloneType, - e.viewAs[V5].cloneType, f.viewAs[V6].cloneType, g.viewAs[V7].cloneType - ) + { + case (a, b, c, d, e, f, g) => + new HWTuple7( + a.viewAs[V1].cloneType, + b.viewAs[V2].cloneType, + c.viewAs[V3].cloneType, + d.viewAs[V4].cloneType, + e.viewAs[V5].cloneType, + f.viewAs[V6].cloneType, + g.viewAs[V7].cloneType + ) }, - { case ((a, b, c, d, e, f, g), hwt) => - Seq(a.viewAs[V1] -> hwt._1, - b.viewAs[V2] -> hwt._2, - c.viewAs[V3] -> hwt._3, - d.viewAs[V4] -> hwt._4, - e.viewAs[V5] -> hwt._5, - f.viewAs[V6] -> hwt._6, - g.viewAs[V7] -> hwt._7) + { + case ((a, b, c, d, e, f, g), hwt) => + Seq( + a.viewAs[V1] -> hwt._1, + b.viewAs[V2] -> hwt._2, + c.viewAs[V3] -> hwt._3, + d.viewAs[V4] -> hwt._4, + e.viewAs[V5] -> hwt._5, + f.viewAs[V6] -> hwt._6, + g.viewAs[V7] -> hwt._7 + ) } ) - /** Provides implementations of [[DataView]] for [[Tuple8]] to [[HWTuple8]] */ + /** Provides implementations of [[DataView]] for [[Tuple8]] to [[HWTuple8]] */ implicit def tuple8DataView[ - T1 : DataProduct, T2 : DataProduct, T3 : DataProduct, T4 : DataProduct, T5 : DataProduct, - T6 : DataProduct, T7 : DataProduct, T8 : DataProduct, - V1 <: Data, V2 <: Data, V3 <: Data, V4 <: Data, V5 <: Data, - V6 <: Data, V7 <: Data, V8 <: Data + T1: DataProduct, + T2: DataProduct, + T3: DataProduct, + T4: DataProduct, + T5: DataProduct, + T6: DataProduct, + T7: DataProduct, + T8: DataProduct, + V1 <: Data, + V2 <: Data, + V3 <: Data, + V4 <: Data, + V5 <: Data, + V6 <: Data, + V7 <: Data, + V8 <: Data ]( - implicit v1: DataView[T1, V1], v2: DataView[T2, V2], v3: DataView[T3, V3], v4: DataView[T4, V4], - v5: DataView[T5, V5], v6: DataView[T6, V6], v7: DataView[T7, V7], v8: DataView[T8, V8], - sourceInfo: SourceInfo + implicit v1: DataView[T1, V1], + v2: DataView[T2, V2], + v3: DataView[T3, V3], + v4: DataView[T4, V4], + v5: DataView[T5, V5], + v6: DataView[T6, V6], + v7: DataView[T7, V7], + v8: DataView[T8, V8], + sourceInfo: SourceInfo ): DataView[(T1, T2, T3, T4, T5, T6, T7, T8), HWTuple8[V1, V2, V3, V4, V5, V6, V7, V8]] = DataView.mapping( - { case (a, b, c, d, e, f, g, h) => - new HWTuple8(a.viewAs[V1].cloneType, b.viewAs[V2].cloneType, c.viewAs[V3].cloneType, d.viewAs[V4].cloneType, - e.viewAs[V5].cloneType, f.viewAs[V6].cloneType, g.viewAs[V7].cloneType, h.viewAs[V8].cloneType - ) + { + case (a, b, c, d, e, f, g, h) => + new HWTuple8( + a.viewAs[V1].cloneType, + b.viewAs[V2].cloneType, + c.viewAs[V3].cloneType, + d.viewAs[V4].cloneType, + e.viewAs[V5].cloneType, + f.viewAs[V6].cloneType, + g.viewAs[V7].cloneType, + h.viewAs[V8].cloneType + ) }, - { case ((a, b, c, d, e, f, g, h), hwt) => - Seq(a.viewAs[V1] -> hwt._1, - b.viewAs[V2] -> hwt._2, - c.viewAs[V3] -> hwt._3, - d.viewAs[V4] -> hwt._4, - e.viewAs[V5] -> hwt._5, - f.viewAs[V6] -> hwt._6, - g.viewAs[V7] -> hwt._7, - h.viewAs[V8] -> hwt._8) + { + case ((a, b, c, d, e, f, g, h), hwt) => + Seq( + a.viewAs[V1] -> hwt._1, + b.viewAs[V2] -> hwt._2, + c.viewAs[V3] -> hwt._3, + d.viewAs[V4] -> hwt._4, + e.viewAs[V5] -> hwt._5, + f.viewAs[V6] -> hwt._6, + g.viewAs[V7] -> hwt._7, + h.viewAs[V8] -> hwt._8 + ) } ) - /** Provides implementations of [[DataView]] for [[Tuple9]] to [[HWTuple9]] */ + /** Provides implementations of [[DataView]] for [[Tuple9]] to [[HWTuple9]] */ implicit def tuple9DataView[ - T1 : DataProduct, T2 : DataProduct, T3 : DataProduct, T4 : DataProduct, T5 : DataProduct, - T6 : DataProduct, T7 : DataProduct, T8 : DataProduct, T9 : DataProduct, - V1 <: Data, V2 <: Data, V3 <: Data, V4 <: Data, V5 <: Data, - V6 <: Data, V7 <: Data, V8 <: Data, V9 <: Data + T1: DataProduct, + T2: DataProduct, + T3: DataProduct, + T4: DataProduct, + T5: DataProduct, + T6: DataProduct, + T7: DataProduct, + T8: DataProduct, + T9: DataProduct, + V1 <: Data, + V2 <: Data, + V3 <: Data, + V4 <: Data, + V5 <: Data, + V6 <: Data, + V7 <: Data, + V8 <: Data, + V9 <: Data ]( - implicit v1: DataView[T1, V1], v2: DataView[T2, V2], v3: DataView[T3, V3], v4: DataView[T4, V4], - v5: DataView[T5, V5], v6: DataView[T6, V6], v7: DataView[T7, V7], v8: DataView[T8, V8], - v9: DataView[T9, V9], - sourceInfo: SourceInfo + implicit v1: DataView[T1, V1], + v2: DataView[T2, V2], + v3: DataView[T3, V3], + v4: DataView[T4, V4], + v5: DataView[T5, V5], + v6: DataView[T6, V6], + v7: DataView[T7, V7], + v8: DataView[T8, V8], + v9: DataView[T9, V9], + sourceInfo: SourceInfo ): DataView[(T1, T2, T3, T4, T5, T6, T7, T8, T9), HWTuple9[V1, V2, V3, V4, V5, V6, V7, V8, V9]] = DataView.mapping( - { case (a, b, c, d, e, f, g, h, i) => - new HWTuple9(a.viewAs[V1].cloneType, b.viewAs[V2].cloneType, c.viewAs[V3].cloneType, d.viewAs[V4].cloneType, - e.viewAs[V5].cloneType, f.viewAs[V6].cloneType, g.viewAs[V7].cloneType, h.viewAs[V8].cloneType, - i.viewAs[V9].cloneType - ) + { + case (a, b, c, d, e, f, g, h, i) => + new HWTuple9( + a.viewAs[V1].cloneType, + b.viewAs[V2].cloneType, + c.viewAs[V3].cloneType, + d.viewAs[V4].cloneType, + e.viewAs[V5].cloneType, + f.viewAs[V6].cloneType, + g.viewAs[V7].cloneType, + h.viewAs[V8].cloneType, + i.viewAs[V9].cloneType + ) }, - { case ((a, b, c, d, e, f, g, h, i), hwt) => - Seq(a.viewAs[V1] -> hwt._1, - b.viewAs[V2] -> hwt._2, - c.viewAs[V3] -> hwt._3, - d.viewAs[V4] -> hwt._4, - e.viewAs[V5] -> hwt._5, - f.viewAs[V6] -> hwt._6, - g.viewAs[V7] -> hwt._7, - h.viewAs[V8] -> hwt._8, - i.viewAs[V9] -> hwt._9) + { + case ((a, b, c, d, e, f, g, h, i), hwt) => + Seq( + a.viewAs[V1] -> hwt._1, + b.viewAs[V2] -> hwt._2, + c.viewAs[V3] -> hwt._3, + d.viewAs[V4] -> hwt._4, + e.viewAs[V5] -> hwt._5, + f.viewAs[V6] -> hwt._6, + g.viewAs[V7] -> hwt._7, + h.viewAs[V8] -> hwt._8, + i.viewAs[V9] -> hwt._9 + ) } ) - /** Provides implementations of [[DataView]] for [[Tuple10]] to [[HWTuple10]] */ + /** Provides implementations of [[DataView]] for [[Tuple10]] to [[HWTuple10]] */ implicit def tuple10DataView[ - T1 : DataProduct, T2 : DataProduct, T3 : DataProduct, T4 : DataProduct, T5 : DataProduct, - T6 : DataProduct, T7 : DataProduct, T8 : DataProduct, T9 : DataProduct, T10 : DataProduct, - V1 <: Data, V2 <: Data, V3 <: Data, V4 <: Data, V5 <: Data, - V6 <: Data, V7 <: Data, V8 <: Data, V9 <: Data, V10 <: Data + T1: DataProduct, + T2: DataProduct, + T3: DataProduct, + T4: DataProduct, + T5: DataProduct, + T6: DataProduct, + T7: DataProduct, + T8: DataProduct, + T9: DataProduct, + T10: DataProduct, + V1 <: Data, + V2 <: Data, + V3 <: Data, + V4 <: Data, + V5 <: Data, + V6 <: Data, + V7 <: Data, + V8 <: Data, + V9 <: Data, + V10 <: Data ]( - implicit v1: DataView[T1, V1], v2: DataView[T2, V2], v3: DataView[T3, V3], v4: DataView[T4, V4], - v5: DataView[T5, V5], v6: DataView[T6, V6], v7: DataView[T7, V7], v8: DataView[T8, V8], - v9: DataView[T9, V9], v10: DataView[T10, V10], - sourceInfo: SourceInfo + implicit v1: DataView[T1, V1], + v2: DataView[T2, V2], + v3: DataView[T3, V3], + v4: DataView[T4, V4], + v5: DataView[T5, V5], + v6: DataView[T6, V6], + v7: DataView[T7, V7], + v8: DataView[T8, V8], + v9: DataView[T9, V9], + v10: DataView[T10, V10], + sourceInfo: SourceInfo ): DataView[(T1, T2, T3, T4, T5, T6, T7, T8, T9, T10), HWTuple10[V1, V2, V3, V4, V5, V6, V7, V8, V9, V10]] = DataView.mapping( - { case (a, b, c, d, e, f, g, h, i, j) => - new HWTuple10(a.viewAs[V1].cloneType, b.viewAs[V2].cloneType, c.viewAs[V3].cloneType, d.viewAs[V4].cloneType, - e.viewAs[V5].cloneType, f.viewAs[V6].cloneType, g.viewAs[V7].cloneType, h.viewAs[V8].cloneType, - i.viewAs[V9].cloneType, j.viewAs[V10].cloneType - ) + { + case (a, b, c, d, e, f, g, h, i, j) => + new HWTuple10( + a.viewAs[V1].cloneType, + b.viewAs[V2].cloneType, + c.viewAs[V3].cloneType, + d.viewAs[V4].cloneType, + e.viewAs[V5].cloneType, + f.viewAs[V6].cloneType, + g.viewAs[V7].cloneType, + h.viewAs[V8].cloneType, + i.viewAs[V9].cloneType, + j.viewAs[V10].cloneType + ) }, - { case ((a, b, c, d, e, f, g, h, i, j), hwt) => - Seq(a.viewAs[V1] -> hwt._1, - b.viewAs[V2] -> hwt._2, - c.viewAs[V3] -> hwt._3, - d.viewAs[V4] -> hwt._4, - e.viewAs[V5] -> hwt._5, - f.viewAs[V6] -> hwt._6, - g.viewAs[V7] -> hwt._7, - h.viewAs[V8] -> hwt._8, - i.viewAs[V9] -> hwt._9, - j.viewAs[V10] -> hwt._10) + { + case ((a, b, c, d, e, f, g, h, i, j), hwt) => + Seq( + a.viewAs[V1] -> hwt._1, + b.viewAs[V2] -> hwt._2, + c.viewAs[V3] -> hwt._3, + d.viewAs[V4] -> hwt._4, + e.viewAs[V5] -> hwt._5, + f.viewAs[V6] -> hwt._6, + g.viewAs[V7] -> hwt._7, + h.viewAs[V8] -> hwt._8, + i.viewAs[V9] -> hwt._9, + j.viewAs[V10] -> hwt._10 + ) } ) } @@ -376,14 +567,29 @@ object DataView { object PartialDataView { /** Default factory method, alias for [[pairs]] */ - def apply[T: DataProduct, V <: Data](mkView: T => V, pairs: ((T, V) => (Data, Data))*)(implicit sourceInfo: SourceInfo): DataView[T, V] = + def apply[T: DataProduct, V <: Data]( + mkView: T => V, + pairs: ((T, V) => (Data, Data))* + )( + implicit sourceInfo: SourceInfo + ): DataView[T, V] = PartialDataView.pairs(mkView, pairs: _*) /** Construct [[DataView]]s with pairs of functions from the target and view to corresponding fields */ - def pairs[T: DataProduct, V <: Data](mkView: T => V, pairs: ((T, V) => (Data, Data))*)(implicit sourceInfo: SourceInfo): DataView[T, V] = + def pairs[T: DataProduct, V <: Data]( + mkView: T => V, + pairs: ((T, V) => (Data, Data))* + )( + implicit sourceInfo: SourceInfo + ): DataView[T, V] = mapping(mkView, DataView.swizzle(pairs)) /** More general factory method for complex mappings */ - def mapping[T: DataProduct, V <: Data](mkView: T => V, mapping: (T, V) => Iterable[(Data, Data)])(implicit sourceInfo: SourceInfo): DataView[T, V] = + def mapping[T: DataProduct, V <: Data]( + mkView: T => V, + mapping: (T, V) => Iterable[(Data, Data)] + )( + implicit sourceInfo: SourceInfo + ): DataView[T, V] = new DataView[T, V](mkView, mapping, _total = false) } diff --git a/core/src/main/scala/chisel3/experimental/dataview/package.scala b/core/src/main/scala/chisel3/experimental/dataview/package.scala index 1acf43e1..3278d82c 100644 --- a/core/src/main/scala/chisel3/experimental/dataview/package.scala +++ b/core/src/main/scala/chisel3/experimental/dataview/package.scala @@ -39,27 +39,39 @@ package object dataview { } // This private type alias lets us provide a custom error message for misuing the .viewAs for upcasting Bundles - @implicitNotFound("${A} is not a subtype of ${B}! Did you mean .viewAs[${B}]? " + - "Please see https://www.chisel-lang.org/chisel3/docs/cookbooks/dataview") + @implicitNotFound( + "${A} is not a subtype of ${B}! Did you mean .viewAs[${B}]? " + + "Please see https://www.chisel-lang.org/chisel3/docs/cookbooks/dataview" + ) private type SubTypeOf[A, B] = A <:< B /** Provides `viewAsSupertype` for subclasses of [[Bundle]] */ implicit class BundleUpcastable[T <: Bundle](target: T) { + /** View a [[Bundle]] or [[Record]] as a parent type (upcast) */ def viewAsSupertype[V <: Bundle](proto: V)(implicit ev: SubTypeOf[T, V], sourceInfo: SourceInfo): V = { - implicit val dataView = PartialDataView.mapping[T, V](_ => proto, { - case (a, b) => - val aElts = a.elements - val bElts = b.elements - val bKeys = bElts.keySet - val keys = aElts.keysIterator.filter(bKeys.contains) - keys.map(k => aElts(k) -> bElts(k)).toSeq - }) + implicit val dataView = PartialDataView.mapping[T, V]( + _ => proto, + { + case (a, b) => + val aElts = a.elements + val bElts = b.elements + val bKeys = bElts.keySet + val keys = aElts.keysIterator.filter(bKeys.contains) + keys.map(k => aElts(k) -> bElts(k)).toSeq + } + ) target.viewAs[V] } } - private def nonTotalViewException(dataView: DataView[_, _], target: Any, view: Data, targetFields: Seq[String], viewFields: Seq[String]) = { + private def nonTotalViewException( + dataView: DataView[_, _], + target: Any, + view: Data, + targetFields: Seq[String], + viewFields: Seq[String] + ) = { def missingMsg(name: String, fields: Seq[String]): Option[String] = { val str = fields.mkString(", ") fields.size match { @@ -77,18 +89,17 @@ package object dataview { } // TODO should this be moved to class Aggregate / can it be unified with Aggregate.bind? - private def doBind[T : DataProduct, V <: Data](target: T, view: V, dataView: DataView[T, V]): Unit = { + private def doBind[T: DataProduct, V <: Data](target: T, view: V, dataView: DataView[T, V]): Unit = { val mapping = dataView.mapping(target, view) val total = dataView.total // Lookups to check the mapping results val viewFieldLookup: Map[Data, String] = getRecursiveFields(view, "_").toMap - val targetContains: Data => Boolean = implicitly[DataProduct[T]].dataSet(target) + val targetContains: Data => Boolean = implicitly[DataProduct[T]].dataSet(target) // Resulting bindings for each Element of the View val childBindings = new mutable.HashMap[Data, mutable.ListBuffer[Element]] ++ - viewFieldLookup.view - .collect { case (elt: Element, _) => elt } + viewFieldLookup.view.collect { case (elt: Element, _) => elt } .map(_ -> new mutable.ListBuffer[Element]) def viewFieldName(d: Data): String = @@ -115,7 +126,9 @@ package object dataview { val fieldName = viewFieldName(vex) val vwidth = widthAsString(vex) val twidth = widthAsString(tex) - throw InvalidViewException(s"View field $fieldName has width ${vwidth} that is incompatible with target value $tex's width ${twidth}") + throw InvalidViewException( + s"View field $fieldName has width ${vwidth} that is incompatible with target value $tex's width ${twidth}" + ) } childBindings(vex) += tex } @@ -137,23 +150,24 @@ package object dataview { } // Errors in totality of the View, use var List to keep fast path cheap (no allocation) - var viewNonTotalErrors: List[Data] = Nil + var viewNonTotalErrors: List[Data] = Nil var targetNonTotalErrors: List[String] = Nil val targetSeen: Option[mutable.Set[Data]] = if (total) Some(mutable.Set.empty[Data]) else None - val resultBindings = childBindings.map { case (data, targets) => - val targetsx = targets match { - case collection.Seq(target: Element) => target - case collection.Seq() => - viewNonTotalErrors = data :: viewNonTotalErrors - data.asInstanceOf[Element] // Return the Data itself, will error after this map, cast is safe - case x => - throw InvalidViewException(s"Got $x, expected Seq(_: Direct)") - } - // TODO record and report aliasing errors - targetSeen.foreach(_ += targetsx) - data -> targetsx + val resultBindings = childBindings.map { + case (data, targets) => + val targetsx = targets match { + case collection.Seq(target: Element) => target + case collection.Seq() => + viewNonTotalErrors = data :: viewNonTotalErrors + data.asInstanceOf[Element] // Return the Data itself, will error after this map, cast is safe + case x => + throw InvalidViewException(s"Got $x, expected Seq(_: Direct)") + } + // TODO record and report aliasing errors + targetSeen.foreach(_ += targetsx) + data -> targetsx }.toMap // Check for totality of Target @@ -169,7 +183,7 @@ package object dataview { } view match { - case elt: Element => view.bind(ViewBinding(resultBindings(elt))) + case elt: Element => view.bind(ViewBinding(resultBindings(elt))) case agg: Aggregate => // We record total Data mappings to provide a better .toTarget val topt = target match { @@ -221,31 +235,31 @@ package object dataview { @tailrec private[chisel3] def reify(elt: Element, topBinding: TopBinding): Element = topBinding match { case ViewBinding(target) => reify(target, elt.topBinding) - case _ => elt + case _ => elt } - /** Determine the target of a View if it is a single Target - * - * @note An Aggregate may be a view of unrelated [[Data]] (eg. like a Seq or tuple) and thus this - * there is no single Data representing the Target and this function will return None - * @return The single Data target of this view or None if a single Data doesn't exist - */ - private[chisel3] def reifySingleData(data: Data): Option[Data] = { - val candidate: Option[Data] = - data.binding.collect { // First check if this is a total mapping of an Aggregate - case AggregateViewBinding(_, Some(t)) => t - }.orElse { // Otherwise look via top binding - data.topBindingOpt match { - case None => None - case Some(ViewBinding(target)) => Some(target) - case Some(AggregateViewBinding(lookup, _)) => lookup.get(data) - case Some(_) => None - } + /** Determine the target of a View if it is a single Target + * + * @note An Aggregate may be a view of unrelated [[Data]] (eg. like a Seq or tuple) and thus this + * there is no single Data representing the Target and this function will return None + * @return The single Data target of this view or None if a single Data doesn't exist + */ + private[chisel3] def reifySingleData(data: Data): Option[Data] = { + val candidate: Option[Data] = + data.binding.collect { // First check if this is a total mapping of an Aggregate + case AggregateViewBinding(_, Some(t)) => t + }.orElse { // Otherwise look via top binding + data.topBindingOpt match { + case None => None + case Some(ViewBinding(target)) => Some(target) + case Some(AggregateViewBinding(lookup, _)) => lookup.get(data) + case Some(_) => None } - candidate.flatMap { d => - // Candidate may itself be a view, keep tracing in those cases - if (isView(d)) reifySingleData(d) else Some(d) } + candidate.flatMap { d => + // Candidate may itself be a view, keep tracing in those cases + if (isView(d)) reifySingleData(d) else Some(d) } + } } diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala b/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala index c7b51072..b498daf0 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/Definition.scala @@ -13,14 +13,17 @@ import chisel3.internal.BaseModule.IsClone import firrtl.annotations.{IsModule, ModuleTarget} /** User-facing Definition type. - * Represents a definition of an object of type [[A]] which are marked as @instantiable + * Represents a definition of an object of type [[A]] which are marked as @instantiable * Can be created using Definition.apply method. - * + * * These definitions are then used to create multiple [[Instance]]s. * * @param underlying The internal representation of the definition, which may be either be directly the object, or a clone of an object */ -final case class Definition[+A] private[chisel3] (private[chisel3] underlying: Underlying[A]) extends IsLookupable with SealedHierarchy[A] { +final case class Definition[+A] private[chisel3] (private[chisel3] underlying: Underlying[A]) + extends IsLookupable + with SealedHierarchy[A] { + /** Used by Chisel's internal macros. DO NOT USE in your normal Chisel code!!! * Instead, mark the field you are accessing with [[@public]] * @@ -35,14 +38,22 @@ final case class Definition[+A] private[chisel3] (private[chisel3] underlying: U * @param lookup typeclass which contains the correct lookup function, based on the types of A and B * @param macroGenerated a value created in the macro, to make it harder for users to use this API */ - def _lookup[B, C](that: A => B)(implicit lookup: Lookupable[B], macroGenerated: chisel3.internal.MacroGenerated): lookup.C = { + def _lookup[B, C]( + that: A => B + )( + implicit lookup: Lookupable[B], + macroGenerated: chisel3.internal.MacroGenerated + ): lookup.C = { lookup.definitionLookup(that, this) } /** @return the context of any Data's return from inside the instance */ private[chisel3] def getInnerDataContext: Option[BaseModule] = proto match { case value: BaseModule => - val newChild = Module.do_pseudo_apply(new internal.BaseModule.DefinitionClone(value))(chisel3.internal.sourceinfo.UnlocatableSourceInfo, chisel3.ExplicitCompileOptions.Strict) + val newChild = Module.do_pseudo_apply(new internal.BaseModule.DefinitionClone(value))( + chisel3.internal.sourceinfo.UnlocatableSourceInfo, + chisel3.ExplicitCompileOptions.Strict + ) newChild._circuit = value._circuit.orElse(Some(value)) newChild._parent = None Some(newChild) @@ -50,14 +61,14 @@ final case class Definition[+A] private[chisel3] (private[chisel3] underlying: U } override def toDefinition: Definition[A] = this - override def toInstance: Instance[A] = new Instance(underlying) - + override def toInstance: Instance[A] = new Instance(underlying) } /** Factory methods for constructing [[Definition]]s */ object Definition extends SourceInfoDoc { implicit class DefinitionBaseModuleExtensions[T <: BaseModule](d: Definition[T]) { + /** If this is an instance of a Module, returns the toTarget of this instance * @return target of this instance */ @@ -68,6 +79,7 @@ object Definition extends SourceInfoDoc { */ def toAbsoluteTarget: IsModule = d.proto.toAbsoluteTarget } + /** A construction method to build a Definition of a Module * * @param proto the Module being defined @@ -82,7 +94,12 @@ object Definition extends SourceInfoDoc { * * @return the input module as a Definition */ - def do_apply[T <: BaseModule with IsInstantiable](proto: => T) (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Definition[T] = { + def do_apply[T <: BaseModule with IsInstantiable]( + proto: => T + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Definition[T] = { val dynamicContext = new DynamicContext(Nil) Builder.globalNamespace.copyTo(dynamicContext.globalNamespace) dynamicContext.inDefinition = true diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/Hierarchy.scala b/core/src/main/scala/chisel3/experimental/hierarchy/Hierarchy.scala index 4b8d3ccc..2016bb54 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/Hierarchy.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/Hierarchy.scala @@ -34,28 +34,27 @@ sealed trait Hierarchy[+A] { * E.g. isA[List[Int]] will return true, even if underlying proto is of type List[String] * @return Whether underlying proto is of provided type (with caveats outlined above) */ - def isA[B : TypeTag]: Boolean = { + def isA[B: TypeTag]: Boolean = { val tptag = implicitly[TypeTag[B]] // drop any type information for the comparison, because the proto will not have that information. - val name = tptag.tpe.toString.takeWhile(_ != '[') + val name = tptag.tpe.toString.takeWhile(_ != '[') inBaseClasses(name) } - // This code handles a special-case where, within an mdoc context, the type returned from // scala reflection (typetag) looks different than when returned from java reflection. // This function detects this case and reshapes the string to match. private def modifyReplString(clz: String): String = { - if(clz != null) { + if (clz != null) { clz.split('.').toList match { case "repl" :: "MdocSession" :: app :: rest => s"$app.this." + rest.mkString(".") - case other => clz + case other => clz } } else clz } private lazy val superClasses = calculateSuperClasses(proto.getClass()) private def calculateSuperClasses(clz: Class[_]): Set[String] = { - if(clz != null) { + if (clz != null) { Set(modifyReplString(clz.getCanonicalName())) ++ clz.getInterfaces().flatMap(i => calculateSuperClasses(i)) ++ calculateSuperClasses(clz.getSuperclass()) @@ -65,7 +64,6 @@ sealed trait Hierarchy[+A] { } private def inBaseClasses(clz: String): Boolean = superClasses.contains(clz) - /** Used by Chisel's internal macros. DO NOT USE in your normal Chisel code!!! * Instead, mark the field you are accessing with [[@public]] * @@ -80,7 +78,12 @@ sealed trait Hierarchy[+A] { * @param lookup typeclass which contains the correct lookup function, based on the types of A and B * @param macroGenerated a value created in the macro, to make it harder for users to use this API */ - def _lookup[B, C](that: A => B)(implicit lookup: Lookupable[B], macroGenerated: chisel3.internal.MacroGenerated): lookup.C + def _lookup[B, C]( + that: A => B + )( + implicit lookup: Lookupable[B], + macroGenerated: chisel3.internal.MacroGenerated + ): lookup.C /** @return Return the underlying Definition[A] of this Hierarchy[A] */ def toDefinition: Definition[A] @@ -94,6 +97,7 @@ private[chisel3] trait SealedHierarchy[+A] extends Hierarchy[A] object Hierarchy { implicit class HierarchyBaseModuleExtensions[T <: BaseModule](i: Hierarchy[T]) { + /** Returns the toTarget of this hierarchy * @return target of this hierarchy */ diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/Instance.scala b/core/src/main/scala/chisel3/experimental/hierarchy/Instance.scala index 97b62c23..cc926771 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/Instance.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/Instance.scala @@ -11,12 +11,12 @@ import chisel3.experimental.BaseModule import firrtl.annotations.IsModule /** User-facing Instance type. - * Represents a unique instance of type [[A]] which are marked as @instantiable + * Represents a unique instance of type [[A]] which are marked as @instantiable * Can be created using Instance.apply method. * * @param underlying The internal representation of the instance, which may be either be directly the object, or a clone of an object */ -final case class Instance[+A] private [chisel3] (private[chisel3] underlying: Underlying[A]) extends SealedHierarchy[A] { +final case class Instance[+A] private[chisel3] (private[chisel3] underlying: Underlying[A]) extends SealedHierarchy[A] { underlying match { case Proto(p: IsClone[_]) => chisel3.internal.throwException("Cannot have a Proto with a clone!") case other => //Ok @@ -24,16 +24,16 @@ final case class Instance[+A] private [chisel3] (private[chisel3] underlying: Un /** @return the context of any Data's return from inside the instance */ private[chisel3] def getInnerDataContext: Option[BaseModule] = underlying match { - case Proto(value: BaseModule) => Some(value) - case Proto(value: IsInstantiable) => None - case Clone(i: BaseModule) => Some(i) + case Proto(value: BaseModule) => Some(value) + case Proto(value: IsInstantiable) => None + case Clone(i: BaseModule) => Some(i) case Clone(i: InstantiableClone[_]) => i.getInnerContext } /** @return the context this instance. Note that for non-module clones, getInnerDataContext will be the same as getClonedParent */ private[chisel3] def getClonedParent: Option[BaseModule] = underlying match { case Proto(value: BaseModule) => value._parent - case Clone(i: BaseModule) => i._parent + case Clone(i: BaseModule) => i._parent case Clone(i: InstantiableClone[_]) => i.getInnerContext } @@ -51,19 +51,25 @@ final case class Instance[+A] private [chisel3] (private[chisel3] underlying: Un * @param lookup typeclass which contains the correct lookup function, based on the types of A and B * @param macroGenerated a value created in the macro, to make it harder for users to use this API */ - def _lookup[B, C](that: A => B)(implicit lookup: Lookupable[B], macroGenerated: chisel3.internal.MacroGenerated): lookup.C = { + def _lookup[B, C]( + that: A => B + )( + implicit lookup: Lookupable[B], + macroGenerated: chisel3.internal.MacroGenerated + ): lookup.C = { lookup.instanceLookup(that, this) } /** Returns the definition of this Instance */ override def toDefinition: Definition[A] = new Definition(Proto(proto)) - override def toInstance: Instance[A] = this + override def toInstance: Instance[A] = this } /** Factory methods for constructing [[Instance]]s */ object Instance extends SourceInfoDoc { implicit class InstanceBaseModuleExtensions[T <: BaseModule](i: Instance[T]) { + /** If this is an instance of a Module, returns the toTarget of this instance * @return target of this instance */ @@ -81,19 +87,26 @@ object Instance extends SourceInfoDoc { } } + /** A constructs an [[Instance]] from a [[Definition]] * * @param definition the Module being created * @return an instance of the module definition */ - def apply[T <: BaseModule with IsInstantiable](definition: Definition[T]): Instance[T] = macro InstanceTransform.apply[T] + def apply[T <: BaseModule with IsInstantiable](definition: Definition[T]): Instance[T] = + macro InstanceTransform.apply[T] /** A constructs an [[Instance]] from a [[Definition]] * * @param definition the Module being created * @return an instance of the module definition */ - def do_apply[T <: BaseModule with IsInstantiable](definition: Definition[T])(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Instance[T] = { + def do_apply[T <: BaseModule with IsInstantiable]( + definition: Definition[T] + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Instance[T] = { val ports = experimental.CloneModuleAsRecord(definition.proto) val clone = ports._parent.get.asInstanceOf[ModuleClone[T]] clone._madeFromDefinition = true diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/IsInstantiable.scala b/core/src/main/scala/chisel3/experimental/hierarchy/IsInstantiable.scala index 4f3c2d42..27e06d92 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/IsInstantiable.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/IsInstantiable.scala @@ -6,7 +6,6 @@ package chisel3.experimental.hierarchy * Instead, use the [[@instantiable]] annotation on your trait or class. * * This trait indicates whether a class can be returned from an Instance. - * */ trait IsInstantiable diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/IsLookupable.scala b/core/src/main/scala/chisel3/experimental/hierarchy/IsLookupable.scala index 37d29a43..a82cbd7d 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/IsLookupable.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/IsLookupable.scala @@ -4,9 +4,9 @@ package chisel3.experimental.hierarchy /** A User-extendable trait to mark metadata-containers, e.g. parameter case classes, as valid to return unchanged * from an instance. - * + * * This should only be true of the metadata returned is identical for ALL instances! - * + * * @example For instances of the same proto, metadata or other construction parameters * may be useful to access outside of the instance construction. For parameters that are * the same for all instances, we should mark it as IsLookupable diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/LibraryHooks.scala b/core/src/main/scala/chisel3/experimental/hierarchy/LibraryHooks.scala index c16cc633..d4818f63 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/LibraryHooks.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/LibraryHooks.scala @@ -16,9 +16,12 @@ object LibraryHooks { * definition's Underlying * @note Implicitly requires being inside a Hierarchy Library Extension */ - def buildInstance[A](definition: Definition[A], - createUnderlying: Underlying[A] => Underlying[A] - )(implicit inside: InsideHierarchyLibraryExtension): Instance[A] = { + def buildInstance[A]( + definition: Definition[A], + createUnderlying: Underlying[A] => Underlying[A] + )( + implicit inside: InsideHierarchyLibraryExtension + ): Instance[A] = { new Instance(createUnderlying(definition.underlying)) } diff --git a/core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala b/core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala index ff4d676c..1223d6ce 100644 --- a/core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala +++ b/core/src/main/scala/chisel3/experimental/hierarchy/Lookupable.scala @@ -11,18 +11,20 @@ import scala.collection.mutable.HashMap import chisel3._ import chisel3.experimental.dataview.{isView, reify, reifySingleData} import chisel3.internal.firrtl.{Arg, ILit, Index, Slot, ULit} -import chisel3.internal.{AggregateViewBinding, Builder, ChildBinding, ViewBinding, ViewParent, throwException} +import chisel3.internal.{throwException, AggregateViewBinding, Builder, ChildBinding, ViewBinding, ViewParent} /** Represents lookup typeclass to determine how a value accessed from an original IsInstantiable * should be tweaked to return the Instance's version * Sealed. */ -@implicitNotFound("@public is only legal within a class marked @instantiable and only on vals of type" + - " Data, BaseModule, IsInstantiable, IsLookupable, or Instance[_], or in an Iterable or Option") +@implicitNotFound( + "@public is only legal within a class marked @instantiable and only on vals of type" + + " Data, BaseModule, IsInstantiable, IsLookupable, or Instance[_], or in an Iterable or Option" +) trait Lookupable[-B] { type C // Return type of the lookup /** Function called to modify the returned value of type B from A, into C - * + * * @param that function that selects B from A * @param instance Instance of A, used to determine C's context * @return @@ -35,8 +37,8 @@ trait Lookupable[-B] { * @param definition Definition of A, used to determine C's context * @return */ - def definitionLookup[A](that: A => B, definition: Definition[A]): C - protected def getProto[A](h: Hierarchy[A]): A = h.proto + def definitionLookup[A](that: A => B, definition: Definition[A]): C + protected def getProto[A](h: Hierarchy[A]): A = h.proto protected def getUnderlying[A](h: Hierarchy[A]): Underlying[A] = h.underlying } @@ -48,8 +50,13 @@ object Lookupable { * @param context new context * @return */ - private[chisel3] def cloneDataToContext[T <: Data](data: T, context: BaseModule) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = { + private[chisel3] def cloneDataToContext[T <: Data]( + data: T, + context: BaseModule + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): T = { internal.requireIsHardware(data, "cross module reference type") data._parent match { case None => data @@ -68,11 +75,18 @@ object Lookupable { } // The business logic of lookupData // Also called by cloneViewToContext which potentially needs to lookup stuff from ioMap or the cache - private[chisel3] def doLookupData[A, B <: Data](data: B, cache: HashMap[Data, Data], ioMap: Option[Map[Data, Data]], context: Option[BaseModule]) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): B = { + private[chisel3] def doLookupData[A, B <: Data]( + data: B, + cache: HashMap[Data, Data], + ioMap: Option[Map[Data, Data]], + context: Option[BaseModule] + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): B = { def impl[C <: Data](d: C): C = d match { case x: Data if ioMap.nonEmpty && ioMap.get.contains(x) => ioMap.get(x).asInstanceOf[C] - case x: Data if cache.contains(x) => cache(x).asInstanceOf[C] + case x: Data if cache.contains(x) => cache(x).asInstanceOf[C] case _ => assert(context.nonEmpty) // TODO is this even possible? Better error message here val ret = cloneDataToContext(d, context.get) @@ -105,12 +119,13 @@ object Lookupable { * Invariants that elt is a Child of something of the type of data is dynamically checked as we traverse */ private def mapRootAndExtractSubField[A <: Data](arg: A, f: Data => Data): A = { - def err(msg: String) = throwException(s"Internal Error! $msg") + def err(msg: String) = throwException(s"Internal Error! $msg") def unrollCoordinates(res: List[Arg], d: Data): (List[Arg], Data) = d.binding.get match { - case ChildBinding(parent) => d.getRef match { - case arg @ (_: Slot | _: Index) => unrollCoordinates(arg :: res, parent) - case other => err(s"Unroll coordinates failed for '$arg'! Unexpected arg '$other'") - } + case ChildBinding(parent) => + d.getRef match { + case arg @ (_: Slot | _: Index) => unrollCoordinates(arg :: res, parent) + case other => err(s"Unroll coordinates failed for '$arg'! Unexpected arg '$other'") + } case _ => (res, d) } def applyCoordinates(fullCoor: List[Arg], start: Data): Data = { @@ -133,15 +148,22 @@ object Lookupable { try { result.asInstanceOf[A] } catch { - case _: ClassCastException => err(s"Applying '$coor' to '$newRoot' somehow resulted in '$result'") + case _: ClassCastException => err(s"Applying '$coor' to '$newRoot' somehow resulted in '$result'") } } // TODO this logic is complicated, can any of it be unified with viewAs? // If `.viewAs` would capture its arguments, we could potentially use it // TODO Describe what this is doing at a high level - private[chisel3] def cloneViewToContext[A, B <: Data](data: B, cache: HashMap[Data, Data], ioMap: Option[Map[Data, Data]], context: Option[BaseModule]) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): B = { + private[chisel3] def cloneViewToContext[A, B <: Data]( + data: B, + cache: HashMap[Data, Data], + ioMap: Option[Map[Data, Data]], + context: Option[BaseModule] + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): B = { // alias to shorten lookups def lookupData[C <: Data](d: C) = doLookupData(d, cache, ioMap, context) @@ -150,29 +172,31 @@ object Lookupable { // We have to lookup the target(s) of the view since they may need to be underlying into the current context val newBinding = data.topBinding match { case ViewBinding(target) => ViewBinding(lookupData(reify(target))) - case avb @ AggregateViewBinding(map, targetOpt) => data match { - case _: Element => ViewBinding(lookupData(reify(map(data)))) - case _: Aggregate => - // Provide a 1:1 mapping if possible - val singleTargetOpt = targetOpt.filter(_ => avb == data.binding.get).flatMap(reifySingleData) - singleTargetOpt match { - case Some(singleTarget) => // It is 1:1! - // This is a little tricky because the values in newMap need to point to Elements of newTarget - val newTarget = lookupData(singleTarget) - val newMap = coiterate(result, data).map { case (res, from) => - (res: Data) -> mapRootAndExtractSubField(map(from), _ => newTarget) - }.toMap - AggregateViewBinding(newMap, Some(newTarget)) + case avb @ AggregateViewBinding(map, targetOpt) => + data match { + case _: Element => ViewBinding(lookupData(reify(map(data)))) + case _: Aggregate => + // Provide a 1:1 mapping if possible + val singleTargetOpt = targetOpt.filter(_ => avb == data.binding.get).flatMap(reifySingleData) + singleTargetOpt match { + case Some(singleTarget) => // It is 1:1! + // This is a little tricky because the values in newMap need to point to Elements of newTarget + val newTarget = lookupData(singleTarget) + val newMap = coiterate(result, data).map { + case (res, from) => + (res: Data) -> mapRootAndExtractSubField(map(from), _ => newTarget) + }.toMap + AggregateViewBinding(newMap, Some(newTarget)) - case None => // No 1:1 mapping so we have to do a flat binding - // Just remap each Element of this aggregate - val newMap = coiterate(result, data).map { - // Upcast res to Data since Maps are invariant in the Key type parameter - case (res, from) => (res: Data) -> lookupData(reify(map(from))) - }.toMap - AggregateViewBinding(newMap, None) - } - } + case None => // No 1:1 mapping so we have to do a flat binding + // Just remap each Element of this aggregate + val newMap = coiterate(result, data).map { + // Upcast res to Data since Maps are invariant in the Key type parameter + case (res, from) => (res: Data) -> lookupData(reify(map(from))) + }.toMap + AggregateViewBinding(newMap, None) + } + } } // TODO Unify the following with `.viewAs` @@ -188,7 +212,7 @@ object Lookupable { case (agg: Aggregate, _) if agg != result => Builder.unnamedViews += agg case _ => // Do nothing - } + } } result.bind(newBinding) @@ -196,6 +220,7 @@ object Lookupable { result.forceName(None, "view", Builder.viewNamespace) result } + /** Given a module (either original or a clone), clone it to a new context * * This function effectively recurses up the parents of module to find whether: @@ -208,8 +233,13 @@ object Lookupable { * @param context new context * @return original or clone in the new context */ - private[chisel3] def cloneModuleToContext[T <: BaseModule](module: Underlying[T], context: BaseModule) - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Underlying[T] = { + private[chisel3] def cloneModuleToContext[T <: BaseModule]( + module: Underlying[T], + context: BaseModule + )( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ): Underlying[T] = { // Recursive call def rec[A <: BaseModule](m: A): Underlying[A] = { def clone(x: A, p: Option[BaseModule], name: () => String): Underlying[A] = { @@ -221,7 +251,7 @@ object Lookupable { case (c, ctx) if ctx == c => Proto(c) case (c, ctx: IsClone[_]) if ctx.hasSameProto(c) => Clone(ctx.asInstanceOf[IsClone[A]]) case (c, ctx) if c._parent.isEmpty => Proto(c) - case (_, _) => + case (_, _) => cloneModuleToContext(Proto(m._parent.get), context) match { case Proto(p) => Proto(m) case Clone(p: BaseModule) => @@ -254,93 +284,107 @@ object Lookupable { type B = X type C = X def definitionLookup[A](that: A => B, definition: Definition[A]): C = that(definition.proto) - def instanceLookup[A](that: A => B, instance: Instance[A]): C = that(instance.proto) + def instanceLookup[A](that: A => B, instance: Instance[A]): C = that(instance.proto) } - implicit def lookupInstance[B <: BaseModule](implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) = new Lookupable[Instance[B]] { - type C = Instance[B] - def definitionLookup[A](that: A => Instance[B], definition: Definition[A]): C = { - val ret = that(definition.proto) - new Instance(cloneModuleToContext(ret.underlying, definition.getInnerDataContext.get)) - } - def instanceLookup[A](that: A => Instance[B], instance: Instance[A]): C = { - val ret = that(instance.proto) - instance.underlying match { - // If instance is just a normal module, no changing of context is necessary - case Proto(_) => new Instance(ret.underlying) - case Clone(_) => new Instance(cloneModuleToContext(ret.underlying, instance.getInnerDataContext.get)) + implicit def lookupInstance[B <: BaseModule](implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) = + new Lookupable[Instance[B]] { + type C = Instance[B] + def definitionLookup[A](that: A => Instance[B], definition: Definition[A]): C = { + val ret = that(definition.proto) + new Instance(cloneModuleToContext(ret.underlying, definition.getInnerDataContext.get)) } - } - } - - implicit def lookupModule[B <: BaseModule](implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) = new Lookupable[B] { - type C = Instance[B] - def definitionLookup[A](that: A => B, definition: Definition[A]): C = { - val ret = that(definition.proto) - new Instance(cloneModuleToContext(Proto(ret), definition.getInnerDataContext.get)) - } - def instanceLookup[A](that: A => B, instance: Instance[A]): C = { - val ret = that(instance.proto) - instance.underlying match { - // If instance is just a normal module, no changing of context is necessary - case Proto(_) => new Instance(Proto(ret)) - case Clone(_) => new Instance(cloneModuleToContext(Proto(ret), instance.getInnerDataContext.get)) + def instanceLookup[A](that: A => Instance[B], instance: Instance[A]): C = { + val ret = that(instance.proto) + instance.underlying match { + // If instance is just a normal module, no changing of context is necessary + case Proto(_) => new Instance(ret.underlying) + case Clone(_) => new Instance(cloneModuleToContext(ret.underlying, instance.getInnerDataContext.get)) + } } } - } - implicit def lookupData[B <: Data](implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) = new Lookupable[B] { - type C = B - def definitionLookup[A](that: A => B, definition: Definition[A]): C = { - val ret = that(definition.proto) - if (isView(ret)) { - ??? // TODO!!!!!! cloneViewToContext(ret, instance, ioMap, instance.getInnerDataContext) - } else { - doLookupData(ret, definition.cache, None, definition.getInnerDataContext) + implicit def lookupModule[B <: BaseModule](implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) = + new Lookupable[B] { + type C = Instance[B] + def definitionLookup[A](that: A => B, definition: Definition[A]): C = { + val ret = that(definition.proto) + new Instance(cloneModuleToContext(Proto(ret), definition.getInnerDataContext.get)) } - } - def instanceLookup[A](that: A => B, instance: Instance[A]): C = { - val ret = that(instance.proto) - val ioMap: Option[Map[Data, Data]] = instance.underlying match { - case Clone(x: ModuleClone[_]) => Some(x.ioMap) - case Proto(x: BaseModule) => Some(x.getChiselPorts.map { case (_, data) => data -> data }.toMap) - case _ => None + def instanceLookup[A](that: A => B, instance: Instance[A]): C = { + val ret = that(instance.proto) + instance.underlying match { + // If instance is just a normal module, no changing of context is necessary + case Proto(_) => new Instance(Proto(ret)) + case Clone(_) => new Instance(cloneModuleToContext(Proto(ret), instance.getInnerDataContext.get)) + } } - if (isView(ret)) { - cloneViewToContext(ret, instance.cache, ioMap, instance.getInnerDataContext) - } else { - doLookupData(ret, instance.cache, ioMap, instance.getInnerDataContext) + } + + implicit def lookupData[B <: Data](implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) = + new Lookupable[B] { + type C = B + def definitionLookup[A](that: A => B, definition: Definition[A]): C = { + val ret = that(definition.proto) + if (isView(ret)) { + ??? // TODO!!!!!! cloneViewToContext(ret, instance, ioMap, instance.getInnerDataContext) + } else { + doLookupData(ret, definition.cache, None, definition.getInnerDataContext) + } } + def instanceLookup[A](that: A => B, instance: Instance[A]): C = { + val ret = that(instance.proto) + val ioMap: Option[Map[Data, Data]] = instance.underlying match { + case Clone(x: ModuleClone[_]) => Some(x.ioMap) + case Proto(x: BaseModule) => Some(x.getChiselPorts.map { case (_, data) => data -> data }.toMap) + case _ => None + } + if (isView(ret)) { + cloneViewToContext(ret, instance.cache, ioMap, instance.getInnerDataContext) + } else { + doLookupData(ret, instance.cache, ioMap, instance.getInnerDataContext) + } + } } - } import scala.language.higherKinds // Required to avoid warning for lookupIterable type parameter - implicit def lookupIterable[B, F[_] <: Iterable[_]](implicit sourceInfo: SourceInfo, compileOptions: CompileOptions, lookupable: Lookupable[B]) = new Lookupable[F[B]] { + implicit def lookupIterable[B, F[_] <: Iterable[_]]( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions, + lookupable: Lookupable[B] + ) = new Lookupable[F[B]] { type C = F[lookupable.C] def definitionLookup[A](that: A => F[B], definition: Definition[A]): C = { val ret = that(definition.proto).asInstanceOf[Iterable[B]] - ret.map{ x: B => lookupable.definitionLookup[A](_ => x, definition) }.asInstanceOf[C] + ret.map { x: B => lookupable.definitionLookup[A](_ => x, definition) }.asInstanceOf[C] } def instanceLookup[A](that: A => F[B], instance: Instance[A]): C = { import instance._ val ret = that(proto).asInstanceOf[Iterable[B]] - ret.map{ x: B => lookupable.instanceLookup[A](_ => x, instance) }.asInstanceOf[C] + ret.map { x: B => lookupable.instanceLookup[A](_ => x, instance) }.asInstanceOf[C] } } - implicit def lookupOption[B](implicit sourceInfo: SourceInfo, compileOptions: CompileOptions, lookupable: Lookupable[B]) = new Lookupable[Option[B]] { + implicit def lookupOption[B]( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions, + lookupable: Lookupable[B] + ) = new Lookupable[Option[B]] { type C = Option[lookupable.C] def definitionLookup[A](that: A => Option[B], definition: Definition[A]): C = { val ret = that(definition.proto) - ret.map{ x: B => lookupable.definitionLookup[A](_ => x, definition) } + ret.map { x: B => lookupable.definitionLookup[A](_ => x, definition) } } def instanceLookup[A](that: A => Option[B], instance: Instance[A]): C = { import instance._ val ret = that(proto) - ret.map{ x: B => lookupable.instanceLookup[A](_ => x, instance) } + ret.map { x: B => lookupable.instanceLookup[A](_ => x, instance) } } } - implicit def lookupIsInstantiable[B <: IsInstantiable](implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) = new Lookupable[B] { + implicit def lookupIsInstantiable[B <: IsInstantiable]( + implicit sourceInfo: SourceInfo, + compileOptions: CompileOptions + ) = new Lookupable[B] { type C = Instance[B] def definitionLookup[A](that: A => B, definition: Definition[A]): C = { val ret = that(definition.proto) @@ -360,8 +404,9 @@ object Lookupable { } } - implicit def lookupIsLookupable[B <: IsLookupable](implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) = new SimpleLookupable[B]() - + implicit def lookupIsLookupable[B <: IsLookupable](implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) = + new SimpleLookupable[B]() + implicit val lookupInt = new SimpleLookupable[Int]() implicit val lookupByte = new SimpleLookupable[Byte]() implicit val lookupShort = new SimpleLookupable[Short]() diff --git a/core/src/main/scala/chisel3/experimental/package.scala b/core/src/main/scala/chisel3/experimental/package.scala index 5397a1c3..ce258a25 100644 --- a/core/src/main/scala/chisel3/experimental/package.scala +++ b/core/src/main/scala/chisel3/experimental/package.scala @@ -16,9 +16,9 @@ package object experimental { 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 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) @@ -32,6 +32,7 @@ package object experimental { 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. @@ -41,13 +42,18 @@ package object experimental { * q2_io.enq <> q1.io.deq * }}} */ - def apply(proto: BaseModule)(implicit sourceInfo: chisel3.internal.sourceinfo.SourceInfo, compileOptions: CompileOptions): ClonePorts = { + def apply( + proto: BaseModule + )( + implicit sourceInfo: chisel3.internal.sourceinfo.SourceInfo, + compileOptions: CompileOptions + ): ClonePorts = { BaseModule.cloneIORecord(proto) } } val requireIsHardware = chisel3.internal.requireIsHardware - val requireIsChiselType = chisel3.internal.requireIsChiselType + val requireIsChiselType = chisel3.internal.requireIsChiselType type Direction = ActualDirection val Direction = ActualDirection @@ -68,6 +74,7 @@ package object experimental { class dump extends chisel3.internal.naming.dump class treedump extends chisel3.internal.naming.treedump + /** Experimental macro for naming Chisel hardware values * * By default, Chisel uses reflection for naming which only works for public fields of `Bundle` @@ -94,6 +101,7 @@ package object experimental { * }}} */ class chiselName extends chisel3.internal.naming.chiselName + /** Do not name instances of this type in [[chiselName]] * * By default, `chiselName` will include `val` names of instances of annotated classes as a @@ -138,6 +146,7 @@ package object experimental { */ object VecLiterals { implicit class AddVecLiteralConstructor[T <: Data](x: Vec[T]) { + /** Given a generator of a list tuples of the form [Int, Data] * constructs a Vec literal, parallel concept to `BundleLiteral` * @@ -150,15 +159,16 @@ package object experimental { } implicit class AddObjectLiteralConstructor(x: Vec.type) { + /** This provides an literal construction method for cases using * object `Vec` as in `Vec.Lit(1.U, 2.U)` */ def Lit[T <: Data](elems: T*)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Vec[T] = { require(elems.nonEmpty, s"Lit.Vec(...) must have at least one element") - val indexElements = elems.zipWithIndex.map { case (element, index) => (index, element)} + val indexElements = elems.zipWithIndex.map { case (element, index) => (index, element) } val widestElement = elems.maxBy(_.getWidth) val vec: Vec[T] = Vec.apply(indexElements.length, chiselTypeOf(widestElement)) - vec.Lit(indexElements:_*) + vec.Lit(indexElements: _*) } } } @@ -178,7 +188,7 @@ package object experimental { */ final class HWTuple2[+A <: Data, +B <: Data] private[chisel3] (val _1: A, val _2: B) extends Bundle()(Strict) { // Because this implementation exists in chisel3.core, it cannot compile with the plugin, so we implement the behavior manually - override protected def _usingPlugin: Boolean = true + override protected def _usingPlugin: Boolean = true override protected def _cloneTypeImpl: Bundle = new HWTuple2(chiselTypeClone(_1), chiselTypeClone(_2)) } @@ -188,12 +198,16 @@ package object experimental { * `chisel3.experimental.conversions` */ final class HWTuple3[+A <: Data, +B <: Data, +C <: Data] private[chisel3] ( - val _1: A, val _2: B, val _3: C - ) extends Bundle()(Strict) { + val _1: A, + val _2: B, + val _3: C) + extends Bundle()(Strict) { // Because this implementation exists in chisel3.core, it cannot compile with the plugin, so we implement the behavior manually override protected def _usingPlugin: Boolean = true override protected def _cloneTypeImpl: Bundle = new HWTuple3( - chiselTypeClone(_1), chiselTypeClone(_2), chiselTypeClone(_3) + chiselTypeClone(_1), + chiselTypeClone(_2), + chiselTypeClone(_3) ) } @@ -203,12 +217,18 @@ package object experimental { * `chisel3.experimental.conversions` */ final class HWTuple4[+A <: Data, +B <: Data, +C <: Data, +D <: Data] private[chisel3] ( - val _1: A, val _2: B, val _3: C, val _4: D - ) extends Bundle()(Strict) { + val _1: A, + val _2: B, + val _3: C, + val _4: D) + extends Bundle()(Strict) { // Because this implementation exists in chisel3.core, it cannot compile with the plugin, so we implement the behavior manually override protected def _usingPlugin: Boolean = true override protected def _cloneTypeImpl: Bundle = new HWTuple4( - chiselTypeClone(_1), chiselTypeClone(_2), chiselTypeClone(_3), chiselTypeClone(_4) + chiselTypeClone(_1), + chiselTypeClone(_2), + chiselTypeClone(_3), + chiselTypeClone(_4) ) } @@ -218,12 +238,20 @@ package object experimental { * `chisel3.experimental.conversions` */ final class HWTuple5[+A <: Data, +B <: Data, +C <: Data, +D <: Data, +E <: Data] private[chisel3] ( - val _1: A, val _2: B, val _3: C, val _4: D, val _5: E - ) extends Bundle()(Strict) { + val _1: A, + val _2: B, + val _3: C, + val _4: D, + val _5: E) + extends Bundle()(Strict) { // Because this implementation exists in chisel3.core, it cannot compile with the plugin, so we implement the behavior manually override protected def _usingPlugin: Boolean = true override protected def _cloneTypeImpl: Bundle = new HWTuple5( - chiselTypeClone(_1), chiselTypeClone(_2), chiselTypeClone(_3), chiselTypeClone(_4), chiselTypeClone(_5) + chiselTypeClone(_1), + chiselTypeClone(_2), + chiselTypeClone(_3), + chiselTypeClone(_4), + chiselTypeClone(_5) ) } @@ -233,12 +261,21 @@ package object experimental { * `chisel3.experimental.conversions` */ final class HWTuple6[+A <: Data, +B <: Data, +C <: Data, +D <: Data, +E <: Data, +F <: Data] private[chisel3] ( - val _1: A, val _2: B, val _3: C, val _4: D, val _5: E, val _6: F - ) extends Bundle()(Strict) { + val _1: A, + val _2: B, + val _3: C, + val _4: D, + val _5: E, + val _6: F) + extends Bundle()(Strict) { // Because this implementation exists in chisel3.core, it cannot compile with the plugin, so we implement the behavior manually override protected def _usingPlugin: Boolean = true override protected def _cloneTypeImpl: Bundle = new HWTuple6( - chiselTypeClone(_1), chiselTypeClone(_2), chiselTypeClone(_3), chiselTypeClone(_4), chiselTypeClone(_5), + chiselTypeClone(_1), + chiselTypeClone(_2), + chiselTypeClone(_3), + chiselTypeClone(_4), + chiselTypeClone(_5), chiselTypeClone(_6) ) } @@ -248,14 +285,33 @@ package object experimental { * Users may not instantiate this class directly. Instead they should use the implicit conversion from `Tuple7` in * `chisel3.experimental.conversions` */ - final class HWTuple7[+A <: Data, +B <: Data, +C <: Data, +D <: Data, +E <: Data, +F <: Data, +G <: Data] private[chisel3] ( - val _1: A, val _2: B, val _3: C, val _4: D, val _5: E, val _6: F, val _7: G - ) extends Bundle()(Strict) { + final class HWTuple7[ + +A <: Data, + +B <: Data, + +C <: Data, + +D <: Data, + +E <: Data, + +F <: Data, + +G <: Data + ] private[chisel3] ( + val _1: A, + val _2: B, + val _3: C, + val _4: D, + val _5: E, + val _6: F, + val _7: G) + extends Bundle()(Strict) { // Because this implementation exists in chisel3.core, it cannot compile with the plugin, so we implement the behavior manually override protected def _usingPlugin: Boolean = true override protected def _cloneTypeImpl: Bundle = new HWTuple7( - chiselTypeClone(_1), chiselTypeClone(_2), chiselTypeClone(_3), chiselTypeClone(_4), chiselTypeClone(_5), - chiselTypeClone(_6), chiselTypeClone(_7) + chiselTypeClone(_1), + chiselTypeClone(_2), + chiselTypeClone(_3), + chiselTypeClone(_4), + chiselTypeClone(_5), + chiselTypeClone(_6), + chiselTypeClone(_7) ) } @@ -265,15 +321,35 @@ package object experimental { * `chisel3.experimental.conversions` */ final class HWTuple8[ - +A <: Data, +B <: Data, +C <: Data, +D <: Data, +E <: Data, +F <: Data, +G <: Data, +H <: Data + +A <: Data, + +B <: Data, + +C <: Data, + +D <: Data, + +E <: Data, + +F <: Data, + +G <: Data, + +H <: Data ] private[chisel3] ( - val _1: A, val _2: B, val _3: C, val _4: D, val _5: E, val _6: F, val _7: G, val _8: H - ) extends Bundle()(Strict) { + val _1: A, + val _2: B, + val _3: C, + val _4: D, + val _5: E, + val _6: F, + val _7: G, + val _8: H) + extends Bundle()(Strict) { // Because this implementation exists in chisel3.core, it cannot compile with the plugin, so we implement the behavior manually override protected def _usingPlugin: Boolean = true override protected def _cloneTypeImpl: Bundle = new HWTuple8( - chiselTypeClone(_1), chiselTypeClone(_2), chiselTypeClone(_3), chiselTypeClone(_4), chiselTypeClone(_5), - chiselTypeClone(_6), chiselTypeClone(_7), chiselTypeClone(_8) + chiselTypeClone(_1), + chiselTypeClone(_2), + chiselTypeClone(_3), + chiselTypeClone(_4), + chiselTypeClone(_5), + chiselTypeClone(_6), + chiselTypeClone(_7), + chiselTypeClone(_8) ) } @@ -283,34 +359,82 @@ package object experimental { * `chisel3.experimental.conversions` */ final class HWTuple9[ - +A <: Data, +B <: Data, +C <: Data, +D <: Data, +E <: Data, +F <: Data, +G <: Data, +H <: Data, +I <: Data + +A <: Data, + +B <: Data, + +C <: Data, + +D <: Data, + +E <: Data, + +F <: Data, + +G <: Data, + +H <: Data, + +I <: Data ] private[chisel3] ( - val _1: A, val _2: B, val _3: C, val _4: D, val _5: E, val _6: F, val _7: G, val _8: H, val _9: I - ) extends Bundle()(Strict) { + val _1: A, + val _2: B, + val _3: C, + val _4: D, + val _5: E, + val _6: F, + val _7: G, + val _8: H, + val _9: I) + extends Bundle()(Strict) { // Because this implementation exists in chisel3.core, it cannot compile with the plugin, so we implement the behavior manually override protected def _usingPlugin: Boolean = true override protected def _cloneTypeImpl: Bundle = new HWTuple9( - chiselTypeClone(_1), chiselTypeClone(_2), chiselTypeClone(_3), chiselTypeClone(_4), chiselTypeClone(_5), - chiselTypeClone(_6), chiselTypeClone(_7), chiselTypeClone(_8), chiselTypeClone(_9) + chiselTypeClone(_1), + chiselTypeClone(_2), + chiselTypeClone(_3), + chiselTypeClone(_4), + chiselTypeClone(_5), + chiselTypeClone(_6), + chiselTypeClone(_7), + chiselTypeClone(_8), + chiselTypeClone(_9) ) } - /** [[Data]] equivalent of Scala's [[Tuple9]] * * Users may not instantiate this class directly. Instead they should use the implicit conversion from `Tuple9` in * `chisel3.experimental.conversions` */ final class HWTuple10[ - +A <: Data, +B <: Data, +C <: Data, +D <: Data, +E <: Data, +F <: Data, +G <: Data, +H <: Data, +I <: Data, +J <: Data + +A <: Data, + +B <: Data, + +C <: Data, + +D <: Data, + +E <: Data, + +F <: Data, + +G <: Data, + +H <: Data, + +I <: Data, + +J <: Data ] private[chisel3] ( - val _1: A, val _2: B, val _3: C, val _4: D, val _5: E, val _6: F, val _7: G, val _8: H, val _9: I, val _10: J - ) extends Bundle()(Strict) { + val _1: A, + val _2: B, + val _3: C, + val _4: D, + val _5: E, + val _6: F, + val _7: G, + val _8: H, + val _9: I, + val _10: J) + extends Bundle()(Strict) { // Because this implementation exists in chisel3.core, it cannot compile with the plugin, so we implement the behavior manually override protected def _usingPlugin: Boolean = true override protected def _cloneTypeImpl: Bundle = new HWTuple10( - chiselTypeClone(_1), chiselTypeClone(_2), chiselTypeClone(_3), chiselTypeClone(_4), chiselTypeClone(_5), - chiselTypeClone(_6), chiselTypeClone(_7), chiselTypeClone(_8), chiselTypeClone(_9), chiselTypeClone(_10) + chiselTypeClone(_1), + chiselTypeClone(_2), + chiselTypeClone(_3), + chiselTypeClone(_4), + chiselTypeClone(_5), + chiselTypeClone(_6), + chiselTypeClone(_7), + chiselTypeClone(_8), + chiselTypeClone(_9), + chiselTypeClone(_10) ) } } diff --git a/core/src/main/scala/chisel3/internal/BiConnect.scala b/core/src/main/scala/chisel3/internal/BiConnect.scala index aa58cb95..5b4ad1b9 100644 --- a/core/src/main/scala/chisel3/internal/BiConnect.scala +++ b/core/src/main/scala/chisel3/internal/BiConnect.scala @@ -4,7 +4,7 @@ package chisel3.internal import chisel3._ import chisel3.experimental.dataview.reify -import chisel3.experimental.{Analog, BaseModule, attach} +import chisel3.experimental.{attach, Analog, BaseModule} import chisel3.internal.Builder.pushCommand import chisel3.internal.firrtl.{Connect, DefInvalid} @@ -14,18 +14,17 @@ import chisel3.internal.sourceinfo._ import scala.annotation.tailrec /** -* BiConnect.connect executes a bidirectional connection element-wise. -* -* Note that the arguments are left and right (not source and sink) so the -* intent is for the operation to be commutative. -* -* The connect operation will recurse down the left Data (with the right Data). -* An exception will be thrown if a movement through the left cannot be matched -* in the right (or if the right side has extra fields). -* -* See elemConnect for details on how the root connections are issued. -* -*/ + * BiConnect.connect executes a bidirectional connection element-wise. + * + * Note that the arguments are left and right (not source and sink) so the + * intent is for the operation to be commutative. + * + * The connect operation will recurse down the left Data (with the right Data). + * An exception will be thrown if a movement through the left cannot be matched + * in the right (or if the right side has extra fields). + * + * See elemConnect for details on how the root connections are issued. + */ private[chisel3] object BiConnect { // These are all the possible exceptions that can be thrown. @@ -53,26 +52,32 @@ private[chisel3] object BiConnect { BiConnectException(": DontCare cannot be a connection sink (LHS)") /** This function is what recursively tries to connect a left and right together - * - * There is some cleverness in the use of internal try-catch to catch exceptions - * during the recursive decent and then rethrow them with extra information added. - * This gives the user a 'path' to where in the connections things went wrong. - */ - def connect(sourceInfo: SourceInfo, connectCompileOptions: CompileOptions, left: Data, right: Data, context_mod: RawModule): Unit = { + * + * There is some cleverness in the use of internal try-catch to catch exceptions + * during the recursive decent and then rethrow them with extra information added. + * This gives the user a 'path' to where in the connections things went wrong. + */ + def connect( + sourceInfo: SourceInfo, + connectCompileOptions: CompileOptions, + left: Data, + right: Data, + context_mod: RawModule + ): Unit = { (left, right) match { // Handle element case (root case) case (left_a: Analog, right_a: Analog) => try { markAnalogConnected(sourceInfo, left_a, context_mod) markAnalogConnected(sourceInfo, right_a, context_mod) - } catch { // convert attach exceptions to BiConnectExceptions + } catch { // convert attach exceptions to BiConnectExceptions case attach.AttachException(message) => throw BiConnectException(message) } attach.impl(Seq(left_a, right_a), context_mod)(sourceInfo) case (left_a: Analog, DontCare) => try { markAnalogConnected(sourceInfo, left_a, context_mod) - } catch { // convert attach exceptions to BiConnectExceptions + } catch { // convert attach exceptions to BiConnectExceptions case attach.AttachException(message) => throw BiConnectException(message) } pushCommand(DefInvalid(sourceInfo, left_a.lref)) @@ -82,7 +87,7 @@ private[chisel3] object BiConnect { // TODO(twigg): Verify the element-level classes are connectable } // Handle Vec case - case (left_v: Vec[Data@unchecked], right_v: Vec[Data@unchecked]) => { + case (left_v: Vec[Data @unchecked], right_v: Vec[Data @unchecked]) => { if (left_v.length != right_v.length) { throw MismatchedVecException } @@ -96,7 +101,7 @@ private[chisel3] object BiConnect { } } // Handle Vec connected to DontCare - case (left_v: Vec[Data@unchecked], DontCare) => { + case (left_v: Vec[Data @unchecked], DontCare) => { for (idx <- 0 until left_v.length) { try { implicit val compileOptions = connectCompileOptions @@ -107,7 +112,7 @@ private[chisel3] object BiConnect { } } // Handle DontCare connected to Vec - case (DontCare, right_v: Vec[Data@unchecked]) => { + case (DontCare, right_v: Vec[Data @unchecked]) => { for (idx <- 0 until right_v.length) { try { implicit val compileOptions = connectCompileOptions @@ -135,7 +140,7 @@ private[chisel3] object BiConnect { case _ => true } } - def canBeSink(data: Data): Boolean = traceFlow(true, data) + def canBeSink(data: Data): Boolean = traceFlow(true, data) def canBeSource(data: Data): Boolean = traceFlow(false, data) // chisel3 <> is commutative but FIRRTL <- is not val flipConnection = !canBeSink(left_r) || !canBeSource(right_r) @@ -181,21 +186,23 @@ private[chisel3] object BiConnect { } // Do connection of two Records - def recordConnect(sourceInfo: SourceInfo, - connectCompileOptions: CompileOptions, - left_r: Record, - right_r: Record, - context_mod: RawModule): Unit = { + def recordConnect( + sourceInfo: SourceInfo, + connectCompileOptions: CompileOptions, + left_r: Record, + right_r: Record, + context_mod: RawModule + ): Unit = { // Verify right has no extra fields that left doesn't have - for((field, right_sub) <- right_r.elements) { - if(!left_r.elements.isDefinedAt(field)) { + for ((field, right_sub) <- right_r.elements) { + if (!left_r.elements.isDefinedAt(field)) { if (connectCompileOptions.connectFieldsMustMatch) { throw MissingLeftFieldException(field) } } } // For each field in left, descend with right - for((field, left_sub) <- left_r.elements) { + for ((field, left_sub) <- left_r.elements) { try { right_r.elements.get(field) match { case Some(right_sub) => connect(sourceInfo, connectCompileOptions, left_sub, right_sub, context_mod) @@ -211,7 +218,6 @@ private[chisel3] object BiConnect { } } - // These functions (finally) issue the connection operation // Issue with right as sink, left as source private def issueConnectL2R(left: Element, right: Element)(implicit sourceInfo: SourceInfo): Unit = { @@ -238,13 +244,19 @@ private[chisel3] object BiConnect { // This function checks if element-level connection operation allowed. // Then it either issues it or throws the appropriate exception. - def elemConnect(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions, _left: Element, _right: Element, context_mod: RawModule): Unit = { - import BindingDirection.{Internal, Input, Output} // Using extensively so import these + def elemConnect( + implicit sourceInfo: SourceInfo, + connectCompileOptions: CompileOptions, + _left: Element, + _right: Element, + context_mod: RawModule + ): Unit = { + import BindingDirection.{Input, Internal, Output} // Using extensively so import these val left = reify(_left) val right = reify(_right) // If left or right have no location, assume in context module // This can occur if one of them is a literal, unbound will error previously - val left_mod: BaseModule = left.topBinding.location.getOrElse(context_mod) + val left_mod: BaseModule = left.topBinding.location.getOrElse(context_mod) val right_mod: BaseModule = right.topBinding.location.getOrElse(context_mod) val left_parent = Builder.retrieveParent(left_mod, context_mod).getOrElse(None) @@ -254,54 +266,54 @@ private[chisel3] object BiConnect { val right_direction = BindingDirection.from(right.topBinding, right.direction) // CASE: Context is same module as left node and right node is in a child module - if((left_mod == context_mod) && (right_parent == context_mod)) { + if ((left_mod == context_mod) && (right_parent == context_mod)) { // Thus, right node better be a port node and thus have a direction hint ((left_direction, right_direction): @unchecked) match { // CURRENT MOD CHILD MOD - case (Input, Input) => issueConnectL2R(left, right) - case (Internal, Input) => issueConnectL2R(left, right) + case (Input, Input) => issueConnectL2R(left, right) + case (Internal, Input) => issueConnectL2R(left, right) - case (Output, Output) => issueConnectR2L(left, right) - case (Internal, Output) => issueConnectR2L(left, right) + case (Output, Output) => issueConnectR2L(left, right) + case (Internal, Output) => issueConnectR2L(left, right) - case (Input, Output) => throw BothDriversException - case (Output, Input) => throw NeitherDriverException - case (_, Internal) => throw UnknownRelationException + case (Input, Output) => throw BothDriversException + case (Output, Input) => throw NeitherDriverException + case (_, Internal) => throw UnknownRelationException } } // CASE: Context is same module as right node and left node is in child module - else if((right_mod == context_mod) && (left_parent == context_mod)) { + else if ((right_mod == context_mod) && (left_parent == context_mod)) { // Thus, left node better be a port node and thus have a direction hint ((left_direction, right_direction): @unchecked) match { // CHILD MOD CURRENT MOD - case (Input, Input) => issueConnectR2L(left, right) - case (Input, Internal) => issueConnectR2L(left, right) + case (Input, Input) => issueConnectR2L(left, right) + case (Input, Internal) => issueConnectR2L(left, right) - case (Output, Output) => issueConnectL2R(left, right) - case (Output, Internal) => issueConnectL2R(left, right) + case (Output, Output) => issueConnectL2R(left, right) + case (Output, Internal) => issueConnectL2R(left, right) - case (Input, Output) => throw NeitherDriverException - case (Output, Input) => throw BothDriversException - case (Internal, _) => throw UnknownRelationException + case (Input, Output) => throw NeitherDriverException + case (Output, Input) => throw BothDriversException + case (Internal, _) => throw UnknownRelationException } } // CASE: Context is same module that both left node and right node are in - else if( (context_mod == left_mod) && (context_mod == right_mod) ) { + else if ((context_mod == left_mod) && (context_mod == right_mod)) { ((left_direction, right_direction): @unchecked) match { // CURRENT MOD CURRENT MOD - case (Input, Output) => issueConnectL2R(left, right) - case (Input, Internal) => issueConnectL2R(left, right) - case (Internal, Output) => issueConnectL2R(left, right) + case (Input, Output) => issueConnectL2R(left, right) + case (Input, Internal) => issueConnectL2R(left, right) + case (Internal, Output) => issueConnectL2R(left, right) - case (Output, Input) => issueConnectR2L(left, right) - case (Output, Internal) => issueConnectR2L(left, right) - case (Internal, Input) => issueConnectR2L(left, right) + case (Output, Input) => issueConnectR2L(left, right) + case (Output, Internal) => issueConnectR2L(left, right) + case (Internal, Input) => issueConnectR2L(left, right) - case (Input, Input) => throw BothDriversException - case (Output, Output) => throw BothDriversException - case (Internal, Internal) => { + case (Input, Input) => throw BothDriversException + case (Output, Output) => throw BothDriversException + case (Internal, Internal) => { if (connectCompileOptions.dontAssumeDirectionality) { throw UnknownDriverException } else { @@ -314,22 +326,22 @@ private[chisel3] object BiConnect { // CASE: Context is the parent module of both the module containing left node // and the module containing right node // Note: This includes case when left and right in same module but in parent - else if((left_parent == context_mod) && (right_parent == context_mod)) { + else if ((left_parent == context_mod) && (right_parent == context_mod)) { // Thus both nodes must be ports and have a direction hint ((left_direction, right_direction): @unchecked) match { // CHILD MOD CHILD MOD - case (Input, Output) => issueConnectR2L(left, right) - case (Output, Input) => issueConnectL2R(left, right) + case (Input, Output) => issueConnectR2L(left, right) + case (Output, Input) => issueConnectL2R(left, right) - case (Input, Input) => throw NeitherDriverException - case (Output, Output) => throw BothDriversException - case (_, Internal) => + case (Input, Input) => throw NeitherDriverException + case (Output, Output) => throw BothDriversException + case (_, Internal) => if (connectCompileOptions.dontAssumeDirectionality) { throw UnknownRelationException } else { issueConnectR2L(left, right) } - case (Internal, _) => + case (Internal, _) => if (connectCompileOptions.dontAssumeDirectionality) { throw UnknownRelationException } else { @@ -347,7 +359,7 @@ private[chisel3] object BiConnect { def markAnalogConnected(implicit sourceInfo: SourceInfo, analog: Analog, contextModule: RawModule): Unit = { analog.biConnectLocs.get(contextModule) match { case Some(sl) => throw AttachAlreadyBulkConnectedException(sl) - case None => // Do nothing + case None => // Do nothing } // Mark bulk connected analog.biConnectLocs(contextModule) = sourceInfo diff --git a/core/src/main/scala/chisel3/internal/Binding.scala b/core/src/main/scala/chisel3/internal/Binding.scala index a0dcc20c..6431dd23 100644 --- a/core/src/main/scala/chisel3/internal/Binding.scala +++ b/core/src/main/scala/chisel3/internal/Binding.scala @@ -12,14 +12,16 @@ import scala.collection.immutable.VectorMap */ object requireIsHardware { def apply(node: Data, msg: String = ""): Unit = { - node._parent match { // Compatibility layer hack + node._parent match { // Compatibility layer hack case Some(x: BaseModule) => x._compatAutoWrapPorts case _ => } if (!node.isSynthesizable) { val prefix = if (msg.nonEmpty) s"$msg " else "" - throw ExpectedHardwareException(s"$prefix'$node' must be hardware, " + - "not a bare Chisel type. Perhaps you forgot to wrap it in Wire(_) or IO(_)?") + throw ExpectedHardwareException( + s"$prefix'$node' must be hardware, " + + "not a bare Chisel type. Perhaps you forgot to wrap it in Wire(_) or IO(_)?" + ) } } } @@ -36,12 +38,15 @@ object requireIsChiselType { // Element only direction used for the Binding system only. private[chisel3] sealed abstract class BindingDirection private[chisel3] object BindingDirection { + /** Internal type or wire */ case object Internal extends BindingDirection + /** Module port with output direction */ case object Output extends BindingDirection + /** Module port with input direction */ case object Input extends BindingDirection @@ -50,11 +55,12 @@ private[chisel3] object BindingDirection { */ def from(binding: TopBinding, direction: ActualDirection): BindingDirection = { binding match { - case PortBinding(_) => direction match { - case ActualDirection.Output => Output - case ActualDirection.Input => Input - case dir => throw new RuntimeException(s"Unexpected port element direction '$dir'") - } + case PortBinding(_) => + direction match { + case ActualDirection.Output => Output + case ActualDirection.Input => Input + case dir => throw new RuntimeException(s"Unexpected port element direction '$dir'") + } case _ => Internal } } @@ -81,7 +87,7 @@ sealed trait ConstrainedBinding extends TopBinding { // This allows aspect modules to pretend to be enclosed modules for connectivity checking, // inside vs outside instance checking, etc. Builder.aspectModule(enclosure) match { - case None => Some(enclosure) + case None => Some(enclosure) case Some(aspect) => Some(aspect) } } @@ -100,18 +106,29 @@ sealed trait ConditionalDeclarable extends TopBinding { case class PortBinding(enclosure: BaseModule) extends ConstrainedBinding -case class OpBinding(enclosure: RawModule, visibility: Option[WhenContext]) extends ConstrainedBinding with ReadOnlyBinding with ConditionalDeclarable -case class MemoryPortBinding(enclosure: RawModule, visibility: Option[WhenContext]) extends ConstrainedBinding with ConditionalDeclarable -case class RegBinding(enclosure: RawModule, visibility: Option[WhenContext]) extends ConstrainedBinding with ConditionalDeclarable -case class WireBinding(enclosure: RawModule, visibility: Option[WhenContext]) extends ConstrainedBinding with ConditionalDeclarable +case class OpBinding(enclosure: RawModule, visibility: Option[WhenContext]) + extends ConstrainedBinding + with ReadOnlyBinding + with ConditionalDeclarable +case class MemoryPortBinding(enclosure: RawModule, visibility: Option[WhenContext]) + extends ConstrainedBinding + with ConditionalDeclarable +case class RegBinding(enclosure: RawModule, visibility: Option[WhenContext]) + extends ConstrainedBinding + with ConditionalDeclarable +case class WireBinding(enclosure: RawModule, visibility: Option[WhenContext]) + extends ConstrainedBinding + with ConditionalDeclarable case class ChildBinding(parent: Data) extends Binding { def location: Option[BaseModule] = parent.topBinding.location } + /** Special binding for Vec.sample_element */ case class SampleElementBinding[T <: Data](parent: Vec[T]) extends Binding { def location = parent.topBinding.location } + /** Special binding for Mem types */ case class MemTypeBinding[T <: Data](parent: MemBase[T]) extends Binding { def location: Option[BaseModule] = parent._parent @@ -122,12 +139,13 @@ case class DontCareBinding() extends UnconstrainedBinding // Views currently only support 1:1 Element-level mappings private[chisel3] case class ViewBinding(target: Element) extends UnconstrainedBinding + /** Binding for Aggregate Views * @param childMap Mapping from children of this view to each child's target * @param target Optional Data this Aggregate views if the view is total and the target is a Data */ -private[chisel3] case class AggregateViewBinding(childMap: Map[Data, Element], target: Option[Data]) extends UnconstrainedBinding - +private[chisel3] case class AggregateViewBinding(childMap: Map[Data, Element], target: Option[Data]) + extends UnconstrainedBinding /** Binding for Data's returned from accessing an Instance/Definition members, if not readable/writable port */ private[chisel3] case object CrossModuleBinding extends TopBinding { diff --git a/core/src/main/scala/chisel3/internal/Builder.scala b/core/src/main/scala/chisel3/internal/Builder.scala index 71894887..fb6ebcc7 100644 --- a/core/src/main/scala/chisel3/internal/Builder.scala +++ b/core/src/main/scala/chisel3/internal/Builder.scala @@ -6,7 +6,7 @@ import scala.util.DynamicVariable import scala.collection.mutable.ArrayBuffer import chisel3._ import chisel3.experimental._ -import chisel3.experimental.hierarchy.{Instance, Clone} +import chisel3.experimental.hierarchy.{Clone, Instance} import chisel3.internal.firrtl._ import chisel3.internal.naming._ import _root_.firrtl.annotations.{CircuitName, ComponentName, IsMember, ModuleName, Named, ReferenceTarget} @@ -34,8 +34,8 @@ private[chisel3] class Namespace(keywords: Set[String]) { private def sanitize(s: String, leadingDigitOk: Boolean = false): String = { // TODO what character set does FIRRTL truly support? using ANSI C for now def legalStart(c: Char) = (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || c == '_' - def legal(c: Char) = legalStart(c) || (c >= '0' && c <= '9') - val res = s filter legal + def legal(c: Char) = legalStart(c) || (c >= '0' && c <= '9') + val res = s.filter(legal) val headOk = (!res.isEmpty) && (leadingDigitOk || legalStart(res.head)) if (headOk) res else s"_$res" } @@ -55,6 +55,7 @@ private[chisel3] class Namespace(keywords: Set[String]) { } private[chisel3] object Namespace { + /** Constructs an empty Namespace */ def empty: Namespace = new Namespace(Set.empty[String]) } @@ -73,14 +74,17 @@ private[chisel3] class IdGen { * These are only valid once the design has been elaborated, and should not be used during its construction. */ trait InstanceId { - def instanceName: String - def pathName: String + def instanceName: String + def pathName: String def parentPathName: String - def parentModName: String + def parentModName: String + /** Returns a FIRRTL Named that refers to this object in the elaborated hardware graph */ def toNamed: Named + /** Returns a FIRRTL IsMember that refers to this object in the elaborated hardware graph */ def toTarget: IsMember + /** Returns a FIRRTL IsMember that refers to the absolute path to this object in the elaborated hardware graph */ def toAbsoluteTarget: IsMember } @@ -111,10 +115,10 @@ private[chisel3] trait HasId extends InstanceId { private var prefix_seed: Prefix = Nil // Post-seed hooks called to carry the suggested seeds to other candidates as needed - private val suggest_postseed_hooks = scala.collection.mutable.ListBuffer.empty[String=>Unit] + private val suggest_postseed_hooks = scala.collection.mutable.ListBuffer.empty[String => Unit] // Post-seed hooks called to carry the auto seeds to other candidates as needed - private val auto_postseed_hooks = scala.collection.mutable.ListBuffer.empty[String=>Unit] + private val auto_postseed_hooks = scala.collection.mutable.ListBuffer.empty[String => Unit] /** Takes the last seed suggested. Multiple calls to this function will take the last given seed, unless * this HasId is a module port (see overridden method in Data.scala). @@ -124,7 +128,7 @@ private[chisel3] trait HasId extends InstanceId { * * Is a lower priority than [[suggestName]], in that regardless of whether [[autoSeed]] * was called, [[suggestName]] will always take precedence if it was called. - * + * * @param seed Seed for the name of this component * @return this object */ @@ -132,7 +136,7 @@ private[chisel3] trait HasId extends InstanceId { // Bypass the overridden behavior of autoSeed in [[Data]], apply autoSeed even to ports private[chisel3] def forceAutoSeed(seed: String): this.type = { auto_seed = Some(seed) - for(hook <- auto_postseed_hooks) { hook(seed) } + for (hook <- auto_postseed_hooks) { hook(seed) } prefix_seed = Builder.getPrefix this } @@ -143,14 +147,14 @@ private[chisel3] trait HasId extends InstanceId { * * Is a higher priority than [[autoSeed]], in that regardless of whether [[autoSeed]] * was called, [[suggestName]] will always take precedence. - * + * * @param seed The seed for the name of this component * @return this object */ - def suggestName(seed: =>String): this.type = { - if(suggested_seed.isEmpty) suggested_seed = Some(seed) + def suggestName(seed: => String): this.type = { + if (suggested_seed.isEmpty) suggested_seed = Some(seed) prefix_seed = Builder.getPrefix - for(hook <- suggest_postseed_hooks) { hook(seed) } + for (hook <- suggest_postseed_hooks) { hook(seed) } this } @@ -171,6 +175,7 @@ private[chisel3] trait HasId extends InstanceId { * @return the name, if it can be computed */ private[chisel3] def _computeName(defaultPrefix: Option[String], defaultSeed: Option[String]): Option[String] = { + /** Computes a name of this signal, given the seed and prefix * @param seed * @param prefix @@ -189,14 +194,14 @@ private[chisel3] trait HasId extends InstanceId { defaultSeed.map { default => defaultPrefix match { case Some(p) => buildName(default, p :: construction_prefix.reverse) - case None => buildName(default, construction_prefix.reverse) + case None => buildName(default, construction_prefix.reverse) } } } } /** This resolves the precedence of [[autoSeed]] and [[suggestName]] - * + * * @return the current calculation of a name, if it exists */ private[chisel3] def seedOpt: Option[String] = suggested_seed.orElse(auto_seed) @@ -206,14 +211,14 @@ private[chisel3] trait HasId extends InstanceId { private[chisel3] def hasAutoSeed: Boolean = auto_seed.isDefined - private[chisel3] def addSuggestPostnameHook(hook: String=>Unit): Unit = suggest_postseed_hooks += hook - private[chisel3] def addAutoPostnameHook(hook: String=>Unit): Unit = auto_postseed_hooks += hook + private[chisel3] def addSuggestPostnameHook(hook: String => Unit): Unit = suggest_postseed_hooks += hook + private[chisel3] def addAutoPostnameHook(hook: String => Unit): Unit = auto_postseed_hooks += hook // Uses a namespace to convert suggestion into a true name // Will not do any naming if the reference already assigned. // (e.g. tried to suggest a name to part of a Record) - private[chisel3] def forceName(prefix: Option[String], default: =>String, namespace: Namespace): Unit = - if(_ref.isEmpty) { + private[chisel3] def forceName(prefix: Option[String], default: => String, namespace: Namespace): Unit = + if (_ref.isEmpty) { val candidate_name = _computeName(prefix, Some(default)).get val available_name = namespace.name(candidate_name) setRef(Ref(available_name)) @@ -226,15 +231,15 @@ private[chisel3] trait HasId extends InstanceId { _ref = Some(imm) } } - private[chisel3] def setRef(parent: HasId, name: String): Unit = setRef(Slot(Node(parent), name)) - private[chisel3] def setRef(parent: HasId, index: Int): Unit = setRef(Index(Node(parent), ILit(index))) - private[chisel3] def setRef(parent: HasId, index: UInt): Unit = setRef(Index(Node(parent), index.ref)) - private[chisel3] def getRef: Arg = _ref.get + private[chisel3] def setRef(parent: HasId, name: String): Unit = setRef(Slot(Node(parent), name)) + private[chisel3] def setRef(parent: HasId, index: Int): Unit = setRef(Index(Node(parent), ILit(index))) + private[chisel3] def setRef(parent: HasId, index: UInt): Unit = setRef(Index(Node(parent), index.ref)) + private[chisel3] def getRef: Arg = _ref.get private[chisel3] def getOptionRef: Option[Arg] = _ref private def refName(c: Component): String = _ref match { - case Some(arg) => arg fullName c - case None => _computeName(None, None).get + case Some(arg) => arg.fullName(c) + case None => _computeName(None, None).get } // Helper for reifying views if they map to a single Target @@ -253,33 +258,35 @@ private[chisel3] trait HasId extends InstanceId { (p._component, this) match { case (Some(c), _) => refName(c) case (None, d: Data) if d.topBindingOpt == Some(CrossModuleBinding) => _ref.get.localName - case (None, _) => throwException(s"signalName/pathName should be called after circuit elaboration: $this, ${_parent}") + case (None, _) => + throwException(s"signalName/pathName should be called after circuit elaboration: $this, ${_parent}") } case None => throwException("this cannot happen") } def pathName: String = _parent match { - case None => instanceName + case None => instanceName case Some(ViewParent) => s"${reifyParent.pathName}.$instanceName" - case Some(p) => s"${p.pathName}.$instanceName" + case Some(p) => s"${p.pathName}.$instanceName" } def parentPathName: String = _parent match { case Some(ViewParent) => reifyParent.pathName - case Some(p) => p.pathName - case None => throwException(s"$instanceName doesn't have a parent") + case Some(p) => p.pathName + case None => throwException(s"$instanceName doesn't have a parent") } def parentModName: String = _parent match { case Some(ViewParent) => reifyParent.name - case Some(p) => p.name - case None => throwException(s"$instanceName doesn't have a parent") + case Some(p) => p.name + case None => throwException(s"$instanceName doesn't have a parent") } // TODO Should this be public? protected def circuitName: String = _parent match { - case None => _circuit match { - case None => instanceName - case Some(o) => o.circuitName - } + case None => + _circuit match { + case None => instanceName + case Some(o) => o.circuitName + } case Some(ViewParent) => reifyParent.circuitName - case Some(p) => p.circuitName + case Some(p) => p.circuitName } private[chisel3] def getPublicFields(rootClass: Class[_]): Seq[java.lang.reflect.Method] = { @@ -302,8 +309,10 @@ private[chisel3] trait HasId extends InstanceId { this.getClass.getMethods.filter(isPublicVal).sortWith(_.getName < _.getName) } } + /** Holds the implementation of toNamed for Data and MemBase */ private[chisel3] trait NamedComponent extends HasId { + /** Returns a FIRRTL ComponentName that references this object * @note Should not be called until circuit elaboration is complete */ @@ -319,7 +328,7 @@ private[chisel3] trait NamedComponent extends HasId { import _root_.firrtl.annotations.{Target, TargetToken} val root = _parent.map { case ViewParent => reifyParent - case other => other + case other => other }.get.getTarget // All NamedComponents will have a parent, only the top module can have None here Target.toTargetTokens(name).toList match { case TargetToken.Ref(r) :: components => root.ref(r).copy(component = components) @@ -333,8 +342,8 @@ private[chisel3] trait NamedComponent extends HasId { def makeTarget(p: BaseModule) = p.toAbsoluteTarget.ref(localTarget.ref).copy(component = localTarget.component) _parent match { case Some(ViewParent) => makeTarget(reifyParent) - case Some(parent) => makeTarget(parent) - case None => localTarget + case Some(parent) => makeTarget(parent) + case None => localTarget } } } @@ -369,9 +378,9 @@ private[chisel3] class DynamicContext(val annotationSeq: AnnotationSeq) { // Set by object Module.apply before calling class Module constructor // Used to distinguish between no Module() wrapping, multiple wrappings, and rewrapping var readyForModuleConstr: Boolean = false - var whenStack: List[WhenContext] = Nil - var currentClock: Option[Clock] = None - var currentReset: Option[Reset] = None + var whenStack: List[WhenContext] = Nil + var currentClock: Option[Clock] = None + var currentReset: Option[Reset] = None val errors = new ErrorLog val namingStack = new NamingStack // Used to indicate if this is the top-level module of full elaboration, or from a Definition @@ -396,7 +405,7 @@ private[chisel3] object Builder extends LazyLogging { def restoreContext(dc: DynamicContext) = dynamicContextVar.value = Some(dc) // Ensure we have a thread-specific ChiselContext - private val chiselContext = new ThreadLocal[ChiselContext]{ + private val chiselContext = new ThreadLocal[ChiselContext] { override def initialValue: ChiselContext = { new ChiselContext } @@ -419,12 +428,12 @@ private[chisel3] object Builder extends LazyLogging { def idGen: IdGen = chiselContext.get.idGen def globalNamespace: Namespace = dynamicContext.globalNamespace - def components: ArrayBuffer[Component] = dynamicContext.components - def annotations: ArrayBuffer[ChiselAnnotation] = dynamicContext.annotations - def annotationSeq: AnnotationSeq = dynamicContext.annotationSeq - def namingStack: NamingStack = dynamicContext.namingStack + def components: ArrayBuffer[Component] = dynamicContext.components + def annotations: ArrayBuffer[ChiselAnnotation] = dynamicContext.annotations + def annotationSeq: AnnotationSeq = dynamicContext.annotationSeq + def namingStack: NamingStack = dynamicContext.namingStack - def unnamedViews: ArrayBuffer[Data] = dynamicContext.unnamedViews + def unnamedViews: ArrayBuffer[Data] = dynamicContext.unnamedViews def viewNamespace: Namespace = chiselContext.get.viewNamespace // Puts a prefix string onto the prefix stack @@ -441,8 +450,8 @@ private[chisel3] object Builder extends LazyLogging { def pushPrefix(d: HasId): Boolean = { def buildAggName(id: HasId): Option[String] = { def getSubName(field: Data): Option[String] = field.getOptionRef.flatMap { - case Slot(_, field) => Some(field) // Record - case Index(_, ILit(n)) => Some(n.toString) // Vec static indexing + case Slot(_, field) => Some(field) // Record + case Index(_, ILit(n)) => Some(n.toString) // Vec static indexing case Index(_, ULit(n, _)) => Some(n.toString) // Vec lit indexing case Index(_, _: Node) => None // Vec dynamic indexing case ModuleIO(_, n) => Some(n) // BlackBox port @@ -452,13 +461,14 @@ private[chisel3] object Builder extends LazyLogging { // If the binding is None, this is an illegal connection and later logic will error def recData(data: Data): Option[String] = data.binding.flatMap { case (_: WireBinding | _: RegBinding | _: MemoryPortBinding | _: OpBinding) => data.seedOpt - case ChildBinding(parent) => recData(parent).map { p => - // And name of the field if we have one, we don't for dynamic indexing of Vecs - getSubName(data).map(p + "_" + _).getOrElse(p) - } - case SampleElementBinding(parent) => recData(parent) + case ChildBinding(parent) => + recData(parent).map { p => + // And name of the field if we have one, we don't for dynamic indexing of Vecs + getSubName(data).map(p + "_" + _).getOrElse(p) + } + case SampleElementBinding(parent) => recData(parent) case PortBinding(mod) if Builder.currentModule.contains(mod) => data.seedOpt - case PortBinding(mod) => map2(mod.seedOpt, data.seedOpt)(_ + "_" + _) + case PortBinding(mod) => map2(mod.seedOpt, data.seedOpt)(_ + "_" + _) case (_: LitBinding | _: DontCareBinding) => None case _ => Some("view_") // TODO implement } @@ -495,30 +505,31 @@ private[chisel3] object Builder extends LazyLogging { def currentModule: Option[BaseModule] = dynamicContextVar.value match { case Some(dyanmicContext) => dynamicContext.currentModule - case _ => None + case _ => None } def currentModule_=(target: Option[BaseModule]): Unit = { dynamicContext.currentModule = target } def aspectModule(module: BaseModule): Option[BaseModule] = dynamicContextVar.value match { case Some(dynamicContext) => dynamicContext.aspectModule.get(module) - case _ => None + case _ => None } + /** Retrieves the parent of a module based on the elaboration context - * - * @param module the module to get the parent of - * @param context the context the parent should be evaluated in - * @return the parent of the module provided - */ + * + * @param module the module to get the parent of + * @param context the context the parent should be evaluated in + * @return the parent of the module provided + */ def retrieveParent(module: BaseModule, context: BaseModule): Option[BaseModule] = { module._parent match { case Some(parentModule) => { //if a parent exists investigate, otherwise return None context match { case aspect: ModuleAspect => { //if aspect context, do the translation - Builder.aspectModule(parentModule) match { - case Some(parentAspect) => Some(parentAspect) //we've found a translation - case _ => Some(parentModule) //no translation found - } + Builder.aspectModule(parentModule) match { + case Some(parentAspect) => Some(parentAspect) //we've found a translation + case _ => Some(parentModule) //no translation found + } } //otherwise just return our parent case _ => Some(parentModule) } @@ -531,10 +542,11 @@ private[chisel3] object Builder extends LazyLogging { } def forcedModule: BaseModule = currentModule match { case Some(module) => module - case None => throwException( - "Error: Not in a Module. Likely cause: Missed Module() wrap or bare chisel API call." - // A bare api call is, e.g. calling Wire() from the scala console). - ) + case None => + throwException( + "Error: Not in a Module. Likely cause: Missed Module() wrap or bare chisel API call." + // A bare api call is, e.g. calling Wire() from the scala console). + ) } def referenceUserModule: RawModule = { currentModule match { @@ -543,18 +555,20 @@ private[chisel3] object Builder extends LazyLogging { case Some(aspect: RawModule) => aspect case other => module } - case _ => throwException( - "Error: Not in a RawModule. Likely cause: Missed Module() wrap, bare chisel API call, or attempting to construct hardware inside a BlackBox." - // A bare api call is, e.g. calling Wire() from the scala console). - ) + case _ => + throwException( + "Error: Not in a RawModule. Likely cause: Missed Module() wrap, bare chisel API call, or attempting to construct hardware inside a BlackBox." + // A bare api call is, e.g. calling Wire() from the scala console). + ) } } def forcedUserModule: RawModule = currentModule match { case Some(module: RawModule) => module - case _ => throwException( - "Error: Not in a UserModule. Likely cause: Missed Module() wrap, bare chisel API call, or attempting to construct hardware inside a BlackBox." - // A bare api call is, e.g. calling Wire() from the scala console). - ) + case _ => + throwException( + "Error: Not in a UserModule. Likely cause: Missed Module() wrap, bare chisel API call, or attempting to construct hardware inside a BlackBox." + // A bare api call is, e.g. calling Wire() from the scala console). + ) } def hasDynamicContext: Boolean = dynamicContextVar.value.isDefined @@ -594,8 +608,8 @@ private[chisel3] object Builder extends LazyLogging { def inDefinition: Boolean = { dynamicContextVar.value - .map(_.inDefinition) - .getOrElse(false) + .map(_.inDefinition) + .getOrElse(false) } def forcedClock: Clock = currentClock.getOrElse( @@ -623,10 +637,11 @@ private[chisel3] object Builder extends LazyLogging { * (Note: Map is Iterable[Tuple2[_,_]] and thus excluded) */ def nameRecursively(prefix: String, nameMe: Any, namer: (HasId, String) => Unit): Unit = nameMe match { - case (id: Instance[_]) => id.underlying match { - case Clone(m: internal.BaseModule.ModuleClone[_]) => namer(m.getPorts, prefix) - case _ => - } + case (id: Instance[_]) => + id.underlying match { + case Clone(m: internal.BaseModule.ModuleClone[_]) => namer(m.getPorts, prefix) + case _ => + } case (id: HasId) => namer(id, prefix) case Some(elt) => nameRecursively(prefix, elt, namer) case (iter: Iterable[_]) if iter.hasDefiniteSize => @@ -644,7 +659,7 @@ private[chisel3] object Builder extends LazyLogging { throwException(m) } } - def warning(m: => String): Unit = if (dynamicContextVar.value.isDefined) errors.warning(m) + def warning(m: => String): Unit = if (dynamicContextVar.value.isDefined) errors.warning(m) def deprecated(m: => String, location: Option[String] = None): Unit = if (dynamicContextVar.value.isDefined) errors.deprecated(m, location) @@ -667,7 +682,7 @@ private[chisel3] object Builder extends LazyLogging { if (getScalaMajorVersion == 11) { val url = _root_.firrtl.stage.transforms.CheckScalaVersion.migrationDocumentLink val msg = s"Chisel 3.4 is the last version that will support Scala 2.11. " + - s"Please upgrade to Scala 2.12. See $url" + s"Please upgrade to Scala 2.12. See $url" deprecated(msg, Some("")) } } @@ -680,8 +695,7 @@ private[chisel3] object Builder extends LazyLogging { for (view <- unnamedViews) { val localTarget = view.toTarget val absTarget = view.toAbsoluteTarget - val elts = getRecursiveFields.lazily(view, "") - .collect { case (elt: Element, _) => elt } + val elts = getRecursiveFields.lazily(view, "").collect { case (elt: Element, _) => elt } for (elt <- elts) { val targetOfView = reify(elt) renames.record(localTarget, targetOfView.toTarget) @@ -691,10 +705,14 @@ private[chisel3] object Builder extends LazyLogging { renames } - private[chisel3] def build[T <: BaseModule](f: => T, dynamicContext: DynamicContext, forceModName: Boolean = true): (Circuit, T) = { + private[chisel3] def build[T <: BaseModule]( + f: => T, + dynamicContext: DynamicContext, + forceModName: Boolean = true + ): (Circuit, T) = { dynamicContextVar.withValue(Some(dynamicContext)) { ViewParent // Must initialize the singleton in a Builder context or weird things can happen - // in tiny designs/testcases that never access anything in chisel3.internal + // in tiny designs/testcases that never access anything in chisel3.internal checkScalaVersion() logger.info("Elaborating design...") val mod = f @@ -719,24 +737,28 @@ object DynamicNamingStack { def pushContext(): NamingContextInterface = { Builder.namingStackOption match { case Some(namingStack) => namingStack.pushContext() - case None => DummyNamer + case None => DummyNamer } } def popReturnContext[T <: Any](prefixRef: T, until: NamingContextInterface): T = { until match { case DummyNamer => - require(Builder.namingStackOption.isEmpty, - "Builder context must remain stable throughout a chiselName-annotated function invocation") + require( + Builder.namingStackOption.isEmpty, + "Builder context must remain stable throughout a chiselName-annotated function invocation" + ) case context: NamingContext => - require(Builder.namingStackOption.isDefined, - "Builder context must remain stable throughout a chiselName-annotated function invocation") + require( + Builder.namingStackOption.isDefined, + "Builder context must remain stable throughout a chiselName-annotated function invocation" + ) Builder.namingStackOption.get.popContext(prefixRef, context) } prefixRef } - def length() : Int = Builder.namingStackOption.get.length + def length(): Int = Builder.namingStackOption.get.length } /** Casts BigInt to Int, issuing an error when the input isn't representable. */ diff --git a/core/src/main/scala/chisel3/internal/Error.scala b/core/src/main/scala/chisel3/internal/Error.scala index d6e0c0e6..c42f39ed 100644 --- a/core/src/main/scala/chisel3/internal/Error.scala +++ b/core/src/main/scala/chisel3/internal/Error.scala @@ -38,7 +38,7 @@ object ExceptionHelpers { */ def trimStackTraceToUserCode( packageTrimlist: Set[String] = packageTrimlist, - anchor: Option[String] = Some(builderName) + anchor: Option[String] = Some(builderName) ): Unit = { def inTrimlist(ste: StackTraceElement) = { val packageName = ste.getClassName().takeWhile(_ != '.') @@ -47,25 +47,28 @@ object ExceptionHelpers { // Step 1: Remove elements from the top in the package trimlist ((a: Array[StackTraceElement]) => a.dropWhile(inTrimlist)) - // Step 2: Optionally remove elements from the bottom until the anchor + // Step 2: Optionally remove elements from the bottom until the anchor .andThen(_.reverse) - .andThen( a => + .andThen(a => anchor match { case Some(b) => a.dropWhile(ste => !ste.getClassName.startsWith(b)) case None => a } ) - // Step 3: Remove elements from the bottom in the package trimlist + // Step 3: Remove elements from the bottom in the package trimlist .andThen(_.dropWhile(inTrimlist)) - // Step 4: Reverse back to the original order + // Step 4: Reverse back to the original order .andThen(_.reverse.toArray) - // Step 5: Add ellipsis stack trace elements and "--full-stacktrace" info + // Step 5: Add ellipsis stack trace elements and "--full-stacktrace" info .andThen(a => ellipsis() +: a :+ ellipsis() :+ - ellipsis(Some("Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace"))) - // Step 5: Mutate the stack trace in this exception + ellipsis( + Some("Stack trace trimmed to user code only. Rerun with --full-stacktrace to see the full stack trace") + ) + ) + // Step 5: Mutate the stack trace in this exception .andThen(throwable.setStackTrace(_)) .apply(throwable.getStackTrace) } @@ -95,18 +98,21 @@ class ChiselException(message: String, cause: Throwable = null) extends Exceptio case a => getCauses(a, throwable +: acc) } - /** Returns true if an exception contains */ + /** Returns true if an exception contains */ private def containsBuilder(throwable: Throwable): Boolean = - throwable.getStackTrace().collectFirst { - case ste if ste.getClassName().startsWith(ExceptionHelpers.builderName) => throwable - }.isDefined + throwable + .getStackTrace() + .collectFirst { + case ste if ste.getClassName().startsWith(ExceptionHelpers.builderName) => throwable + } + .isDefined /** Examine this [[ChiselException]] and it's causes for the first [[Throwable]] that contains a stack trace including * a stack trace element whose declaring class is the [[builderName]]. If no such element exists, return this * [[ChiselException]]. */ private lazy val likelyCause: Throwable = - getCauses(this).collectFirst{ case a if containsBuilder(a) => a }.getOrElse(this) + getCauses(this).collectFirst { case a if containsBuilder(a) => a }.getOrElse(this) /** For an exception, return a stack trace trimmed to user code only * @@ -139,7 +145,9 @@ class ChiselException(message: String, cause: Throwable = null) extends Exceptio sw.write(likelyCause.toString + "\n") sw.write("\t...\n") trimmed.foreach(ste => sw.write(s"\tat $ste\n")) - sw.write("\t... (Stack trace trimmed to user code only, rerun with --full-stacktrace if you wish to see the full stack trace)\n") + sw.write( + "\t... (Stack trace trimmed to user code only, rerun with --full-stacktrace if you wish to see the full stack trace)\n" + ) sw.toString } } @@ -157,6 +165,7 @@ private[chisel3] object ErrorLog { } private[chisel3] class ErrorLog { + /** Log an error message */ def error(m: => String): Unit = errors += new Error(m, getUserLineNumber) @@ -168,16 +177,17 @@ private[chisel3] class ErrorLog { /** Emit an informational message */ @deprecated("This method will be removed in 3.5", "3.4") def info(m: String): Unit = - println(new Info("[%2.3f] %s".format(elapsedTime/1e3, m), None)) + println(new Info("[%2.3f] %s".format(elapsedTime / 1e3, m), None)) /** Log a deprecation warning message */ def deprecated(m: => String, location: Option[String]): Unit = { val sourceLoc = location match { case Some(loc) => loc - case None => getUserLineNumber match { - case Some(elt: StackTraceElement) => s"${elt.getFileName}:${elt.getLineNumber}" - case None => "(unknown)" - } + case None => + getUserLineNumber match { + case Some(elt: StackTraceElement) => s"${elt.getFileName}:${elt.getLineNumber}" + case None => "(unknown)" + } } val thisEntry = (m, sourceLoc) @@ -186,15 +196,20 @@ private[chisel3] class ErrorLog { /** Throw an exception if any errors have yet occurred. */ def checkpoint(logger: Logger): Unit = { - deprecations.foreach { case ((message, sourceLoc), count) => - logger.warn(s"${ErrorLog.depTag} $sourceLoc ($count calls): $message") + deprecations.foreach { + case ((message, sourceLoc), count) => + logger.warn(s"${ErrorLog.depTag} $sourceLoc ($count calls): $message") } errors.foreach(e => logger.error(e.toString)) if (!deprecations.isEmpty) { - logger.warn(s"${ErrorLog.warnTag} ${Console.YELLOW}There were ${deprecations.size} deprecated function(s) used." + - s" These may stop compiling in a future release - you are encouraged to fix these issues.${Console.RESET}") - logger.warn(s"${ErrorLog.warnTag} Line numbers for deprecations reported by Chisel may be inaccurate; enable scalac compiler deprecation warnings via either of the following methods:") + logger.warn( + s"${ErrorLog.warnTag} ${Console.YELLOW}There were ${deprecations.size} deprecated function(s) used." + + s" These may stop compiling in a future release - you are encouraged to fix these issues.${Console.RESET}" + ) + logger.warn( + s"${ErrorLog.warnTag} Line numbers for deprecations reported by Chisel may be inaccurate; enable scalac compiler deprecation warnings via either of the following methods:" + ) logger.warn(s"${ErrorLog.warnTag} In the sbt interactive console, enter:") logger.warn(s"""${ErrorLog.warnTag} set scalacOptions in ThisBuild ++= Seq("-unchecked", "-deprecation")""") logger.warn(s"${ErrorLog.warnTag} or, in your build.sbt, add the line:") @@ -205,16 +220,22 @@ private[chisel3] class ErrorLog { val allWarnings = errors.filter(!_.isFatal) if (!allWarnings.isEmpty && !allErrors.isEmpty) { - logger.warn(s"${ErrorLog.errTag} There were ${Console.RED}${allErrors.size} error(s)${Console.RESET} and ${Console.YELLOW}${allWarnings.size} warning(s)${Console.RESET} during hardware elaboration.") + logger.warn( + s"${ErrorLog.errTag} There were ${Console.RED}${allErrors.size} error(s)${Console.RESET} and ${Console.YELLOW}${allWarnings.size} warning(s)${Console.RESET} during hardware elaboration." + ) } else if (!allWarnings.isEmpty) { - logger.warn(s"${ErrorLog.warnTag} There were ${Console.YELLOW}${allWarnings.size} warning(s)${Console.RESET} during hardware elaboration.") + logger.warn( + s"${ErrorLog.warnTag} There were ${Console.YELLOW}${allWarnings.size} warning(s)${Console.RESET} during hardware elaboration." + ) } else if (!allErrors.isEmpty) { - logger.warn(s"${ErrorLog.errTag} There were ${Console.RED}${allErrors.size} error(s)${Console.RESET} during hardware elaboration.") + logger.warn( + s"${ErrorLog.errTag} There were ${Console.RED}${allErrors.size} error(s)${Console.RESET} during hardware elaboration." + ) } if (!allErrors.isEmpty) { throw new ChiselException("Fatal errors during hardware elaboration. Look above for error list.") - with scala.util.control.NoStackTrace + with scala.util.control.NoStackTrace } else { // No fatal errors, clear accumulated warnings since they've been reported errors.clear() @@ -228,20 +249,25 @@ private[chisel3] class ErrorLog { // List of classpath prefixes that are Chisel internals and should be ignored when looking for user code // utils are not part of internals and errors there can be reported val chiselPrefixes = Set( - "java.", - "scala.", - "chisel3.", - "chisel3.internal.", - "chisel3.experimental.", - "chisel3.package$" // for some compatibility / deprecated types - ) + "java.", + "scala.", + "chisel3.", + "chisel3.internal.", + "chisel3.experimental.", + "chisel3.package$" // for some compatibility / deprecated types + ) !chiselPrefixes.filter(className.startsWith(_)).isEmpty } - Thread.currentThread().getStackTrace.toList.dropWhile( - // Get rid of everything in Chisel core - ste => isChiselClassname(ste.getClassName) - ).headOption + Thread + .currentThread() + .getStackTrace + .toList + .dropWhile( + // Get rid of everything in Chisel core + ste => isChiselClassname(ste.getClassName) + ) + .headOption } private val errors = ArrayBuffer[LogEntry]() @@ -257,7 +283,7 @@ private abstract class LogEntry(msg: => String, line: Option[StackTraceElement]) override def toString: String = line match { case Some(l) => s"${format} ${l.getFileName}:${l.getLineNumber}: ${msg} in class ${l.getClassName}" - case None => s"${format} ${msg}" + case None => s"${format} ${msg}" } protected def tag(name: String, color: String): String = @@ -266,7 +292,7 @@ private abstract class LogEntry(msg: => String, line: Option[StackTraceElement]) private class Error(msg: => String, line: Option[StackTraceElement]) extends LogEntry(msg, line) { override def isFatal: Boolean = true - def format: String = tag("error", Console.RED) + def format: String = tag("error", Console.RED) } private class Warning(msg: => String, line: Option[StackTraceElement]) extends LogEntry(msg, line) { diff --git a/core/src/main/scala/chisel3/internal/MonoConnect.scala b/core/src/main/scala/chisel3/internal/MonoConnect.scala index 6173fc91..b4d9aeff 100644 --- a/core/src/main/scala/chisel3/internal/MonoConnect.scala +++ b/core/src/main/scala/chisel3/internal/MonoConnect.scala @@ -12,28 +12,28 @@ import scala.language.experimental.macros import chisel3.internal.sourceinfo.SourceInfo /** -* MonoConnect.connect executes a mono-directional connection element-wise. -* -* Note that this isn't commutative. There is an explicit source and sink -* already determined before this function is called. -* -* The connect operation will recurse down the left Data (with the right Data). -* An exception will be thrown if a movement through the left cannot be matched -* in the right. The right side is allowed to have extra Record fields. -* Vecs must still be exactly the same size. -* -* See elemConnect for details on how the root connections are issued. -* -* Note that a valid sink must be writable so, one of these must hold: -* - Is an internal writable node (Reg or Wire) -* - Is an output of the current module -* - Is an input of a submodule of the current module -* -* Note that a valid source must be readable so, one of these must hold: -* - Is an internal readable node (Reg, Wire, Op) -* - Is a literal -* - Is a port of the current module or submodule of the current module -*/ + * MonoConnect.connect executes a mono-directional connection element-wise. + * + * Note that this isn't commutative. There is an explicit source and sink + * already determined before this function is called. + * + * The connect operation will recurse down the left Data (with the right Data). + * An exception will be thrown if a movement through the left cannot be matched + * in the right. The right side is allowed to have extra Record fields. + * Vecs must still be exactly the same size. + * + * See elemConnect for details on how the root connections are issued. + * + * Note that a valid sink must be writable so, one of these must hold: + * - Is an internal writable node (Reg or Wire) + * - Is an output of the current module + * - Is an input of a submodule of the current module + * + * Note that a valid source must be readable so, one of these must hold: + * - Is an internal readable node (Reg, Wire, Op) + * - Is a literal + * - Is a port of the current module or submodule of the current module + */ private[chisel3] object MonoConnect { def formatName(data: Data) = s"""${data.earlyName} in ${data.parentNameOpt.getOrElse("(unknown)")}""" @@ -41,9 +41,13 @@ private[chisel3] object MonoConnect { // These are all the possible exceptions that can be thrown. // These are from element-level connection def UnreadableSourceException(sink: Data, source: Data) = - MonoConnectException(s"""${formatName(source)} cannot be read from module ${sink.parentNameOpt.getOrElse("(unknown)")}.""") + MonoConnectException( + s"""${formatName(source)} cannot be read from module ${sink.parentNameOpt.getOrElse("(unknown)")}.""" + ) def UnwritableSinkException(sink: Data, source: Data) = - MonoConnectException(s"""${formatName(sink)} cannot be written from module ${source.parentNameOpt.getOrElse("(unknown)")}.""") + MonoConnectException( + s"""${formatName(sink)} cannot be written from module ${source.parentNameOpt.getOrElse("(unknown)")}.""" + ) def SourceEscapedWhenScopeException(source: Data) = MonoConnectException(s"Source ${formatName(source)} has escaped the scope of the when in which it was constructed.") def SinkEscapedWhenScopeException(sink: Data) = @@ -56,7 +60,9 @@ private[chisel3] object MonoConnect { def MissingFieldException(field: String) = MonoConnectException(s"Source Record missing field ($field).") def MismatchedException(sink: Data, source: Data) = - MonoConnectException(s"Sink (${sink.cloneType.toString}) and Source (${source.cloneType.toString}) have different types.") + MonoConnectException( + s"Sink (${sink.cloneType.toString}) and Source (${source.cloneType.toString}) have different types." + ) def DontCareCantBeSink = MonoConnectException("DontCare cannot be a connection sink") def AnalogCantBeMonoSink(sink: Data) = @@ -64,28 +70,32 @@ private[chisel3] object MonoConnect { def AnalogCantBeMonoSource(source: Data) = MonoConnectException(s"Source ${formatName(source)} of type Analog cannot participate in a mono connection (:=)") def AnalogMonoConnectionException(source: Data, sink: Data) = - MonoConnectException(s"Source ${formatName(source)} and sink ${formatName(sink)} of type Analog cannot participate in a mono connection (:=)") + MonoConnectException( + s"Source ${formatName(source)} and sink ${formatName(sink)} of type Analog cannot participate in a mono connection (:=)" + ) def checkWhenVisibility(x: Data): Boolean = { x.topBinding match { - case mp: MemoryPortBinding => true // TODO (albert-magyar): remove this "bridge" for odd enable logic of current CHIRRTL memories + case mp: MemoryPortBinding => + true // TODO (albert-magyar): remove this "bridge" for odd enable logic of current CHIRRTL memories case cd: ConditionalDeclarable => cd.visibility.map(_.active()).getOrElse(true) case _ => true } } /** This function is what recursively tries to connect a sink and source together - * - * There is some cleverness in the use of internal try-catch to catch exceptions - * during the recursive decent and then rethrow them with extra information added. - * This gives the user a 'path' to where in the connections things went wrong. - */ + * + * There is some cleverness in the use of internal try-catch to catch exceptions + * during the recursive decent and then rethrow them with extra information added. + * This gives the user a 'path' to where in the connections things went wrong. + */ def connect( - sourceInfo: SourceInfo, - connectCompileOptions: CompileOptions, - sink: Data, - source: Data, - context_mod: RawModule): Unit = + sourceInfo: SourceInfo, + connectCompileOptions: CompileOptions, + sink: Data, + source: Data, + context_mod: RawModule + ): Unit = (sink, source) match { // Handle legal element cases, note (Bool, Bool) is caught by the first two, as Bool is a UInt @@ -118,8 +128,8 @@ private[chisel3] object MonoConnect { // Handle Vec case case (sink_v: Vec[Data @unchecked], source_v: Vec[Data @unchecked]) => - if(sink_v.length != source_v.length) { throw MismatchedVecException } - for(idx <- 0 until sink_v.length) { + if (sink_v.length != source_v.length) { throw MismatchedVecException } + for (idx <- 0 until sink_v.length) { try { implicit val compileOptions = connectCompileOptions connect(sourceInfo, connectCompileOptions, sink_v(idx), source_v(idx), context_mod) @@ -129,7 +139,7 @@ private[chisel3] object MonoConnect { } // Handle Vec connected to DontCare. Apply the DontCare to individual elements. case (sink_v: Vec[Data @unchecked], DontCare) => - for(idx <- 0 until sink_v.length) { + for (idx <- 0 until sink_v.length) { try { implicit val compileOptions = connectCompileOptions connect(sourceInfo, connectCompileOptions, sink_v(idx), source, context_mod) @@ -141,7 +151,7 @@ private[chisel3] object MonoConnect { // Handle Record case case (sink_r: Record, source_r: Record) => // For each field, descend with right - for((field, sink_sub) <- sink_r.elements) { + for ((field, sink_sub) <- sink_r.elements) { try { source_r.elements.get(field) match { case Some(source_sub) => connect(sourceInfo, connectCompileOptions, sink_sub, source_sub, context_mod) @@ -158,7 +168,7 @@ private[chisel3] object MonoConnect { // Handle Record connected to DontCare. Apply the DontCare to individual elements. case (sink_r: Record, DontCare) => // For each field, descend with right - for((field, sink_sub) <- sink_r.elements) { + for ((field, sink_sub) <- sink_r.elements) { try { connect(sourceInfo, connectCompileOptions, sink_sub, source, context_mod) } catch { @@ -171,7 +181,7 @@ private[chisel3] object MonoConnect { // DontCare as a sink is illegal. case (DontCare, _) => throw DontCareCantBeSink // Analog is illegal in mono connections. - case (_: Analog, _:Analog) => throw AnalogMonoConnectionException(source, sink) + case (_: Analog, _: Analog) => throw AnalogMonoConnectionException(source, sink) // Analog is illegal in mono connections. case (_: Analog, _) => throw AnalogCantBeMonoSink(sink) // Analog is illegal in mono connections. @@ -192,13 +202,19 @@ private[chisel3] object MonoConnect { // This function checks if element-level connection operation allowed. // Then it either issues it or throws the appropriate exception. - def elemConnect(implicit sourceInfo: SourceInfo, connectCompileOptions: CompileOptions, _sink: Element, _source: Element, context_mod: RawModule): Unit = { - import BindingDirection.{Internal, Input, Output} // Using extensively so import these + def elemConnect( + implicit sourceInfo: SourceInfo, + connectCompileOptions: CompileOptions, + _sink: Element, + _source: Element, + context_mod: RawModule + ): Unit = { + import BindingDirection.{Input, Internal, Output} // Using extensively so import these val sink = reify(_sink) val source = reify(_source) // If source has no location, assume in context module // This can occur if is a literal, unbound will error previously - val sink_mod: BaseModule = sink.topBinding.location.getOrElse(throw UnwritableSinkException(sink, source)) + val sink_mod: BaseModule = sink.topBinding.location.getOrElse(throw UnwritableSinkException(sink, source)) val source_mod: BaseModule = source.topBinding.location.getOrElse(context_mod) val sink_parent = Builder.retrieveParent(sink_mod, context_mod).getOrElse(None) @@ -216,69 +232,69 @@ private[chisel3] object MonoConnect { } // CASE: Context is same module that both left node and right node are in - if( (context_mod == sink_mod) && (context_mod == source_mod) ) { + if ((context_mod == sink_mod) && (context_mod == source_mod)) { ((sink_direction, source_direction): @unchecked) match { // SINK SOURCE // CURRENT MOD CURRENT MOD - case (Output, _) => issueConnect(sink, source) - case (Internal, _) => issueConnect(sink, source) - case (Input, _) => throw UnwritableSinkException(sink, source) + case (Output, _) => issueConnect(sink, source) + case (Internal, _) => issueConnect(sink, source) + case (Input, _) => throw UnwritableSinkException(sink, source) } } // CASE: Context is same module as sink node and right node is in a child module - else if((sink_mod == context_mod) && (source_parent == context_mod)) { + else if ((sink_mod == context_mod) && (source_parent == context_mod)) { // Thus, right node better be a port node and thus have a direction ((sink_direction, source_direction): @unchecked) match { // SINK SOURCE // CURRENT MOD CHILD MOD - case (Internal, Output) => issueConnect(sink, source) - case (Internal, Input) => issueConnect(sink, source) - case (Output, Output) => issueConnect(sink, source) - case (Output, Input) => issueConnect(sink, source) - case (_, Internal) => { + case (Internal, Output) => issueConnect(sink, source) + case (Internal, Input) => issueConnect(sink, source) + case (Output, Output) => issueConnect(sink, source) + case (Output, Input) => issueConnect(sink, source) + case (_, Internal) => { if (!(connectCompileOptions.dontAssumeDirectionality)) { issueConnect(sink, source) } else { throw UnreadableSourceException(sink, source) } } - case (Input, Output) if (!(connectCompileOptions.dontTryConnectionsSwapped)) => issueConnect(source, sink) - case (Input, _) => throw UnwritableSinkException(sink, source) + case (Input, Output) if (!(connectCompileOptions.dontTryConnectionsSwapped)) => issueConnect(source, sink) + case (Input, _) => throw UnwritableSinkException(sink, source) } } // CASE: Context is same module as source node and sink node is in child module - else if((source_mod == context_mod) && (sink_parent == context_mod)) { + else if ((source_mod == context_mod) && (sink_parent == context_mod)) { // Thus, left node better be a port node and thus have a direction ((sink_direction, source_direction): @unchecked) match { // SINK SOURCE // CHILD MOD CURRENT MOD - case (Input, _) => issueConnect(sink, source) - case (Output, _) => throw UnwritableSinkException(sink, source) - case (Internal, _) => throw UnwritableSinkException(sink, source) + case (Input, _) => issueConnect(sink, source) + case (Output, _) => throw UnwritableSinkException(sink, source) + case (Internal, _) => throw UnwritableSinkException(sink, source) } } // CASE: Context is the parent module of both the module containing sink node // and the module containing source node // Note: This includes case when sink and source in same module but in parent - else if((sink_parent == context_mod) && (source_parent == context_mod)) { + else if ((sink_parent == context_mod) && (source_parent == context_mod)) { // Thus both nodes must be ports and have a direction ((sink_direction, source_direction): @unchecked) match { // SINK SOURCE // CHILD MOD CHILD MOD - case (Input, Input) => issueConnect(sink, source) - case (Input, Output) => issueConnect(sink, source) - case (Output, _) => throw UnwritableSinkException(sink, source) - case (_, Internal) => { + case (Input, Input) => issueConnect(sink, source) + case (Input, Output) => issueConnect(sink, source) + case (Output, _) => throw UnwritableSinkException(sink, source) + case (_, Internal) => { if (!(connectCompileOptions.dontAssumeDirectionality)) { issueConnect(sink, source) } else { throw UnreadableSourceException(sink, source) } } - case (Internal, _) => throw UnwritableSinkException(sink, source) + case (Internal, _) => throw UnwritableSinkException(sink, source) } } diff --git a/core/src/main/scala/chisel3/internal/Namer.scala b/core/src/main/scala/chisel3/internal/Namer.scala index c6e36cb6..c36aafef 100644 --- a/core/src/main/scala/chisel3/internal/Namer.scala +++ b/core/src/main/scala/chisel3/internal/Namer.scala @@ -42,6 +42,7 @@ import scala.collection.JavaConverters._ * ability to take descendant naming contexts. */ sealed trait NamingContextInterface { + /** Suggest a name (that will be propagated to FIRRTL) for an object, then returns the object * itself (so this can be inserted transparently anywhere). * Is a no-op (so safe) when applied on objects that aren't named, including non-Chisel data @@ -61,8 +62,7 @@ sealed trait NamingContextInterface { object DummyNamer extends NamingContextInterface { def name[T](obj: T, name: String): T = obj - def namePrefix(prefix: String): Unit = { - } + def namePrefix(prefix: String): Unit = {} } /** Actual namer functionality. @@ -71,7 +71,7 @@ class NamingContext extends NamingContextInterface { val descendants = new IdentityHashMap[AnyRef, ListBuffer[NamingContext]]() val anonymousDescendants = ListBuffer[NamingContext]() val items = ListBuffer[(AnyRef, String)]() - var closed = false // a sanity check to ensure no more name() calls are done after namePrefix + var closed = false // a sanity check to ensure no more name() calls are done after namePrefix /** Adds a NamingContext object as a descendant - where its contained objects will have names * prefixed with the name given to the reference object, if the reference object is named in the @@ -82,11 +82,13 @@ class NamingContext extends NamingContextInterface { case ref: AnyRef => // getOrElseUpdate val l = descendants.get(ref) - val buf = if (l != null) l else { - val value = ListBuffer[NamingContext]() - descendants.put(ref, value) - value - } + val buf = + if (l != null) l + else { + val value = ListBuffer[NamingContext]() + descendants.put(ref, value) + value + } buf += descendant case _ => anonymousDescendants += descendant } @@ -95,8 +97,8 @@ class NamingContext extends NamingContextInterface { def name[T](obj: T, name: String): T = { assert(!closed, "Can't name elements after namePrefix called") obj match { - case _: NoChiselNamePrefix => // Don't name things with NoChiselNamePrefix - case ref: AnyRef => items += ((ref, name)) + case _: NoChiselNamePrefix => // Don't name things with NoChiselNamePrefix + case ref: AnyRef => items += ((ref, name)) case _ => } obj @@ -156,5 +158,5 @@ class NamingStack { } } - def length() : Int = namingStack.length + def length(): Int = namingStack.length } diff --git a/core/src/main/scala/chisel3/internal/SourceInfo.scala b/core/src/main/scala/chisel3/internal/SourceInfo.scala index 0d6d8eb7..dc7f7fab 100644 --- a/core/src/main/scala/chisel3/internal/SourceInfo.scala +++ b/core/src/main/scala/chisel3/internal/SourceInfo.scala @@ -20,6 +20,7 @@ import scala.reflect.macros.blackbox.Context /** Abstract base class for generalized source information. */ sealed trait SourceInfo { + /** A prettier toString * * Make a useful message if SourceInfo is available, nothing otherwise diff --git a/core/src/main/scala/chisel3/internal/firrtl/Converter.scala b/core/src/main/scala/chisel3/internal/firrtl/Converter.scala index ac784882..2d21a7cb 100644 --- a/core/src/main/scala/chisel3/internal/firrtl/Converter.scala +++ b/core/src/main/scala/chisel3/internal/firrtl/Converter.scala @@ -5,7 +5,7 @@ import chisel3._ import chisel3.experimental._ import chisel3.internal.sourceinfo.{NoSourceInfo, SourceInfo, SourceLine, UnlocatableSourceInfo} import firrtl.{ir => fir} -import chisel3.internal.{HasId, castToInt, throwException} +import chisel3.internal.{castToInt, throwException, HasId} import scala.annotation.{nowarn, tailrec} import scala.collection.immutable.Queue @@ -21,9 +21,9 @@ private[chisel3] object Converter { case PString(str) => (str.replaceAll("%", "%%"), List.empty) case format: FirrtlFormat => ("%" + format.specifier, List(format.bits.ref)) - case Name(data) => (data.ref.name, List.empty) + case Name(data) => (data.ref.name, List.empty) case FullName(data) => (data.ref.fullName(ctx), List.empty) - case Percent => ("%%", List.empty) + case Percent => ("%%", List.empty) } private def reportInternalError(msg: String): Nothing = { @@ -53,9 +53,9 @@ private[chisel3] object Converter { def convert(dir: MemPortDirection): firrtl.MPortDir = dir match { case MemPortDirection.INFER => firrtl.MInfer - case MemPortDirection.READ => firrtl.MRead + case MemPortDirection.READ => firrtl.MRead case MemPortDirection.WRITE => firrtl.MWrite - case MemPortDirection.RDWR => firrtl.MReadWrite + case MemPortDirection.RDWR => firrtl.MReadWrite } // TODO @@ -82,7 +82,8 @@ private[chisel3] object Converter { fir.UIntLiteral(n, fir.IntWidth(u.minWidth)) case ULit(n, w) => fir.UIntLiteral(n, convert(w)) - case slit @ SLit(n, w) => fir.SIntLiteral(n, convert(w)) + case slit @ SLit(n, w) => + fir.SIntLiteral(n, convert(w)) val unsigned = if (n < 0) (BigInt(1) << slit.width.get) + n else n val uint = convert(ULit(unsigned, slit.width), ctx, info) fir.DoPrim(firrtl.PrimOps.AsSInt, Seq(uint), Seq.empty, fir.UnknownType) @@ -120,19 +121,43 @@ private[chisel3] object Converter { case e @ DefWire(info, id) => Some(fir.DefWire(convert(info), e.name, extractType(id, info))) case e @ DefReg(info, id, clock) => - Some(fir.DefRegister(convert(info), e.name, extractType(id, info), convert(clock, ctx, info), - firrtl.Utils.zero, convert(getRef(id, info), ctx, info))) + Some( + fir.DefRegister( + convert(info), + e.name, + extractType(id, info), + convert(clock, ctx, info), + firrtl.Utils.zero, + convert(getRef(id, info), ctx, info) + ) + ) case e @ DefRegInit(info, id, clock, reset, init) => - Some(fir.DefRegister(convert(info), e.name, extractType(id, info), convert(clock, ctx, info), - convert(reset, ctx, info), convert(init, ctx, info))) + Some( + fir.DefRegister( + convert(info), + e.name, + extractType(id, info), + convert(clock, ctx, info), + convert(reset, ctx, info), + convert(init, ctx, info) + ) + ) case e @ DefMemory(info, id, t, size) => Some(firrtl.CDefMemory(convert(info), e.name, extractType(t, info), size, false)) case e @ DefSeqMemory(info, id, t, size, ruw) => Some(firrtl.CDefMemory(convert(info), e.name, extractType(t, info), size, true, ruw)) case e: DefMemPort[_] => val info = e.sourceInfo - Some(firrtl.CDefMPort(convert(e.sourceInfo), e.name, fir.UnknownType, - e.source.fullName(ctx), Seq(convert(e.index, ctx, info), convert(e.clock, ctx, info)), convert(e.dir))) + Some( + firrtl.CDefMPort( + convert(e.sourceInfo), + e.name, + fir.UnknownType, + e.source.fullName(ctx), + Seq(convert(e.index, ctx, info), convert(e.clock, ctx, info)), + convert(e.dir) + ) + ) case Connect(info, loc, exp) => Some(fir.Connect(convert(info), convert(loc, ctx, info), convert(exp, ctx, info))) case BulkConnect(info, loc, exp) => @@ -147,16 +172,33 @@ private[chisel3] object Converter { Some(fir.Stop(convert(info), ret, convert(clock, ctx, info), firrtl.Utils.one, e.name)) case e @ Printf(_, info, clock, pable) => val (fmt, args) = unpack(pable, ctx) - Some(fir.Print(convert(info), fir.StringLit(fmt), - args.map(a => convert(a, ctx, info)), convert(clock, ctx, info), firrtl.Utils.one, e.name)) + Some( + fir.Print( + convert(info), + fir.StringLit(fmt), + args.map(a => convert(a, ctx, info)), + convert(clock, ctx, info), + firrtl.Utils.one, + e.name + ) + ) case e @ Verification(_, op, info, clk, pred, msg) => val firOp = op match { case Formal.Assert => fir.Formal.Assert case Formal.Assume => fir.Formal.Assume - case Formal.Cover => fir.Formal.Cover + case Formal.Cover => fir.Formal.Cover } - Some(fir.Verification(firOp, convert(info), convert(clk, ctx, info), - convert(pred, ctx, info), firrtl.Utils.one, fir.StringLit(msg), e.name)) + Some( + fir.Verification( + firOp, + convert(info), + convert(clk, ctx, info), + convert(pred, ctx, info), + firrtl.Utils.one, + fir.StringLit(msg), + e.name + ) + ) case _ => None } @@ -183,59 +225,60 @@ private[chisel3] object Converter { */ def convert(cmds: Seq[Command], ctx: Component): fir.Statement = { @tailrec - def rec(acc: Queue[fir.Statement], - scope: List[WhenFrame]) - (cmds: Seq[Command]): Seq[fir.Statement] = { + def rec(acc: Queue[fir.Statement], scope: List[WhenFrame])(cmds: Seq[Command]): Seq[fir.Statement] = { if (cmds.isEmpty) { assert(scope.isEmpty) acc - } else convertSimpleCommand(cmds.head, ctx) match { - // Most Commands map 1:1 - case Some(stmt) => - rec(acc :+ stmt, scope)(cmds.tail) - // When scoping logic does not map 1:1 and requires pushing/popping WhenFrames - // Please see WhenFrame for more details - case None => cmds.head match { - case WhenBegin(info, pred) => - val when = fir.Conditionally(convert(info), convert(pred, ctx, info), fir.EmptyStmt, fir.EmptyStmt) - val frame = WhenFrame(when, acc, false) - rec(Queue.empty, frame +: scope)(cmds.tail) - case WhenEnd(info, depth, _) => - val frame = scope.head - val when = if (frame.alt) frame.when.copy(alt = fir.Block(acc)) - else frame.when.copy(conseq = fir.Block(acc)) - // Check if this when has an else - cmds.tail.headOption match { - case Some(AltBegin(_)) => - assert(!frame.alt, "Internal Error! Unexpected when structure!") // Only 1 else per when - rec(Queue.empty, frame.copy(when = when, alt = true) +: scope.tail)(cmds.drop(2)) - case _ => // Not followed by otherwise - // If depth > 0 then we need to close multiple When scopes so we add a new WhenEnd - // If we're nested we need to add more WhenEnds to ensure each When scope gets - // properly closed - val cmdsx = if (depth > 0) WhenEnd(info, depth - 1, false) +: cmds.tail else cmds.tail - rec(frame.outer :+ when, scope.tail)(cmdsx) + } else + convertSimpleCommand(cmds.head, ctx) match { + // Most Commands map 1:1 + case Some(stmt) => + rec(acc :+ stmt, scope)(cmds.tail) + // When scoping logic does not map 1:1 and requires pushing/popping WhenFrames + // Please see WhenFrame for more details + case None => + cmds.head match { + case WhenBegin(info, pred) => + val when = fir.Conditionally(convert(info), convert(pred, ctx, info), fir.EmptyStmt, fir.EmptyStmt) + val frame = WhenFrame(when, acc, false) + rec(Queue.empty, frame +: scope)(cmds.tail) + case WhenEnd(info, depth, _) => + val frame = scope.head + val when = + if (frame.alt) frame.when.copy(alt = fir.Block(acc)) + else frame.when.copy(conseq = fir.Block(acc)) + // Check if this when has an else + cmds.tail.headOption match { + case Some(AltBegin(_)) => + assert(!frame.alt, "Internal Error! Unexpected when structure!") // Only 1 else per when + rec(Queue.empty, frame.copy(when = when, alt = true) +: scope.tail)(cmds.drop(2)) + case _ => // Not followed by otherwise + // If depth > 0 then we need to close multiple When scopes so we add a new WhenEnd + // If we're nested we need to add more WhenEnds to ensure each When scope gets + // properly closed + val cmdsx = if (depth > 0) WhenEnd(info, depth - 1, false) +: cmds.tail else cmds.tail + rec(frame.outer :+ when, scope.tail)(cmdsx) + } + case OtherwiseEnd(info, depth) => + val frame = scope.head + val when = frame.when.copy(alt = fir.Block(acc)) + // TODO For some reason depth == 1 indicates the last closing otherwise whereas + // depth == 0 indicates last closing when + val cmdsx = if (depth > 1) OtherwiseEnd(info, depth - 1) +: cmds.tail else cmds.tail + rec(scope.head.outer :+ when, scope.tail)(cmdsx) } - case OtherwiseEnd(info, depth) => - val frame = scope.head - val when = frame.when.copy(alt = fir.Block(acc)) - // TODO For some reason depth == 1 indicates the last closing otherwise whereas - // depth == 0 indicates last closing when - val cmdsx = if (depth > 1) OtherwiseEnd(info, depth - 1) +: cmds.tail else cmds.tail - rec(scope.head.outer :+ when, scope.tail)(cmdsx) } - } } fir.Block(rec(Queue.empty, List.empty)(cmds)) } def convert(width: Width): fir.Width = width match { - case UnknownWidth() => fir.UnknownWidth + case UnknownWidth() => fir.UnknownWidth case KnownWidth(value) => fir.IntWidth(value) } def convert(bp: BinaryPoint): fir.Width = bp match { - case UnknownBinaryPoint => fir.UnknownWidth + case UnknownBinaryPoint => fir.UnknownWidth case KnownBinaryPoint(value) => fir.IntWidth(value) } @@ -248,15 +291,15 @@ private[chisel3] object Converter { def extractType(data: Data, info: SourceInfo): fir.Type = extractType(data, false, info) def extractType(data: Data, clearDir: Boolean, info: SourceInfo): fir.Type = data match { - case _: Clock => fir.ClockType + case _: Clock => fir.ClockType case _: AsyncReset => fir.AsyncResetType - case _: ResetType => fir.ResetType - case d: EnumType => fir.UIntType(convert(d.width)) - case d: UInt => fir.UIntType(convert(d.width)) - case d: SInt => fir.SIntType(convert(d.width)) + case _: ResetType => fir.ResetType + case d: EnumType => fir.UIntType(convert(d.width)) + case d: UInt => fir.UIntType(convert(d.width)) + case d: SInt => fir.SIntType(convert(d.width)) case d: FixedPoint => fir.FixedType(convert(d.width), convert(d.binaryPoint)) - case d: Interval => fir.IntervalType(d.range.lowerBound, d.range.upperBound, d.range.firrtlBinaryPoint) - case d: Analog => fir.AnalogType(convert(d.width)) + case d: Interval => fir.IntervalType(d.range.lowerBound, d.range.upperBound, d.range.firrtlBinaryPoint) + case d: Analog => fir.AnalogType(convert(d.width)) case d: Vec[_] => fir.VectorType(extractType(d.sample_element, clearDir, info), d.length) case d: Record => val childClearDir = clearDir || @@ -269,23 +312,23 @@ private[chisel3] object Converter { fir.Field(getRef(elt, info).name, fir.Flip, extractType(elt, false, info)) } fir.BundleType(d.elements.toIndexedSeq.reverse.map { case (_, e) => eltField(e) }) - } + } def convert(name: String, param: Param): fir.Param = param match { - case IntParam(value) => fir.IntParam(name, value) + case IntParam(value) => fir.IntParam(name, value) case DoubleParam(value) => fir.DoubleParam(name, value) case StringParam(value) => fir.StringParam(name, fir.StringLit(value)) - case RawParam(value) => fir.RawStringParam(name, value) + case RawParam(value) => fir.RawStringParam(name, value) } def convert(port: Port, topDir: SpecifiedDirection = SpecifiedDirection.Unspecified): fir.Port = { val resolvedDir = SpecifiedDirection.fromParent(topDir, port.dir) val dir = resolvedDir match { case SpecifiedDirection.Unspecified | SpecifiedDirection.Output => fir.Output - case SpecifiedDirection.Flip | SpecifiedDirection.Input => fir.Input + case SpecifiedDirection.Flip | SpecifiedDirection.Input => fir.Input } val clearDir = resolvedDir match { - case SpecifiedDirection.Input | SpecifiedDirection.Output => true + case SpecifiedDirection.Input | SpecifiedDirection.Output => true case SpecifiedDirection.Unspecified | SpecifiedDirection.Flip => false } val info = UnlocatableSourceInfo // Unfortunately there is no source locator for ports ATM @@ -297,8 +340,13 @@ private[chisel3] object Converter { case ctx @ DefModule(_, name, ports, cmds) => fir.Module(fir.NoInfo, name, ports.map(p => convert(p)), convert(cmds.toList, ctx)) case ctx @ DefBlackBox(id, name, ports, topDir, params) => - fir.ExtModule(fir.NoInfo, name, ports.map(p => convert(p, topDir)), id.desiredName, - params.map { case (name, p) => convert(name, p) }.toSeq) + fir.ExtModule( + fir.NoInfo, + name, + ports.map(p => convert(p, topDir)), + id.desiredName, + params.map { case (name, p) => convert(name, p) }.toSeq + ) } def convert(circuit: Circuit): fir.Circuit = @@ -310,4 +358,3 @@ private[chisel3] object Converter { fir.Circuit(fir.NoInfo, lazyModules.map(convert), circuit.name) } } - diff --git a/core/src/main/scala/chisel3/internal/firrtl/IR.scala b/core/src/main/scala/chisel3/internal/firrtl/IR.scala index 68f5f18e..1ee8842f 100644 --- a/core/src/main/scala/chisel3/internal/firrtl/IR.scala +++ b/core/src/main/scala/chisel3/internal/firrtl/IR.scala @@ -15,7 +15,6 @@ import scala.collection.immutable.NumericRange import scala.math.BigDecimal.RoundingMode import scala.annotation.nowarn - case class PrimOp(name: String) { override def toString: String = name } @@ -68,35 +67,36 @@ object PrimOp { sealed abstract class Arg { def localName: String = name def contextualName(ctx: Component): String = name - def fullName(ctx: Component): String = contextualName(ctx) + def fullName(ctx: Component): String = contextualName(ctx) def name: String } case class Node(id: HasId) extends Arg { override def contextualName(ctx: Component): String = id.getOptionRef match { case Some(arg) => arg.contextualName(ctx) - case None => id.instanceName + case None => id.instanceName } override def localName: String = id.getOptionRef match { case Some(arg) => arg.localName - case None => id.instanceName + case None => id.instanceName } def name: String = id.getOptionRef match { case Some(arg) => arg.name - case None => id.instanceName + case None => id.instanceName } } object Arg { def earlyLocalName(id: HasId): String = id.getOptionRef match { case Some(Index(Node(imm), Node(value))) => s"${earlyLocalName(imm)}[${earlyLocalName(imm)}]" - case Some(Index(Node(imm), arg)) => s"${earlyLocalName(imm)}[${arg.localName}]" - case Some(Slot(Node(imm), name)) => s"${earlyLocalName(imm)}.$name" - case Some(arg) => arg.name - case None => id match { - case data: Data => data._computeName(None, Some("?")).get - case _ => "?" - } + case Some(Index(Node(imm), arg)) => s"${earlyLocalName(imm)}[${arg.localName}]" + case Some(Slot(Node(imm), name)) => s"${earlyLocalName(imm)}.$name" + case Some(arg) => arg.name + case None => + id match { + case data: Data => data._computeName(None, Some("?")).get + case _ => "?" + } } } @@ -121,8 +121,10 @@ 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 specified width of ${widthArg.get} bits, but at least ${minWidth} bits are required.") + require( + widthArg.get >= minWidth, + s"The literal value ${num} was elaborated with a specified width of ${widthArg.get} bits, but at least ${minWidth} bits are required." + ) } } @@ -131,8 +133,8 @@ case class ILit(n: BigInt) extends Arg { } case class ULit(n: BigInt, w: Width) extends LitArg(n, w) { - def name: String = "UInt" + width + "(\"h0" + num.toString(16) + "\")" - def minWidth: Int = 1 max n.bitLength + def name: String = "UInt" + width + "(\"h0" + num.toString(16) + "\")" + def minWidth: Int = 1.max(n.bitLength) def cloneWithWidth(newWidth: Width): this.type = { ULit(n, newWidth).asInstanceOf[this.type] @@ -171,8 +173,11 @@ case class IntervalLit(n: BigInt, w: Width, binaryPoint: BinaryPoint) extends Li s"asInterval(${ULit(unsigned, width).name}, ${n}, ${n}, ${binaryPoint.asInstanceOf[KnownBinaryPoint].value})" } val range: IntervalRange = { - new IntervalRange(IntervalRange.getBound(isClosed = true, BigDecimal(n)), - IntervalRange.getBound(isClosed = true, BigDecimal(n)), IntervalRange.getRangeWidth(binaryPoint)) + new IntervalRange( + IntervalRange.getBound(isClosed = true, BigDecimal(n)), + IntervalRange.getBound(isClosed = true, BigDecimal(n)), + IntervalRange.getRangeWidth(binaryPoint) + ) } def minWidth: Int = 1 + n.bitLength @@ -182,6 +187,7 @@ case class IntervalLit(n: BigInt, w: Width, binaryPoint: BinaryPoint) extends Li } case class Ref(name: String) extends Arg + /** Arg for ports of Modules * @param mod the module this port belongs to * @param name the name of the port @@ -190,6 +196,7 @@ case class ModuleIO(mod: BaseModule, name: String) extends Arg { override def contextualName(ctx: Component): String = if (mod eq ctx.id) name else s"${mod.getRef.name}.$name" } + /** Ports of cloned modules (CloneModuleAsRecord) * @param mod The original module for which these ports are a clone * @param name the name of the module instance @@ -224,22 +231,22 @@ object Width { sealed abstract class Width { type W = Int - def min(that: Width): Width = this.op(that, _ min _) - def max(that: Width): Width = this.op(that, _ max _) - def + (that: Width): Width = this.op(that, _ + _) - def + (that: Int): Width = this.op(this, (a, b) => a + that) - def shiftRight(that: Int): Width = this.op(this, (a, b) => 0 max (a - that)) + def min(that: Width): Width = this.op(that, _ min _) + def max(that: Width): Width = this.op(that, _ max _) + def +(that: Width): Width = this.op(that, _ + _) + def +(that: Int): Width = this.op(this, (a, b) => a + that) + def shiftRight(that: Int): Width = this.op(this, (a, b) => 0.max(a - that)) def dynamicShiftLeft(that: Width): Width = this.op(that, (a, b) => a + (1 << b) - 1) def known: Boolean - def get: W + def get: W protected def op(that: Width, f: (W, W) => W): Width } sealed case class UnknownWidth() extends Width { def known: Boolean = false - def get: Int = None.get + def get: Int = None.get def op(that: Width, f: (W, W) => W): Width = this override def toString: String = "" } @@ -247,10 +254,10 @@ sealed case class UnknownWidth() extends Width { sealed case class KnownWidth(value: Int) extends Width { require(value >= 0) def known: Boolean = true - def get: Int = value + def get: Int = value def op(that: Width, f: (W, W) => W): Width = that match { case KnownWidth(x) => KnownWidth(f(value, x)) - case _ => that + case _ => that } override def toString: String = s"<${value.toString}>" } @@ -262,36 +269,35 @@ object BinaryPoint { sealed abstract class BinaryPoint { type W = Int - def max(that: BinaryPoint): BinaryPoint = this.op(that, _ max _) - def + (that: BinaryPoint): BinaryPoint = this.op(that, _ + _) - def + (that: Int): BinaryPoint = this.op(this, (a, b) => a + that) - def shiftRight(that: Int): BinaryPoint = this.op(this, (a, b) => 0 max (a - that)) + def max(that: BinaryPoint): BinaryPoint = this.op(that, _ max _) + def +(that: BinaryPoint): BinaryPoint = this.op(that, _ + _) + def +(that: Int): BinaryPoint = this.op(this, (a, b) => a + that) + def shiftRight(that: Int): BinaryPoint = this.op(this, (a, b) => 0.max(a - that)) def dynamicShiftLeft(that: BinaryPoint): BinaryPoint = this.op(that, (a, b) => a + (1 << b) - 1) def known: Boolean - def get: W + def get: W protected def op(that: BinaryPoint, f: (W, W) => W): BinaryPoint } case object UnknownBinaryPoint extends BinaryPoint { def known: Boolean = false - def get: Int = None.get + def get: Int = None.get def op(that: BinaryPoint, f: (W, W) => W): BinaryPoint = this override def toString: String = "" } sealed case class KnownBinaryPoint(value: Int) extends BinaryPoint { def known: Boolean = true - def get: Int = value + def get: Int = value def op(that: BinaryPoint, f: (W, W) => W): BinaryPoint = that match { case KnownBinaryPoint(x) => KnownBinaryPoint(f(value, x)) - case _ => that + case _ => that } override def toString: String = s"<<${value.toString}>>" } - sealed abstract class MemPortDirection(name: String) { override def toString: String = name } @@ -305,17 +311,18 @@ object MemPortDirection { sealed trait RangeType { def getWidth: Width - def * (that: IntervalRange): IntervalRange - def +& (that: IntervalRange): IntervalRange - def -& (that: IntervalRange): IntervalRange - def << (that: Int): IntervalRange - def >> (that: Int): IntervalRange - def << (that: KnownWidth): IntervalRange - def >> (that: KnownWidth): IntervalRange + def *(that: IntervalRange): IntervalRange + def +&(that: IntervalRange): IntervalRange + def -&(that: IntervalRange): IntervalRange + def <<(that: Int): IntervalRange + def >>(that: Int): IntervalRange + def <<(that: KnownWidth): IntervalRange + def >>(that: KnownWidth): IntervalRange def merge(that: IntervalRange): IntervalRange } object IntervalRange { + /** Creates an IntervalRange, this is used primarily by the range interpolator macro * @param lower lower bound * @param upper upper bound @@ -352,7 +359,9 @@ object IntervalRange { case KnownWidth(w) => val nearestPowerOf2 = BigInt("1" + ("0" * (w - 1)), 2) IntervalRange( - firrtlir.Closed(BigDecimal(-nearestPowerOf2)), firrtlir.Closed(BigDecimal(nearestPowerOf2 - 1)), binaryPoint + firrtlir.Closed(BigDecimal(-nearestPowerOf2)), + firrtlir.Closed(BigDecimal(nearestPowerOf2 - 1)), + binaryPoint ) case _ => IntervalRange(firrtlir.UnknownBound, firrtlir.UnknownBound, binaryPoint) @@ -365,22 +374,19 @@ object IntervalRange { } def getBound(isClosed: Boolean, value: String): firrtlir.Bound = { - if(value == "?") { + if (value == "?") { firrtlir.UnknownBound - } - else if(isClosed) { + } else if (isClosed) { firrtlir.Closed(BigDecimal(value)) - } - else { + } else { firrtlir.Open(BigDecimal(value)) } } def getBound(isClosed: Boolean, value: BigDecimal): firrtlir.Bound = { - if(isClosed) { + if (isClosed) { firrtlir.Closed(value) - } - else { + } else { firrtlir.Open(value) } } @@ -394,33 +400,30 @@ object IntervalRange { } def getBinaryPoint(n: Int): firrtlir.Width = { - if(n < 0) { + if (n < 0) { firrtlir.UnknownWidth - } - else { + } else { firrtlir.IntWidth(n) } } def getBinaryPoint(n: BinaryPoint): firrtlir.Width = { n match { - case UnknownBinaryPoint => firrtlir.UnknownWidth + case UnknownBinaryPoint => firrtlir.UnknownWidth case KnownBinaryPoint(w) => firrtlir.IntWidth(w) } } def getRangeWidth(w: Width): firrtlir.Width = { - if(w.known) { + if (w.known) { firrtlir.IntWidth(w.get) - } - else { + } else { firrtlir.UnknownWidth } } def getRangeWidth(binaryPoint: BinaryPoint): firrtlir.Width = { - if(binaryPoint.known) { + if (binaryPoint.known) { firrtlir.IntWidth(binaryPoint.get) - } - else { + } else { firrtlir.UnknownWidth } } @@ -428,47 +431,46 @@ object IntervalRange { def Unknown: IntervalRange = range"[?,?].?" } - sealed class IntervalRange( - val lowerBound: firrtlir.Bound, - val upperBound: firrtlir.Bound, - private[chisel3] val firrtlBinaryPoint: firrtlir.Width) - extends firrtlir.IntervalType(lowerBound, upperBound, firrtlBinaryPoint) + val lowerBound: firrtlir.Bound, + val upperBound: firrtlir.Bound, + private[chisel3] val firrtlBinaryPoint: firrtlir.Width) + extends firrtlir.IntervalType(lowerBound, upperBound, firrtlBinaryPoint) with RangeType { (lowerBound, upperBound) match { case (firrtlir.Open(begin), firrtlir.Open(end)) => - if(begin >= end) throw new ChiselException(s"Invalid range with ${serialize}") + if (begin >= end) throw new ChiselException(s"Invalid range with ${serialize}") binaryPoint match { case KnownBinaryPoint(bp) => - if(begin >= end - (BigDecimal(1) / BigDecimal(BigInt(1) << bp))) { + if (begin >= end - (BigDecimal(1) / BigDecimal(BigInt(1) << bp))) { throw new ChiselException(s"Invalid range with ${serialize}") } case _ => } case (firrtlir.Open(begin), firrtlir.Closed(end)) => - if(begin >= end) throw new ChiselException(s"Invalid range with ${serialize}") + if (begin >= end) throw new ChiselException(s"Invalid range with ${serialize}") case (firrtlir.Closed(begin), firrtlir.Open(end)) => - if(begin >= end) throw new ChiselException(s"Invalid range with ${serialize}") + if (begin >= end) throw new ChiselException(s"Invalid range with ${serialize}") case (firrtlir.Closed(begin), firrtlir.Closed(end)) => - if(begin > end) throw new ChiselException(s"Invalid range with ${serialize}") + if (begin > end) throw new ChiselException(s"Invalid range with ${serialize}") case _ => } override def toString: String = { val binaryPoint = firrtlBinaryPoint match { case firrtlir.IntWidth(n) => s"$n" - case _ => "?" + case _ => "?" } val lowerBoundString = lowerBound match { - case firrtlir.Closed(l) => s"[$l" - case firrtlir.Open(l) => s"($l" - case firrtlir.UnknownBound => s"[?" + case firrtlir.Closed(l) => s"[$l" + case firrtlir.Open(l) => s"($l" + case firrtlir.UnknownBound => s"[?" } val upperBoundString = upperBound match { - case firrtlir.Closed(l) => s"$l]" - case firrtlir.Open(l) => s"$l)" - case firrtlir.UnknownBound => s"?]" + case firrtlir.Closed(l) => s"$l]" + case firrtlir.Open(l) => s"$l)" + case firrtlir.UnknownBound => s"?]" } s"""range"$lowerBoundString,$upperBoundString.$binaryPoint"""" } @@ -487,8 +489,8 @@ sealed class IntervalRange( case Some(inc) => lower match { case firrtlir.Closed(n) => Some(n) - case firrtlir.Open(n) => Some(n + inc) - case _ => None + case firrtlir.Open(n) => Some(n + inc) + case _ => None } case _ => None @@ -503,8 +505,8 @@ sealed class IntervalRange( case Some(inc) => upper match { case firrtlir.Closed(n) => Some(n) - case firrtlir.Open(n) => Some(n - inc) - case _ => None + case firrtlir.Open(n) => Some(n - inc) + case _ => None } case _ => None @@ -528,16 +530,18 @@ sealed class IntervalRange( override def getWidth: Width = { width match { - case firrtlir.IntWidth(n) => KnownWidth(n.toInt) + case firrtlir.IntWidth(n) => KnownWidth(n.toInt) case firrtlir.UnknownWidth => UnknownWidth() } } private def doFirrtlOp(op: firrtlir.PrimOp, that: IntervalRange): IntervalRange = { - PrimOps.set_primop_type( - firrtlir.DoPrim(op, - Seq(firrtlir.Reference("a", this), firrtlir.Reference("b", that)), Nil,firrtlir.UnknownType) - ).tpe match { + PrimOps + .set_primop_type( + firrtlir + .DoPrim(op, Seq(firrtlir.Reference("a", this), firrtlir.Reference("b", that)), Nil, firrtlir.UnknownType) + ) + .tpe match { case i: firrtlir.IntervalType => IntervalRange(i.lower, i.upper, i.point) case other => sys.error("BAD!") } @@ -545,24 +549,27 @@ sealed class IntervalRange( private def doFirrtlDynamicShift(that: UInt, isLeft: Boolean): IntervalRange = { val uinttpe = that.widthOption match { - case None => firrtlir.UIntType(firrtlir.UnknownWidth) + case None => firrtlir.UIntType(firrtlir.UnknownWidth) case Some(w) => firrtlir.UIntType(firrtlir.IntWidth(w)) } - val op = if(isLeft) PrimOps.Dshl else PrimOps.Dshr - PrimOps.set_primop_type( - firrtlir.DoPrim(op, - Seq(firrtlir.Reference("a", this), firrtlir.Reference("b", uinttpe)), Nil,firrtlir.UnknownType) - ).tpe match { + val op = if (isLeft) PrimOps.Dshl else PrimOps.Dshr + PrimOps + .set_primop_type( + firrtlir + .DoPrim(op, Seq(firrtlir.Reference("a", this), firrtlir.Reference("b", uinttpe)), Nil, firrtlir.UnknownType) + ) + .tpe match { case i: firrtlir.IntervalType => IntervalRange(i.lower, i.upper, i.point) case other => sys.error("BAD!") } } private def doFirrtlOp(op: firrtlir.PrimOp, that: Int): IntervalRange = { - PrimOps.set_primop_type( - firrtlir.DoPrim(op, - Seq(firrtlir.Reference("a", this)), Seq(BigInt(that)), firrtlir.UnknownType) - ).tpe match { + PrimOps + .set_primop_type( + firrtlir.DoPrim(op, Seq(firrtlir.Reference("a", this)), Seq(BigInt(that)), firrtlir.UnknownType) + ) + .tpe match { case i: firrtlir.IntervalType => IntervalRange(i.lower, i.upper, i.point) case other => sys.error("BAD!") } @@ -596,7 +603,7 @@ sealed class IntervalRange( } private def adjustBoundValue(value: BigDecimal, binaryPointValue: Int): BigDecimal = { - if(binaryPointValue >= 0) { + if (binaryPointValue >= 0) { val maskFactor = BigDecimal(1 << binaryPointValue) val a = (value * maskFactor) val b = a.setScale(0, RoundingMode.DOWN) @@ -611,9 +618,9 @@ sealed class IntervalRange( binaryPoint match { case KnownBinaryPoint(binaryPointValue) => bound match { - case firrtlir.Open(value) => firrtlir.Open(adjustBoundValue(value, binaryPointValue)) + case firrtlir.Open(value) => firrtlir.Open(adjustBoundValue(value, binaryPointValue)) case firrtlir.Closed(value) => firrtlir.Closed(adjustBoundValue(value, binaryPointValue)) - case _ => bound + case _ => bound } case _ => firrtlir.UnknownBound } @@ -746,19 +753,22 @@ sealed class IntervalRange( override def merge(that: IntervalRange): IntervalRange = { val lowest = (this.getLowestPossibleValue, that.getLowestPossibleValue) match { case (Some(l1), Some(l2)) => - if(l1 < l2) { this.lower } else { that.lower } + if (l1 < l2) { this.lower } + else { that.lower } case _ => firrtlir.UnknownBound } val highest = (this.getHighestPossibleValue, that.getHighestPossibleValue) match { case (Some(l1), Some(l2)) => - if(l1 >= l2) { this.lower } else { that.lower } + if (l1 >= l2) { this.lower } + else { that.lower } case _ => firrtlir.UnknownBound } val newBinaryPoint = (this.firrtlBinaryPoint, that.firrtlBinaryPoint) match { case (firrtlir.IntWidth(b1), firrtlir.IntWidth(b2)) => - if(b1 > b2) { firrtlir.IntWidth(b1)} else { firrtlir.IntWidth(b2) } + if (b1 > b2) { firrtlir.IntWidth(b1) } + else { firrtlir.IntWidth(b2) } case _ => firrtlir.UnknownWidth } @@ -788,8 +798,21 @@ case class DefWire(sourceInfo: SourceInfo, id: Data) extends Definition case class DefReg(sourceInfo: SourceInfo, id: Data, clock: Arg) extends Definition case class DefRegInit(sourceInfo: SourceInfo, id: Data, clock: Arg, reset: Arg, init: Arg) extends Definition case class DefMemory(sourceInfo: SourceInfo, id: HasId, t: Data, size: BigInt) extends Definition -case class DefSeqMemory(sourceInfo: SourceInfo, id: HasId, t: Data, size: BigInt, readUnderWrite: fir.ReadUnderWrite.Value) extends Definition -case class DefMemPort[T <: Data](sourceInfo: SourceInfo, id: T, source: Node, dir: MemPortDirection, index: Arg, clock: Arg) extends Definition +case class DefSeqMemory( + sourceInfo: SourceInfo, + id: HasId, + t: Data, + size: BigInt, + readUnderWrite: fir.ReadUnderWrite.Value) + extends Definition +case class DefMemPort[T <: Data]( + sourceInfo: SourceInfo, + id: T, + source: Node, + dir: MemPortDirection, + index: Arg, + clock: Arg) + extends Definition @nowarn("msg=class Port") // delete when Port becomes private case class DefInstance(sourceInfo: SourceInfo, id: BaseModule, ports: Seq[Port]) extends Definition case class WhenBegin(sourceInfo: SourceInfo, pred: Arg) extends Command @@ -802,7 +825,10 @@ case class Attach(sourceInfo: SourceInfo, locs: Seq[Node]) extends Command case class ConnectInit(sourceInfo: SourceInfo, loc: Node, exp: Arg) extends Command case class Stop(id: stop.Stop, sourceInfo: SourceInfo, clock: Arg, ret: Int) extends Definition // Note this is just deprecated which will cause deprecation warnings, use @nowarn -@deprecated("This API should never have been public, for Module port reflection, use DataMirror.modulePorts", "Chisel 3.5") +@deprecated( + "This API should never have been public, for Module port reflection, use DataMirror.modulePorts", + "Chisel 3.5" +) case class Port(id: Data, dir: SpecifiedDirection) case class Printf(id: printf.Printf, sourceInfo: SourceInfo, clock: Arg, pable: Printable) extends Definition object Formal extends Enumeration { @@ -810,18 +836,30 @@ object Formal extends Enumeration { val Assume = Value("assume") val Cover = Value("cover") } -case class Verification[T <: VerificationStatement](id: T, op: Formal.Value, sourceInfo: SourceInfo, clock: Arg, - predicate: Arg, message: String) extends Definition +case class Verification[T <: VerificationStatement]( + id: T, + op: Formal.Value, + sourceInfo: SourceInfo, + clock: Arg, + predicate: Arg, + message: String) + extends Definition @nowarn("msg=class Port") // delete when Port becomes private abstract class Component extends Arg { - def id: BaseModule - def name: String + def id: BaseModule + def name: String def ports: Seq[Port] } @nowarn("msg=class Port") // delete when Port becomes private case class DefModule(id: RawModule, name: String, ports: Seq[Port], commands: Seq[Command]) extends Component @nowarn("msg=class Port") // delete when Port becomes private -case class DefBlackBox(id: BaseBlackBox, name: String, ports: Seq[Port], topDir: SpecifiedDirection, params: Map[String, Param]) extends Component +case class DefBlackBox( + id: BaseBlackBox, + name: String, + ports: Seq[Port], + topDir: SpecifiedDirection, + params: Map[String, Param]) + extends Component case class Circuit(name: String, components: Seq[Component], annotations: Seq[ChiselAnnotation], renames: RenameMap) { def firrtlAnnotations: Iterable[Annotation] = annotations.flatMap(_.toFirrtl.update(renames)) diff --git a/core/src/main/scala/chisel3/internal/prefix.scala b/core/src/main/scala/chisel3/internal/prefix.scala index 620d0864..1e4c5ff1 100644 --- a/core/src/main/scala/chisel3/internal/prefix.scala +++ b/core/src/main/scala/chisel3/internal/prefix.scala @@ -15,7 +15,6 @@ package chisel3.internal * } * * }}} - * */ private[chisel3] object prefix { // scalastyle:ignore @@ -51,7 +50,7 @@ private[chisel3] object prefix { // scalastyle:ignore // This causes extra prefixes to be added, and subsequently cleared in the // Module constructor. Thus, we need to just make sure if the previous push // was an incorrect one, to not pop off an empty stack - if(Builder.getPrefix.nonEmpty) Builder.popPrefix() + if (Builder.getPrefix.nonEmpty) Builder.popPrefix() ret } } @@ -65,7 +64,6 @@ private[chisel3] object prefix { // scalastyle:ignore * } * * }}} - * */ private[chisel3] object noPrefix { diff --git a/core/src/main/scala/chisel3/package.scala b/core/src/main/scala/chisel3/package.scala index faca3ae4..bd088e21 100644 --- a/core/src/main/scala/chisel3/package.scala +++ b/core/src/main/scala/chisel3/package.scala @@ -3,7 +3,7 @@ import chisel3.internal.firrtl.BinaryPoint /** This package contains the main chisel3 API. - */ + */ package object chisel3 { import internal.firrtl.{Port, Width} import internal.Builder @@ -28,22 +28,27 @@ package object chisel3 { * `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 { 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) + 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()) + /** Int to SInt conversion, recommended style for constants. */ def S: SInt = SInt.Lit(bigint, Width()) + /** Int to UInt conversion with specified width, recommended style for constants. */ def U(width: Width): UInt = UInt.Lit(bigint, width) + /** Int to SInt conversion with specified width, recommended style for constants. */ def S(width: Width): SInt = SInt.Lit(bigint, width) @@ -52,19 +57,26 @@ package object chisel3 { */ def asUInt: UInt = UInt.Lit(bigint, Width()) - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) def asUInt(dummy: Int*): UInt = asUInt /** Int to SInt conversion, recommended style for variables. */ def asSInt: SInt = SInt.Lit(bigint, Width()) - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) def asSInt(dummy: Int*): SInt = asSInt /** 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) @@ -74,9 +86,11 @@ package object chisel3 { 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 + /** String to UInt parse with specified width, recommended style for constants. */ def U(width: Width): UInt = str.asUInt(width) @@ -85,10 +99,13 @@ package object chisel3 { */ def asUInt: UInt = { val bigInt = parse(str) - UInt.Lit(bigInt, Width(bigInt.bitLength max 1)) + UInt.Lit(bigInt, Width(bigInt.bitLength.max(1))) } - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) def asUInt(dummy: Int*): UInt = asUInt /** String to UInt parse with specified width, recommended style for variables. @@ -99,10 +116,10 @@ package object chisel3 { 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 + case "d" => 10 + case "o" => 8 + case "b" => 2 + case _ => Builder.error(s"Invalid base $base"); 2 } BigInt(num.filterNot(_ == '_'), radix) } @@ -113,6 +130,7 @@ package object chisel3 { } implicit class fromBooleanToLiteral(boolean: Boolean) { + /** Boolean to Bool conversion, recommended style for constants. */ def B: Bool = Bool.Lit(boolean) @@ -121,34 +139,37 @@ package object chisel3 { */ def asBool: Bool = Bool.Lit(boolean) - @deprecated("Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", "Chisel 3.5") + @deprecated( + "Calling this function with an empty argument list is invalid in Scala 3. Use the form without parentheses instead", + "Chisel 3.5" + ) def asBool(dummy: Int*): Bool = asBool } // 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) + extends experimental.FixedPoint.Implicits.fromDoubleToLiteral(double) implicit class fromBigDecimalToLiteral(bigDecimal: BigDecimal) - extends experimental.FixedPoint.Implicits.fromBigDecimalToLiteral(bigDecimal) + extends experimental.FixedPoint.Implicits.fromBigDecimalToLiteral(bigDecimal) // Interval is experimental for now, but we alias the implicit conversion classes here // to minimize disruption with existing code. implicit class fromIntToLiteralInterval(int: Int) - extends experimental.Interval.Implicits.fromIntToLiteralInterval(int) + extends experimental.Interval.Implicits.fromIntToLiteralInterval(int) implicit class fromLongToLiteralInterval(long: Long) - extends experimental.Interval.Implicits.fromLongToLiteralInterval(long) + extends experimental.Interval.Implicits.fromLongToLiteralInterval(long) implicit class fromBigIntToLiteralInterval(bigInt: BigInt) - extends experimental.Interval.Implicits.fromBigIntToLiteralInterval(bigInt) + extends experimental.Interval.Implicits.fromBigIntToLiteralInterval(bigInt) implicit class fromDoubleToLiteralInterval(double: Double) - extends experimental.Interval.Implicits.fromDoubleToLiteralInterval(double) + extends experimental.Interval.Implicits.fromDoubleToLiteralInterval(double) implicit class fromBigDecimalToLiteralInterval(bigDecimal: BigDecimal) - extends experimental.Interval.Implicits.fromBigDecimalToLiteralInterval(bigDecimal) + extends experimental.Interval.Implicits.fromBigDecimalToLiteralInterval(bigDecimal) implicit class fromIntToWidth(int: Int) { def W: Width = Width(int) @@ -187,25 +208,27 @@ package object chisel3 { /** 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 { + 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) + 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 + 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) + (literal, arg) <- parts.zip(pargs :+ None) optPable <- Seq(Some(PString(literal)), arg) pable <- optPable // Remove Option[_] } yield pable @@ -221,19 +244,26 @@ package object chisel3 { def getDataElements(a: Aggregate): Seq[Element] = { a.allElements } - @deprecated("duplicated with DataMirror.fullModulePorts, this returns an internal API, will be removed in Chisel 3.6", "Chisel 3.5") + @deprecated( + "duplicated with DataMirror.fullModulePorts, this returns an internal API, will be removed in Chisel 3.6", + "Chisel 3.5" + ) def getModulePorts(m: Module): Seq[Port] = m.getPorts 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 + + /** 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) |
