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
|
// SPDX-License-Identifier: Apache-2.0
package firrtl.passes
package clocklist
import firrtl._
import firrtl.ir._
import annotations._
import java.io.{CharArrayWriter, Writer}
import wiring.WiringUtils.{getChildrenMap, getLineage}
import ClockListUtils._
import Utils._
import memlib.AnalysisUtils._
/** Starting with a top module, determine the clock origins of each child instance.
* Write the result to writer.
*/
class ClockList(top: String, writer: Writer) extends Pass {
def run(c: Circuit): Circuit = {
// Build useful datastructures
val childrenMap = getChildrenMap(c)
val moduleMap = c.modules.foldLeft(Map[String, DefModule]())((map, m) => map + (m.name -> m))
val lineages = getLineage(childrenMap, top)
val outputBuffer = new CharArrayWriter
// === Checks ===
// TODO(izraelevitz): Check all registers/memories use "clock" clock port
// ==============
// Clock sources must be blackbox outputs and top's clock
val partialSourceList = getSourceList(moduleMap)(lineages)
val sourceList = partialSourceList ++ moduleMap(top).ports.collect { case Port(i, n, Input, ClockType) => n }
writer.append(s"Sourcelist: $sourceList \n")
// Remove everything from the circuit, unless it has a clock type
// This simplifies the circuit drastically so InlineInstances doesn't take forever.
val onlyClockCircuit = RemoveAllButClocks.run(c)
// Inline the clock-only circuit up to the specified top module
val modulesToInline =
(c.modules.collect { case Module(_, n, _, _) if n != top => ModuleName(n, CircuitName(c.main)) }).toSet
val inlineTransform = new InlineInstances { override val inlineDelim = "$" }
val inlinedCircuit = inlineTransform.run(onlyClockCircuit, modulesToInline, Set(), Seq()).circuit
val topModule = inlinedCircuit.modules.find(_.name == top).getOrElse(throwInternalError("no top module"))
// Build a hashmap of connections to use for getOrigins
val connects = getConnects(topModule)
// Return a map from instance name to clock origin
val origins = getOrigins(connects, "", moduleMap)(lineages)
// If the clock origin is contained in the source list, label good (otherwise bad)
origins.foreach {
case (instance, origin) =>
val sep = if (instance == "") "" else "."
if (!sourceList.contains(origin.replace('.', '$'))) {
outputBuffer.append(s"Bad Origin of $instance${sep}clock is $origin\n")
} else {
outputBuffer.append(s"Good Origin of $instance${sep}clock is $origin\n")
}
}
// Write to output file
writer.write(outputBuffer.toString)
// Return unchanged circuit
c
}
}
|