diff --git a/src/main/scala/vexriscv/TestsWorkspace.scala b/src/main/scala/vexriscv/TestsWorkspace.scala index 425173a..638af86 100644 --- a/src/main/scala/vexriscv/TestsWorkspace.scala +++ b/src/main/scala/vexriscv/TestsWorkspace.scala @@ -41,7 +41,7 @@ object TestsWorkspace { // ), new IBusCachedPlugin( config = InstructionCacheConfig( - cacheSize = 2048, + cacheSize = 1024*16, bytePerLine = 32, wayCount = 1, addressWidth = 32, @@ -113,8 +113,14 @@ object TestsWorkspace { ), // new HazardSimplePlugin(false, true, false, true), // new HazardSimplePlugin(false, false, false, false), - new MulPlugin, - new DivPlugin, +// new MulPlugin, + new MulDivIterativePlugin( + genMul = true, + genDiv = true, + mulUnroolFactor = 32, + divUnroolFactor = 1 + ), +// new DivPlugin, new CsrPlugin(CsrPluginConfig.all(0x80000020l).copy(deterministicInteruptionEntry = false)), new DebugPlugin(ClockDomain.current.clone(reset = Bool().setName("debugReset"))), new BranchPlugin( diff --git a/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala b/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala index 0c82518..2bf0bf2 100644 --- a/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala +++ b/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala @@ -4,8 +4,10 @@ import spinal.core._ import spinal.lib._ import vexriscv.{VexRiscv, _} -class MulDivIterativePlugin(mulUnroolFactor : Int = 1) extends Plugin[VexRiscv]{ +class MulDivIterativePlugin(genMul : Boolean, genDiv : Boolean, mulUnroolFactor : Int, divUnroolFactor : Int) extends Plugin[VexRiscv]{ object IS_MUL extends Stageable(Bool) + object IS_DIV extends Stageable(Bool) + object IS_REM extends Stageable(Bool) object IS_RS1_SIGNED extends Stageable(Bool) object IS_RS2_SIGNED extends Stageable(Bool) @@ -24,34 +26,52 @@ class MulDivIterativePlugin(mulUnroolFactor : Int = 1) extends Plugin[VexRiscv]{ RS2_USE -> True ) - val mulActions = commonActions ++ List(IS_MUL -> True) val decoderService = pipeline.service(classOf[DecoderService]) - decoderService.addDefault(IS_MUL, False) - decoderService.add(List( - MUL -> (mulActions ++ List(IS_RS1_SIGNED -> False, IS_RS2_SIGNED -> False)), - MULH -> (mulActions ++ List(IS_RS1_SIGNED -> True, IS_RS2_SIGNED -> True)), - MULHSU -> (mulActions ++ List(IS_RS1_SIGNED -> True, IS_RS2_SIGNED -> False)), - MULHU -> (mulActions ++ List(IS_RS1_SIGNED -> False, IS_RS2_SIGNED -> False)) - )) + + if(genMul) { + val mulActions = commonActions ++ List(IS_MUL -> True) + decoderService.addDefault(IS_MUL, False) + decoderService.add(List( + MUL -> (mulActions ++ List(IS_RS1_SIGNED -> False, IS_RS2_SIGNED -> False)), + MULH -> (mulActions ++ List(IS_RS1_SIGNED -> True, IS_RS2_SIGNED -> True)), + MULHSU -> (mulActions ++ List(IS_RS1_SIGNED -> True, IS_RS2_SIGNED -> False)), + MULHU -> (mulActions ++ List(IS_RS1_SIGNED -> False, IS_RS2_SIGNED -> False)) + )) + } + + if(genDiv) { + val divActions = commonActions ++ List(IS_DIV -> True) + decoderService.addDefault(IS_DIV, False) + decoderService.add(List( + DIV -> (divActions ++ List(IS_RS1_SIGNED -> True, IS_RS2_SIGNED -> True)), + DIVU -> (divActions ++ List(IS_RS1_SIGNED -> False, IS_RS2_SIGNED -> False)), + REM -> (divActions ++ List(IS_RS1_SIGNED -> True, IS_RS2_SIGNED -> True)), + REMU -> (divActions ++ List(IS_RS1_SIGNED -> False, IS_RS2_SIGNED -> False)) + )) + } } override def build(pipeline: VexRiscv): Unit = { import pipeline._ import pipeline.config._ - + if(!genMul && !genDiv) return memory plug new Area { import memory._ + + //Shared ressources val rs1 = Reg(UInt(33 bits)) val rs2 = Reg(UInt(32 bits)) val accumulator = Reg(UInt(65 bits)) - val mul = new Area{ + + + val mul = ifGen(genMul) (new Area{ assert(isPow2(mulUnroolFactor)) val counter = Counter(32 / mulUnroolFactor + 1) val done = counter.willOverflowIfInc - when(input(IS_MUL)){ + when(arbitration.isValid && input(IS_MUL)){ when(!done){ arbitration.haltItself := True counter.increment() @@ -62,21 +82,67 @@ class MulDivIterativePlugin(mulUnroolFactor : Int = 1) extends Plugin[VexRiscv]{ } output(REGFILE_WRITE_DATA) := ((input(INSTRUCTION)(13 downto 12) === B"00") ? accumulator(31 downto 0) | accumulator(63 downto 32)).asBits } - } + }) + + val div = ifGen(genDiv) (new Area{ + assert(isPow2(divUnroolFactor)) + + //register allocation + def numerator = rs1(31 downto 0) + def denominator = rs2 + def remainder = accumulator(31 downto 0) + + val needRevert = Reg(Bool) + val counter = Counter(32 / divUnroolFactor + 2) + val done = counter.willOverflowIfInc + val result = Reg(Bits(32 bits)) + when(arbitration.isValid && input(IS_DIV)){ + when(!done){ + arbitration.haltItself := True + counter.increment() + + def stages(inNumerator: UInt, inRemainder: UInt, stage: Int): Unit = stage match { + case 0 => { + numerator := inNumerator + remainder := inRemainder + } + case _ => { + val remainderShifted = (inRemainder ## inNumerator.msb).asUInt + val remainderMinusDenominator = remainderShifted - denominator + val outRemainder = !remainderMinusDenominator.msb ? remainderMinusDenominator.resize(32 bits) | remainderShifted.resize(32 bits) + val outNumerator = (inNumerator ## !remainderMinusDenominator.msb).asUInt.resize(32 bits) + stages(outNumerator, outRemainder, stage - 1) + } + } + + stages(numerator, remainder, divUnroolFactor) + + when(counter === 32 / divUnroolFactor){ + val selectedResult = (input(INSTRUCTION)(13) ? remainder | numerator) + result := selectedResult.twoComplement(needRevert).asBits.resized + } + } + + output(REGFILE_WRITE_DATA) := result + } + }) + + //Execute stage logic to drive memory stage's input regs when(!arbitration.isStuck){ accumulator := 0 def twoComplement(that : Bits, enable: Bool): UInt = (Mux(enable, ~that, that).asUInt + enable.asUInt) val rs2NeedRevert = execute.input(RS2).msb && execute.input(IS_RS2_SIGNED) - val rs1Extended = B((32 downto 32) -> (execute.input(IS_RS1_SIGNED) && execute.input(RS1).msb), (31 downto 0) -> execute.input(RS1)) - rs1 := twoComplement(rs1Extended, rs2NeedRevert).resized + val rs1NeedRevert = (if(genMul)(execute.input(IS_MUL) && rs2NeedRevert) else False) || + (if(genDiv)(execute.input(IS_DIV) && execute.input(RS1).msb && execute.input(IS_RS1_SIGNED)) else False) + val rs1Extended = B((32 downto 32) -> (execute.input(IS_RS1_SIGNED) && execute.input(RS1).msb), (31 downto 0) -> execute.input(RS1)) + + rs1 := twoComplement(rs1Extended, rs1NeedRevert).resized rs2 := twoComplement(execute.input(RS2), rs2NeedRevert) - mul.counter.clear() + if(genMul) mul.counter.clear() + if(genDiv) div.needRevert := rs1NeedRevert ^ (rs2NeedRevert && !execute.input(INSTRUCTION)(13)) + if(genDiv) div.counter.clear() } } } -} - - - -// val mulEnables = rs2.subdivideIn(mulUnroolFactor bits)(counter(log2Up(32/mulUnroolFactor)-1 downto 0)) \ No newline at end of file +} \ No newline at end of file