[stevo]: adds a bunch of pad frame commits, as well as beginning work on clocking annotations and constraints * start add io pads pass * save progress adding yaml pad info * saving some semi-presentable work -- parses yaml for pad templates and associates templates with ports * added black boxes to the module; still need to hook up * added supply pad yaml example; added option to not include pad for an IO, blackboxed that cat + bit extraction functions * rewrite createbbs and some other parts of the transform * finally got blackboxhelper to work -- seems there was a typo in the firrtl pass (?) have not connected them up properly in the padframe * finished first version of pad transform; need to add bells and whistles + special case stuff * made a bunch of changes in firrtl to shorthand things * done with padframe for signals * started major refactoring; first of pad yaml stuff * forgot to update verilogTemplate -> verilog * rename ParsePadYaml -> ChipPadsYaml; moved some stuff * separated out stuff that describes pads i.e. direction, type, side * forgot to update import for yamlhelpers * trying to make the process of creating annotations more structured * saving annotation helpers but prob better to switch to yaml * saving changes -- reworking annotations * fixing some bugs; properly annotated ports with pads * annotate supply pads * lesson (re)learned. cleaned up constants * finished adding supply pads to pad frame; still need to generate io file * also committing updated transform; still without io file * big typo was causing pad verilog files not to be generated * verilator passes with transform; had to fix verilog bb typo * added unused pads; added more thorough tests + did visual inspection of output; made some port types more explicit * renamed files/classes to be clearer * started creating pad io template * update spec so that transform order matters * get rid of logger * went around in circles with blackboxhelper + way to annotate * finished adding + testing pad.io creation * starting clkgen pass -- made model for asynchronously reset clk divider + wrappers for programmatic bundling * temporarily locating albert's utility functions here * saving work on clk constraints * redid input config passing -- pass in tech directory instead; seems like getting clk sink, src, and relationship works * not done; need to pause to do tapeout-y things. the clk gen pass gets all the clks and their sources, but i need to build a proper graph to handle clks coming out of muxes
109 lines
4.4 KiB
Scala
109 lines
4.4 KiB
Scala
package barstools.tapeout.transforms.pads
|
|
|
|
import firrtl.annotations._
|
|
import firrtl._
|
|
import firrtl.ir._
|
|
import firrtl.transforms._
|
|
|
|
object CreatePadBBs {
|
|
|
|
private [barstools] case class UsedPadInfo(
|
|
// The following are found with both supply + io pads
|
|
padInline: String, // Verilog txt
|
|
padName: String, // Pad module name
|
|
padType: PadType, // Pad type: supply, analog, digital
|
|
// The following only affects io pads (due to using parameterized modules for bit extraction / cat)
|
|
padArrayName: String, // Name of parameterized pad wrapper (that does bit extract/cat)
|
|
firrtlBBName: String, // Unique Firrtl name of each parameterized pad wrapper
|
|
portWidth: Int // Port width for analog/digital
|
|
)
|
|
|
|
def convertToUsedPad(p: PortIOPad): UsedPadInfo = {
|
|
UsedPadInfo(
|
|
padInline = p.createPadInline,
|
|
padName = p.getPadName,
|
|
padType = p.padType,
|
|
padArrayName = p.getPadArrayName,
|
|
firrtlBBName = p.firrtlBBName,
|
|
portWidth = p.portWidth)
|
|
}
|
|
|
|
def convertToUsedPad(p: TopSupplyPad): UsedPadInfo = {
|
|
UsedPadInfo(
|
|
padInline = p.createPadInline,
|
|
padName = p.getPadName,
|
|
padType = p.padType,
|
|
// Supply pads don't require bit extraction / cat so don't care
|
|
padArrayName = p.getPadName,
|
|
firrtlBBName = p.getPadName,
|
|
portWidth = 0)
|
|
}
|
|
|
|
def checkLegalPadName(namespace: Namespace, usedPads: Seq[UsedPadInfo]): Unit = {
|
|
usedPads foreach { x =>
|
|
if (namespace contains x.padName)
|
|
throw new Exception(s"Pad name ${x.padName} already used!")
|
|
if (namespace contains x.padArrayName)
|
|
throw new Exception(s"Pad array ${x.padArrayName} name already used!")
|
|
if (namespace contains x.firrtlBBName)
|
|
throw new Exception(s"Firrtl black box ${x.firrtlBBName} name already used!")
|
|
}
|
|
}
|
|
|
|
def apply(
|
|
c: Circuit,
|
|
ioPads: Seq[PortIOPad],
|
|
supplyPads: Seq[TopSupplyPad]): (Circuit, Seq[Annotation]) = {
|
|
|
|
// Add black boxes for both supply + (used) io pads
|
|
val usedPads = ioPads.filter(x => x.pad.nonEmpty).map(convertToUsedPad(_)) ++ supplyPads.map(convertToUsedPad(_))
|
|
checkLegalPadName(Namespace(c), usedPads)
|
|
|
|
// Note that we need to check for Firrtl name uniqueness here! (due to parameterization)
|
|
val uniqueExtMods = scala.collection.mutable.ArrayBuffer[UsedPadInfo]()
|
|
usedPads foreach { x =>
|
|
if (uniqueExtMods.find(_.firrtlBBName == x.firrtlBBName).isEmpty)
|
|
uniqueExtMods += x
|
|
}
|
|
|
|
// Collecting unique parameterized black boxes
|
|
// (for io, they're wrapped pads; for supply, they're pad modules directly)
|
|
val uniqueParameterizedBBs = scala.collection.mutable.ArrayBuffer[UsedPadInfo]()
|
|
uniqueExtMods foreach { x =>
|
|
if (uniqueParameterizedBBs.find(_.padArrayName == x.padArrayName).isEmpty)
|
|
uniqueParameterizedBBs += x
|
|
}
|
|
|
|
// Note: Firrtl is silly and doesn't implement true parameterization -- each module with
|
|
// parameterization that potentially affects # of IO needs to be uniquely identified
|
|
// (but only in Firrtl)
|
|
val bbs = uniqueExtMods.map(x => {
|
|
// Supply pads don't have ports
|
|
val ports = x.padType match {
|
|
case AnalogPad => Seq(Port(NoInfo, AnalogPad.ioName, Input, AnalogType(IntWidth(x.portWidth))))
|
|
case DigitalPad => Seq(
|
|
Port(NoInfo, DigitalPad.inName, Input, UIntType(IntWidth(x.portWidth))),
|
|
Port(NoInfo, DigitalPad.outName, Output, UIntType(IntWidth(x.portWidth)))
|
|
)
|
|
case SupplyPad => Seq.empty
|
|
case _ => throw new Exception("Port pad type invalid!")
|
|
}
|
|
// Supply black boxes are not parameterized
|
|
val params = x.padType match {
|
|
case AnalogPad | DigitalPad => Seq(IntParam(ioPads.head.widthParamName, x.portWidth))
|
|
case SupplyPad => Seq()
|
|
case _ => throw new Exception("Port pad type invalid!")
|
|
}
|
|
// Firrtl name is unique
|
|
ExtModule(NoInfo, x.firrtlBBName, ports, x.padArrayName, params)
|
|
} ).toSeq
|
|
|
|
// Add annotations to black boxes to inline Verilog from template
|
|
// Again, note the weirdness in parameterization -- just need to hook to one matching Firrtl instance
|
|
val annos = uniqueParameterizedBBs.map(x =>
|
|
BlackBoxSourceAnnotation(ModuleName(x.firrtlBBName, CircuitName(c.main)), x.padInline)
|
|
).toSeq
|
|
(c.copy(modules = c.modules ++ bbs), annos)
|
|
}
|
|
|
|
} |