1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
|
// See LICENSE for license details.
package chisel3.internal
import scala.collection.mutable.ArrayBuffer
import chisel3.core._
class ChiselException(message: String, cause: Throwable) extends Exception(message, cause)
private[chisel3] object throwException {
def apply(s: String, t: Throwable = null): Nothing =
throw new ChiselException(s, t)
}
/** Records and reports runtime errors and warnings. */
private[chisel3] class ErrorLog {
def hasErrors: Boolean = errors.exists(_.isFatal)
/** Log an error message */
def error(m: => String): Unit =
errors += new Error(m, getUserLineNumber)
/** Log a warning message */
def warning(m: => String): Unit =
errors += new Warning(m, getUserLineNumber)
/** Log a deprecation warning message */
def deprecated(m: => String): Unit =
errors += new DeprecationWarning(m, getUserLineNumber)
/** Emit an informational message */
def info(m: String): Unit =
println(new Info("[%2.3f] %s".format(elapsedTime/1e3, m), None)) // scalastyle:ignore regex
/** Prints error messages generated by Chisel at runtime. */
def report(): Unit = errors foreach println // scalastyle:ignore regex
/** Throw an exception if any errors have yet occurred. */
def checkpoint(): Unit = if(hasErrors) {
import Console._
throwException(errors.map(_ + "\n").reduce(_ + _) +
UNDERLINED + "CODE HAS " + errors.filter(_.isFatal).length + RESET +
UNDERLINED + " " + RED + "ERRORS" + RESET +
UNDERLINED + " and " + errors.filterNot(_.isFatal).length + RESET +
UNDERLINED + " " + YELLOW + "WARNINGS" + RESET)
}
private def findFirstUserFrame(stack: Array[StackTraceElement]): Option[StackTraceElement] = {
def isUserCode(ste: StackTraceElement): Boolean = {
def isUserModule(c: Class[_]): Boolean =
c != null && (c == classOf[Module] || isUserModule(c.getSuperclass))
isUserModule(Class.forName(ste.getClassName))
}
stack.indexWhere(isUserCode) match {
case x if x < 0 => None
case x => Some(stack(x))
}
}
private def getUserLineNumber =
findFirstUserFrame(Thread.currentThread().getStackTrace)
private val errors = ArrayBuffer[LogEntry]()
private val startTime = System.currentTimeMillis
private def elapsedTime: Long = System.currentTimeMillis - startTime
}
private abstract class LogEntry(msg: => String, line: Option[StackTraceElement]) {
def isFatal: Boolean = false
def format: String
override def toString: String = line match {
case Some(l) => s"${format} ${l.getFileName}:${l.getLineNumber}: ${msg} in class ${l.getClassName}"
case None => s"${format} ${msg}"
}
protected def tag(name: String, color: String): String =
s"[${color}${name}${Console.RESET}]"
}
private class Error(msg: => String, line: Option[StackTraceElement]) extends LogEntry(msg, line) {
override def isFatal: Boolean = true
def format: String = tag("error", Console.RED)
}
private class Warning(msg: => String, line: Option[StackTraceElement]) extends LogEntry(msg, line) {
def format: String = tag("warn", Console.YELLOW)
}
private class DeprecationWarning(msg: => String, line: Option[StackTraceElement]) extends LogEntry(msg, line) {
def format: String = tag("warn", Console.CYAN)
}
private class Info(msg: => String, line: Option[StackTraceElement]) extends LogEntry(msg, line) {
def format: String = tag("info", Console.MAGENTA)
}
|