Add MemConf and change MacroCompiler to use a conf file instead of MDF JSON
This commit is contained in:
@@ -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)
|
||||
|
||||
55
macros/src/main/scala/MemConf.scala
Normal file
55
macros/src/main/scala/MemConf.scala
Normal 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}")
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -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]) =>
|
||||
|
||||
Reference in New Issue
Block a user