Add division support in the MulDivInterativePlugin

This commit is contained in:
Dolu1990 2018-03-09 22:41:47 +01:00
parent 36438bd306
commit e437a1d44e
2 changed files with 96 additions and 24 deletions

View file

@ -41,7 +41,7 @@ object TestsWorkspace {
// ), // ),
new IBusCachedPlugin( new IBusCachedPlugin(
config = InstructionCacheConfig( config = InstructionCacheConfig(
cacheSize = 2048, cacheSize = 1024*16,
bytePerLine = 32, bytePerLine = 32,
wayCount = 1, wayCount = 1,
addressWidth = 32, addressWidth = 32,
@ -113,8 +113,14 @@ object TestsWorkspace {
), ),
// new HazardSimplePlugin(false, true, false, true), // new HazardSimplePlugin(false, true, false, true),
// new HazardSimplePlugin(false, false, false, false), // new HazardSimplePlugin(false, false, false, false),
new MulPlugin, // new MulPlugin,
new DivPlugin, new MulDivIterativePlugin(
genMul = true,
genDiv = true,
mulUnroolFactor = 32,
divUnroolFactor = 1
),
// new DivPlugin,
new CsrPlugin(CsrPluginConfig.all(0x80000020l).copy(deterministicInteruptionEntry = false)), new CsrPlugin(CsrPluginConfig.all(0x80000020l).copy(deterministicInteruptionEntry = false)),
new DebugPlugin(ClockDomain.current.clone(reset = Bool().setName("debugReset"))), new DebugPlugin(ClockDomain.current.clone(reset = Bool().setName("debugReset"))),
new BranchPlugin( new BranchPlugin(

View file

@ -4,8 +4,10 @@ import spinal.core._
import spinal.lib._ import spinal.lib._
import vexriscv.{VexRiscv, _} 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_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_RS1_SIGNED extends Stageable(Bool)
object IS_RS2_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 RS2_USE -> True
) )
val mulActions = commonActions ++ List(IS_MUL -> True)
val decoderService = pipeline.service(classOf[DecoderService]) val decoderService = pipeline.service(classOf[DecoderService])
decoderService.addDefault(IS_MUL, False)
decoderService.add(List( if(genMul) {
MUL -> (mulActions ++ List(IS_RS1_SIGNED -> False, IS_RS2_SIGNED -> False)), val mulActions = commonActions ++ List(IS_MUL -> True)
MULH -> (mulActions ++ List(IS_RS1_SIGNED -> True, IS_RS2_SIGNED -> True)), decoderService.addDefault(IS_MUL, False)
MULHSU -> (mulActions ++ List(IS_RS1_SIGNED -> True, IS_RS2_SIGNED -> False)), decoderService.add(List(
MULHU -> (mulActions ++ List(IS_RS1_SIGNED -> False, IS_RS2_SIGNED -> False)) 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 = { override def build(pipeline: VexRiscv): Unit = {
import pipeline._ import pipeline._
import pipeline.config._ import pipeline.config._
if(!genMul && !genDiv) return
memory plug new Area { memory plug new Area {
import memory._ import memory._
//Shared ressources
val rs1 = Reg(UInt(33 bits)) val rs1 = Reg(UInt(33 bits))
val rs2 = Reg(UInt(32 bits)) val rs2 = Reg(UInt(32 bits))
val accumulator = Reg(UInt(65 bits)) val accumulator = Reg(UInt(65 bits))
val mul = new Area{
val mul = ifGen(genMul) (new Area{
assert(isPow2(mulUnroolFactor)) assert(isPow2(mulUnroolFactor))
val counter = Counter(32 / mulUnroolFactor + 1) val counter = Counter(32 / mulUnroolFactor + 1)
val done = counter.willOverflowIfInc val done = counter.willOverflowIfInc
when(input(IS_MUL)){ when(arbitration.isValid && input(IS_MUL)){
when(!done){ when(!done){
arbitration.haltItself := True arbitration.haltItself := True
counter.increment() 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 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){ when(!arbitration.isStuck){
accumulator := 0 accumulator := 0
def twoComplement(that : Bits, enable: Bool): UInt = (Mux(enable, ~that, that).asUInt + enable.asUInt) 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 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)) val rs1NeedRevert = (if(genMul)(execute.input(IS_MUL) && rs2NeedRevert) else False) ||
rs1 := twoComplement(rs1Extended, rs2NeedRevert).resized (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) 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))