Files
chipyard/tapeout/src/main/scala/transforms/pads/PadAnnotations.scala
Angie Wang f1c437f830 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
2017-03-05 18:50:56 -08:00

133 lines
5.3 KiB
Scala

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]))
}
}
}