diff options
| -rw-r--r-- | core/src/main/scala/chisel3/Assert.scala | 92 | ||||
| -rw-r--r-- | core/src/main/scala/chisel3/Printf.scala | 3 | ||||
| -rw-r--r-- | core/src/main/scala/chisel3/RawModule.scala | 8 | ||||
| -rw-r--r-- | core/src/main/scala/chisel3/VerificationStatement.scala | 236 | ||||
| -rw-r--r-- | core/src/main/scala/chisel3/experimental/package.scala | 5 | ||||
| -rw-r--r-- | core/src/main/scala/chisel3/experimental/verification/package.scala | 60 | ||||
| -rw-r--r-- | core/src/main/scala/chisel3/internal/firrtl/Converter.scala | 4 | ||||
| -rw-r--r-- | core/src/main/scala/chisel3/internal/firrtl/IR.scala | 4 | ||||
| -rw-r--r-- | src/main/scala/chisel3/aop/Select.scala | 2 | ||||
| -rw-r--r-- | src/main/scala/chisel3/experimental/verification/package.scala | 27 | ||||
| -rw-r--r-- | src/main/scala/chisel3/testers/BasicTester.scala | 7 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/PrintableSpec.scala | 8 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/VerificationSpec.scala (renamed from src/test/scala/chiselTests/experimental/verification/VerificationSpec.scala) | 35 | ||||
| -rw-r--r-- | src/test/scala/chiselTests/aop/SelectSpec.scala | 7 |
14 files changed, 300 insertions, 198 deletions
diff --git a/core/src/main/scala/chisel3/Assert.scala b/core/src/main/scala/chisel3/Assert.scala deleted file mode 100644 index 9a497e1f..00000000 --- a/core/src/main/scala/chisel3/Assert.scala +++ /dev/null @@ -1,92 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chisel3 - -import scala.reflect.macros.blackbox.Context -import scala.language.experimental.macros - -import chisel3.internal._ -import chisel3.internal.Builder.pushCommand -import chisel3.internal.firrtl._ -import chisel3.internal.sourceinfo.SourceInfo - -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. - * - * Does not fire when in reset (defined as the encapsulating Module's - * reset). If your definition of reset is not the encapsulating Module's - * reset, you will need to gate this externally. - * - * May be called outside of a Module (like defined in a function), so - * functions using assert make the standard Module assumptions (single clock - * and single reset). - * - * @param cond condition, assertion fires (simulation fails) when false - * @param message optional format string to print when the assertion fires - * @param data optional bits to print in the message formatting - * - * @note See [[printf.apply(fmt:String* printf]] for format string documentation - * @note currently cannot be used in core Chisel / libraries because macro - * defs need to be compiled first and the SBT project is not set up to do - * 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): Unit = macro apply_impl_msg_data - def apply(cond: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Unit = macro apply_impl - - def apply_impl_msg_data(c: Context)(cond: c.Tree, message: c.Tree, data: c.Tree*)(sourceInfo: c.Tree, compileOptions: c.Tree): c.Tree = { - import c.universe._ - val p = c.enclosingPosition - val condStr = s"${p.source.file.name}:${p.line} ${p.lineContent.trim}" - val apply_impl_do = symbolOf[this.type].asClass.module.info.member(TermName("apply_impl_do")) - q"$apply_impl_do($cond, $condStr, _root_.scala.Some($message), ..$data)($sourceInfo, $compileOptions)" - } - - def apply_impl(c: Context)(cond: c.Tree)(sourceInfo: c.Tree, compileOptions: c.Tree): c.Tree = { - import c.universe._ - val p = c.enclosingPosition - val condStr = s"${p.source.file.name}:${p.line} ${p.lineContent.trim}" - val apply_impl_do = symbolOf[this.type].asClass.module.info.member(TermName("apply_impl_do")) - q"$apply_impl_do($cond, $condStr, _root_.scala.None)($sourceInfo, $compileOptions)" - } - - def apply_impl_do(cond: Bool, line: String, message: Option[String], data: Bits*)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions) { - val escLine = line.replaceAll("%", "%%") - when (!(cond || Module.reset.asBool)) { - val fmt = message match { - case Some(msg) => - s"Assertion failed: $msg\n at $escLine\n" - case None => s"Assertion failed\n at $escLine\n" - } - printf.printfWithoutReset(fmt, data:_*) - pushCommand(Stop(sourceInfo, Builder.forcedClock.ref, 1)) - } - } - - /** An elaboration-time assertion, otherwise the same as the above run-time - * assertion. */ - def apply(cond: Boolean, message: => String) { - Predef.assert(cond, message) - } - - /** A workaround for default-value overloading problems in Scala, just - * 'assert(cond, "")' */ - def apply(cond: Boolean) { - Predef.assert(cond, "") - } -} - -object stop { - /** Terminate execution with a failure code. */ - def apply(code: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Unit = { - when (!Module.reset.asBool) { - pushCommand(Stop(sourceInfo, Builder.forcedClock.ref, code)) - } - } - - /** Terminate execution, indicating success. */ - def apply()(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Unit = { - stop(0) - } -} diff --git a/core/src/main/scala/chisel3/Printf.scala b/core/src/main/scala/chisel3/Printf.scala index cf7821b8..be0146bb 100644 --- a/core/src/main/scala/chisel3/Printf.scala +++ b/core/src/main/scala/chisel3/Printf.scala @@ -6,7 +6,6 @@ import scala.language.experimental.macros import chisel3.internal._ import chisel3.internal.Builder.pushCommand import chisel3.internal.sourceinfo.SourceInfo -import chisel3.experimental.BaseSim /** Prints a message in simulation * @@ -34,7 +33,7 @@ object printf { } /** Named class for [[printf]]s. */ - final class Printf(val pable: Printable) extends BaseSim + final class Printf private[chisel3](val pable: Printable) extends VerificationStatement /** Prints a message in simulation * diff --git a/core/src/main/scala/chisel3/RawModule.scala b/core/src/main/scala/chisel3/RawModule.scala index 27f16ad4..f1b4c1cf 100644 --- a/core/src/main/scala/chisel3/RawModule.scala +++ b/core/src/main/scala/chisel3/RawModule.scala @@ -5,7 +5,7 @@ package chisel3 import scala.collection.mutable.{ArrayBuffer, HashMap} import scala.util.Try import scala.language.experimental.macros -import chisel3.experimental.{BaseModule, BaseSim} +import chisel3.experimental.BaseModule import chisel3.internal._ import chisel3.internal.BaseModule.{ModuleClone, InstanceClone} import chisel3.internal.Builder._ @@ -81,7 +81,11 @@ abstract class RawModule(implicit moduleCompileOptions: CompileOptions) 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: BaseSim => id.forceName(None, default="SIM", _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 { diff --git a/core/src/main/scala/chisel3/VerificationStatement.scala b/core/src/main/scala/chisel3/VerificationStatement.scala new file mode 100644 index 00000000..23adc192 --- /dev/null +++ b/core/src/main/scala/chisel3/VerificationStatement.scala @@ -0,0 +1,236 @@ +// SPDX-License-Identifier: Apache-2.0 + +package chisel3 + +import scala.reflect.macros.blackbox.Context +import scala.language.experimental.macros +import chisel3.internal._ +import chisel3.internal.Builder.pushCommand +import chisel3.internal.firrtl._ +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. + * + * Does not fire when in reset (defined as the encapsulating Module's + * reset). If your definition of reset is not the encapsulating Module's + * reset, you will need to gate this externally. + * + * May be called outside of a Module (like defined in a function), so + * functions using assert make the standard Module assumptions (single clock + * and single reset). + * + * @param cond condition, assertion fires (simulation fails) when false + * @param message optional format string to print when the assertion fires + * @param data optional bits to print in the message formatting + * + * @note See [[printf.apply(fmt:String* printf]] for format string documentation + * @note currently cannot be used in core Chisel / libraries because macro + * defs need to be compiled first and the SBT project is not set up to do + * 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 + + /** 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 + + import VerificationStatement._ + + 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 = { + 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 = { + val id = new Assert() + when(!Module.reset.asBool()) { + Builder.pushCommand(Verification(id, Formal.Assert, sourceInfo, Module.clock.ref, cond.ref, "")) + failureMessage("Assertion", line, cond, message, data) + } + id + } +} + + +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. + * + * Does not fire when in reset (defined as the encapsulating Module's + * reset). If your definition of reset is not the encapsulating Module's + * reset, you will need to gate this externally. + * + * May be called outside of a Module (like defined in a function), so + * functions using assert make the standard Module assumptions (single clock + * and single reset). + * + * @param cond condition, assertion fires (simulation fails) when false + * @param message optional format string to print when the assertion fires + * @param data optional bits to print in the message formatting + * + * @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 + + /** 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 + + import VerificationStatement._ + + 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 = { + 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 = { + val id = new Assume() + when(!Module.reset.asBool()) { + Builder.pushCommand(Verification(id, Formal.Assume, sourceInfo, Module.clock.ref, cond.ref, "")) + failureMessage("Assumption", line, cond, message, data) + } + id + } +} + + +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. + * + * Does not fire when in reset (defined as the encapsulating Module's + * reset). If your definition of reset is not the encapsulating Module's + * reset, you will need to gate this externally. + * + * May be called outside of a Module (like defined in a function), so + * functions using assert make the standard Module assumptions (single clock + * and single reset). + * + * @param cond condition that will be sampled on every clock tick + * @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 + + /** Named class for cover statements. */ + 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 = { + 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 = { + 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 = { + val id = new Cover() + when(!Module.reset.asBool()) { + Builder.pushCommand(Verification(id, Formal.Cover, sourceInfo, Module.clock.ref, cond.ref, "")) + } + id + } +} + +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) { + 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") + def apply(code: Int)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Stop = { + val stp = new Stop() + 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 +} + +/** Base class for all verification statements: Assert, Assume, Cover, Stop and Printf. */ +abstract class VerificationStatement extends NamedComponent { + _parent.foreach(_.addId(this)) +} + +/** Helper functions for common functionality required by stop, assert, assume or cover */ +private object VerificationStatement { + + type SourceLineInfo = (String, Int, String) + + def getLine(c: blackbox.Context): SourceLineInfo = { + val p = c.enclosingPosition + (p.source.file.name, p.line, p.lineContent.trim) + } + + // 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 = { + val (filename, line, content) = lineInfo + val lineMsg = s"$filename:$line $content".replaceAll("%", "%%") + val fmt = message match { + case Some(msg) => + s"$kind failed: $msg\n at $lineMsg\n" + case None => s"$kind failed\n at $lineMsg\n" + } + when(!cond) { + printf.printfWithoutReset(fmt, data:_*) + } + } +} diff --git a/core/src/main/scala/chisel3/experimental/package.scala b/core/src/main/scala/chisel3/experimental/package.scala index 8018159f..0fc79487 100644 --- a/core/src/main/scala/chisel3/experimental/package.scala +++ b/core/src/main/scala/chisel3/experimental/package.scala @@ -166,9 +166,4 @@ package object experimental { val prefix = chisel3.internal.prefix // Use to remove prefixes not in provided scope val noPrefix = chisel3.internal.noPrefix - - /** Base simulation-only component. */ - abstract class BaseSim extends NamedComponent { - _parent.foreach(_.addId(this)) - } } diff --git a/core/src/main/scala/chisel3/experimental/verification/package.scala b/core/src/main/scala/chisel3/experimental/verification/package.scala deleted file mode 100644 index 190083fd..00000000 --- a/core/src/main/scala/chisel3/experimental/verification/package.scala +++ /dev/null @@ -1,60 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -package chisel3.experimental - -import chisel3._ -import chisel3.internal.Builder -import chisel3.internal.firrtl.{Formal, Verification} -import chisel3.internal.sourceinfo.SourceInfo - -package object verification { - - object assert { - /** Named class for assertions. */ - final class Assert(private[chisel3] val predicate: Bool) extends BaseSim - - - def apply(predicate: Bool, msg: String = "")( - implicit sourceInfo: SourceInfo, - compileOptions: CompileOptions): Assert = { - val a = new Assert(predicate) - when (!Module.reset.asBool) { - val clock = Module.clock - Builder.pushCommand(Verification(a, Formal.Assert, sourceInfo, clock.ref, predicate.ref, msg)) - } - a - } - } - - object assume { - /** Named class for assumes. */ - final class Assume(private[chisel3] val predicate: Bool) extends BaseSim - - def apply(predicate: Bool, msg: String = "")( - implicit sourceInfo: SourceInfo, - compileOptions: CompileOptions): Assume = { - val a = new Assume(predicate) - when (!Module.reset.asBool) { - val clock = Module.clock - Builder.pushCommand(Verification(a, Formal.Assume, sourceInfo, clock.ref, predicate.ref, msg)) - } - a - } - } - - object cover { - /** Named class for covers. */ - final class Cover(private[chisel3] val predicate: Bool) extends BaseSim - - def apply(predicate: Bool, msg: String = "")( - implicit sourceInfo: SourceInfo, - compileOptions: CompileOptions): Cover = { - val clock = Module.clock - val c = new Cover(predicate) - when (!Module.reset.asBool) { - Builder.pushCommand(Verification(c, Formal.Cover, sourceInfo, clock.ref, predicate.ref, msg)) - } - c - } - } -} diff --git a/core/src/main/scala/chisel3/internal/firrtl/Converter.scala b/core/src/main/scala/chisel3/internal/firrtl/Converter.scala index f56c3b15..1dc52823 100644 --- a/core/src/main/scala/chisel3/internal/firrtl/Converter.scala +++ b/core/src/main/scala/chisel3/internal/firrtl/Converter.scala @@ -142,8 +142,8 @@ private[chisel3] object Converter { Some(fir.IsInvalid(convert(info), convert(arg, ctx, info))) case e @ DefInstance(info, id, _) => Some(fir.DefInstance(convert(info), e.name, id.name)) - case Stop(info, clock, ret) => - Some(fir.Stop(convert(info), ret, convert(clock, ctx, info), firrtl.Utils.one)) + case e @ Stop(_, info, clock, ret) => + 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), diff --git a/core/src/main/scala/chisel3/internal/firrtl/IR.scala b/core/src/main/scala/chisel3/internal/firrtl/IR.scala index 0b568548..1a06cd36 100644 --- a/core/src/main/scala/chisel3/internal/firrtl/IR.scala +++ b/core/src/main/scala/chisel3/internal/firrtl/IR.scala @@ -784,7 +784,7 @@ case class Connect(sourceInfo: SourceInfo, loc: Node, exp: Arg) extends Command case class BulkConnect(sourceInfo: SourceInfo, loc1: Node, loc2: Node) extends Command case class Attach(sourceInfo: SourceInfo, locs: Seq[Node]) extends Command case class ConnectInit(sourceInfo: SourceInfo, loc: Node, exp: Arg) extends Command -case class Stop(sourceInfo: SourceInfo, clock: Arg, ret: Int) extends Command +case class Stop(id: stop.Stop, sourceInfo: SourceInfo, clock: Arg, ret: Int) extends Definition 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 { @@ -792,7 +792,7 @@ object Formal extends Enumeration { val Assume = Value("assume") val Cover = Value("cover") } -case class Verification[T <: BaseSim](id: T, op: Formal.Value, sourceInfo: SourceInfo, clock: Arg, +case class Verification[T <: VerificationStatement](id: T, op: Formal.Value, sourceInfo: SourceInfo, clock: Arg, predicate: Arg, message: String) extends Definition abstract class Component extends Arg { def id: BaseModule diff --git a/src/main/scala/chisel3/aop/Select.scala b/src/main/scala/chisel3/aop/Select.scala index 2384c4d3..9c7320ce 100644 --- a/src/main/scala/chisel3/aop/Select.scala +++ b/src/main/scala/chisel3/aop/Select.scala @@ -269,7 +269,7 @@ object Select { val stops = mutable.ArrayBuffer[Stop]() searchWhens(module, (cmd: Command, preds: Seq[Predicate]) => { cmd match { - case chisel3.internal.firrtl.Stop(_, clock, ret) => stops += Stop(preds, ret, getId(clock).asInstanceOf[Clock]) + case chisel3.internal.firrtl.Stop(_, _, clock, ret) => stops += Stop(preds, ret, getId(clock).asInstanceOf[Clock]) case other => } }) diff --git a/src/main/scala/chisel3/experimental/verification/package.scala b/src/main/scala/chisel3/experimental/verification/package.scala new file mode 100644 index 00000000..f95b30bc --- /dev/null +++ b/src/main/scala/chisel3/experimental/verification/package.scala @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: Apache-2.0 + +package chisel3.experimental + +import chisel3.{Bool, CompileOptions} +import chisel3.internal.sourceinfo.SourceInfo + +package object verification { + + object assert { + @deprecated("Please use chisel3.assert instead. The chisel3.experimental.verification package will be removed.", "Chisel 3.4") + def apply(predicate: Bool, msg: String = "") + (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): chisel3.assert.Assert = chisel3.assert(predicate, msg) + } + + object assume { + @deprecated("Please use chisel3.assume instead. The chisel3.experimental.verification package will be removed.", "Chisel 3.4") + def apply(predicate: Bool, msg: String = "") + (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): chisel3.assume.Assume = chisel3.assume(predicate, msg) + } + + object cover { + @deprecated("Please use chisel3.cover instead. The chisel3.experimental.verification package will be removed.", "Chisel 3.4") + def apply(predicate: Bool, msg: String = "") + (implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): chisel3.cover.Cover = chisel3.cover(predicate, msg) + } +} diff --git a/src/main/scala/chisel3/testers/BasicTester.scala b/src/main/scala/chisel3/testers/BasicTester.scala index d17407ea..99002660 100644 --- a/src/main/scala/chisel3/testers/BasicTester.scala +++ b/src/main/scala/chisel3/testers/BasicTester.scala @@ -21,12 +21,7 @@ class BasicTester extends Module() { * reset). If your definition of reset is not the encapsulating Module's * reset, you will need to gate this externally. */ - def stop()(implicit sourceInfo: SourceInfo) { - // TODO: rewrite this using library-style SourceInfo passing. - when (!reset.asBool) { - pushCommand(Stop(sourceInfo, clock.ref, 0)) - } - } + def stop()(implicit sourceInfo: SourceInfo): Unit = chisel3.stop() /** The finish method provides a hook that subclasses of BasicTester can use to * alter a circuit after their constructor has been called. diff --git a/src/test/scala/chiselTests/PrintableSpec.scala b/src/test/scala/chiselTests/PrintableSpec.scala index 25b54966..95103352 100644 --- a/src/test/scala/chiselTests/PrintableSpec.scala +++ b/src/test/scala/chiselTests/PrintableSpec.scala @@ -3,7 +3,7 @@ package chiselTests import chisel3._ -import chisel3.experimental.{BaseSim, ChiselAnnotation} +import chisel3.experimental.ChiselAnnotation import chisel3.stage.ChiselStage import chisel3.testers.BasicTester import firrtl.annotations.{ReferenceTarget, SingleTargetAnnotation} @@ -23,7 +23,7 @@ object PrintfAnnotation { /** Create annotation for a given [[printf]]. * @param c component to be annotated */ - def annotate(c: BaseSim): Unit = { + def annotate(c: VerificationStatement): Unit = { chisel3.experimental.annotate(new ChiselAnnotation { def toFirrtl: PrintfAnnotation = PrintfAnnotation(c.toTarget) }) @@ -246,7 +246,7 @@ class PrintableSpec extends AnyFlatSpec with Matchers { // check for expected annotations exactly(3, annoLines) should include ("chiselTests.PrintfAnnotation") exactly(1, annoLines) should include ("~PrintfAnnotationTest|PrintfAnnotationTest>farewell") - exactly(1, annoLines) should include ("~PrintfAnnotationTest|PrintfAnnotationTest>SIM") + exactly(1, annoLines) should include ("~PrintfAnnotationTest|PrintfAnnotationTest>printf") exactly(1, annoLines) should include ("~PrintfAnnotationTest|PrintfAnnotationTest>howdy") // read in FIRRTL file @@ -256,7 +256,7 @@ class PrintableSpec extends AnyFlatSpec with Matchers { // check that verification components have expected names exactly(1, firLines) should include ("""printf(clock, UInt<1>("h1"), "hello AnonymousBundle(foo -> %d, bar -> %d)", myBun.foo, myBun.bar) : howdy""") - exactly(1, firLines) should include ("""printf(clock, UInt<1>("h1"), "goodbye AnonymousBundle(foo -> %d, bar -> %d)", myBun.foo, myBun.bar) : SIM""") + exactly(1, firLines) should include ("""printf(clock, UInt<1>("h1"), "goodbye AnonymousBundle(foo -> %d, bar -> %d)", myBun.foo, myBun.bar) : printf""") exactly(1, firLines) should include ("""printf(clock, UInt<1>("h1"), "adieu AnonymousBundle(foo -> %d, bar -> %d)", myBun.foo, myBun.bar) : farewell""") } } diff --git a/src/test/scala/chiselTests/experimental/verification/VerificationSpec.scala b/src/test/scala/chiselTests/VerificationSpec.scala index 1e080739..2d7144df 100644 --- a/src/test/scala/chiselTests/experimental/verification/VerificationSpec.scala +++ b/src/test/scala/chiselTests/VerificationSpec.scala @@ -1,15 +1,14 @@ // SPDX-License-Identifier: Apache-2.0 -package chiselTests.experimental.verification +package chiselTests import chisel3._ import chisel3.experimental.{ChiselAnnotation, verification => formal} import chisel3.stage.ChiselStage -import chiselTests.ChiselPropSpec import firrtl.annotations.{ReferenceTarget, SingleTargetAnnotation} +import org.scalatest.matchers.should.Matchers import java.io.File -import org.scalatest.matchers.should.Matchers class SimpleTest extends Module { val io = IO(new Bundle{ @@ -17,10 +16,10 @@ class SimpleTest extends Module { val out = Output(UInt(8.W)) }) io.out := io.in - formal.cover(io.in === 3.U) + cover(io.in === 3.U) when (io.in === 3.U) { - formal.assume(io.in =/= 2.U) - formal.assert(io.out === io.in) + assume(io.in =/= 2.U) + assert(io.out === io.in) } } @@ -35,7 +34,7 @@ object VerifAnnotation { /** Create annotation for a given verification component. * @param c component to be annotated */ - def annotate(c: experimental.BaseSim): Unit = { + def annotate(c: VerificationStatement): Unit = { chisel3.experimental.annotate(new ChiselAnnotation { def toFirrtl: VerifAnnotation = VerifAnnotation(c.toTarget) }) @@ -60,8 +59,8 @@ class VerificationSpec extends ChiselPropSpec with Matchers { assertContains(lines, "when _T_6 : @[VerificationSpec.scala") assertContains(lines, "assume(clock, _T_4, UInt<1>(\"h1\"), \"\")") - assertContains(lines, "when _T_9 : @[VerificationSpec.scala") - assertContains(lines, "assert(clock, _T_7, UInt<1>(\"h1\"), \"\")") + assertContains(lines, "when _T_10 : @[VerificationSpec.scala") + assertContains(lines, "assert(clock, _T_8, UInt<1>(\"h1\"), \"\")") } property("annotation of verification constructs should work") { @@ -72,9 +71,9 @@ class VerificationSpec extends ChiselPropSpec with Matchers { val out = Output(UInt(8.W)) }) io.out := io.in - val cov = formal.cover(io.in === 3.U) - val assm = formal.assume(io.in =/= 2.U) - val asst = formal.assert(io.out === io.in) + val cov = cover(io.in === 3.U) + val assm = chisel3.assume(io.in =/= 2.U) + val asst = chisel3.assert(io.out === io.in) VerifAnnotation.annotate(cov) VerifAnnotation.annotate(assm) VerifAnnotation.annotate(asst) @@ -93,7 +92,7 @@ class VerificationSpec extends ChiselPropSpec with Matchers { val annoLines = scala.io.Source.fromFile(annoFile).getLines.toList // check for expected verification annotations - exactly(3, annoLines) should include ("chiselTests.experimental.verification.VerifAnnotation") + exactly(3, annoLines) should include ("chiselTests.VerifAnnotation") exactly(1, annoLines) should include ("~AnnotationTest|AnnotationTest>asst") exactly(1, annoLines) should include ("~AnnotationTest|AnnotationTest>assm") exactly(1, annoLines) should include ("~AnnotationTest|AnnotationTest>cov") @@ -106,7 +105,7 @@ class VerificationSpec extends ChiselPropSpec with Matchers { // check that verification components have expected names exactly(1, firLines) should include ("cover(clock, _T, UInt<1>(\"h1\"), \"\") : cov") exactly(1, firLines) should include ("assume(clock, _T_3, UInt<1>(\"h1\"), \"\") : assm") - exactly(1, firLines) should include ("assert(clock, _T_6, UInt<1>(\"h1\"), \"\") : asst") + exactly(1, firLines) should include ("assert(clock, _T_7, UInt<1>(\"h1\"), \"\") : asst") } property("annotation of verification constructs with suggested name should work") { @@ -118,11 +117,11 @@ class VerificationSpec extends ChiselPropSpec with Matchers { }) io.out := io.in - val goodbye = formal.assert(io.in === 1.U) + val goodbye = chisel3.assert(io.in === 1.U) goodbye.suggestName("hello") VerifAnnotation.annotate(goodbye) - VerifAnnotation.annotate(formal.assume(io.in =/= 2.U).suggestName("howdy")) + VerifAnnotation.annotate(chisel3.assume(io.in =/= 2.U).suggestName("howdy")) } // compile circuit @@ -138,7 +137,7 @@ class VerificationSpec extends ChiselPropSpec with Matchers { val annoLines = scala.io.Source.fromFile(annoFile).getLines.toList // check for expected verification annotations - exactly(2, annoLines) should include ("chiselTests.experimental.verification.VerifAnnotation") + exactly(2, annoLines) should include ("chiselTests.VerifAnnotation") exactly(1, annoLines) should include ("~AnnotationRenameTest|AnnotationRenameTest>hello") exactly(1, annoLines) should include ("~AnnotationRenameTest|AnnotationRenameTest>howdy") @@ -149,6 +148,6 @@ class VerificationSpec extends ChiselPropSpec with Matchers { // check that verification components have expected names exactly(1, firLines) should include ("assert(clock, _T, UInt<1>(\"h1\"), \"\") : hello") - exactly(1, firLines) should include ("assume(clock, _T_3, UInt<1>(\"h1\"), \"\") : howdy") + exactly(1, firLines) should include ("assume(clock, _T_4, UInt<1>(\"h1\"), \"\") : howdy") } } diff --git a/src/test/scala/chiselTests/aop/SelectSpec.scala b/src/test/scala/chiselTests/aop/SelectSpec.scala index e09e78c8..2b47c6b8 100644 --- a/src/test/scala/chiselTests/aop/SelectSpec.scala +++ b/src/test/scala/chiselTests/aop/SelectSpec.scala @@ -133,11 +133,10 @@ class SelectSpec extends ChiselFlatSpec { { dut: SelectTester => Seq(Select.Stop( Seq( - When(Select.ops("eq")(dut).dropRight(1).last.asInstanceOf[Bool]), - When(dut.nreset), - WhenNot(dut.overflow) + When(Select.ops("eq")(dut)(1).asInstanceOf[Bool]), + When(dut.overflow) ), - 1, + 0, dut.clock )) } |
