summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--chiselFrontend/src/main/scala/chisel3/core/Assert.scala11
-rw-r--r--src/test/scala/chiselTests/Assert.scala21
2 files changed, 27 insertions, 5 deletions
diff --git a/chiselFrontend/src/main/scala/chisel3/core/Assert.scala b/chiselFrontend/src/main/scala/chisel3/core/Assert.scala
index 7f67f244..43a74192 100644
--- a/chiselFrontend/src/main/scala/chisel3/core/Assert.scala
+++ b/chiselFrontend/src/main/scala/chisel3/core/Assert.scala
@@ -23,9 +23,10 @@ object assert { // scalastyle:ignore object.name
* and single reset).
*
* @param cond condition, assertion fires (simulation fails) when false
- * @param message optional message to print when the assertion fires
+ * @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
@@ -51,12 +52,14 @@ object assert { // scalastyle:ignore object.name
}
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.toBool)) {
val fmt = message match {
- case Some(str) => s"Assertion failed: $str\n at $line\n"
- case None => s"Assertion failed\n at $line\n"
+ case Some(msg) =>
+ s"Assertion failed: $msg\n at $escLine\n"
+ case None => s"Assertion failed\n at $escLine\n"
}
- printf.printfWithoutReset(fmt.replaceAll("%", "%%"), data:_*)
+ printf.printfWithoutReset(fmt, data:_*)
pushCommand(Stop(sourceInfo, Node(Builder.forcedClock), 1))
}
}
diff --git a/src/test/scala/chiselTests/Assert.scala b/src/test/scala/chiselTests/Assert.scala
index 994a16fd..075cc4e2 100644
--- a/src/test/scala/chiselTests/Assert.scala
+++ b/src/test/scala/chiselTests/Assert.scala
@@ -46,7 +46,18 @@ class PipelinedResetTester extends BasicTester {
class ModuloAssertTester extends BasicTester {
assert((4.U % 2.U) === 0.U)
- assert(1.U === 1.U, "I'm 110% sure this will succeed")
+ stop()
+}
+
+class FormattedAssertTester extends BasicTester {
+ val foobar = Wire(UInt(32.W))
+ foobar := 123.U
+ assert(foobar === 123.U, "Error! Wire foobar =/= %x! This is 100%% wrong.\n", foobar)
+ stop()
+}
+
+class BadUnescapedPercentAssertTester extends BasicTester {
+ assert(1.U === 1.U, "I'm 110% sure this is an invalid message")
stop()
}
@@ -63,4 +74,12 @@ class AssertSpec extends ChiselFlatSpec {
"Assertions" should "allow the modulo operator % in the message" in {
assertTesterPasses{ new ModuloAssertTester }
}
+ they should "allow printf-style format strings with arguments" in {
+ assertTesterPasses{ new FormattedAssertTester }
+ }
+ they should "not allow unescaped % in the message" in {
+ a [java.util.UnknownFormatConversionException] should be thrownBy {
+ elaborate { new BadUnescapedPercentAssertTester }
+ }
+ }
}