summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAndrew Waterman2015-08-12 16:52:51 -0700
committerAndrew Waterman2015-08-12 16:52:51 -0700
commitac582545be061be24cabd982dfad913e1114ecbe (patch)
tree26a06607cbdd3338f2210fb34ba0469df5308b0a /src
parent8b77888313c2b8f3014eacd49db59ee7405774ea (diff)
Remove old testers for now
Diffstat (limited to 'src')
-rw-r--r--src/main/scala/Chisel/testers/AdvTester.scala223
-rw-r--r--src/main/scala/Chisel/testers/Driver.scala104
-rw-r--r--src/main/scala/Chisel/testers/Tester.scala383
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)
- //}
-}