Files
chipyard/generators/firechip/src/test/scala/ScalaTestSuite.scala
2020-12-13 10:45:51 -05:00

124 lines
4.8 KiB
Scala

//See LICENSE for license details.
package firesim.firesim
import java.io.File
import scala.concurrent.{Future, Await, ExecutionContext}
import scala.sys.process.{stringSeqToProcess, ProcessLogger}
import scala.io.Source
import org.scalatest.Suites
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.system.{RocketTestSuite, BenchmarkTestSuite}
import freechips.rocketchip.system.TestGeneration._
import freechips.rocketchip.system.DefaultTestSuites._
abstract class FireSimTestSuite(
topModuleClass: String,
targetConfigs: String,
platformConfigs: String,
N: Int = 8
) extends firesim.TestSuiteCommon {
import scala.concurrent.duration._
import ExecutionContext.Implicits.global
val topModuleProject = "firesim.firesim"
val chipyardLongName = topModuleProject + "." + topModuleClass + "." + targetConfigs
// From TestSuiteCommon
val targetTuple = s"$topModuleClass-$targetConfigs-$platformConfigs"
val commonMakeArgs = Seq(s"DESIGN=${topModuleClass}",
s"TARGET_CONFIG=${targetConfigs}",
s"PLATFORM_CONFIG=${platformConfigs}")
override lazy val genDir = new File(firesimDir, s"generated-src/${chipyardLongName}")
def invokeMlSimulator(backend: String, name: String, debug: Boolean, additionalArgs: Seq[String] = Nil) = {
make((Seq(s"${outDir.getAbsolutePath}/${name}.%s".format(if (debug) "vpd" else "out"),
s"EMUL=${backend}")
++ additionalArgs):_*)
}
def runTest(backend: String, name: String, debug: Boolean, additionalArgs: Seq[String] = Nil) = {
compileMlSimulator(backend, debug)
if (isCmdAvailable(backend)) {
it should s"pass in ML simulation on ${backend}" in {
assert(invokeMlSimulator(backend, name, debug, additionalArgs) == 0)
}
}
}
def runSuite(backend: String, debug: Boolean = false)(suite: RocketTestSuite) {
// compile emulators
behavior of s"${suite.makeTargetName} running on $backend"
if (isCmdAvailable(backend)) {
val postfix = suite match {
case _: BenchmarkTestSuite | _: BlockdevTestSuite | _: NICTestSuite => ".riscv"
case _ => ""
}
it should s"pass all tests in ${suite.makeTargetName}" in {
val results = suite.names.toSeq sliding (N, N) map { t =>
val subresults = t map (name =>
Future(name -> invokeMlSimulator(backend, s"$name$postfix", debug)))
Await result (Future sequence subresults, Duration.Inf)
}
results.flatten foreach { case (name, exitcode) =>
assert(exitcode == 0, "Failed $name")
}
}
} else {
ignore should s"pass $backend"
}
}
// Checks the collected trace log matches the behavior of a chisel printf
def diffTracelog(verilatedLog: String) {
behavior of "captured instruction trace"
it should s"match the chisel printf in ${verilatedLog}" in {
def getLines(file: File): Seq[String] = Source.fromFile(file).getLines.toList
val printfPrefix = "TRACEPORT 0: "
val verilatedOutput = getLines(new File(outDir, s"/${verilatedLog}")).collect({
case line if line.startsWith(printfPrefix) => line.stripPrefix(printfPrefix) })
// Last bit indicates the core was under reset; reject those tokens
// Tail to drop the first token which is initialized in the channel
val synthPrintOutput = getLines(new File(genDir, s"/TRACEFILE")).tail.filter(line =>
(line.last.toInt & 1) == 0)
assert(math.abs(verilatedOutput.size - synthPrintOutput.size) <= 1,
s"\nPrintf Length: ${verilatedOutput.size}, Trace Length: ${synthPrintOutput.size}")
assert(verilatedOutput.nonEmpty)
for ( (vPrint, sPrint) <- verilatedOutput.zip(synthPrintOutput) ) {
assert(vPrint == sPrint)
}
}
}
mkdirs
behavior of s"Tuple: ${targetTuple}"
elaborateAndCompile()
runTest("verilator", "rv64ui-p-simple", false, Seq(s"""EXTRA_SIM_ARGS=+trace-humanreadable0"""))
runSuite("verilator")(benchmarks)
}
class RocketF1Tests extends FireSimTestSuite("FireSim", "DDR3FRFCFSLLC4MB_FireSimQuadRocketConfig", "WithSynthAsserts_BaseF1Config")
class BoomF1Tests extends FireSimTestSuite("FireSim", "DDR3FRFCFSLLC4MB_FireSimLargeBoomConfig", "BaseF1Config")
class RocketNICF1Tests extends FireSimTestSuite("FireSim", "WithNIC_DDR3FRFCFSLLC4MB_FireSimRocketConfig", "BaseF1Config")
// Multiclock tests
class RocketMulticlockF1Tests extends FireSimTestSuite(
"FireSim",
"FireSimMulticlockRocketConfig",
"WithSynthAsserts_BaseF1Config")
class CVA6F1Tests extends FireSimTestSuite("FireSim", "WithNIC_DDR3FRFCFSLLC4MB_FireSimCVA6Config", "BaseF1Config")
// This test suite only mirrors what is run in CI. CI invokes each test individually, using a testOnly call.
class CITests extends Suites(
new RocketF1Tests,
new BoomF1Tests,
new RocketNICF1Tests,
new RocketMulticlockF1Tests)