diff options
| author | Henry Cook | 2015-08-05 00:54:32 -0700 |
|---|---|---|
| committer | Andrew Waterman | 2015-08-05 16:36:08 -0700 |
| commit | f98e9e4143a113ac1020ed20c5e01b41aa29efe5 (patch) | |
| tree | 89fa57975e1f137ee184aafdc7a0a81ec09aa994 /src/main/scala/Chisel/Driver.scala | |
| parent | a02d788d9e9c4b42fd866e5c34e42aa771aab68c (diff) | |
Massive Driver simplification, some tweaks to Parameter api
Diffstat (limited to 'src/main/scala/Chisel/Driver.scala')
| -rw-r--r-- | src/main/scala/Chisel/Driver.scala | 389 |
1 files changed, 57 insertions, 332 deletions
diff --git a/src/main/scala/Chisel/Driver.scala b/src/main/scala/Chisel/Driver.scala index 5baaafaf..0d2b48b5 100644 --- a/src/main/scala/Chisel/Driver.scala +++ b/src/main/scala/Chisel/Driver.scala @@ -29,364 +29,89 @@ */ package Chisel -import Builder._ -import ChiselError._ +package testers import collection.mutable.{ArrayBuffer, HashSet, HashMap, Stack, LinkedHashSet, Queue => ScalaQueue} import scala.math.min -import java.io.File -import java.io.InputStream -import java.io.OutputStream -import java.io.PrintStream trait FileSystemUtilities { /** Ensures a directory *dir* exists on the filesystem. */ def ensureDir(dir: String): String = { val d = dir + (if (dir == "" || dir(dir.length-1) == '/') "" else "/") - new File(d).mkdirs() + new java.io.File(d).mkdirs() d } - def createOutputFile(name: String): java.io.FileWriter = { - val baseDir = ensureDir(Driver.targetDir) - new java.io.FileWriter(baseDir + name) + def createOutputFile(name: String, contents: String) { + val f = new java.io.FileWriter(name) + f.write(contents) + f.close } -} - -class ChiselException(message: String, cause: Throwable) extends Exception(message, cause) - -object throwException { - def apply(s: String, t: Throwable = null) = { - val xcpt = new ChiselException(s, t) - findFirstUserLine(xcpt.getStackTrace) foreach { u => xcpt.setStackTrace(Array(u)) } - throw xcpt - } -} - -object chiselMain { - val wrapped = true - val unwrapped = false - - def apply[T <: Module](args: Array[String], gen: () => T): (Circuit, T) = - Driver(args, gen, wrapped) - - def apply[T <: Module](args: Array[String], gen: () => T, ftester: T => Tester[T]): (Circuit, T) = - Driver(args, gen, ftester, wrapped) - - // Assumes gen needs to be wrapped in Module() - def run[T <: Module] (args: Array[String], gen: () => T): (Circuit, T) = - Driver(args, gen, unwrapped) - - def run[T <: Module] (args: Array[String], gen: () => T, ftester: T => Tester[T]): (Circuit, T) = - Driver(args, gen, ftester, unwrapped) -} - -//Is this antiquated? -object chiselMainTest { - def apply[T <: Module](args: Array[String], gen: () => T)(tester: T => Tester[T]): (Circuit, T) = { - chiselMain(args, gen, tester) - } -} -object Driver extends FileSystemUtilities{ - def apply[T <: Module](args: Array[String], gen: () => T, wrapped:Boolean = true): (Circuit, T) = { - initChisel(args) - try { - if(wrapped) execute(gen) else executeUnwrapped(gen) - } finally { - ChiselError.report - if (ChiselError.hasErrors && !getLineNumbers) { - println("Re-running Chisel in debug mode to obtain erroneous line numbers...") - // apply(args :+ "--lineNumbers", gen, wrapped) + def appendString(s1:Option[String],s2:Option[String]):String = { + if(s1.isEmpty && s2.isEmpty) "" else { + if(!s1.isEmpty) { + s1.get + (if(!s2.isEmpty) "." + s2.get else "") + } else { + if(!s2.isEmpty) s2.get else "" } } } - def apply[T <: Module](args: Array[String], gen: () => T, - ftester: T => Tester[T], wrapped:Boolean): (Circuit, T) = { - val (circuit, mod) = apply(args, gen, wrapped) - if (isTesting) test(mod, ftester) - (circuit, mod) - } + def getArg(s:String,i:Int):String = s.split('.')(i) +} - private def executeUnwrapped[T <: Module](gen: () => T): (Circuit, T) = { - if (!chiselConfigMode.isEmpty && !chiselConfigClassName.isEmpty) { - println("CHISEL PARAMS") - val name = appendString(chiselProjectName,chiselConfigClassName) - val config = try { - Class.forName(name).newInstance.asInstanceOf[ChiselConfig] - } catch { - case e: java.lang.ClassNotFoundException => - throwException("Could not find the ChiselConfig subclass you asked for (\"" + - name + "\"), did you misspell it?", e) - } - val world = if(chiselConfigMode.get == "collect") { - new Collector(config.topDefinitions,config.knobValues) - } else { new Instance(config.topDefinitions,config.knobValues) } - val p = Parameters.root(world) - config.topConstraints.foreach(c => p.constrain(c)) - val (circuit, mod) = execute(() => Module(gen())(p)) - if(chiselConfigMode.get == "collect") { - val v = createOutputFile(chiselConfigClassName.get + ".knb") - v.write(world.getKnobs) - v.close - val w = createOutputFile(chiselConfigClassName.get + ".cst") - w.write(world.getConstraints) - w.close - } - (circuit, mod) - } - else { - execute(() => Module(gen())) +object Driver extends FileSystemUtilities { + + /** 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 = appendString(projectName,Some(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) } - private def execute[T <: Module](gen: () => T): (Circuit, T) = { - val emitter = new Emitter - ChiselError.info("Elaborating design") - val (c, mod) = build{ gen() } - if (!isTesting) { - ChiselError.info(s"Emitting circuit ${c.main}") - val s = emitter.emit( c ) - val filename = c.main + ".fir" - val out = createOutputFile(filename) - out.write(s) - /* Params - If dumping design, dump space to pDir*/ - if (chiselConfigMode == None || chiselConfigMode.get == "instance") { - if(chiselConfigDump && !Dump.dump.isEmpty) { - val w = createOutputFile(appendString(Some(topComponent.name),chiselConfigClassName) + ".prm") - w.write(Dump.getDump); w.close - } - } - out.close() - } - ChiselError.info("Finished") - (c, mod) + /** 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) } - - private def test[T <: Module](mod: T, ftester: T => Tester[T]): Unit = { - // We shouldn't have to do this. There should be a class of Builder that doesn't pushCommand. - Builder.pushCommands - var res = false - var tester: Tester[T] = null + + /** 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. + */ + def elaborate[T <: Module](gen: () => T, p: Parameters = Parameters.empty) { try { - tester = ftester(mod) + ChiselError.clear() + ChiselError.info("Elaborating design...") + val ir = build(Module(gen())(p)) + ChiselError.info("Done elaborating.") + + val name = ir.main +"."+ p.getClass.getSimpleName + createOutputFile(s"$name.knb", p.getKnobs) + createOutputFile(s"$name.cst", p.getConstraints) + createOutputFile(s"$name.prm", Dump.getDump) + createOutputFile(s"$name.fir", emit(ir)) } finally { - if (tester != null && tester.process != null) - res = tester.finish() - } - println(if (res) "PASSED" else "*** FAILED ***") - if(!res) throwException("Module under test FAILED at least one test vector.") - } - - def elapsedTime: Long = System.currentTimeMillis - startTime - - def initChisel(args: Array[String]): Unit = { - ChiselError.clear() - warnInputs = false - warnOutputs = false - saveConnectionWarnings = false - saveComponentTrace = false - dontFindCombLoop = false - isGenHarness = false - isDebug = false - getLineNumbers = false - isCSE = false - isIoDebug = true - isVCD = false - isVCDMem = false - isReportDims = false - targetDir = "." - components.clear() - sortedComps.clear() - compStack.clear() - stackIndent = 0 - printStackStruct.clear() - // blackboxes.clear() - chiselOneHotMap.clear() - chiselOneHotBitMap.clear() - isCompiling = false - isCheckingPorts = false - isTesting = false - isDebugMem = false - isSupportW0W = false - partitionIslands = false - lineLimitFunctions = 0 - minimumLinesPerFile = 0 - shadowRegisterInObject = false - allocateOnlyNeededShadowRegisters = false - compileInitializationUnoptimized = false - useSimpleQueue = false - parallelMakeJobs = 0 - isVCDinline = false - isSupportW0W = false - hasMem = false - hasSRAM = false - sramMaxSize = 0 - topComponent = null - // clocks.clear() - // implicitReset.isIo = true - // implicitReset.setName("reset") - // implicitClock = new Clock() - // implicitClock.setName("clk") - isInGetWidth = false - startTime = System.currentTimeMillis - modStackPushed = false - - readArgs(args) - } - - private def readArgs(args: Array[String]): Unit = { - var i = 0 - var backendName = "c" // Default backend is Cpp. - while (i < args.length) { - val arg = args(i) - arg match { - case "--Wall" => { - saveConnectionWarnings = true - saveComponentTrace = true - isCheckingPorts = true - } - case "--wi" => warnInputs = true - case "--wo" => warnOutputs = true - case "--wio" => {warnInputs = true; warnOutputs = true} - case "--Wconnection" => saveConnectionWarnings = true - case "--Wcomponent" => saveComponentTrace = true - case "--W0W" => isSupportW0W = true - case "--noW0W" => isSupportW0W = false - case "--noCombLoop" => dontFindCombLoop = true - case "--genHarness" => isGenHarness = true - case "--debug" => isDebug = true - case "--lineNumbers" => getLineNumbers = true - case "--cse" => isCSE = true - case "--ioDebug" => isIoDebug = true - case "--noIoDebug" => isIoDebug = false - case "--vcd" => isVCD = true - case "--vcdMem" => isVCDMem = true - case "--v" => backendName = "v" - case "--inlineMem" => isInlineMem = true - case "--noInlineMem" => isInlineMem = false - case "--assert" => isAssert = true - case "--noAssert" => isAssert = false - case "--debugMem" => isDebugMem = true - case "--partitionIslands" => partitionIslands = true - case "--lineLimitFunctions" => lineLimitFunctions = args(i + 1).toInt; i += 1 - case "--minimumLinesPerFile" => minimumLinesPerFile = args(i + 1).toInt; i += 1 - case "--shadowRegisterInObject" => shadowRegisterInObject = true - case "--allocateOnlyNeededShadowRegisters" => allocateOnlyNeededShadowRegisters = true - case "--compileInitializationUnoptimized" => compileInitializationUnoptimized = true - case "--useSimpleQueue" => useSimpleQueue = true - case "--parallelMakeJobs" => parallelMakeJobs = args(i + 1).toInt; i += 1 - case "--isVCDinline" => isVCDinline = true - case "--backend" => backendName = args(i + 1); i += 1 - case "--compile" => isCompiling = true - case "--test" => isTesting = true - case "--targetDir" => targetDir = args(i + 1); i += 1 - case "--include" => includeArgs = args(i + 1).split(' ').toList; i += 1 - case "--checkPorts" => isCheckingPorts = true - case "--reportDims" => isReportDims = true - //Jackhammer Flags - case "--configCollect" => chiselConfigMode = Some("collect"); chiselConfigClassName = Some(getArg(args(i+1),1)); chiselProjectName = Some(getArg(args(i+1),0)); i+=1; //dump constraints in dse dir - case "--configInstance" => chiselConfigMode = Some("instance"); chiselConfigClassName = Some(getArg(args(i+1),1)); chiselProjectName = Some(getArg(args(i+1),0)); i+=1; //use ChiselConfig to supply parameters - case "--configDump" => chiselConfigDump = true; //when using --configInstance, write Dump parameters to .prm file in targetDir - case "--dumpTestInput" => dumpTestInput = true - case "--testerSeed" => { - testerSeedValid = true - testerSeed = args(i+1).toLong - i += 1 - } - case "--emitTempNodes" => { - isDebug = true - emitTempNodes = true - } - case any => ChiselError.warning("'" + arg + "' is an unknown argument.") - } - i += 1 - } - // Check for bogus flags - if (!isVCD) { - isVCDinline = false - } - } - - var warnInputs = false - var warnOutputs = false - var saveConnectionWarnings = false - var saveComponentTrace = false - var dontFindCombLoop = false - var isDebug = false - var getLineNumbers = false - var isCSE = false - var isIoDebug = true - var isVCD = false - var isVCDMem = false - var isInlineMem = true - var isGenHarness = false - var isReportDims = false - var includeArgs: List[String] = Nil - var targetDir: String = null - var isCompiling = false - var isCheckingPorts = false - var isTesting = false - var isAssert = true - var isDebugMem = false - var partitionIslands = false - var lineLimitFunctions = 0 - var minimumLinesPerFile = 0 - var shadowRegisterInObject = false - var allocateOnlyNeededShadowRegisters = false - var compileInitializationUnoptimized = false - var useSimpleQueue = false - var parallelMakeJobs = 0 - var isVCDinline = false - var isSupportW0W = false - var hasMem = false - var hasSRAM = false - var sramMaxSize = 0 - var topComponent: Module = null - val components = ArrayBuffer[Module]() - val sortedComps = ArrayBuffer[Module]() - // val blackboxes = ArrayBuffer[BlackBox]() - val chiselOneHotMap = HashMap[(UInt, Int), UInt]() - val chiselOneHotBitMap = HashMap[(Bits, Int), Bool]() - val compStack = Stack[Module]() - val parStack = new Stack[Parameters] - var stackIndent = 0 - val printStackStruct = ArrayBuffer[(Int, Module)]() - // val clocks = ArrayBuffer[Clock]() - // val implicitReset = Bool(INPUT) - // var implicitClock: Clock = null - var isInGetWidth: Boolean = false - var modStackPushed: Boolean = false - var modAdded: Boolean = false - var startTime = 0L - /* ChiselConfig flags */ - var chiselConfigClassName: Option[String] = None - var chiselProjectName: Option[String] = None - var chiselConfigMode: Option[String] = None - var chiselConfigDump: Boolean = false - - def appendString(s1:Option[String],s2:Option[String]):String = { - if(s1.isEmpty && s2.isEmpty) "" else { - if(!s1.isEmpty) { - s1.get + (if(!s2.isEmpty) "." + s2.get else "") - } else { - if(!s2.isEmpty) s2.get else "" - } + ChiselError.report } } - def getArg(s:String,i:Int):String = s.split('.')(i) - - // Setting this to TRUE will case the test harness to print its - // standard input stream to a file. - var dumpTestInput = false - // Setting this to TRUE will initialize the tester's RNG with the - // seed below. - var testerSeedValid = false - var testerSeed = System.currentTimeMillis() - // Setting this to TRUE will result in temporary values (ie, nodes - // named "T*") to be emited to the VCD file. - var emitTempNodes = false } |
