diff options
| author | Richard Lin | 2018-01-23 13:53:56 -0800 |
|---|---|---|
| committer | GitHub | 2018-01-23 13:53:56 -0800 |
| commit | 224740acda1929f1a96e165912234eec6ee90fc3 (patch) | |
| tree | 155d390ea53062f2543d666e804a05dca856bfbb | |
| parent | 70ca35b9d7b3884e5f701d49bc5286f89701fd14 (diff) | |
Runtime API deprecation warnings (#761)
Add runtime warnings for use of deprecated Chisel methods. This is done using a macro that takes the message from a `@deprecated` annotation, and adds a call to `Builder.deprecated`.
Reasoning is that by default, Scala doesn't print all deprecations, and that it's somewhat tricky to notice them - yet some support questions revolve around the use of deprecated and terribad API. This now prints warnings for uses of deprecated functions at runtime, and aggregates them by error and line to avoid spam. Also included is convenient information on enabling scalac deprecations.
This also changes how line numbers for Chisel's error facility is determined, using prefix string comparison of the stack trace element classnames, instead of checking if the class is a subtype of UserModule. The previous one (specifically, calls to Class.forName) seems to interact badly with reflection-based cloneType when called at scale. This should also give more accurate reporting of errors that are in user code but outside of a UserModule.
It turns out that `@deprecated` on macro functions don't do anything, so this changes the tags to the functions that the macros point to, which seems to work properly. It also turns out that there's a bunch of uses of deprecated functions in chiselTests which needs to be fixed.
Not all `@deprecated` functions are also annotated with `@chiselRuntimeDeprecation`, because they're still used in Chisel internals, and we can't track whether they're called by the user or by Chisel and it will give a misleading error. These are a small amount of functions.
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala | 16 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/core/Bits.scala | 33 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/core/Data.scala | 4 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/core/Mem.scala | 2 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/core/UserModule.scala | 6 | ||||
| -rw-r--r-- | chiselFrontend/src/main/scala/chisel3/internal/Error.scala | 95 | ||||
| -rw-r--r-- | coreMacros/src/main/scala/chisel3/internal/RuntimeDeprecationTransform.scala | 42 | ||||
| -rw-r--r-- | src/main/scala/chisel3/compatibility.scala | 13 | ||||
| -rw-r--r-- | src/main/scala/chisel3/package.scala | 58 | ||||
| -rw-r--r-- | src/main/scala/chisel3/util/BitPat.scala | 10 | ||||
| -rw-r--r-- | src/main/scala/chisel3/util/Decoupled.scala | 13 | ||||
| -rw-r--r-- | src/main/scala/chisel3/util/Enum.scala | 2 | ||||
| -rw-r--r-- | src/main/scala/chisel3/util/Math.scala | 7 | ||||
| -rw-r--r-- | src/main/scala/chisel3/util/Valid.scala | 5 |
14 files changed, 227 insertions, 79 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala index 14011cd9..e45f6d72 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Aggregate.scala @@ -231,14 +231,6 @@ sealed class Vec[T <: Data] private[core] (gen: => T, val length: Int) */ def apply(idx: Int): T = self(idx) - @deprecated("Use Vec.apply instead", "chisel3") - def read(idx: UInt)(implicit compileOptions: CompileOptions): T = do_apply(idx)(compileOptions) - - @deprecated("Use Vec.apply instead", "chisel3") - def write(idx: UInt, data: T)(implicit compileOptions: CompileOptions): Unit = { - do_apply(idx)(compileOptions).:=(data)(DeprecatedSourceInfo, compileOptions) - } - override def cloneType: this.type = { new Vec(gen.cloneType, length).asInstanceOf[this.type] } @@ -341,11 +333,15 @@ trait VecLike[T <: Data] extends collection.IndexedSeq[T] with HasId { override def hashCode: Int = super[HasId].hashCode override def equals(that: Any): Boolean = super[HasId].equals(that) + @chiselRuntimeDeprecated @deprecated("Use Vec.apply instead", "chisel3") - def read(idx: UInt)(implicit compileOptions: CompileOptions): T + def read(idx: UInt)(implicit compileOptions: CompileOptions): T = do_apply(idx)(compileOptions) + @chiselRuntimeDeprecated @deprecated("Use Vec.apply instead", "chisel3") - def write(idx: UInt, data: T)(implicit compileOptions: CompileOptions): Unit + def write(idx: UInt, data: T)(implicit compileOptions: CompileOptions): Unit = { + do_apply(idx)(compileOptions).:=(data)(DeprecatedSourceInfo, compileOptions) + } /** Outputs true if p outputs true for every element. */ diff --git a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala index 61617775..51f5f5ec 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Bits.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Bits.scala @@ -277,15 +277,26 @@ sealed abstract class Bits(width: Width, override val litArg: Option[LitArg]) } /** Reinterpret cast to Bits. */ + @chiselRuntimeDeprecated @deprecated("Use asUInt, which does the same thing but returns a more concrete type", "chisel3") - final def asBits(): Bits = macro SourceInfoTransform.noArg - - def do_asBits(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bits = asUInt() + final def asBits(implicit compileOptions: CompileOptions): Bits = { + implicit val sourceInfo = DeprecatedSourceInfo + do_asUInt + } + @chiselRuntimeDeprecated @deprecated("Use asSInt, which makes the reinterpret cast more explicit", "chisel3") - final def toSInt(implicit compileOptions: CompileOptions): SInt = do_asSInt(DeprecatedSourceInfo, compileOptions) + final def toSInt(implicit compileOptions: CompileOptions): SInt = { + implicit val sourceInfo = DeprecatedSourceInfo + do_asSInt + } + + @chiselRuntimeDeprecated @deprecated("Use asUInt, which makes the reinterpret cast more explicit", "chisel3") - final def toUInt(implicit compileOptions: CompileOptions): UInt = do_asUInt(DeprecatedSourceInfo, compileOptions) + final def toUInt(implicit compileOptions: CompileOptions): UInt = { + implicit val sourceInfo = DeprecatedSourceInfo + do_asUInt + } final def do_toBool(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = { width match { @@ -477,7 +488,7 @@ sealed class UInt private[core] (width: Width, lit: Option[ULit] = None) final def andR(): Bool = macro SourceInfoTransform.noArg final def xorR(): Bool = macro SourceInfoTransform.noArg - def do_orR(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = this != 0.U + def do_orR(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = this =/= 0.U def do_andR(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = ~this === 0.U def do_xorR(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = redop(sourceInfo, XorReduceOp) @@ -486,12 +497,12 @@ sealed class UInt private[core] (width: Width, lit: Option[ULit] = None) 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) + @chiselRuntimeDeprecated @deprecated("Use '=/=', which avoids potential precedence problems", "chisel3") - final def != (that: UInt): Bool = macro SourceInfoTransform.thatArg + final def != (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = this =/= that final def =/= (that: UInt): Bool = macro SourceInfoTransform.thatArg final def === (that: UInt): Bool = macro SourceInfoTransform.thatArg - 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) def do_=== (that: UInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, EqualOp, that) @@ -652,12 +663,12 @@ sealed class SInt private[core] (width: Width, lit: Option[SLit] = None) 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) + @chiselRuntimeDeprecated @deprecated("Use '=/=', which avoids potential precedence problems", "chisel3") - final def != (that: SInt): Bool = macro SourceInfoTransform.thatArg + final def != (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = this =/= that final def =/= (that: SInt): Bool = macro SourceInfoTransform.thatArg final def === (that: SInt): Bool = macro SourceInfoTransform.thatArg - 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) def do_=== (that: SInt)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = compop(sourceInfo, EqualOp, that) @@ -979,6 +990,7 @@ object FixedPoint { def apply(): FixedPoint = apply(Width(), BinaryPoint()) /** Create an FixedPoint type or port with fixed width. */ + @chiselRuntimeDeprecated @deprecated("Use FixedPoint(width: Width, binaryPoint: BinaryPoint) example FixedPoint(16.W, 8.BP)", "chisel3") def apply(width: Int, binaryPoint: Int): FixedPoint = apply(Width(width), BinaryPoint(binaryPoint)) @@ -1010,6 +1022,7 @@ object FixedPoint { /** Create an FixedPoint literal with inferred width from Double. * Use PrivateObject to force users to specify width and binaryPoint by name */ + @chiselRuntimeDeprecated @deprecated("use fromDouble(value: Double, width: Width, binaryPoint: BinaryPoint)", "chisel3") def fromDouble(value: Double, dummy: PrivateType = PrivateObject, width: Int = -1, binaryPoint: Int = 0): FixedPoint = { diff --git a/chiselFrontend/src/main/scala/chisel3/core/Data.scala b/chiselFrontend/src/main/scala/chisel3/core/Data.scala index 1cf50e9f..40781490 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Data.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Data.scala @@ -70,8 +70,9 @@ object ActualDirection { case class Bidirectional(dir: BidirectionalDirection) extends ActualDirection } -@deprecated("debug doesn't do anything in Chisel3 as no pruning happens in the frontend", "chisel3") object debug { // scalastyle:ignore object.name + @chiselRuntimeDeprecated + @deprecated("debug doesn't do anything in Chisel3 as no pruning happens in the frontend", "chisel3") def apply (arg: Data): Data = arg } @@ -379,6 +380,7 @@ abstract class Data extends HasId { * * This performs the inverse operation of fromBits(Bits). */ + @chiselRuntimeDeprecated @deprecated("Best alternative, .asUInt()", "chisel3") def toBits(implicit compileOptions: CompileOptions): UInt = do_asUInt(DeprecatedSourceInfo, compileOptions) diff --git a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala index 2c8e1a1e..c9208030 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/Mem.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/Mem.scala @@ -10,6 +10,7 @@ import chisel3.internal.firrtl._ import chisel3.internal.sourceinfo.{SourceInfo, SourceInfoTransform, UnlocatableSourceInfo, MemTransform} object Mem { + @chiselRuntimeDeprecated @deprecated("Mem argument order should be size, t; this will be removed by the official release", "chisel3") def apply[T <: Data](t: T, size: Int)(implicit compileOptions: CompileOptions): Mem[T] = do_apply(size, t)(UnlocatableSourceInfo, compileOptions) @@ -118,6 +119,7 @@ sealed abstract class MemBase[T <: Data](t: T, val length: Int) extends HasId { sealed class Mem[T <: Data](t: T, length: Int) extends MemBase(t, length) object SyncReadMem { + @chiselRuntimeDeprecated @deprecated("SeqMem/SyncReadMem argument order should be size, t; this will be removed by the official release", "chisel3") def apply[T <: Data](t: T, size: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): SyncReadMem[T] = do_apply(size, t) diff --git a/chiselFrontend/src/main/scala/chisel3/core/UserModule.scala b/chiselFrontend/src/main/scala/chisel3/core/UserModule.scala index 9c923037..1411fa80 100644 --- a/chiselFrontend/src/main/scala/chisel3/core/UserModule.scala +++ b/chiselFrontend/src/main/scala/chisel3/core/UserModule.scala @@ -131,6 +131,7 @@ abstract class LegacyModule(implicit moduleCompileOptions: CompileOptions) // _clock and _reset can be clock and reset in these 2ary constructors // once chisel2 compatibility issues are resolved + @chiselRuntimeDeprecated @deprecated("Module constructor with override_clock and override_reset deprecated, use withClockAndReset", "chisel3") def this(override_clock: Option[Clock]=None, override_reset: Option[Bool]=None) (implicit moduleCompileOptions: CompileOptions) = { @@ -139,10 +140,15 @@ abstract class LegacyModule(implicit moduleCompileOptions: CompileOptions) this.override_reset = override_reset } + @chiselRuntimeDeprecated @deprecated("Module constructor with override _clock deprecated, use withClock", "chisel3") def this(_clock: Clock)(implicit moduleCompileOptions: CompileOptions) = this(Option(_clock), None)(moduleCompileOptions) + + @chiselRuntimeDeprecated @deprecated("Module constructor with override _reset deprecated, use withReset", "chisel3") def this(_reset: Bool)(implicit moduleCompileOptions: CompileOptions) = this(None, Option(_reset))(moduleCompileOptions) + + @chiselRuntimeDeprecated @deprecated("Module constructor with override _clock, _reset deprecated, use withClockAndReset", "chisel3") def this(_clock: Clock, _reset: Bool)(implicit moduleCompileOptions: CompileOptions) = this(Option(_clock), Option(_reset))(moduleCompileOptions) diff --git a/chiselFrontend/src/main/scala/chisel3/internal/Error.scala b/chiselFrontend/src/main/scala/chisel3/internal/Error.scala index 25a3ec2a..6e7e4002 100644 --- a/chiselFrontend/src/main/scala/chisel3/internal/Error.scala +++ b/chiselFrontend/src/main/scala/chisel3/internal/Error.scala @@ -2,7 +2,7 @@ package chisel3.internal -import scala.collection.mutable.ArrayBuffer +import scala.collection.mutable.{ArrayBuffer, LinkedHashMap} import chisel3.core._ @@ -15,8 +15,6 @@ private[chisel3] object throwException { /** Records and reports runtime errors and warnings. */ private[chisel3] class ErrorLog { - def hasErrors: Boolean = errors.exists(_.isFatal) - /** Log an error message */ def error(m: => String): Unit = errors += new Error(m, getUserLineNumber) @@ -25,50 +23,83 @@ private[chisel3] class ErrorLog { def warning(m: => String): Unit = errors += new Warning(m, getUserLineNumber) - /** Log a deprecation warning message */ - def deprecated(m: => String): Unit = - errors += new DeprecationWarning(m, getUserLineNumber) - /** Emit an informational message */ def info(m: String): Unit = println(new Info("[%2.3f] %s".format(elapsedTime/1e3, m), None)) // scalastyle:ignore regex - /** Prints error messages generated by Chisel at runtime. */ - def report(): Unit = errors foreach println // scalastyle:ignore regex + /** Log a deprecation warning message */ + def deprecated(m: => String): Unit = { + val thisEntry = (m, getUserLineNumber) + deprecations += ((thisEntry, deprecations.getOrElse(thisEntry, 0) + 1)) + } /** Throw an exception if any errors have yet occurred. */ def checkpoint(): Unit = { - if(hasErrors) { - import Console._ - throwException(errors.map(_ + "\n").reduce(_ + _) + - UNDERLINED + "CODE HAS " + errors.filter(_.isFatal).length + RESET + - UNDERLINED + " " + RED + "ERRORS" + RESET + - UNDERLINED + " and " + errors.filterNot(_.isFatal).length + RESET + - UNDERLINED + " " + YELLOW + "WARNINGS" + RESET) + val depTag = s"[${Console.BLUE}deprecated${Console.RESET}]" + val warnTag = s"[${Console.YELLOW}warn${Console.RESET}]" + val errTag = s"[${Console.RED}error${Console.RESET}]" + deprecations foreach { case ((message, stackElement), count) => + val line = stackElement match { + case Some(stackElement) => s"$depTag ${stackElement.getFileName}:${stackElement.getLineNumber} ($count calls): $message" + case None => s"$depTag (unknown location) ($count calls): $message" + } + println(line) + } + errors foreach println + + if (!deprecations.isEmpty) { + println(s"$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}") + println(s"$warnTag Line numbers for deprecations reported by Chisel may be inaccurate, enable scalac compiler deprecation warnings by either:") + println(s"$warnTag In the sbt interactive console, enter:") + println(s"""$warnTag set scalacOptions in ThisBuild ++= Seq("-unchecked", "-deprecation")""") + println(s"$warnTag or, in your build.sbt, add the line:") + println(s"""$warnTag scalacOptions := Seq("-unchecked", "-deprecation")""") + } + + val allErrors = errors.filter(_.isFatal) + val allWarnings = errors.filter(!_.isFatal) + + if (!allWarnings.isEmpty && !allErrors.isEmpty) { + println(s"$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) { + println(s"$warnTag There were ${Console.YELLOW}${allWarnings.size} warning(s)${Console.RESET} during hardware elaboration.") + } else if (!allErrors.isEmpty) { + println(s"$errTag There were ${Console.RED}${allErrors.size} error(s)${Console.RESET} during hardware elaboration.") + } + + if (!allErrors.isEmpty) { + throwException("Fatal errors during hardware elaboration") } else { - // No fatal errors. Report accumulated warnings and clear them. - report() + // No fatal errors, clear accumulated warnings since they've been reported errors.clear() } } - private def findFirstUserFrame(stack: Array[StackTraceElement]): Option[StackTraceElement] = { - def isUserCode(ste: StackTraceElement): Boolean = { - def isUserModule(c: Class[_]): Boolean = - c != null && (c == classOf[UserModule] || isUserModule(c.getSuperclass)) - isUserModule(Class.forName(ste.getClassName)) + /** Returns the best guess at the first stack frame that belongs to user code. + */ + private def getUserLineNumber = { + def isChiselClassname(className: String): Boolean = { + // 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.internal.", + "chisel3.core.", + "chisel3.package$" // for some compatibility / deprecated types + ) + !chiselPrefixes.filter(className.startsWith(_)).isEmpty } - stack.indexWhere(isUserCode) match { - case x if x < 0 => None - case x => Some(stack(x)) - } + Thread.currentThread().getStackTrace.toList.dropWhile( + // Get rid of everything in Chisel core + ste => isChiselClassname(ste.getClassName) + ).headOption } - private def getUserLineNumber = - findFirstUserFrame(Thread.currentThread().getStackTrace) - private val errors = ArrayBuffer[LogEntry]() + private val deprecations = LinkedHashMap[(String, Option[StackTraceElement]), Int]() private val startTime = System.currentTimeMillis private def elapsedTime: Long = System.currentTimeMillis - startTime @@ -96,10 +127,6 @@ private class Warning(msg: => String, line: Option[StackTraceElement]) extends L def format: String = tag("warn", Console.YELLOW) } -private class DeprecationWarning(msg: => String, line: Option[StackTraceElement]) extends LogEntry(msg, line) { - def format: String = tag("warn", Console.CYAN) -} - private class Info(msg: => String, line: Option[StackTraceElement]) extends LogEntry(msg, line) { def format: String = tag("info", Console.MAGENTA) } diff --git a/coreMacros/src/main/scala/chisel3/internal/RuntimeDeprecationTransform.scala b/coreMacros/src/main/scala/chisel3/internal/RuntimeDeprecationTransform.scala new file mode 100644 index 00000000..baf5b746 --- /dev/null +++ b/coreMacros/src/main/scala/chisel3/internal/RuntimeDeprecationTransform.scala @@ -0,0 +1,42 @@ +// See LICENSE for license details. + +package chisel3.internal + +import scala.reflect.macros.whitebox.Context +import scala.language.experimental.macros +import scala.annotation.StaticAnnotation +import scala.annotation.compileTimeOnly + + +class RuntimeDeprecatedTransform(val c: Context) { + import c.universe._ + + /** Adds a Builder.deprecated(...) call based on the contents of a plain @deprecated annotation. + */ + def runtimeDeprecated(annottees: c.Tree*): c.Tree = { + val transformed = annottees.map(annottee => annottee match { + case q"$mods def $tname[..$tparams](...$paramss): $tpt = $expr" => { + val Modifiers(_, _, annotations) = mods + val annotationMessage = annotations.collect { // get all messages from deprecated annotations + case q"new deprecated($desc, $since)" => desc + } match { // ensure there's only one and return it + case msg :: Nil => msg + case _ => c.abort(c.enclosingPosition, s"@chiselRuntimeDeprecated annotion must be used with exactly one @deprecated annotation, got annotations $annotations") + } + val message = s"$tname is deprecated: $annotationMessage" + val transformedExpr = q""" { + _root_.chisel3.internal.Builder.deprecated($message) + $expr + } """ + q"$mods def $tname[..$tparams](...$paramss): $tpt = $transformedExpr" + } + case other => c.abort(c.enclosingPosition, s"@chiselRuntimeDeprecated annotion may only be used on defs, got ${showCode(other)}") + }) + q"..$transformed" + } +} + +@compileTimeOnly("enable macro paradise to expand macro annotations") +class chiselRuntimeDeprecated extends StaticAnnotation { + def macroTransform(annottees: Any*): Any = macro chisel3.internal.RuntimeDeprecatedTransform.runtimeDeprecated +} diff --git a/src/main/scala/chisel3/compatibility.scala b/src/main/scala/chisel3/compatibility.scala index f299a287..d80ff40b 100644 --- a/src/main/scala/chisel3/compatibility.scala +++ b/src/main/scala/chisel3/compatibility.scala @@ -263,14 +263,19 @@ package object Chisel { // scalastyle:ignore package.object.name type SeqMem[T <: Data] = chisel3.core.SyncReadMem[T] import chisel3.core.CompileOptions - abstract class CompatibilityModule( - override_clock: Option[Clock]=None, override_reset: Option[Bool]=None) - (implicit moduleCompileOptions: CompileOptions) - extends chisel3.core.LegacyModule(override_clock, override_reset) { + abstract class CompatibilityModule(implicit moduleCompileOptions: CompileOptions) + extends chisel3.core.LegacyModule { // This class auto-wraps the Module IO with IO(...), allowing legacy code (where IO(...) wasn't // required) to build. // Also provides the clock / reset constructors, which were used before withClock happened. + // Provide a non-deprecated constructor + 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) = diff --git a/src/main/scala/chisel3/package.scala b/src/main/scala/chisel3/package.scala index a502ef2d..973ad026 100644 --- a/src/main/scala/chisel3/package.scala +++ b/src/main/scala/chisel3/package.scala @@ -13,6 +13,7 @@ package object chisel3 { // scalastyle:ignore package.object.name import util.BitPat import chisel3.util._ + import chisel3.internal.chiselRuntimeDeprecated import chisel3.internal.firrtl.Port import chisel3.core.CompileOptions @@ -25,14 +26,17 @@ package object chisel3 { // scalastyle:ignore package.object.name object Wire extends chisel3.core.WireFactory { import chisel3.core.CompileOptions + @chiselRuntimeDeprecated @deprecated("Wire(init=init) is deprecated, use WireInit(init) instead", "chisel3") def apply[T <: Data](dummy: Int = 0, init: T)(implicit compileOptions: CompileOptions): T = chisel3.core.WireInit(init) + @chiselRuntimeDeprecated @deprecated("Wire(t, init) is deprecated, use WireInit(t, init) instead", "chisel3") def apply[T <: Data](t: T, init: T)(implicit compileOptions: CompileOptions): T = chisel3.core.WireInit(t, init) + @chiselRuntimeDeprecated @deprecated("Wire(t, init) is deprecated, use WireInit(t, init) instead", "chisel3") def apply[T <: Data](t: T, init: DontCare.type)(implicit compileOptions: CompileOptions): T = chisel3.core.WireInit(t, init) @@ -43,10 +47,15 @@ package object chisel3 { // scalastyle:ignore package.object.name type Clock = chisel3.core.Clock implicit class AddDirectionToData[T<:Data](val target: T) extends AnyVal { + @chiselRuntimeDeprecated @deprecated("Input(Data) should be used over Data.asInput", "chisel3") def asInput: T = Input(target) + + @chiselRuntimeDeprecated @deprecated("Output(Data) should be used over Data.asOutput", "chisel3") def asOutput: T = Output(target) + + @chiselRuntimeDeprecated @deprecated("Flipped(Data) should be used over Data.flip", "chisel3") def flip(): T = Flipped(target) } @@ -55,6 +64,7 @@ package object chisel3 { // scalastyle:ignore package.object.name import chisel3.core.CompileOptions import chisel3.internal.sourceinfo.SourceInfo + @chiselRuntimeDeprecated @deprecated("fromBits is deprecated, use asTypeOf instead", "chisel3") def fromBits(that: Bits)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = { that.asTypeOf(data) @@ -62,6 +72,7 @@ package object chisel3 { // scalastyle:ignore package.object.name } implicit class cloneTypeable[T <: Data](val target: T) extends AnyVal { + @chiselRuntimeDeprecated @deprecated("chiselCloneType is deprecated, use chiselTypeOf(...) to get the Chisel Type of a hardware object", "chisel3") def chiselCloneType: T = { target.cloneTypeFull.asInstanceOf[T] @@ -74,27 +85,32 @@ package object chisel3 { // scalastyle:ignore package.object.name import chisel3.core.CompileOptions import chisel3.internal.sourceinfo._ + @chiselRuntimeDeprecated @deprecated("Vec argument order should be size, t; this will be removed by the official release", "chisel3") def apply[T <: Data](gen: T, n: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Vec[T] = apply(n, gen) + @chiselRuntimeDeprecated @deprecated("Vec.fill(n)(gen) is deprecated, use VecInit(Seq.fill(n)(gen)) instead", "chisel3") def fill[T <: Data](n: Int)(gen: => T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Vec[T] = apply(Seq.fill(n)(gen)) - @deprecated("Vec(elts) is deprecated, use VecInit(elts) instead", "chisel3") def apply[T <: Data](elts: Seq[T]): Vec[T] = macro VecTransform.apply_elts + @chiselRuntimeDeprecated + @deprecated("Vec(elts) is deprecated, use VecInit(elts) instead", "chisel3") def do_apply[T <: Data](elts: Seq[T])(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Vec[T] = chisel3.core.VecInit(elts) - @deprecated("Vec(elt0, ...) is deprecated, use VecInit(elt0, ...) instead", "chisel3") def apply[T <: Data](elt0: T, elts: T*): Vec[T] = macro VecTransform.apply_elt0 + @chiselRuntimeDeprecated + @deprecated("Vec(elt0, ...) is deprecated, use VecInit(elt0, ...) instead", "chisel3") def do_apply[T <: Data](elt0: T, elts: T*) (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Vec[T] = chisel3.core.VecInit(elt0 +: elts.toSeq) - @deprecated("Vec.tabulate(n)(gen) is deprecated, use VecInit.tabulate(n)(gen) instead", "chisel3") def tabulate[T <: Data](n: Int)(gen: (Int) => T): Vec[T] = macro VecTransform.tabulate + @chiselRuntimeDeprecated + @deprecated("Vec.tabulate(n)(gen) is deprecated, use VecInit.tabulate(n)(gen) instead", "chisel3") def do_tabulate[T <: Data](n: Int)(gen: (Int) => T) (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Vec[T] = chisel3.core.VecInit.tabulate(n)(gen) @@ -132,29 +148,37 @@ package object chisel3 { // scalastyle:ignore package.object.name */ trait UIntFactory extends chisel3.core.UIntFactory { /** Create a UInt literal with inferred width. */ + @chiselRuntimeDeprecated @deprecated("use n.U", "chisel3, will be removed by end of 2017") def apply(n: String): UInt = n.asUInt + /** Create a UInt literal with fixed width. */ + @chiselRuntimeDeprecated @deprecated("use n.U(width.W)", "chisel3, will be removed by end of 2017") def apply(n: String, width: Int): UInt = n.asUInt(width.W) /** Create a UInt literal with specified width. */ + @chiselRuntimeDeprecated @deprecated("use value.U(width)", "chisel3, will be removed by end of 2017") def apply(value: BigInt, width: Width): UInt = value.asUInt(width) /** Create a UInt literal with fixed width. */ + @chiselRuntimeDeprecated @deprecated("use value.U(width.W)", "chisel3, will be removed by end of 2017") def apply(value: BigInt, width: Int): UInt = value.asUInt(width.W) /** Create a UInt literal with inferred width.- compatibility with Chisel2. */ + @chiselRuntimeDeprecated @deprecated("use value.U", "chisel3, will be removed by end of 2017") def apply(value: BigInt): UInt = value.asUInt /** Create a UInt with a specified width */ + @chiselRuntimeDeprecated @deprecated("use UInt(width.W)", "chisel3, will be removed by end of 2017") def width(width: Int): UInt = apply(width.W) /** Create a UInt port with specified width. */ + @chiselRuntimeDeprecated @deprecated("use UInt(width)", "chisel3, will be removed by end of 2017") def width(width: Width): UInt = apply(width) } @@ -164,26 +188,35 @@ package object chisel3 { // scalastyle:ignore package.object.name */ trait SIntFactory extends chisel3.core.SIntFactory { /** Create a SInt type or port with fixed width. */ + @chiselRuntimeDeprecated @deprecated("use SInt(width.W)", "chisel3, will be removed by end of 2017") def width(width: Int): SInt = apply(width.W) + /** Create an SInt type with specified width. */ + @chiselRuntimeDeprecated @deprecated("use SInt(width)", "chisel3, will be removed by end of 2017") def width(width: Width): SInt = apply(width) /** Create an SInt literal with inferred width. */ + @chiselRuntimeDeprecated @deprecated("use value.S", "chisel3, will be removed by end of 2017") def apply(value: BigInt): SInt = value.asSInt + /** Create an SInt literal with fixed width. */ + @chiselRuntimeDeprecated @deprecated("use value.S(width.W)", "chisel3, will be removed by end of 2017") def apply(value: BigInt, width: Int): SInt = value.asSInt(width.W) /** Create an SInt literal with specified width. */ + @chiselRuntimeDeprecated @deprecated("use value.S(width)", "chisel3, will be removed by end of 2017") def apply(value: BigInt, width: Width): SInt = value.asSInt(width) + @chiselRuntimeDeprecated @deprecated("use value.S", "chisel3, will be removed by end of 2017") def Lit(value: BigInt): SInt = value.asSInt // scalastyle:ignore method.name + @chiselRuntimeDeprecated @deprecated("use value.S(width)", "chisel3, will be removed by end of 2017") def Lit(value: BigInt, width: Int): SInt = value.asSInt(width.W) // scalastyle:ignore method.name } @@ -194,6 +227,7 @@ package object chisel3 { // scalastyle:ignore package.object.name trait BoolFactory extends chisel3.core.BoolFactory { /** Creates Bool literal. */ + @chiselRuntimeDeprecated @deprecated("use x.B", "chisel3, will be removed by end of 2017") def apply(x: Boolean): Bool = x.B } @@ -213,13 +247,14 @@ package object chisel3 { // scalastyle:ignore package.object.name val Mem = chisel3.core.Mem type MemBase[T <: Data] = chisel3.core.MemBase[T] type Mem[T <: Data] = chisel3.core.Mem[T] + val SyncReadMem = chisel3.core.SyncReadMem + type SyncReadMem[T <: Data] = chisel3.core.SyncReadMem[T] + @deprecated("Use 'SyncReadMem'", "chisel3") val SeqMem = chisel3.core.SyncReadMem @deprecated("Use 'SyncReadMem'", "chisel3") type SeqMem[T <: Data] = chisel3.core.SyncReadMem[T] - val SyncReadMem = chisel3.core.SyncReadMem - type SyncReadMem[T <: Data] = chisel3.core.SyncReadMem[T] - + val Module = chisel3.core.Module type Module = chisel3.core.LegacyModule @@ -237,6 +272,7 @@ package object chisel3 { // scalastyle:ignore package.object.name def apply[T <: Data](t: T)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = chisel3.core.Reg(t) + @chiselRuntimeDeprecated @deprecated("Use Reg(t), RegNext(next, [init]) or RegInit([t], init) instead", "chisel3") def apply[T <: Data](t: T = null, next: T = null, init: T = null) (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): T = { @@ -333,16 +369,18 @@ package object chisel3 { // scalastyle:ignore package.object.name import internal.sourceinfo.{SourceInfo, SourceInfoTransform} final def === (that: BitPat): Bool = macro SourceInfoTransform.thatArg - @deprecated("Use '=/=', which avoids potential precedence problems", "chisel3") - final def != (that: BitPat): Bool = macro SourceInfoTransform.thatArg final def =/= (that: BitPat): Bool = macro SourceInfoTransform.thatArg def do_=== (that: BitPat) // scalastyle:ignore method.name (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = that === x - def do_!= (that: BitPat) // scalastyle:ignore method.name - (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = that != x def do_=/= (that: BitPat) // scalastyle:ignore method.name (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = that =/= x + + final def != (that: BitPat): Bool = macro SourceInfoTransform.thatArg + @chiselRuntimeDeprecated + @deprecated("Use '=/=', which avoids potential precedence problems", "chisel3") + def do_!= (that: BitPat) // scalastyle:ignore method.name + (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = that != x } diff --git a/src/main/scala/chisel3/util/BitPat.scala b/src/main/scala/chisel3/util/BitPat.scala index c962813d..8d6565fb 100644 --- a/src/main/scala/chisel3/util/BitPat.scala +++ b/src/main/scala/chisel3/util/BitPat.scala @@ -5,6 +5,7 @@ package chisel3.util import scala.language.experimental.macros import chisel3._ import chisel3.core.CompileOptions +import chisel3.internal.chiselRuntimeDeprecated import chisel3.internal.sourceinfo.{SourceInfo, SourceInfoTransform} object BitPat { @@ -53,6 +54,7 @@ object BitPat { */ def dontCare(width: Int): BitPat = BitPat("b" + ("?" * width)) + @chiselRuntimeDeprecated @deprecated("Use BitPat.dontCare", "chisel3") def DC(width: Int): BitPat = dontCare(width) // scalastyle:ignore method.name @@ -91,9 +93,7 @@ sealed class BitPat(val value: BigInt, val mask: BigInt, width: Int) { def getWidth: Int = width def === (that: UInt): Bool = macro SourceInfoTransform.thatArg def =/= (that: UInt): Bool = macro SourceInfoTransform.thatArg - @deprecated("Use '=/=', which avoids potential precedence problems", "chisel3") - def != (that: UInt): Bool = macro SourceInfoTransform.thatArg - + def do_=== (that: UInt) // scalastyle:ignore method.name (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = { value.asUInt === (that & mask.asUInt) @@ -102,6 +102,10 @@ sealed class BitPat(val value: BigInt, val mask: BigInt, width: Int) { (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = { !(this === that) } + + def != (that: UInt): Bool = macro SourceInfoTransform.thatArg + @chiselRuntimeDeprecated + @deprecated("Use '=/=', which avoids potential precedence problems", "chisel3") def do_!= (that: UInt) // scalastyle:ignore method.name (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Bool = { this =/= that diff --git a/src/main/scala/chisel3/util/Decoupled.scala b/src/main/scala/chisel3/util/Decoupled.scala index d35046af..bcd65a1b 100644 --- a/src/main/scala/chisel3/util/Decoupled.scala +++ b/src/main/scala/chisel3/util/Decoupled.scala @@ -19,9 +19,16 @@ import chisel3.internal.naming._ // can't use chisel3_ version because of compi */ abstract class ReadyValidIO[+T <: Data](gen: T) extends Bundle { + // Compatibility hack for rocket-chip + private val genType = (DataMirror.internal.isSynthesizable(gen), chisel3.internal.Builder.currentModule) match { + case (true, Some(module: chisel3.core.ImplicitModule)) + if !module.compileOptions.declaredTypeMustBeUnbound => chiselTypeOf(gen) + case _ => gen + } + val ready = Input(Bool()) val valid = Output(Bool()) - val bits = Output(gen.chiselCloneType) + val bits = Output(genType) } object ReadyValidIO { @@ -200,7 +207,7 @@ class Queue[T <: Data](gen: T, gen } else { if (DataMirror.internal.isSynthesizable(gen)) { - gen.chiselCloneType + chiselTypeOf(gen) } else { gen } @@ -226,7 +233,7 @@ class Queue[T <: Data](gen: T, when (do_deq) { deq_ptr.inc() } - when (do_enq != do_deq) { + when (do_enq =/= do_deq) { maybe_full := do_enq } diff --git a/src/main/scala/chisel3/util/Enum.scala b/src/main/scala/chisel3/util/Enum.scala index 2fdd1a92..92de56ea 100644 --- a/src/main/scala/chisel3/util/Enum.scala +++ b/src/main/scala/chisel3/util/Enum.scala @@ -6,6 +6,7 @@ package chisel3.util import chisel3._ +import chisel3.internal.chiselRuntimeDeprecated /** Defines a set of unique UInt constants * @@ -39,6 +40,7 @@ trait Enum { } object Enum extends Enum { + @chiselRuntimeDeprecated @deprecated("use Enum(n)", "chisel3, will be removed soon") def apply[T <: Bits](nodeType: T, n: Int): List[T] = { require(nodeType.isInstanceOf[UInt], "Only UInt supported for enums") diff --git a/src/main/scala/chisel3/util/Math.scala b/src/main/scala/chisel3/util/Math.scala index cf75e756..3884ea21 100644 --- a/src/main/scala/chisel3/util/Math.scala +++ b/src/main/scala/chisel3/util/Math.scala @@ -6,10 +6,12 @@ package chisel3.util import chisel3._ +import chisel3.internal.chiselRuntimeDeprecated /** Compute the log2 rounded up with min value of 1 */ -@deprecated("Use log2Ceil instead", "chisel3") object log2Up { + @chiselRuntimeDeprecated + @deprecated("Use log2Ceil instead", "chisel3") def apply(in: BigInt): Int = Chisel.log2Up(in) } @@ -23,8 +25,9 @@ object log2Ceil { } /** Compute the log2 rounded down with min value of 1 */ -@deprecated("Use log2Floor instead", "chisel3") object log2Down { + @chiselRuntimeDeprecated + @deprecated("Use log2Floor instead", "chisel3") def apply(in: BigInt): Int = Chisel.log2Down(in) } diff --git a/src/main/scala/chisel3/util/Valid.scala b/src/main/scala/chisel3/util/Valid.scala index 95f0dcea..67a1a362 100644 --- a/src/main/scala/chisel3/util/Valid.scala +++ b/src/main/scala/chisel3/util/Valid.scala @@ -7,13 +7,14 @@ package chisel3.util import chisel3._ import chisel3.core.CompileOptions +import chisel3.experimental.DataMirror import chisel3.internal.naming.chiselName // can't use chisel3_ version because of compile order /** An Bundle containing data and a signal determining if it is valid */ class Valid[+T <: Data](gen: T) extends Bundle { val valid = Output(Bool()) - val bits = Output(gen.chiselCloneType) + val bits = Output(gen) def fire(dummy: Int = 0): Bool = valid override def cloneType: this.type = Valid(gen).asInstanceOf[this.type] } @@ -39,7 +40,7 @@ object Pipe @chiselName def apply[T <: Data](enqValid: Bool, enqBits: T, latency: Int)(implicit compileOptions: CompileOptions): Valid[T] = { if (latency == 0) { - val out = Wire(Valid(enqBits)) + val out = Wire(Valid(chiselTypeOf(enqBits))) out.valid := enqValid out.bits := enqBits out |
