-
Notifications
You must be signed in to change notification settings - Fork 612
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
git-subtree add sifive/chisel-circt #2477
Changes from all commits
c136d11
2460754
1046d8c
2f3c5cb
a043bb3
dfaed69
042a276
92041a5
80fa20c
13b9a9e
493988e
17c9d39
26bc35c
0c21356
cf2993b
caeb131
ef09fa0
bdc5ae4
f1bdfe4
b333604
3e95ad7
54f881d
beb37c2
f73c720
8ff8aab
72bd6af
6bcb704
58d933f
5554b38
e1f8778
d89b2c1
b2b740f
7dd9f0e
73551f0
e8b5b03
abab0dd
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package circt | ||
|
||
/** A collection of implicit classes to provide additional methods to existing types */ | ||
object Implicits { | ||
|
||
/** Helpers for working with Boolean */ | ||
implicit class BooleanImplicits(a: Boolean) { | ||
|
||
/** Construct an Option from a Boolean. */ | ||
def option[A](b: => A): Option[A] = | ||
if (a) | ||
Some(b) | ||
else | ||
None | ||
} | ||
|
||
} | ||
Comment on lines
+6
to
+19
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought these APIs may not be public?
Comment on lines
+6
to
+19
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry for the delay review: |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package circt.stage | ||
|
||
import firrtl.AnnotationSeq | ||
import firrtl.annotations.{Annotation, NoTargetAnnotation} | ||
import firrtl.options.{CustomFileEmission, HasShellOptions, OptionsException, ShellOption, Unserializable} | ||
import firrtl.options.Viewer.view | ||
import firrtl.stage.FirrtlOptions | ||
|
||
/** An option consumed by [[circt.stage.CIRCTStage CIRCTStage]] */ | ||
sealed trait CIRCTOption extends Unserializable { this: Annotation => } | ||
|
||
object PreserveAggregate extends HasShellOptions { | ||
sealed trait Type | ||
object OneDimVec extends Type | ||
object Vec extends Type | ||
object All extends Type | ||
|
||
override def options = Seq( | ||
new ShellOption[String]( | ||
longOption = "preserve-aggregate", | ||
toAnnotationSeq = _ match { | ||
case "none" => Seq.empty | ||
case "1d-vec" => Seq(PreserveAggregate(PreserveAggregate.OneDimVec)) | ||
case "vec" => Seq(PreserveAggregate(PreserveAggregate.Vec)) | ||
case "all" => Seq(PreserveAggregate(PreserveAggregate.All)) | ||
}, | ||
helpText = "Do not lower aggregate types to ground types" | ||
) | ||
) | ||
|
||
} | ||
|
||
/** Preserve passive aggregate types in CIRCT. | ||
*/ | ||
case class PreserveAggregate(mode: PreserveAggregate.Type) extends NoTargetAnnotation with CIRCTOption | ||
|
||
/** Object storing types associated with different CIRCT target languages, e.g., RTL or SystemVerilog */ | ||
object CIRCTTarget { | ||
|
||
/** The parent type of all CIRCT targets */ | ||
sealed trait Type | ||
|
||
/** The FIRRTL dialect */ | ||
case object FIRRTL extends Type | ||
|
||
/** The HW dialect */ | ||
case object HW extends Type | ||
|
||
/** The Verilog language */ | ||
case object Verilog extends Type | ||
|
||
/** The SystemVerilog language */ | ||
case object SystemVerilog extends Type | ||
|
||
} | ||
|
||
/** Annotation that tells [[circt.stage.phases.CIRCT CIRCT]] what target to compile to */ | ||
case class CIRCTTargetAnnotation(target: CIRCTTarget.Type) extends NoTargetAnnotation with CIRCTOption | ||
|
||
object CIRCTTargetAnnotation extends HasShellOptions { | ||
|
||
override def options = Seq( | ||
new ShellOption[String]( | ||
longOption = "target", | ||
toAnnotationSeq = _ match { | ||
case "firrtl" => Seq(CIRCTTargetAnnotation(CIRCTTarget.FIRRTL)) | ||
case "hw" => Seq(CIRCTTargetAnnotation(CIRCTTarget.HW)) | ||
case "verilog" => Seq(CIRCTTargetAnnotation(CIRCTTarget.Verilog)) | ||
case "systemverilog" => Seq(CIRCTTargetAnnotation(CIRCTTarget.SystemVerilog)) | ||
case a => throw new OptionsException(s"Unknown target name '$a'! (Did you misspell it?)") | ||
}, | ||
helpText = "The CIRCT", | ||
helpValueName = Some("{firrtl|rtl|systemverilog}") | ||
) | ||
) | ||
|
||
} | ||
|
||
/** Annotation holding an emitted MLIR string | ||
* | ||
* @param filename the name of the file where this should be written | ||
* @param value a string of MLIR | ||
* @param suffix an optional suffix added to the filename when this is written to disk | ||
*/ | ||
case class EmittedMLIR( | ||
filename: String, | ||
value: String, | ||
suffix: Option[String]) | ||
extends NoTargetAnnotation | ||
with CustomFileEmission { | ||
|
||
override protected def baseFileName(annotations: AnnotationSeq): String = filename | ||
|
||
override def getBytes = value.getBytes | ||
|
||
} | ||
|
||
object CIRCTHandover extends HasShellOptions { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought we might eventually get rid of the |
||
|
||
sealed trait Type | ||
|
||
case object CHIRRTL extends Type | ||
case object HighFIRRTL extends Type | ||
case object MiddleFIRRTL extends Type | ||
case object LowFIRRTL extends Type | ||
case object LowOptimizedFIRRTL extends Type | ||
|
||
override def options = Seq( | ||
new ShellOption[String]( | ||
longOption = "handover", | ||
toAnnotationSeq = _ match { | ||
case "chirrtl" => Seq(CIRCTHandover(CHIRRTL)) | ||
case "high" => Seq(CIRCTHandover(HighFIRRTL)) | ||
case "middle" => Seq(CIRCTHandover(MiddleFIRRTL)) | ||
case "low" => Seq(CIRCTHandover(LowFIRRTL)) | ||
case "lowopt" => Seq(CIRCTHandover(LowOptimizedFIRRTL)) | ||
case a => throw new OptionsException(s"Unknown handover point '$a'! (Did you misspell it?)") | ||
}, | ||
helpText = "Switch to the CIRCT compiler at this point, using the Scala FIRRTL Compiler if needed", | ||
helpValueName = Some("{chirrtl|high|middle|low|lowopt}") | ||
) | ||
) | ||
} | ||
|
||
case class CIRCTHandover(handover: CIRCTHandover.Type) extends NoTargetAnnotation with CIRCTOption | ||
|
||
case class FirtoolOption(option: String) extends NoTargetAnnotation with CIRCTOption |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package circt.stage | ||
|
||
import java.io.File | ||
|
||
/** Options associated with CIRCT | ||
* | ||
* @param inputFile the name of an input FIRRTL IR file | ||
* @param outputFile the name of the file where the result will be written, if not split | ||
* @param preserveAggregate causes CIRCT to not lower aggregate FIRRTL IR types | ||
* @param target the specific IR or language target that CIRCT should compile to | ||
*/ | ||
class CIRCTOptions private[stage] ( | ||
val inputFile: Option[File] = None, | ||
val outputFile: Option[File] = None, | ||
val preserveAggregate: Option[PreserveAggregate.Type] = None, | ||
val target: Option[CIRCTTarget.Type] = None, | ||
val handover: Option[CIRCTHandover.Type] = None, | ||
val firtoolOptions: Seq[String] = Seq.empty) { | ||
|
||
private[stage] def copy( | ||
inputFile: Option[File] = inputFile, | ||
outputFile: Option[File] = outputFile, | ||
preserveAggregate: Option[PreserveAggregate.Type] = preserveAggregate, | ||
target: Option[CIRCTTarget.Type] = target, | ||
handover: Option[CIRCTHandover.Type] = handover, | ||
firtoolOptions: Seq[String] = firtoolOptions | ||
): CIRCTOptions = new CIRCTOptions(inputFile, outputFile, preserveAggregate, target, handover, firtoolOptions) | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package circt.stage | ||
|
||
import chisel3.stage.ChiselGeneratorAnnotation | ||
|
||
import firrtl.AnnotationSeq | ||
import firrtl.options.{Dependency, Phase, PhaseManager, Shell, Stage, StageMain} | ||
import firrtl.stage.FirrtlCli | ||
|
||
trait CLI { this: Shell => | ||
parser.note("CIRCT (MLIR FIRRTL Compiler) options") | ||
Seq( | ||
CIRCTTargetAnnotation, | ||
PreserveAggregate, | ||
ChiselGeneratorAnnotation, | ||
CIRCTHandover | ||
).foreach(_.addOptions(parser)) | ||
} | ||
|
||
/** A [[firrtl.options.Stage Stage]] used to compile FIRRTL IR using CIRCT. This is a drop-in replacement for | ||
* [[firrtl.stage.FirrtlStage]]. | ||
* | ||
* @see [[https://github.com/llvm/circt llvm/circt]] | ||
*/ | ||
class CIRCTStage extends Stage { | ||
|
||
override def prerequisites = Seq.empty | ||
override def optionalPrerequisites = Seq(Dependency[firrtl.stage.phases.Compiler]) | ||
override def optionalPrerequisiteOf = Seq.empty | ||
override def invalidates(a: Phase) = false | ||
|
||
override val shell: Shell = new Shell("circt") with CLI with FirrtlCli | ||
|
||
final val phaseManager = new PhaseManager( | ||
targets = Seq( | ||
Dependency[circt.stage.phases.CIRCT] | ||
), | ||
currentState = Seq( | ||
Dependency[firrtl.stage.phases.AddImplicitEmitter] | ||
) | ||
) | ||
|
||
override def run(annotations: AnnotationSeq): AnnotationSeq = phaseManager.transform(annotations) | ||
|
||
} | ||
|
||
/** Command line utility for [[CIRCTStage]]. */ | ||
object CIRCTMain extends StageMain(new CIRCTStage) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package circt.stage | ||
|
||
import chisel3.RawModule | ||
import chisel3.stage.{ChiselGeneratorAnnotation, NoRunFirrtlCompilerAnnotation} | ||
|
||
import firrtl.{AnnotationSeq, EmittedVerilogCircuitAnnotation} | ||
import firrtl.options.{Dependency, Phase, PhaseManager, Shell, Stage, StageMain} | ||
import firrtl.options.Viewer.view | ||
import firrtl.stage.{Forms, RunFirrtlTransformAnnotation} | ||
|
||
/** Entry point for running Chisel with the CIRCT compiler. | ||
* | ||
* This is intended to be a replacement for [[chisel3.stage.ChiselStage]]. | ||
* | ||
* @note The companion object, [[ChiselStage$]], has a cleaner API for compiling and returning a string. | ||
*/ | ||
class ChiselStage extends Stage { | ||
|
||
override def prerequisites = Seq.empty | ||
override def optionalPrerequisites = Seq.empty | ||
override def optionalPrerequisiteOf = Seq.empty | ||
override def invalidates(a: Phase) = false | ||
|
||
override val shell = new Shell("circt") with CLI | ||
|
||
override def run(annotations: AnnotationSeq): AnnotationSeq = { | ||
|
||
val pm = new PhaseManager( | ||
targets = Seq( | ||
Dependency[chisel3.stage.ChiselStage], | ||
Dependency[firrtl.stage.phases.AddImplicitOutputFile], | ||
Dependency[circt.stage.phases.AddDefaults], | ||
Dependency[circt.stage.phases.Checks], | ||
Dependency[circt.stage.phases.MaybeSFC], | ||
Dependency[circt.stage.CIRCTStage] | ||
), | ||
currentState = Seq( | ||
Dependency[firrtl.stage.phases.AddDefaults], | ||
Dependency[firrtl.stage.phases.Checks] | ||
) | ||
) | ||
pm.transform(NoRunFirrtlCompilerAnnotation +: annotations) | ||
} | ||
|
||
} | ||
|
||
/** Utilities for compiling Chisel */ | ||
object ChiselStage { | ||
|
||
/** Elaborate a Chisel circuit into a CHIRRTL string */ | ||
def emitCHIRRTL(gen: => RawModule): String = chisel3.stage.ChiselStage.emitChirrtl(gen) | ||
|
||
/** A phase shared by all the CIRCT backends */ | ||
private def phase = new PhaseManager( | ||
Seq( | ||
Dependency[chisel3.stage.phases.Checks], | ||
Dependency[chisel3.stage.phases.Elaborate], | ||
Dependency[chisel3.stage.phases.Convert], | ||
Dependency[firrtl.stage.phases.AddImplicitOutputFile], | ||
Dependency[chisel3.stage.phases.AddImplicitOutputAnnotationFile], | ||
Dependency[circt.stage.phases.Checks], | ||
Dependency[circt.stage.phases.CIRCT] | ||
) | ||
) | ||
|
||
/** Compile a Chisel circuit to FIRRTL dialect */ | ||
def emitFIRRTLDialect(gen: => RawModule): String = phase | ||
.transform( | ||
Seq( | ||
ChiselGeneratorAnnotation(() => gen), | ||
CIRCTTargetAnnotation(CIRCTTarget.FIRRTL), | ||
CIRCTHandover(CIRCTHandover.CHIRRTL) | ||
) | ||
) | ||
.collectFirst { | ||
case EmittedMLIR(_, a, _) => a | ||
} | ||
.get | ||
|
||
/** Compile a Chisel circuit to HWS dialect */ | ||
def emitHWDialect(gen: => RawModule): String = phase | ||
.transform( | ||
Seq( | ||
ChiselGeneratorAnnotation(() => gen), | ||
CIRCTTargetAnnotation(CIRCTTarget.HW), | ||
CIRCTHandover(CIRCTHandover.CHIRRTL) | ||
) | ||
) | ||
.collectFirst { | ||
case EmittedMLIR(_, a, _) => a | ||
} | ||
.get | ||
|
||
/** Compile a Chisel circuit to SystemVerilog */ | ||
def emitSystemVerilog(gen: => RawModule): String = phase | ||
.transform( | ||
Seq( | ||
ChiselGeneratorAnnotation(() => gen), | ||
CIRCTTargetAnnotation(CIRCTTarget.SystemVerilog), | ||
CIRCTHandover(CIRCTHandover.CHIRRTL) | ||
) | ||
) | ||
.collectFirst { | ||
case EmittedVerilogCircuitAnnotation(a) => a | ||
} | ||
.get | ||
.value | ||
|
||
} | ||
|
||
/** Command line entry point to [[ChiselStage]] */ | ||
object ChiselMain extends StageMain(new ChiselStage) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
package circt | ||
|
||
import circt.stage.{CIRCTOption, CIRCTTargetAnnotation, PreserveAggregate} | ||
|
||
import firrtl.AnnotationSeq | ||
import firrtl.options.OptionsView | ||
import firrtl.stage.{FirrtlFileAnnotation, FirrtlOption, OutputFileAnnotation} | ||
|
||
import java.io.File | ||
|
||
package object stage { | ||
|
||
implicit object CIRCTOptionsView extends OptionsView[CIRCTOptions] { | ||
|
||
def view(annotations: AnnotationSeq): CIRCTOptions = | ||
annotations.collect { | ||
case a: CIRCTOption => a | ||
case a: FirrtlOption => a | ||
case a: FirrtlFileAnnotation => a | ||
} | ||
.foldLeft(new CIRCTOptions()) { (acc, c) => | ||
c match { | ||
case FirrtlFileAnnotation(a) => acc.copy(inputFile = Some(new File(a))) | ||
case OutputFileAnnotation(a) => acc.copy(outputFile = Some(new File(a))) | ||
case CIRCTTargetAnnotation(a) => acc.copy(target = Some(a)) | ||
case PreserveAggregate(a) => acc.copy(preserveAggregate = Some(a)) | ||
case CIRCTHandover(a) => acc.copy(handover = Some(a)) | ||
case FirtoolOption(a) => acc.copy(firtoolOptions = acc.firtoolOptions :+ a) | ||
case _ => acc | ||
} | ||
} | ||
|
||
} | ||
|
||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hope we can have a better way to install CIRCT in the system.