Add Pads + other utilities (#7)
[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
This commit is contained in:
133
tapeout/src/main/scala/transforms/pads/PadAnnotations.scala
Normal file
133
tapeout/src/main/scala/transforms/pads/PadAnnotations.scala
Normal file
@@ -0,0 +1,133 @@
|
||||
package barstools.tapeout.transforms.pads
|
||||
|
||||
import firrtl.annotations._
|
||||
import chisel3.experimental._
|
||||
import chisel3._
|
||||
import barstools.tapeout.transforms._
|
||||
import firrtl._
|
||||
|
||||
import net.jcazevedo.moultingyaml._
|
||||
|
||||
object PadAnnotationsYaml extends DefaultYamlProtocol {
|
||||
implicit val _iopad = yamlFormat2(IOPadAnnotation)
|
||||
implicit val _noiopad = yamlFormat1(NoIOPadAnnotation)
|
||||
implicit val _supplyanno = yamlFormat5(SupplyAnnotation)
|
||||
implicit val _modulepadanno = yamlFormat4(ModulePadAnnotation)
|
||||
}
|
||||
|
||||
abstract class FirrtlPadTransformAnnotation {
|
||||
def targetName: String
|
||||
}
|
||||
|
||||
// IO Port can either be annotated with padName + padSide OR noPad (mutually exclusive)
|
||||
abstract class IOAnnotation {
|
||||
def serialize: String
|
||||
}
|
||||
case class IOPadAnnotation(padSide: String, padName: String) extends IOAnnotation {
|
||||
import PadAnnotationsYaml._
|
||||
def serialize: String = this.toYaml.prettyPrint
|
||||
def getPadSide: PadSide = HasPadAnnotation.getSide(padSide)
|
||||
}
|
||||
case class NoIOPadAnnotation(noPad: String = "") extends IOAnnotation {
|
||||
import PadAnnotationsYaml._
|
||||
def serialize: String = this.toYaml.prettyPrint
|
||||
def field = "noPad:"
|
||||
}
|
||||
// Firrtl version
|
||||
case class TargetIOPadAnnoF(target: ComponentName, anno: IOAnnotation) extends FirrtlPadTransformAnnotation {
|
||||
def getAnno = Annotation(target, classOf[AddIOPadsTransform], anno.serialize)
|
||||
def targetName = target.name
|
||||
}
|
||||
// Chisel version
|
||||
case class TargetIOPadAnnoC(target: Element, anno: IOAnnotation) {
|
||||
def getAnno = ChiselAnnotation(target, classOf[AddIOPadsTransform], anno.serialize)
|
||||
}
|
||||
|
||||
// A bunch of supply pads (designated by name, # on each chip side) can be associated with the top module
|
||||
case class SupplyAnnotation(
|
||||
padName: String,
|
||||
leftSide: Int = 0,
|
||||
rightSide: Int = 0,
|
||||
topSide: Int = 0,
|
||||
bottomSide: Int = 0)
|
||||
// The chip top should have a default pad side, a pad template file, and supply annotations
|
||||
case class ModulePadAnnotation(
|
||||
defaultPadSide: String = Top.serialize,
|
||||
coreWidth: Int = 0,
|
||||
coreHeight: Int = 0,
|
||||
supplyAnnos: Seq[SupplyAnnotation] = Seq.empty) {
|
||||
import PadAnnotationsYaml._
|
||||
def serialize: String = this.toYaml.prettyPrint
|
||||
val supplyPadNames = supplyAnnos.map(_.padName)
|
||||
require(supplyPadNames.distinct.length == supplyPadNames.length, "Supply pads should only be specified once!")
|
||||
def getDefaultPadSide: PadSide = HasPadAnnotation.getSide(defaultPadSide)
|
||||
}
|
||||
// Firrtl version
|
||||
case class TargetModulePadAnnoF(target: ModuleName, anno: ModulePadAnnotation) extends FirrtlPadTransformAnnotation {
|
||||
def getAnno = Annotation(target, classOf[AddIOPadsTransform], anno.serialize)
|
||||
def targetName = target.name
|
||||
}
|
||||
// Chisel version
|
||||
case class TargetModulePadAnnoC(target: Module, anno: ModulePadAnnotation) {
|
||||
def getAnno = ChiselAnnotation(target, classOf[AddIOPadsTransform], anno.serialize)
|
||||
}
|
||||
|
||||
case class CollectedAnnos(
|
||||
componentAnnos: Seq[TargetIOPadAnnoF],
|
||||
moduleAnnos: TargetModulePadAnnoF) {
|
||||
def supplyAnnos = moduleAnnos.anno.supplyAnnos
|
||||
def defaultPadSide = moduleAnnos.anno.defaultPadSide
|
||||
def topModName = moduleAnnos.targetName
|
||||
def coreWidth = moduleAnnos.anno.coreWidth
|
||||
def coreHeight = moduleAnnos.anno.coreHeight
|
||||
}
|
||||
|
||||
object HasPadAnnotation {
|
||||
import PadAnnotationsYaml._
|
||||
|
||||
def getSide(a: String): PadSide = a match {
|
||||
case i if i == Left.serialize => Left
|
||||
case i if i == Right.serialize => Right
|
||||
case i if i == Top.serialize => Top
|
||||
case i if i == Bottom.serialize => Bottom
|
||||
case _ => throw new Exception(s" $a not a valid pad side annotation!")
|
||||
}
|
||||
|
||||
def unapply(a: Annotation): Option[FirrtlPadTransformAnnotation] = a match {
|
||||
case Annotation(f, t, s) if t == classOf[AddIOPadsTransform] => f match {
|
||||
case m: ModuleName =>
|
||||
Some(TargetModulePadAnnoF(m, s.parseYaml.convertTo[ModulePadAnnotation]))
|
||||
case c: ComponentName if s.contains(NoIOPadAnnotation().field) =>
|
||||
Some(TargetIOPadAnnoF(c, s.parseYaml.convertTo[NoIOPadAnnotation]))
|
||||
case c: ComponentName =>
|
||||
Some(TargetIOPadAnnoF(c, s.parseYaml.convertTo[IOPadAnnotation]))
|
||||
case _ => throw new Exception("Annotation only valid on module or component")
|
||||
}
|
||||
case _ => None
|
||||
}
|
||||
|
||||
def apply(annos: Seq[Annotation]): Option[CollectedAnnos] = {
|
||||
// Get all pad-related annotations (config files, pad sides, pad names, etc.)
|
||||
val padAnnos = annos.map(x => unapply(x)).flatten
|
||||
val targets = padAnnos.map(x => x.targetName)
|
||||
require(targets.distinct.length == targets.length, "Only 1 pad related annotation is allowed per component/module")
|
||||
if (padAnnos.length == 0) None
|
||||
else {
|
||||
val moduleAnnosTemp = padAnnos.filter {
|
||||
case TargetModulePadAnnoF(_, _) => true
|
||||
case _ => false
|
||||
}
|
||||
require(moduleAnnosTemp.length == 1, "Only 1 module may be designated 'Top'")
|
||||
val moduleAnnos = moduleAnnosTemp.head
|
||||
val topModName = moduleAnnos.targetName
|
||||
val componentAnnos = padAnnos.filter {
|
||||
case TargetIOPadAnnoF(ComponentName(_, ModuleName(n, _)), _) if n == topModName =>
|
||||
true
|
||||
case TargetIOPadAnnoF(ComponentName(_, ModuleName(n, _)), _) if n != topModName =>
|
||||
throw new Exception("Pad related component annotations must all be in the same top module")
|
||||
case _ => false
|
||||
}.map(x => x.asInstanceOf[TargetIOPadAnnoF])
|
||||
Some(CollectedAnnos(componentAnnos, moduleAnnos.asInstanceOf[TargetModulePadAnnoF]))
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user