summaryrefslogtreecommitdiff
path: root/core/src/main/scala/chisel3/Printf.scala
diff options
context:
space:
mode:
authorJack Koenig2020-03-22 18:13:58 -0700
committerJack Koenig2020-03-25 19:17:15 -0700
commitfbf5e6f1a0e8bf535d465b748ad554575fe62156 (patch)
tree578858ab6d219ca6daf44cf87b73f75054989097 /core/src/main/scala/chisel3/Printf.scala
parentb2e004fb615a3c931d910a338b9faa99c1c975d7 (diff)
Rename subprojects to more canonical names
* Rename coreMacros to macros * Rename chiselFrontend to core Also make each subproject publish with "chisel3-" as a prefix
Diffstat (limited to 'core/src/main/scala/chisel3/Printf.scala')
-rw-r--r--core/src/main/scala/chisel3/Printf.scala102
1 files changed, 102 insertions, 0 deletions
diff --git a/core/src/main/scala/chisel3/Printf.scala b/core/src/main/scala/chisel3/Printf.scala
new file mode 100644
index 00000000..0478e889
--- /dev/null
+++ b/core/src/main/scala/chisel3/Printf.scala
@@ -0,0 +1,102 @@
+// See LICENSE for license details.
+
+package chisel3
+
+import scala.language.experimental.macros
+
+import chisel3.internal._
+import chisel3.internal.Builder.pushCommand
+import chisel3.internal.firrtl._
+import chisel3.internal.sourceinfo.SourceInfo
+
+/** Prints a message in simulation
+ *
+ * See apply methods for use
+ */
+object printf { // scalastyle:ignore object.name
+ /** Helper for packing escape characters */
+ private[chisel3] def format(formatIn: String): String = {
+ require(formatIn forall (c => c.toInt > 0 && c.toInt < 128),
+ "format strings must comprise non-null ASCII values")
+ def escaped(x: Char) = {
+ require(x.toInt >= 0, s"char ${x} to Int ${x.toInt} must be >= 0")
+ if (x == '"' || x == '\\') {
+ s"\\${x}"
+ } else if (x == '\n') {
+ "\\n"
+ } else if (x == '\t') {
+ "\\t"
+ } else {
+ require(x.toInt >= 32, s"char ${x} to Int ${x.toInt} must be >= 32") // TODO \xNN once FIRRTL issue #59 is resolved
+ x
+ }
+ }
+ formatIn map escaped mkString ""
+ }
+
+ /** Prints a message in simulation
+ *
+ * Prints a message every cycle. If defined within the scope of a [[when]] block, the message
+ * will only be printed on cycles that the when condition is true.
+ *
+ * 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), uses the current default clock
+ * and reset. These can be overriden with [[withClockAndReset]].
+ *
+ * ==Format Strings==
+ *
+ * This method expects a ''format string'' and an ''argument list'' in a similar style to printf
+ * in C. The format string expects a [[scala.Predef.String String]] that may contain ''format
+ * specifiers'' For example:
+ * {{{
+ * printf("myWire has the value %d\n", myWire)
+ * }}}
+ * This prints the string "myWire has the value " followed by the current value of `myWire` (in
+ * decimal, followed by a newline.
+ *
+ * There must be exactly as many arguments as there are format specifiers
+ *
+ * ===Format Specifiers===
+ *
+ * Format specifiers are prefixed by `%`. If you wish to print a literal `%`, use `%%`.
+ * - `%d` - Decimal
+ * - `%x` - Hexadecimal
+ * - `%b` - Binary
+ * - `%c` - 8-bit Character
+ * - `%n` - Name of a signal
+ * - `%N` - Full name of a leaf signal (in an aggregate)
+ *
+ * @param fmt printf format string
+ * @param data format string varargs containing data to print
+ */
+ def apply(fmt: String, data: Bits*)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Unit =
+ apply(Printable.pack(fmt, data:_*))
+ /** Prints a message in simulation
+ *
+ * Prints a message every cycle. If defined within the scope of a [[when]] block, the message
+ * will only be printed on cycles that the when condition is true.
+ *
+ * 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), uses the current default clock
+ * and reset. These can be overriden with [[withClockAndReset]].
+ *
+ * @see [[Printable]] documentation
+ * @param pable [[Printable]] to print
+ */
+ def apply(pable: Printable)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Unit = {
+ when (!Module.reset.asBool) {
+ printfWithoutReset(pable)
+ }
+ }
+
+ private[chisel3] def printfWithoutReset(pable: Printable)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Unit = { // scalastyle:ignore line.size.limit
+ val clock = Builder.forcedClock
+ pushCommand(Printf(sourceInfo, clock.ref, pable))
+ }
+ private[chisel3] def printfWithoutReset(fmt: String, data: Bits*)(implicit sourceInfo: SourceInfo, compileOptions: CompileOptions): Unit = // scalastyle:ignore line.size.limit
+ printfWithoutReset(Printable.pack(fmt, data:_*))
+}