SRAM depth to bigint
max synflop depth support Fix annotation mangling on the harness side
This commit is contained in:
committed by
Colin Schmidt
parent
e548210ef4
commit
c23b2b6f84
@@ -126,9 +126,9 @@ object DefaultMetric extends CostMetric with CostMetricCompanion {
|
||||
}
|
||||
val depthCost = math.ceil(mem.src.depth.toDouble / lib.src.depth.toDouble)
|
||||
val widthCost = math.ceil(memWidth.toDouble / lib.src.width.toDouble)
|
||||
val bitsCost = (lib.src.depth * lib.src.width)
|
||||
val bitsCost = (lib.src.depth * lib.src.width).toDouble
|
||||
// Fraction of wasted bits plus const per mem
|
||||
val requestedBits = mem.src.depth * mem.src.width
|
||||
val requestedBits = (mem.src.depth * mem.src.width).toDouble
|
||||
val bitsWasted = depthCost*widthCost*bitsCost - requestedBits
|
||||
val wastedConst = 0.05 // 0 means waste as few bits with no regard for instance count
|
||||
val costPerInst = wastedConst*depthCost*widthCost
|
||||
|
||||
@@ -312,7 +312,7 @@ class MacroCompilerPass(mems: Option[Seq[Macro]],
|
||||
}
|
||||
}
|
||||
}
|
||||
for ((off, i) <- (0 until mem.src.depth by lib.src.depth).zipWithIndex) {
|
||||
for ((off, i) <- (BigInt(0).until(mem.src.depth, lib.src.depth)).zipWithIndex) {
|
||||
for (j <- bitPairs.indices) {
|
||||
val name = s"mem_${i}_${j}"
|
||||
// Create the instance.
|
||||
|
||||
@@ -30,7 +30,7 @@ object MemPort {
|
||||
// TODO standardize this in FIRRTL
|
||||
case class MemConf(
|
||||
name: String,
|
||||
depth: Int,
|
||||
depth: BigInt,
|
||||
width: Int,
|
||||
ports: Seq[MemPort],
|
||||
maskGranularity: Option[Int]
|
||||
@@ -51,7 +51,7 @@ object MemConf {
|
||||
Seq[MemConf]()
|
||||
} else {
|
||||
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 MemConf.regex(name, depth, width, ports, maskGran) => MemConf(name, BigInt(depth), width.toInt, MemPort.fromString(ports), Option(maskGran).map(_.toInt))
|
||||
case _ => throw new Exception(s"Error parsing MemConf string : ${s}")
|
||||
})
|
||||
}
|
||||
|
||||
@@ -9,8 +9,9 @@ import firrtl.passes.MemPortUtils.{memPortField, memType}
|
||||
import Utils._
|
||||
|
||||
class SynFlopsPass(synflops: Boolean, libs: Seq[Macro]) extends firrtl.passes.Pass {
|
||||
val extraMods = scala.collection.mutable.ArrayBuffer.empty[Module]
|
||||
lazy val libMods = (libs map { lib => lib.src.name -> {
|
||||
val dataType = (lib.src.ports foldLeft (None: Option[BigInt]))((res, port) =>
|
||||
val (dataType, dataWidth) = (lib.src.ports foldLeft (None: Option[BigInt]))((res, port) =>
|
||||
(res, port.maskPort) match {
|
||||
case (_, None) =>
|
||||
res
|
||||
@@ -21,23 +22,35 @@ class SynFlopsPass(synflops: Boolean, libs: Seq[Macro]) extends firrtl.passes.Pa
|
||||
res
|
||||
}
|
||||
) match {
|
||||
case None => UIntType(IntWidth(lib.src.width))
|
||||
case Some(gran) => VectorType(UIntType(IntWidth(gran)), (lib.src.width / gran).toInt)
|
||||
case None => (UIntType(IntWidth(lib.src.width)), lib.src.width)
|
||||
case Some(gran) => (UIntType(IntWidth(gran)), gran.intValue)
|
||||
}
|
||||
|
||||
val maxDepth = min(lib.src.depth, 1<<26)
|
||||
val numMems = lib.src.depth / maxDepth
|
||||
|
||||
// Change macro to be mapped onto to look like the below mem
|
||||
// by changing its depth, and width
|
||||
val lib_macro = new Macro(lib.src.copy(name="split_"+lib.src.name,
|
||||
depth = maxDepth, width = dataWidth, ports = lib.src.ports.map(p =>
|
||||
p.copy(width = p.width.map(_ => dataWidth), depth = p.depth.map(_ => maxDepth),
|
||||
maskGran = p.maskGran.map(_ => dataWidth)))))
|
||||
val mod_macro = (new MacroCompilerPass(None,None,None,None)).compile(lib, lib_macro)
|
||||
val (real_mod, real_macro) = mod_macro.get
|
||||
|
||||
val mem = DefMemory(
|
||||
NoInfo,
|
||||
"ram",
|
||||
dataType,
|
||||
lib.src.depth,
|
||||
maxDepth,
|
||||
1, // writeLatency
|
||||
1, // readLatency. This is possible because of VerilogMemDelays
|
||||
lib.readers.indices map (i => s"R_$i"),
|
||||
lib.writers.indices map (i => s"W_$i"),
|
||||
lib.readwriters.indices map (i => s"RW_$i")
|
||||
real_macro.readers.indices map (i => s"R_$i"),
|
||||
real_macro.writers.indices map (i => s"W_$i"),
|
||||
real_macro.readwriters.indices map (i => s"RW_$i")
|
||||
)
|
||||
|
||||
val readConnects = lib.readers.zipWithIndex flatMap { case (r, i) =>
|
||||
val readConnects = real_macro.readers.zipWithIndex flatMap { case (r, i) =>
|
||||
val clock = portToExpression(r.src.clock.get)
|
||||
val address = portToExpression(r.src.address)
|
||||
val enable = (r.src chipEnable, r.src readEnable) match {
|
||||
@@ -49,11 +62,7 @@ class SynFlopsPass(synflops: Boolean, libs: Seq[Macro]) extends firrtl.passes.Pa
|
||||
case (None, None) => one
|
||||
}
|
||||
val data = memPortField(mem, s"R_$i", "data")
|
||||
val read = (dataType: @unchecked) match {
|
||||
case VectorType(tpe, size) => cat(((0 until size) map (k =>
|
||||
WSubIndex(data, k, tpe, UNKNOWNGENDER))).reverse)
|
||||
case _: UIntType => data
|
||||
}
|
||||
val read = data
|
||||
Seq(
|
||||
Connect(NoInfo, memPortField(mem, s"R_$i", "clk"), clock),
|
||||
Connect(NoInfo, memPortField(mem, s"R_$i", "addr"), address),
|
||||
@@ -62,7 +71,7 @@ class SynFlopsPass(synflops: Boolean, libs: Seq[Macro]) extends firrtl.passes.Pa
|
||||
)
|
||||
}
|
||||
|
||||
val writeConnects = lib.writers.zipWithIndex flatMap { case (w, i) =>
|
||||
val writeConnects = real_macro.writers.zipWithIndex flatMap { case (w, i) =>
|
||||
val clock = portToExpression(w.src.clock.get)
|
||||
val address = portToExpression(w.src.address)
|
||||
val enable = (w.src.chipEnable, w.src.writeEnable) match {
|
||||
@@ -73,34 +82,32 @@ class SynFlopsPass(synflops: Boolean, libs: Seq[Macro]) extends firrtl.passes.Pa
|
||||
case (None, Some(we)) => portToExpression(we)
|
||||
case (None, None) => zero // is it possible?
|
||||
}
|
||||
val mask = memPortField(mem, s"W_$i", "mask")
|
||||
val mask = w.src.maskPort match {
|
||||
case Some(m) => portToExpression(m)
|
||||
case None => one
|
||||
}
|
||||
val data = memPortField(mem, s"W_$i", "data")
|
||||
val write = portToExpression(w.src.input.get)
|
||||
Seq(
|
||||
Connect(NoInfo, memPortField(mem, s"W_$i", "clk"), clock),
|
||||
Connect(NoInfo, memPortField(mem, s"W_$i", "addr"), address),
|
||||
Connect(NoInfo, memPortField(mem, s"W_$i", "en"), enable)
|
||||
) ++ (dataType match {
|
||||
case VectorType(tpe, size) =>
|
||||
val width = bitWidth(tpe).toInt
|
||||
((0 until size) map (k =>
|
||||
Connect(NoInfo, WSubIndex(data, k, tpe, UNKNOWNGENDER),
|
||||
bits(write, (k + 1) * width - 1, k * width)))) ++
|
||||
((0 until size) map (k =>
|
||||
Connect(NoInfo, WSubIndex(mask, k, BoolType, UNKNOWNGENDER),
|
||||
bits(WRef(w.src.maskPort.get.name), k))))
|
||||
case _: UIntType =>
|
||||
Seq(Connect(NoInfo, data, write), Connect(NoInfo, mask, one))
|
||||
})
|
||||
Connect(NoInfo, memPortField(mem, s"W_$i", "en"), enable),
|
||||
Connect(NoInfo, memPortField(mem, s"W_$i", "mask"), mask),
|
||||
Connect(NoInfo, data, write)
|
||||
)
|
||||
}
|
||||
|
||||
val readwriteConnects = lib.readwriters.zipWithIndex flatMap { case (rw, i) =>
|
||||
val readwriteConnects = real_macro.readwriters.zipWithIndex flatMap { case (rw, i) =>
|
||||
val clock = portToExpression(rw.src.clock.get)
|
||||
val address = portToExpression(rw.src.address)
|
||||
val wmode = rw.src.writeEnable match {
|
||||
case Some(we) => portToExpression(we)
|
||||
case None => zero // is it possible?
|
||||
}
|
||||
val wmask = rw.src.maskPort match {
|
||||
case Some(wm) => portToExpression(wm)
|
||||
case None => one
|
||||
}
|
||||
val enable = (rw.src.chipEnable, rw.src.readEnable) match {
|
||||
case (Some(en), Some(re)) =>
|
||||
and(portToExpression(en), or(portToExpression(re), wmode))
|
||||
@@ -108,40 +115,27 @@ class SynFlopsPass(synflops: Boolean, libs: Seq[Macro]) extends firrtl.passes.Pa
|
||||
case (None, Some(re)) => or(portToExpression(re), wmode)
|
||||
case (None, None) => one
|
||||
}
|
||||
val wmask = memPortField(mem, s"RW_$i", "wmask")
|
||||
val wdata = memPortField(mem, s"RW_$i", "wdata")
|
||||
val rdata = memPortField(mem, s"RW_$i", "rdata")
|
||||
val write = portToExpression(rw.src.input.get)
|
||||
val read = (dataType: @unchecked) match {
|
||||
case VectorType(tpe, size) => cat(((0 until size) map (k =>
|
||||
WSubIndex(rdata, k, tpe, UNKNOWNGENDER))).reverse)
|
||||
case _: UIntType => rdata
|
||||
}
|
||||
val read = rdata
|
||||
Seq(
|
||||
Connect(NoInfo, memPortField(mem, s"RW_$i", "clk"), clock),
|
||||
Connect(NoInfo, memPortField(mem, s"RW_$i", "addr"), address),
|
||||
Connect(NoInfo, memPortField(mem, s"RW_$i", "en"), enable),
|
||||
Connect(NoInfo, memPortField(mem, s"RW_$i", "wmode"), wmode),
|
||||
Connect(NoInfo, WRef(rw.src.output.get.name), read)
|
||||
) ++ (dataType match {
|
||||
case VectorType(tpe, size) =>
|
||||
val width = bitWidth(tpe).toInt
|
||||
((0 until size) map (k =>
|
||||
Connect(NoInfo, WSubIndex(wdata, k, tpe, UNKNOWNGENDER),
|
||||
bits(write, (k + 1) * width - 1, k * width)))) ++
|
||||
((0 until size) map (k =>
|
||||
Connect(NoInfo, WSubIndex(wmask, k, BoolType, UNKNOWNGENDER),
|
||||
bits(WRef(rw.src.maskPort.get.name), k))))
|
||||
case _: UIntType =>
|
||||
Seq(Connect(NoInfo, wdata, write), Connect(NoInfo, wmask, one))
|
||||
})
|
||||
Connect(NoInfo, memPortField(mem, s"RW_$i", "wmask"), wmask),
|
||||
Connect(NoInfo, WRef(rw.src.output.get.name), read),
|
||||
Connect(NoInfo, wdata, write)
|
||||
)
|
||||
}
|
||||
|
||||
lib.module(Block(mem +: (readConnects ++ writeConnects ++ readwriteConnects)))
|
||||
extraMods.append(real_macro.module(Block(mem +: (readConnects ++ writeConnects ++ readwriteConnects))))
|
||||
real_mod
|
||||
}}).toMap
|
||||
|
||||
def run(c: Circuit): Circuit = {
|
||||
if (!synflops) c
|
||||
else c.copy(modules = (c.modules map (m => libMods getOrElse (m.name, m))))
|
||||
else c.copy(modules = (c.modules map (m => libMods.getOrElse(m.name, m))) ++ extraMods)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,7 +91,7 @@ object Utils {
|
||||
return numRStr + numWStr + numRWStr
|
||||
}
|
||||
// This translates between two represenations of ports
|
||||
def portSpecToMacroPort(width: Int, depth: Int, maskGran: Option[Int], ports: Seq[MemPort]): Seq[MacroPort] = {
|
||||
def portSpecToMacroPort(width: Int, depth: BigInt, maskGran: Option[Int], ports: Seq[MemPort]): Seq[MacroPort] = {
|
||||
var numR = 0
|
||||
var numW = 0
|
||||
var numRW = 0
|
||||
@@ -103,7 +103,7 @@ object Utils {
|
||||
width=Some(width), depth=Some(depth),
|
||||
address=PolarizedPort(s"${portName}_addr", ActiveHigh),
|
||||
clock=Some(PolarizedPort(s"${portName}_clk", PositiveEdge)),
|
||||
chipEnable=Some(PolarizedPort(s"${portName}_en", ActiveHigh)),
|
||||
readEnable=Some(PolarizedPort(s"${portName}_en", ActiveHigh)),
|
||||
output=Some(PolarizedPort(s"${portName}_data", ActiveHigh))
|
||||
) }
|
||||
case WritePort => {
|
||||
|
||||
Reference in New Issue
Block a user