Move passes from pfpmp to barstools. (#5)

* Move passes from pfpmp to barstools.

* add an app that does both the harness and top generation

This reduces the number of firrtl.compile calls

* Add the ability to read annotations file

This helps with chisel annotation integration
This commit is contained in:
Colin Schmidt
2017-02-21 11:11:33 -08:00
committed by GitHub
parent d86dea58cf
commit 43f1a699ad
8 changed files with 471 additions and 0 deletions

View File

@@ -0,0 +1,36 @@
// See LICENSE for license details.
package barstools.tapeout.transforms
import firrtl._
import firrtl.ir._
import firrtl.passes.Pass
// Converts some modules to external modules, based on a given function. If
// that function returns "true" then the module is converted into an ExtModule,
// otherwise it's left alone.
class ConvertToExtModPass(classify: (Module) => Boolean) extends Pass {
def name = "Convert to External Modules"
def run(c: Circuit): Circuit = {
val modulesx = c.modules.map {
case m: ExtModule => m
case m: Module =>
if (classify(m)) {
new ExtModule(m.info, m.name, m.ports, m.name, Seq.empty)
} else {
m
}
}
Circuit(c.info, modulesx, c.main)
}
}
class ConvertToExtMod(classify: (Module) => Boolean) extends Transform with PassBased {
def inputForm = MidForm
def outputForm = MidForm
def passSeq = Seq(new ConvertToExtModPass(classify))
def execute(state: CircuitState): CircuitState = {
CircuitState(runPasses(state.circuit), state.form)
}
}

View File

@@ -0,0 +1,32 @@
// See LICENSE for license details.
package barstools.tapeout.transforms
import firrtl._
import firrtl.ir._
import firrtl.passes.Pass
class EnumerateModulesPass(enumerate: (Module) => Unit) extends Pass {
def name = "Enumurate Modules"
def run(c: Circuit): Circuit = {
val modulesx = c.modules.map {
case m: ExtModule => m
case m: Module => {
enumerate(m)
m
}
}
Circuit(c.info, modulesx, c.main)
}
}
class EnumerateModules(enumerate: (Module) => Unit) extends Transform with PassBased {
def inputForm = LowForm
def outputForm = LowForm
def passSeq = Seq(new EnumerateModulesPass(enumerate))
def execute(state: CircuitState): CircuitState = {
CircuitState(runPasses(state.circuit), state.form)
}
}

View File

@@ -0,0 +1,79 @@
// See LICENSE for license details.
package barstools.tapeout.transforms
import firrtl._
import firrtl.ir._
import firrtl.annotations._
import firrtl.passes.Pass
object AllModules {
private var modules = Set[String]()
def add(module: String) = {
modules = modules | Set(module)
}
def rename(module: String) = {
var new_name = module
while (modules.contains(new_name))
new_name = new_name + "_inTestHarness"
new_name
}
}
object GenerateHarness extends App {
var input: Option[String] = None
var output: Option[String] = None
var synTop: Option[String] = None
var harnessTop: Option[String] = None
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 "--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 _ => {
if (! (usedOptions contains i)) {
error("Unknown option " + arg)
}
}
}
}
firrtl.Driver.compile(
input.get,
output.get,
new VerilogCompiler(),
Parser.UseInfo,
Seq(
new ReParentCircuit(synTop.get),
new RemoveUnusedModules,
new EnumerateModules( { m => if (m.name != synTop.get) { AllModules.add(m.name) } } )
)
)
firrtl.Driver.compile(
input.get,
output.get,
new VerilogCompiler(),
Parser.UseInfo,
Seq(
new ConvertToExtMod((m) => m.name == synTop.get),
new RemoveUnusedModules,
new RenameModulesAndInstances((m) => AllModules.rename(m))
)
)
}

View File

@@ -0,0 +1,77 @@
// See LICENSE for license details.
package barstools.tapeout.transforms
import firrtl._
import firrtl.ir._
import firrtl.annotations._
import firrtl.passes.Pass
object GenerateTop extends App {
var input: Option[String] = None
var output: 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]
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 "--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)) {
error("Unknown option " + arg)
}
}
}
}
firrtl.Driver.compile(
input.get,
output.get,
new VerilogCompiler(),
Parser.UseInfo,
Seq(
new ReParentCircuit(synTop.get),
new RemoveUnusedModules,
new passes.memlib.InferReadWrite(),
new passes.memlib.ReplSeqMem(),
new passes.clocklist.ClockListTransform()
),
AnnotationMap(Seq(
passes.memlib.InferReadWriteAnnotation(
s"${synTop.get}"
),
passes.clocklist.ClockListAnnotation(
s"-c:${synTop.get}:-m:${synTop.get}:${listClocks.get}"
),
passes.memlib.ReplSeqMemAnnotation(
s"-c:${synTop.get}:${seqMemFlags.get}"
)
))
)
}

View File

