From 617f4742cd2936f9e1cf988257fcaa7ec9ddc509 Mon Sep 17 00:00:00 2001 From: Charles Papon Date: Fri, 14 Jun 2019 08:13:22 +0200 Subject: [PATCH] Fix dynamic branch prediction correction on misspredicted fetch which are done on a 32 bits instruction crossing two words in configs which have at least 2 cycle latency fetch --- .../vexriscv/plugin/DecoderSimplePlugin.scala | 48 +++++++++++++------ src/main/scala/vexriscv/plugin/Fetcher.scala | 1 + .../vexriscv/TestIndividualFeatures.scala | 4 +- 3 files changed, 37 insertions(+), 16 deletions(-) diff --git a/src/main/scala/vexriscv/plugin/DecoderSimplePlugin.scala b/src/main/scala/vexriscv/plugin/DecoderSimplePlugin.scala index 22afa26..a1076e7 100644 --- a/src/main/scala/vexriscv/plugin/DecoderSimplePlugin.scala +++ b/src/main/scala/vexriscv/plugin/DecoderSimplePlugin.scala @@ -28,7 +28,7 @@ case class Masked(value : BigInt,care : BigInt){ def mergeOneBitDifSmaller(x: Masked) = { val bit = value - x.value val ret = new Masked(value &~ bit, care & ~bit) -// ret.isPrime = isPrime || x.isPrime + // ret.isPrime = isPrime || x.isPrime isPrime = false x.isPrime = false ret @@ -44,7 +44,10 @@ case class Masked(value : BigInt,care : BigInt){ def toString(bitCount : Int) = (0 until bitCount).map(i => if(care.testBit(i)) (if(value.testBit(i)) "1" else "0") else "-").reverseIterator.reduce(_+_) } -class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false, forceLegalInstructionComputation : Boolean = false) extends Plugin[VexRiscv] with DecoderService { +class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false, + throwIllegalInstruction : Boolean = false, + assertIllegalInstruction : Boolean = false, + forceLegalInstructionComputation : Boolean = false) extends Plugin[VexRiscv] with DecoderService { override def add(encoding: Seq[(MaskedLiteral, Seq[(Stageable[_ <: BaseType], Any)])]): Unit = encoding.foreach(e => this.add(e._1,e._2)) override def add(key: MaskedLiteral, values: Seq[(Stageable[_ <: BaseType], Any)]): Unit = { val instructionModel = encodings.getOrElseUpdate(key,ArrayBuffer[(Stageable[_ <: BaseType], BaseType)]()) @@ -78,6 +81,10 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false, forceLegalI } } + val detectLegalInstructions = catchIllegalInstruction || throwIllegalInstruction || forceLegalInstructionComputation || assertIllegalInstruction + + object ASSERT_ERROR extends Stageable(Bool) + override def build(pipeline: VexRiscv): Unit = { import pipeline.config._ import pipeline.decode._ @@ -86,7 +93,7 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false, forceLegalI val stupidDecoder = false if(stupidDecoder){ - if (catchIllegalInstruction || forceLegalInstructionComputation) insert(LEGAL_INSTRUCTION) := False + if (detectLegalInstructions) insert(LEGAL_INSTRUCTION) := False for(stageable <- stageables){ if(defaults.contains(stageable)){ insert(stageable).assignFrom(defaults(stageable)) @@ -96,7 +103,7 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false, forceLegalI } for((key, tasks) <- encodings){ when(input(INSTRUCTION) === key){ - if (catchIllegalInstruction || forceLegalInstructionComputation) insert(LEGAL_INSTRUCTION) := True + if (detectLegalInstructions) insert(LEGAL_INSTRUCTION) := True for((stageable, value) <- tasks){ insert(stageable).assignFrom(value) } @@ -145,8 +152,15 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false, forceLegalI // logic implementation val decodedBits = Bits(stageables.foldLeft(0)(_ + _.dataType.getBitsWidth) bits) decodedBits := Symplify(input(INSTRUCTION), spec, decodedBits.getWidth) - if (catchIllegalInstruction || forceLegalInstructionComputation) insert(LEGAL_INSTRUCTION) := Symplify.logicOf(input(INSTRUCTION), SymplifyBit.getPrimeImplicantsByTrueAndDontCare(spec.unzip._1.toSeq, Nil, 32)) - + if (detectLegalInstructions) insert(LEGAL_INSTRUCTION) := Symplify.logicOf(input(INSTRUCTION), SymplifyBit.getPrimeImplicantsByTrueAndDontCare(spec.unzip._1.toSeq, Nil, 32)) + if (throwIllegalInstruction) { + input(LEGAL_INSTRUCTION) //Fill the request for later (prePopTask) + Component.current.addPrePopTask(() => arbitration.isValid clearWhen(!input(LEGAL_INSTRUCTION))) + } + if(assertIllegalInstruction){ + val reg = RegInit(False) setWhen(arbitration.isValid) clearWhen(arbitration.isRemoved || !arbitration.isStuck) + insert(ASSERT_ERROR) := arbitration.isValid || reg + } //Unpack decodedBits and insert fields in the pipeline offset = 0 @@ -162,6 +176,10 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false, forceLegalI decodeExceptionPort.code := 2 decodeExceptionPort.badAddr := input(INSTRUCTION).asUInt } + if(assertIllegalInstruction){ + pipeline.stages.tail.foreach(s => s.output(ASSERT_ERROR) clearWhen(s.arbitration.isRemoved)) + assert(!pipeline.stages.last.output(ASSERT_ERROR)) + } } def bench(toplevel : VexRiscv): Unit ={ @@ -176,7 +194,7 @@ class DecoderSimplePlugin(catchIllegalInstruction : Boolean = false, forceLegalI val stageables = encodings.flatMap(_._2.map(_._1)).toSet stageables.foreach(e => out(RegNext(RegNext(toplevel.decode.insert(e)).setName(e.getName())))) if(catchIllegalInstruction) out(RegNext(RegNext(toplevel.decode.insert(LEGAL_INSTRUCTION)).setName(LEGAL_INSTRUCTION.getName()))) - // toplevel.getAdditionalNodesRoot.clear() + // toplevel.getAdditionalNodesRoot.clear() } } } @@ -345,14 +363,14 @@ object SymplifyBit{ def main(args: Array[String]) { { -// val default = Masked(0, 0xF) -// val primeImplicants = List(4, 8, 10, 11, 12, 15).map(v => Masked(v, 0xF)) -// val dcImplicants = List(9, 14).map(v => Masked(v, 0xF).setPrime(false)) -// val reducedPrimeImplicants = getPrimeImplicantsByTrueAndDontCare(primeImplicants, dcImplicants, 4) -// println("UUT") -// println(reducedPrimeImplicants.map(_.toString(4)).mkString("\n")) -// println("REF") -// println("-100\n10--\n1--0\n1-1-") + // val default = Masked(0, 0xF) + // val primeImplicants = List(4, 8, 10, 11, 12, 15).map(v => Masked(v, 0xF)) + // val dcImplicants = List(9, 14).map(v => Masked(v, 0xF).setPrime(false)) + // val reducedPrimeImplicants = getPrimeImplicantsByTrueAndDontCare(primeImplicants, dcImplicants, 4) + // println("UUT") + // println(reducedPrimeImplicants.map(_.toString(4)).mkString("\n")) + // println("REF") + // println("-100\n10--\n1--0\n1-1-") } { diff --git a/src/main/scala/vexriscv/plugin/Fetcher.scala b/src/main/scala/vexriscv/plugin/Fetcher.scala index 5b9c3ac..5df80e7 100644 --- a/src/main/scala/vexriscv/plugin/Fetcher.scala +++ b/src/main/scala/vexriscv/plugin/Fetcher.scala @@ -596,6 +596,7 @@ abstract class IBusFetcherImpl(val resetVector : BigInt, historyWrite.data.branchWish := 0 decode.arbitration.isValid := False + decode.arbitration.flushNext := True dynamicTargetFailureCorrection.valid := True } }) diff --git a/src/test/scala/vexriscv/TestIndividualFeatures.scala b/src/test/scala/vexriscv/TestIndividualFeatures.scala index e397a67..1c741ad 100644 --- a/src/test/scala/vexriscv/TestIndividualFeatures.scala +++ b/src/test/scala/vexriscv/TestIndividualFeatures.scala @@ -514,7 +514,8 @@ class DecoderDimension extends VexRiscvDimension("Decoder") { val catchAll = universes.contains(VexRiscvUniverse.CATCH_ALL) new VexRiscvPosition("") { override def applyOn(config: VexRiscvConfig): Unit = config.plugins += new DecoderSimplePlugin( - catchIllegalInstruction = catchAll + catchIllegalInstruction = catchAll, + throwIllegalInstruction = false ) // override def isCompatibleWith(positions: Seq[ConfigPosition[VexRiscvConfig]]) = catchAll == positions.exists(_.isInstanceOf[CatchAllPosition]) @@ -587,6 +588,7 @@ class TestIndividualFeatures extends FunSuite { test(prefix + name + "_test") { + println("START TEST " + prefix + name) val debug = true val stdCmd = (s"make clean run WITH_USER_IO=no REDO=10 TRACE=${if(debug) "yes" else "no"} TRACE_START=9999924910246l STOP_ON_ERROR=no FLOW_INFO=no STOP_ON_ERROR=no DHRYSTONE=yes COREMARK=${sys.env.getOrElse("VEXRISCV_REGRESSION_COREMARK", "yes")} THREAD_COUNT=${sys.env.getOrElse("VEXRISCV_REGRESSION_THREAD_COUNT", 1)} ") + s" SEED=${testSeed} " val testCmd = stdCmd + (positionsToApply).map(_.testParam).mkString(" ")