diff options
| author | Schuyler Eldridge | 2020-03-11 14:32:32 -0400 |
|---|---|---|
| committer | GitHub | 2020-03-11 14:32:32 -0400 |
| commit | 026c18dd76d4e2121c7f6c582d15e4d5a3ab842b (patch) | |
| tree | 0537dff3091db3da167c0fffc3388a5966c46204 /src/test | |
| parent | 646c91e71b8bfb1b0d0f22e81ca113147637ce71 (diff) | |
| parent | abf226471249a1cbb8de33d0c4bc8526f9aafa70 (diff) | |
Merge pull request #1123 from freechipsproject/dependency-api-2
- Use Dependency API for transform scheduling
- Add tests that old order/behavior is preserved
Or: "Now you're thinking with dependencies."
Diffstat (limited to 'src/test')
8 files changed, 544 insertions, 72 deletions
diff --git a/src/test/scala/firrtlTests/AnnotationTests.scala b/src/test/scala/firrtlTests/AnnotationTests.scala index 03e3198e..a1c6580d 100644 --- a/src/test/scala/firrtlTests/AnnotationTests.scala +++ b/src/test/scala/firrtlTests/AnnotationTests.scala @@ -627,7 +627,7 @@ class JsonAnnotationTests extends AnnotationTests with BackendCompilationUtiliti override def inputForm: CircuitForm = UnknownForm override def outputForm: CircuitForm = UnknownForm - protected def execute(state: CircuitState): CircuitState = state + def execute(state: CircuitState): CircuitState = state } "annotation order" should "should be preserved" in { diff --git a/src/test/scala/firrtlTests/CInferMDirSpec.scala b/src/test/scala/firrtlTests/CInferMDirSpec.scala index e03d1ab9..715e0cda 100644 --- a/src/test/scala/firrtlTests/CInferMDirSpec.scala +++ b/src/test/scala/firrtlTests/CInferMDirSpec.scala @@ -7,7 +7,7 @@ import firrtl.ir._ import firrtl.passes._ import firrtl.transforms._ -class CInferMDir extends LowTransformSpec { +class CInferMDirSpec extends LowTransformSpec { object CInferMDirCheckPass extends Pass { // finds the memory and check its read port def checkStmt(s: Statement): Boolean = s match { diff --git a/src/test/scala/firrtlTests/CustomTransformSpec.scala b/src/test/scala/firrtlTests/CustomTransformSpec.scala index 04cbf276..809f2b1e 100644 --- a/src/test/scala/firrtlTests/CustomTransformSpec.scala +++ b/src/test/scala/firrtlTests/CustomTransformSpec.scala @@ -6,12 +6,15 @@ import firrtl.ir.Circuit import firrtl._ import firrtl.passes.Pass import firrtl.ir._ -import firrtl.stage.{FirrtlSourceAnnotation, FirrtlStage, RunFirrtlTransformAnnotation} +import firrtl.stage.{FirrtlSourceAnnotation, FirrtlStage, Forms, RunFirrtlTransformAnnotation} +import firrtl.options.Dependency +import firrtl.transforms.IdentityTransform -class CustomTransformSpec extends FirrtlFlatSpec { - behavior of "Custom Transforms" +import scala.reflect.runtime - they should "be able to introduce high firrtl" in { +object CustomTransformSpec { + + class ReplaceExtModuleTransform extends SeqTransform with FirrtlMatchers { // Simple module val delayModuleString = """ |circuit Delay : @@ -31,38 +34,99 @@ class CustomTransformSpec extends FirrtlFlatSpec { val delayModuleCircuit = parse(delayModuleString) val delayModule = delayModuleCircuit.modules.find(_.name == delayModuleCircuit.main).get - class ReplaceExtModuleTransform extends SeqTransform { - class ReplaceExtModule extends Pass { - def run(c: Circuit): Circuit = c.copy( - modules = c.modules map { - case ExtModule(_, "Delay", _, _, _) => delayModule - case other => other - } - ) - } - def transforms = Seq(new ReplaceExtModule) - def inputForm = LowForm - def outputForm = HighForm + class ReplaceExtModule extends Pass { + def run(c: Circuit): Circuit = c.copy( + modules = c.modules map { + case ExtModule(_, "Delay", _, _, _) => delayModule + case other => other + } + ) } - - runFirrtlTest("CustomTransform", "/features", customTransforms = List(new ReplaceExtModuleTransform)) + def transforms = Seq(new ReplaceExtModule) + def inputForm = LowForm + def outputForm = HighForm } - they should "not cause \"Internal Errors\"" in { - val input = """ + val input = """ |circuit test : | module test : | output out : UInt | out <= UInt(123)""".stripMargin - val errorString = "My Custom Transform failed!" - class ErroringTransform extends Transform { + val errorString = "My Custom Transform failed!" + class ErroringTransform extends Transform { + def inputForm = HighForm + def outputForm = HighForm + def execute(state: CircuitState): CircuitState = { + require(false, errorString) + state + } + } + + object MutableState { + var count: Int = 0 + } + + class FirstTransform extends Transform { + def inputForm = HighForm + def outputForm = HighForm + + def execute(state: CircuitState): CircuitState = { + require(MutableState.count == 0, s"Count was ${MutableState.count}, expected 0") + MutableState.count = 1 + state + } + } + + class SecondTransform extends Transform { + def inputForm = HighForm + def outputForm = HighForm + + def execute(state: CircuitState): CircuitState = { + require(MutableState.count == 1, s"Count was ${MutableState.count}, expected 1") + MutableState.count = 2 + state + } + } + + class ThirdTransform extends Transform { + def inputForm = HighForm + def outputForm = HighForm + + def execute(state: CircuitState): CircuitState = { + require(MutableState.count == 2, s"Count was ${MutableState.count}, expected 2") + MutableState.count = 3 + state + } + } + + class IdentityLowForm extends IdentityTransform(LowForm) { + override val name = ">>>>> IdentityLowForm <<<<<" + } + + object Foo { + class A extends Transform { def inputForm = HighForm def outputForm = HighForm - def execute(state: CircuitState): CircuitState = { - require(false, errorString) - state + def execute(s: CircuitState) = { + assert(name.endsWith("A")) + s } } + } + +} + +class CustomTransformSpec extends FirrtlFlatSpec { + + import CustomTransformSpec._ + + behavior of "Custom Transforms" + + they should "be able to introduce high firrtl" in { + runFirrtlTest("CustomTransform", "/features", customTransforms = List(new ReplaceExtModuleTransform)) + } + + they should "not cause \"Internal Errors\"" in { val optionsManager = new ExecutionOptionsManager("test") with HasFirrtlOptions { firrtlOptions = FirrtlExecutionOptions( firrtlSource = Some(input), @@ -73,15 +137,38 @@ class CustomTransformSpec extends FirrtlFlatSpec { }).getMessage should include (errorString) } - object Foo { - class A extends Transform { - def inputForm = HighForm - def outputForm = HighForm - def execute(s: CircuitState) = { - assert(name.endsWith("A")) - s - } + they should "preserve the input order" in { + runFirrtlTest("CustomTransform", "/features", customTransforms = List( + new FirstTransform, + new SecondTransform, + new ThirdTransform, + new ReplaceExtModuleTransform + )) + } + + they should "run right before the emitter when inputForm=LowForm" in { + + val custom = Dependency[IdentityLowForm] + + def testOrder(emitter: Dependency[Emitter], preceders: Seq[Dependency[Transform]]): Unit = { + info(s"""${preceders.map(_.getSimpleName).mkString(" -> ")} -> ${custom.getSimpleName} -> ${emitter.getSimpleName} ok!""") + + val compiler = new firrtl.stage.transforms.Compiler(Seq(custom, emitter)) + info("Transform Order: \n" + compiler.prettyPrint(" ")) + + val expectedSlice = preceders ++ Seq(custom, emitter) + + compiler + .flattenedTransformOrder + .map(Dependency.fromTransform(_)) + .containsSlice(expectedSlice) should be (true) } + + Seq( (Dependency[LowFirrtlEmitter], Seq(Forms.LowForm.last) ), + (Dependency[MinimumVerilogEmitter], Seq(Forms.LowFormMinimumOptimized.last) ), + (Dependency[VerilogEmitter], Seq(Forms.LowFormOptimized.last) ), + (Dependency[SystemVerilogEmitter], Seq(Forms.LowFormOptimized.last) ) + ).foreach((testOrder _).tupled) } they should "work if placed inside an object" in { diff --git a/src/test/scala/firrtlTests/LoweringCompilersSpec.scala b/src/test/scala/firrtlTests/LoweringCompilersSpec.scala new file mode 100644 index 00000000..f3183599 --- /dev/null +++ b/src/test/scala/firrtlTests/LoweringCompilersSpec.scala @@ -0,0 +1,349 @@ +// See LICENSE for license details. + +package firrtlTests + +import org.scalatest.{FlatSpec, Matchers} + +import firrtl._ +import firrtl.passes +import firrtl.options.Dependency +import firrtl.stage.{Forms, TransformManager} +import firrtl.transforms.IdentityTransform + +sealed trait PatchAction { val line: Int } + +case class Add(line: Int, transforms: Seq[Dependency[Transform]]) extends PatchAction +case class Del(line: Int) extends PatchAction + +object Transforms { + class IdentityTransformDiff(val inputForm: CircuitForm, val outputForm: CircuitForm) extends Transform { + override def execute(state: CircuitState): CircuitState = state + override def name: String = s">>>>> $inputForm -> $outputForm <<<<<" + } + import firrtl.{ChirrtlForm => C, HighForm => H, MidForm => M, LowForm => L, UnknownForm => U} + class ChirrtlToChirrtl extends IdentityTransformDiff(C, C) + class HighToChirrtl extends IdentityTransformDiff(H, C) + class HighToHigh extends IdentityTransformDiff(H, H) + class MidToMid extends IdentityTransformDiff(M, M) + class MidToChirrtl extends IdentityTransformDiff(M, C) + class MidToHigh extends IdentityTransformDiff(M, H) + class LowToChirrtl extends IdentityTransformDiff(L, C) + class LowToHigh extends IdentityTransformDiff(L, H) + class LowToMid extends IdentityTransformDiff(L, M) + class LowToLow extends IdentityTransformDiff(L, L) +} + +class LoweringCompilersSpec extends FlatSpec with Matchers { + + def legacyTransforms(a: CoreTransform): Seq[Transform] = a match { + case _: ChirrtlToHighFirrtl => Seq( + passes.CheckChirrtl, + passes.CInferTypes, + passes.CInferMDir, + passes.RemoveCHIRRTL) + case _: IRToWorkingIR => Seq(passes.ToWorkingIR) + case _: ResolveAndCheck => Seq( + passes.CheckHighForm, + passes.ResolveKinds, + passes.InferTypes, + passes.CheckTypes, + passes.Uniquify, + passes.ResolveKinds, + passes.InferTypes, + passes.ResolveFlows, + passes.CheckFlows, + new passes.InferBinaryPoints, + new passes.TrimIntervals, + new passes.InferWidths, + passes.CheckWidths, + new firrtl.transforms.InferResets) + case _: HighFirrtlToMiddleFirrtl => Seq( + passes.PullMuxes, + passes.ReplaceAccesses, + passes.ExpandConnects, + passes.RemoveAccesses, + passes.Uniquify, + passes.ExpandWhens, + passes.CheckInitialization, + passes.ResolveKinds, + passes.InferTypes, + passes.CheckTypes, + passes.ResolveFlows, + new passes.InferWidths, + passes.CheckWidths, + new passes.RemoveIntervals, + passes.ConvertFixedToSInt, + passes.ZeroWidth, + passes.InferTypes) + case _: MiddleFirrtlToLowFirrtl => Seq( + passes.LowerTypes, + passes.ResolveKinds, + passes.InferTypes, + passes.ResolveFlows, + new passes.InferWidths, + passes.Legalize, + firrtl.transforms.RemoveReset, + passes.ResolveFlows, + new firrtl.transforms.CheckCombLoops, + new checks.CheckResets, + new firrtl.transforms.RemoveWires) + case _: LowFirrtlOptimization => Seq( + passes.RemoveValidIf, + new firrtl.transforms.ConstantPropagation, + passes.PadWidths, + new firrtl.transforms.ConstantPropagation, + passes.Legalize, + passes.memlib.VerilogMemDelays, // TODO move to Verilog emitter + new firrtl.transforms.ConstantPropagation, + passes.SplitExpressions, + new firrtl.transforms.CombineCats, + passes.CommonSubexpressionElimination, + new firrtl.transforms.DeadCodeElimination) + case _: MinimumLowFirrtlOptimization => Seq( + passes.RemoveValidIf, + passes.Legalize, + passes.memlib.VerilogMemDelays, // TODO move to Verilog emitter + passes.SplitExpressions) + } + + def compare(a: Seq[Transform], b: TransformManager, patches: Seq[PatchAction] = Seq.empty): Unit = { + info(s"""Transform Order:\n${b.prettyPrint(" ")}""") + + val m = new scala.collection.mutable.HashMap[Int, Seq[Dependency[Transform]]].withDefault(_ => Seq.empty) + a.map(Dependency.fromTransform).zipWithIndex.foreach{ case (t, idx) => m(idx) = Seq(t) } + + patches.foreach { + case Add(line, txs) => m(line - 1) = m(line - 1) ++ txs + case Del(line) => m.remove(line - 1) + } + + val patched = scala.collection.immutable.TreeMap(m.toArray:_*).values.flatten + + patched + .zip(b.flattenedTransformOrder.map(Dependency.fromTransform)) + .foreach{ case (aa, bb) => bb should be (aa) } + + info(s"found ${b.flattenedTransformOrder.size} transforms") + patched.size should be (b.flattenedTransformOrder.size) + } + + behavior of "ChirrtlToHighFirrtl" + + it should "replicate the old order" in { + val tm = new TransformManager(Forms.MinimalHighForm, Forms.ChirrtlForm) + compare(legacyTransforms(new firrtl.ChirrtlToHighFirrtl), tm) + } + + behavior of "IRToWorkingIR" + + it should "replicate the old order" in { + val tm = new TransformManager(Forms.WorkingIR, Forms.MinimalHighForm) + compare(legacyTransforms(new firrtl.IRToWorkingIR), tm) + } + + behavior of "ResolveAndCheck" + + it should "replicate the old order" in { + val tm = new TransformManager(Forms.Resolved, Forms.WorkingIR) + val patches = Seq( + Add(14, Seq(Dependency.fromTransform(firrtl.passes.CheckTypes))) + ) + compare(legacyTransforms(new ResolveAndCheck), tm, patches) + } + + behavior of "HighFirrtlToMiddleFirrtl" + + it should "replicate the old order" in { + val tm = new TransformManager(Forms.MidForm, Forms.Deduped) + val patches = Seq( + Add(5, Seq(Dependency(firrtl.passes.ResolveKinds), + Dependency(firrtl.passes.InferTypes))), + Del(6), + Del(7), + Add(6, Seq(Dependency[firrtl.passes.ExpandWhensAndCheck])), + Del(10), + Del(11), + Del(12), + Add(11, Seq(Dependency(firrtl.passes.ResolveFlows), + Dependency[firrtl.passes.InferWidths])), + Del(13) + ) + compare(legacyTransforms(new HighFirrtlToMiddleFirrtl), tm, patches) + } + + behavior of "MiddleFirrtlToLowFirrtl" + + it should "replicate the old order" in { + val tm = new TransformManager(Forms.LowForm, Forms.MidForm) + compare(legacyTransforms(new MiddleFirrtlToLowFirrtl), tm) + } + + behavior of "MinimumLowFirrtlOptimization" + + it should "replicate the old order" in { + val tm = new TransformManager(Forms.LowFormMinimumOptimized, Forms.LowForm) + compare(legacyTransforms(new MinimumLowFirrtlOptimization), tm) + } + + behavior of "LowFirrtlOptimization" + + it should "replicate the old order" in { + val tm = new TransformManager(Forms.LowFormOptimized, Forms.LowForm) + val patches = Seq( + Add(7, Seq(Dependency(firrtl.passes.Legalize))) + ) + compare(legacyTransforms(new LowFirrtlOptimization), tm, patches) + } + + behavior of "VerilogMinimumOptimized" + + it should "replicate the old order" in { + val legacy = Seq( + new firrtl.transforms.BlackBoxSourceHelper, + new firrtl.transforms.FixAddingNegativeLiterals, + new firrtl.transforms.ReplaceTruncatingArithmetic, + new firrtl.transforms.InlineBitExtractionsTransform, + new firrtl.transforms.InlineCastsTransform, + new firrtl.transforms.LegalizeClocksTransform, + new firrtl.transforms.FlattenRegUpdate, + firrtl.passes.VerilogModulusCleanup, + new firrtl.transforms.VerilogRename, + firrtl.passes.VerilogPrep, + new firrtl.AddDescriptionNodes) + val tm = new TransformManager(Forms.VerilogMinimumOptimized, (new firrtl.VerilogEmitter).prerequisites) + compare(legacy, tm) + } + + behavior of "VerilogOptimized" + + it should "replicate the old order" in { + val legacy = Seq( + new firrtl.transforms.BlackBoxSourceHelper, + new firrtl.transforms.FixAddingNegativeLiterals, + new firrtl.transforms.ReplaceTruncatingArithmetic, + new firrtl.transforms.InlineBitExtractionsTransform, + new firrtl.transforms.InlineCastsTransform, + new firrtl.transforms.LegalizeClocksTransform, + new firrtl.transforms.FlattenRegUpdate, + new firrtl.transforms.DeadCodeElimination, + firrtl.passes.VerilogModulusCleanup, + new firrtl.transforms.VerilogRename, + firrtl.passes.VerilogPrep, + new firrtl.AddDescriptionNodes) + val tm = new TransformManager(Forms.VerilogOptimized, Forms.LowFormOptimized) + compare(legacy, tm) + } + + behavior of "Legacy Custom Transforms" + + it should "work for Chirrtl -> Chirrtl" in { + val expected = new Transforms.ChirrtlToChirrtl :: new firrtl.ChirrtlEmitter :: Nil + val tm = new TransformManager(Dependency[firrtl.ChirrtlEmitter] :: Dependency[Transforms.ChirrtlToChirrtl] :: Nil) + compare(expected, tm) + } + + it should "work for High -> High" in { + val expected = + new TransformManager(Forms.HighForm).flattenedTransformOrder ++ + Some(new Transforms.HighToHigh) ++ + (new TransformManager(Forms.MidForm, Forms.HighForm).flattenedTransformOrder) + val tm = new TransformManager(Forms.MidForm :+ Dependency[Transforms.HighToHigh]) + compare(expected, tm) + } + + it should "work for High -> Chirrtl" in { + val expected = + new TransformManager(Forms.HighForm).flattenedTransformOrder ++ + Some(new Transforms.HighToChirrtl) ++ + (new TransformManager(Forms.HighForm, Forms.ChirrtlForm).flattenedTransformOrder) + val tm = new TransformManager(Forms.HighForm :+ Dependency[Transforms.HighToChirrtl]) + compare(expected, tm) + } + + it should "work for Mid -> Mid" in { + val expected = + new TransformManager(Forms.MidForm).flattenedTransformOrder ++ + Some(new Transforms.MidToMid) ++ + (new TransformManager(Forms.LowForm, Forms.MidForm).flattenedTransformOrder) + val tm = new TransformManager(Forms.LowForm :+ Dependency[Transforms.MidToMid]) + compare(expected, tm) + } + + it should "work for Mid -> High" in { + val expected = + new TransformManager(Forms.MidForm).flattenedTransformOrder ++ + Some(new Transforms.MidToHigh) ++ + (new TransformManager(Forms.LowForm, Forms.MinimalHighForm).flattenedTransformOrder) + val tm = new TransformManager(Forms.LowForm :+ Dependency[Transforms.MidToHigh]) + compare(expected, tm) + } + + it should "work for Mid -> Chirrtl" in { + val expected = + new TransformManager(Forms.MidForm).flattenedTransformOrder ++ + Some(new Transforms.MidToChirrtl) ++ + (new TransformManager(Forms.LowForm, Forms.ChirrtlForm).flattenedTransformOrder) + val tm = new TransformManager(Forms.LowForm :+ Dependency[Transforms.MidToChirrtl]) + compare(expected, tm) + } + + it should "work for Low -> Low" in { + val expected = + new TransformManager(Forms.LowFormOptimized).flattenedTransformOrder ++ + Seq(new Transforms.LowToLow) + val tm = new TransformManager(Forms.LowFormOptimized :+ Dependency[Transforms.LowToLow]) + compare(expected, tm) + } + + it should "work for Low -> Mid" in { + val expected = + new TransformManager(Forms.LowFormOptimized).flattenedTransformOrder ++ + Seq(new Transforms.LowToMid) ++ + (new TransformManager(Forms.LowFormOptimized, Forms.MidForm).flattenedTransformOrder) + val tm = new TransformManager(Forms.LowFormOptimized :+ Dependency[Transforms.LowToMid]) + compare(expected, tm) + } + + it should "work for Low -> High" in { + val expected = + new TransformManager(Forms.LowFormOptimized).flattenedTransformOrder ++ + Seq(new Transforms.LowToHigh) ++ + (new TransformManager(Forms.LowFormOptimized, Forms.MinimalHighForm).flattenedTransformOrder) + val tm = new TransformManager(Forms.LowFormOptimized :+ Dependency[Transforms.LowToHigh]) + compare(expected, tm) + } + + it should "work for Low -> Chirrtl" in { + val expected = + new TransformManager(Forms.LowFormOptimized).flattenedTransformOrder ++ + Seq(new Transforms.LowToChirrtl) ++ + (new TransformManager(Forms.LowFormOptimized, Forms.ChirrtlForm).flattenedTransformOrder) + val tm = new TransformManager(Forms.LowFormOptimized :+ Dependency[Transforms.LowToChirrtl]) + compare(expected, tm) + } + + it should "schedule inputForm=LowForm after MiddleFirrtlToLowFirrtl for the LowFirrtlEmitter" in { + val expected = + new TransformManager(Forms.LowForm).flattenedTransformOrder ++ + Seq(new Transforms.LowToLow, new firrtl.LowFirrtlEmitter) + val tm = (new TransformManager(Seq(Dependency[firrtl.LowFirrtlEmitter], Dependency[Transforms.LowToLow]))) + compare(expected, tm) + } + + it should "schedule inputForm=LowForm after MinimumLowFirrtlOptimizations for the MinimalVerilogEmitter" in { + val expected = + new TransformManager(Forms.LowFormMinimumOptimized).flattenedTransformOrder ++ + Seq(new Transforms.LowToLow, new firrtl.MinimumVerilogEmitter) + val tm = (new TransformManager(Seq(Dependency[firrtl.MinimumVerilogEmitter], Dependency[Transforms.LowToLow]))) + compare(expected, tm) + } + + it should "schedule inputForm=LowForm after LowFirrtlOptimizations for the VerilogEmitter" in { + val expected = + new TransformManager(Forms.LowFormOptimized).flattenedTransformOrder ++ + Seq(new Transforms.LowToLow, new firrtl.VerilogEmitter) + val tm = (new TransformManager(Seq(Dependency[firrtl.VerilogEmitter], Dependency[Transforms.LowToLow]))) + compare(expected, tm) + } + +} diff --git a/src/test/scala/firrtlTests/VerilogEmitterTests.scala b/src/test/scala/firrtlTests/VerilogEmitterTests.scala index c5d0eacc..825d706f 100644 --- a/src/test/scala/firrtlTests/VerilogEmitterTests.scala +++ b/src/test/scala/firrtlTests/VerilogEmitterTests.scala @@ -13,12 +13,12 @@ class DoPrimVerilog extends FirrtlFlatSpec { "Xorr" should "emit correctly" in { val compiler = new VerilogCompiler val input = - """circuit Xorr : - | module Xorr : + """circuit Xorr : + | module Xorr : | input a: UInt<4> | output b: UInt<1> | b <= xorr(a)""".stripMargin - val check = + val check = """module Xorr( | input [3:0] a, | output b @@ -31,12 +31,12 @@ class DoPrimVerilog extends FirrtlFlatSpec { "Andr" should "emit correctly" in { val compiler = new VerilogCompiler val input = - """circuit Andr : - | module Andr : + """circuit Andr : + | module Andr : | input a: UInt<4> | output b: UInt<1> | b <= andr(a)""".stripMargin - val check = + val check = """module Andr( | input [3:0] a, | output b @@ -49,12 +49,12 @@ class DoPrimVerilog extends FirrtlFlatSpec { "Orr" should "emit correctly" in { val compiler = new VerilogCompiler val input = - """circuit Orr : - | module Orr : + """circuit Orr : + | module Orr : | input a: UInt<4> | output b: UInt<1> | b <= orr(a)""".stripMargin - val check = + val check = """module Orr( | input [3:0] a, | output b @@ -187,8 +187,8 @@ class DoPrimVerilog extends FirrtlFlatSpec { |""".stripMargin val check = """module Test( - | input [7:0] in, - | output out + | input [7:0] in, + | output out |); | wire [7:0] _GEN_0; | assign out = _GEN_0[0]; diff --git a/src/test/scala/firrtlTests/annotationTests/TargetDirAnnotationSpec.scala b/src/test/scala/firrtlTests/annotationTests/TargetDirAnnotationSpec.scala index eb061d8f..ea4127bc 100644 --- a/src/test/scala/firrtlTests/annotationTests/TargetDirAnnotationSpec.scala +++ b/src/test/scala/firrtlTests/annotationTests/TargetDirAnnotationSpec.scala @@ -5,24 +5,25 @@ package annotationTests import firrtlTests._ import firrtl._ +import firrtl.annotations.{Annotation, NoTargetAnnotation} + +case object FoundTargetDirTransformRanAnnotation extends NoTargetAnnotation +case object FoundTargetDirTransformFoundTargetDirAnnotation extends NoTargetAnnotation /** Looks for [[TargetDirAnnotation]] */ -class FindTargetDirTransform(expected: String) extends Transform { +class FindTargetDirTransform extends Transform { def inputForm = HighForm def outputForm = HighForm - var foundTargetDir = false - var run = false + def execute(state: CircuitState): CircuitState = { - run = true - state.annotations.collectFirst { - case TargetDirAnnotation(expected) => - foundTargetDir = true - } - state + val a: Option[Annotation] = state.annotations.collectFirst { + case TargetDirAnnotation("a/b/c") => FoundTargetDirTransformFoundTargetDirAnnotation } + state.copy(annotations = state.annotations ++ a ++ Some(FoundTargetDirTransformRanAnnotation)) } } class TargetDirAnnotationSpec extends FirrtlFlatSpec { + behavior of "The target directory" val input = @@ -35,7 +36,7 @@ class TargetDirAnnotationSpec extends FirrtlFlatSpec { val targetDir = "a/b/c" it should "be available as an annotation when using execution options" in { - val findTargetDir = new FindTargetDirTransform(targetDir) // looks for the annotation + val findTargetDir = new FindTargetDirTransform // looks for the annotation val optionsManager = new ExecutionOptionsManager("TargetDir") with HasFirrtlOptions { commonOptions = commonOptions.copy(targetDirName = targetDir, @@ -44,11 +45,13 @@ class TargetDirAnnotationSpec extends FirrtlFlatSpec { firrtlSource = Some(input), customTransforms = Seq(findTargetDir)) } - Driver.execute(optionsManager) + val annotations: Seq[Annotation] = Driver.execute(optionsManager) match { + case a: FirrtlExecutionSuccess => a.circuitState.annotations + case _ => fail + } - // Check that FindTargetDirTransform transform is run and finds the annotation - findTargetDir.run should be (true) - findTargetDir.foundTargetDir should be (true) + annotations should contain (FoundTargetDirTransformRanAnnotation) + annotations should contain (FoundTargetDirTransformFoundTargetDirAnnotation) // Delete created directory val dir = new java.io.File(targetDir) @@ -57,13 +60,16 @@ class TargetDirAnnotationSpec extends FirrtlFlatSpec { } it should "NOT be available as an annotation when using a raw compiler" in { - val findTargetDir = new FindTargetDirTransform(targetDir) // looks for the annotation + val findTargetDir = new FindTargetDirTransform // looks for the annotation val compiler = new VerilogCompiler val circuit = Parser.parse(input split "\n") - compiler.compileAndEmit(CircuitState(circuit, HighForm), Seq(findTargetDir)) + + val annotations: Seq[Annotation] = compiler + .compileAndEmit(CircuitState(circuit, HighForm), Seq(findTargetDir)) + .annotations // Check that FindTargetDirTransform does not find the annotation - findTargetDir.run should be (true) - findTargetDir.foundTargetDir should be (false) + annotations should contain (FoundTargetDirTransformRanAnnotation) + annotations should not contain (FoundTargetDirTransformFoundTargetDirAnnotation) } } diff --git a/src/test/scala/firrtlTests/stage/phases/CompilerSpec.scala b/src/test/scala/firrtlTests/stage/phases/CompilerSpec.scala index a8176316..f2620051 100644 --- a/src/test/scala/firrtlTests/stage/phases/CompilerSpec.scala +++ b/src/test/scala/firrtlTests/stage/phases/CompilerSpec.scala @@ -4,9 +4,11 @@ package firrtlTests.stage.phases import org.scalatest.{FlatSpec, Matchers} +import scala.collection.mutable + import firrtl.{Compiler => _, _} -import firrtl.options.Phase -import firrtl.stage.{CompilerAnnotation, FirrtlCircuitAnnotation, RunFirrtlTransformAnnotation} +import firrtl.options.{Phase, PreservesAll} +import firrtl.stage.{CompilerAnnotation, FirrtlCircuitAnnotation, Forms, RunFirrtlTransformAnnotation} import firrtl.stage.phases.Compiler class CompilerSpec extends FlatSpec with Matchers { @@ -40,7 +42,7 @@ class CompilerSpec extends FlatSpec with Matchers { val expected = Seq(FirrtlCircuitAnnotation(circuitOut)) - phase.transform(input).toSeq should be (expected) + phase.transform(input).collect{ case a: FirrtlCircuitAnnotation => a }.toSeq should be (expected) } it should "compile multiple FirrtlCircuitAnnotations" in new Fixture { @@ -140,4 +142,37 @@ class CompilerSpec extends FlatSpec with Matchers { .size should be (20) } + it should "run transforms in sequential order" in new Fixture { + import CompilerSpec.{FirstTransform, SecondTransform} + + val circuitIn = Parser.parse(chirrtl("top")) + val annotations = + Seq( FirrtlCircuitAnnotation(circuitIn), + CompilerAnnotation(new VerilogCompiler), + RunFirrtlTransformAnnotation(new FirstTransform), + RunFirrtlTransformAnnotation(new SecondTransform) ) + phase.transform(annotations) + + CompilerSpec.globalState.toSeq should be (Seq(classOf[FirstTransform], classOf[SecondTransform])) + } + +} + +object CompilerSpec { + + private[CompilerSpec] val globalState: mutable.Queue[Class[_ <: Transform]] = mutable.Queue.empty[Class[_ <: Transform]] + + class LoggingTransform extends Transform with PreservesAll[Transform] { + override def inputForm = UnknownForm + override def outputForm = UnknownForm + override def prerequisites = Forms.HighForm + def execute(c: CircuitState): CircuitState = { + globalState += this.getClass + c + } + } + + class FirstTransform extends LoggingTransform + class SecondTransform extends LoggingTransform + } diff --git a/src/test/scala/firrtlTests/transforms/BlackBoxSourceHelperSpec.scala b/src/test/scala/firrtlTests/transforms/BlackBoxSourceHelperSpec.scala index 213ead77..feba5a24 100644 --- a/src/test/scala/firrtlTests/transforms/BlackBoxSourceHelperSpec.scala +++ b/src/test/scala/firrtlTests/transforms/BlackBoxSourceHelperSpec.scala @@ -100,11 +100,6 @@ class BlacklBoxSourceHelperTransformSpec extends LowTransformSpec { new java.io.File(s"test_run_dir/${BlackBoxSourceHelper.defaultFileListName}").exists should be (true) } - "verilog compiler" should "have BlackBoxSourceHelper transform" in { - val verilogCompiler = new VerilogEmitter - verilogCompiler.transforms.map { x => x.getClass } should contain (classOf[BlackBoxSourceHelper]) - } - "verilog header files" should "be available but not mentioned in the file list" in { // Issue #917 - We don't want to list Verilog header files ("*.vh") in our file list. // We don't actually verify that the generated verilog code works, |
