summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHenry Cook2015-08-05 00:54:32 -0700
committerAndrew Waterman2015-08-05 16:36:08 -0700
commitf98e9e4143a113ac1020ed20c5e01b41aa29efe5 (patch)
tree89fa57975e1f137ee184aafdc7a0a81ec09aa994
parenta02d788d9e9c4b42fd866e5c34e42aa771aab68c (diff)
Massive Driver simplification, some tweaks to Parameter api
-rw-r--r--src/main/scala/Chisel/AdvTester.scala2
-rw-r--r--src/main/scala/Chisel/Core.scala40
-rw-r--r--src/main/scala/Chisel/Driver.scala389
-rw-r--r--src/main/scala/Chisel/Error.scala15
-rw-r--r--src/main/scala/Chisel/Parameters.scala6
-rw-r--r--src/main/scala/Chisel/Tester.scala71
6 files changed, 139 insertions, 384 deletions
diff --git a/src/main/scala/Chisel/AdvTester.scala b/src/main/scala/Chisel/AdvTester.scala
index f0e76b2e..9520932b 100644
--- a/src/main/scala/Chisel/AdvTester.scala
+++ b/src/main/scala/Chisel/AdvTester.scala
@@ -32,7 +32,7 @@
Written by Stephen Twigg, Eric Love
Version 0.9
*/
-package Chisel.AdvTester // May eventually add this to the base Chisel package
+package Chisel.testers
import Chisel._
import scala.collection.mutable.ArrayBuffer
diff --git a/src/main/scala/Chisel/Core.scala b/src/main/scala/Chisel/Core.scala
index 52b7ea48..b5bebe33 100644
--- a/src/main/scala/Chisel/Core.scala
+++ b/src/main/scala/Chisel/Core.scala
@@ -16,14 +16,13 @@ class IdGen {
object Builder {
val components = new ArrayBuffer[Component]()
val idGen = new IdGen
+ val paramz = new Stack[Parameters]
+ def pushParameters(p: Parameters) { paramz.push(p) }
+ def popParameters { paramz.pop }
val modulez = new Stack[Module]()
- def pushModule(mod: Module) {
- modulez.push(mod)
- }
+ def pushModule(mod: Module) { modulez.push(mod) }
+ def popModule { modulez.pop }
def getComponent(): Module = if (modulez.length > 0) modulez.head else null
- def popModule() {
- modulez.pop
- }
val globalNamespace = new FIRRTLNamespace
def namespace = if (modulez.isEmpty) globalNamespace else modulez.head._namespace
val commandz = new Stack[ArrayBuffer[Command]]()
@@ -71,14 +70,20 @@ object Builder {
refmap(id._id)
}
- def build[T <: Module](f: => T): (Circuit, T) = {
+ def build[T <: Module](f: => T): Circuit = {
val (cmd, mod) = collectCommands(f)
setRefForId(mod, mod.name)
- (Circuit(components, components.last.name), mod)
+ Circuit(components, components.last.name)
}
}
+object build {
+ def apply[T <: Module](f: => T): Circuit = {
+ Builder.build(f)
+ }
+}
+
import Builder._
/// CHISEL IR
@@ -350,7 +355,7 @@ abstract class Data(dirArg: Direction) extends Id {
}
def toPort: Port = Port(this, toType)
- def params = if(Driver.parStack.isEmpty) Parameters.empty else Driver.parStack.top
+ def params = if(paramz.isEmpty) Parameters.empty else paramz.top
}
object Wire {
@@ -932,16 +937,16 @@ object Bundle {
val keywords = HashSet[String]("flip", "asInput", "asOutput",
"cloneType", "clone", "toBits")
def apply[T <: Bundle](b: => T)(implicit p: Parameters): T = {
- Driver.parStack.push(p.push)
+ pushParameters(p.push)
val res = b
- Driver.parStack.pop
+ popParameters
res
}
def apply[T <: Bundle](b: => T, f: PartialFunction[Any,Any]): T = {
val q = params.alterPartial(f)
apply(b)(q)
}
- private def params = if(Driver.parStack.isEmpty) Parameters.empty else Driver.parStack.top
+ private def params = if(paramz.isEmpty) Parameters.empty else paramz.top
}
class Bundle extends Aggregate(NO_DIR) {
@@ -1004,8 +1009,7 @@ class Bundle extends Aggregate(NO_DIR) {
object Module {
def apply[T <: Module](bc: => T)(implicit p: Parameters = params): T = {
- Driver.modStackPushed = true
- Driver.parStack.push(p.push)
+ pushParameters(p.push)
val m = bc
m.setRefs
val cmd = popCommands
@@ -1014,7 +1018,7 @@ object Module {
val component = Component(m.name, ports, cmd)
components += component
pushCommand(DefInstance(m, m.name, ports))
- Driver.parStack.pop
+ popParameters
m.connectImplicitIOs
m
}
@@ -1022,7 +1026,7 @@ object Module {
val q = params.alterPartial(f)
apply(m)(q)
}
- private def params = if(Driver.parStack.isEmpty) Parameters.empty else Driver.parStack.top
+ private def params = if(paramz.isEmpty) Parameters.empty else paramz.top
}
abstract class Module(_clock: Clock = null, _reset: Bool = null) extends Id {
@@ -1222,3 +1226,7 @@ class Emitter {
def emit(e: Circuit): String =
withIndent{ "circuit " + e.main + " : " + join0(e.components.map(x => emit(x)), newline) } + newline
}
+
+object emit {
+ def apply(e: Circuit) = new Emitter().emit(e)
+}
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
}
diff --git a/src/main/scala/Chisel/Error.scala b/src/main/scala/Chisel/Error.scala
index 1ad5414d..287b65eb 100644
--- a/src/main/scala/Chisel/Error.scala
+++ b/src/main/scala/Chisel/Error.scala
@@ -31,6 +31,16 @@
package Chisel
import scala.collection.mutable.ArrayBuffer
+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)
+ ChiselError.findFirstUserLine(xcpt.getStackTrace) foreach { u => xcpt.setStackTrace(Array(u)) }
+ throw xcpt
+ }
+}
+
/** This Singleton implements a log4j compatible interface.
It is used through out the Chisel package to report errors and warnings
detected at runtime.
@@ -39,6 +49,9 @@ object ChiselError {
var hasErrors: Boolean = false;
val ChiselErrors = new ArrayBuffer[ChiselError];
+ var startTime = System.currentTimeMillis
+ def elapsedTime: Long = System.currentTimeMillis - startTime
+
def clear() {
ChiselErrors.clear()
hasErrors = false
@@ -58,7 +71,7 @@ object ChiselError {
/** Emit an informational message
(useful to track long running passes) */
def info(m: String): Unit =
- println(tag("info", Console.MAGENTA) + " [%2.3f] ".format(Driver.elapsedTime/1e3) + m)
+ println(tag("info", Console.MAGENTA) + " [%2.3f] ".format(elapsedTime/1e3) + m)
/** emit a warning message */
def warning(m: => String) {
diff --git a/src/main/scala/Chisel/Parameters.scala b/src/main/scala/Chisel/Parameters.scala
index 9a117ee0..b6d2f328 100644
--- a/src/main/scala/Chisel/Parameters.scala
+++ b/src/main/scala/Chisel/Parameters.scala
@@ -119,6 +119,8 @@ class ChiselConfig(
}
}
+ def toCollector = new Collector(this.topDefinitions, this.knobValues)
+ def toInstance = new Instance(this.topDefinitions, this.knobValues)
}
object Dump {
@@ -470,6 +472,10 @@ final class Parameters(
def alterPartial(mask:PartialFunction[Any,Any]) =
_alter(Parameters.makeMask(mask))
+
+ def getConstraints:String = _world.getConstraints
+
+ def getKnobs:String = _world.getKnobs
}
diff --git a/src/main/scala/Chisel/Tester.scala b/src/main/scala/Chisel/Tester.scala
index 8f013f7b..9c6f51d0 100644
--- a/src/main/scala/Chisel/Tester.scala
+++ b/src/main/scala/Chisel/Tester.scala
@@ -28,7 +28,7 @@
MODIFICATIONS.
*/
-package Chisel
+package Chisel.testers
import Chisel._
import scala.math._
import scala.collection.mutable.ArrayBuffer
@@ -43,6 +43,36 @@ import scala.sys.process._
import scala.io.Source._
import Literal._
+object TesterDriver extends FileSystemUtilities {
+ // Setting this to TRUE will initialize the tester's RNG with the
+ // seed below.
+ // case "--testerSeed" => {
+ // testerSeedValid = true
+ // testerSeed = args(i+1).toLong }
+ var testerSeedValid = false
+ var testerSeed = System.currentTimeMillis()
+
+ // Setting this to TRUE will case the test harness to print its
+ // standard input stream to a file.
+ var dumpTestInput = false
+
+ 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
+ try {
+ tester = ftester(mod)
+ } 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.")
+ }
+
+}
+
case class Poke(val node: Data, val index: Int, val value: BigInt);
class Snapshot(val t: Int) {
@@ -50,7 +80,7 @@ class Snapshot(val t: Int) {
}
class ManualTester[+T <: Module]
- (val c: T, val isT: Boolean = true, val skipVPDMessage: Boolean = true) {
+ (val name: String, val isT: Boolean = true, val skipVPDMessage: Boolean = true) {
var testIn: InputStream = null
var testOut: OutputStream = null
var testErr: InputStream = null
@@ -73,17 +103,6 @@ class ManualTester[+T <: Module]
}
}
- // TODO: MOVE TO SOMEWHERE COMMON TO BACKEND
- def ensureDir(dir: String): String = {
- val d = dir + (if (dir == "" || dir(dir.length-1) == '/') "" else "/")
- new File(d).mkdirs()
- d
- }
- def createOutputFile(name: String): java.io.FileWriter = {
- val baseDir = ensureDir(Driver.targetDir)
- new java.io.FileWriter(baseDir + name)
- }
-
def puts(str: String) = {
while (testOut == null) { Thread.sleep(100) }
for (e <- str) testOut.write(e);
@@ -152,20 +171,6 @@ class ManualTester[+T <: Module]
return sb.toString
}
- /*
- def setClocks(clocks: HashMap[Clock, Int]) {
- var cmd = "set_clocks"
- for (clock <- Driver.clocks) {
- if (clock.srcClock == null) {
- val s = BigInt(clocks(clock)).toString(16)
- cmd = cmd + " " + s
- }
- }
- emulatorCmd(cmd)
- // TODO: check for errors in return
- }
- */
-
def doPeekBits(name: String, off: Int = -1): BigInt = {
if (name == "") {
println("Unable to peek data " + name) // TODO: USE DATA
@@ -353,16 +358,14 @@ class ManualTester[+T <: Module]
"EXPECT " + data.debugName + " <- " + gotFLoat + " == " + expectedFloat)
}
- val rnd = if (Driver.testerSeedValid) new Random(Driver.testerSeed) else new Random()
+ val rnd = if (TesterDriver.testerSeedValid) new Random(TesterDriver.testerSeed) else new Random()
var process: Process = null
def start(): Process = {
- val n = Driver.appendString(Some(c.name),Driver.chiselConfigClassName)
- val target = "cd " + Driver.targetDir + " && ./" + n
- val cmd = target
+ val cmd = "./" + name
println("RUNNING " + cmd)
- println("SEED " + Driver.testerSeed)
- println("STARTING " + n)
+ println("SEED " + TesterDriver.testerSeed)
+ println("STARTING " + name)
val processBuilder = Process(Seq("bash", "-c", cmd))
val pio = new ProcessIO(in => testOut = in, out => testIn = out, err => testErr = err)
process = processBuilder.run(pio)
@@ -399,7 +402,7 @@ class ManualTester[+T <: Module]
}
}
-class Tester[+T <: Module](c: T, isTrace: Boolean = true, skipVPDMessage: Boolean = false) extends ManualTester(c, isTrace, skipVPDMessage) {
+class Tester[+T <: Module](c: T, isTrace: Boolean = true, skipVPDMessage: Boolean = false) extends ManualTester(c.name, isTrace, skipVPDMessage) {
start()
}