diff options
| author | Aditya Naik | 2024-08-06 05:35:30 -0700 |
|---|---|---|
| committer | Aditya Naik | 2024-08-06 05:35:30 -0700 |
| commit | 51864db8176662d134e1a260f92eafc83f9933d8 (patch) | |
| tree | a92572eb64033060304df5ab9ebec0047e97dbbb /core/src/main | |
| parent | cf31062758d4d9722ac30f89fdfe7cc7c1d8cc74 (diff) | |
Update ChiselEnum.scala
And more changes
Diffstat (limited to 'core/src/main')
| -rw-r--r-- | core/src/main/scala/chisel3/ChiselEnum.scala (renamed from core/src/main/scala/chisel3/experimental/ChiselEnum.scala) | 123 | ||||
| -rw-r--r-- | core/src/main/scala/chisel3/Width.scala | 71 | ||||
| -rw-r--r-- | core/src/main/scala/chisel3/experimental/EnumAnnotations.scala | 63 | ||||
| -rw-r--r-- | core/src/main/scala/chisel3/experimental/package.scala | 13 | ||||
| -rw-r--r-- | core/src/main/scala/chisel3/internal/Binding.scala | 1 | ||||
| -rw-r--r-- | core/src/main/scala/chisel3/internal/Error.scala | 4 | ||||
| -rw-r--r-- | core/src/main/scala/chisel3/internal/Warning.scala | 36 | ||||
| -rw-r--r-- | core/src/main/scala/chisel3/internal/firrtl/IR.scala | 38 | ||||
| -rw-r--r-- | core/src/main/scala/chisel3/package.scala | 4 |
9 files changed, 221 insertions, 132 deletions
diff --git a/core/src/main/scala/chisel3/experimental/ChiselEnum.scala b/core/src/main/scala/chisel3/ChiselEnum.scala index d0ad6949..881bbc62 100644 --- a/core/src/main/scala/chisel3/experimental/ChiselEnum.scala +++ b/core/src/main/scala/chisel3/ChiselEnum.scala @@ -1,75 +1,18 @@ // SPDX-License-Identifier: Apache-2.0 -package chisel3.experimental +package chisel3 import scala.collection.mutable import chisel3._ -import chisel3.internal.Builder.pushOp +import chisel3.internal.Builder +import chisel3.internal.Builder._ import chisel3.internal.firrtl.PrimOp._ import chisel3.internal.firrtl._ -import chisel3.internal.{throwException, Binding, Builder, ChildBinding, ConstrainedBinding} -import firrtl.annotations._ +import chisel3.internal.{throwException, Binding, Builder, ChildBinding, ConstrainedBinding, Warning, WarningID} +import chisel3.experimental.{annotate, requireIsHardware, ChiselAnnotation} +import chisel3.experimental.EnumAnnotations._ -object EnumAnnotations { - /** An annotation for strong enum instances that are ''not'' inside of Vecs - * - * @param target the enum instance being annotated - * @param enumTypeName the name of the enum's type (e.g. ''"mypackage.MyEnum"'') - */ - case class EnumComponentAnnotation(target: Named, enumTypeName: String) extends SingleTargetAnnotation[Named] { - def duplicate(n: Named): EnumComponentAnnotation = this.copy(target = n) - } - - case class EnumComponentChiselAnnotation(target: InstanceId, enumTypeName: String) extends ChiselAnnotation { - def toFirrtl: EnumComponentAnnotation = EnumComponentAnnotation(target.toNamed, enumTypeName) - } - - /** 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() - * val b = new Bundle { - * val inner_e = MyEnum() - * } - * val v = Vec(3, MyEnum()) - * } - * }}} - * - * Then, the ''fields'' parameter will be: ''Seq(Seq("e"), Seq("b", "inner_e"), Seq("v"))''. Note that for any Vec that doesn't contain Bundles, this field will simply be an empty Seq. - * - * @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] { - def duplicate(n: Named): EnumVecAnnotation = this.copy(target = n) - } - - case class EnumVecChiselAnnotation(target: InstanceId, typeName: String, fields: Seq[Seq[String]]) - extends ChiselAnnotation { - override def toFirrtl: EnumVecAnnotation = EnumVecAnnotation(target.toNamed, typeName, fields) - } - - /** An annotation for enum types (rather than enum ''instances''). - * - * @param typeName the name of the enum's type (e.g. ''"mypackage.MyEnum"'') - * @param definition a map describing which integer values correspond to which enum names - */ - case class EnumDefAnnotation(typeName: String, definition: Map[String, BigInt]) extends NoTargetAnnotation - - case class EnumDefChiselAnnotation(typeName: String, definition: Map[String, BigInt]) extends ChiselAnnotation { - override def toFirrtl: Annotation = EnumDefAnnotation(typeName, definition) - } -} - -import EnumAnnotations._ - -@deprecated("This type has moved to chisel3", "Chisel 3.5") abstract class EnumType(private[chisel3] val factory: ChiselEnum, selfAnnotating: Boolean = true) extends Element { // Use getSimpleName instead of enumTypeName because for debugging purposes @@ -196,7 +139,7 @@ abstract class EnumType(private[chisel3] val factory: ChiselEnum, selfAnnotating case b: Bundle => enumFields(b) case _ => Seq() } - case b: Bundle => + case b: Record => b.elements.collect { case (name, e: EnumType) if this.typeEquivalent(e) => Seq(Seq(name)) case (name, v: Vec[_]) if this.typeEquivalent(v.sample_element) => Seq(Seq(name)) @@ -221,20 +164,21 @@ abstract class EnumType(private[chisel3] val factory: ChiselEnum, selfAnnotating } private def annotateEnum(): Unit = { - val anno = outerMostVec() match { - case Some(v) => EnumVecChiselAnnotation(v, enumTypeName, enumFields(v)) - case None => EnumComponentChiselAnnotation(this, enumTypeName) - } - - if (!Builder.enumAnnos.contains(anno)) { - Builder.enumAnnos += anno - annotate(anno) - } - - if (!Builder.enumAnnos.contains(factory.globalAnnotation)) { - Builder.enumAnnos += factory.globalAnnotation - annotate(factory.globalAnnotation) - } + // add after builder.enumAnnos + // val anno = outerMostVec() match { + // case Some(v) => EnumVecChiselAnnotation(v, enumTypeName, enumFields(v)) + // case None => EnumComponentChiselAnnotation(this, enumTypeName) + // } + + // if (!Builder.enumAnnos.contains(anno)) { + // Builder.enumAnnos += anno + // annotate(anno) + // } + + // if (!Builder.enumAnnos.contains(factory.globalAnnotation)) { + // Builder.enumAnnos += factory.globalAnnotation + // annotate(factory.globalAnnotation) + // } } protected def enumTypeName: String = factory.enumTypeName @@ -253,6 +197,9 @@ abstract class EnumType(private[chisel3] val factory: ChiselEnum, selfAnnotating for ((name, value) <- allNamesPadded) { when(this === value) { for ((r, c) <- result.zip(name)) { + // toChar doesn't work with + // An extension method was tried, but could not be fully constructed: + // chisel3.fromLongToLiteral(c.toChar) r := c.toInt.U } } @@ -261,11 +208,15 @@ abstract class EnumType(private[chisel3] val factory: ChiselEnum, selfAnnotating } } -@deprecated("This type has been moved and renamed to chisel3.ChiselEnum", "Chisel 3.5") -abstract class EnumFactory { +private[chisel3] object ChiselEnum { + // add after buildercontextcache +// private[chisel3] case object CacheKey extends BuilderContextCache.Key[mutable.HashSet[ChiselAnnotation]] +} + +abstract class ChiselEnum { class Type extends EnumType(this) object Type { - def apply(): Type = EnumFactory.this.apply() + def apply(): Type = ChiselEnum.this.apply() } private var id: BigInt = 0 @@ -287,7 +238,7 @@ abstract class EnumFactory { } private[chisel3] def globalAnnotation: EnumDefChiselAnnotation = - EnumDefChiselAnnotation(enumTypeName, (enumNames, enumValues).zipped.toMap) + EnumDefChiselAnnotation(enumTypeName, enumNames.zip(enumValues).toMap) def getWidth: Int = width.get @@ -303,7 +254,7 @@ abstract class EnumFactory { val result = new Type // We have to use UnknownWidth here, because we don't actually know what the final width will be - result.bindToLiteral(id, UnknownWidth()) + result.bindToLiteral(id, UnknownWidth) enumRecords.append(EnumRecord(result, name)) @@ -343,10 +294,11 @@ abstract class EnumFactory { } else if (n.getWidth > this.getWidth) { throwException(s"The UInt being cast to $enumTypeName is wider than $enumTypeName's width ($getWidth)") } else { + // TODO fold this into warning filters if (!Builder.suppressEnumCastWarning && warn && !this.isTotal) { - Builder.warning( + val msg = s"Casting non-literal UInt to $enumTypeName. You can use $enumTypeName.safe to cast without this warning." - ) + Builder.warning(Warning(WarningID.UnsafeUIntCastToEnum, msg)) } val glue = Wire(new UnsafeEnum(width)) glue := n @@ -401,7 +353,6 @@ private object UnsafeEnum extends ChiselEnum * } * }}} */ -@deprecated("This type has moved to chisel3", "Chisel 3.5") object suppressEnumCastWarning { def apply[T](block: => T): T = { val parentWarn = Builder.suppressEnumCastWarning diff --git a/core/src/main/scala/chisel3/Width.scala b/core/src/main/scala/chisel3/Width.scala new file mode 100644 index 00000000..3c1abf5e --- /dev/null +++ b/core/src/main/scala/chisel3/Width.scala @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: Apache-2.0 + +package chisel3 + +object Width { + def apply(x: Int): Width = KnownWidth(x) + def apply(): Width = UnknownWidth +} + +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) + @deprecated( + "The width of shift-right now differs by type, use unsignedShiftRight and signedShiftRight", + "Chisel 7.0.0" + ) + def shiftRight(that: Int): Width = this.op(this, (a, b) => 0.max(a - that)) + def unsignedShiftRight(that: Int): Width = this.op(this, (a, b) => 0.max(a - that)) + def signedShiftRight(that: Int): Width = this.op(this, (a, b) => 1.max(a - that)) + def dynamicShiftLeft(that: Width): Width = + this.op(that, (a, b) => a + (1 << b) - 1) + + def known: Boolean + def get: W + protected def op(that: Width, f: (W, W) => W): Width +} + +case object UnknownWidth extends Width { + def known: Boolean = false + def get: Int = None.get + def op(that: Width, f: (W, W) => W): Width = this + override def toString: String = "" + + @deprecated("UnknownWidth is now a case object, remove the parentheses", "Chisel 7.0") + def apply(): UnknownWidth.type = this + + @deprecated("UnknownWidth is now a case object, remove the parentheses", "Chisel 7.0") + def unapply(x: UnknownWidth.type): Boolean = true +} + +sealed case class KnownWidth private (value: Int) extends Width { + + @deprecated("Use the companion object appy method (remove the \"new\")", "Chisel 7.0") + def this(value: Int, dummy: Int = 0) = this(value.toInt) + + require(value >= 0, s"Widths must be non-negative, got $value") + def known: Boolean = true + def get: Int = value + def op(that: Width, f: (W, W) => W): Width = that match { + case KnownWidth(x) => KnownWidth(f(value, x)) + case _ => that + } + override def toString: String = s"<${value.toString}>" +} +object KnownWidth { + private val maxCached = 1024 + private val cache = new Array[KnownWidth](maxCached + 1) + def apply(value: Int): KnownWidth = { + if (0 <= value && value <= maxCached) { + var w = cache(value) + if (w eq null) { + w = new KnownWidth(value) + cache(value) = w + } + w + } else new KnownWidth(value) + } +} diff --git a/core/src/main/scala/chisel3/experimental/EnumAnnotations.scala b/core/src/main/scala/chisel3/experimental/EnumAnnotations.scala new file mode 100644 index 00000000..4719928e --- /dev/null +++ b/core/src/main/scala/chisel3/experimental/EnumAnnotations.scala @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: Apache-2.0 + +package chisel3.experimental + +import chisel3._ +import firrtl.annotations._ + +object EnumAnnotations { + + /** An annotation for strong enum instances that are ''not'' inside of Vecs + * + * @param target the enum instance being annotated + * @param enumTypeName the name of the enum's type (e.g. ''"mypackage.MyEnum"'') + */ + case class EnumComponentAnnotation(target: Named, enumTypeName: String) extends SingleTargetAnnotation[Named] { + def duplicate(n: Named): EnumComponentAnnotation = this.copy(target = n) + } + + case class EnumComponentChiselAnnotation(target: InstanceId, enumTypeName: String) extends ChiselAnnotation { + def toFirrtl: EnumComponentAnnotation = EnumComponentAnnotation(target.toNamed, enumTypeName) + } + + /** 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() + * val b = new Bundle { + * val inner_e = MyEnum() + * } + * val v = Vec(3, MyEnum()) + * } + * }}} + * + * Then, the ''fields'' parameter will be: ''Seq(Seq("e"), Seq("b", "inner_e"), Seq("v"))''. Note that for any Vec that doesn't contain Bundles, this field will simply be an empty Seq. + * + * @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] { + def duplicate(n: Named): EnumVecAnnotation = this.copy(target = n) + } + + case class EnumVecChiselAnnotation(target: InstanceId, typeName: String, fields: Seq[Seq[String]]) + extends ChiselAnnotation { + override def toFirrtl: EnumVecAnnotation = EnumVecAnnotation(target.toNamed, typeName, fields) + } + + /** An annotation for enum types (rather than enum ''instances''). + * + * @param typeName the name of the enum's type (e.g. ''"mypackage.MyEnum"'') + * @param definition a map describing which integer values correspond to which enum names + */ + case class EnumDefAnnotation(typeName: String, definition: Map[String, BigInt]) extends NoTargetAnnotation + + case class EnumDefChiselAnnotation(typeName: String, definition: Map[String, BigInt]) extends ChiselAnnotation { + override def toFirrtl: Annotation = EnumDefAnnotation(typeName, definition) + } +} diff --git a/core/src/main/scala/chisel3/experimental/package.scala b/core/src/main/scala/chisel3/experimental/package.scala index 6dc14afb..d07bcf4a 100644 --- a/core/src/main/scala/chisel3/experimental/package.scala +++ b/core/src/main/scala/chisel3/experimental/package.scala @@ -23,6 +23,19 @@ package object experimental { type Direction = ActualDirection val Direction = ActualDirection + /** Requires that a node is hardware ("bound") + */ + object requireIsHardware { + def apply(node: Data, msg: String = ""): Unit = { + 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(_)?" + ) + } + } + } // class dump extends chisel3.internal.naming.dump // class treedump extends chisel3.internal.naming.treedump diff --git a/core/src/main/scala/chisel3/internal/Binding.scala b/core/src/main/scala/chisel3/internal/Binding.scala index 3a12afde..db85b355 100644 --- a/core/src/main/scala/chisel3/internal/Binding.scala +++ b/core/src/main/scala/chisel3/internal/Binding.scala @@ -10,6 +10,7 @@ import scala.collection.immutable.VectorMap /** Requires that a node is hardware ("bound") */ +// remove/move this to chisel3.experimental once references are fixed object requireIsHardware { def apply(node: Data, msg: String = ""): Unit = { node._parent match { // Compatibility layer hack diff --git a/core/src/main/scala/chisel3/internal/Error.scala b/core/src/main/scala/chisel3/internal/Error.scala index b7c4be35..730c9510 100644 --- a/core/src/main/scala/chisel3/internal/Error.scala +++ b/core/src/main/scala/chisel3/internal/Error.scala @@ -324,10 +324,6 @@ private class Error(msg: => String, line: Option[StackTraceElement]) extends Log def format: String = tag("error", Console.RED) } -class Warning(msg: => String, line: Option[StackTraceElement]) extends LogEntry(msg, line) { - def format: String = tag("warn", Console.YELLOW) -} - private class Info(msg: => String, line: Option[StackTraceElement]) extends LogEntry(msg, line) { def format: String = tag("info", Console.MAGENTA) } diff --git a/core/src/main/scala/chisel3/internal/Warning.scala b/core/src/main/scala/chisel3/internal/Warning.scala new file mode 100644 index 00000000..5ac506c9 --- /dev/null +++ b/core/src/main/scala/chisel3/internal/Warning.scala @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: Apache-2.0 + +package chisel3.internal + +/////////////////////////////////////////////////// +// Never remove IDs and only ever add to the end // +/////////////////////////////////////////////////// + +// TODO should deprecations be included here? +private[chisel3] object WarningID extends Enumeration { + type WarningID = Value + + val NoID = Value(0) // Reserved + val UnsafeUIntCastToEnum = Value(1) + val DynamicBitSelectTooWide = Value(2) + val DynamicBitSelectTooNarrow = Value(3) + val DynamicIndexTooWide = Value(4) + val DynamicIndexTooNarrow = Value(5) + val ExtractFromVecSizeZero = Value(6) + val BundleLiteralValueTooWide = Value(7) + val AsTypeOfReadOnly = Value(8) +} +import WarningID.WarningID + +// Argument order differs from apply below to avoid type signature collision with apply method below +private[chisel3] case class Warning(id: WarningID, msg: String) +private[chisel3] object Warning { + def apply(id: WarningID, msg: String): Warning = { + val num = f"[W${id.id}%03d] " + new Warning(info, id, num + msg) + } + def noInfo(id: WarningID, msg: String): Warning = { + implicit val info = SourceInfo.materializeFromStacktrace + Warning(id, msg) + } +} diff --git a/core/src/main/scala/chisel3/internal/firrtl/IR.scala b/core/src/main/scala/chisel3/internal/firrtl/IR.scala index de3d8716..9fee727c 100644 --- a/core/src/main/scala/chisel3/internal/firrtl/IR.scala +++ b/core/src/main/scala/chisel3/internal/firrtl/IR.scala @@ -216,44 +216,6 @@ case class LitIndex(imm: Arg, value: Int) extends Arg { override def localName: String = s"${imm.localName}[$value]" } -object Width { - def apply(x: Int): Width = KnownWidth(x) - def apply(): Width = UnknownWidth() -} - -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 dynamicShiftLeft(that: Width): Width = - this.op(that, (a, b) => a + (1 << b) - 1) - - def known: Boolean - def get: W - protected def op(that: Width, f: (W, W) => W): Width -} - -sealed case class UnknownWidth() extends Width { - def known: Boolean = false - def get: Int = None.get - def op(that: Width, f: (W, W) => W): Width = this - override def toString: String = "" -} - -sealed case class KnownWidth(value: Int) extends Width { - require(value >= 0) - def known: Boolean = true - def get: Int = value - def op(that: Width, f: (W, W) => W): Width = that match { - case KnownWidth(x) => KnownWidth(f(value, x)) - case _ => that - } - override def toString: String = s"<${value.toString}>" -} - object BinaryPoint { def apply(x: Int): BinaryPoint = KnownBinaryPoint(x) def apply(): BinaryPoint = UnknownBinaryPoint diff --git a/core/src/main/scala/chisel3/package.scala b/core/src/main/scala/chisel3/package.scala index 6633e7ab..be5fb7b5 100644 --- a/core/src/main/scala/chisel3/package.scala +++ b/core/src/main/scala/chisel3/package.scala @@ -18,10 +18,6 @@ package object chisel3 { import scala.language.implicitConversions - type ChiselEnum = experimental.ChiselEnum - type EnumType = experimental.EnumType - val suppressEnumCastWarning = experimental.suppressEnumCastWarning - /** * These implicit classes allow one to convert [[scala.Int]] or [[scala.BigInt]] to * Chisel.UInt|Chisel.SInt by calling .asUInt|.asSInt on them, respectively. |
