From 04caf395c737450c26f59d373d76b567a2b80f0f Mon Sep 17 00:00:00 2001 From: Jack Koenig Date: Thu, 1 Jul 2021 16:33:38 -0700 Subject: Change Chisel warnings to use logger instead of println It also uses the same logger as the Builder so that if we ever refactor that to be passed as an argument, it will be the same logger for both Builder and warning reporting. --- core/src/main/scala/chisel3/internal/Builder.scala | 2 +- core/src/main/scala/chisel3/internal/Error.scala | 25 +++++++++++----------- 2 files changed, 14 insertions(+), 13 deletions(-) (limited to 'core/src/main/scala/chisel3') diff --git a/core/src/main/scala/chisel3/internal/Builder.scala b/core/src/main/scala/chisel3/internal/Builder.scala index 35c4bdf9..fef12093 100644 --- a/core/src/main/scala/chisel3/internal/Builder.scala +++ b/core/src/main/scala/chisel3/internal/Builder.scala @@ -652,7 +652,7 @@ private[chisel3] object Builder extends LazyLogging { logger.warn("Elaborating design...") val mod = f mod.forceName(None, mod.name, globalNamespace) - errors.checkpoint() + errors.checkpoint(logger) logger.warn("Done elaborating.") (Circuit(components.last.name, components.toSeq, annotations.toSeq), mod) diff --git a/core/src/main/scala/chisel3/internal/Error.scala b/core/src/main/scala/chisel3/internal/Error.scala index 454be360..d6e0c0e6 100644 --- a/core/src/main/scala/chisel3/internal/Error.scala +++ b/core/src/main/scala/chisel3/internal/Error.scala @@ -4,6 +4,7 @@ package chisel3.internal import scala.annotation.tailrec import scala.collection.mutable.{ArrayBuffer, LinkedHashMap} +import _root_.logger.Logger object ExceptionHelpers { @@ -184,31 +185,31 @@ private[chisel3] class ErrorLog { } /** Throw an exception if any errors have yet occurred. */ - def checkpoint(): Unit = { + def checkpoint(logger: Logger): Unit = { deprecations.foreach { case ((message, sourceLoc), count) => - println(s"${ErrorLog.depTag} $sourceLoc ($count calls): $message") + logger.warn(s"${ErrorLog.depTag} $sourceLoc ($count calls): $message") } - errors foreach println + errors.foreach(e => logger.error(e.toString)) if (!deprecations.isEmpty) { - println(s"${ErrorLog.warnTag} ${Console.YELLOW}There were ${deprecations.size} deprecated function(s) used." + + 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}") - println(s"${ErrorLog.warnTag} Line numbers for deprecations reported by Chisel may be inaccurate; enable scalac compiler deprecation warnings via either of the following methods:") - println(s"${ErrorLog.warnTag} In the sbt interactive console, enter:") - println(s"""${ErrorLog.warnTag} set scalacOptions in ThisBuild ++= Seq("-unchecked", "-deprecation")""") - println(s"${ErrorLog.warnTag} or, in your build.sbt, add the line:") - println(s"""${ErrorLog.warnTag} scalacOptions := Seq("-unchecked", "-deprecation")""") + 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:") + logger.warn(s"""${ErrorLog.warnTag} scalacOptions := Seq("-unchecked", "-deprecation")""") } val allErrors = errors.filter(_.isFatal) val allWarnings = errors.filter(!_.isFatal) if (!allWarnings.isEmpty && !allErrors.isEmpty) { - println(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) { - println(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) { - println(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) { -- cgit v1.2.3 From 5fe539c707c88eedbb112f5c6bcea1dfe1d52169 Mon Sep 17 00:00:00 2001 From: Jack Koenig Date: Thu, 1 Jul 2021 16:34:48 -0700 Subject: Add ChiselEnum.safe factory method and avoid warning Previously, ChiselEnum would warn any time a UInt is converted to an Enum. There was no way to suppress this warning. Now there is a factory method (`.safe`) that does not warn and returns (Enum, Bool) where the Bool is the result of calling .isValid on an Enum object. The regular UInt cast is also now smarter and will not warn if all bitvectors of the width of the Enum are legal states. --- core/src/main/scala/chisel3/StrongEnum.scala | 34 ++++++++++++++++++++++++---- 1 file changed, 30 insertions(+), 4 deletions(-) (limited to 'core/src/main/scala/chisel3') diff --git a/core/src/main/scala/chisel3/StrongEnum.scala b/core/src/main/scala/chisel3/StrongEnum.scala index 7d328eb7..1d0e04d3 100644 --- a/core/src/main/scala/chisel3/StrongEnum.scala +++ b/core/src/main/scala/chisel3/StrongEnum.scala @@ -131,7 +131,7 @@ abstract class EnumType(private val factory: EnumFactory, selfAnnotating: Boolea if (litOption.isDefined) { true.B } else { - factory.all.map(this === _).reduce(_ || _) + if (factory.isTotal) true.B else factory.all.map(this === _).reduce(_ || _) } } @@ -233,6 +233,12 @@ abstract class EnumFactory { private[chisel3] val enumTypeName = getClass.getName.init + // 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)) + } + private[chisel3] def globalAnnotation: EnumDefChiselAnnotation = EnumDefChiselAnnotation(enumTypeName, (enumNames, enumValues).zipped.toMap) @@ -277,7 +283,7 @@ abstract class EnumFactory { def apply(): Type = new Type - def apply(n: UInt)(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 @@ -288,8 +294,9 @@ 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 { - Builder.warning(s"Casting non-literal UInt to $enumTypeName. You can check that its value is legal by calling isValid") - + if (warn && !this.isTotal) { + 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 val result = Wire(new Type) @@ -297,6 +304,25 @@ abstract class EnumFactory { result } } + + /** Cast an [[UInt]] to the type of this Enum + * + * @note will give a Chisel elaboration time warning if the argument could hit invalid states + * @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) + + /** Safely cast an [[UInt]] to the type of this Enum + * + * @param n the UInt to cast + * @return the equivalent Enum to the value of the cast UInt and a Bool indicating if the + * Enum is valid + */ + def safe(n: UInt)(implicit sourceInfo: SourceInfo, connectionCompileOptions: CompileOptions): (Type, Bool) = { + val t = castImpl(n, warn = false) + (t, t.isValid) + } } -- cgit v1.2.3