Files
chipyard/tapeout/src/main/scala/transforms/pads/FoundryPadsYaml.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

95 lines
3.8 KiB
Scala

package barstools.tapeout.transforms.pads
import net.jcazevedo.moultingyaml._
import firrtl._
import firrtl.ir._
import barstools.tapeout.transforms._
case class FoundryPad(
tpe: String,
name: String,
width: Int,
height: Int,
supplySetNum: Option[Int],
verilog: String) {
def padInstName = "PAD"
require(verilog.contains("{{#if isHorizontal}}"), "All pad templates must contain '{{#if isHorizontal}}'")
require(verilog.contains("{{name}}"), "All pad templates must contain module name '{{name}}'")
require(verilog.contains(padInstName), s"All pad templates should have instances called ${padInstName}")
def getSupplySetNum = supplySetNum.getOrElse(1)
val padType = tpe match {
case "digital" =>
require(verilog.contains(DigitalPad.inName), "Digital pad template must contain input called 'in'")
require(verilog.contains(DigitalPad.outName), "Digital pad template must contain output called 'out'")
require(verilog.contains("{{#if isInput}}"), "Digital pad template must contain '{{#if isInput}}'")
DigitalPad
case "analog" =>
require(verilog.contains(AnalogPad.ioName), "Analog pad template must contain inout called 'io'")
require(!verilog.contains("{{#if isInput}}"), "Analog pad template must not contain '{{#if isInput}}'")
AnalogPad
case "supply" =>
// Supply pads don't have IO
require(!verilog.contains("{{#if isInput}}"), "Supply pad template must not contain '{{#if isInput}}'")
require(
verilog.contains(s"${padInstName}["), "All supply pad templates should have instance arrays" +
" called ${padInstName}[n:0], where n = ${getSupplySetNum-1}")
require(supplySetNum.nonEmpty, "# of grouped supply pads 'supplySetNum' should be specified!")
SupplyPad
case _ => throw new Exception("Illegal pad type in config!")
}
import com.gilt.handlebars.scala.binding.dynamic._
import com.gilt.handlebars.scala.Handlebars
private val template = Handlebars(verilog)
// Make sure names don't have spaces in Verilog!
private[barstools] val correctedName = name.replace(" ", "_")
case class TemplateParams(
// isInput only used with digital pads
isInput: Boolean,
isHorizontal: Boolean) {
private val orient = if (isHorizontal) Horizontal.serialize else Vertical.serialize
private val dir = padType match {
case AnalogPad => InOut.serialize
case SupplyPad => NoDirection.serialize
case DigitalPad => if (isInput) Input.serialize else Output.serialize
}
val name = {
val start = Seq("pad", tpe, correctedName, orient)
if (padType == DigitalPad) start :+ dir
else start
}.mkString("_")
}
// Note: Analog + supply don't use direction
private def getTemplateParams(dir: Direction, orient: PadOrientation): TemplateParams =
TemplateParams(isInput = (dir == Input), isHorizontal = (orient == Horizontal))
def getVerilog(dir: Direction, orient: PadOrientation): String = {
val p = getTemplateParams(dir, orient)
template(p).stripMargin
}
def getName(dir: Direction, orient: PadOrientation): String = getTemplateParams(dir, orient).name
}
object FoundryPadsYaml extends DefaultYamlProtocol {
val exampleResource = "/FoundryPads.yaml"
implicit val _pad = yamlFormat6(FoundryPad)
def parse(techDir: String): Seq[FoundryPad] = {
val file = techDir + exampleResource
if(techDir != "" && !(new java.io.File(file)).exists())
throw new Exception("Technology directory must contain FoundryPads.yaml!")
val out = (new YamlFileReader(exampleResource)).parse[FoundryPad](if (techDir == "") "" else file)
val padNames = out.map(x => x.correctedName)
require(padNames.distinct.length == padNames.length, "Pad names must be unique!")
out
}
}