summaryrefslogtreecommitdiff
path: root/src/main/scala
diff options
context:
space:
mode:
authorHenry Cook2015-08-06 16:36:27 -0700
committerHenry Cook2015-08-06 16:36:27 -0700
commit1db280299c08ec08053cd23aac752ebcc8ae09f7 (patch)
tree1e65701be887cee28f1bdde304c6112c08868355 /src/main/scala
parenta76e77774976365e9717ab5272870c99bb63982c (diff)
updated Tester compiles with a few abstracted fields
Diffstat (limited to 'src/main/scala')
-rw-r--r--src/main/scala/Chisel/testers/AdvTester.scala2
-rw-r--r--src/main/scala/Chisel/testers/Driver.scala60
-rw-r--r--src/main/scala/Chisel/testers/Tester.scala440
3 files changed, 272 insertions, 230 deletions
diff --git a/src/main/scala/Chisel/testers/AdvTester.scala b/src/main/scala/Chisel/testers/AdvTester.scala
index 9520932b..6db823ed 100644
--- a/src/main/scala/Chisel/testers/AdvTester.scala
+++ b/src/main/scala/Chisel/testers/AdvTester.scala
@@ -36,7 +36,7 @@ package Chisel.testers
import Chisel._
import scala.collection.mutable.ArrayBuffer
-class AdvTester[+T <: Module](val dut: T, isTrace: Boolean = false) extends Tester[T](dut, isTrace) {
+abstract class AdvTester[+T <: Module](val dut: T, isTrace: Boolean = false) extends Tester[T](dut, isTrace) {
val defaultMaxCycles = 1024
var cycles = 0
var pass = true
diff --git a/src/main/scala/Chisel/testers/Driver.scala b/src/main/scala/Chisel/testers/Driver.scala
index 778f2edf..294c77c1 100644
--- a/src/main/scala/Chisel/testers/Driver.scala
+++ b/src/main/scala/Chisel/testers/Driver.scala
@@ -31,7 +31,55 @@
package Chisel.testers
import Chisel._
+
+
+object CompilationUtilitiess {
+ import scala.util.Properties.envOrElse
+ import sys.process.stringSeqToProcess
+ protected val CC = envOrElse("CC", "g++" )
+ protected val CXX = envOrElse("CXX", "g++" )
+ protected val CCFLAGS = envOrElse("CCFLAGS", "")
+ protected val CXXFLAGS = envOrElse("CXXFLAGS", "")
+ protected val CPPFLAGS = envOrElse("CPPFLAGS", "")
+ protected val LDFLAGS = envOrElse("LDFLAGS", "")
+ protected val chiselENV = envOrElse("CHISEL", "")
+
+ def run(cmd: String) = {
+ val bashCmd = Seq("bash", "-c", cmd)
+ val c = bashCmd.!
+ ChiselError.info(cmd + " RET " + c)
+ c == 0
+ }
+
+ def cc(dir: String, name: String, flags: String = "", isCC: Boolean = false) {
+ val compiler = if (isCC) CC else CXX
+ val cmd = List(compiler, "-c", "-o", dir + name + ".o", flags, dir + name + ".cpp").mkString(" ")
+ if (!run(cmd)) throw new Exception("failed to compile " + name + ".cpp")
+ }
+
+ def link(dir: String, target: String, objects: Seq[String], isCC: Boolean = false, isLib: Boolean = false) {
+ val compiler = if (isCC) CC else CXX
+ val shared = if (isLib) "-shared" else ""
+ val ac = (List(compiler, LDFLAGS, shared, "-o", dir + target) ++ (objects map (dir + _))).mkString(" ")
+ if (!run(ac)) throw new Exception("failed to link " + objects.mkString(", "))
+ }
+}
+
+abstract class Backend
+class FloBackend extends Backend
+class VerilogBackend extends Backend {
+ def genHarness(c: Module, name: String) { }
+}
+
object TesterDriver {
+ val isVCD = false
+ val targetDir = "."
+ val backend: Backend = new VerilogBackend
+ val name = "test"
+ val circuit = Circuit(Seq(Component("top",Seq(Port(null,null)),Nil)),"main")
+ val testCommand: Option[String] = None
+
+
// Setting this to TRUE will initialize the tester's RNG with the
// seed below.
// case "--testerSeed" => {
@@ -45,17 +93,7 @@ object TesterDriver {
var dumpTestInput = false
private def test[T <: Module](mod: T, ftester: T => Tester[T]): Unit = {
- 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.")
+ ftester(mod).finish
}
-
}
diff --git a/src/main/scala/Chisel/testers/Tester.scala b/src/main/scala/Chisel/testers/Tester.scala
index d3ed7170..01d7b256 100644
--- a/src/main/scala/Chisel/testers/Tester.scala
+++ b/src/main/scala/Chisel/testers/Tester.scala
@@ -30,141 +30,105 @@
package Chisel.testers
import Chisel._
-import scala.math._
-import scala.collection.mutable.ArrayBuffer
-import scala.collection.mutable.HashMap
+import scala.collection.mutable.{ArrayBuffer, HashMap, Queue => ScalaQueue}
+import scala.collection.immutable.ListSet
import scala.util.Random
-import java.io.{File, IOException, InputStream, OutputStream, PrintStream}
-import java.lang.Double.longBitsToDouble
-import java.lang.Float.intBitsToFloat
-import java.lang.Double.doubleToLongBits
-import java.lang.Float.floatToIntBits
-import scala.sys.process._
-import scala.io.Source._
-import Literal._
-
-
-case class Poke(val node: Data, val index: Int, val value: BigInt);
-
-class Snapshot(val t: Int) {
- val pokes = new ArrayBuffer[Poke]()
-}
-
-class ManualTester[+T <: Module]
- (val name: String, val isT: Boolean = true, val skipVPDMessage: Boolean = true) {
- var testIn: InputStream = null
- var testOut: OutputStream = null
- var testErr: InputStream = null
- val sb = new StringBuilder()
+import java.io._
+import java.lang.Double.{longBitsToDouble, doubleToLongBits}
+import java.lang.Float.{intBitsToFloat, floatToIntBits}
+import scala.sys.process.{Process, ProcessIO}
+
+abstract class Tester[+T <: Module](c: T, isTrace: Boolean = true) extends FileSystemUtilities {
+ private var _testIn: Option[InputStream] = None
+ private var _testErr: Option[InputStream] = None
+ private var _testOut: Option[OutputStream] = None
+ private lazy val _reader: BufferedReader = new BufferedReader(new InputStreamReader(_testIn.get))
+ private lazy val _writer: BufferedWriter = new BufferedWriter(new OutputStreamWriter(_testOut.get))
+ private lazy val _logger: BufferedReader = new BufferedReader(new InputStreamReader(_testErr.get))
+ var t = 0 // simulation time
var delta = 0
- var t = 0
- var isTrace = isT
+ private val _pokeMap = HashMap[Bits, BigInt]()
+ private val _peekMap = HashMap[Bits, BigInt]()
+ private val _signalMap = HashMap[String, Int]()
+ val _clocks: List[(Clock, Int)]// = TesterDriver.clocks map (clk => clk -> clk.period.round.toInt)
+ private val _clockLens = HashMap(_clocks:_*)
+ private val _clockCnts = HashMap(_clocks:_*)
+ val _inputs: ListSet[Bits]
+ val _outputs: ListSet[Bits]
+ //ListSet(c.wires.unzip._2: _*) partition (_.dir == INPUT)
+ private var isStale = false
+ val _logs = ScalaQueue[String]()
+ def testOutputString = {
+ if(_logs.isEmpty) "" else _logs.dequeue
+ }
+ object SIM_CMD extends Enumeration { val RESET, STEP, UPDATE, POKE, PEEK, GETID, SETCLK, FIN = Value }
/**
* Waits until the emulator streams are ready. This is a dirty hack related
* to the way Process works. TODO: FIXME.
*/
def waitForStreams() = {
var waited = 0
- while (testOut == null || testIn == null || testErr == null) {
+ while (_testIn == None || _testOut == None || _testErr == None) {
Thread.sleep(100)
if (waited % 10 == 0 && waited > 30) {
- println("waiting for emulator process treams to be valid ...")
+ ChiselError.info("waiting for emulator process streams to be valid ...")
}
}
}
- def puts(str: String) = {
- while (testOut == null) { Thread.sleep(100) }
- for (e <- str) testOut.write(e);
+ private def writeln(str: String) {
+ _writer write str
+ _writer.newLine
+ _writer.flush
}
- /**
- * Sends a command to the emulator and returns the reply.
- * The standard protocol treats a single line as a command, which always
- * returns a single line of reply.
- */
- def emulatorCmd(str: String): String = {
- // validate cmd
- if (str contains "\n") {
- System.err.print(s"emulatorCmd($str): command should not contain newline")
- return "error"
+ private def dumpLogs = {
+ while (_logger.ready) {
+ _logs enqueue _logger.readLine
}
+ }
- waitForStreams()
-
- // send command to emulator
- for (e <- str) testOut.write(e);
- testOut.write('\n');
- testOut.flush()
-
- // read output from emulator
- var c = testIn.read
- sb.clear()
- while (c != '\n' && c != -1) {
- if (c == 0) {
- Thread.sleep(100)
- }
- sb += c.toChar
- // Look for a "PRINT" command.
- if (sb.length == 6 && sb.startsWith("PRINT ")) {
- do {
- c = testIn.read
- sb += c.toChar
- } while (c != ' ')
- // Get the PRINT character count.
- val printCommand = """^PRINT (\d+) """.r
- val printCommand(nChars) = sb.toString
- sb.clear()
- for (i <- 0 until nChars.toInt) {
- c = testIn.read
- sb += c.toChar
- }
- System.out.print(sb.toString())
- sb.clear()
- }
- c = testIn.read
+ private def readln: String = {
+ Option(_reader.readLine) match {
+ case None =>
+ dumpLogs
+ while (!_logs.isEmpty)
+ println(testOutputString)
+ throw new Exception("Errors occurred in simulation")
+ case Some(ln) => ln
}
+ }
- // drain errors
- try {
- while(testErr.available() > 0) {
- System.err.print(Character.toChars(testErr.read()))
- }
- } catch {
- case e : IOException => testErr = null; println("ERR EXCEPTION")
- }
+ private def sendCmd(cmd: SIM_CMD.Value) {
+ writeln(cmd.id.toString)
+ }
- if (sb == "error") {
- System.err.print(s"FAILED: emulatorCmd($str): returned error")
- ok = false
- }
- return sb.toString
- }
-
- def doPeekBits(name: String, off: Int = -1): BigInt = {
- if (name == "") {
- println("Unable to peek data " + name) // TODO: USE DATA
- -1
- } else {
- var cmd = ""
- if (off != -1) {
- cmd = "mem_peek " + name + " " + off;
- } else {
- cmd = "wire_peek " + name;
- }
- val s = emulatorCmd(cmd)
- val rv = BigInt(s.substring(2), 16)
- if (isTrace) println(" PEEK " + name + " " + (if (off >= 0) (off + " ") else "") + "-> " + s)
- rv
+ private val writeMask = int(-1L)
+ private def writeValue(v: BigInt, w: Int = 1) {
+ for (i <- ((w - 1) >> 6) to 0 by -1) {
+ writeln(((v >> (64 * i)) & writeMask).toString(16))
}
}
- def peekBits(data: Data, off: Int = -1): BigInt = {
- doPeekBits(data.debugName, off)
+ def dumpName(data: Data): String = TesterDriver.backend match {
+ case _: FloBackend => data.name
+ case _: VerilogBackend => data.name
+ }
+
+ def setClock(clk: Clock, len: Int) {
+ _clockLens(clk) = len
+ _clockCnts(clk) = len
+ sendCmd(SIM_CMD.SETCLK)
+ writeln(clk.name)
+ writeValue(len)
+ }
+
+ def setClocks(clocks: Iterable[(Clock, Int)]) {
+ clocks foreach { case (clk, len) => setClock(clk, len) }
}
- def signed_fix(dtype: Element, rv: BigInt): BigInt = {
+ def signed_fix(dtype: Data, rv: BigInt): BigInt = {
val w = dtype.getWidth
dtype match {
/* Any "signed" node */
@@ -174,90 +138,132 @@ class ManualTester[+T <: Module]
}
}
- def peekAt[T <: Bits](data: Mem[T], off: Int): BigInt = {
- // signed_fix(data(1), peekBits(data, off))
- doPeekBits(data.debugName, off)
+ def peek(id: Int) = {
+ sendCmd(SIM_CMD.PEEK)
+ writeln(id.toString)
+ try { BigInt(readln, 16) } catch { case e: Throwable => BigInt(0) }
}
-
+ def peekPath(path: String) = {
+ peek(_signalMap getOrElseUpdate (path, getId(path)))
+ }
+ def peekNode(node: Data, off: Option[Int] = None) = {
+ peekPath(dumpName(node) + ((off map ("[" + _ + "]")) getOrElse ""))
+ }
+ //def peekAt[T <: Bits](data: Mem[T], off: Int): BigInt = {
+ // val value = peekNode(data, Some(off))
+ // if (isTrace) println(" PEEK %s[%d] -> %s".format(dumpName(data), off, value.toString(16)))
+ // value
+ //}
def peek(data: Bits): BigInt = {
- signed_fix(data, peekBits(data))
+ if (isStale) update
+ val value = if (/*data.isTopLevelIO &&*/ data.dir == INPUT) _pokeMap(data)
+ else signed_fix(data, _peekMap getOrElse (data, peekNode(data)))
+ if (isTrace) println(" PEEK " + dumpName(data) + " -> " + value.toString(16))
+ value
+ }
+ def peek(data: Aggregate): Array[BigInt] = {
+ data.flatten.map (peek(_)).toArray
}
-
def peek(data: Flo): Float = {
- intBitsToFloat(peekBits(data).toInt)
+ intBitsToFloat(peek(data.asInstanceOf[Bits]).toInt)
}
-
def peek(data: Dbl): Double = {
- longBitsToDouble(peekBits(data).toLong)
+ longBitsToDouble(peek(data.asInstanceOf[Bits]).toLong)
}
- def peek(data: Aggregate /*, off: Int = -1 */): IndexedSeq[BigInt] = {
- data.flatten.map(peek(_))
- }
- def reset(n: Int = 1) = {
- emulatorCmd("reset " + n)
- // TODO: check for errors in return
- if (isTrace) println("RESET " + n)
+ def poke(id: Int, v: BigInt, w: Int = 1) {
+ sendCmd(SIM_CMD.POKE)
+ writeln(id.toString)
+ writeValue(v, w)
}
-
- def doPokeBits(name: String, x: BigInt, off: Int): Unit = {
- if (name == "") {
- println("Unable to poke data " + name) // TODO: data.toString
- } else {
-
- var cmd = ""
- if (off != -1) {
- cmd = "mem_poke " + name + " " + off;
- } else {
- cmd = "wire_poke " + name;
- }
- // Don't prefix negative numbers with "0x"
- val radixPrefix = if (x < 0) " -0x" else " 0x"
- val xval = radixPrefix + x.abs.toString(16)
- cmd = cmd + xval
- if (isTrace) {
- println(" POKE " + name + " " + (if (off >= 0) (off + " ") else "") + "<- " + xval)
- }
- val rtn = emulatorCmd(cmd)
- if (rtn != "ok") {
- System.err.print(s"FAILED: poke(${name}) returned false")
- ok = false
- }
+ def pokePath(path: String, v: BigInt, w: Int = 1) {
+ poke(_signalMap getOrElseUpdate (path, getId(path)), v, w)
+ }
+ //def pokeNode(node: Node, v: BigInt, off: Option[Int] = None) {
+ // pokePath(dumpName(node) + ((off map ("[" + _ + "]")) getOrElse ""), v, node.needWidth)
+ //}
+ //def pokeAt[T <: Bits](data: Mem[T], value: BigInt, off: Int): Unit = {
+ // if (isTrace) println(" POKE %s[%d] <- %s".format(dumpName(data), off, value.toString(16)))
+ // pokeNode(data, value, Some(off))
+ //}
+ def poke(data: Bits, x: Boolean) { this.poke(data, int(x)) }
+ def poke(data: Bits, x: Int) { this.poke(data, int(x)) }
+ def poke(data: Bits, x: Long) { this.poke(data, int(x)) }
+ def poke(data: Bits, x: BigInt) {
+ val value = if (x >= 0) x else {
+ val cnt = (data.getWidth - 1) >> 6
+ ((0 to cnt) foldLeft BigInt(0))((res, i) => res | (int((x >> (64 * i)).toLong) << (64 * i)))
}
+ if (isTrace) println(" POKE " + dumpName(data) + " <- " + value.toString(16))
+ if (/*data.isTopLevelIO &&*/ data.dir == INPUT)
+ _pokeMap(data) = value
+ else if (/*data.isTopLevelIO &&*/ data.dir == OUTPUT)
+ println(" NOT ALLOWED TO POKE OUTPUT " + dumpName(data))
+ //else
+ // pokeNode(data, value)
+ isStale = true
+ }
+ def poke(data: Aggregate, x: Array[BigInt]): Unit = {
+ val kv = (data.flatten, x.reverse).zipped
+ for ((x, y) <- kv) poke(x, y)
+ }
+ def poke(data: Flo, x: Float): Unit = {
+ poke(data.asInstanceOf[Bits], BigInt(floatToIntBits(x)))
+ }
+ def poke(data: Dbl, x: Double): Unit = {
+ poke(data.asInstanceOf[Bits], BigInt(doubleToLongBits(x)))
}
- def pokeAt[T <: Bits](data: Mem[T], x: BigInt, off: Int): Unit = {
- doPokeBits(data.debugName, x, off)
+ def readOutputs {
+ _peekMap.clear
+ _outputs foreach (x => _peekMap(x) = try { BigInt(readln, 16) } catch { case e: Throwable => BigInt(0) })
}
- def pokeBits(data: Data, x: BigInt, off: Int = -1): Unit = {
- doPokeBits(data.debugName, x, off)
+ def writeInputs {
+ _inputs foreach (x => writeValue(_pokeMap getOrElse (x, BigInt(0)), x.getWidth))
}
- def poke(data: Bits, x: BigInt): Unit = {
- pokeBits(data, x)
+ def reset(n: Int = 1) {
+ if (isTrace) println("RESET " + n)
+ for (i <- 0 until n) {
+ sendCmd(SIM_CMD.RESET)
+ readOutputs
+ }
}
- def poke(data: Flo, x: Float): Unit = {
- pokeBits(data, BigInt(floatToIntBits(x)))
+ protected def update {
+ sendCmd(SIM_CMD.UPDATE)
+ writeInputs
+ readOutputs
+ isStale = false
}
- def poke(data: Dbl, x: Double): Unit = {
- pokeBits(data, BigInt(doubleToLongBits(x)))
+ private def calcDelta = {
+ val min = (_clockCnts.values foldLeft Int.MaxValue)(math.min(_, _))
+ _clockCnts.keys foreach (_clockCnts(_) -= min)
+ (_clockCnts filter (_._2 == 0)).keys foreach (k => _clockCnts(k) = _clockLens(k))
+ min
}
- def poke(data: Aggregate, x: Array[BigInt]): Unit = {
- val kv = (data.flatten, x.reverse).zipped;
- for ((x, y) <- kv)
- poke(x, y)
+ protected def takeStep {
+ sendCmd(SIM_CMD.STEP)
+ writeInputs
+ delta += calcDelta
+ readOutputs
+ dumpLogs
+ isStale = false
}
- def step(n: Int) = {
- val target = t + n
- val s = emulatorCmd("step " + n)
- delta += s.toInt
- if (isTrace) println("STEP " + n + " -> " + target)
+ protected def getId(path: String) = {
+ sendCmd(SIM_CMD.GETID)
+ writeln(path)
+ readln.toInt
+ }
+
+ def step(n: Int) {
+ if (isTrace) println("STEP " + n + " -> " + (t + n))
+ (0 until n) foreach (_ => takeStep)
t += n
}
@@ -266,7 +272,7 @@ class ManualTester[+T <: Module]
def int(x: Long): BigInt = (BigInt(x >>> 1) << 1) | x & 1
def int(x: Bits): BigInt = x.litValue()
- var ok = true;
+ var ok = true
var failureTime = -1
def expect (good: Boolean, msg: String): Boolean = {
@@ -277,12 +283,10 @@ class ManualTester[+T <: Module]
}
def expect (data: Bits, expected: BigInt): Boolean = {
- // val mask = (BigInt(1) << data) - 1
- val got = peek(data)
-
- // expect((got & mask) == (expected & mask),
- expect(got == expected,
- "EXPECT " + data.debugName + " <- 0x" + got.toString(16) + " == 0x" + expected.toString(16))
+ val mask = (BigInt(1) << data.getWidth) - 1
+ val got = peek(data) & mask
+ val exp = expected & mask
+ expect(got == exp, "EXPECT " + dumpName(data) + " <- " + got.toString(16) + " == " + exp.toString(16))
}
def expect (data: Aggregate, expected: Array[BigInt]): Boolean = {
@@ -296,18 +300,18 @@ class ManualTester[+T <: Module]
/* We need the following so scala doesn't use our "tolerant" Float version of expect.
*/
def expect (data: Bits, expected: Int): Boolean = {
- expect(data, BigInt(expected))
+ expect(data, int(expected))
}
def expect (data: Bits, expected: Long): Boolean = {
- expect(data, BigInt(expected))
+ expect(data, int(expected))
}
- def expect (data: Flo, expected: Double): Boolean = {
+ def expect (data: Flo, expected: Float): Boolean = {
val got = peek(data)
- expect(got == expected, "EXPECT " + data.debugName + " <- " + got + " == " + expected)
+ expect(got == expected, "EXPECT " + dumpName(data) + " <- " + got + " == " + expected)
}
def expect (data: Dbl, expected: Double): Boolean = {
val got = peek(data)
- expect(got == expected, "EXPECT " + data.debugName + " <- " + got + " == " + expected)
+ expect(got == expected, "EXPECT " + dumpName(data) + " <- " + got + " == " + expected)
}
/* Compare the floating point value of a node with an expected floating point value.
@@ -321,59 +325,59 @@ class ManualTester[+T <: Module]
if (gotFLoat != expectedFloat) {
val gotDiff = gotBits - expectedBits
// Do we have a single bit difference?
- if (abs(gotDiff) <= 1) {
+ if (scala.math.abs(gotDiff) <= 1) {
expectedFloat = gotFLoat
}
}
expect(gotFLoat == expectedFloat,
- "EXPECT " + data.debugName + " <- " + gotFLoat + " == " + expectedFloat)
+ "EXPECT " + dumpName(data) + " <- " + gotFLoat + " == " + expectedFloat)
}
val rnd = if (TesterDriver.testerSeedValid) new Random(TesterDriver.testerSeed) else new Random()
- var process: Process = null
-
- def start(): Process = {
- val cmd = "./" + name
- println("RUNNING " + cmd)
+ val process: Process = {
+ val n = TesterDriver.name
+ val target = TesterDriver.targetDir + "/" + n
+ // If the caller has provided a specific command to execute, use it.
+ val cmd = TesterDriver.testCommand match {
+ case Some(cmd) => TesterDriver.targetDir + "/" + cmd
+ case None => TesterDriver.backend match {
+ case b: FloBackend => target
+ /*val command = ArrayBuffer(b.floDir + "fix-console", ":is-debug", "true", ":filename", target + ".hex", ":flo-filename", target + ".mwe.flo")
+ if (TesterDriver.isVCD) { command ++= ArrayBuffer(":is-vcd-dump", "true") }
+ if (TesterDriver.emitTempNodes) { command ++= ArrayBuffer(":emit-temp-nodes", "true") }
+ command ++= ArrayBuffer(":target-dir", TesterDriver.targetDir)
+ command.mkString(" ")*/
+ case b: VerilogBackend => target + " -q +vcs+initreg+0 "
+ case _ => target
+ }
+ }
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)
+ println("STARTING " + cmd)
+ val processBuilder = Process(cmd)
+ val pio = new ProcessIO(
+ in => _testOut = Option(in), out => _testErr = Option(out), err => _testIn = Option(err))
+ val process = processBuilder.run(pio)
waitForStreams()
t = 0
+ readOutputs
reset(5)
- if (skipVPDMessage) {
- var vpdmsg = testIn.read
- while (vpdmsg != '\n' && vpdmsg != -1)
- vpdmsg = testIn.read
- }
+ while (_logger.ready) println(_logger.readLine)
process
}
- def finish(): Boolean = {
- if (process != null) {
- emulatorCmd("quit")
-
- if (testOut != null) {
- testOut.flush()
- testOut.close()
- }
- if (testIn != null) {
- testIn.close()
- }
- if (testErr != null) {
- testErr.close()
- }
-
- process.destroy()
- }
- println("RAN " + t + " CYCLES " + (if (ok) "PASSED" else { "FAILED FIRST AT CYCLE " + failureTime }))
- ok
+ def finish {
+ sendCmd(SIM_CMD.FIN)
+ _testIn match { case Some(in) => in.close case None => }
+ _testErr match { case Some(err) => err.close case None => }
+ _testOut match { case Some(out) => { out.flush ; out.close } case None => }
+ process.destroy()
+ println("RAN " + t + " CYCLES " + (if (ok) "PASSED" else "FAILED FIRST AT CYCLE " + failureTime))
+ if(!ok) throwException("Module under test FAILED at least one test vector.")
}
-}
-class Tester[+T <: Module](c: T, isTrace: Boolean = true, skipVPDMessage: Boolean = false) extends ManualTester(c.name, isTrace, skipVPDMessage) {
- start()
+ //_signalMap ++= TesterDriver.signalMap flatMap {
+ // case (m: Mem[_], id) =>
+ // (0 until m.n) map (idx => "%s[%d]".format(dumpName(m), idx) -> (id + idx))
+ // case (node, id) => Seq(dumpName(node) -> id)
+ //}
}
-