aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/firrtl/DebugUtils.scala
blob: e802d93510c7933e1ce1cddbe0a0fd110fd8942c (plain)
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
// Private implicit classes and other utility functions for debugging

package firrtl

import java.io.PrintWriter
import Utils._

private object DebugUtils {

  implicit class DebugASTUtils(ast: AST) {
    // Is this actually any use?
    def preOrderTraversal(f: AST => Unit): Unit = {
      f(ast)
      ast match {
        case a: Block => a.stmts.foreach(_.preOrderTraversal(f))
        case a: Assert => a.pred.preOrderTraversal(f)
        case a: When => {
          a.pred.preOrderTraversal(f)
          a.conseq.preOrderTraversal(f)
          a.alt.preOrderTraversal(f)
        }
        case a: BulkConnect => {
          a.lhs.preOrderTraversal(f)
          a.rhs.preOrderTraversal(f)
        }
        case a: Connect => {
          a.lhs.preOrderTraversal(f)
          a.rhs.preOrderTraversal(f)
        }
        case a: OnReset => {
          a.lhs.preOrderTraversal(f)
          a.rhs.preOrderTraversal(f)
        }
        case a: DefAccessor => {
          a.dir.preOrderTraversal(f)
          a.source.preOrderTraversal(f)
          a.index.preOrderTraversal(f)
        }
        case a: DefPoison => a.tpe.preOrderTraversal(f)
        case a: DefNode => a.value.preOrderTraversal(f)
        case a: DefInst => a.module.preOrderTraversal(f)
        case a: DefMemory => {
          a.tpe.preOrderTraversal(f)
          a.clock.preOrderTraversal(f)
        }
        case a: DefReg => {
          a.tpe.preOrderTraversal(f)
          a.clock.preOrderTraversal(f)
          a.reset.preOrderTraversal(f)
        }
        case a: DefWire => a.tpe.preOrderTraversal(f)
        case a: Field => {
          a.dir.preOrderTraversal(f)
          a.tpe.preOrderTraversal(f)
        }
        case a: VectorType => a.tpe.preOrderTraversal(f)
        case a: BundleType => a.fields.foreach(_.preOrderTraversal(f))
        case a: Port => {
          a.dir.preOrderTraversal(f)
          a.tpe.preOrderTraversal(f)
        }
        case a: Module => {
          a.ports.foreach(_.preOrderTraversal(f))
          a.stmt.preOrderTraversal(f)
        }
        case a: Circuit => a.modules.foreach(_.preOrderTraversal(f)) 
        //case _ => throw new Exception(s"Unsupported FIRRTL node ${ast.getClass.getSimpleName}!")
        case _ => 
      }
    }
  }


  /** Private class for recording and organizing debug information  */
  class Logger private (
    writer: PrintWriter,
    printMode: Symbol,
    printVars: List[Symbol]){
   
    // Legal printModes: 'none, 'error, 'warn, 'info, 'debug, 'trace
    require(List('none, 'error, 'warn, 'info, 'debug, 'trace) contains printMode) 
    val errorEnable = List('error, 'warn, 'info, 'debug, 'trace) contains printMode
    val warnEnable  = List('warn, 'info, 'debug, 'trace) contains printMode
    val infoEnable  = List('info, 'debug, 'trace) contains printMode
    val debugEnable = List('debug, 'trace) contains printMode
    val traceEnable = List('trace) contains printMode
    val circuitEnable = printVars contains 'circuit
    val debugFlags = printVars.map(_ -> true).toMap.withDefaultValue(false)

    def println(message: => String){
      writer.println(message)
    }
    def error(message: => String){
      if (errorEnable) writer.println(message.split("\n").map("[error] " + _).mkString("\n"))
    }
    def warn(message: => String){
      if (warnEnable) writer.println(message.split("\n").map("[warn] " + _).mkString("\n"))
    }
    def info(message: => String){
      if (infoEnable) writer.println(message.split("\n").map("[info] " + _).mkString("\n"))
    }
    def debug(message: => String){
      if (debugEnable) writer.println(message.split("\n").map("[debug] " + _).mkString("\n"))
    }
    def trace(message: => String){
      if (traceEnable) writer.println(message.split("\n").map("[trace] " + _).mkString("\n"))
    }
    def printlnDebug(circuit: Circuit){
      if (circuitEnable) this.println(circuit.serialize(debugFlags))
    }
    // Used if not autoflushing
    def flush() = writer.flush()
    
  }
  /** Factory object for logger
    *
    * Logger records and organizes debug information
    */
  object Logger
  {
    def apply(writer: PrintWriter): Logger = 
      new Logger(writer, 'warn, List())
    def apply(writer: PrintWriter, printMode: Symbol): Logger = 
      new Logger(writer, printMode, List())
    def apply(writer: PrintWriter, printMode: Symbol, printVars: List[Symbol]): Logger = 
      new Logger(writer, printMode, printVars)
    def apply(): Logger = new Logger(null, 'none, List())
  }
}