aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAdam Izraelevitz2018-07-10 18:36:02 -0700
committerJack Koenig2018-07-10 18:36:02 -0700
commit6b02d09eb412df275d00930ab0e167b07fa61862 (patch)
treed2e9933d7cd7c13f09f9a085e9a1efb61aa48ecf /src
parenta0d23c1192712be1a5970bb70bb8f0cbafbe4e11 (diff)
Combinational Dependency Annotation (#809)
Diffstat (limited to 'src')
-rw-r--r--src/main/scala/firrtl/transforms/CheckCombLoops.scala22
-rw-r--r--src/test/scala/firrtlTests/CheckCombLoopsSpec.scala29
2 files changed, 47 insertions, 4 deletions
diff --git a/src/main/scala/firrtl/transforms/CheckCombLoops.scala b/src/main/scala/firrtl/transforms/CheckCombLoops.scala
index e1e6cf63..98033a2f 100644
--- a/src/main/scala/firrtl/transforms/CheckCombLoops.scala
+++ b/src/main/scala/firrtl/transforms/CheckCombLoops.scala
@@ -24,6 +24,14 @@ object CheckCombLoops {
case object DontCheckCombLoopsAnnotation extends NoTargetAnnotation
+case class CombinationalPath(sink: ComponentName, sources: Seq[ComponentName]) extends Annotation {
+ override def update(renames: RenameMap): Seq[Annotation] = {
+ val newSources = sources.flatMap { s => renames.get(s).getOrElse(Seq(s)) }
+ val newSinks = renames.get(sink).getOrElse(Seq(sink))
+ newSinks.map(snk => CombinationalPath(snk, newSources))
+ }
+}
+
/** Finds and detects combinational logic loops in a circuit, if any
* exist. Returns the input circuit with no modifications.
*
@@ -181,7 +189,7 @@ class CheckCombLoops extends Transform {
* and only if it combinationally depends on input Y. Associate this
* reduced graph with the module for future use.
*/
- private def run(c: Circuit): Circuit = {
+ private def run(c: Circuit): (Circuit, Seq[Annotation]) = {
val errors = new Errors()
/* TODO(magyar): deal with exmodules! No pass warnings currently
* exist. Maybe warn when iterating through modules.
@@ -211,8 +219,14 @@ class CheckCombLoops extends Transform {
errors.append(new CombLoopException(m.info, m.name, expandedCycle))
}
}
+ val mn = ModuleName(c.main, CircuitName(c.main))
+ val annos = simplifiedModuleGraphs(c.main).getEdgeMap.collect { case (from, tos) if tos.nonEmpty =>
+ val sink = ComponentName(from.name, mn)
+ val sources = tos.map(x => ComponentName(x.name, mn))
+ CombinationalPath(sink, sources.toSeq)
+ }
errors.trigger()
- c
+ (c, annos.toSeq)
}
def execute(state: CircuitState): CircuitState = {
@@ -221,8 +235,8 @@ class CheckCombLoops extends Transform {
logger.warn("Skipping Combinational Loop Detection")
state
} else {
- val result = run(state.circuit)
- CircuitState(result, outputForm, state.annotations, state.renames)
+ val (result, annos) = run(state.circuit)
+ CircuitState(result, outputForm, state.annotations ++ annos, state.renames)
}
}
}
diff --git a/src/test/scala/firrtlTests/CheckCombLoopsSpec.scala b/src/test/scala/firrtlTests/CheckCombLoopsSpec.scala
index d09b4d06..ed498180 100644
--- a/src/test/scala/firrtlTests/CheckCombLoopsSpec.scala
+++ b/src/test/scala/firrtlTests/CheckCombLoopsSpec.scala
@@ -189,6 +189,35 @@ class CheckCombLoopsSpec extends SimpleTransformSpec {
compile(CircuitState(parse(input), ChirrtlForm), writer)
}
}
+
+ "Circuit" should "create an annotation" in {
+ val input = """circuit hasnoloops :
+ | module thru :
+ | input in1 : UInt<1>
+ | input in2 : UInt<1>
+ | output out1 : UInt<1>
+ | output out2 : UInt<1>
+ | out1 <= in1
+ | out2 <= in2
+ | module hasnoloops :
+ | input clk : Clock
+ | input a : UInt<1>
+ | output b : UInt<1>
+ | wire x : UInt<1>
+ | inst inner of thru
+ | inner.in1 <= a
+ | x <= inner.out1
+ | inner.in2 <= x
+ | b <= inner.out2
+ |""".stripMargin
+
+ val writer = new java.io.StringWriter
+ val cs = compile(CircuitState(parse(input), ChirrtlForm), writer)
+ val mn = ModuleName("hasnoloops", CircuitName("hasnoloops"))
+ cs.annotations.collect {
+ case c @ CombinationalPath(ComponentName("b", `mn`), Seq(ComponentName("a", `mn`))) => c
+ }.nonEmpty should be (true)
+ }
}
class CheckCombLoopsCommandLineSpec extends FirrtlFlatSpec {