Skip to content

Commit

Permalink
Use HowToSerialize for ChiselCircuitAnnotation
Browse files Browse the repository at this point in the history
Removes the explicit chisel3.phases.Emitter and instead does emission
with a HowToSerialize mixin to ChiselCircuitAnnotation. This then
prevents the need for passing around DeletedAnnotations. As a
consequence, I removed an unnecessary run of a second Converter in the
Driver.

Signed-off-by: Schuyler Eldridge <schuyler.eldridge@ibm.com>
  • Loading branch information
seldridge committed Jul 27, 2020
1 parent cceff69 commit 4eb7e9f
Show file tree
Hide file tree
Showing 5 changed files with 47 additions and 25 deletions.
3 changes: 2 additions & 1 deletion src/main/scala/chisel3/Driver.scala
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,8 @@ object Driver extends BackendCompilationUtilities {
Dependency[DriverCompatibility.FirrtlPreprocessing],
Dependency[chisel3.stage.phases.MaybeFirrtlStage] )
val currentState =
Seq( Dependency[firrtl.stage.phases.DriverCompatibility.AddImplicitFirrtlFile] )
Seq( Dependency[firrtl.stage.phases.DriverCompatibility.AddImplicitFirrtlFile],
Dependency[chisel3.stage.phases.Convert] )

