Add MemConf and change MacroCompiler to use a conf file instead of MDF JSON

This commit is contained in:
John Wright
2019-02-11 22:54:01 -08:00
committed by John Wright
parent 79b8fd324b
commit 12842cb3a7
3 changed files with 135 additions and 5 deletions

View File

@@ -618,7 +618,7 @@ class MacroCompilerTransform extends Transform {
assert((forceCompile intersect forceSynflops).isEmpty, "Cannot have modules both forced to compile and synflops")
// 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]] = Utils.readConfFromPath(Some(memFile)) match {
case Some(x:Seq[mdf.macrolib.Macro]) =>
Some(Utils.filterForSRAM(Some(x)) getOrElse(List()) map {new Macro(_)})
case _ => None
@@ -701,7 +701,7 @@ object MacroCompiler extends App {
.map { case (_, cmd, description) => s" $cmd: $description" }
val usage: String = (Seq(
"Options:",
" -m, --macro-list: The set of macros to compile",
" -m, --macro-conf: The set of macros to compile in firrtl-generated conf format",
" -l, --library: The set of macros that have blackbox instances",
" -u, --use-compiler: Flag, whether to use the memory compiler defined in library",
" -v, --verilog: Verilog output",
@@ -717,7 +717,7 @@ object MacroCompiler extends App {
args: List[String]): (MacroParamMap, CostParamMap, ForcedMemories) =
args match {
case Nil => (map, costMap, forcedMemories)
case ("-m" | "--macro-list") :: value :: tail =>
case ("-m" | "--macro-conf") :: value :: tail =>
parseArgs(map + (Macros -> value), costMap, forcedMemories, tail)
case ("-l" | "--library") :: value :: tail =>
parseArgs(map + (Library -> value), costMap, forcedMemories, tail)
@@ -746,7 +746,7 @@ object MacroCompiler extends App {
def run(args: List[String]) {
val (params, costParams, forcedMemories) = parseArgs(Map[MacroParam, String](), Map[String, String](), (Set.empty, Set.empty), args)
try {
val macros = Utils.filterForSRAM(mdf.macrolib.Utils.readMDFFromPath(params.get(Macros))).get map (x => (new Macro(x)).blackbox)
val macros = Utils.filterForSRAM(Utils.readConfFromPath(params.get(Macros))).get map (x => (new Macro(x)).blackbox)
if (macros.nonEmpty) {
// Note: the last macro in the input list is (seemingly arbitrarily)

View File

@@ -0,0 +1,55 @@
// See LICENSE for license details.
package barstools.macros
import scala.util.matching._
sealed abstract class MemPort(val name: String) { override def toString = name }
case object ReadPort extends MemPort("read")
case object WritePort extends MemPort("write")
case object MaskWritePort extends MemPort("mwrite")
case object ReadWritePort extends MemPort("rw")
case object MaskReadWritePort extends MemPort("mrw")
object MemPort {
val all = Set(ReadPort, WritePort, MaskWritePort, ReadWritePort, MaskReadWritePort)
def apply(s: String): Option[MemPort] = MemPort.all.find(_.name == s)
def fromString(s: String): Seq[MemPort] = {
s.split(",").toSeq.map(MemPort.apply).map(_ match {
case Some(x) => x
case _ => throw new Exception(s"Error parsing MemPort string : ${s}")
})
}
}
// This is based on firrtl.passes.memlib.ConfWriter
// TODO standardize this in FIRRTL
case class MemConf(
name: String,
depth: Int,
width: Int,
ports: Seq[MemPort],
maskGranularity: Option[Int]
) {
private def portsStr = ports.map(_.name).mkString(",")
private def maskGranStr = maskGranularity.map((p) => s"mask_gran $p").getOrElse("")
override def toString() = s"name ${name} depth ${depth} width ${width} ports ${portsStr} ${maskGranStr} "
}
object MemConf {
val regex = raw"\s*name\s+(\w+)\s+depth\s+(\d+)\s+width\s+(\d+)\s+ports\s+([^\s]+)\s+(?:mask_gran\s+(\d+))?\s*".r
def fromString(s: String): Seq[MemConf] = {
s.split("\n").toSeq.map(_ match {
case MemConf.regex(name, depth, width, ports, maskGran) => MemConf(name, depth.toInt, width.toInt, MemPort.fromString(ports), Option(maskGran).map(_.toInt))
case _ => throw new Exception(s"Error parsing MemConf string : ${s}")
})
}
}

View File

@@ -7,7 +7,7 @@ import firrtl.ir._
import firrtl.PrimOps
import firrtl.Utils.{ceilLog2, BoolType}
import mdf.macrolib.{Constant, MacroPort, SRAMMacro}
import mdf.macrolib.{PolarizedPort, PortPolarity, ActiveLow, ActiveHigh, NegativeEdge, PositiveEdge}
import mdf.macrolib.{PolarizedPort, PortPolarity, ActiveLow, ActiveHigh, NegativeEdge, PositiveEdge, MacroExtraPort}
import java.io.File
import scala.language.implicitConversions
@@ -72,6 +72,81 @@ object Utils {
case _ => None
}
}
// This utility reads a conf in and returns MDF like mdf.macrolib.Utils.readMDFFromPath
def readConfFromPath(path: Option[String]): Option[Seq[mdf.macrolib.Macro]] = {
path.map((p) => Utils.readConfFromString(scala.io.Source.fromFile(p).mkString))
}
def readConfFromString(str: String): Seq[mdf.macrolib.Macro] = {
MemConf.fromString(str).map { m:MemConf =>
SRAMMacro(m.name, m.width, m.depth, "", Utils.portSpecToMacroPort(m.width, m.depth, m.maskGranularity, m.ports), Seq.empty[MacroExtraPort])
}
}
// This translates between two represenations of ports
def portSpecToMacroPort(width: Int, depth: Int, maskGran: Option[Int], ports: Seq[MemPort]): Seq[MacroPort] = {
var numR = 0
var numW = 0
var numRW = 0
ports.map { _ match {
case ReadPort => {
val portName = s"R${numR}"
numR += 1
MacroPort(
width=Some(width), depth=Some(depth),
address=PolarizedPort(s"${portName}_address", ActiveHigh),
clock=PolarizedPort(s"${portName}_clock", PositiveEdge),
readEnable=Some(PolarizedPort(s"${portName}_ren", ActiveHigh)),
output=Some(PolarizedPort(s"${portName}_data", ActiveHigh))
) }
case WritePort => {
val portName = s"W${numW}"
numW += 1
MacroPort(
width=Some(width), depth=Some(depth),
address=PolarizedPort(s"${portName}_address", ActiveHigh),
clock=PolarizedPort(s"${portName}_clock", PositiveEdge),
writeEnable=Some(PolarizedPort(s"${portName}_wen", ActiveHigh)),
input=Some(PolarizedPort(s"${portName}_data", ActiveHigh))
) }
case MaskWritePort => {
val portName = s"W${numW}"
numW += 1
MacroPort(
width=Some(width), depth=Some(depth),
address=PolarizedPort(s"${portName}_address", ActiveHigh),
clock=PolarizedPort(s"${portName}_clock", PositiveEdge),
writeEnable=Some(PolarizedPort(s"${portName}_wen", ActiveHigh)),
maskPort=Some(PolarizedPort(s"${portName}_mask", ActiveHigh)),
maskGran=maskGran,
input=Some(PolarizedPort(s"${portName}_data", ActiveHigh))
) }
case ReadWritePort => {
val portName = s"RW${numRW}"
numRW += 1
MacroPort(
width=Some(width), depth=Some(depth),
address=PolarizedPort(s"${portName}_address", ActiveHigh),
clock=PolarizedPort(s"${portName}_clock", PositiveEdge),
writeEnable=Some(PolarizedPort(s"${portName}_wen", ActiveHigh)),
readEnable=Some(PolarizedPort(s"${portName}_ren", ActiveHigh)),
input=Some(PolarizedPort(s"${portName}_wdata", ActiveHigh)),
output=Some(PolarizedPort(s"${portName}_rdata", ActiveHigh))
) }
case MaskReadWritePort => {
val portName = s"RW${numRW}"
numRW += 1
MacroPort(
width=Some(width), depth=Some(depth),
address=PolarizedPort(s"${portName}_address", ActiveHigh),
clock=PolarizedPort(s"${portName}_clock", PositiveEdge),
writeEnable=Some(PolarizedPort(s"${portName}_wen", ActiveHigh)),
readEnable=Some(PolarizedPort(s"${portName}_ren", ActiveHigh)),
maskPort=Some(PolarizedPort(s"${portName}_mask", ActiveHigh)),
maskGran=maskGran,
input=Some(PolarizedPort(s"${portName}_wdata", ActiveHigh)),
output=Some(PolarizedPort(s"${portName}_rdata", ActiveHigh))
) }
}}
}
def findSRAMCompiler(s: Option[Seq[mdf.macrolib.Macro]]): Option[mdf.macrolib.SRAMCompiler] = {
s match {
case Some(l:Seq[mdf.macrolib.Macro]) =>