Nuke
This commit is contained in:
commit
932413bb3d
61 changed files with 7249 additions and 0 deletions
188
src/test/scala/chiselTestRunner.scala
Normal file
188
src/test/scala/chiselTestRunner.scala
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
package FiveStage
|
||||
import chisel3.iotesters._
|
||||
import scala.collection.mutable.LinkedHashMap
|
||||
|
||||
import fileUtils.say
|
||||
|
||||
import Data._
|
||||
import PrintUtils._
|
||||
|
||||
private class ChiselTestRunner (
|
||||
instructions : List[Int],
|
||||
settings : List[TestSetting],
|
||||
c : Tile,
|
||||
d : PeekPokeTester[Tile],
|
||||
terminalAddress : Addr,
|
||||
maxSteps : Int) {
|
||||
|
||||
|
||||
/**
|
||||
* Currently unused as it is quite nontrivial to figure out whether read data is actually used.
|
||||
* Still, with the necessary scaffolding these can be correlated with reg writes to figure out
|
||||
* if they are valid or not.
|
||||
*/
|
||||
case class ChiselMemReadEvent(pcAddr: Addr, memAddr: Addr, word: Int)
|
||||
|
||||
private def setup = {
|
||||
|
||||
d.poke(d.dut.io.setup, 1)
|
||||
|
||||
val initDMem = DMem(settings).repr.toList
|
||||
val initRegs = Regs(settings).repr.toList
|
||||
|
||||
setupImem(instructions)
|
||||
setupRegs(initRegs)
|
||||
setupDmem(initDMem)
|
||||
|
||||
// flush
|
||||
d.step(1)
|
||||
disableTestSignals
|
||||
d.step(5)
|
||||
d.poke(d.dut.io.setup, 0)
|
||||
|
||||
def disableTestSignals: Unit = {
|
||||
d.poke(d.dut.io.DMEMWriteData, 0)
|
||||
d.poke(d.dut.io.DMEMAddress, 0)
|
||||
d.poke(d.dut.io.DMEMWriteEnable, 0)
|
||||
d.poke(d.dut.io.regsWriteData, 0)
|
||||
d.poke(d.dut.io.regsAddress, 0)
|
||||
d.poke(d.dut.io.regsWriteEnable, 0)
|
||||
d.poke(d.dut.io.IMEMWriteData, 0)
|
||||
d.poke(d.dut.io.IMEMAddress, 4092)
|
||||
}
|
||||
|
||||
def setupRegs(regs: List[(Reg, Int)]) = {
|
||||
regs.foreach{ case(reg, word) =>
|
||||
d.poke(d.dut.io.setup, 1)
|
||||
d.poke(d.dut.io.regsWriteEnable, 1)
|
||||
d.poke(d.dut.io.regsWriteData, BigInt(word))
|
||||
d.poke(d.dut.io.regsAddress, reg.value)
|
||||
d.step(1)
|
||||
}
|
||||
d.poke(d.dut.io.regsWriteEnable, 0)
|
||||
d.poke(d.dut.io.regsWriteData, 0)
|
||||
d.poke(d.dut.io.regsAddress, 0)
|
||||
}
|
||||
|
||||
def setupDmem(mem: List[(Addr, Int)]) = {
|
||||
mem.foreach { case (addr, word) =>
|
||||
d.poke(d.dut.io.setup, 1)
|
||||
d.poke(d.dut.io.DMEMWriteEnable, 1)
|
||||
d.poke(d.dut.io.DMEMWriteData, word)
|
||||
d.poke(d.dut.io.DMEMAddress, addr.value)
|
||||
d.step(1)
|
||||
}
|
||||
d.poke(d.dut.io.DMEMWriteEnable, 0)
|
||||
d.poke(d.dut.io.DMEMWriteData, 0)
|
||||
d.poke(d.dut.io.DMEMAddress, 0)
|
||||
|
||||
}
|
||||
|
||||
def setupImem(instructions: List[Int]) = {
|
||||
(0 until instructions.length).foreach{ ii =>
|
||||
d.poke(d.dut.io.IMEMAddress, ii*4)
|
||||
d.poke(d.dut.io.IMEMWriteData, instructions(ii).toInt)
|
||||
d.step(1)
|
||||
}
|
||||
d.poke(d.dut.io.IMEMAddress, 4092) // Ensures that we don't overwrite an instruction. Bandaid for lack of IMEM.writeEnable
|
||||
d.poke(d.dut.io.IMEMWriteData, 0)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private def getPC = Addr(d.peek(d.dut.io.currentPC).toInt)
|
||||
private def getDMemWriteAddress = Addr(d.peek(d.dut.io.memDeviceWriteAddress).toInt)
|
||||
private def getRegWriteAddress = Reg(d.peek(d.dut.io.regsDeviceWriteAddress).toInt)
|
||||
|
||||
private def getRegUpdate: Option[ChiselRegEvent] = {
|
||||
if(
|
||||
(d.peek(d.dut.io.regsDeviceWriteEnable) == 1) &&
|
||||
(getRegWriteAddress.value != 0)
|
||||
){
|
||||
val regWriteAddress = getRegWriteAddress
|
||||
val regWriteData = d.peek(d.dut.io.regsDeviceWriteData).toInt
|
||||
val regUpdate = ChiselRegEvent(getPC, regWriteAddress, regWriteData)
|
||||
Some(regUpdate)
|
||||
}
|
||||
else
|
||||
None
|
||||
}
|
||||
|
||||
private def getMemWrite: Option[ChiselMemWriteEvent] = {
|
||||
if(d.peek(d.dut.io.memDeviceWriteEnable) == 1) {
|
||||
val memWriteAddress = getDMemWriteAddress
|
||||
val memWriteData = d.peek(d.dut.io.memDeviceWriteData).toInt
|
||||
val memUpdate = ChiselMemWriteEvent(getPC, memWriteAddress, memWriteData)
|
||||
Some(memUpdate)
|
||||
}
|
||||
else
|
||||
None
|
||||
}
|
||||
|
||||
private def stepOne: CircuitTrace = {
|
||||
val state = (getPC, List(getRegUpdate, getMemWrite).flatten)
|
||||
// say(d.peek(d.dut.io).toList.mkStringN)
|
||||
d.step(1)
|
||||
state
|
||||
}
|
||||
|
||||
|
||||
private def go(log: List[CircuitTrace], timeOut: Int): (Option[String], List[CircuitTrace]) = {
|
||||
if(timeOut == 0){
|
||||
(Some("Chisel tester timed out before reaching termination address"), log.reverse)
|
||||
}
|
||||
else if(getPC == terminalAddress){
|
||||
(None, (flush ::: log).reverse)
|
||||
}
|
||||
else {
|
||||
val step = stepOne
|
||||
go(step :: log, timeOut - 1)
|
||||
}
|
||||
}
|
||||
|
||||
// After finishing, let the circuit run until all updates can be committed.
|
||||
private def flush: List[CircuitTrace] =
|
||||
(0 to 3).map(_ => stepOne).reverse.toList
|
||||
|
||||
/**
|
||||
* Run the entire shebang
|
||||
*/
|
||||
def run: (Option[String], List[CircuitTrace]) = {
|
||||
setup
|
||||
go(Nil, maxSteps)
|
||||
}
|
||||
}
|
||||
|
||||
object ChiselTestRunner {
|
||||
|
||||
def apply(
|
||||
binary : List[Int],
|
||||
settings : List[TestSetting],
|
||||
terminalAddress : Addr,
|
||||
maxSteps : Int): Either[String, (Option[String], List[CircuitTrace])] = {
|
||||
|
||||
var sideEffectExtravaganza: Option[(Option[String], List[CircuitTrace])] = None
|
||||
|
||||
val error: Either[String, Boolean] = scala.util.Try {
|
||||
chisel3.iotesters.Driver(() => new Tile(), "treadle") { c =>
|
||||
new PeekPokeTester(c) {
|
||||
val testRunner = new ChiselTestRunner(
|
||||
binary,
|
||||
settings,
|
||||
c,
|
||||
this,
|
||||
terminalAddress,
|
||||
maxSteps
|
||||
)
|
||||
|
||||
val log = testRunner.run
|
||||
sideEffectExtravaganza = Some(log)
|
||||
}
|
||||
}
|
||||
}.toEither.left.map{printChiselError}
|
||||
|
||||
error.flatMap{ e =>
|
||||
sideEffectExtravaganza.toRight("Unknown test failure, please let me know")
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue