add SynFlops

This commit is contained in:
Donggyu Kim
2017-07-05 12:46:58 -07:00
committed by edwardcwang
parent 4f5a9ae02e
commit 9e7c8dce3e
5 changed files with 479 additions and 34 deletions

View File

@@ -25,22 +25,10 @@ object MacroCompilerAnnotation {
}
}
class MacroCompilerPass(memFile: Option[File],
libFile: Option[File]) extends firrtl.passes.Pass {
require(memFile.isDefined)
private val mems: Option[Seq[Macro]] = readJSON(memFile) map (_ map (x => new Macro(x)))
private val libs: Option[Seq[Macro]] = readJSON(libFile) map (_ map (x => new Macro(x)))
class MacroCompilerPass(mems: Option[Seq[Macro]],
libs: Option[Seq[Macro]]) extends firrtl.passes.Pass {
def compile(mem: Macro, lib: Macro): Option[(Module, ExtModule)] = {
val pairedPorts = (
(mem.ports filter (p => p.inputName.isDefined && !p.outputName.isDefined)) ++ // write
(mem.ports filter (p => !p.inputName.isDefined && p.outputName.isDefined)) ++ // read
(mem.ports filter (p => p.inputName.isDefined && p.outputName.isDefined)) // read writers
) zip (
(lib.ports filter (p => p.inputName.isDefined && !p.outputName.isDefined)) ++ // write
(lib.ports filter (p => !p.inputName.isDefined && p.outputName.isDefined)) ++ // read
(lib.ports filter (p => p.inputName.isDefined && p.outputName.isDefined)) // read writers
)
val pairedPorts = mem.sortedPorts zip lib.sortedPorts
// Parallel mapping
val pairs = ArrayBuffer[(BigInt, BigInt)]()
@@ -74,7 +62,6 @@ class MacroCompilerPass(memFile: Option[File],
pairs += ((last, mem.width.toInt - 1))
// Serial mapping
val instType = BundleType(lib.ports flatMap (_.tpe.fields))
val stmts = ArrayBuffer[Statement]()
val selects = HashMap[String, Expression]()
val outputs = HashMap[String, ArrayBuffer[(Expression, Expression)]]()
@@ -93,7 +80,7 @@ class MacroCompilerPass(memFile: Option[File],
for ((off, i) <- (0 until mem.depth.toInt by lib.depth.toInt).zipWithIndex) {
for (j <- pairs.indices) {
val name = s"mem_${i}_${j}"
stmts += WDefInstance(NoInfo, name, lib.name, instType)
stmts += WDefInstance(NoInfo, name, lib.name, lib.tpe)
// connect extra ports
stmts ++= lib.extraPorts map { case (portName, portValue) =>
Connect(NoInfo, WSubField(WRef(name), portName), portValue)
@@ -109,12 +96,7 @@ class MacroCompilerPass(memFile: Option[File],
def andAddrMatch(e: Expression) = and(e, addrMatch)
val cats = ArrayBuffer[Expression]()
for (((low, high), j) <- pairs.zipWithIndex) {
val inst = WRef(s"mem_${i}_${j}", instType)
def invert(exp: Expression, polarity: Option[PortPolarity]) =
polarity match {
case Some(ActiveLow) | Some(NegativeEdge) => not(exp)
case _ => exp
}
val inst = WRef(s"mem_${i}_${j}", lib.tpe)
def connectPorts(mem: Expression,
lib: String,
@@ -344,10 +326,13 @@ class MacroCompilerTransform extends Transform {
def inputForm = HighForm
def outputForm = HighForm
def execute(state: CircuitState) = getMyAnnotations(state) match {
case Seq(MacroCompilerAnnotation(state.circuit.main, mem, lib, synflops)) =>
case Seq(MacroCompilerAnnotation(state.circuit.main, memFile, libFile, synflops)) =>
require(memFile.isDefined)
val mems: Option[Seq[Macro]] = readJSON(memFile) map (_ map (x => new Macro(x)))
val libs: Option[Seq[Macro]] = readJSON(libFile) map (_ map (x => new Macro(x)))
val transforms = Seq(
new MacroCompilerPass(mem, lib),
// TODO: Syn flops
new MacroCompilerPass(mems, libs),
new SynFlopsPass(synflops, libs getOrElse mems.get),
firrtl.passes.SplitExpressions
)
((transforms foldLeft state)((s, xform) => xform runTransform s))
@@ -359,7 +344,7 @@ class MacroCompiler extends Compiler {
def transforms =
Seq(new MacroCompilerTransform) ++
getLoweringTransforms(firrtl.HighForm, firrtl.LowForm) // ++
// Seq(new LowFirrtlOptimization) // Todo: This is dangerous...
// Seq(new LowFirrtlOptimization) // Todo: This is dangerous
}
object MacroCompiler extends App {

View File

@@ -0,0 +1,110 @@
// See LICENSE for license details.
package barstools.tapeout.transforms.macros
import firrtl._
import firrtl.ir._
import firrtl.Utils._
import firrtl.passes.MemPortUtils.{memPortField, memType}
import Utils._
class SynFlopsPass(synflops: Boolean, libs: Seq[Macro]) extends firrtl.passes.Pass {
lazy val libMods = (libs map { lib => lib.name -> {
val dataType = (lib.ports foldLeft (None: Option[BigInt]))((res, port) =>
(res, port.maskName) match {
case (_, None) =>
res
case (None, Some(_)) =>
Some(port.effectiveMaskGran)
case (Some(x), Some(_)) =>
assert(x == port.effectiveMaskGran)
res
}
) match {
case None => UIntType(IntWidth(lib.width))
case Some(gran) => VectorType(UIntType(IntWidth(gran)), (lib.width / gran).toInt)
}
val mem = DefMemory(
NoInfo,
"ram",
dataType,
lib.depth.toInt,
1, // writeLatency
0, // readLatency
(lib.readers ++ lib.readwriters).indices map (i => s"R_$i"),
(lib.writers ++ lib.readwriters).indices map (i => s"W_$i"),
Nil
)
val readConnects = (lib.readers ++ lib.readwriters).zipWithIndex flatMap { case (r, i) =>
val clock = invert(WRef(r.clockName), r.clockPolarity)
val address = invert(WRef(r.addressName), r.addressPolarity)
val enable = (r.chipEnableName, r.readEnableName) match {
case (Some(en), Some(re)) =>
and(invert(WRef(en), r.chipEnablePolarity),
invert(WRef(re), r.readEnablePolarity))
case (Some(en), None) => invert(WRef(en), r.chipEnablePolarity)
case (None, Some(re)) => invert(WRef(re), r.readEnablePolarity)
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 addrReg = WRef(s"R_${i}_addr_reg", r.AddrType, RegKind)
Seq(
DefRegister(NoInfo, addrReg.name, r.AddrType, clock, zero, addrReg),
Connect(NoInfo, memPortField(mem, s"R_$i", "clk"), clock),
Connect(NoInfo, memPortField(mem, s"R_$i", "addr"), addrReg),
Connect(NoInfo, memPortField(mem, s"R_$i", "en"), enable),
Connect(NoInfo, WRef(r.outputName.get), read),
Connect(NoInfo, addrReg, Mux(enable, address, addrReg, UnknownType))
)
}
val writeConnects = (lib.writers ++ lib.readwriters).zipWithIndex flatMap { case (w, i) =>
val clock = invert(WRef(w.clockName), w.clockPolarity)
val address = invert(WRef(w.addressName), w.addressPolarity)
val enable = (w.chipEnableName, w.writeEnableName) match {
case (Some(en), Some(we)) =>
and(invert(WRef(en), w.chipEnablePolarity),
invert(WRef(we), w.writeEnablePolarity))
case (Some(en), None) => invert(WRef(en), w.chipEnablePolarity)
case (None, Some(we)) => invert(WRef(we), w.writeEnablePolarity)
case (None, None) => zero // is it possible?
}
val mask = memPortField(mem, s"W_$i", "mask")
val data = memPortField(mem, s"W_$i", "data")
val write = invert(WRef(w.inputName.get), w.inputPolarity)
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.maskName.get), k))))
case _: UIntType =>
Seq(Connect(NoInfo, data, write), Connect(NoInfo, mask, one))
})
}
lib.module(Block(mem +: (readConnects ++ writeConnects)))
}}).toMap
def run(c: Circuit): Circuit = {
if (!synflops) c
else {
val circuit = c.copy(modules = (c.modules map (m => libMods getOrElse (m.name, m))))
// print(circuit.serialize)
circuit
}
}
}

View File

@@ -48,9 +48,9 @@ case class MacroPort(
width: BigInt,
depth: BigInt) {
val effectiveMaskGran = maskGran.getOrElse(width)
private val AddrType = UIntType(IntWidth(ceilLog2(depth) max 1))
private val DataType = UIntType(IntWidth(width))
private val MaskType = UIntType(IntWidth(width / effectiveMaskGran))
val AddrType = UIntType(IntWidth(ceilLog2(depth) max 1))
val DataType = UIntType(IntWidth(width))
val MaskType = UIntType(IntWidth(width / effectiveMaskGran))
val tpe = BundleType(Seq(
Field(clockName, Flip, ClockType),
Field(addressName, Flip, AddrType)) ++
@@ -93,6 +93,10 @@ class Macro(lib: Map[String, Any]) {
depth
)
}
val writers = ports filter (p => p.inputName.isDefined && !p.outputName.isDefined)
val readers = ports filter (p => !p.inputName.isDefined && p.outputName.isDefined)
val readwriters = ports filter (p => p.inputName.isDefined && p.outputName.isDefined)
val sortedPorts = writers ++ readers ++ readwriters
val extraPorts = lib get "extra ports" match {
case None => Nil
case Some(p) => p.asInstanceOf[List[_]] map { x =>
@@ -104,6 +108,7 @@ class Macro(lib: Map[String, Any]) {
(name -> UIntLiteral(value, IntWidth(width)))
}
}
val tpe = BundleType(ports flatMap (_.tpe.fields))
private val modPorts = (ports flatMap (_.ports)) ++
(extraPorts map { case (name, value) => Port(NoInfo, name, Input, value.tpe) })
val blackbox = ExtModule(NoInfo, name, modPorts, name, Nil)
@@ -140,4 +145,10 @@ object Utils {
else DoPrim(PrimOps.Cat, Seq(es.head, cat(es.tail)), Nil, UnknownType)
def not(e: Expression) =
DoPrim(PrimOps.Not, Seq(e), Nil, e.tpe)
def invert(exp: Expression, polarity: Option[PortPolarity]) =
polarity match {
case Some(ActiveLow) | Some(NegativeEdge) => not(exp)
case _ => exp
}
}