diff --git a/src/main/scala/vexriscv/VexRiscv.scala b/src/main/scala/vexriscv/VexRiscv.scala index 3350dc9..5f7865c 100644 --- a/src/main/scala/vexriscv/VexRiscv.scala +++ b/src/main/scala/vexriscv/VexRiscv.scala @@ -23,6 +23,12 @@ case class VexRiscvConfig(){ val plugins = ArrayBuffer[Plugin[VexRiscv]]() def add(that : Plugin[VexRiscv]) : this.type = {plugins += that;this} + def find[T](clazz: Class[T]): Option[T] = { + plugins.find(_.getClass == clazz) match { + case Some(x) => Some(x.asInstanceOf[T]) + case None => None + } + } //Default Stageables object IS_RVC extends Stageable(Bool) diff --git a/src/main/scala/vexriscv/VexRiscvBmbGenerator.scala b/src/main/scala/vexriscv/VexRiscvBmbGenerator.scala index d7d578f..5460299 100644 --- a/src/main/scala/vexriscv/VexRiscvBmbGenerator.scala +++ b/src/main/scala/vexriscv/VexRiscvBmbGenerator.scala @@ -1,7 +1,7 @@ package vexriscv import spinal.core._ -import spinal.lib.bus.bmb.{Bmb, BmbAccessCapabilities, BmbAccessParameter, BmbImplicitDebugDecoder, BmbParameter, BmbSmpInterconnectGenerator} +import spinal.lib.bus.bmb.{Bmb, BmbAccessCapabilities, BmbAccessParameter, BmbImplicitDebugDecoder, BmbInvalidationParameter, BmbParameter, BmbSmpInterconnectGenerator} import spinal.lib.bus.misc.AddressMapping import spinal.lib.com.jtag.{Jtag, JtagTapInstructionCtrl} import spinal.lib.generator._ @@ -148,9 +148,17 @@ case class VexRiscvBmbGenerator()(implicit interconnectSmp: BmbSmpInterconnectGe } } + val invalidationSource = Handle[BmbInvalidationParameter] + val invalidationRequirements = Handle[BmbInvalidationParameter] if(interconnectSmp != null){ interconnectSmp.addMaster(accessRequirements = parameterGenerator.iBusParameter.derivate(_.access), bus = iBus) - interconnectSmp.addMaster(accessRequirements = parameterGenerator.dBusParameter.derivate(_.access), bus = dBus) + interconnectSmp.addMaster( + accessRequirements = parameterGenerator.dBusParameter.derivate(_.access), + invalidationSource = invalidationSource, + invalidationCapabilities = invalidationSource, + invalidationRequirements = invalidationRequirements, + bus = dBus + ) } } diff --git a/src/main/scala/vexriscv/demo/SynthesisBench.scala b/src/main/scala/vexriscv/demo/SynthesisBench.scala index b6e9f2f..d0a2118 100644 --- a/src/main/scala/vexriscv/demo/SynthesisBench.scala +++ b/src/main/scala/vexriscv/demo/SynthesisBench.scala @@ -54,39 +54,86 @@ object VexRiscvSynthesisBench { val twoStage = new Rtl { override def getName(): String = "VexRiscv two stages" override def getRtlPath(): String = "VexRiscvTwoStages.v" - SpinalVerilog(wrap(GenTwoStage.cpu( + SpinalVerilog(wrap(GenTwoThreeStage.cpu( withMulDiv = false, bypass = false, - barrielShifter = false + barrielShifter = false, + withMemoryStage = false )).setDefinitionName(getRtlPath().split("\\.").head)) } val twoStageBarell = new Rtl { override def getName(): String = "VexRiscv two stages with barriel" override def getRtlPath(): String = "VexRiscvTwoStagesBar.v" - SpinalVerilog(wrap(GenTwoStage.cpu( + SpinalVerilog(wrap(GenTwoThreeStage.cpu( withMulDiv = false, bypass = true, - barrielShifter = true + barrielShifter = true, + withMemoryStage = false )).setDefinitionName(getRtlPath().split("\\.").head)) } val twoStageMulDiv = new Rtl { override def getName(): String = "VexRiscv two stages with Mul Div" override def getRtlPath(): String = "VexRiscvTwoStagesMD.v" - SpinalVerilog(wrap(GenTwoStage.cpu( + SpinalVerilog(wrap(GenTwoThreeStage.cpu( withMulDiv = true, bypass = false, - barrielShifter = false + barrielShifter = false, + withMemoryStage = false )).setDefinitionName(getRtlPath().split("\\.").head)) } val twoStageAll = new Rtl { override def getName(): String = "VexRiscv two stages with Mul Div fast" override def getRtlPath(): String = "VexRiscvTwoStagesMDfast.v" - SpinalVerilog(wrap(GenTwoStage.cpu( + SpinalVerilog(wrap(GenTwoThreeStage.cpu( withMulDiv = true, bypass = true, - barrielShifter = true + barrielShifter = true, + withMemoryStage = false )).setDefinitionName(getRtlPath().split("\\.").head)) } + + + val threeStage = new Rtl { + override def getName(): String = "VexRiscv three stages" + override def getRtlPath(): String = "VexRiscvThreeStages.v" + SpinalVerilog(wrap(GenTwoThreeStage.cpu( + withMulDiv = false, + bypass = false, + barrielShifter = false, + withMemoryStage = true + )).setDefinitionName(getRtlPath().split("\\.").head)) + } + val threeStageBarell = new Rtl { + override def getName(): String = "VexRiscv three stages with barriel" + override def getRtlPath(): String = "VexRiscvThreeStagesBar.v" + SpinalVerilog(wrap(GenTwoThreeStage.cpu( + withMulDiv = false, + bypass = true, + barrielShifter = true, + withMemoryStage = true + )).setDefinitionName(getRtlPath().split("\\.").head)) + } + val threeStageMulDiv = new Rtl { + override def getName(): String = "VexRiscv three stages with Mul Div" + override def getRtlPath(): String = "VexRiscvThreeStagesMD.v" + SpinalVerilog(wrap(GenTwoThreeStage.cpu( + withMulDiv = true, + bypass = false, + barrielShifter = false, + withMemoryStage = true + )).setDefinitionName(getRtlPath().split("\\.").head)) + } + val threeStageAll = new Rtl { + override def getName(): String = "VexRiscv three stages with Mul Div fast" + override def getRtlPath(): String = "VexRiscvThreeStagesMDfast.v" + SpinalVerilog(wrap(GenTwoThreeStage.cpu( + withMulDiv = true, + bypass = true, + barrielShifter = true, + withMemoryStage = true + )).setDefinitionName(getRtlPath().split("\\.").head)) + } + val smallestNoCsr = new Rtl { override def getName(): String = "VexRiscv smallest no CSR" override def getRtlPath(): String = "VexRiscvSmallestNoCsr.v" @@ -155,8 +202,12 @@ object VexRiscvSynthesisBench { -// val rtls = List(twoStage, twoStageBarell, twoStageMulDiv, twoStageAll, smallestNoCsr, smallest, smallAndProductive, smallAndProductiveWithICache, fullNoMmuNoCache, noCacheNoMmuMaxPerf, fullNoMmuMaxPerf, fullNoMmu, full, linuxBalanced, linuxBalancedSmp) - val rtls = List(linuxBalanced, linuxBalancedSmp) + val rtls = List( + twoStage, twoStageBarell, twoStageMulDiv, twoStageAll, + threeStage, threeStageBarell, threeStageMulDiv, threeStageAll, + smallestNoCsr, smallest, smallAndProductive, smallAndProductiveWithICache, fullNoMmuNoCache, noCacheNoMmuMaxPerf, fullNoMmuMaxPerf, fullNoMmu, full, linuxBalanced, linuxBalancedSmp + ) +// val rtls = List(linuxBalanced, linuxBalancedSmp) // val rtls = List(smallest) val targets = XilinxStdTargets() ++ AlteraStdTargets() ++ IcestormStdTargets().take(1) ++ List( new Target { diff --git a/src/main/scala/vexriscv/ip/DataCache.scala b/src/main/scala/vexriscv/ip/DataCache.scala index d5e688c..78f9607 100644 --- a/src/main/scala/vexriscv/ip/DataCache.scala +++ b/src/main/scala/vexriscv/ip/DataCache.scala @@ -88,7 +88,8 @@ case class DataCacheConfig(cacheSize : Int, lengthWidth = log2Up(this.bytePerLine), contextWidth = (if(!withWriteResponse) 1 else 0) + (if(cpuDataWidth != memDataWidth) log2Up(memDataBytes) else 0), alignment = BmbParameter.BurstAlignement.LENGTH, - canExclusive = withExclusive + canExclusive = withExclusive, + withCachedRead = true )), BmbInvalidationParameter( canInvalidate = withInvalidate, diff --git a/src/test/cpp/regression/main.cpp b/src/test/cpp/regression/main.cpp index 5468545..bc960fb 100644 --- a/src/test/cpp/regression/main.cpp +++ b/src/test/cpp/regression/main.cpp @@ -1248,8 +1248,13 @@ public: }; CpuRef riscvRef = CpuRef(this); - + string vcdName; + Workspace* setVcdName(string name){ + vcdName = name; + return this; + } Workspace(string name){ + vcdName = name; //seed = VL_RANDOM_I(32)^VL_RANDOM_I(32)^0x1093472; //srand48(seed); // setIStall(false); @@ -1450,7 +1455,7 @@ public: Verilated::traceEverOn(true); tfp = new VerilatedVcdC; top->trace(tfp, 99); - tfp->open((string(name)+ ".vcd").c_str()); + tfp->open((vcdName + ".vcd").c_str()); #endif // Reset @@ -1679,7 +1684,7 @@ public: - dump(i); + dump(i+2); dump(i+10); #ifdef TRACE tfp->close(); @@ -1750,6 +1755,7 @@ public: #endif case 0xF00FFF48u: mTimeCmp = (mTimeCmp & 0xFFFFFFFF00000000) | *data;break; case 0xF00FFF4Cu: mTimeCmp = (mTimeCmp & 0x00000000FFFFFFFF) | (((uint64_t)*data) << 32); break; + case 0xF00FFF50u: cout << "mTime " << *data << " : " << mTime << endl; } if((addr & 0xFFFFF000) == 0xF5670000){ uint32_t t = 0x900FF000 | (addr & 0xFFF); @@ -3970,14 +3976,15 @@ int main(int argc, char **argv, char **env) { w.loadHex(RUN_HEX); w.withRiscvRef(); #endif - //w.setIStall(false); - //w.setDStall(false); + w.setIStall(false); + w.setDStall(false); #if defined(TRACE) || defined(TRACE_ACCESS) //w.setCyclesPerSecond(5e3); //printf("Speed reduced 5Khz\n"); #endif w.run(0xFFFFFFFFFFFF); + exit(0); } #endif @@ -4047,11 +4054,11 @@ int main(int argc, char **argv, char **env) { #ifndef COMPRESSED uint32_t machineCsrRef[] = {1,11, 2,0x80000003u, 3,0x80000007u, 4,0x8000000bu, 5,6,7,0x80000007u , 8,6,9,6,10,4,11,4, 12,13,0, 14,2, 15,5,16,17,1 }; - redo(REDO,TestX28("../../cpp/raw/machineCsr/build/machineCsr",machineCsrRef, sizeof(machineCsrRef)/4).withRiscvRef()->run(10e4);) + redo(REDO,TestX28("../../cpp/raw/machineCsr/build/machineCsr",machineCsrRef, sizeof(machineCsrRef)/4).withRiscvRef()->setVcdName("machineCsr")->run(10e4);) #else uint32_t machineCsrRef[] = {1,11, 2,0x80000003u, 3,0x80000007u, 4,0x8000000bu, 5,6,7,0x80000007u , 8,6,9,6,10,4,11,4, 12,13, 14,2, 15,5,16,17,1 }; - redo(REDO,TestX28("../../cpp/raw/machineCsr/build/machineCsrCompressed",machineCsrRef, sizeof(machineCsrRef)/4).withRiscvRef()->run(10e4);) + redo(REDO,TestX28("../../cpp/raw/machineCsr/build/machineCsrCompressed",machineCsrRef, sizeof(machineCsrRef)/4).withRiscvRef()->setVcdName("machineCsrCompressed")->run(10e4);) #endif #endif // #ifdef MMU diff --git a/src/test/scala/vexriscv/DhrystoneBench.scala b/src/test/scala/vexriscv/DhrystoneBench.scala index 39c434a..31c8c14 100644 --- a/src/test/scala/vexriscv/DhrystoneBench.scala +++ b/src/test/scala/vexriscv/DhrystoneBench.scala @@ -8,27 +8,34 @@ import vexriscv.demo._ import scala.sys.process._ -class DhrystoneBench extends FunSuite{ - def doCmd(cmd : String) : String = { +class DhrystoneBench extends FunSuite { + 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)} + 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 report = new StringBuilder() - def getDmips(name : String, gen : => Unit, testCmd : String): Unit = { + + def getDmips(name: String, gen: => Unit, testCmd: String): Unit = { var genPassed = false test(name + "_gen") { gen genPassed = true } - test(name + "_test"){ + test(name + "_test") { assert(genPassed) val str = doCmd(testCmd) assert(!str.contains("FAIL")) @@ -37,48 +44,55 @@ class DhrystoneBench extends FunSuite{ val coremarkTicks = intFind.findFirstIn("Total ticks \\: (\\d+.?)+".r.findAllIn(str).toList.last).get.toDouble val coremarkIterations = intFind.findFirstIn("Iterations \\: (\\d+.?)+".r.findAllIn(str).toList.last).get.toDouble val coremarkHzs = intFind.findFirstIn("DCLOCKS_PER_SEC=(\\d+.?)+".r.findAllIn(str).toList.last).get.toDouble - val coremarkPerMhz =1e6*coremarkIterations/coremarkTicks + val coremarkPerMhz = 1e6 * coremarkIterations / coremarkTicks report ++= s"$name -> $dmips DMIPS/Mhz $coremarkPerMhz Coremark/Mhz\n" } } - getDmips( - name = "GenTwoStageArty", - gen = SpinalVerilog(GenTwoStage.cpu( - withMulDiv = false, - bypass = false, - barrielShifter = false - )), - testCmd = "make clean run REDO=10 IBUS=SIMPLE DBUS=SIMPLE CSR=no MMU=no DEBUG_PLUGIN=no MUL=no DIV=no COREMARK=yes" - ) - getDmips( - name = "GenTwoStageBarrielArty", - gen = SpinalVerilog(GenTwoStage.cpu( - withMulDiv = false, - bypass = true, - barrielShifter = true - )), - testCmd = "make clean run REDO=10 IBUS=SIMPLE DBUS=SIMPLE CSR=no MMU=no DEBUG_PLUGIN=no MUL=no DIV=no COREMARK=yes" - ) - getDmips( - name = "GenTwoStageMDArty", - gen = SpinalVerilog(GenTwoStage.cpu( - withMulDiv = true, - bypass = false, - barrielShifter = false - )), - testCmd = "make clean run REDO=10 IBUS=SIMPLE DBUS=SIMPLE CSR=no MMU=no DEBUG_PLUGIN=no MUL=yes DIV=yes COREMARK=yes" - ) - getDmips( - name = "GenTwoStageMDBarrielArty", - gen = SpinalVerilog(GenTwoStage.cpu( - withMulDiv = true, - bypass = true, - barrielShifter = true - )), - testCmd = "make clean run REDO=10 IBUS=SIMPLE DBUS=SIMPLE CSR=no MMU=no DEBUG_PLUGIN=no MUL=yes DIV=yes COREMARK=yes" - ) + for(withMemoryStage <- List(false, true)){ + val stages = if(withMemoryStage) "Three" else "Two" + getDmips( + name = s"Gen${stages}StageArty", + gen = SpinalVerilog(GenTwoThreeStage.cpu( + withMulDiv = false, + bypass = false, + barrielShifter = false, + withMemoryStage = withMemoryStage + )), + testCmd = "make clean run REDO=10 IBUS=SIMPLE DBUS=SIMPLE CSR=no MMU=no DEBUG_PLUGIN=no MUL=no DIV=no COREMARK=yes" + ) + getDmips( + name = s"Gen${stages}StageBarrielArty", + gen = SpinalVerilog(GenTwoThreeStage.cpu( + withMulDiv = false, + bypass = true, + barrielShifter = true, + withMemoryStage = withMemoryStage + )), + testCmd = "make clean run REDO=10 IBUS=SIMPLE DBUS=SIMPLE CSR=no MMU=no DEBUG_PLUGIN=no MUL=no DIV=no COREMARK=yes" + ) + getDmips( + name = s"Gen${stages}StageMDArty", + gen = SpinalVerilog(GenTwoThreeStage.cpu( + withMulDiv = true, + bypass = false, + barrielShifter = false, + withMemoryStage = withMemoryStage + )), + testCmd = "make clean run REDO=10 IBUS=SIMPLE DBUS=SIMPLE CSR=no MMU=no DEBUG_PLUGIN=no MUL=yes DIV=yes COREMARK=yes" + ) + getDmips( + name = s"Gen${stages}StageMDBarrielArty", + gen = SpinalVerilog(GenTwoThreeStage.cpu( + withMulDiv = true, + bypass = true, + barrielShifter = true, + withMemoryStage = withMemoryStage + )), + testCmd = "make clean run REDO=10 IBUS=SIMPLE DBUS=SIMPLE CSR=no MMU=no DEBUG_PLUGIN=no MUL=yes DIV=yes COREMARK=yes" + ) + } getDmips( name = "GenSmallestNoCsr", diff --git a/src/test/scala/vexriscv/TestIndividualFeatures.scala b/src/test/scala/vexriscv/TestIndividualFeatures.scala index f3f5b28..6139bad 100644 --- a/src/test/scala/vexriscv/TestIndividualFeatures.scala +++ b/src/test/scala/vexriscv/TestIndividualFeatures.scala @@ -669,6 +669,7 @@ class TestIndividualFeatures extends MultithreadedFunSuite(sys.env.getOrElse("VE 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 stopOnError = sys.env.getOrElse("VEXRISCV_REGRESSION_STOP_ON_ERROR", "no") val lock = new{} @@ -740,7 +741,7 @@ class TestIndividualFeatures extends MultithreadedFunSuite(sys.env.getOrElse("VE //Test RTL val debug = true - 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=100000000000ll 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=100000000000ll FLOW_INFO=no STOP_ON_ERROR=$stopOnError DHRYSTONE=yes COREMARK=${coremarkRegression} THREAD_COUNT=1 ") + s" SEED=${testSeed} " val testCmd = stdCmd + (positionsToApply).map(_.testParam).mkString(" ") println(testCmd) val str = doCmd(testCmd)