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")
|
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]] = Utils.readConfFromPath(Some(memFile)) match {
|
||||||
case Some(x:Seq[mdf.macrolib.Macro]) =>
|
case Some(x:Seq[mdf.macrolib.Macro]) =>
|
||||||
Some(Utils.filterForSRAM(Some(x)) getOrElse(List()) map {new Macro(_)})
|
Some(Utils.filterForSRAM(Some(x)) getOrElse(List()) map {new Macro(_)})
|
||||||
case _ => None
|
case _ => None
|
||||||
@@ -701,7 +701,7 @@ object MacroCompiler extends App {
|
|||||||
.map { case (_, cmd, description) => s" $cmd: $description" }
|
.map { case (_, cmd, description) => s" $cmd: $description" }
|
||||||
val usage: String = (Seq(
|
val usage: String = (Seq(
|
||||||
"Options:",
|
"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",
|
" -l, --library: The set of macros that have blackbox instances",
|
||||||
" -u, --use-compiler: Flag, whether to use the memory compiler defined in library",
|
" -u, --use-compiler: Flag, whether to use the memory compiler defined in library",
|
||||||
" -v, --verilog: Verilog output",
|
" -v, --verilog: Verilog output",
|
||||||
@@ -717,7 +717,7 @@ object MacroCompiler extends App {
|
|||||||
args: List[String]): (MacroParamMap, CostParamMap, ForcedMemories) =
|
args: List[String]): (MacroParamMap, CostParamMap, ForcedMemories) =
|
||||||
args match {
|
args match {
|
||||||
case Nil => (map, costMap, forcedMemories)
|
case Nil => (map, costMap, forcedMemories)
|
||||||
case ("-m" | "--macro-list") :: value :: tail =>
|
case ("-m" | "--macro-conf") :: value :: tail =>
|
||||||
parseArgs(map + (Macros -> value), costMap, forcedMemories, tail)
|
parseArgs(map + (Macros -> value), costMap, forcedMemories, tail)
|
||||||
case ("-l" | "--library") :: value :: tail =>
|
case ("-l" | "--library") :: value :: tail =>
|
||||||
parseArgs(map + (Library -> value), costMap, forcedMemories, tail)
|
parseArgs(map + (Library -> value), costMap, forcedMemories, tail)
|
||||||
@@ -746,7 +746,7 @@ object MacroCompiler extends App {
|
|||||||
def run(args: List[String]) {
|
def run(args: List[String]) {
|
||||||
val (params, costParams, forcedMemories) = parseArgs(Map[MacroParam, String](), Map[String, String](), (Set.empty, Set.empty), 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(Utils.readConfFromPath(params.get(Macros))).get map (x => (new Macro(x)).blackbox)
|
||||||
|
|
||||||
if (macros.nonEmpty) {
|
if (macros.nonEmpty) {
|
||||||
// Note: the last macro in the input list is (seemingly arbitrarily)
|
// 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.PrimOps
|
||||||
import firrtl.Utils.{ceilLog2, BoolType}
|
import firrtl.Utils.{ceilLog2, BoolType}
|
||||||
import mdf.macrolib.{Constant, MacroPort, SRAMMacro}
|
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 java.io.File
|
||||||
import scala.language.implicitConversions
|
import scala.language.implicitConversions
|
||||||
|
|
||||||
@@ -72,6 +72,81 @@ object Utils {
|
|||||||
case _ => None
|
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] = {
|
def findSRAMCompiler(s: Option[Seq[mdf.macrolib.Macro]]): Option[mdf.macrolib.SRAMCompiler] = {
|
||||||
s match {
|
s match {
|
||||||
case Some(l:Seq[mdf.macrolib.Macro]) =>
|
case Some(l:Seq[mdf.macrolib.Macro]) =>
|
||||||
|
|||||||
Reference in New Issue
Block a user