Update to chisel 3.2.x

This commit is contained in:
Colin Schmidt
2020-02-18 14:56:17 -08:00
parent 5198b3883c
commit 7de4c478c3
9 changed files with 124 additions and 122 deletions

View File

@@ -52,12 +52,12 @@ class AddIOPadsTransform extends Transform with SeqTransformBased {
)
// Expects BlackBox helper to be run after to inline pad Verilog!
val ret = runTransforms(state)
val currentAnnos = ret.annotations.getOrElse(AnnotationMap(Seq.empty)).annotations
val newAnnoMap = AnnotationMap(currentAnnos ++ bbAnnotations)
val newState = CircuitState(ret.circuit, outputForm, Some(newAnnoMap), ret.renames)
val currentAnnos = ret.annotations
val newAnnoMap = AnnotationSeq(currentAnnos ++ bbAnnotations)
val newState = CircuitState(ret.circuit, outputForm, newAnnoMap, ret.renames)
// TODO: *.f file is overwritten on subsequent executions, but it doesn't seem to be used anywhere?
(new firrtl.transforms.BlackBoxSourceHelper).execute(newState)
}
}
}
}

View File

@@ -22,13 +22,13 @@ case class TopSupplyPad(
require(pad.padType == SupplyPad)
def padOrientation = padSide.orientation
def getPadName = pad.getName(NoDirection, padOrientation)
def getPadName = pad.getName(Output/*Should be None*/, padOrientation)
def firrtlBBName = getPadName
private def instNamePrefix = Seq(firrtlBBName, padSide.serialize).mkString("_")
def instNames = (0 until num).map(i => Seq(instNamePrefix, i.toString).mkString("_"))
def createPadInline(): String = {
def getPadVerilog(): String = pad.getVerilog(NoDirection, padOrientation)
def getPadVerilog(): String = pad.getVerilog(Output/*Should be None*/, padOrientation)
s"""inline
|${getPadName}.v
|${getPadVerilog}""".stripMargin
@@ -37,14 +37,14 @@ case class TopSupplyPad(
object AnnotateSupplyPads {
def apply(
pads: Seq[FoundryPad],
pads: Seq[FoundryPad],
supplyAnnos: Seq[SupplyAnnotation]
): Seq[TopSupplyPad] = {
supplyAnnos.map( a =>
supplyAnnos.map( a =>
pads.find(_.name == a.padName) match {
case None =>
case None =>
throw new Exception(s"Supply pad ${a.padName} not found in Yaml file!")
case Some(x) =>
case Some(x) =>
Seq(
TopSupplyPad(x, Left, a.leftSide),
TopSupplyPad(x, Right, a.rightSide),
@@ -53,4 +53,4 @@ object AnnotateSupplyPads {
}
).flatten.filter(_.num > 0)
}
}
}

View File

@@ -8,8 +8,8 @@ import firrtl.transforms.DedupModules
// TODO: Move out of pads
// NOTE: You can't really annotate outside of the module itself UNLESS you break up the compile step in 2 i.e.
// annotate post-Chisel but pre-Firrtl (unfortunate non-generator friendly downside).
// It's recommended to have a Tapeout specific TopModule wrapper.
// annotate post-Chisel but pre-Firrtl (unfortunate non-generator friendly downside).
// It's recommended to have a Tapeout specific TopModule wrapper.
// LIMITATION: All signals of a bus must be on the same chip side
// Chisel-y annotations
@@ -19,14 +19,17 @@ abstract class TopModule(
coreWidth: Int = 0,
coreHeight: Int = 0,
usePads: Boolean = true,
override_clock: Option[Clock] = None,
override_reset: Option[Bool] = None) extends Module(override_clock, override_reset) with IsClkModule {
override_clock: Option[Clock] = None,
override_reset: Option[Bool] = None) extends Module with IsClkModule {
override_clock.foreach(clock := _)
override_reset.foreach(reset := _)
override def annotateClkPort(p: Element, anno: ClkPortAnnotation): Unit = {
p.dir match {
case chisel3.core.Direction.Input =>
DataMirror.directionOf(p) match {
case chisel3.core.ActualDirection.Input =>
require(anno.tag.nonEmpty, "Top Module input clks must be clk sinks")
require(anno.tag.get.src.nonEmpty,
require(anno.tag.get.src.nonEmpty,
"Top module input clks must have clk period, etc. specified")
case _ =>
throw new Exception("Clk port direction must be specified!")
@@ -35,10 +38,10 @@ abstract class TopModule(
case _: chisel3.core.Clock =>
case _ => throw new Exception("Clock port must be of type Clock")
}
annotate(TargetClkPortAnnoC(p, anno).getAnno)
annotate(TargetClkPortAnnoC(p, anno))
}
override def annotateDerivedClks(m: Module, anno: ClkModAnnotation): Unit =
override def annotateDerivedClks(m: Module, anno: ClkModAnnotation): Unit =
throw new Exception("Top module cannot be pure clock module!")
// Annotate module as top module (that requires pad transform)
@@ -52,25 +55,25 @@ abstract class TopModule(
coreHeight = coreHeight,
supplyAnnos = supplyAnnos
)
annotate(TargetModulePadAnnoC(this, modulePadAnnotation).getAnno)
annotate(TargetModulePadAnnoC(this, modulePadAnnotation))
}
// Annotate IO with side + pad name
def annotatePad(sig: Element, side: PadSide = defaultPadSide, name: String = ""): Unit = if (usePads) {
val anno = IOPadAnnotation(side.serialize, name)
annotate(TargetIOPadAnnoC(sig, anno).getAnno)
annotate(TargetIOPadAnnoC(sig, anno))
}
def annotatePad(sig: Aggregate, name: String): Unit = annotatePad(sig, side = defaultPadSide, name)
def annotatePad(sig: Aggregate, side: PadSide): Unit = annotatePad(sig, side, name = "")
def annotatePad(sig: Aggregate, side: PadSide, name: String): Unit =
def annotatePad(sig: Aggregate, side: PadSide, name: String): Unit =
extractElements(sig) foreach { x => annotatePad(x, side, name) }
// There may be cases where pads were inserted elsewhere. If that's the case, allow certain IO to
// not have pads auto added. Note that annotatePad and noPad are mutually exclusive!
def noPad(sig: Element): Unit = if (usePads) annotate(TargetIOPadAnnoC(sig, NoIOPadAnnotation()).getAnno)
// There may be cases where pads were inserted elsewhere. If that's the case, allow certain IO to
// not have pads auto added. Note that annotatePad and noPad are mutually exclusive!
def noPad(sig: Element): Unit = if (usePads) annotate(TargetIOPadAnnoC(sig, NoIOPadAnnotation()))
def noPad(sig: Aggregate): Unit = extractElements(sig) foreach { x => noPad(x) }
// Since this is a super class, this should be the first thing that gets run
// Since this is a super class, this should be the first thing that gets run
// (at least when the module is actually at the top -- currently no guarantees otherwise :( firrtl limitation)
createPads()
}
}

View File

@@ -40,7 +40,7 @@ object CreatePadBBs {
}
def checkLegalPadName(namespace: Namespace, usedPads: Seq[UsedPadInfo]): Unit = {
usedPads foreach { x =>
usedPads foreach { x =>
if (namespace contains x.padName)
throw new Exception(s"Pad name ${x.padName} already used!")
if (namespace contains x.padArrayName)
@@ -61,21 +61,21 @@ object CreatePadBBs {
// Note that we need to check for Firrtl name uniqueness here! (due to parameterization)
val uniqueExtMods = scala.collection.mutable.ArrayBuffer[UsedPadInfo]()
usedPads foreach { x =>
usedPads foreach { x =>
if (uniqueExtMods.find(_.firrtlBBName == x.firrtlBBName).isEmpty)
uniqueExtMods += x
}
// Collecting unique parameterized black boxes
// 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 =>
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
// 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
@@ -100,10 +100,10 @@ object CreatePadBBs {
// 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)
val annos = uniqueParameterizedBBs.map(x =>
BlackBoxInlineAnno(ModuleName(x.firrtlBBName, CircuitName(c.main)), x.firrtlBBName, x.padInline)
).toSeq
(c.copy(modules = c.modules ++ bbs), annos)
}
}
}

View File

@@ -7,11 +7,11 @@ import firrtl.ir._
import barstools.tapeout.transforms._
case class FoundryPad(
tpe: String,
name: String,
width: Int,
tpe: String,
name: String,
width: Int,
height: Int,
supplySetNum: Option[Int],
supplySetNum: Option[Int],
verilog: String) {
def padInstName = "PAD"
@@ -23,16 +23,16 @@ case class FoundryPad(
def getSupplySetNum = supplySetNum.getOrElse(1)
val padType = tpe match {
case "digital" =>
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" =>
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" =>
case "supply" =>
// Supply pads don't have IO
require(!verilog.contains("{{#if isInput}}"), "Supply pad template must not contain '{{#if isInput}}'")
require(
@@ -57,8 +57,8 @@ case class FoundryPad(
private val orient = if (isHorizontal) Horizontal.serialize else Vertical.serialize
private val dir = padType match {
case AnalogPad => InOut.serialize
case SupplyPad => NoDirection.serialize
case AnalogPad => "inout"
case SupplyPad => "none"
case DigitalPad => if (isInput) Input.serialize else Output.serialize
}
val name = {
@@ -69,7 +69,7 @@ case class FoundryPad(
}
// Note: Analog + supply don't use direction
private def getTemplateParams(dir: Direction, orient: PadOrientation): TemplateParams =
private def getTemplateParams(dir: Direction, orient: PadOrientation): TemplateParams =
TemplateParams(isInput = (dir == Input), isHorizontal = (orient == Horizontal))
def getVerilog(dir: Direction, orient: PadOrientation): String = {
@@ -85,11 +85,11 @@ object FoundryPadsYaml extends DefaultYamlProtocol {
implicit val _pad = yamlFormat6(FoundryPad)
def parse(techDir: String): Seq[FoundryPad] = {
val file = techDir + exampleResource
if(techDir != "" && !(new java.io.File(file)).exists())
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
}
}
}

View File

@@ -21,7 +21,7 @@ abstract class FirrtlPadTransformAnnotation {
// IO Port can either be annotated with padName + padSide OR noPad (mutually exclusive)
abstract class IOAnnotation {
def serialize: String
def serialize: String
}
case class IOPadAnnotation(padSide: String, padName: String) extends IOAnnotation {
import PadAnnotationsYaml._
@@ -31,29 +31,30 @@ case class IOPadAnnotation(padSide: String, padName: String) extends IOAnnotatio
case class NoIOPadAnnotation(noPad: String = "") extends IOAnnotation {
import PadAnnotationsYaml._
def serialize: String = this.toYaml.prettyPrint
def field = "noPad:"
def field = "noPad:"
}
// Firrtl version
case class TargetIOPadAnnoF(target: ComponentName, anno: IOAnnotation) extends FirrtlPadTransformAnnotation {
case class TargetIOPadAnnoF(target: ComponentName, anno: IOAnnotation) extends FirrtlPadTransformAnnotation with SingleTargetAnnotation[ComponentName] {
def duplicate(n: ComponentName): TargetIOPadAnnoF = this.copy(target = n)
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)
case class TargetIOPadAnnoC(target: Element, anno: IOAnnotation) extends ChiselAnnotation {
def toFirrtl = TargetIOPadAnnoF(target.toNamed, anno)
}
// 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,
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,
defaultPadSide: String = Top.serialize,
coreWidth: Int = 0,
coreHeight: Int = 0,
supplyAnnos: Seq[SupplyAnnotation] = Seq.empty) {
import PadAnnotationsYaml._
@@ -63,13 +64,14 @@ case class ModulePadAnnotation(
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)
case class TargetModulePadAnnoF(target: ModuleName, anno: ModulePadAnnotation) extends FirrtlPadTransformAnnotation with SingleTargetAnnotation[ModuleName] {
def duplicate(n: ModuleName): TargetModulePadAnnoF = this.copy(target = n)
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 TargetModulePadAnnoC(target: Module, anno: ModulePadAnnotation) extends ChiselAnnotation {
def toFirrtl = TargetModulePadAnnoF(target.toNamed, anno)
}
case class CollectedAnnos(
@@ -95,9 +97,9 @@ object HasPadAnnotation {
def unapply(a: Annotation): Option[FirrtlPadTransformAnnotation] = a match {
case Annotation(f, t, s) if t == classOf[AddIOPadsTransform] => f match {
case m: ModuleName =>
case m: ModuleName =>
Some(TargetModulePadAnnoF(m, s.parseYaml.convertTo[ModulePadAnnotation]))
case c: ComponentName if s.contains(NoIOPadAnnotation().field) =>
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]))
@@ -108,26 +110,26 @@ object HasPadAnnotation {
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 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
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 =>
val componentAnnos = padAnnos.filter {
case TargetIOPadAnnoF(ComponentName(_, ModuleName(n, _)), _) if n == topModName =>
true
case TargetIOPadAnnoF(ComponentName(_, ModuleName(n, _)), _) if n != topModName =>
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]))
}
}
}
}

View File

@@ -28,13 +28,6 @@ case object NoPad extends PadType {
def serialize: String = "none"
}
case object InOut extends Direction {
def serialize: String = "inout"
}
case object NoDirection extends Direction {
def serialize: String = "none"
}
abstract class PadSide extends FirrtlNode {
def orientation: PadOrientation
}
@@ -53,4 +46,4 @@ case object Top extends PadSide {
case object Bottom extends PadSide {
def serialize: String = "bottom"
def orientation: PadOrientation = Vertical
}
}