Moved clkgen -> .clkgen and pads -> .pads
They no longer compile with the latest Chisel/FIRRTL, and may not be supported. However, future work will need them, so this keeps the files around but are ignored by sbt.
This commit is contained in:
134
tapeout/src/main/scala/transforms/.pads/AnnotatePortPads.scala
Normal file
134
tapeout/src/main/scala/transforms/.pads/AnnotatePortPads.scala
Normal file
@@ -0,0 +1,134 @@
|
||||
package barstools.tapeout.transforms.pads
|
||||
|
||||
import firrtl.annotations._
|
||||
import firrtl._
|
||||
import firrtl.ir._
|
||||
import barstools.tapeout.transforms._
|
||||
|
||||
// TODO: Make some trait with commonalities between IO Pad + supply pad
|
||||
|
||||
// Pads associated with IO Ports! (Not supplies!)
|
||||
case class PortIOPad(
|
||||
pad: Option[FoundryPad],
|
||||
padSide: PadSide,
|
||||
port: Port) {
|
||||
|
||||
def arrayInstNamePrefix(mod: String): String = Seq(mod, firrtlBBName, getPadName).mkString("/")
|
||||
def arrayInstNameSuffix: String = pad match {
|
||||
case None => throw new Exception("Port needs to use pad to get array instance name!")
|
||||
case Some(x) => "/" + x.padInstName
|
||||
}
|
||||
|
||||
def portName = port.name
|
||||
def portWidth = bitWidth(port.tpe).intValue
|
||||
def portDirection = port.direction
|
||||
def padOrientation = padSide.orientation
|
||||
def padType = pad match {
|
||||
case None => NoPad
|
||||
case Some(x) => x.padType
|
||||
}
|
||||
|
||||
def widthParamName = "WIDTH"
|
||||
def getPadName: String = pad match {
|
||||
case None => throw new Exception("Cannot get pad name when no pad specified!")
|
||||
case Some(x) => x.getName(portDirection, padOrientation)
|
||||
}
|
||||
def getPadArrayName: String = Seq(getPadName, "array").mkString("_")
|
||||
// Firrtl black box name must be unique, even though the parameterized Verilog modules don't
|
||||
// need to have separate names
|
||||
def firrtlBBName = Seq(getPadArrayName, portName).mkString("_")
|
||||
|
||||
// Note: This includes both the pad wrapper + an additional wrapper for n-bit wide to
|
||||
// multiple pad conversion!
|
||||
def createPadInline(): String = {
|
||||
// For blackboxing bit extraction/concatenation (with module arrays)
|
||||
def io(): String = padType match {
|
||||
case DigitalPad =>
|
||||
s"""| input [${widthParamName}-1:0] ${DigitalPad.inName},
|
||||
| output reg [${widthParamName}-1:0] ${DigitalPad.outName}""".stripMargin
|
||||
case AnalogPad =>
|
||||
s" inout [${widthParamName}-1:0] ${AnalogPad.ioName}"
|
||||
case _ => throw new Exception("IO pad can only be digital or analog")
|
||||
}
|
||||
def assignIO(): String = padType match {
|
||||
case DigitalPad =>
|
||||
s"""| .${DigitalPad.inName}(${DigitalPad.inName}),
|
||||
| .${DigitalPad.outName}(${DigitalPad.outName})""".stripMargin
|
||||
case AnalogPad =>
|
||||
s" .${AnalogPad.ioName}(${AnalogPad.ioName})"
|
||||
case _ => throw new Exception("IO pad can only be digital or analog")
|
||||
}
|
||||
def getPadVerilog(): String = pad match {
|
||||
case None => throw new Exception("Cannot get Verilog when no pad specified!")
|
||||
case Some(x) => x.getVerilog(portDirection, padOrientation)
|
||||
}
|
||||
s"""inline
|
||||
|${getPadArrayName}.v
|
||||
|${getPadVerilog}
|
||||
|module ${getPadArrayName} #(
|
||||
| parameter int ${widthParamName}=1
|
||||
|)(
|
||||
|${io}
|
||||
|);
|
||||
| ${getPadName} ${getPadName}[${widthParamName}-1:0](
|
||||
|${assignIO}
|
||||
| );
|
||||
|endmodule""".stripMargin
|
||||
}
|
||||
}
|
||||
|
||||
object AnnotatePortPads {
|
||||
def apply(
|
||||
c: Circuit,
|
||||
topMod: String,
|
||||
pads: Seq[FoundryPad],
|
||||
componentAnnos: Seq[TargetIOPadAnnoF],
|
||||
defaultSide: PadSide): Seq[PortIOPad] = {
|
||||
|
||||
def lowerAnnotations(): Seq[TargetIOPadAnnoF] = {
|
||||
componentAnnos map { x => x.target match {
|
||||
case c: ComponentName => x.copy(target = c.copy(name = LowerName(c.name)))
|
||||
case _ => throw new Exception("Not a component annotation! Can't lower!")
|
||||
}}
|
||||
}
|
||||
|
||||
// Make annotations match low form
|
||||
val annos = lowerAnnotations()
|
||||
|
||||
def getPortIOPad(port: Port): PortIOPad = {
|
||||
val portAnnos = annos.find(_.targetName == port.name)
|
||||
// Ports can only be digital or analog
|
||||
val padTypeRequired = port.tpe match {
|
||||
case AnalogType(_) => AnalogPad
|
||||
case _ => DigitalPad
|
||||
}
|
||||
val validPads = pads.filter(_.padType == padTypeRequired)
|
||||
require(validPads.length > 0, s"No ${padTypeRequired.serialize} pads specified in the config yaml file!")
|
||||
portAnnos match {
|
||||
case None =>
|
||||
// If no pad-related annotation is found on a port, use defaults based off of port type
|
||||
PortIOPad(Some(validPads.head), defaultSide, port)
|
||||
case Some(x) =>
|
||||
x.anno match {
|
||||
case NoIOPadAnnotation(_) =>
|
||||
// Some ports might not want attached pads
|
||||
PortIOPad(None, defaultSide, port)
|
||||
case IOPadAnnotation(padSide, padName) if padName.isEmpty =>
|
||||
// If no pad name is used, select the first valid pad based off of port type
|
||||
PortIOPad(Some(validPads.head), HasPadAnnotation.getSide(padSide), port)
|
||||
case IOPadAnnotation(padSide, padName) =>
|
||||
// If name doesn't match any provided -- maybe someone typoed?
|
||||
validPads.find(_.name == padName) match {
|
||||
case None =>
|
||||
throw new Exception(
|
||||
s"Pad name associated with ${port.name} doesn't match valid pad names. Did you typo?")
|
||||
case Some(x) =>
|
||||
PortIOPad(Some(x), HasPadAnnotation.getSide(padSide), port)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Top MUST be internal module
|
||||
c.modules.filter(_.name == topMod).head.ports.map(x => getPortIOPad(x))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user