Files
chipyard/tapeout/src/main/scala/transforms/.pads/ChiselTopModule.scala
2020-02-18 14:56:17 -08:00

80 lines
3.4 KiB
Scala

package barstools.tapeout.transforms.pads
import chisel3._
import barstools.tapeout.transforms.clkgen._
import chisel3.experimental._
import firrtl.transforms.DedupModules
// TODO: Move out of pads
// NOTE: You can't really annotate outside of the module itself UNLESS you break up the compile step in 2 i.e.
// annotate post-Chisel but pre-Firrtl (unfortunate non-generator friendly downside).
// It's recommended to have a Tapeout specific TopModule wrapper.
// LIMITATION: All signals of a bus must be on the same chip side
// Chisel-y annotations
abstract class TopModule(
supplyAnnos: Seq[SupplyAnnotation] = Seq.empty,
defaultPadSide: PadSide = Top,
coreWidth: Int = 0,
coreHeight: Int = 0,
usePads: Boolean = true,
override_clock: Option[Clock] = None,
override_reset: Option[Bool] = None) extends Module with IsClkModule {
override_clock.foreach(clock := _)
override_reset.foreach(reset := _)
override def annotateClkPort(p: Element, anno: ClkPortAnnotation): Unit = {
DataMirror.directionOf(p) match {
case chisel3.core.ActualDirection.Input =>
require(anno.tag.nonEmpty, "Top Module input clks must be clk sinks")
require(anno.tag.get.src.nonEmpty,
"Top module input clks must have clk period, etc. specified")
case _ =>
throw new Exception("Clk port direction must be specified!")
}
p match {
case _: chisel3.core.Clock =>
case _ => throw new Exception("Clock port must be of type Clock")
}
annotate(TargetClkPortAnnoC(p, anno))
}
override def annotateDerivedClks(m: Module, anno: ClkModAnnotation): Unit =
throw new Exception("Top module cannot be pure clock module!")
// Annotate module as top module (that requires pad transform)
// Specify the yaml file that indicates how pads are templated,
// the default chip side that pads should be placed (if nothing is specified per IO),
// and supply annotations: supply pad name, location, and #
def createPads(): Unit = if (usePads) {
val modulePadAnnotation = ModulePadAnnotation(
defaultPadSide = defaultPadSide.serialize,
coreWidth = coreWidth,
coreHeight = coreHeight,
supplyAnnos = supplyAnnos
)
annotate(TargetModulePadAnnoC(this, modulePadAnnotation))
}
// Annotate IO with side + pad name
def annotatePad(sig: Element, side: PadSide = defaultPadSide, name: String = ""): Unit = if (usePads) {
val anno = IOPadAnnotation(side.serialize, name)
annotate(TargetIOPadAnnoC(sig, anno))
}
def annotatePad(sig: Aggregate, name: String): Unit = annotatePad(sig, side = defaultPadSide, name)
def annotatePad(sig: Aggregate, side: PadSide): Unit = annotatePad(sig, side, name = "")
def annotatePad(sig: Aggregate, side: PadSide, name: String): Unit =
extractElements(sig) foreach { x => annotatePad(x, side, name) }
// There may be cases where pads were inserted elsewhere. If that's the case, allow certain IO to
// not have pads auto added. Note that annotatePad and noPad are mutually exclusive!
def noPad(sig: Element): Unit = if (usePads) annotate(TargetIOPadAnnoC(sig, NoIOPadAnnotation()))
def noPad(sig: Aggregate): Unit = extractElements(sig) foreach { x => noPad(x) }
// Since this is a super class, this should be the first thing that gets run
// (at least when the module is actually at the top -- currently no guarantees otherwise :( firrtl limitation)
createPads()
}