diff --git a/build.sbt b/build.sbt index f18110c7..d254ca24 100644 --- a/build.sbt +++ b/build.sbt @@ -1,21 +1,22 @@ // See LICENSE for license details. -import Dependencies._ - val defaultVersions = Map( - "chisel3" -> "3.1-SNAPSHOT", - "chisel-iotesters" -> "1.2-SNAPSHOT" + "chisel3" -> "3.2-SNAPSHOT", + "chisel-iotesters" -> "1.3-SNAPSHOT" ) lazy val commonSettings = Seq( organization := "edu.berkeley.cs", version := "0.1-SNAPSHOT", - scalaVersion := "2.11.8", - scalacOptions := Seq("-deprecation", "-feature", "-language:reflectiveCalls"), - libraryDependencies ++= commonDependencies, + scalaVersion := "2.12.8", + scalacOptions := Seq("-deprecation", "-feature", "-language:reflectiveCalls", "-Xsource:2.11"), libraryDependencies ++= Seq("chisel3","chisel-iotesters").map { dep: String => "edu.berkeley.cs" %% dep % sys.props.getOrElse(dep + "Version", defaultVersions(dep)) }, + libraryDependencies in Test ++= Seq( + "org.scalatest" %% "scalatest" % "2.2.5" % "test", + "org.scalacheck" %% "scalacheck" % "1.12.4" % "test" + ), resolvers ++= Seq( Resolver.sonatypeRepo("snapshots"), Resolver.sonatypeRepo("releases") @@ -30,7 +31,7 @@ lazy val macros = (project in file("macros")) .settings(commonSettings) .settings(Seq( libraryDependencies ++= Seq( - "edu.berkeley.cs" %% "firrtl-interpreter" % "0.1-SNAPSHOT" % Test + "edu.berkeley.cs" %% "firrtl-interpreter" % "1.2-SNAPSHOT" % Test ), mainClass := Some("barstools.macros.MacroCompiler") )) diff --git a/macros/src/main/scala/MacroCompiler.scala b/macros/src/main/scala/MacroCompiler.scala index 62bf518f..410372dd 100644 --- a/macros/src/main/scala/MacroCompiler.scala +++ b/macros/src/main/scala/MacroCompiler.scala @@ -752,7 +752,7 @@ object MacroCompiler extends App { // Note: the last macro in the input list is (seemingly arbitrarily) // determined as the firrtl "top-level module". val circuit = Circuit(NoInfo, macros, macros.last.name) - val annotations = AnnotationMap( + val annotations = AnnotationSeq( Seq(MacroCompilerAnnotation( circuit.main, MacroCompilerAnnotation.Params( @@ -764,7 +764,7 @@ object MacroCompiler extends App { ) )) ) - val state = CircuitState(circuit, HighForm, Some(annotations)) + val state = CircuitState(circuit, HighForm, annotations) // Run the compiler. val result = new MacroCompiler().compileAndEmit(state) diff --git a/project/Dependencies.scala b/project/Dependencies.scala deleted file mode 100644 index 5c327ec4..00000000 --- a/project/Dependencies.scala +++ /dev/null @@ -1,22 +0,0 @@ -import sbt._ -import Keys._ - -object Dependencies { - val scalatestVersion = "2.2.5" - val scalatest = "org.scalatest" %% "scalatest" % scalatestVersion % "test" - val scalacheckVersion = "1.12.4" - val scalacheck = "org.scalacheck" %% "scalacheck" % scalacheckVersion % "test" - - // Templating! - val handlebarsVersion = "2.1.1" - val handlebars = "com.gilt" %% "handlebars-scala" % handlebarsVersion exclude("org.slf4j", "slf4j-simple") - // org.slf4j.slf4j-simple's StaticLoggerBinder (from handlebars) conflicts with - // ch.qos.logback.logback-classic's StaticLoggerBinder (from firrtl). - - val commonDependencies: Seq[ModuleID] = Seq( - scalatest, - scalacheck, - handlebars - ) - -} diff --git a/project/assembly.sbt b/project/assembly.sbt index 8956d332..17de943f 100644 --- a/project/assembly.sbt +++ b/project/assembly.sbt @@ -1,2 +1,2 @@ addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.5") -addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % "0.8.2") +addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % "0.9.2") diff --git a/project/build.properties b/project/build.properties index 7d789d45..72f90289 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=0.13.12 \ No newline at end of file +sbt.version=1.2.7 diff --git a/tapeout/src/main/scala/transforms/Generate.scala b/tapeout/src/main/scala/transforms/Generate.scala index 79bbd3b0..0d976cdd 100644 --- a/tapeout/src/main/scala/transforms/Generate.scala +++ b/tapeout/src/main/scala/transforms/Generate.scala @@ -23,70 +23,78 @@ object AllModules { } } -case class ParsedInput(args: Seq[String]) extends LazyLogging { - var input: Option[String] = None - var output: Option[String] = None - var topOutput: Option[String] = None - var harnessOutput: Option[String] = None - var annoFile: Option[String] = None - var synTop: Option[String] = None - var harnessTop: Option[String] = None - var seqMemFlags: Option[String] = Some("-o:unused.confg") - var listClocks: Option[String] = Some("-o:unused.clocks") +trait HasTapeoutOptions { self: ExecutionOptionsManager with HasFirrtlOptions => + var tapeoutOptions = TapeoutOptions() - var usedOptions = Set.empty[Integer] - args.zipWithIndex.foreach{ case (arg, i) => - arg match { - case "-i" => { - input = Some(args(i+1)) - usedOptions = usedOptions | Set(i+1) - } - case "-o" => { - output = Some(args(i+1)) - usedOptions = usedOptions | Set(i+1) - } - case "--top-o" => { - topOutput = Some(args(i+1)) - usedOptions = usedOptions | Set(i+1) - } - case "--harness-o" => { - harnessOutput = Some(args(i+1)) - usedOptions = usedOptions | Set(i+1) - } - case "--anno-file" => { - annoFile = Some(args(i+1)) - usedOptions = usedOptions | Set(i+1) - } - case "--syn-top" => { - synTop = Some(args(i+1)) - usedOptions = usedOptions | Set(i+1) - } - case "--harness-top" => { - harnessTop = Some(args(i+1)) - usedOptions = usedOptions | Set(i+1) - } - case "--seq-mem-flags" => { - seqMemFlags = Some(args(i+1)) - usedOptions = usedOptions | Set(i+1) - } - case "--list-clocks" => { - listClocks = Some(args(i+1)) - usedOptions = usedOptions | Set(i+1) - } - case _ => { - if (! (usedOptions contains i)) { - logger.error("Unknown option " + arg) - } - } + parser.note("tapeout options") + + parser.opt[String]("harness-o") + .abbr("tho") + .valueName("") + .foreach { x => + tapeoutOptions = tapeoutOptions.copy( + harnessOutput = Some(x) + ) + }.text { + "use this to generate a harness at " } - } + parser.opt[String]("syn-top") + .abbr("tst") + .valueName(" + tapeoutOptions = tapeoutOptions.copy( + synTop = Some(x) + ) + }.text { + "use this to set synTop" + } + + parser.opt[String]("harness-top") + .abbr("tht") + .valueName("") + .foreach { x => + tapeoutOptions = tapeoutOptions.copy( + harnessTop = Some(x) + ) + }.text { + "use this to set harnessTop" + } + + parser.opt[String]("list-clocks") + .abbr("tlc") + .valueName("") + .foreach { x => + tapeoutOptions = tapeoutOptions.copy( + listClocks = Some(x) + ) + }.text { + "use this to list " + } + + parser.note("") } +case class TapeoutOptions( + input: Option[String] = None, + output: Option[String] = None, + topOutput: Option[String] = None, + harnessOutput: Option[String] = None, + annoFile: Option[String] = None, + synTop: Option[String] = None, + harnessTop: Option[String] = None, + seqMemFlags: Option[String] = Some("-o:unused.confg"), + listClocks: Option[String] = Some("-o:unused.clocks") +) extends LazyLogging + // Requires two phases, one to collect modules below synTop in the hierarchy // and a second to remove those modules to generate the test harness sealed trait GenerateTopAndHarnessApp extends App with LazyLogging { - lazy val options: ParsedInput = ParsedInput(args) + val optionsManager = new ExecutionOptionsManager("tapeout") with HasFirrtlOptions with HasTapeoutOptions + if (!optionsManager.parse(args)) { + throw new Exception("Error parsing options!") + } + lazy val options = optionsManager.tapeoutOptions lazy val input = options.input lazy val output = options.output lazy val topOutput = options.topOutput @@ -116,34 +124,32 @@ sealed trait GenerateTopAndHarnessApp extends App with LazyLogging { pre ++ enumerate ++ post } - private def getFirstPhaseAnnotations(top: Boolean): AnnotationMap = { - if (top) { + private def getFirstPhaseAnnotations(top: Boolean): AnnotationSeq = { + if (top) { //Load annotations from file - val annotationArray = annoFile match { + val annotationArray: Seq[Annotation] = annoFile match { case None => Array[Annotation]() case Some(fileName) => { val annotations = new File(fileName) if(annotations.exists) { - val annotationsYaml = io.Source.fromFile(annotations).getLines().mkString("\n").parseYaml - annotationsYaml.convertTo[Array[Annotation]] + val annotationsYaml = io.Source.fromFile(annotations).getLines().mkString("\n") + Seq(AnnotationUtils.fromYaml(annotationsYaml)) // TODO } else { - Array[Annotation]() + Seq[Annotation]() } } } // add new annotations - AnnotationMap(Seq( - passes.memlib.InferReadWriteAnnotation( - s"${synTop.get}" - ), - passes.clocklist.ClockListAnnotation( + AnnotationSeq(Seq( + passes.memlib.InferReadWriteAnnotation, + passes.clocklist.ClockListAnnotation.parse( s"-c:${synTop.get}:-m:${synTop.get}:${listClocks.get}" ), - passes.memlib.ReplSeqMemAnnotation( + passes.memlib.ReplSeqMemAnnotation.parse( s"-c:${synTop.get}:${seqMemFlags.get}" ) ) ++ annotationArray) - } else { AnnotationMap(Seq.empty) } + } else { AnnotationSeq(Seq.empty) } } private def getSecondPhasePasses: Seq[Transform] = { @@ -156,31 +162,36 @@ sealed trait GenerateTopAndHarnessApp extends App with LazyLogging { } // always the same for now - private def getSecondPhaseAnnotations: AnnotationMap = AnnotationMap(Seq.empty) + private def getSecondPhaseAnnotations: AnnotationSeq = AnnotationSeq(Seq.empty) // Top Generation protected def firstPhase(top: Boolean, harness: Boolean): Unit = { require(top || harness, "Must specify either top or harness") - firrtl.Driver.compile( - input.get, - topOutput.getOrElse(output.get), - new VerilogCompiler(), - Parser.UseInfo, - getFirstPhasePasses(top, harness), - getFirstPhaseAnnotations(top) + + val firrtlOptions = optionsManager.firrtlOptions + optionsManager.firrtlOptions = firrtlOptions.copy( + annotations = firrtlOptions.annotations ++ getFirstPhaseAnnotations(top) + ) + + optionsManager.firrtlOptions = firrtlOptions.copy( + customTransforms = firrtlOptions.customTransforms ++ getFirstPhasePasses(top, harness) ) } // Harness Generation protected def secondPhase: Unit = { - firrtl.Driver.compile( - input.get, - harnessOutput.getOrElse(output.get), - new VerilogCompiler(), - Parser.UseInfo, - getSecondPhasePasses, - getSecondPhaseAnnotations + val firrtlOptions = optionsManager.firrtlOptions + optionsManager.firrtlOptions = firrtlOptions.copy( + annotations = firrtlOptions.annotations ++ getSecondPhaseAnnotations ) + + optionsManager.firrtlOptions = firrtlOptions.copy( + customTransforms = firrtlOptions.customTransforms ++ getSecondPhasePasses + ) + } + + protected def execute: Unit = { + firrtl.Driver.execute(optionsManager) } } @@ -191,6 +202,7 @@ object GenerateTop extends GenerateTopAndHarnessApp { n => logger.warn(s"Not using generic output filename $n since you asked for just a top-level output and also specified a generic output.")}) // Only need a single phase to generate the top module firstPhase(top = true, harness = false) + execute } object GenerateHarness extends GenerateTopAndHarnessApp { @@ -206,6 +218,7 @@ object GenerateHarness extends GenerateTopAndHarnessApp { // Do minimal work for the first phase to generate test harness firstPhase(top = false, harness = true) secondPhase + execute } object GenerateTopAndHarness extends GenerateTopAndHarnessApp { @@ -214,4 +227,5 @@ object GenerateTopAndHarness extends GenerateTopAndHarnessApp { // Do everything, top and harness generation firstPhase(top = true, harness = true) secondPhase + execute } diff --git a/tapeout/src/main/scala/transforms/utils/FileUtils.scala b/tapeout/src/main/scala/transforms/utils/FileUtils.scala index 5fc35842..7baf3e14 100644 --- a/tapeout/src/main/scala/transforms/utils/FileUtils.scala +++ b/tapeout/src/main/scala/transforms/utils/FileUtils.scala @@ -15,13 +15,10 @@ object WriteConfig { object GetTargetDir { def apply(state: CircuitState): String = { - val annos = state.annotations.getOrElse(AnnotationMap(Seq.empty)).annotations + val annos = state.annotations val destDir = annos.map { - case Annotation(f, t, s) if t == classOf[transforms.BlackBoxSourceHelper] => - transforms.BlackBoxSource.parse(s) match { - case Some(transforms.BlackBoxTargetDir(dest)) => Some(dest) - case _ => None - } + case Annotation(f, t, s) if t == classOf[firrtl.transforms.BlackBoxTargetDirAnno] => + Some(s) case _ => None }.flatten val loc = { @@ -45,14 +42,14 @@ class TechnologyLocation extends Transform { def outputForm: CircuitForm = LowForm def execute(state: CircuitState) = throw new Exception("Technology Location transform execution doesn't work!") def get(state: CircuitState): String = { - val annos = state.annotations.getOrElse(AnnotationMap(Seq.empty)).annotations + val annos = state.annotations val dir = annos.map { case Annotation(f, t, s) if t == classOf[TechnologyLocation] => Some(s) case _ => None }.flatten dir.length match { case 0 => "" - case 1 => + case 1 => val targetDir = new java.io.File(dir.head) if(!targetDir.exists()) throw new Exception("Technology yaml directory doesn't exist!") dir.head diff --git a/tapeout/src/test/scala/transforms/ResetInverterSpec.scala b/tapeout/src/test/scala/transforms/ResetInverterSpec.scala index 0ae41dc1..7abcbf4c 100644 --- a/tapeout/src/test/scala/transforms/ResetInverterSpec.scala +++ b/tapeout/src/test/scala/transforms/ResetInverterSpec.scala @@ -13,6 +13,8 @@ class ExampleModuleNeedsResetInverted extends Module with ResetInverter { val r = RegInit(0.U) + io.out := r + invert(this) } @@ -35,4 +37,4 @@ class ResetNSpec extends FreeSpec with Matchers { // bad } } -} \ No newline at end of file +} diff --git a/tapeout/src/test/scala/transforms/retime/RetimeSpec.scala b/tapeout/src/test/scala/transforms/retime/RetimeSpec.scala index bd52b5bc..7c634837 100644 --- a/tapeout/src/test/scala/transforms/retime/RetimeSpec.scala +++ b/tapeout/src/test/scala/transforms/retime/RetimeSpec.scala @@ -25,10 +25,10 @@ class RetimeSpec extends FlatSpec with Matchers { it should "pass simple retime module annotation" in { val gen = () => new RetimeModule() val dir = uniqueDirName(gen, "RetimeModule") - chisel3.Driver.execute(Array("-td", s"test_run_dir/$dir", "-foaf", s"test_run_dir/$dir/final.anno"), gen) shouldBe a [ChiselExecutionSuccess] + chisel3.Driver.execute(Array("-td", s"test_run_dir/$dir", "-foaf", s"test_run_dir/$dir/final"), gen) shouldBe a [ChiselExecutionSuccess] - val lines = io.Source.fromFile(s"test_run_dir/$dir/final.anno").getLines().map(normalized).toSeq - lines should contain ("Annotation(ModuleName(RetimeModule,CircuitName(RetimeModule)),class barstools.tapeout.transforms.retime.RetimeTransform,retime)") + val lines = io.Source.fromFile(s"test_run_dir/$dir/final.anno.json").getLines().map(normalized).mkString("\n") + lines should include("barstools.tapeout.transforms.retime.RetimeTransform") } // TODO(azidar): need to fix/add instance annotations