TestIndividualFeatures is now multithreaded

This commit is contained in:
Dolu1990 2020-03-01 21:40:53 +01:00
parent 02545b9bea
commit ea5464ea26
3 changed files with 160 additions and 79 deletions

View File

@ -2805,7 +2805,7 @@ public:
uint32_t regFileWriteRefIndex = 0;
TestA() : WorkspaceRegression("testA") {
loadHex("../../resources/hex/testA.hex");
loadHex(string(REGRESSION_PATH) + "../../resources/hex/testA.hex");
}
virtual void checks(){
@ -2831,7 +2831,7 @@ public:
TestX28(string name, uint32_t *ref, uint32_t refSize) : WorkspaceRegression(name) {
this->ref = ref;
this->refSize = refSize;
loadHex("../../resources/hex/" + name + ".hex");
loadHex(string(REGRESSION_PATH) + "../../resources/hex/" + name + ".hex");
}
virtual void checks(){
@ -2851,7 +2851,7 @@ public:
class RiscvTest : public WorkspaceRegression{
public:
RiscvTest(string name) : WorkspaceRegression(name) {
loadHex("../../resources/hex/" + name + ".hex");
loadHex(string(REGRESSION_PATH) + "../../resources/hex/" + name + ".hex");
bootAt(0x800000bcu);
}
@ -2899,7 +2899,7 @@ public:
setIStall(iStall);
setDStall(dStall);
withRiscvRef();
loadHex("../../resources/hex/" + hexName + ".hex");
loadHex(string(REGRESSION_PATH) + "../../resources/hex/" + hexName + ".hex");
this->hexName = hexName;
}
@ -2942,7 +2942,7 @@ public:
int out32Counter = 0;
Compliance(string name) : WorkspaceRegression(name) {
withRiscvRef();
loadHex("../../resources/hex/" + name + ".elf.hex");
loadHex(string(REGRESSION_PATH) + "../../resources/hex/" + name + ".elf.hex");
out32.open (name + ".out32");
this->name = name;
}
@ -2963,7 +2963,7 @@ public:
virtual void pass(){
FILE *refFile = fopen((string("../../resources/ref/") + name + ".reference_output").c_str(), "r");
FILE *refFile = fopen((string(REGRESSION_PATH) + string("../../resources/ref/") + name + ".reference_output").c_str(), "r");
fseek(refFile, 0, SEEK_END);
uint32_t refSize = ftell(refFile);
fseek(refFile, 0, SEEK_SET);
@ -3152,7 +3152,7 @@ public:
DebugPluginTest() : WorkspaceRegression("DebugPluginTest") {
loadHex("../../resources/hex/debugPlugin.hex");
loadHex(string(REGRESSION_PATH) + "../../resources/hex/debugPlugin.hex");
pthread_create(&clientThreadId, NULL, &clientThreadWrapper, this);
}
@ -3837,17 +3837,17 @@ int main(int argc, char **argv, char **env) {
// #endif
#ifdef IBUS_CACHED
redo(REDO,WorkspaceRegression("icache").withRiscvRef()->loadHex("../raw/icache/build/icache.hex")->bootAt(0x80000000u)->run(50e3););
redo(REDO,WorkspaceRegression("icache").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../raw/icache/build/icache.hex")->bootAt(0x80000000u)->run(50e3););
#endif
#ifdef DBUS_CACHED
redo(REDO,WorkspaceRegression("dcache").loadHex("../raw/dcache/build/dcache.hex")->bootAt(0x80000000u)->run(2500e3););
redo(REDO,WorkspaceRegression("dcache").loadHex(string(REGRESSION_PATH) + "../raw/dcache/build/dcache.hex")->bootAt(0x80000000u)->run(2500e3););
#endif
#ifdef MMU
redo(REDO,WorkspaceRegression("mmu").withRiscvRef()->loadHex("../raw/mmu/build/mmu.hex")->bootAt(0x80000000u)->run(50e3););
redo(REDO,WorkspaceRegression("mmu").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../raw/mmu/build/mmu.hex")->bootAt(0x80000000u)->run(50e3););
#endif
#ifdef SUPERVISOR
redo(REDO,WorkspaceRegression("deleg").withRiscvRef()->loadHex("../raw/deleg/build/deleg.hex")->bootAt(0x80000000u)->run(50e3););
redo(REDO,WorkspaceRegression("deleg").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../raw/deleg/build/deleg.hex")->bootAt(0x80000000u)->run(50e3););
#endif
#ifdef DEBUG_PLUGIN
@ -3858,20 +3858,20 @@ int main(int argc, char **argv, char **env) {
#endif
#ifdef CUSTOM_SIMD_ADD
redo(REDO,WorkspaceRegression("custom_simd_add").loadHex("../custom/simd_add/build/custom_simd_add.hex")->bootAt(0x00000000u)->run(50e3););
redo(REDO,WorkspaceRegression("custom_simd_add").loadHex(string(REGRESSION_PATH) + "../custom/simd_add/build/custom_simd_add.hex")->bootAt(0x00000000u)->run(50e3););
#endif
#ifdef CUSTOM_CSR
redo(REDO,WorkspaceRegression("custom_csr").loadHex("../custom/custom_csr/build/custom_csr.hex")->bootAt(0x00000000u)->run(50e3););
redo(REDO,WorkspaceRegression("custom_csr").loadHex(string(REGRESSION_PATH) + "../custom/custom_csr/build/custom_csr.hex")->bootAt(0x00000000u)->run(50e3););
#endif
#ifdef LRSC
redo(REDO,WorkspaceRegression("lrsc").withRiscvRef()->loadHex("../raw/lrsc/build/lrsc.hex")->bootAt(0x00000000u)->run(10e3););
redo(REDO,WorkspaceRegression("lrsc").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../raw/lrsc/build/lrsc.hex")->bootAt(0x00000000u)->run(10e3););
#endif
#ifdef AMO
redo(REDO,WorkspaceRegression("amo").withRiscvRef()->loadHex("../raw/amo/build/amo.hex")->bootAt(0x00000000u)->run(10e3););
redo(REDO,WorkspaceRegression("amo").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../raw/amo/build/amo.hex")->bootAt(0x00000000u)->run(10e3););
#endif
#ifdef DHRYSTONE
@ -3910,7 +3910,7 @@ int main(int argc, char **argv, char **env) {
if(withStall == -1) break;
#endif
WorkspaceRegression("coremark_" + rv + (withStall > 0 ? "_stall" : "_nostall")).withRiscvRef()
->loadBin("../../resources/bin/coremark_" + rv + ".bin", 0x80000000)
->loadBin(string(REGRESSION_PATH) + "../../resources/bin/coremark_" + rv + ".bin", 0x80000000)
->bootAt(0x80000000)
->setIStall(withStall > 0)
->setDStall(withStall > 0)
@ -3930,17 +3930,17 @@ int main(int argc, char **argv, char **env) {
/*for(int redo = 0;redo < 4;redo++)*/{
for(const string &name : freeRtosTests){
tasks.push_back([=]() { WorkspaceRegression(name + "_rv32i_O0").withRiscvRef()->loadHex("../../resources/freertos/" + name + "_rv32i_O0.hex")->bootAt(0x80000000u)->run(4e6*15);});
tasks.push_back([=]() { WorkspaceRegression(name + "_rv32i_O3").withRiscvRef()->loadHex("../../resources/freertos/" + name + "_rv32i_O3.hex")->bootAt(0x80000000u)->run(4e6*15);});
tasks.push_back([=]() { WorkspaceRegression(name + "_rv32i_O0").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../../resources/freertos/" + name + "_rv32i_O0.hex")->bootAt(0x80000000u)->run(4e6*15);});
tasks.push_back([=]() { WorkspaceRegression(name + "_rv32i_O3").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../../resources/freertos/" + name + "_rv32i_O3.hex")->bootAt(0x80000000u)->run(4e6*15);});
#ifdef COMPRESSED
// tasks.push_back([=]() { WorkspaceRegression(name + "_rv32ic_O0").withRiscvRef()->loadHex("../../resources/freertos/" + name + "_rv32ic_O0.hex")->bootAt(0x80000000u)->run(5e6*15);});
tasks.push_back([=]() { WorkspaceRegression(name + "_rv32ic_O3").withRiscvRef()->loadHex("../../resources/freertos/" + name + "_rv32ic_O3.hex")->bootAt(0x80000000u)->run(4e6*15);});
// tasks.push_back([=]() { WorkspaceRegression(name + "_rv32ic_O0").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../../resources/freertos/" + name + "_rv32ic_O0.hex")->bootAt(0x80000000u)->run(5e6*15);});
tasks.push_back([=]() { WorkspaceRegression(name + "_rv32ic_O3").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../../resources/freertos/" + name + "_rv32ic_O3.hex")->bootAt(0x80000000u)->run(4e6*15);});
#endif
#if defined(MUL) && defined(DIV)
// #ifdef COMPRESSED
// tasks.push_back([=]() { WorkspaceRegression(name + "_rv32imac_O3").withRiscvRef()->loadHex("../../resources/freertos/" + name + "_rv32imac_O3.hex")->bootAt(0x80000000u)->run(4e6*15);});
// tasks.push_back([=]() { WorkspaceRegression(name + "_rv32imac_O3").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../../resources/freertos/" + name + "_rv32imac_O3.hex")->bootAt(0x80000000u)->run(4e6*15);});
// #else
tasks.push_back([=]() { WorkspaceRegression(name + "_rv32im_O3").withRiscvRef()->loadHex("../../resources/freertos/" + name + "_rv32im_O3.hex")->bootAt(0x80000000u)->run(4e6*15);});
tasks.push_back([=]() { WorkspaceRegression(name + "_rv32im_O3").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../../resources/freertos/" + name + "_rv32im_O3.hex")->bootAt(0x80000000u)->run(4e6*15);});
// #endif
#endif
}
@ -3967,12 +3967,12 @@ int main(int argc, char **argv, char **env) {
/*for(int redo = 0;redo < 4;redo++)*/{
for(const string &name : zephyrTests){
#ifdef COMPRESSED
tasks.push_back([=]() { ZephyrRegression(name + "_rv32ic").withRiscvRef()->loadHex("../../resources/VexRiscvRegressionData/sim/zephyr/" + name + "_rv32ic.hex")->bootAt(0x80000000u)->run(180e6);});
tasks.push_back([=]() { ZephyrRegression(name + "_rv32ic").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../../resources/VexRiscvRegressionData/sim/zephyr/" + name + "_rv32ic.hex")->bootAt(0x80000000u)->run(180e6);});
#else
tasks.push_back([=]() { ZephyrRegression(name + "_rv32i").withRiscvRef()->loadHex("../../resources/VexRiscvRegressionData/sim/zephyr/" + name + "_rv32i.hex")->bootAt(0x80000000u)->run(180e6);});
tasks.push_back([=]() { ZephyrRegression(name + "_rv32i").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../../resources/VexRiscvRegressionData/sim/zephyr/" + name + "_rv32i.hex")->bootAt(0x80000000u)->run(180e6);});
#endif
#if defined(MUL) && defined(DIV)
tasks.push_back([=]() { ZephyrRegression(name + "_rv32im").withRiscvRef()->loadHex("../../resources/VexRiscvRegressionData/sim/zephyr/" + name + "_rv32im.hex")->bootAt(0x80000000u)->run(180e6);});
tasks.push_back([=]() { ZephyrRegression(name + "_rv32im").withRiscvRef()->loadHex(string(REGRESSION_PATH) + "../../resources/VexRiscvRegressionData/sim/zephyr/" + name + "_rv32im.hex")->bootAt(0x80000000u)->run(180e6);});
#endif
}
}
@ -3993,10 +3993,10 @@ int main(int argc, char **argv, char **env) {
LinuxRegression soc("linux");
#ifndef DEBUG_PLUGIN_EXTERNAL
soc.withRiscvRef();
soc.loadBin(EMULATOR, 0x80000000);
soc.loadBin(VMLINUX, 0xC0000000);
soc.loadBin(DTB, 0xC3000000);
soc.loadBin(RAMDISK, 0xC2000000);
soc.loadBin(string(REGRESSION_PATH) + EMULATOR, 0x80000000);
soc.loadBin(string(REGRESSION_PATH) + VMLINUX, 0xC0000000);
soc.loadBin(string(REGRESSION_PATH) + DTB, 0xC3000000);
soc.loadBin(string(REGRESSION_PATH) + RAMDISK, 0xC2000000);
#endif
//soc.setIStall(true);
//soc.setDStall(true);

View File

@ -1,5 +1,6 @@
DEBUG?=no
REGRESSION_PATH?=./
VEXRISCV_FILE?=../../../../VexRiscv.v
IBUS?=CACHED
IBUS_TC?=no
DBUS?=CACHED
@ -38,6 +39,7 @@ STOP_ON_ERROR?=no
COREMARK=no
WITH_USER_IO?=no
ADDCFLAGS += -CFLAGS -DREGRESSION_PATH='\"$(REGRESSION_PATH)/\"'
ADDCFLAGS += -CFLAGS -DIBUS_${IBUS}
ADDCFLAGS += -CFLAGS -DDBUS_${DBUS}
ADDCFLAGS += -CFLAGS -DREDO=${REDO}
@ -107,11 +109,11 @@ endif
ifneq ($(shell grep timerInterrupt ../../../../VexRiscv.v -w),)
ifneq ($(shell grep timerInterrupt ${VEXRISCV_FILE} -w),)
ADDCFLAGS += -CFLAGS -DTIMER_INTERRUPT
endif
ifneq ($(shell grep externalInterrupt ../../../../VexRiscv.v -w),)
ifneq ($(shell grep externalInterrupt ${VEXRISCV_FILE} -w),)
ifneq ($(EXTERNAL_INTERRUPT),no)
ADDCFLAGS += -CFLAGS -DEXTERNAL_INTERRUPT
endif
@ -267,10 +269,9 @@ all: clean run
run: compile
./obj_dir/VVexRiscv
verilate: ../../../../VexRiscv.v
rm -f VexRiscv.v*.bin
cp ../../../../VexRiscv.v*.bin . | true
verilator -cc ../../../../VexRiscv.v -O3 -CFLAGS -std=c++11 -LDFLAGS -pthread ${ADDCFLAGS} --gdbbt ${VERILATOR_ARGS} -Wno-UNOPTFLAT -Wno-WIDTH --x-assign unique --exe main.cpp
verilate: ${VEXRISCV_FILE}
cp ${VEXRISCV_FILE}*.bin . | true
verilator -cc ${VEXRISCV_FILE} -O3 -CFLAGS -std=c++11 -LDFLAGS -pthread ${ADDCFLAGS} --gdbbt ${VERILATOR_ARGS} -Wno-UNOPTFLAT -Wno-WIDTH --x-assign unique --exe main.cpp
compile: verilate
make -j${THREAD_COUNT} -C obj_dir/ -f VVexRiscv.mk VVexRiscv

View File

@ -1,9 +1,10 @@
package vexriscv
import java.io.File
import java.io.{File, OutputStream}
import java.util.concurrent.TimeUnit
import org.apache.commons.io.FileUtils
import org.scalatest.{BeforeAndAfterAll, FunSuite, ParallelTestExecution}
import org.scalatest.{BeforeAndAfterAll, FunSuite, ParallelTestExecution, Tag, Transformer}
import spinal.core._
import vexriscv.demo._
import vexriscv.ip.{DataCacheConfig, InstructionCacheConfig}
@ -11,6 +12,8 @@ import vexriscv.plugin._
import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer
import scala.concurrent.duration.Duration
import scala.concurrent.{Await, ExecutionContext, Future}
import scala.sys.process._
import scala.util.Random
@ -534,6 +537,7 @@ class DebugDimension extends VexRiscvDimension("Debug") {
},
new VexRiscvPosition("Enable") {
override def applyOn(config: VexRiscvConfig): Unit = config.plugins += new DebugPlugin(ClockDomain.current.clone(reset = Bool().setName("debugReset")))
override def testParam = "CONCURRENT_OS_EXECUTIONS=yes"
}
))
}
@ -553,21 +557,80 @@ class DecoderDimension extends VexRiscvDimension("Decoder") {
}
}
object PlayFuture extends App{
implicit val ec = ExecutionContext.global
val x = for(i <- 0 until 160) yield Future {
print(s"$i ")
Thread.sleep(1000)
}
//class TesterPlay extends FunSuite with ParallelTestExecution {
// def createTest(name : String): Unit ={
// test(name){
// for(i <- 0 to 4) {
// println(s"$name $i")
// Thread.sleep(2000)
// }
// }
// }
// List("a", "b","c").foreach(createTest)
//}
Thread.sleep(8000)
}
class MultithreadedFunSuite extends FunSuite {
implicit val ec = ExecutionContext.global
class Job(body : => Unit){
val originalOutput = Console.out
val buffer = mutable.Queue[Char]()
var bufferEnabled = true
def redirector() = new OutputStream{
override def write(i: Int): Unit = synchronized {
if(bufferEnabled) buffer += i.toChar
else originalOutput.print(i.toChar)
}
}
val future = Future{
Console.withOut(redirector()){
Console.withErr(redirector())(body)
}
}
def join(): Unit = {
Thread.sleep(50)
synchronized{
bufferEnabled = false
buffer.foreach(originalOutput.print)
}
Await.result(future, Duration.Inf)
}
}
override protected def test(testName: String, testTags: Tag*)(testFun: => Unit) {
val job = new Job(testFun)
super.test(testName, testTags :_*)(job.join())
}
protected def testSingleThread(testName: String, testTags: Tag*)(testFun: => Unit) {
super.test(testName, testTags :_*)(testFun)
}
}
class TestIndividualFeatures extends FunSuite {
class FunTestPara extends MultithreadedFunSuite{
def createTest(name : String): Unit ={
test(name){
for(i <- 0 to 4) {
println(s"$name $i")
Thread.sleep(500)
}
}
}
(0 to 80).map(_.toString).foreach(createTest)
}
class FunTestPlay extends FunSuite {
def createTest(name : String): Unit ={
test(name){
Thread.sleep(500)
for(i <- 0 to 4) {
println(s"$name $i")
Thread.sleep(500)
}
}
}
(0 to 80).map(_.toString).foreach(createTest)
}
class TestIndividualFeatures extends MultithreadedFunSuite {
val testCount = sys.env.getOrElse("VEXRISCV_REGRESSION_CONFIG_COUNT", "100").toInt
val seed = sys.env.getOrElse("VEXRISCV_REGRESSION_SEED", Random.nextLong().toString).toLong
val testId : Set[Int] = sys.env.get("VEXRISCV_REGRESSION_TEST_ID") match {
@ -582,24 +645,8 @@ class TestIndividualFeatures extends FunSuite {
val zephyrCount = sys.env.getOrElse("VEXRISCV_REGRESSION_ZEPHYR_COUNT", "4")
val demwRate = sys.env.getOrElse("VEXRISCV_REGRESSION_CONFIG_DEMW_RATE", "0.6").toDouble
val demRate = sys.env.getOrElse("VEXRISCV_REGRESSION_CONFIG_DEM_RATE", "0.5").toDouble
val lock = new{}
def doCmd(cmd: String): String = {
val stdOut = new StringBuilder()
class Logger extends ProcessLogger {
override def err(s: => String): Unit = {
if (!s.startsWith("ar: creating ")) println(s)
}
override def out(s: => String): Unit = {
println(s)
stdOut ++= s
}
override def buffer[T](f: => T) = f
}
Process(cmd, new File("src/test/cpp/regression")).!(new Logger)
stdOut.toString()
}
val dimensions = List(
@ -617,12 +664,40 @@ class TestIndividualFeatures extends FunSuite {
new MmuDimension
)
var clockCounter = 0l
var startAt = System.currentTimeMillis()
def doTest(positionsToApply : List[VexRiscvPosition], prefix : String = "", testSeed : Int, universes : mutable.HashSet[VexRiscvUniverse]): Unit ={
val noMemory = universes.contains(VexRiscvUniverse.NO_MEMORY)
val noWriteback = universes.contains(VexRiscvUniverse.NO_WRITEBACK)
def gen = {
val name = (if(noMemory) "noMemoryStage_" else "") + (if(noWriteback) "noWritebackStage_" else "") + positionsToApply.map(d => d.dimension.name + "_" + d.name).mkString("_")
val workspace = "simWorkspace"
val project = s"$workspace/$prefix"
def doCmd(cmd: String): String = {
val stdOut = new StringBuilder()
class Logger extends ProcessLogger {
override def err(s: => String): Unit = {
if (!s.startsWith("ar: creating ")) println(s)
}
override def out(s: => String): Unit = {
println(s)
stdOut ++= s
}
override def buffer[T](f: => T) = f
}
Process(cmd, new File(project)).!(new Logger)
stdOut.toString()
}
test(prefix + name) {
println("START TEST " + prefix + name)
//Cleanup
FileUtils.deleteDirectory(new File(project))
FileUtils.forceMkdir(new File(project))
//Generate RTL
FileUtils.deleteQuietly(new File("VexRiscv.v"))
SpinalVerilog{
SpinalConfig(targetDirectory = project).generateVerilog{
val config = VexRiscvConfig(
withMemoryStage = !noMemory,
withWriteBackStage = !noWriteback,
@ -634,22 +709,22 @@ class TestIndividualFeatures extends FunSuite {
for (positionToApply <- positionsToApply) positionToApply.applyOn(config)
new VexRiscv(config)
}
}
val name = (if(noMemory) "noMemoryStage_" else "") + (if(noWriteback) "noWritebackStage_" else "") + positionsToApply.map(d => d.dimension.name + "_" + d.name).mkString("_")
test(prefix + "gen_" + name) {
gen
}
//Setup test
val files = List("main.cpp", "encoding.h" ,"makefile", "dhrystoneO3.logRef", "dhrystoneO3C.logRef","dhrystoneO3MC.logRef","dhrystoneO3M.logRef")
files.foreach(f => FileUtils.copyFileToDirectory(new File(s"src/test/cpp/regression/$f"), new File(project)))
test(prefix + "test_" + name) {
println("START TEST " + prefix + name)
//Test RTL
val debug = true
val stdCmd = (s"make clean run WITH_USER_IO=no REDO=10 TRACE=${if(debug) "yes" else "no"} TRACE_START=1000000000000l STOP_ON_ERROR=no FLOW_INFO=no STOP_ON_ERROR=no DHRYSTONE=yes COREMARK=${coremarkRegression} THREAD_COUNT=1 ") + s" SEED=${testSeed} "
val stdCmd = (s"make run REGRESSION_PATH=../../src/test/cpp/regression VEXRISCV_FILE=VexRiscv.v WITH_USER_IO=no REDO=10 TRACE=${if(debug) "yes" else "no"} TRACE_START=1000000000000l STOP_ON_ERROR=no FLOW_INFO=no STOP_ON_ERROR=no DHRYSTONE=yes COREMARK=${coremarkRegression} THREAD_COUNT=1 ") + s" SEED=${testSeed} "
val testCmd = stdCmd + (positionsToApply).map(_.testParam).mkString(" ")
println(testCmd)
val str = doCmd(testCmd)
assert(str.contains("REGRESSION SUCCESS") && !str.contains("Broken pipe"))
val pattern = "Had simulate ([0-9]+)".r
val hit = pattern.findFirstMatchIn(str)
lock.synchronized(clockCounter += hit.get.group(1).toLong)
}
}
@ -693,7 +768,12 @@ class TestIndividualFeatures extends FunSuite {
val testSeed = rand.nextInt()
if(testId.contains(i))
doTest(positions," test_id_" + i + "_", testSeed, universe)
doTest(positions,"test_id_" + i + "_", testSeed, universe)
Hack.dCounter += 1
}
testSingleThread("report"){
val time = (System.currentTimeMillis() - startAt)*1e-3
val clockPerSecond = (clockCounter/time*1e-3).toLong
println(s"Duration=${(time/60).toInt}mn clocks=${(clockCounter*1e-6).toLong}M clockPerSecond=${clockPerSecond}K")
}
}