summaryrefslogtreecommitdiff
path: root/src/main
diff options
context:
space:
mode:
authorJim Lawson2016-10-24 10:31:26 -0700
committerJim Lawson2016-10-24 10:31:26 -0700
commitb0b5fd3140186651eb558bd6f4ca51c618deacc9 (patch)
tree1393bbb14303af86aeb5e5ed0375f302864b8307 /src/main
parent82625071405672eb4a19363d6f73f359ac28a7f5 (diff)
parent5df30b390ae5817c4793c6d4e0c5466d96d241f1 (diff)
Merge branch 'master' into tobits-deprecation
Diffstat (limited to 'src/main')
-rw-r--r--src/main/scala/chisel3/ChiselExecutionOptions.scala34
-rw-r--r--src/main/scala/chisel3/Driver.scala161
-rw-r--r--src/main/scala/chisel3/compatibility.scala19
-rw-r--r--src/main/scala/chisel3/internal/firrtl/Emitter.scala6
-rw-r--r--src/main/scala/chisel3/package.scala23
-rw-r--r--src/main/scala/chisel3/testers/TesterDriver.scala35
-rw-r--r--src/main/scala/chisel3/util/BitPat.scala1
7 files changed, 219 insertions, 60 deletions
diff --git a/src/main/scala/chisel3/ChiselExecutionOptions.scala b/src/main/scala/chisel3/ChiselExecutionOptions.scala
new file mode 100644
index 00000000..6f58153f
--- /dev/null
+++ b/src/main/scala/chisel3/ChiselExecutionOptions.scala
@@ -0,0 +1,34 @@
+// See LICENSE for license details.
+
+package chisel3
+
+import firrtl.{ExecutionOptionsManager, ComposableOptions}
+
+//TODO: provide support for running firrtl as separate process, could alternatively be controlled by external driver
+//TODO: provide option for not saving chirrtl file, instead calling firrtl with in memory chirrtl
+/**
+ * Options that are specific to chisel.
+ *
+ * @param runFirrtlCompiler when true just run chisel, when false run chisel then compile its output with firrtl
+ * @note this extends FirrtlExecutionOptions which extends CommonOptions providing easy access to down chain options
+ */
+case class ChiselExecutionOptions(
+ runFirrtlCompiler: Boolean = true
+ // var runFirrtlAsProcess: Boolean = false
+ ) extends ComposableOptions
+
+trait HasChiselExecutionOptions {
+ self: ExecutionOptionsManager =>
+
+ var chiselOptions = ChiselExecutionOptions()
+
+ parser.note("chisel3 options")
+
+ parser.opt[Unit]("no-run-firrtl")
+ .abbr("chnrf")
+ .foreach { _ =>
+ chiselOptions = chiselOptions.copy(runFirrtlCompiler = false)
+ }
+ .text("Stop after chisel emits chirrtl file")
+}
+
diff --git a/src/main/scala/chisel3/Driver.scala b/src/main/scala/chisel3/Driver.scala
index 5e0a3a0f..a0713379 100644
--- a/src/main/scala/chisel3/Driver.scala
+++ b/src/main/scala/chisel3/Driver.scala
@@ -2,11 +2,37 @@
package chisel3
+import chisel3.internal.firrtl.Emitter
+
import scala.sys.process._
import java.io._
-import internal._
import internal.firrtl._
+import firrtl._
+
+/**
+ * The Driver provides methods to invoke the chisel3 compiler and the firrtl compiler.
+ * By default firrtl is automatically run after chisel. an [[ExecutionOptionsManager]]
+ * is needed to manage options. It can parser command line arguments or coordinate
+ * multiple chisel toolchain tools options.
+ *
+ * @example
+ * {{{
+ * val optionsManager = new ExecutionOptionsManager("chisel3")
+ * with FirrtlExecutionOptions
+ * with ChiselExecutionOptions {
+ * commonOptions = CommonOption(targetDirName = "my_target_dir")
+ * chiselOptions = ChiselExecutionOptions(runFirrtlCompiler = false)
+ * }
+ * chisel3.Driver.execute(optionsManager, () => new Dut)
+ * }}}
+ * or via command line arguments
+ * @example {{{
+ * args = "--no-run-firrtl --target-dir my-target-dir".split(" +")
+ * chisel3.execute(args, () => new DUT)
+ * }}}
+ */
+import BuildInfo._
trait BackendCompilationUtilities {
/** Create a temporary directory with the prefix name. Exists here because it doesn't in Java 6.
@@ -31,6 +57,32 @@ trait BackendCompilationUtilities {
vf
}
+ /**
+ * like 'firrtlToVerilog' except it runs the process inside the same JVM
+ *
+ * @param prefix basename of the file
+ * @param dir directory where file lives
+ * @return true if compiler completed successfully
+ */
+ def compileFirrtlToVerilog(prefix: String, dir: File): Boolean = {
+ val optionsManager = new ExecutionOptionsManager("chisel3") with HasChiselExecutionOptions with HasFirrtlOptions {
+ commonOptions = CommonOptions(topName = prefix, targetDirName = dir.getAbsolutePath)
+ firrtlOptions = FirrtlExecutionOptions(compilerName = "verilog")
+ }
+
+ firrtl.Driver.execute(optionsManager) match {
+ case _: FirrtlExecutionSuccess => true
+ case _: FirrtlExecutionFailure => false
+ }
+ }
+
+ /**
+ * compule chirrtl to verilog by using a separate process
+ *
+ * @param prefix basename of the file
+ * @param dir directory where file lives
+ * @return true if compiler completed successfully
+ */
def firrtlToVerilog(prefix: String, dir: File): ProcessBuilder = {
Process(
Seq("firrtl",
@@ -67,13 +119,13 @@ trait BackendCompilationUtilities {
"-Wno-WIDTH",
"-Wno-STMTDLY",
"--trace",
- "-O2",
+ "-O0",
"--top-module", topModule,
"+define+TOP_TYPE=V" + dutFile,
s"+define+PRINTF_COND=!$topModule.reset",
s"+define+STOP_COND=!$topModule.reset",
"-CFLAGS",
- s"""-Wno-undefined-bool-conversion -O2 -DTOP_TYPE=V$dutFile -include V$dutFile.h""",
+ s"""-Wno-undefined-bool-conversion -O0 -DTOP_TYPE=V$dutFile -include V$dutFile.h""",
"-Mdir", dir.toString,
"--exe", cppHarness.toString)
System.out.println(s"${command.mkString(" ")}") // scalastyle:ignore regex
@@ -86,14 +138,17 @@ trait BackendCompilationUtilities {
def executeExpectingFailure(
prefix: String,
dir: File,
- assertionMsg: String = "Assertion failed"): Boolean = {
+ assertionMsg: String = ""): Boolean = {
var triggered = false
+ val assertionMessageSupplied = assertionMsg != ""
val e = Process(s"./V${prefix}", dir) !
ProcessLogger(line => {
- triggered = triggered || line.contains(assertionMsg)
+ triggered = triggered || (assertionMessageSupplied && line.contains(assertionMsg))
System.out.println(line) // scalastyle:ignore regex
})
- triggered
+ // Fail if a line contained an assertion or if we get a non-zero exit code
+ // or, we get a SIGABRT (assertion failure) and we didn't provide a specific assertion message
+ triggered || (e != 0 && (e != 134 || !assertionMessageSupplied))
}
def executeExpectingSuccess(prefix: String, dir: File): Boolean = {
@@ -101,6 +156,30 @@ trait BackendCompilationUtilities {
}
}
+/**
+ * This family provides return values from the chisel3 and possibly firrtl compile steps
+ */
+trait ChiselExecutionResult
+
+/**
+ *
+ * @param circuitOption Optional circuit, has information like circuit name
+ * @param emitted The emitted Chirrrl text
+ * @param firrtlResultOption Optional Firrtl result, @see ucb-bar/firrtl for details
+ */
+case class ChiselExecutionSucccess(
+ circuitOption: Option[Circuit],
+ emitted: String,
+ firrtlResultOption: Option[FirrtlExecutionResult]
+ ) extends ChiselExecutionResult
+
+/**
+ * Getting one of these indicates failure of some sort
+ *
+ * @param message a clue perhaps will be provided in the here
+ */
+case class ChiselExecutionFailure(message: String) extends ChiselExecutionResult
+
object Driver extends BackendCompilationUtilities {
/** Elaborates the Module specified in the gen function into a Circuit
@@ -108,7 +187,7 @@ 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)
*/
- def elaborate[T <: Module](gen: () => T): Circuit = Builder.build(Module(gen()))
+ def elaborate[T <: Module](gen: () => T): Circuit = internal.Builder.build(Module(gen()))
def emit[T <: Module](gen: () => T): String = Emitter.emit(elaborate(gen))
@@ -132,4 +211,72 @@ object Driver extends BackendCompilationUtilities {
}
def targetDir(): String = { target_dir getOrElse new File(".").getCanonicalPath }
+
+ /**
+ * Run the chisel3 compiler and possibly the firrtl compiler with options specified
+ *
+ * @param optionsManager The options specified
+ * @param dut The device under test
+ * @return An execution result with useful stuff, or failure with message
+ */
+ def execute(
+ optionsManager: ExecutionOptionsManager with HasChiselExecutionOptions with HasFirrtlOptions,
+ dut: () => Module): ChiselExecutionResult = {
+ val circuit = elaborate(dut)
+
+ // this little hack let's us set the topName with the circuit name if it has not been set from args
+ optionsManager.setTopNameIfNotSet(circuit.name)
+
+ val firrtlOptions = optionsManager.firrtlOptions
+ val chiselOptions = optionsManager.chiselOptions
+
+ // use input because firrtl will be reading this
+ val firrtlString = Emitter.emit(circuit)
+ val firrtlFileName = firrtlOptions.getInputFileName(optionsManager)
+ val firrtlFile = new File(firrtlFileName)
+
+ val w = new FileWriter(firrtlFile)
+ w.write(firrtlString)
+ w.close()
+
+ val firrtlExecutionResult = if(chiselOptions.runFirrtlCompiler) {
+ Some(firrtl.Driver.execute(optionsManager))
+ }
+ else {
+ None
+ }
+ ChiselExecutionSucccess(Some(circuit), firrtlString, firrtlExecutionResult)
+ }
+
+ /**
+ * Run the chisel3 compiler and possibly the firrtl compiler with options specified via an array of Strings
+ *
+ * @param args The options specified, command line style
+ * @param dut The device under test
+ * @return An execution result with useful stuff, or failure with message
+ */
+ def execute(args: Array[String], dut: () => Module): ChiselExecutionResult = {
+ val optionsManager = new ExecutionOptionsManager("chisel3") with HasChiselExecutionOptions with HasFirrtlOptions
+
+ optionsManager.parse(args) match {
+ case true =>
+ execute(optionsManager, dut)
+ case _ =>
+ ChiselExecutionFailure("could not parse results")
+ }
+ }
+
+ /**
+ * This is just here as command line way to see what the options are
+ * It will not successfully run
+ * TODO: Look into dynamic class loading as way to make this main useful
+ *
+ * @param args unused args
+ */
+ def main(args: Array[String]) {
+ execute(Array("--help"), null)
+ }
+
+ val version = BuildInfo.version
+ val chiselVersionString = BuildInfo.toString
}
diff --git a/src/main/scala/chisel3/compatibility.scala b/src/main/scala/chisel3/compatibility.scala
index d13fcb06..d0d2ddb4 100644
--- a/src/main/scala/chisel3/compatibility.scala
+++ b/src/main/scala/chisel3/compatibility.scala
@@ -158,25 +158,6 @@ package object Chisel { // scalastyle:ignore package.object.name
type DecoupledIO[+T <: Data] = chisel3.util.DecoupledIO[T]
val DecoupledIO = chisel3.util.Decoupled
val Decoupled = chisel3.util.Decoupled
- class EnqIO[+T <: Data](gen: T) extends DecoupledIO(gen) {
- def init(): Unit = {
- this.noenq()
- }
- override def cloneType: this.type = EnqIO(gen).asInstanceOf[this.type]
- }
- class DeqIO[+T <: Data](gen: T) extends DecoupledIO(gen) {
- chisel3.core.Binding.bind(this, chisel3.core.FlippedBinder, "Error: Cannot flip ")
- def init(): Unit = {
- this.nodeq()
- }
- override def cloneType: this.type = DeqIO(gen).asInstanceOf[this.type]
- }
- object EnqIO {
- def apply[T<:Data](gen: T): DecoupledIO[T] = DecoupledIO(gen)
- }
- object DeqIO {
- def apply[T<:Data](gen: T): DecoupledIO[T] = Flipped(DecoupledIO(gen))
- }
type QueueIO[T <: Data] = chisel3.util.QueueIO[T]
type Queue[T <: Data] = chisel3.util.Queue[T]
val Queue = chisel3.util.Queue
diff --git a/src/main/scala/chisel3/internal/firrtl/Emitter.scala b/src/main/scala/chisel3/internal/firrtl/Emitter.scala
index f1908089..0793fd7d 100644
--- a/src/main/scala/chisel3/internal/firrtl/Emitter.scala
+++ b/src/main/scala/chisel3/internal/firrtl/Emitter.scala
@@ -40,7 +40,7 @@ private class Emitter(circuit: Circuit) {
s"skip"
}
e.sourceInfo match {
- case SourceLine(filename, line, col) => s"${firrtlLine} @[${filename} ${line}:${col}] "
+ case SourceLine(filename, line, col) => s"${firrtlLine} @[${filename} ${line}:${col}]"
case _: NoSourceInfo => firrtlLine
}
}
@@ -102,7 +102,9 @@ private class Emitter(circuit: Circuit) {
private def unindent() { require(indentLevel > 0); indentLevel -= 1 }
private def withIndent(f: => Unit) { indent(); f; unindent() }
- private val res = new StringBuilder(s"circuit ${circuit.name} : ")
+ private val res = new StringBuilder()
+ res ++= s";${Driver.chiselVersionString}\n"
+ res ++= s"circuit ${circuit.name} : "
withIndent { circuit.components.foreach(c => res ++= emit(c)) }
res ++= newline
}
diff --git a/src/main/scala/chisel3/package.scala b/src/main/scala/chisel3/package.scala
index 17ddd55a..d0808980 100644
--- a/src/main/scala/chisel3/package.scala
+++ b/src/main/scala/chisel3/package.scala
@@ -152,6 +152,7 @@ package object chisel3 { // scalastyle:ignore package.object.name
implicit class fromUIntToBitPatComparable(val x: UInt) extends AnyVal {
final def === (that: BitPat): Bool = macro SourceInfoTransform.thatArg
+ @deprecated("Use '=/=', which avoids potential precedence problems", "chisel3")
final def != (that: BitPat): Bool = macro SourceInfoTransform.thatArg
final def =/= (that: BitPat): Bool = macro SourceInfoTransform.thatArg
@@ -166,28 +167,6 @@ package object chisel3 { // scalastyle:ignore package.object.name
val NODIR = chisel3.core.Direction.Unspecified
type ChiselException = chisel3.internal.ChiselException
- class EnqIO[+T <: Data](gen: T) extends DecoupledIO(gen) {
- def init(): Unit = {
- this.noenq()
- }
- override def cloneType: this.type = EnqIO(gen).asInstanceOf[this.type]
- }
- class DeqIO[+T <: Data](gen: T) extends DecoupledIO(gen) {
- val Data = chisel3.core.Data
- Data.setFirrtlDirection(this, Data.getFirrtlDirection(this).flip)
- Binding.bind(this, FlippedBinder, "Error: Cannot flip ")
- def init(): Unit = {
- this.nodeq()
- }
- override def cloneType: this.type = DeqIO(gen).asInstanceOf[this.type]
- }
- object EnqIO {
- def apply[T<:Data](gen: T): EnqIO[T] = new EnqIO(gen)
- }
- object DeqIO {
- def apply[T<:Data](gen: T): DeqIO[T] = new DeqIO(gen)
- }
-
// Debugger/Tester access to internal Chisel data structures and methods.
def getDataElements(a: Aggregate): Seq[Element] = {
a.allElements
diff --git a/src/main/scala/chisel3/testers/TesterDriver.scala b/src/main/scala/chisel3/testers/TesterDriver.scala
index 586fa780..76b9a2e9 100644
--- a/src/main/scala/chisel3/testers/TesterDriver.scala
+++ b/src/main/scala/chisel3/testers/TesterDriver.scala
@@ -3,15 +3,13 @@
package chisel3.testers
import chisel3._
-import scala.io.Source
-import scala.sys.process._
import java.io._
object TesterDriver extends BackendCompilationUtilities {
/** Copy the contents of a resource to a destination file.
*/
def copyResourceToFile(name: String, file: File) {
- val in = getClass().getResourceAsStream(name)
+ val in = getClass.getResourceAsStream(name)
if (in == null) {
throw new FileNotFoundException(s"Resource '$name'")
}
@@ -22,7 +20,9 @@ object TesterDriver extends BackendCompilationUtilities {
/** For use with modules that should successfully be elaborated by the
* frontend, and which can be turned into executables with assertions. */
- def execute(t: () => BasicTester, additionalVResources: Seq[String] = Seq()): Boolean = {
+ def execute(t: () => BasicTester,
+ additionalVResources: Seq[String] = Seq(),
+ runFirrtlasProcess: Boolean = false): Boolean = {
// Invoke the chisel compiler to get the circuit's IR
val circuit = Driver.elaborate(finishWrapper(t))
@@ -46,13 +46,28 @@ object TesterDriver extends BackendCompilationUtilities {
out
})
- // Use sys.Process to invoke a bunch of backend stuff, then run the resulting exe
- if ((firrtlToVerilog(target, path) #&&
+ if(runFirrtlasProcess) {
+ // Use sys.Process to invoke a bunch of backend stuff, then run the resulting exe
+ if ((firrtlToVerilog(target, path) #&&
verilogToCpp(target, target, path, additionalVFiles, cppHarness) #&&
- cppToExe(target, path)).! == 0) {
- executeExpectingSuccess(target, path)
- } else {
- false
+ cppToExe(target, path)).! == 0) {
+ executeExpectingSuccess(target, path)
+ } else {
+ false
+ }
+ }
+ else {
+ // Compile firrtl
+ if (!compileFirrtlToVerilog(target, path)) {
+ return false
+ }
+ // Use sys.Process to invoke a bunch of backend stuff, then run the resulting exe
+ if ((verilogToCpp(target, target, path, additionalVFiles, cppHarness) #&&
+ cppToExe(target, path)).! == 0) {
+ executeExpectingSuccess(target, path)
+ } else {
+ false
+ }
}
}
/**
diff --git a/src/main/scala/chisel3/util/BitPat.scala b/src/main/scala/chisel3/util/BitPat.scala
index 972010a6..e58258c7 100644
--- a/src/main/scala/chisel3/util/BitPat.scala
+++ b/src/main/scala/chisel3/util/BitPat.scala
@@ -82,6 +82,7 @@ sealed class BitPat(val value: BigInt, val mask: BigInt, width: Int) {
def getWidth: Int = width
def === (that: UInt): Bool = macro SourceInfoTransform.thatArg
def =/= (that: UInt): Bool = macro SourceInfoTransform.thatArg
+ @deprecated("Use '=/=', which avoids potential precedence problems", "chisel3")
def != (that: UInt): Bool = macro SourceInfoTransform.thatArg
def do_=== (that: UInt)(implicit sourceInfo: SourceInfo): Bool = value.asUInt === (that & mask.asUInt) // scalastyle:ignore method.name