Skip to content

Commit

Permalink
Merge pull request #1213 from freechipsproject/driver-deprecations
Browse files Browse the repository at this point in the history
Deprecate Driver methods in favor of ChiselStage
  • Loading branch information
seldridge authored Mar 24, 2020
2 parents 6ed81bc + 3fb11ea commit 3f6b1ce
Show file tree
Hide file tree
Showing 4 changed files with 200 additions and 8 deletions.
22 changes: 18 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,25 @@ class FirFilter(bitWidth: Int, coeffs: Seq[UInt]) extends Module {

and use and re-use them across designs:
```scala
val movingAverage3Filter = FirFilter(8.W, Seq(1.U, 1.U, 1.U)) // same 3-point moving average filter as before
val delayFilter = FirFilter(8.W, Seq(0.U, 1.U)) // 1-cycle delay as a FIR filter
val triangleFilter = FirFilter(8.W, Seq(1.U, 2.U, 3.U, 2.U, 1.U)) // 5-point FIR filter with a triangle impulse response
val movingAverage3Filter = Module(new FirFilter(8, Seq(1.U, 1.U, 1.U))) // same 3-point moving average filter as before
val delayFilter = Module(new FirFilter(8, Seq(0.U, 1.U))) // 1-cycle delay as a FIR filter
val triangleFilter = Module(new FirFilter(8, Seq(1.U, 2.U, 3.U, 2.U, 1.U))) // 5-point FIR filter with a triangle impulse response
```

The above can be converted to Verilog using `ChiselStage`:
```scala
import chisel3.stage.{ChiselStage, ChiselGeneratorAnnotation}

(new chisel3.stage.ChiselStage).execute(
Array("-X", "verilog"),
Seq(ChiselGeneratorAnnotation(() => new FirFilter(8, Seq(1.U, 1.U, 1.U)))))
```

Alternatively, you may generate some Verilog directly for inspection:
```scala
val verilogString = (new chisel3.stage.ChiselStage).emitVerilog(new FirFilter(8, Seq(0.U, 1.U)))
println(verilogString)
```

## Getting Started

Expand Down Expand Up @@ -186,7 +200,7 @@ Also included is:
contain commonly used interfaces and constructors (like `Decoupled`, which
wraps a signal with a ready-valid pair) as well as fully parameterizable
circuit generators (like arbiters and multiplexors).
- **Driver utilities**, `chisel3.Driver`, which contains compilation and test
- **Chisel Stage**, `chisel3.stage.*`, which contains compilation and test
functions that are invoked in the standard Verilog generation and simulation
testing infrastructure. These can also be used as part of custom flows.

Expand Down
14 changes: 14 additions & 0 deletions src/main/scala/chisel3/Driver.scala
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ case class ChiselExecutionSuccess(
*/
case class ChiselExecutionFailure(message: String) extends ChiselExecutionResult

@deprecated("Please switch to chisel3.stage.ChiselStage. Driver will be removed in 3.4.", "3.2.4")
object Driver extends BackendCompilationUtilities {

/**
Expand All @@ -90,13 +91,15 @@ object Driver extends BackendCompilationUtilities {
* @param gen A function that creates a Module hierarchy.
* @return The resulting Chisel IR in the form of a Circuit. (TODO: Should be FIRRTL IR)
*/
@deprecated("Use ChiselStage.elaborate or use a ChiselStage class. This will be removed in 3.4.", "3.2.4")
def elaborate[T <: RawModule](gen: () => T): Circuit = internal.Builder.build(Module(gen()))._1

/**
* Convert the given Chisel IR Circuit to a FIRRTL Circuit.
*
* @param ir Chisel IR Circuit, generated e.g. by elaborate().
*/
@deprecated("Use ChiselStage.convert or use a ChiselStage class. This will be removed in 3.4.", "3.2.4")
def toFirrtl(ir: Circuit): firrtl.ir.Circuit = Converter.convert(ir)

/**
Expand All @@ -105,13 +108,15 @@ object Driver extends BackendCompilationUtilities {
*
* @param gen A function that creates a Module hierarchy.
*/
@deprecated("Use (new chisel3.stage.ChiselStage).emitChirrtl. This will be removed in 3.4.", "3.2.2")
def emit[T <: RawModule](gen: () => T): String = Driver.emit(elaborate(gen))

/**
* Emit the given Chisel IR Circuit as a FIRRTL string, without invoking FIRRTL.
*
* @param ir Chisel IR Circuit, generated e.g. by elaborate().
*/
@deprecated("Use (new chisel3.stage.ChiselStage).emitChirrtl", "3.2.2")
def emit[T <: RawModule](ir: Circuit): String = Emitter.emit(ir)

/**
Expand All @@ -120,6 +125,7 @@ object Driver extends BackendCompilationUtilities {
* @param gen A function that creates a Module hierarchy.
* @return A String containing the design in Verilog.
*/
@deprecated("Use (new chisel3.stage.ChiselStage).emitVerilog. This will be removed in 3.4.", "3.2.2")
def emitVerilog[T <: RawModule](gen: => T): String = {
execute(Array[String](), { () => gen }) match {
case ChiselExecutionSuccess(_, _, Some(firrtl.FirrtlExecutionSuccess(_, verilog))) => verilog
Expand All @@ -137,6 +143,7 @@ object Driver extends BackendCompilationUtilities {
* @param optName File to dump to. If unspecified, defaults to "<topmodule>.fir".
* @return The File the circuit was dumped to.
*/
@deprecated("Migrate to chisel3.stage.ChiselStage. This will be removed in 3.4.", "3.2.4")
def dumpFirrtl(ir: Circuit, optName: Option[File]): File = {
val f = optName.getOrElse(new File(ir.name + ".fir"))
val w = new FileWriter(f)
Expand All @@ -151,6 +158,7 @@ object Driver extends BackendCompilationUtilities {
* @param ir The circuit containing annotations to be emitted
* @param optName An optional filename (will use s"\${ir.name}.json" otherwise)
*/
@deprecated("Migrate to chisel3.stage.ChiselStage. This will be removed in 3.4.", "3.2.4")
def dumpAnnotations(ir: Circuit, optName: Option[File]): File = {
val f = optName.getOrElse(new File(ir.name + ".anno.json"))
val w = new FileWriter(f)
Expand All @@ -169,6 +177,7 @@ object Driver extends BackendCompilationUtilities {
* @param optFile Optional File to dump to. If unspecified, defaults to "<topmodule>.pb".
* @return The File the circuit was dumped to.
*/
@deprecated("Migrate to chisel3.stage.ChiselStage. This will be removed in 3.4.", "3.2.4")
def dumpProto(c: Circuit, optFile: Option[File]): File = {
val f = optFile.getOrElse(new File(c.name + ".pb"))
val ostream = new java.io.FileOutputStream(f)
Expand All @@ -179,6 +188,7 @@ object Driver extends BackendCompilationUtilities {
}

private var target_dir: Option[String] = None
@deprecated("Use chisel3.stage.ChiselStage with '--target-directory'. This will be removed in 3.4.", "3.2.2")
def parseArgs(args: Array[String]): Unit = {
for (i <- 0 until args.size) {
if (args(i) == "--targetDir") {
Expand All @@ -187,6 +197,7 @@ object Driver extends BackendCompilationUtilities {
}
}

@deprecated("This has no effect on Chisel3 Driver! This will be removed in 3.4.", "3.2.2")
def targetDir(): String = { target_dir getOrElse new File(".").getCanonicalPath }

/**
Expand All @@ -196,6 +207,7 @@ object Driver extends BackendCompilationUtilities {
* @param dut The device under test
* @return An execution result with useful stuff, or failure with message
*/
@deprecated("Use chisel3.stage.ChiselStage.execute. This will be removed in 3.4.", "3.2.2")
def execute( // scalastyle:ignore method.length
optionsManager: ExecutionOptionsManager with HasChiselExecutionOptions with HasFirrtlOptions,
dut: () => RawModule): ChiselExecutionResult = {
Expand Down Expand Up @@ -241,6 +253,7 @@ object Driver extends BackendCompilationUtilities {
* @param dut The device under test
* @return An execution result with useful stuff, or failure with message
*/
@deprecated("Use chisel3.stage.ChiselStage.execute. This will be removed in 3.4.", "3.2.2")
def execute(args: Array[String], dut: () => RawModule): ChiselExecutionResult = {
val optionsManager = new ExecutionOptionsManager("chisel3") with HasChiselExecutionOptions with HasFirrtlOptions

Expand All @@ -259,6 +272,7 @@ object Driver extends BackendCompilationUtilities {
*
* @param args unused args
*/
@deprecated("Use chisel3.stage.ChiselMain. This will be removed in 3.4.", "3.2.2")
def main(args: Array[String]) {
execute(Array("--help"), null)
}
Expand Down
113 changes: 109 additions & 4 deletions src/main/scala/chisel3/stage/ChiselStage.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,20 @@

package chisel3.stage

import firrtl.AnnotationSeq
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.FirrtlCli
import firrtl.stage.{FirrtlCircuitAnnotation, FirrtlCli}
import firrtl.options.Viewer.view

import chisel3.ChiselException
import chisel3.internal.ErrorLog
import chisel3.{ChiselException, RawModule}
import chisel3.internal.{firrtl => cir, ErrorLog}

import java.io.{StringWriter, PrintWriter}

class ChiselStage extends Stage with PreservesAll[Phase] {

val shell: Shell = new Shell("chisel") with ChiselCli with FirrtlCli

val targets: Seq[Dependency[Phase]] =
Expand Down Expand Up @@ -47,6 +49,109 @@ class ChiselStage extends Stage with PreservesAll[Phase] {
throw new StageError()
}

/** Convert a Chisel module to a CHIRRTL string
* @param gen a call-by-name Chisel module
* @param args additional command line arguments to pass to Chisel
* param annotations additional annotations to pass to Chisel
* @return a string containing the Verilog output
*/
final def emitChirrtl(
gen: => RawModule,
args: Array[String] = Array.empty,
annotations: AnnotationSeq = Seq.empty): String = {

execute(Array("-X", "none") ++ args, ChiselGeneratorAnnotation(() => gen) +: annotations)
.collectFirst {
case DeletedAnnotation(_, EmittedFirrtlCircuitAnnotation(a)) => a
}
.get
.value

}

/** Convert a Chisel module to a FIRRTL string
* @param gen a call-by-name Chisel module
* @param args additional command line arguments to pass to Chisel
* param annotations additional annotations to pass to Chisel
* @return a string containing the Verilog output
*/
final def emitFirrtl(
gen: => RawModule,
args: Array[String] = Array.empty,
annotations: AnnotationSeq = Seq.empty): String = {

execute(Array("-X", "high") ++ args, ChiselGeneratorAnnotation(() => gen) +: annotations)
.collectFirst {
case DeletedAnnotation(_, EmittedFirrtlCircuitAnnotation(a)) => a
}
.get
.value

}

/** Convert a Chisel module to Verilog
* @param gen a call-by-name Chisel module
* @param args additional command line arguments to pass to Chisel
* param annotations additional annotations to pass to Chisel
* @return a string containing the Verilog output
*/
final def emitVerilog(
gen: => RawModule,
args: Array[String] = Array.empty,
annotations: AnnotationSeq = Seq.empty): String = {

execute(Array("-X", "verilog") ++ args, ChiselGeneratorAnnotation(() => gen) +: annotations)
.collectFirst {
case DeletedAnnotation(_, EmittedVerilogCircuitAnnotation(a)) => a
}
.get
.value
}

}

object ChiselMain extends StageMain(new ChiselStage)

/** Helper methods for working with [[ChiselStage]] */
object ChiselStage {

/** Return a Chisel circuit for a Chisel module
* @param gen a call-by-name Chisel module
*/
def elaborate(gen: => RawModule): cir.Circuit = {
val stage = new ChiselStage {
override val targets = Seq( Dependency[chisel3.stage.phases.Checks],
Dependency[chisel3.stage.phases.Elaborate] )
}

stage
.execute(Array("--no-run-firrtl"), Seq(ChiselGeneratorAnnotation(() => gen)))
.collectFirst {
case ChiselCircuitAnnotation(a) => a
}
.get
}

/** Return a CHIRRTL circuit for a Chisel module
* @param gen a call-by-name Chisel module
*/
def convert(gen: => RawModule): fir.Circuit = {
val stage = new ChiselStage {
override val targets = Seq(
Dependency[chisel3.stage.phases.Checks],
Dependency[chisel3.stage.phases.Elaborate],
Dependency[chisel3.stage.phases.AddImplicitOutputFile],
Dependency[chisel3.stage.phases.AddImplicitOutputAnnotationFile],
Dependency[chisel3.stage.phases.MaybeAspectPhase],
Dependency[chisel3.stage.phases.Convert] )
}

stage
.execute(Array("--no-run-firrtl"), Seq(ChiselGeneratorAnnotation(() => gen)))
.collectFirst {
case FirrtlCircuitAnnotation(a) => a
}
.get
}

}
59 changes: 59 additions & 0 deletions src/test/scala/chiselTests/stage/ChiselStageSpec.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// See LICENSE for license details.

package chiselTests.stage

import chisel3._
import chisel3.stage.ChiselStage

import org.scalatest.{FlatSpec, Matchers}

object ChiselStageSpec {

class Foo extends MultiIOModule {
val addr = IO(Input(UInt(4.W)))
val out = IO(Output(Bool()))
val bar = SyncReadMem(8, Bool())
out := bar(addr)
}

}

class ChiselStageSpec extends FlatSpec with Matchers {

import ChiselStageSpec._

private trait ChiselStageFixture {
val stage = new ChiselStage
}

behavior of "ChiselStage.emitChirrtl"

it should "return a CHIRRTL string" in new ChiselStageFixture {
stage.emitChirrtl(new Foo) should include ("infer mport")
}

behavior of "ChiselStage.emitFirrtl"

it should "return a High FIRRTL string" in new ChiselStageFixture {
stage.emitFirrtl(new Foo) should include ("mem bar")
}

behavior of "ChiselStage.emitVerilog"

it should "return a Verilog string" in new ChiselStageFixture {
stage.emitVerilog(new Foo) should include ("endmodule")
}

behavior of "ChiselStage$.elaborate"

it should "generate a Chisel circuit from a Chisel module" in {
ChiselStage.elaborate(new Foo)
}

behavior of "ChiselStage$.convert"

it should "generate a CHIRRTL circuit from a Chisel module" in {
ChiselStage.convert(new Foo)
}

}

0 comments on commit 3f6b1ce

Please sign in to comment.