// // 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 // /** Scaladoc information for internal verification statement macros // * that are used in objects assert, assume and cover. // * // * @groupdesc VerifPrintMacros // * // *

// * '''These internal methods are not part of the public-facing API!''' // *

// *
// * // * @groupprio VerifPrintMacros 1001 // */ // trait VerifPrintMacrosDoc // object assert extends VerifPrintMacrosDoc { // /** Checks for a condition to be valid in the circuit at rising clock edge // * when not in reset. If the condition evaluates to false, the circuit // * simulation stops with an error. // * // * @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 _applyMacroWithInterpolatorCheck // /** 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 current implicit reset, e.g. as set by // * the enclosing `withReset` or Module.reset. // * // * 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) on a rising clock edge when false and reset is not asserted // * @param message optional chisel Printable type message // * // * @note See [[printf.apply(fmt:Printable)]] for documentation on printf using Printables // * @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 // */ // def apply( // cond: Bool, // message: Printable // )( // implicit sourceInfo: SourceInfo, // compileOptions: CompileOptions // ): Assert = macro _applyMacroWithPrintableMessage // def apply(cond: Bool)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Assert = // macro _applyMacroWithNoMessage // import VerificationStatement._ // /** @group VerifPrintMacros */ // def _applyMacroWithInterpolatorCheck( // c: blackbox.Context // )(cond: c.Tree, // message: c.Tree, // data: c.Tree* // )(sourceInfo: c.Tree, // compileOptions: c.Tree // ): c.Tree = { // import c.universe._ // message match { // case q"scala.StringContext.apply(..$_).s(..$_)" => // c.warning( // c.enclosingPosition, // "The s-interpolator prints the Scala .toString of Data objects rather than the value " + // "of the hardware wire during simulation. Use the cf-interpolator instead. If you want " + // "an elaboration time check, call assert with a Boolean condition." // ) // case _ => // } // val apply_impl_do = symbolOf[this.type].asClass.module.info.member(TermName("_applyWithSourceLinePrintable")) // q"$apply_impl_do($cond, ${getLine(c)}, _root_.scala.Some(_root_.chisel3.Printable.pack($message, ..$data)))($sourceInfo, $compileOptions)" // } // /** 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 // /** @group VerifPrintMacros */ // @deprecated( // "This method has been deprecated in favor of _applyMacroWithStringMessage. Please use the same.", // "Chisel 3.5" // ) // 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("_applyWithSourceLinePrintable")) // q"$apply_impl_do($cond, ${getLine(c)},_root_.scala.Some(_root_.chisel3.Printable.pack($message,..$data)))($sourceInfo, $compileOptions)" // } // /** @group VerifPrintMacros */ // def _applyMacroWithStringMessage( // 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("_applyWithSourceLinePrintable")) // q"$apply_impl_do($cond, ${getLine(c)},_root_.scala.Some(_root_.chisel3.Printable.pack($message,..$data)))($sourceInfo, $compileOptions)" // } // /** @group VerifPrintMacros */ // def _applyMacroWithPrintableMessage( // 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("_applyWithSourceLinePrintable")) // q"$apply_impl_do($cond, ${getLine(c)}, _root_.scala.Some($message))($sourceInfo, $compileOptions)" // } // /** @group VerifPrintMacros */ // 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("_applyWithSourceLinePrintable")) // q"$apply_impl_do($cond, ${getLine(c)}, _root_.scala.None)($sourceInfo, $compileOptions)" // } // /** This will be removed in Chisel 3.6 in favor of the Printable version // * // * @group VerifPrintMacros // */ // 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()) { // failureMessage("Assertion", line, cond, message.map(Printable.pack(_, data: _*))) // Builder.pushCommand(Verification(id, Formal.Assert, sourceInfo, Module.clock.ref, cond.ref, "")) // } // id // } // /** @group VerifPrintMacros */ // def _applyWithSourceLinePrintable( // cond: Bool, // line: SourceLineInfo, // message: Option[Printable] // )( // implicit sourceInfo: SourceInfo, // compileOptions: CompileOptions // ): Assert = { // val id = new Assert() // message.foreach(Printable.checkScope(_)) // when(!Module.reset.asBool()) { // failureMessage("Assertion", line, cond, message) // Builder.pushCommand(Verification(id, Formal.Assert, sourceInfo, Module.clock.ref, cond.ref, "")) // } // id // } // } // object assume extends VerifPrintMacrosDoc { // /** 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 _applyMacroWithInterpolatorCheck // /** 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 Printable type message when the assertion fires // * // * @note See [[printf.apply(fmt:Printable]] for documentation on printf using Printables // */ // def apply( // cond: Bool, // message: Printable // )( // implicit sourceInfo: SourceInfo, // compileOptions: CompileOptions // ): Assume = macro _applyMacroWithPrintableMessage // 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._ // /** @group VerifPrintMacros */ // def _applyMacroWithInterpolatorCheck( // c: blackbox.Context // )(cond: c.Tree, // message: c.Tree, // data: c.Tree* // )(sourceInfo: c.Tree, // compileOptions: c.Tree // ): c.Tree = { // import c.universe._ // message match { // case q"scala.StringContext.apply(..$_).s(..$_)" => // c.warning( // c.enclosingPosition, // "The s-interpolator prints the Scala .toString of Data objects rather than the value " + // "of the hardware wire during simulation. Use the cf-interpolator instead. If you want " + // "an elaboration time check, call assert with a Boolean condition." // ) // case _ => // } // val apply_impl_do = symbolOf[this.type].asClass.module.info.member(TermName("_applyWithSourceLinePrintable")) // q"$apply_impl_do($cond, ${getLine(c)}, _root_.scala.Some(_root_.chisel3.Printable.pack($message, ..$data)))($sourceInfo, $compileOptions)" // } // /** @group VerifPrintMacros */ // @deprecated( // "This method has been deprecated in favor of _applyMacroWithStringMessage. Please use the same.", // "Chisel 3.5" // ) // 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("_applyWithSourceLinePrintable")) // q"$apply_impl_do($cond, ${getLine(c)}, _root_.scala.Some(_root_.chisel3.Printable.pack($message, ..$data)))($sourceInfo, $compileOptions)" // } // /** @group VerifPrintMacros */ // def _applyMacroWithStringMessage( // 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("_applyWithSourceLinePrintable")) // q"$apply_impl_do($cond, ${getLine(c)}, _root_.scala.Some(_root_.chisel3.Printable.pack($message, ..$data)))($sourceInfo, $compileOptions)" // } // /** @group VerifPrintMacros */ // def _applyMacroWithPrintableMessage( // 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("_applyWithSourceLinePrintable")) // q"$apply_impl_do($cond, ${getLine(c)}, _root_.scala.Some($message))($sourceInfo, $compileOptions)" // } // /** @group VerifPrintMacros */ // 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("_applyWithSourceLinePrintable")) // q"$apply_impl_do($cond, ${getLine(c)}, _root_.scala.None)($sourceInfo, $compileOptions)" // } // /** This will be removed in Chisel 3.6 in favor of the Printable version // * // * @group VerifPrintMacros // */ // 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()) { // failureMessage("Assumption", line, cond, message.map(Printable.pack(_, data: _*))) // Builder.pushCommand(Verification(id, Formal.Assume, sourceInfo, Module.clock.ref, cond.ref, "")) // } // id // } // /** @group VerifPrintMacros */ // def _applyWithSourceLinePrintable( // cond: Bool, // line: SourceLineInfo, // message: Option[Printable] // )( // implicit sourceInfo: SourceInfo, // compileOptions: CompileOptions // ): Assume = { // val id = new Assume() // message.foreach(Printable.checkScope(_)) // when(!Module.reset.asBool()) { // failureMessage("Assumption", line, cond, message) // Builder.pushCommand(Verification(id, Formal.Assume, sourceInfo, Module.clock.ref, cond.ref, "")) // } // id // } // } // object cover extends VerifPrintMacrosDoc { // /** 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._ // /** @group VerifPrintMacros */ // 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)" // } // /** @group VerifPrintMacros */ // 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)" // } // /** @group VerifPrintMacros */ // 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) // } // def failureMessage( // kind: String, // lineInfo: SourceLineInfo, // cond: Bool, // message: Option[Printable] // )( // 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) => // p"$kind failed: $msg\n at $lineMsg\n" // case None => p"$kind failed\n at $lineMsg\n" // } // when(!cond) { // printf.printfWithoutReset(fmt) // } // } // }