Refactor tapeout for Chisel 3.4, Firrtl 1.4

- Remove clk package based on discussion with Colin
- Annotations need to be refactored to using latest API
  - Generally that involves making annos generated by a anonymous ChiselAnnotation
  - The chisel annotations will use RunFirrtlTransform to queue up its associated transform
  - Chisel annotation provieds toFirrtl to generate Firrtl form of annotation
- Usages of unapply on firrtl annotations cannot use generic unapply(target, transform, data) which has been eliminated
- Have transforms use with DependencyAPIMigration to avoid deprecated `form`s
- Added some 'see License comments
- TechnologyLocation section of AddIOPadsSpec does not currently run because there is no content for it.
  - Added some tests for annotation serialization here
This commit is contained in:
chick
2020-09-11 17:06:19 -07:00
parent e4cd2b01fe
commit 67de39e957
13 changed files with 275 additions and 218 deletions

View File

@@ -3,24 +3,19 @@
package barstools.tapeout.transforms.pads
import firrtl._
import firrtl.annotations._
import firrtl.passes._
import firrtl.ir._
import barstools.tapeout.transforms._
import scala.collection.mutable
// Main Add IO Pad transform operates on low Firrtl
class AddIOPadsTransform extends Transform with SeqTransformBased {
override def inputForm: CircuitForm = LowForm
override def outputForm: CircuitForm = LowForm
class AddIOPadsTransform extends Transform with SeqTransformBased with DependencyAPIMigration {
val transformList = new mutable.ArrayBuffer[Transform]
def transforms: Seq[Transform] = transformList
override def execute(state: CircuitState): CircuitState = {
val collectedAnnos = HasPadAnnotation(getMyAnnotations(state))
val collectedAnnos = HasPadAnnotation(state.annotations)
collectedAnnos match {
// Transform not used
case None => state

View File

@@ -77,7 +77,12 @@ abstract class TopModule(
// 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))
annotate(new ChiselAnnotation with RunFirrtlTransform {
override def toFirrtl: Annotation = {
TargetIOPadAnnoF(sig.toTarget, anno)
}
def transformClass: Class[_ <: Transform] = classOf[AddIOPadsTransform]
})
}
def annotatePad(sig: Aggregate, name: String): Unit = annotatePad(sig, side = defaultPadSide, name)
def annotatePad(sig: Aggregate, side: PadSide): Unit = annotatePad(sig, side, name = "")
@@ -86,7 +91,16 @@ abstract class TopModule(
// 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: Element): Unit = {
if (usePads) {
annotate(new ChiselAnnotation with RunFirrtlTransform {
override def toFirrtl: Annotation = {
TargetIOPadAnnoF(sig.toTarget, NoIOPadAnnotation())
}
def transformClass: Class[_ <: Transform] = classOf[AddIOPadsTransform]
})
}
}
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

View File

@@ -1,3 +1,5 @@
// See LICENSE for license details.
package barstools.tapeout.transforms.pads
import net.jcazevedo.moultingyaml._
@@ -85,8 +87,9 @@ 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())
throw new Exception("Technology directory must contain FoundryPads.yaml!")
if(techDir != "" && !(new java.io.File(file)).exists()) {
throw new Exception(s"Technology directory $techDir 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!")

View File

@@ -3,9 +3,6 @@
package barstools.tapeout.transforms.pads
import firrtl.annotations._
import chisel3.experimental._
import chisel3._
import net.jcazevedo.moultingyaml._
object PadAnnotationsYaml extends DefaultYamlProtocol {
@@ -13,6 +10,17 @@ object PadAnnotationsYaml extends DefaultYamlProtocol {
implicit val _noiopad = yamlFormat1(NoIOPadAnnotation)
implicit val _supplyanno = yamlFormat5(SupplyAnnotation)
implicit val _modulepadanno = yamlFormat4(ModulePadAnnotation)
// Putting these serialize methods here seems to fix warnings about missing implicits for the toYaml
def serialize(noIOPad: NoIOPadAnnotation): String = {
noIOPad.toYaml.prettyPrint
}
def serialize(ioPadAnnotation: IOPadAnnotation): String = {
ioPadAnnotation.toYaml.prettyPrint
}
def serialize(modulePadAnnotation: ModulePadAnnotation): String = {
modulePadAnnotation.toYaml.prettyPrint
}
}
abstract class FirrtlPadTransformAnnotation {
@@ -25,14 +33,12 @@ abstract class IOAnnotation {
}
case class IOPadAnnotation(padSide: String, padName: String) extends IOAnnotation {
import PadAnnotationsYaml._
def serialize: String = this.toYaml.prettyPrint
def serialize: String = PadAnnotationsYaml.serialize(this)
def getPadSide: PadSide = HasPadAnnotation.getSide(padSide)
}
case class NoIOPadAnnotation(noPad: String = "") extends IOAnnotation {
import PadAnnotationsYaml._
def serialize: String = this.toYaml.prettyPrint
def serialize: String = PadAnnotationsYaml.serialize(this)
def field: String = "noPad:"
}
@@ -44,12 +50,6 @@ case class TargetIOPadAnnoF(target: ComponentName, anno: IOAnnotation)
def targetName: String = target.name
}
//TODO: PORT-1.4: Remove commented code
// Chisel version
//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,
@@ -64,9 +64,9 @@ case class ModulePadAnnotation(
coreWidth: Int = 0,
coreHeight: Int = 0,
supplyAnnos: Seq[SupplyAnnotation] = Seq.empty) {
import PadAnnotationsYaml._
def serialize: String = this.toYaml.prettyPrint
val supplyPadNames = supplyAnnos.map(_.padName)
def serialize: String = PadAnnotationsYaml.serialize(this)
def supplyPadNames: Seq[String] = supplyAnnos.map(_.padName)
require(supplyPadNames.distinct.length == supplyPadNames.length, "Supply pads should only be specified once!")
def getDefaultPadSide: PadSide = HasPadAnnotation.getSide(defaultPadSide)
}
@@ -91,7 +91,6 @@ case class CollectedAnnos(
}
object HasPadAnnotation {
import PadAnnotationsYaml._
def getSide(a: String): PadSide = a match {
case i if i == Left.serialize => Left
@@ -115,26 +114,13 @@ object HasPadAnnotation {
// case _ => None
// }
//scalastyle:off cyclomatic.complexity
def unapply(a: Annotation): Option[FirrtlPadTransformAnnotation] = a match {
case hasTransform: RunFirrtlTransform if hasTransform.transformClass == classOf[AddIOPadsTransform] =>
hasTransform match {
case hasTarget: SingleTargetAnnotation[_] =>
hasTarget.target match {
case m: ModuleName =>
Some(TargetModulePadAnnoF(m, s.parseYaml.convertTo[ModulePadAnnotation]))
hasTarget match {
case _ => None
}
}
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 padAnnos = annos.flatMap {
case a: TargetModulePadAnnoF => Some(a)
case a: TargetIOPadAnnoF => Some(a)
case _ => None
}
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) {