diff options
Diffstat (limited to 'src/main/scala/Chisel/Driver.scala')
| -rw-r--r-- | src/main/scala/Chisel/Driver.scala | 141 |
1 files changed, 83 insertions, 58 deletions
diff --git a/src/main/scala/Chisel/Driver.scala b/src/main/scala/Chisel/Driver.scala index 5247dc0f..64356b21 100644 --- a/src/main/scala/Chisel/Driver.scala +++ b/src/main/scala/Chisel/Driver.scala @@ -2,75 +2,100 @@ package Chisel -import collection.mutable.{ArrayBuffer, HashSet, HashMap, Stack, LinkedHashSet, Queue => ScalaQueue} -import scala.math.min +import scala.sys.process._ +import java.io._ trait FileSystemUtilities { - def createOutputFile(name: String, contents: String) { - val f = new java.io.FileWriter(name) - f.write(contents) - f.close + def writeTempFile(pre: String, post: String, contents: String): File = { + val t = File.createTempFile(pre, post) + val w = new FileWriter(t) + w.write(contents) + w.close() + t + } + + // This "fire-and-forgets" the method, which can be lazily read through + // a Stream[String], and accumulates all errors on a StringBuffer + def sourceFilesAt(baseDir: String): (Stream[String], StringBuffer) = { + val buffer = new StringBuffer() + val cmd = Seq("find", baseDir, "-name", "*.scala", "-type", "f") + val lines = cmd lines_! ProcessLogger(buffer append _) + (lines, buffer) } } -object Driver extends FileSystemUtilities { +trait BackendCompilationUtilities { + def makeHarness(template: String => String, post: String)(f: File): File = { + val prefix = f.toString.split("/").last + val vf = new File(f.toString + post) + val w = new FileWriter(vf) + w.write(template(prefix)) + w.close() + vf + } - /** Instantiates a ChiselConfig class with the given name and uses it for elaboration */ - def elaborateWithConfigName[T <: Module]( - gen: () => T, - configClassName: String, - projectName: Option[String] = None, - collectConstraints: Boolean = false): Unit = { - val className = projectName match { - case Some(pn) => s"$pn.$configClassName" - case None => configClassName - } - val config = try { - Class.forName(className).newInstance.asInstanceOf[ChiselConfig] - } catch { - case e: java.lang.ClassNotFoundException => - throwException("Could not find the ChiselConfig subclass you asked for (i.e. \"" + - className + "\"), did you misspell it?", e) - } - elaborateWithConfig(gen, config, collectConstraints) + def firrtlToVerilog(prefix: String, dir: File): ProcessBuilder = { + Process( + Seq("firrtl", + "-i", s"$prefix.fir", + "-o", s"$prefix.v", + "-X", "verilog"), + dir) } - /** Uses the provided ChiselConfig for elaboration */ - def elaborateWithConfig[T <: Module]( - gen: () => T, - config: ChiselConfig, - collectConstraints: Boolean = false): Unit = { - val world = if(collectConstraints) config.toCollector else config.toInstance - val p = Parameters.root(world) - config.topConstraints.foreach(c => p.constrain(c)) - elaborate(gen, p, config) + def verilogToCpp( + prefix: String, + dir: File, + vDut: File, + cppHarness: File, + vH: File): ProcessBuilder = + Seq("verilator", + "--cc", vDut.toString, + "--assert", + "--Wno-fatal", + "--trace", + "-O2", + "+define+TOP_TYPE=V"+prefix, + "-CFLAGS", s"""-Wno-undefined-bool-conversion -O2 -DTOP_TYPE=V$prefix -include ${vH.toString}""", + "-Mdir", dir.toString, + "--exe", cppHarness.toString) + + def cppToExe(prefix: String, dir: File): ProcessBuilder = + Seq("make", "-C", dir.toString, "-j", "-f", s"V${prefix}.mk", s"V${prefix}") + + def executeExpectingFailure( + prefix: String, + dir: File, + assertionMsg: String = "Assertion failed"): Boolean = { + var triggered = false + val e = Process(s"./V${prefix}", dir) ! ProcessLogger(line => + triggered = triggered || line.contains(assertionMsg)) + triggered } - /** Elaborates the circuit specified in the gen function, optionally uses - * a parameter space to supply context-aware values. - * TODO: Distinguish between cases where we dump to file vs return IR for - * use by other Drivers. - */ - private[Chisel] def elaborateWrappedModule[T <: Module](gen: () => T, p: Parameters, c: Option[ChiselConfig]) { - val ir = Builder.build(gen()) - val name = c match { - case None => ir.name - case Some(config) => s"${ir.name}.$config" - } - createOutputFile(s"$name.knb", p.getKnobs) - createOutputFile(s"$name.cst", p.getConstraints) - createOutputFile(s"$name.prm", ir.parameterDump.getDump) - createOutputFile(s"$name.fir", ir.emit) + def executeExpectingSuccess(prefix: String, dir: File): Boolean = { + !executeExpectingFailure(prefix, dir) } - def elaborate[T <: Module](gen: () => T): Unit = - elaborate(gen, Parameters.empty) - def elaborate[T <: Module](gen: () => T, p: Parameters): Unit = - elaborateWrappedModule(() => Module(gen())(p), p, None) - private def elaborate[T <: Module](gen: () => T, p: Parameters, c: ChiselConfig): Unit = - elaborateWrappedModule(() => Module(gen())(p), p, Some(c)) + } -object chiselMain { - def apply[T <: Module](args: Array[String], gen: () => T, p: Parameters = Parameters.empty): Unit = - Driver.elaborateWrappedModule(gen, p, None) +object Driver extends FileSystemUtilities with BackendCompilationUtilities { + + /** Elaborates the Module specified in the gen function into a Circuit + * + * @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 emit[T <: Module](gen: () => T): String = elaborate(gen).emit + + def dumpFirrtl(ir: Circuit, optName: Option[File]): File = { + val f = optName.getOrElse(new File(ir.name + ".fir")) + val w = new FileWriter(f) + w.write(ir.emit) + w.close() + f + } } |