@@ -0,0 +1,120 @@
// See LICENSE for license details.
package barstools.tapeout.transforms
import firrtl._
import firrtl.ir._
import firrtl.annotations._
import firrtl.passes.Pass
import java.io.File
import firrtl.annotations.AnnotationYamlProtocol._
import net.jcazevedo.moultingyaml._
object GenerateTopAndHarness extends App {
var input: 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]
args.zipWithIndex.foreach{ case (arg, i) =>
arg match {
case "-i" => {
input = 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)) {
error("Unknown option " + arg)
}
}
}
}
//Load annotations from file
val annotationArray = 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]]
} else {
Array[Annotation]()
}
}
}
//Top Generation
firrtl.Driver.compile(
input.get,
topOutput.get,
new VerilogCompiler(),
Parser.UseInfo,
Seq(
new ReParentCircuit(synTop.get),
new RemoveUnusedModules,
new EnumerateModules( { m => if (m.name != synTop.get) { AllModules.add(m.name) } } ),
new passes.memlib.InferReadWrite(),
new passes.memlib.ReplSeqMem(),
new passes.clocklist.ClockListTransform()
),
AnnotationMap(Seq(
passes.memlib.InferReadWriteAnnotation(
s"${synTop.get}"
),
passes.clocklist.ClockListAnnotation(
s"-c:${synTop.get}:-m:${synTop.get}:${listClocks.get}"
),
passes.memlib.ReplSeqMemAnnotation(
s"-c:${synTop.get}:${seqMemFlags.get}"
)
) ++ annotationArray)
)
//Harness Generation
firrtl.Driver.compile(
input.get,
harnessOutput.get,
new VerilogCompiler(),
Parser.UseInfo,
Seq(
new ConvertToExtMod((m) => m.name == synTop.get),
new RemoveUnusedModules,
new RenameModulesAndInstances((m) => AllModules.rename(m))
)
)
}

View File

@@ -0,0 +1,26 @@
// See LICENSE for license details.
package barstools.tapeout.transforms
import firrtl._
import firrtl.ir._
import firrtl.passes.Pass
// "Re-Parents" a circuit, which changes the top module to something else.
class ReParentCircuitPass(newTopName: String) extends Pass {
def name = "Re-Parent Circuit"
def run(c: Circuit): Circuit = {
Circuit(c.info, c.modules, newTopName)
}
}
class ReParentCircuit(newTopName: String) extends Transform with PassBased {
def inputForm = HighForm
def outputForm = HighForm
def passSeq = Seq(new ReParentCircuitPass(newTopName))
def execute(state: CircuitState): CircuitState = {
CircuitState(runPasses(state.circuit), state.form)
}
}

View File

@@ -0,0 +1,59 @@
// See LICENSE for license details.
package barstools.tapeout.transforms
import firrtl._
import firrtl.ir._
import firrtl.passes.Pass
// Removes all the unused modules in a circuit by recursing through every
// instance (starting at the main module)
class RemoveUnusedModulesPass extends Pass {
def name = "Remove Unused Modules"
def run(c: Circuit): Circuit = {
val modulesByName = c.modules.map{
case m: Module => (m.name, Some(m))
case m: ExtModule => (m.name, None)
}.toMap
def getUsedModules(om: Option[Module]): Set[String] = {
om match {
case Some(m) => {
def someStatements(statement: Statement): Seq[Statement] =
statement match {
case b: Block =>
b.stmts.map{ someStatements(_) }
.foldLeft(Seq[Statement]())(_ ++ _)
case i: DefInstance => Seq(i)
case w: WDefInstance => Seq(w)
case _ => Seq()
}
someStatements(m.body).map{
case s: DefInstance => Set(s.module) | getUsedModules(modulesByName(s.module))
case s: WDefInstance => Set(s.module) | getUsedModules(modulesByName(s.module))
case _ => Set[String]()
}.foldLeft(Set(m.name))(_ | _)
}
case None => Set.empty[String]
}
}
val usedModuleSet = getUsedModules(modulesByName(c.main))
val usedModuleSeq = c.modules.filter { usedModuleSet contains _.name }
Circuit(c.info, usedModuleSeq, c.main)
}
}
class RemoveUnusedModules extends Transform with PassBased {
def inputForm = MidForm
def outputForm = MidForm
def passSeq = Seq(new RemoveUnusedModulesPass)
def execute(state: CircuitState): CircuitState = {
CircuitState(runPasses(state.circuit), state.form)
}
}

View File

@@ -0,0 +1,42 @@
// See LICENSE for license details.
package barstools.tapeout.transforms
import firrtl._
import firrtl.ir._
import firrtl.passes.Pass
// This doesn't rename ExtModules under the assumption that they're some
// Verilog black box and therefor can't be renamed. Since the point is to
// allow FIRRTL to be linked together using "cat" and ExtModules don't get
// emitted, this should be safe.
class RenameModulesAndInstancesPass(rename: (String) => String) extends Pass {
def name = "Rename Modules and Instances"
def renameInstances(body: Statement): Statement = {
body match {
case m: DefInstance => new DefInstance(m.info, m.name, rename(m.module))
case m: WDefInstance => new WDefInstance(m.info, m.name, rename(m.module), m.tpe)
case b: Block => new Block( b.stmts map { s => renameInstances(s) } )
case s: Statement => s
}
}
def run(c: Circuit): Circuit = {
val modulesx = c.modules.map {
case m: ExtModule => m
case m: Module => new Module(m.info, rename(m.name), m.ports, renameInstances(m.body))
}
Circuit(c.info, modulesx, c.main)
}
}
class RenameModulesAndInstances(rename: (String) => String) extends Transform with PassBased {
def inputForm = LowForm
def outputForm = LowForm
def passSeq = Seq(new RenameModulesAndInstancesPass(rename))
def execute(state: CircuitState): CircuitState = {
CircuitState(runPasses(state.circuit), state.form)
}
}