From 7de4c478c33458dc3f195e377543ce6bab9ba5b8 Mon Sep 17 00:00:00 2001 From: Colin Schmidt Date: Tue, 18 Feb 2020 14:56:17 -0800 Subject: [PATCH] Update to chisel 3.2.x --- build.sbt | 5 ++ .../transforms/.clkgen/ClkAnnotations.scala | 79 +++++++++---------- .../transforms/.pads/AddIOPadsTransform.scala | 8 +- .../transforms/.pads/AnnotateSupplyPads.scala | 14 ++-- .../transforms/.pads/ChiselTopModule.scala | 39 ++++----- .../scala/transforms/.pads/CreatePadBBs.scala | 18 ++--- .../transforms/.pads/FoundryPadsYaml.scala | 24 +++--- .../transforms/.pads/PadAnnotations.scala | 50 ++++++------ .../transforms/.pads/PadDescriptors.scala | 9 +-- 9 files changed, 124 insertions(+), 122 deletions(-) diff --git a/build.sbt b/build.sbt index d254ca24..9ec44bf7 100644 --- a/build.sbt +++ b/build.sbt @@ -39,6 +39,11 @@ lazy val macros = (project in file("macros")) lazy val tapeout = (project in file("tapeout")) .settings(commonSettings) + .settings(Seq( + libraryDependencies ++= Seq( + "io.github.daviddenton" %% "handlebars-scala-fork" % "2.3.0" + ) + )) .settings(scalacOptions in Test ++= Seq("-language:reflectiveCalls")) lazy val root = (project in file(".")).aggregate(macros, tapeout) diff --git a/tapeout/src/main/scala/transforms/.clkgen/ClkAnnotations.scala b/tapeout/src/main/scala/transforms/.clkgen/ClkAnnotations.scala index 832cfbb1..3a2f9ba3 100644 --- a/tapeout/src/main/scala/transforms/.clkgen/ClkAnnotations.scala +++ b/tapeout/src/main/scala/transforms/.clkgen/ClkAnnotations.scala @@ -42,8 +42,8 @@ case object ClkGen extends ClkModType { def serialize: String = "gen" } -// Unlike typical SDC, starts at 0. -// Otherwise, see pg. 63 of "Constraining Designs for Synthesis and Timing Analysis" +// Unlike typical SDC, starts at 0. +// Otherwise, see pg. 63 of "Constraining Designs for Synthesis and Timing Analysis" // by S. Gangadharan // original clk: |-----|_____|-----|_____| // edges: 0 1 2 3 4 @@ -51,9 +51,9 @@ case object ClkGen extends ClkModType { // ---> |-----------|___________| // sources = source id's case class GeneratedClk( - id: String, - sources: Seq[String] = Seq(), - referenceEdges: Seq[Int] = Seq(), + id: String, + sources: Seq[String] = Seq(), + referenceEdges: Seq[Int] = Seq(), period: Option[Double] = None) { require(referenceEdges.sorted == referenceEdges, "Edges must be in order for generated clk") if (referenceEdges.nonEmpty) require(referenceEdges.length % 2 == 1, "# of reference edges must be odd!") @@ -64,13 +64,13 @@ case class ClkModAnnotation(tpe: String, generatedClks: Seq[GeneratedClk]) { def modType: ClkModType = HasClkAnnotation.modType(tpe) modType match { - case ClkDiv => + case ClkDiv => generatedClks foreach { c => require(c.referenceEdges.nonEmpty, "Reference edges must be defined for clk divider!") require(c.sources.length == 1, "Clk divider output can only have 1 source") require(c.period.isEmpty, "No period should be specified for clk divider output") } - case ClkMux => + case ClkMux => generatedClks foreach { c => require(c.referenceEdges.isEmpty, "Reference edges must not be defined for clk mux!") require(c.period.isEmpty, "No period should be specified for clk mux output") @@ -92,22 +92,24 @@ abstract class FirrtlClkTransformAnnotation { } // Firrtl version -case class TargetClkModAnnoF(target: ModuleName, anno: ClkModAnnotation) extends FirrtlClkTransformAnnotation { +case class TargetClkModAnnoF(target: ModuleName, anno: ClkModAnnotation) extends FirrtlClkTransformAnnotation with SingleTargetAnnotation[ModuleName] { + def duplicate(n: ModuleName): TargetClkModAnnoF = this.copy(target = n) def getAnno = Annotation(target, classOf[ClkSrcTransform], anno.serialize) def targetName = target.name def modType = anno.modType def generatedClks = anno.generatedClks - def getAllClkPorts = anno.generatedClks.map(x => + def getAllClkPorts = anno.generatedClks.map(x => List(List(x.id), x.sources).flatten).flatten.distinct.map(Seq(targetName, _).mkString(".")) } // Chisel version -case class TargetClkModAnnoC(target: Module, anno: ClkModAnnotation) { - def getAnno = ChiselAnnotation(target, classOf[ClkSrcTransform], anno.serialize) +case class TargetClkModAnnoC(target: Module, anno: ClkModAnnotation) extends ChiselAnnotation { + def toFirrtl = TargetClkModAnnoF(target.toNamed, anno) } // Firrtl version -case class TargetClkPortAnnoF(target: ComponentName, anno: ClkPortAnnotation) extends FirrtlClkTransformAnnotation { +case class TargetClkPortAnnoF(target: ComponentName, anno: ClkPortAnnotation) extends FirrtlClkTransformAnnotation with SingleTargetAnnotation[ComponentName] { + def duplicate(n: ComponentName): TargetClkPortAnnoF = this.copy(target = n) def getAnno = Annotation(target, classOf[ClkSrcTransform], anno.serialize) def targetName = Seq(target.module.name, target.name).mkString(".") def modId = Seq(target.module.name, anno.id).mkString(".") @@ -115,8 +117,8 @@ case class TargetClkPortAnnoF(target: ComponentName, anno: ClkPortAnnotation) ex } // Chisel version -case class TargetClkPortAnnoC(target: Element, anno: ClkPortAnnotation) { - def getAnno = ChiselAnnotation(target, classOf[ClkSrcTransform], anno.serialize) +case class TargetClkPortAnnoC(target: Element, anno: ClkPortAnnotation) extends ChiselAnnotation { + def toFirrtl = TargetClkPortAnnoF(target.toNamed, anno) } object HasClkAnnotation { @@ -132,31 +134,31 @@ object HasClkAnnotation { def unapply(a: Annotation): Option[FirrtlClkTransformAnnotation] = a match { case Annotation(f, t, s) if t == classOf[ClkSrcTransform] => f match { - case m: ModuleName => + case m: ModuleName => Some(TargetClkModAnnoF(m, s.parseYaml.convertTo[ClkModAnnotation])) case c: ComponentName => Some(TargetClkPortAnnoF(c, s.parseYaml.convertTo[ClkPortAnnotation])) - case _ => throw new Exception("Clk source annotation only valid on module or component!") + case _ => throw new Exception("Clk source annotation only valid on module or component!") } case _ => None } def apply(annos: Seq[Annotation]): Option[(Seq[TargetClkModAnnoF],Seq[TargetClkPortAnnoF])] = { // Get all clk-related annotations - val clkAnnos = annos.map(x => unapply(x)).flatten + val clkAnnos = annos.map(x => unapply(x)).flatten val targets = clkAnnos.map(x => x.targetName) require(targets.distinct.length == targets.length, "Only 1 clk related annotation is allowed per component/module") if (clkAnnos.length == 0) None else { - val componentAnnos = clkAnnos.filter { + val componentAnnos = clkAnnos.filter { case TargetClkPortAnnoF(ComponentName(_, ModuleName(_, _)), _) => true case _ => false }.map(x => x.asInstanceOf[TargetClkPortAnnoF]) val associatedMods = componentAnnos.map(x => x.target.module.name) - val moduleAnnos = clkAnnos.filter { - case TargetClkModAnnoF(ModuleName(m, _), _) => + val moduleAnnos = clkAnnos.filter { + case TargetClkModAnnoF(ModuleName(m, _), _) => require(associatedMods contains m, "Clk modules should always have clk port annotations!") - true + true case _ => false }.map(x => x.asInstanceOf[TargetClkModAnnoF]) Some((moduleAnnos, componentAnnos)) @@ -170,29 +172,26 @@ trait IsClkModule { self: chisel3.Module => - private def doNotDedup(module: Module): Unit = { - annotate(ChiselAnnotation(module, classOf[DedupModules], "nodedup!")) - } doNotDedup(this) private def extractElementNames(signal: Data): Seq[String] = { val names = signal match { - case elt: Record => + case elt: Record => elt.elements.map { case (key, value) => extractElementNames(value).map(x => key + "_" + x) }.toSeq.flatten - case elt: Vec[_] => + case elt: Vec[_] => elt.zipWithIndex.map { case (elt, i) => extractElementNames(elt).map(x => i + "_" + x) }.toSeq.flatten case elt: Element => Seq("") case elt => throw new Exception(s"Cannot extractElementNames for type ${elt.getClass}") } - names.map(s => s.stripSuffix("_")) + names.map(s => s.stripSuffix("_")) } // TODO: Replace! def extractElements(signal: Data): Seq[Element] = { signal match { - case elt: Record => + case elt: Record => elt.elements.map { case (key, value) => extractElements(value) }.toSeq.flatten - case elt: Vec[_] => + case elt: Vec[_] => elt.map { elt => extractElements(elt) }.toSeq.flatten case elt: Element => Seq(elt) case elt => throw new Exception(s"Cannot extractElements for type ${elt.getClass}") @@ -200,7 +199,7 @@ trait IsClkModule { } def getIOName(signal: Element): String = { - val possibleNames = extractElements(io).zip(extractElementNames(io)).map { + val possibleNames = extractElements(io).zip(extractElementNames(io)).map { case (sig, name) if sig == signal => Some(name) case _ => None }.flatten @@ -208,11 +207,11 @@ trait IsClkModule { else throw new Exception("You can only get the name of an io port!") } - def annotateDerivedClks(tpe: ClkModType, generatedClks: Seq[GeneratedClk]): Unit = + def annotateDerivedClks(tpe: ClkModType, generatedClks: Seq[GeneratedClk]): Unit = annotateDerivedClks(ClkModAnnotation(tpe.serialize, generatedClks)) def annotateDerivedClks(anno: ClkModAnnotation): Unit = annotateDerivedClks(this, anno) - def annotateDerivedClks(m: Module, anno: ClkModAnnotation): Unit = - annotate(TargetClkModAnnoC(m, anno).getAnno) + def annotateDerivedClks(m: Module, anno: ClkModAnnotation): Unit = + annotate(TargetClkModAnnoC(m, anno)) def annotateClkPort(p: Element): Unit = annotateClkPort(p, None, "") def annotateClkPort(p: Element, sink: Sink): Unit = annotateClkPort(p, Some(sink), "") @@ -221,7 +220,7 @@ trait IsClkModule { def annotateClkPort(p: Element, sink: Option[Sink], id: String): Unit = { // If no id is specified, it'll try to figure out a name, assuming p is an io port val newId = id match { - case "" => + case "" => getIOName(p) case _ => id } @@ -229,12 +228,12 @@ trait IsClkModule { } 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, "Module inputs must be clk sinks") - require(anno.tag.get.src.isEmpty, + require(anno.tag.get.src.isEmpty, "Clock module (not top) input clks should not have clk period, etc. specified") - case chisel3.core.Direction.Output => + case chisel3.core.ActualDirection.Output => require(anno.tag.isEmpty, "Module outputs must not be clk sinks (they're sources!)") case _ => throw new Exception("Clk port direction must be specified!") @@ -243,6 +242,6 @@ trait IsClkModule { case _: chisel3.core.Clock => case _ => throw new Exception("Clock port must be of type Clock") } - annotate(TargetClkPortAnnoC(p, anno).getAnno) + annotate(TargetClkPortAnnoC(p, anno)) } -} \ No newline at end of file +} diff --git a/tapeout/src/main/scala/transforms/.pads/AddIOPadsTransform.scala b/tapeout/src/main/scala/transforms/.pads/AddIOPadsTransform.scala index f9501f8f..d427d0d9 100644 --- a/tapeout/src/main/scala/transforms/.pads/AddIOPadsTransform.scala +++ b/tapeout/src/main/scala/transforms/.pads/AddIOPadsTransform.scala @@ -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) } } -} \ No newline at end of file +} diff --git a/tapeout/src/main/scala/transforms/.pads/AnnotateSupplyPads.scala b/tapeout/src/main/scala/transforms/.pads/AnnotateSupplyPads.scala index 27b93b46..cda00791 100644 --- a/tapeout/src/main/scala/transforms/.pads/AnnotateSupplyPads.scala +++ b/tapeout/src/main/scala/transforms/.pads/AnnotateSupplyPads.scala @@ -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) } -} \ No newline at end of file +} diff --git a/tapeout/src/main/scala/transforms/.pads/ChiselTopModule.scala b/tapeout/src/main/scala/transforms/.pads/ChiselTopModule.scala index 8f891e62..36979ce5 100644 --- a/tapeout/src/main/scala/transforms/.pads/ChiselTopModule.scala +++ b/tapeout/src/main/scala/transforms/.pads/ChiselTopModule.scala @@ -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() -} \ No newline at end of file +} diff --git a/tapeout/src/main/scala/transforms/.pads/CreatePadBBs.scala b/tapeout/src/main/scala/transforms/.pads/CreatePadBBs.scala index 1a7f2aa9..5b35fbe4 100644 --- a/tapeout/src/main/scala/transforms/.pads/CreatePadBBs.scala +++ b/tapeout/src/main/scala/transforms/.pads/CreatePadBBs.scala @@ -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) } -} \ No newline at end of file +} diff --git a/tapeout/src/main/scala/transforms/.pads/FoundryPadsYaml.scala b/tapeout/src/main/scala/transforms/.pads/FoundryPadsYaml.scala index ff1b92f0..2d372a51 100644 --- a/tapeout/src/main/scala/transforms/.pads/FoundryPadsYaml.scala +++ b/tapeout/src/main/scala/transforms/.pads/FoundryPadsYaml.scala @@ -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 } -} \ No newline at end of file +} diff --git a/tapeout/src/main/scala/transforms/.pads/PadAnnotations.scala b/tapeout/src/main/scala/transforms/.pads/PadAnnotations.scala index 66b7f184..ed870092 100644 --- a/tapeout/src/main/scala/transforms/.pads/PadAnnotations.scala +++ b/tapeout/src/main/scala/transforms/.pads/PadAnnotations.scala @@ -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])) } } -} \ No newline at end of file +} diff --git a/tapeout/src/main/scala/transforms/.pads/PadDescriptors.scala b/tapeout/src/main/scala/transforms/.pads/PadDescriptors.scala index 95a2cb1b..cb3420b1 100644 --- a/tapeout/src/main/scala/transforms/.pads/PadDescriptors.scala +++ b/tapeout/src/main/scala/transforms/.pads/PadDescriptors.scala @@ -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 -} \ No newline at end of file +}