diff options
Diffstat (limited to 'src/main/scala/Chisel')
| -rw-r--r-- | src/main/scala/Chisel/testers/AdvTester.scala | 223 | ||||
| -rw-r--r-- | src/main/scala/Chisel/testers/Driver.scala | 104 | ||||
| -rw-r--r-- | src/main/scala/Chisel/testers/Tester.scala | 383 |
3 files changed, 0 insertions, 710 deletions
diff --git a/src/main/scala/Chisel/testers/AdvTester.scala b/src/main/scala/Chisel/testers/AdvTester.scala deleted file mode 100644 index 6db823ed..00000000 --- a/src/main/scala/Chisel/testers/AdvTester.scala +++ /dev/null @@ -1,223 +0,0 @@ -/* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of - California (Regents). All Rights Reserved. Redistribution and use in - source and binary forms, with or without modification, are permitted - provided that the following conditions are met: - - * Redistributions of source code must retain the above - copyright notice, this list of conditions and the following - two paragraphs of disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - two paragraphs of disclaimer in the documentation and/or other materials - provided with the distribution. - * Neither the name of the Regents nor the names of its contributors - may be used to endorse or promote products derived from this - software without specific prior written permission. - - IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, - SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, - ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF - REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF - ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION - TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR - MODIFICATIONS. -*/ - -/* - Written by Stephen Twigg, Eric Love - Version 0.9 -*/ -package Chisel.testers -import Chisel._ -import scala.collection.mutable.ArrayBuffer - -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 - - // List of scala objects that need to be processed along with the test benches, like sinks and sources - val preprocessors = new ArrayBuffer[Processable]() - val postprocessors = new ArrayBuffer[Processable]() - // pre v post refers to when user-customized update code ('work') is processed - // e.g. sinks are in the preprocessing list and sources in the postprocessing list - // this allows the testbench to respond to a request within one cycle - - // This section of code lets testers easily emulate have registers right before dut inputs - // This testing style conforms with the general ASPIRE testbench style - // Also, to ensure difference enforced, poke 'deprecated' and replaced with wire_poke - def wire_poke(port: Bits, target: Boolean) = { super.poke(port, int(target)) } - def wire_poke(port: Bits, target: Int) = { super.poke(port, int(target)) } - def wire_poke(port: Bits, target: Long) = { super.poke(port, int(target)) } - def wire_poke(port: Bits, target: BigInt) = { super.poke(port, target) } - def wire_poke(port: Aggregate, target: Array[BigInt]) = { super.poke(port, target) } - - override def poke(port: Bits, target: BigInt) = require(false, "poke hidden for AdvTester, use wire_poke or reg_poke") - override def poke(port: Aggregate, target: Array[BigInt]) = require(false, "poke hidden for AdvTester, use wire_poke or reg_poke") - - val registered_bits_updates = new scala.collection.mutable.HashMap[Bits,BigInt]() - val registered_aggr_updates = new scala.collection.mutable.HashMap[Aggregate,Array[BigInt]]() - - def do_registered_updates() = { - registered_bits_updates.foreach( kv => wire_poke(kv._1,kv._2) ) - registered_aggr_updates.foreach( kv => wire_poke(kv._1,kv._2) ) - - registered_bits_updates.clear() - registered_aggr_updates.clear() - } - - def reg_poke(port: Bits, target: BigInt) = { registered_bits_updates(port) = target } - def reg_poke(port: Aggregate, target: Array[BigInt]) = { registered_aggr_updates(port) = target } - - // Convenience functions - def Boolean2Int(i: Boolean): Int = (if(i) 1 else 0) // TODO: Investigate name and inclusion as a Chisel Tester auto-convert - - // This function replaces step in the advanced tester and makes sure all tester features are clocked in the appropriate order - def takestep(work: => Unit = {}): Unit = { - cycles += 1 - step(1) - do_registered_updates() - preprocessors.foreach(_.process()) // e.g. sinks - work - postprocessors.foreach(_.process()) - } - def takesteps(n: Int)(work: =>Unit = {}): Unit = { - require(n>0, "Number of steps taken must be positive integer.") - (0 until n).foreach(_ => takestep(work)) - } - - // Functions to step depending on predicates - def until(pred: =>Boolean, maxCycles: Int = defaultMaxCycles)(work: =>Unit): Boolean = { - var timeout_cycles = 0 - while(!pred && (timeout_cycles < maxCycles)) { - takestep(work) - timeout_cycles += 1 - } - assert(timeout_cycles < maxCycles, - "until timed out after %d cycles".format(timeout_cycles)) - pred - } - def eventually(pred: =>Boolean, maxCycles: Int = defaultMaxCycles) = {until(pred, maxCycles){}} - def do_until(work: =>Unit)(pred: =>Boolean, maxCycles: Int = defaultMaxCycles): Boolean = { - takestep(work) - until(pred, maxCycles){work} - } - - def assert(expr: Boolean, errMsg:String = "") = { - pass &= expr - if(!expr && errMsg != "") { println("ASSERT FAILED: " + errMsg) } - expr - } - - - class DecoupledSink[T <: Data, R]( socket: DecoupledIO[T], cvt: T=>R ) extends Processable - { - var max_count = -1 - val outputs = new scala.collection.mutable.Queue[R]() - private var amReady = false - private def isValid = () => (peek(socket.valid) == 1) - - def process() = { - // Handle this cycle - if(isValid() && amReady) { - outputs.enqueue(cvt(socket.bits)) - } - // Decide what to do next cycle and post onto register - amReady = max_count < 1 || outputs.length < max_count - reg_poke(socket.ready, Boolean2Int(amReady)) - } - - // Initialize - wire_poke(socket.ready, 0) - preprocessors += this - } - object DecoupledSink { - def apply[T<:Bits](socket: DecoupledIO[T]) = new DecoupledSink(socket, (socket_bits: T) => peek(socket_bits)) - } - - class ValidSink[T <: Data, R]( socket: ValidIO[T], cvt: T=>R ) extends Processable - { - val outputs = new scala.collection.mutable.Queue[R]() - private def isValid = peek(socket.valid) == 1 - - def process() = { - if(isValid) { - outputs.enqueue(cvt(socket.bits)) - } - } - - // Initialize - preprocessors += this - } - object ValidSink { - def apply[T<:Bits](socket: ValidIO[T]) = new ValidSink(socket, (socket_bits: T) => peek(socket_bits)) - } - - class DecoupledSource[T <: Data, R]( socket: DecoupledIO[T], post: (T,R)=>Unit ) extends Processable - { - val inputs = new scala.collection.mutable.Queue[R]() - - private var amValid = false - private var justFired = false - private def isReady = (peek(socket.ready) == 1) - def isIdle = !amValid && inputs.isEmpty && !justFired - - def process() = { - justFired = false - if(isReady && amValid) { // Fired last cycle - amValid = false - justFired = true - } - if(!amValid && !inputs.isEmpty) { - amValid = true - post(socket.bits, inputs.dequeue()) - } - reg_poke(socket.valid, Boolean2Int(amValid)) - } - - // Initialize - wire_poke(socket.valid, 0) - postprocessors += this - } - object DecoupledSource { - def apply[T<:Bits](socket: DecoupledIO[T]) = new DecoupledSource(socket, (socket_bits: T, in: BigInt) => reg_poke(socket_bits, in)) - } - - class ValidSource[T <: Data, R]( socket: ValidIO[T], post: (T,R)=>Unit ) extends Processable - { - val inputs = new scala.collection.mutable.Queue[R]() - private var amValid = false - private var justFired = false - - def isIdle = inputs.isEmpty && !amValid - - def process() = { - // Always advance the input - justFired = (amValid==true) - amValid = false - if(!inputs.isEmpty) { - amValid = true - post(socket.bits, inputs.dequeue()) - } - reg_poke(socket.valid, Boolean2Int(amValid)) - } - - // Initialize - wire_poke(socket.valid, 0) - postprocessors += this - } - object ValidSource { - def apply[T<:Bits](socket: ValidIO[T]) = new ValidSource(socket, (socket_bits: T, in: BigInt) => reg_poke(socket_bits, in)) - } - -} - -trait Processable { - def process(): Unit -} - diff --git a/src/main/scala/Chisel/testers/Driver.scala b/src/main/scala/Chisel/testers/Driver.scala deleted file mode 100644 index 69fddb41..00000000 --- a/src/main/scala/Chisel/testers/Driver.scala +++ /dev/null @@ -1,104 +0,0 @@ -/* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of - California (Regents). All Rights Reserved. Redistribution and use in - source and binary forms, with or without modification, are permitted - provided that the following conditions are met: - - * Redistributions of source code must retain the above - copyright notice, this list of conditions and the following - two paragraphs of disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - two paragraphs of disclaimer in the documentation and/or other materials - provided with the distribution. - * Neither the name of the Regents nor the names of its contributors - may be used to endorse or promote products derived from this - software without specific prior written permission. - - IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, - SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, - ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF - REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF - ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION - TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR - MODIFICATIONS. -*/ - -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" => { - // 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 = { - ftester(mod).finish - } - -} - -// This should go away. -object chiselMainTest { - def apply[T <: Module](args: Array[String], gen: () => T)(tester: T => Tester[T]): T = ??? -} diff --git a/src/main/scala/Chisel/testers/Tester.scala b/src/main/scala/Chisel/testers/Tester.scala deleted file mode 100644 index 01d7b256..00000000 --- a/src/main/scala/Chisel/testers/Tester.scala +++ /dev/null @@ -1,383 +0,0 @@ -/* - Copyright (c) 2011, 2012, 2013, 2014 The Regents of the University of - California (Regents). All Rights Reserved. Redistribution and use in - source and binary forms, with or without modification, are permitted - provided that the following conditions are met: - - * Redistributions of source code must retain the above - copyright notice, this list of conditions and the following - two paragraphs of disclaimer. - * Redistributions in binary form must reproduce the above - copyright notice, this list of conditions and the following - two paragraphs of disclaimer in the documentation and/or other materials - provided with the distribution. - * Neither the name of the Regents nor the names of its contributors - may be used to endorse or promote products derived from this - software without specific prior written permission. - - IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, - SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, - ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF - REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF - ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION - TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR - MODIFICATIONS. -*/ - -package Chisel.testers -import Chisel._ -import scala.collection.mutable.{ArrayBuffer, HashMap, Queue => ScalaQueue} -import scala.collection.immutable.ListSet -import scala.util.Random -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 - 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 (_testIn == None || _testOut == None || _testErr == None) { - Thread.sleep(100) - if (waited % 10 == 0 && waited > 30) { - ChiselError.info("waiting for emulator process streams to be valid ...") - } - } - } - - private def writeln(str: String) { - _writer write str - _writer.newLine - _writer.flush - } - - private def dumpLogs = { - while (_logger.ready) { - _logs enqueue _logger.readLine - } - } - - 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 - } - } - - private def sendCmd(cmd: SIM_CMD.Value) { - writeln(cmd.id.toString) - } - - 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 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: Data, rv: BigInt): BigInt = { - val w = dtype.getWidth - dtype match { - /* Any "signed" node */ - case _: SInt | _ : Flo | _: Dbl => (if(rv >= (BigInt(1) << w - 1)) (rv - (BigInt(1) << w)) else rv) - /* anything else (i.e., UInt) */ - case _ => (rv) - } - } - - 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 = { - 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(peek(data.asInstanceOf[Bits]).toInt) - } - def peek(data: Dbl): Double = { - longBitsToDouble(peek(data.asInstanceOf[Bits]).toLong) - } - - - def poke(id: Int, v: BigInt, w: Int = 1) { - sendCmd(SIM_CMD.POKE) - writeln(id.toString) - writeValue(v, w) - } - 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 readOutputs { - _peekMap.clear - _outputs foreach (x => _peekMap(x) = try { BigInt(readln, 16) } catch { case e: Throwable => BigInt(0) }) - } - - def writeInputs { - _inputs foreach (x => writeValue(_pokeMap getOrElse (x, BigInt(0)), x.getWidth)) - } - - def reset(n: Int = 1) { - if (isTrace) println("RESET " + n) - for (i <- 0 until n) { - sendCmd(SIM_CMD.RESET) - readOutputs - } - } - - protected def update { - sendCmd(SIM_CMD.UPDATE) - writeInputs - readOutputs - isStale = false - } - - 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 - } - - protected def takeStep { - sendCmd(SIM_CMD.STEP) - writeInputs - delta += calcDelta - readOutputs - dumpLogs - isStale = false - } - - 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 - } - - def int(x: Boolean): BigInt = if (x) 1 else 0 - def int(x: Int): BigInt = (BigInt(x >>> 1) << 1) | x & 1 - def int(x: Long): BigInt = (BigInt(x >>> 1) << 1) | x & 1 - def int(x: Bits): BigInt = x.litValue() - - var ok = true - var failureTime = -1 - - def expect (good: Boolean, msg: String): Boolean = { - if (isTrace) - println(msg + " " + (if (good) "PASS" else "FAIL")) - if (!good) { ok = false; if (failureTime == -1) failureTime = t; } - good - } - - def expect (data: Bits, expected: BigInt): Boolean = { - 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 = { - val kv = (data.flatten, expected.reverse).zipped; - var allGood = true - for ((d, e) <- kv) - allGood = expect(d, e) && allGood - allGood - } - - /* We need the following so scala doesn't use our "tolerant" Float version of expect. - */ - def expect (data: Bits, expected: Int): Boolean = { - expect(data, int(expected)) - } - def expect (data: Bits, expected: Long): Boolean = { - expect(data, int(expected)) - } - def expect (data: Flo, expected: Float): Boolean = { - val got = peek(data) - expect(got == expected, "EXPECT " + dumpName(data) + " <- " + got + " == " + expected) - } - def expect (data: Dbl, expected: Double): Boolean = { - val got = peek(data) - expect(got == expected, "EXPECT " + dumpName(data) + " <- " + got + " == " + expected) - } - - /* Compare the floating point value of a node with an expected floating point value. - * We will tolerate differences in the bottom bit. - */ - def expect (data: Bits, expected: Float): Boolean = { - val gotBits = peek(data).toInt - val expectedBits = java.lang.Float.floatToIntBits(expected) - var gotFLoat = java.lang.Float.intBitsToFloat(gotBits) - var expectedFloat = expected - if (gotFLoat != expectedFloat) { - val gotDiff = gotBits - expectedBits - // Do we have a single bit difference? - if (scala.math.abs(gotDiff) <= 1) { - expectedFloat = gotFLoat - } - } - expect(gotFLoat == expectedFloat, - "EXPECT " + dumpName(data) + " <- " + gotFLoat + " == " + expectedFloat) - } - - val rnd = if (TesterDriver.testerSeedValid) new Random(TesterDriver.testerSeed) else new Random() - 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 " + 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) - while (_logger.ready) println(_logger.readLine) - process - } - - 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.") - } - - //_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) - //} -} |
