mirror of
https://github.com/SpinalHDL/VexRiscv.git
synced 2025-01-03 03:43:39 -05:00
Add division support in the MulDivInterativePlugin
This commit is contained in:
parent
36438bd306
commit
e437a1d44e
2 changed files with 96 additions and 24 deletions
|
@ -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(
|
||||||
|
|
|
@ -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,9 +26,11 @@ 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])
|
||||||
|
|
||||||
|
if(genMul) {
|
||||||
|
val mulActions = commonActions ++ List(IS_MUL -> True)
|
||||||
decoderService.addDefault(IS_MUL, False)
|
decoderService.addDefault(IS_MUL, False)
|
||||||
decoderService.add(List(
|
decoderService.add(List(
|
||||||
MUL -> (mulActions ++ List(IS_RS1_SIGNED -> False, IS_RS2_SIGNED -> False)),
|
MUL -> (mulActions ++ List(IS_RS1_SIGNED -> False, IS_RS2_SIGNED -> False)),
|
||||||
|
@ -34,24 +38,40 @@ class MulDivIterativePlugin(mulUnroolFactor : Int = 1) extends Plugin[VexRiscv]{
|
||||||
MULHSU -> (mulActions ++ List(IS_RS1_SIGNED -> True, IS_RS2_SIGNED -> False)),
|
MULHSU -> (mulActions ++ List(IS_RS1_SIGNED -> True, IS_RS2_SIGNED -> False)),
|
||||||
MULHU -> (mulActions ++ List(IS_RS1_SIGNED -> False, 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 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))
|
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
|
|
||||||
|
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))
|
|
Loading…
Reference in a new issue