Refactor barstools for new versions of things.
- No handlebars (not being published for Scala 2.12) - Update for new annotations APIs Bump sbt-dependency-graph to 0.9.2 for this scala version
This commit is contained in:
17
build.sbt
17
build.sbt
@@ -1,21 +1,22 @@
|
|||||||
// See LICENSE for license details.
|
// See LICENSE for license details.
|
||||||
|
|
||||||
import Dependencies._
|
|
||||||
|
|
||||||
val defaultVersions = Map(
|
val defaultVersions = Map(
|
||||||
"chisel3" -> "3.1-SNAPSHOT",
|
"chisel3" -> "3.2-SNAPSHOT",
|
||||||
"chisel-iotesters" -> "1.2-SNAPSHOT"
|
"chisel-iotesters" -> "1.3-SNAPSHOT"
|
||||||
)
|
)
|
||||||
|
|
||||||
lazy val commonSettings = Seq(
|
lazy val commonSettings = Seq(
|
||||||
organization := "edu.berkeley.cs",
|
organization := "edu.berkeley.cs",
|
||||||
version := "0.1-SNAPSHOT",
|
version := "0.1-SNAPSHOT",
|
||||||
scalaVersion := "2.11.8",
|
scalaVersion := "2.12.8",
|
||||||
scalacOptions := Seq("-deprecation", "-feature", "-language:reflectiveCalls"),
|
scalacOptions := Seq("-deprecation", "-feature", "-language:reflectiveCalls", "-Xsource:2.11"),
|
||||||
libraryDependencies ++= commonDependencies,
|
|
||||||
libraryDependencies ++= Seq("chisel3","chisel-iotesters").map {
|
libraryDependencies ++= Seq("chisel3","chisel-iotesters").map {
|
||||||
dep: String => "edu.berkeley.cs" %% dep % sys.props.getOrElse(dep + "Version", defaultVersions(dep))
|
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(
|
resolvers ++= Seq(
|
||||||
Resolver.sonatypeRepo("snapshots"),
|
Resolver.sonatypeRepo("snapshots"),
|
||||||
Resolver.sonatypeRepo("releases")
|
Resolver.sonatypeRepo("releases")
|
||||||
@@ -30,7 +31,7 @@ lazy val macros = (project in file("macros"))
|
|||||||
.settings(commonSettings)
|
.settings(commonSettings)
|
||||||
.settings(Seq(
|
.settings(Seq(
|
||||||
libraryDependencies ++= 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")
|
mainClass := Some("barstools.macros.MacroCompiler")
|
||||||
))
|
))
|
||||||
|
|||||||
@@ -752,7 +752,7 @@ object MacroCompiler extends App {
|
|||||||
// Note: the last macro in the input list is (seemingly arbitrarily)
|
// Note: the last macro in the input list is (seemingly arbitrarily)
|
||||||
// determined as the firrtl "top-level module".
|
// determined as the firrtl "top-level module".
|
||||||
val circuit = Circuit(NoInfo, macros, macros.last.name)
|
val circuit = Circuit(NoInfo, macros, macros.last.name)
|
||||||
val annotations = AnnotationMap(
|
val annotations = AnnotationSeq(
|
||||||
Seq(MacroCompilerAnnotation(
|
Seq(MacroCompilerAnnotation(
|
||||||
circuit.main,
|
circuit.main,
|
||||||
MacroCompilerAnnotation.Params(
|
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.
|
// Run the compiler.
|
||||||
val result = new MacroCompiler().compileAndEmit(state)
|
val result = new MacroCompiler().compileAndEmit(state)
|
||||||
|
|||||||
@@ -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
|
|
||||||
)
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,2 +1,2 @@
|
|||||||
addSbtPlugin("com.eed3si9n" % "sbt-assembly" % "0.14.5")
|
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")
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
sbt.version=0.13.12
|
sbt.version=1.2.7
|
||||||
|
|||||||
@@ -23,70 +23,78 @@ object AllModules {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case class ParsedInput(args: Seq[String]) extends LazyLogging {
|
trait HasTapeoutOptions { self: ExecutionOptionsManager with HasFirrtlOptions =>
|
||||||
var input: Option[String] = None
|
var tapeoutOptions = TapeoutOptions()
|
||||||
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")
|
|
||||||
|
|
||||||
var usedOptions = Set.empty[Integer]
|
parser.note("tapeout options")
|
||||||
args.zipWithIndex.foreach{ case (arg, i) =>
|
|
||||||
arg match {
|
parser.opt[String]("harness-o")
|
||||||
case "-i" => {
|
.abbr("tho")
|
||||||
input = Some(args(i+1))
|
.valueName("<harness-output>")
|
||||||
usedOptions = usedOptions | Set(i+1)
|
.foreach { x =>
|
||||||
}
|
tapeoutOptions = tapeoutOptions.copy(
|
||||||
case "-o" => {
|
harnessOutput = Some(x)
|
||||||
output = Some(args(i+1))
|
)
|
||||||
usedOptions = usedOptions | Set(i+1)
|
}.text {
|
||||||
}
|
"use this to generate a harness at <harness-output>"
|
||||||
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.opt[String]("syn-top")
|
||||||
|
.abbr("tst")
|
||||||
|
.valueName("<syn-top")
|
||||||
|
.foreach { x =>
|
||||||
|
tapeoutOptions = tapeoutOptions.copy(
|
||||||
|
synTop = Some(x)
|
||||||
|
)
|
||||||
|
}.text {
|
||||||
|
"use this to set synTop"
|
||||||
|
}
|
||||||
|
|
||||||
|
parser.opt[String]("harness-top")
|
||||||
|
.abbr("tht")
|
||||||
|
.valueName("<harness-top>")
|
||||||
|
.foreach { x =>
|
||||||
|
tapeoutOptions = tapeoutOptions.copy(
|
||||||
|
harnessTop = Some(x)
|
||||||
|
)
|
||||||
|
}.text {
|
||||||
|
"use this to set harnessTop"
|
||||||
|
}
|
||||||
|
|
||||||
|
parser.opt[String]("list-clocks")
|
||||||
|
.abbr("tlc")
|
||||||
|
.valueName("<clocks>")
|
||||||
|
.foreach { x =>
|
||||||
|
tapeoutOptions = tapeoutOptions.copy(
|
||||||
|
listClocks = Some(x)
|
||||||
|
)
|
||||||
|
}.text {
|
||||||
|
"use this to list <clocks>"
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
// Requires two phases, one to collect modules below synTop in the hierarchy
|
||||||
// and a second to remove those modules to generate the test harness
|
// and a second to remove those modules to generate the test harness
|
||||||
sealed trait GenerateTopAndHarnessApp extends App with LazyLogging {
|
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 input = options.input
|
||||||
lazy val output = options.output
|
lazy val output = options.output
|
||||||
lazy val topOutput = options.topOutput
|
lazy val topOutput = options.topOutput
|
||||||
@@ -116,34 +124,32 @@ sealed trait GenerateTopAndHarnessApp extends App with LazyLogging {
|
|||||||
pre ++ enumerate ++ post
|
pre ++ enumerate ++ post
|
||||||
}
|
}
|
||||||
|
|
||||||
private def getFirstPhaseAnnotations(top: Boolean): AnnotationMap = {
|
private def getFirstPhaseAnnotations(top: Boolean): AnnotationSeq = {
|
||||||
if (top) {
|
if (top) {
|
||||||
//Load annotations from file
|
//Load annotations from file
|
||||||
val annotationArray = annoFile match {
|
val annotationArray: Seq[Annotation] = annoFile match {
|
||||||
case None => Array[Annotation]()
|
case None => Array[Annotation]()
|
||||||
case Some(fileName) => {
|
case Some(fileName) => {
|
||||||
val annotations = new File(fileName)
|
val annotations = new File(fileName)
|
||||||
if(annotations.exists) {
|
if(annotations.exists) {
|
||||||
val annotationsYaml = io.Source.fromFile(annotations).getLines().mkString("\n").parseYaml
|
val annotationsYaml = io.Source.fromFile(annotations).getLines().mkString("\n")
|
||||||
annotationsYaml.convertTo[Array[Annotation]]
|
Seq(AnnotationUtils.fromYaml(annotationsYaml)) // TODO
|
||||||
} else {
|
} else {
|
||||||
Array[Annotation]()
|
Seq[Annotation]()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// add new annotations
|
// add new annotations
|
||||||
AnnotationMap(Seq(
|
AnnotationSeq(Seq(
|
||||||
passes.memlib.InferReadWriteAnnotation(
|
passes.memlib.InferReadWriteAnnotation,
|
||||||
s"${synTop.get}"
|
passes.clocklist.ClockListAnnotation.parse(
|
||||||
),
|
|
||||||
passes.clocklist.ClockListAnnotation(
|
|
||||||
s"-c:${synTop.get}:-m:${synTop.get}:${listClocks.get}"
|
s"-c:${synTop.get}:-m:${synTop.get}:${listClocks.get}"
|
||||||
),
|
),
|
||||||
passes.memlib.ReplSeqMemAnnotation(
|
passes.memlib.ReplSeqMemAnnotation.parse(
|
||||||
s"-c:${synTop.get}:${seqMemFlags.get}"
|
s"-c:${synTop.get}:${seqMemFlags.get}"
|
||||||
)
|
)
|
||||||
) ++ annotationArray)
|
) ++ annotationArray)
|
||||||
} else { AnnotationMap(Seq.empty) }
|
} else { AnnotationSeq(Seq.empty) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private def getSecondPhasePasses: Seq[Transform] = {
|
private def getSecondPhasePasses: Seq[Transform] = {
|
||||||
@@ -156,31 +162,36 @@ sealed trait GenerateTopAndHarnessApp extends App with LazyLogging {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// always the same for now
|
// always the same for now
|
||||||
private def getSecondPhaseAnnotations: AnnotationMap = AnnotationMap(Seq.empty)
|
private def getSecondPhaseAnnotations: AnnotationSeq = AnnotationSeq(Seq.empty)
|
||||||
|
|
||||||
// Top Generation
|
// Top Generation
|
||||||
protected def firstPhase(top: Boolean, harness: Boolean): Unit = {
|
protected def firstPhase(top: Boolean, harness: Boolean): Unit = {
|
||||||
require(top || harness, "Must specify either top or harness")
|
require(top || harness, "Must specify either top or harness")
|
||||||
firrtl.Driver.compile(
|
|
||||||
input.get,
|
val firrtlOptions = optionsManager.firrtlOptions
|
||||||
topOutput.getOrElse(output.get),
|
optionsManager.firrtlOptions = firrtlOptions.copy(
|
||||||
new VerilogCompiler(),
|
annotations = firrtlOptions.annotations ++ getFirstPhaseAnnotations(top)
|
||||||
Parser.UseInfo,
|
)
|
||||||
getFirstPhasePasses(top, harness),
|
|
||||||
getFirstPhaseAnnotations(top)
|
optionsManager.firrtlOptions = firrtlOptions.copy(
|
||||||
|
customTransforms = firrtlOptions.customTransforms ++ getFirstPhasePasses(top, harness)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Harness Generation
|
// Harness Generation
|
||||||
protected def secondPhase: Unit = {
|
protected def secondPhase: Unit = {
|
||||||
firrtl.Driver.compile(
|
val firrtlOptions = optionsManager.firrtlOptions
|
||||||
input.get,
|
optionsManager.firrtlOptions = firrtlOptions.copy(
|
||||||
harnessOutput.getOrElse(output.get),
|
annotations = firrtlOptions.annotations ++ getSecondPhaseAnnotations
|
||||||
new VerilogCompiler(),
|
|
||||||
Parser.UseInfo,
|
|
||||||
getSecondPhasePasses,
|
|
||||||
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.")})
|
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
|
// Only need a single phase to generate the top module
|
||||||
firstPhase(top = true, harness = false)
|
firstPhase(top = true, harness = false)
|
||||||
|
execute
|
||||||
}
|
}
|
||||||
|
|
||||||
object GenerateHarness extends GenerateTopAndHarnessApp {
|
object GenerateHarness extends GenerateTopAndHarnessApp {
|
||||||
@@ -206,6 +218,7 @@ object GenerateHarness extends GenerateTopAndHarnessApp {
|
|||||||
// Do minimal work for the first phase to generate test harness
|
// Do minimal work for the first phase to generate test harness
|
||||||
firstPhase(top = false, harness = true)
|
firstPhase(top = false, harness = true)
|
||||||
secondPhase
|
secondPhase
|
||||||
|
execute
|
||||||
}
|
}
|
||||||
|
|
||||||
object GenerateTopAndHarness extends GenerateTopAndHarnessApp {
|
object GenerateTopAndHarness extends GenerateTopAndHarnessApp {
|
||||||
@@ -214,4 +227,5 @@ object GenerateTopAndHarness extends GenerateTopAndHarnessApp {
|
|||||||
// Do everything, top and harness generation
|
// Do everything, top and harness generation
|
||||||
firstPhase(top = true, harness = true)
|
firstPhase(top = true, harness = true)
|
||||||
secondPhase
|
secondPhase
|
||||||
|
execute
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,13 +15,10 @@ object WriteConfig {
|
|||||||
|
|
||||||
object GetTargetDir {
|
object GetTargetDir {
|
||||||
def apply(state: CircuitState): String = {
|
def apply(state: CircuitState): String = {
|
||||||
val annos = state.annotations.getOrElse(AnnotationMap(Seq.empty)).annotations
|
val annos = state.annotations
|
||||||
val destDir = annos.map {
|
val destDir = annos.map {
|
||||||
case Annotation(f, t, s) if t == classOf[transforms.BlackBoxSourceHelper] =>
|
case Annotation(f, t, s) if t == classOf[firrtl.transforms.BlackBoxTargetDirAnno] =>
|
||||||
transforms.BlackBoxSource.parse(s) match {
|
Some(s)
|
||||||
case Some(transforms.BlackBoxTargetDir(dest)) => Some(dest)
|
|
||||||
case _ => None
|
|
||||||
}
|
|
||||||
case _ => None
|
case _ => None
|
||||||
}.flatten
|
}.flatten
|
||||||
val loc = {
|
val loc = {
|
||||||
@@ -45,7 +42,7 @@ class TechnologyLocation extends Transform {
|
|||||||
def outputForm: CircuitForm = LowForm
|
def outputForm: CircuitForm = LowForm
|
||||||
def execute(state: CircuitState) = throw new Exception("Technology Location transform execution doesn't work!")
|
def execute(state: CircuitState) = throw new Exception("Technology Location transform execution doesn't work!")
|
||||||
def get(state: CircuitState): String = {
|
def get(state: CircuitState): String = {
|
||||||
val annos = state.annotations.getOrElse(AnnotationMap(Seq.empty)).annotations
|
val annos = state.annotations
|
||||||
val dir = annos.map {
|
val dir = annos.map {
|
||||||
case Annotation(f, t, s) if t == classOf[TechnologyLocation] => Some(s)
|
case Annotation(f, t, s) if t == classOf[TechnologyLocation] => Some(s)
|
||||||
case _ => None
|
case _ => None
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ class ExampleModuleNeedsResetInverted extends Module with ResetInverter {
|
|||||||
|
|
||||||
val r = RegInit(0.U)
|
val r = RegInit(0.U)
|
||||||
|
|
||||||
|
io.out := r
|
||||||
|
|
||||||
invert(this)
|
invert(this)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,10 +25,10 @@ class RetimeSpec extends FlatSpec with Matchers {
|
|||||||
it should "pass simple retime module annotation" in {
|
it should "pass simple retime module annotation" in {
|
||||||
val gen = () => new RetimeModule()
|
val gen = () => new RetimeModule()
|
||||||
val dir = uniqueDirName(gen, "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
|
val lines = io.Source.fromFile(s"test_run_dir/$dir/final.anno.json").getLines().map(normalized).mkString("\n")
|
||||||
lines should contain ("Annotation(ModuleName(RetimeModule,CircuitName(RetimeModule)),class barstools.tapeout.transforms.retime.RetimeTransform,retime)")
|
lines should include("barstools.tapeout.transforms.retime.RetimeTransform")
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(azidar): need to fix/add instance annotations
|
// TODO(azidar): need to fix/add instance annotations
|
||||||
|
|||||||
Reference in New Issue
Block a user