aboutsummaryrefslogtreecommitdiff
path: root/src/main/scala/firrtl/passes/memlib/ReplaceMemTransform.scala
diff options
context:
space:
mode:
authorAdam Izraelevitz2016-10-17 18:53:19 -0700
committerAngie Wang2016-10-17 18:53:19 -0700
commit85baeda249e59c7d9d9f159aaf29ff46d685cf02 (patch)
treecfb5f4a6a0a80f9033275de6e5e36b9d5b96faad /src/main/scala/firrtl/passes/memlib/ReplaceMemTransform.scala
parent7d08b9a1486fef0459481f6e542464a29fbe1db5 (diff)
Reorganized memory blackboxing (#336)
* Reorganized memory blackboxing Moved to new package memlib Added comments Moved utility functions around Removed unused AnnotateValidMemConfigs.scala * Fixed tests to pass * Use DefAnnotatedMemory instead of AppendableInfo * Broke passes up into simpler passes AnnotateMemMacros -> (ToMemIR, ResolveMaskGranularity) UpdateDuplicateMemMacros -> (RenameAnnotatedMemoryPorts, ResolveMemoryReference) * Fixed to make tests run * Minor changes from code review * Removed vim comments and renamed ReplSeqMem
Diffstat (limited to 'src/main/scala/firrtl/passes/memlib/ReplaceMemTransform.scala')
-rw-r--r--src/main/scala/firrtl/passes/memlib/ReplaceMemTransform.scala126
1 files changed, 126 insertions, 0 deletions
diff --git a/src/main/scala/firrtl/passes/memlib/ReplaceMemTransform.scala b/src/main/scala/firrtl/passes/memlib/ReplaceMemTransform.scala
new file mode 100644
index 00000000..dfa828c9
--- /dev/null
+++ b/src/main/scala/firrtl/passes/memlib/ReplaceMemTransform.scala
@@ -0,0 +1,126 @@
+// See LICENSE for license details.
+
+package firrtl.passes
+package memlib
+
+import firrtl._
+import firrtl.ir._
+import Annotations._
+import AnalysisUtils._
+import Utils.error
+import java.io.{File, CharArrayWriter, PrintWriter}
+
+sealed trait PassOption
+case object InputConfigFileName extends PassOption
+case object OutputConfigFileName extends PassOption
+case object PassCircuitName extends PassOption
+
+object PassConfigUtil {
+ type PassOptionMap = Map[PassOption, String]
+
+ def getPassOptions(t: String, usage: String = "") = {
+ // can't use space to delimit sub arguments (otherwise, Driver.scala will throw error)
+ val passArgList = t.split(":").toList
+
+ def nextPassOption(map: PassOptionMap, list: List[String]): PassOptionMap = {
+ list match {
+ case Nil => map
+ case "-i" :: value :: tail =>
+ nextPassOption(map + (InputConfigFileName -> value), tail)
+ case "-o" :: value :: tail =>
+ nextPassOption(map + (OutputConfigFileName -> value), tail)
+ case "-c" :: value :: tail =>
+ nextPassOption(map + (PassCircuitName -> value), tail)
+ case option :: tail =>
+ error("Unknown option " + option + usage)
+ }
+ }
+ nextPassOption(Map[PassOption, String](), passArgList)
+ }
+}
+
+class ConfWriter(filename: String) {
+ val outputBuffer = new CharArrayWriter
+ def append(m: DefAnnotatedMemory) = {
+ // legacy
+ val maskGran = m.maskGran
+ val readers = List.fill(m.readers.length)("read")
+ val writers = List.fill(m.writers.length)(if (maskGran.isEmpty) "write" else "mwrite")
+ val readwriters = List.fill(m.readwriters.length)(if (maskGran.isEmpty) "rw" else "mrw")
+ val ports = (writers ++ readers ++ readwriters) mkString ","
+ val maskGranConf = maskGran match { case None => "" case Some(p) => s"mask_gran $p" }
+ val width = bitWidth(m.dataType)
+ val conf = s"name ${m.name} depth ${m.depth} width $width ports $ports $maskGranConf \n"
+ outputBuffer.append(conf)
+ }
+ def serialize() = {
+ val outputFile = new PrintWriter(filename)
+ outputFile.write(outputBuffer.toString)
+ outputFile.close()
+ }
+}
+
+case class ReplSeqMemAnnotation(t: String, tID: TransID)
+ extends Annotation with Loose with Unstable {
+
+ val usage = """
+[Optional] ReplSeqMem
+ Pass to replace sequential memories with blackboxes + configuration file
+
+Usage:
+ --replSeqMem -c:<circuit>:-i:<filename>:-o:<filename>
+ *** Note: sub-arguments to --replSeqMem should be delimited by : and not white space!
+
+Required Arguments:
+ -o<filename> Specify the output configuration file
+ -c<compiler> Specify the target circuit
+
+Optional Arguments:
+ -i<filename> Specify the input configuration file (for additional optimizations)
+"""
+
+ val passOptions = PassConfigUtil.getPassOptions(t, usage)
+ val outputConfig = passOptions.getOrElse(
+ OutputConfigFileName,
+ error("No output config file provided for ReplSeqMem!" + usage)
+ )
+ val passCircuit = passOptions.getOrElse(
+ PassCircuitName,
+ error("No circuit name specified for ReplSeqMem!" + usage)
+ )
+ val target = CircuitName(passCircuit)
+ def duplicate(n: Named) = this copy (t = t.replace(s"-c:$passCircuit", s"-c:${n.name}"))
+}
+
+class ReplSeqMem(transID: TransID) extends Transform with SimpleRun {
+ def passSeq(inConfigFile: Option[YamlFileReader], outConfigFile: ConfWriter) =
+ Seq(Legalize,
+ ToMemIR,
+ ResolveMaskGranularity,
+ RenameAnnotatedMemoryPorts,
+ ResolveMemoryReference,
+ //new AnnotateValidMemConfigs(inConfigFile),
+ new ReplaceMemMacros(outConfigFile),
+ RemoveEmpty,
+ CheckInitialization,
+ InferTypes,
+ Uniquify,
+ ResolveKinds, // Must be run for the transform to work!
+ ResolveGenders)
+
+ def execute(c: Circuit, map: AnnotationMap) = map get transID match {
+ case Some(p) => p get CircuitName(c.main) match {
+ case Some(ReplSeqMemAnnotation(t, _)) =>
+ val inputFileName = PassConfigUtil.getPassOptions(t).getOrElse(InputConfigFileName, "")
+ val inConfigFile = {
+ if (inputFileName.isEmpty) None
+ else if (new File(inputFileName).exists) Some(new YamlFileReader(inputFileName))
+ else error("Input configuration file does not exist!")
+ }
+ val outConfigFile = new ConfWriter(PassConfigUtil.getPassOptions(t)(OutputConfigFileName))
+ run(c, passSeq(inConfigFile, outConfigFile))
+ case _ => error("Unexpected transform annotation")
+ }
+ case _ => TransformResult(c)
+ }
+}