val phases: Seq[Phase] = new PhaseManager(targets, currentState) {
override val wrappers = Seq( DeletedWrapper(_: Phase) )
Expand Down
39 changes: 32 additions & 7 deletions src/main/scala/chisel3/stage/ChiselAnnotations.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,26 @@
package chisel3.stage

import firrtl.annotations.{Annotation, NoTargetAnnotation}
import firrtl.options.{HasShellOptions, OptionsException, ShellOption, Unserializable}
import firrtl.options.{HasShellOptions, HowToSerialize, OptionsException, ShellOption, StageOptions, Unserializable}
import firrtl.options.Viewer.view
import chisel3.{ChiselException, Module}
import chisel3.RawModule
import chisel3.internal.Builder
import chisel3.internal.firrtl.Circuit
import chisel3.internal.firrtl.{Circuit, Emitter => OldEmitter}
import firrtl.AnnotationSeq
import java.io.File

/** Mixin that indicates that this is an [[firrtl.annotations.Annotation]] used to generate a [[ChiselOptions]] view.
*/
sealed trait ChiselOption extends Unserializable { this: Annotation => }
sealed trait ChiselOption { this: Annotation => }

/** Disable the execution of the FIRRTL compiler by Chisel
*/
case object NoRunFirrtlCompilerAnnotation extends NoTargetAnnotation with ChiselOption with HasShellOptions {
case object NoRunFirrtlCompilerAnnotation
extends NoTargetAnnotation
with ChiselOption
with HasShellOptions
with Unserializable {

val options = Seq(
new ShellOption[Unit](
Expand All @@ -29,7 +35,11 @@ case object NoRunFirrtlCompilerAnnotation extends NoTargetAnnotation with Chisel

/** On an exception, this will cause the full stack trace to be printed as opposed to a pruned stack trace.
*/
case object PrintFullStackTraceAnnotation extends NoTargetAnnotation with ChiselOption with HasShellOptions {
case object PrintFullStackTraceAnnotation
extends NoTargetAnnotation
with ChiselOption
with HasShellOptions
with Unserializable {

val options = Seq(
new ShellOption[Unit](
Expand Down Expand Up @@ -90,14 +100,29 @@ object ChiselGeneratorAnnotation extends HasShellOptions {
/** Stores a Chisel Circuit
* @param circuit a Chisel Circuit
*/
case class ChiselCircuitAnnotation(circuit: Circuit) extends NoTargetAnnotation with ChiselOption {
case class ChiselCircuitAnnotation(circuit: Circuit) extends NoTargetAnnotation with ChiselOption with HowToSerialize {
/* Caching the hashCode for a large circuit is necessary due to repeated queries.
* Not caching the hashCode will cause severe performance degredations for large [[Circuit]]s.
*/
override lazy val hashCode: Int = circuit.hashCode

protected def baseFileName: String = circuit.name

protected def suffix: Option[String] = Some(".fir")

override def howToSerialize: Option[Stream[Byte]] = Some(OldEmitter.emit(circuit).toStream.map(_.toByte))

override def howToResume(file: File): Option[AnnotationSeq] = None

override def filename(annotations: AnnotationSeq): File = {
val sopts = view[StageOptions](annotations)
val copts = view[ChiselOptions](annotations)
new File(sopts.getBuildFileName(copts.outputFile.getOrElse(baseFileName), suffix))
}

}

case class ChiselOutputFileAnnotation(file: String) extends NoTargetAnnotation with ChiselOption
case class ChiselOutputFileAnnotation(file: String) extends NoTargetAnnotation with ChiselOption with Unserializable

object ChiselOutputFileAnnotation extends HasShellOptions {

Expand Down
18 changes: 9 additions & 9 deletions src/main/scala/chisel3/stage/ChiselStage.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@
package chisel3.stage

import firrtl.{ir => fir, AnnotationSeq, EmittedFirrtlCircuitAnnotation, EmittedVerilogCircuitAnnotation}
import firrtl.annotations.DeletedAnnotation
import firrtl.options.{Dependency, Phase, PhaseManager, PreservesAll, Shell, Stage, StageError, StageMain}
import firrtl.options.phases.DeletedWrapper
import firrtl.stage.{FirrtlCircuitAnnotation, FirrtlCli}
Expand All @@ -23,16 +22,14 @@ class ChiselStage extends Stage with PreservesAll[Phase] {
Dependency[chisel3.stage.phases.AddImplicitOutputFile],
Dependency[chisel3.stage.phases.AddImplicitOutputAnnotationFile],
Dependency[chisel3.stage.phases.MaybeAspectPhase],
Dependency[chisel3.stage.phases.Emitter],
Dependency[chisel3.stage.phases.Convert],
Dependency[chisel3.stage.phases.MaybeFirrtlStage] )

final lazy val phaseManager = new PhaseManager(targets) {
override val wrappers = Seq( (a: Phase) => DeletedWrapper(a) )
}
private val phaseWrappers: Seq[Phase => Phase] = Seq( (a: Phase) => DeletedWrapper(a) )

def run(annotations: AnnotationSeq): AnnotationSeq = try {
phaseManager.transform(annotations)
val annotationsx = new PhaseManager(targets) { override val wrappers = phaseWrappers }.transform(annotations)
annotationsx
} catch {
case ce: ChiselException =>
val stackTrace = if (!view[ChiselOptions](annotations).printFullStackTrace) {
Expand Down Expand Up @@ -60,12 +57,15 @@ class ChiselStage extends Stage with PreservesAll[Phase] {
args: Array[String] = Array.empty,
annotations: AnnotationSeq = Seq.empty): String = {

execute(Array("-X", "none") ++ args, ChiselGeneratorAnnotation(() => gen) +: annotations)
val annos = execute(Array("--no-run-firrtl") ++ args, ChiselGeneratorAnnotation(() => gen) +: annotations)

annos
.collectFirst {
case DeletedAnnotation(_, EmittedFirrtlCircuitAnnotation(a)) => a
case a: ChiselCircuitAnnotation => a.howToSerialize.get
}
.get
.value
.map(_.toChar)
.mkString

}

Expand Down
11 changes: 3 additions & 8 deletions src/main/scala/chisel3/stage/package.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,9 @@
package chisel3

import firrtl._
import firrtl.annotations.DeletedAnnotation
import firrtl.options.OptionsView

import chisel3.internal.firrtl.{Circuit => ChiselCircuit}
import chisel3.stage.phases.{Convert, Emitter}

package object stage {

Expand All @@ -28,17 +26,14 @@ package object stage {

private[chisel3] implicit object ChiselExecutionResultView extends OptionsView[ChiselExecutionResult] {

lazy val dummyConvert = new Convert
lazy val dummyEmitter = new Emitter

def view(options: AnnotationSeq): ChiselExecutionResult = {
var chiselCircuit: Option[ChiselCircuit] = None
var chirrtlCircuit: Option[String] = None

options.foreach {
case DeletedAnnotation(dummyConvert.name, ChiselCircuitAnnotation(a)) => chiselCircuit = Some(a)
case DeletedAnnotation(dummyEmitter.name, EmittedFirrtlCircuitAnnotation(EmittedFirrtlCircuit(_, a, _))) =>
chirrtlCircuit = Some(a)
case a@ ChiselCircuitAnnotation(b) =>
chiselCircuit = Some(b)
chirrtlCircuit = a.howToSerialize.map(_.map(_.toChar).mkString)
case _ =>
}

Expand Down
1 change: 1 addition & 0 deletions src/main/scala/chisel3/stage/phases/Convert.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ class Convert extends Phase with PreservesAll[Phase] {

def transform(annotations: AnnotationSeq): AnnotationSeq = annotations.flatMap {
case a: ChiselCircuitAnnotation =>
Some(a) ++
/* Convert this Chisel Circuit to a FIRRTL Circuit */
Some(FirrtlCircuitAnnotation(Converter.convert(a.circuit))) ++
/* Convert all Chisel Annotations to FIRRTL Annotations */
Expand Down

0 comments on commit 4eb7e9f

Please # to comment.