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(
|
||||
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(
|
||||
|
|
|
@ -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,9 +26,11 @@ class MulDivIterativePlugin(mulUnroolFactor : Int = 1) extends Plugin[VexRiscv]{
|
|||
RS2_USE -> True
|
||||
)
|
||||
|
||||
val mulActions = commonActions ++ List(IS_MUL -> True)
|
||||
|
||||
val decoderService = pipeline.service(classOf[DecoderService])
|
||||
|
||||
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)),
|
||||
|
@ -34,24 +38,40 @@ class MulDivIterativePlugin(mulUnroolFactor : Int = 1) extends Plugin[VexRiscv]{
|
|||
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 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, rs2NeedRevert).resized
|
||||
|
||||
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))
|
Loading…
Reference in a new issue