Add options to force certain memories to lib or synflops

This commit is contained in:
Edward Wang
2018-04-26 10:33:05 -07:00
committed by edwardcwang
parent d1c1b3fba6
commit 4727d475c7

View File

@@ -55,6 +55,7 @@ object MacroCompilerAnnotation {
// Options as list of (CompilerMode, command-line name, description) // Options as list of (CompilerMode, command-line name, description)
val options: Seq[(CompilerMode, String, String)] = Seq( val options: Seq[(CompilerMode, String, String)] = Seq(
(Default, "default", "Select the default option from below."),
(Strict, "strict", "Compile all memories to library or return an error."), (Strict, "strict", "Compile all memories to library or return an error."),
(Synflops, "synflops", "Produces synthesizable flop-based memories for all memories (do not map to lib at all); likely useful for simulation purposes."), (Synflops, "synflops", "Produces synthesizable flop-based memories for all memories (do not map to lib at all); likely useful for simulation purposes."),
(CompileAndSynflops, "compileandsynflops", "Compile all memories and create mock versions of the target libs with synflops; likely also useful for simulation purposes."), (CompileAndSynflops, "compileandsynflops", "Compile all memories and create mock versions of the target libs with synflops; likely also useful for simulation purposes."),
@@ -69,13 +70,17 @@ object MacroCompilerAnnotation {
} }
/** /**
* Parameters associated to this MacroCompilerAnnotation. * Parameters associated to this MacroCompilerAnnotation.
* @param mem Path to memory lib *
* @param lib Path to library lib or None if no libraries * @param mem Path to memory lib
* @param costMetric Cost metric to use * @param lib Path to library lib or None if no libraries
* @param mode Compiler mode (see CompilerMode) * @param costMetric Cost metric to use
*/ * @param mode Compiler mode (see CompilerMode)
case class Params(mem: String, lib: Option[String], costMetric: CostMetric, mode: CompilerMode, useCompiler: Boolean) * @param forceCompile Set of memories to force compiling to lib regardless of the mode
* @param forceSynflops Set of memories to force compiling as flops regardless of the mode
*/
case class Params(mem: String, lib: Option[String], costMetric: CostMetric, mode: CompilerMode, useCompiler: Boolean,
forceCompile: Set[String], forceSynflops: Set[String])
/** /**
* Create a MacroCompilerAnnotation. * Create a MacroCompilerAnnotation.
@@ -601,11 +606,17 @@ class MacroCompilerPass(mems: Option[Seq[Macro]],
class MacroCompilerTransform extends Transform { class MacroCompilerTransform extends Transform {
def inputForm = MidForm def inputForm = MidForm
def outputForm = MidForm def outputForm = MidForm
def execute(state: CircuitState) = getMyAnnotations(state) match { def execute(state: CircuitState) = getMyAnnotations(state) match {
case Seq(MacroCompilerAnnotation(state.circuit.main, MacroCompilerAnnotation.Params(memFile, libFile, costMetric, mode, useCompiler))) => case Seq(MacroCompilerAnnotation(state.circuit.main,
MacroCompilerAnnotation.Params(memFile, libFile, costMetric, mode, useCompiler, forceCompile, forceSynflops))) =>
if (mode == MacroCompilerAnnotation.FallbackSynflops) { if (mode == MacroCompilerAnnotation.FallbackSynflops) {
throw new UnsupportedOperationException("Not implemented yet") throw new UnsupportedOperationException("Not implemented yet")
} }
// Check that we don't have any modules both forced to compile and synflops.
assert((forceCompile intersect forceSynflops).isEmpty, "Cannot have modules both forced to compile and synflops")
// Read, eliminate None, get only SRAM, make firrtl macro // Read, eliminate None, get only SRAM, make firrtl macro
val mems: Option[Seq[Macro]] = mdf.macrolib.Utils.readMDFFromPath(Some(memFile)) match { val mems: Option[Seq[Macro]] = mdf.macrolib.Utils.readMDFFromPath(Some(memFile)) match {
case Some(x:Seq[mdf.macrolib.Macro]) => case Some(x:Seq[mdf.macrolib.Macro]) =>
@@ -620,15 +631,30 @@ class MacroCompilerTransform extends Transform {
else Some(Utils.filterForSRAM(Some(x)) getOrElse(List()) map {new Macro(_)}) else Some(Utils.filterForSRAM(Some(x)) getOrElse(List()) map {new Macro(_)})
case _ => None case _ => None
} }
// Helper function to turn a set of mem names into a Seq[Macro].
def setToSeqMacro(names: Set[String]): Seq[Macro] = {
names.toSeq.map(memName => mems.get.collectFirst { case m if m.src.name == memName => m }.get)
}
// Build lists of memories for compilation and synflops.
val memCompile = mems.map { actualMems =>
val memsAdjustedForMode = if (mode == MacroCompilerAnnotation.Synflops) Seq.empty else actualMems
memsAdjustedForMode.filterNot(m => forceSynflops.contains(m.src.name)) ++ setToSeqMacro(forceCompile)
}
val memSynflops: Seq[Macro] = mems.map { actualMems =>
val memsAdjustedForMode = if (mode == MacroCompilerAnnotation.Synflops) actualMems else Seq.empty
memsAdjustedForMode.filterNot(m => forceCompile.contains(m.src.name)) ++ setToSeqMacro(forceSynflops)
}.getOrElse(Seq.empty)
val transforms = Seq( val transforms = Seq(
new MacroCompilerPass(mems, if (mode != MacroCompilerAnnotation.Synflops) libs else None, costMetric, mode), new MacroCompilerPass(memCompile, libs, costMetric, mode),
new SynFlopsPass(mode == MacroCompilerAnnotation.Synflops || mode == MacroCompilerAnnotation.CompileAndSynflops, new SynFlopsPass(true, memSynflops ++ (if (mode == MacroCompilerAnnotation.CompileAndSynflops) {
if (mode == MacroCompilerAnnotation.CompileAndSynflops) { libs.get
libs.get } else {
} else { Seq.empty
mems.get })))
})) (transforms foldLeft state) ((s, xform) => xform runTransform s).copy(form = outputForm)
(transforms foldLeft state)((s, xform) => xform runTransform s).copy(form=outputForm)
case _ => state case _ => state
} }
} }
@@ -670,6 +696,7 @@ object MacroCompiler extends App {
type MacroParamMap = Map[MacroParam, String] type MacroParamMap = Map[MacroParam, String]
type CostParamMap = Map[String, String] type CostParamMap = Map[String, String]
type ForcedMemories = (Set[String], Set[String])
val modeOptions: Seq[String] = MacroCompilerAnnotation.options val modeOptions: Seq[String] = MacroCompilerAnnotation.options
.map { case (_, cmd, description) => s" $cmd: $description" } .map { case (_, cmd, description) => s" $cmd: $description" }
val usage: String = (Seq( val usage: String = (Seq(
@@ -681,28 +708,35 @@ object MacroCompiler extends App {
" -f, --firrtl: FIRRTL output (optional)", " -f, --firrtl: FIRRTL output (optional)",
" -c, --cost-func: Cost function to use. Optional (default: \"default\")", " -c, --cost-func: Cost function to use. Optional (default: \"default\")",
" -cp, --cost-param: Cost function parameter. (Optional depending on the cost function.). e.g. -c ExternalMetric -cp path /path/to/my/cost/script", " -cp, --cost-param: Cost function parameter. (Optional depending on the cost function.). e.g. -c ExternalMetric -cp path /path/to/my/cost/script",
" --force-compile [mem]: Force the given memory to be compiled to target libs regardless of the mode",
" --force-synflops [mem]: Force the given memory to be compiled via synflops regardless of the mode",
" --mode:" " --mode:"
) ++ modeOptions) mkString "\n" ) ++ modeOptions) mkString "\n"
def parseArgs(map: MacroParamMap, costMap: CostParamMap, args: List[String]): (MacroParamMap, CostParamMap) = def parseArgs(map: MacroParamMap, costMap: CostParamMap, forcedMemories: ForcedMemories,
args: List[String]): (MacroParamMap, CostParamMap, ForcedMemories) =
args match { args match {
case Nil => (map, costMap) case Nil => (map, costMap, forcedMemories)
case ("-m" | "--macro-list") :: value :: tail => case ("-m" | "--macro-list") :: value :: tail =>
parseArgs(map + (Macros -> value), costMap, tail) parseArgs(map + (Macros -> value), costMap, forcedMemories, tail)
case ("-l" | "--library") :: value :: tail => case ("-l" | "--library") :: value :: tail =>
parseArgs(map + (Library -> value), costMap, tail) parseArgs(map + (Library -> value), costMap, forcedMemories, tail)
case ("-u" | "--use-compiler") :: tail => case ("-u" | "--use-compiler") :: tail =>
parseArgs(map + (UseCompiler -> ""), costMap, tail) parseArgs(map + (UseCompiler -> ""), costMap, forcedMemories, tail)
case ("-v" | "--verilog") :: value :: tail => case ("-v" | "--verilog") :: value :: tail =>
parseArgs(map + (Verilog -> value), costMap, tail) parseArgs(map + (Verilog -> value), costMap, forcedMemories, tail)
case ("-f" | "--firrtl") :: value :: tail => case ("-f" | "--firrtl") :: value :: tail =>
parseArgs(map + (Firrtl -> value), costMap, tail) parseArgs(map + (Firrtl -> value), costMap, forcedMemories, tail)
case ("-c" | "--cost-func") :: value :: tail => case ("-c" | "--cost-func") :: value :: tail =>
parseArgs(map + (CostFunc -> value), costMap, tail) parseArgs(map + (CostFunc -> value), costMap, forcedMemories, tail)
case ("-cp" | "--cost-param") :: value1 :: value2 :: tail => case ("-cp" | "--cost-param") :: value1 :: value2 :: tail =>
parseArgs(map, costMap + (value1 -> value2), tail) parseArgs(map, costMap + (value1 -> value2), forcedMemories, tail)
case "--force-compile" :: value :: tail =>
parseArgs(map, costMap, forcedMemories.copy(_1 = forcedMemories._1 + value), tail)
case "--force-synflops" :: value :: tail =>
parseArgs(map, costMap, forcedMemories.copy(_2 = forcedMemories._2 + value), tail)
case "--mode" :: value :: tail => case "--mode" :: value :: tail =>
parseArgs(map + (Mode -> value), costMap, tail) parseArgs(map + (Mode -> value), costMap, forcedMemories, tail)
case arg :: tail => case arg :: tail =>
println(s"Unknown field $arg\n") println(s"Unknown field $arg\n")
println(usage) println(usage)
@@ -710,7 +744,7 @@ object MacroCompiler extends App {
} }
def run(args: List[String]) { def run(args: List[String]) {
val (params, costParams) = parseArgs(Map[MacroParam, String](), Map[String, String](), args) val (params, costParams, forcedMemories) = parseArgs(Map[MacroParam, String](), Map[String, String](), (Set.empty, Set.empty), args)
try { try {
val macros = Utils.filterForSRAM(mdf.macrolib.Utils.readMDFFromPath(params.get(Macros))).get map (x => (new Macro(x)).blackbox) val macros = Utils.filterForSRAM(mdf.macrolib.Utils.readMDFFromPath(params.get(Macros))).get map (x => (new Macro(x)).blackbox)
@@ -725,7 +759,8 @@ object MacroCompiler extends App {
params.get(Macros).get, params.get(Library), params.get(Macros).get, params.get(Library),
CostMetric.getCostMetric(params.getOrElse(CostFunc, "default"), costParams), CostMetric.getCostMetric(params.getOrElse(CostFunc, "default"), costParams),
MacroCompilerAnnotation.stringToCompilerMode(params.getOrElse(Mode, "default")), MacroCompilerAnnotation.stringToCompilerMode(params.getOrElse(Mode, "default")),
params.contains(UseCompiler) params.contains(UseCompiler),
forceCompile = forcedMemories._1, forceSynflops = forcedMemories._2
) )
)) ))
) )