diff --git a/src/main/scala/vexriscv/Riscv.scala b/src/main/scala/vexriscv/Riscv.scala index d4eea05..6a82a36 100644 --- a/src/main/scala/vexriscv/Riscv.scala +++ b/src/main/scala/vexriscv/Riscv.scala @@ -76,6 +76,19 @@ object Riscv{ def MULX = M"0000001----------0-------0110011" def DIVX = M"0000001----------1-------0110011" + def MUL = M"0000001----------000-----0110011" + def MULH = M"0000001----------001-----0110011" + def MULHSU = M"0000001----------010-----0110011" + def MULHU = M"0000001----------011-----0110011" + + + def DIV = M"0000001----------100-----0110011" + def DIVU = M"0000001----------101-----0110011" + def REM = M"0000001----------110-----0110011" + def REMU = M"0000001----------111-----0110011" + + + def CSRRW = M"-----------------001-----1110011" def CSRRS = M"-----------------010-----1110011" def CSRRC = M"-----------------011-----1110011" diff --git a/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala b/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala new file mode 100644 index 0000000..2e7f8d7 --- /dev/null +++ b/src/main/scala/vexriscv/plugin/MulDivIterativePlugin.scala @@ -0,0 +1,71 @@ +package vexriscv.plugin + +import spinal.core._ +import spinal.lib._ +import vexriscv.{VexRiscv, _} + +class MulDivIterativePlugin(mulUnroolFactor : Int = 1) extends Plugin[VexRiscv]{ + object IS_MUL extends Stageable(Bool) + object IS_RS1_SIGNED extends Stageable(Bool) + object IS_RS2_SIGNED extends Stageable(Bool) + + override def setup(pipeline: VexRiscv): Unit = { + import Riscv._ + import pipeline.config._ + + + val commonActions = List[(Stageable[_ <: BaseType],Any)]( + SRC1_CTRL -> Src1CtrlEnum.RS, + SRC2_CTRL -> Src2CtrlEnum.RS, + REGFILE_WRITE_VALID -> True, + BYPASSABLE_EXECUTE_STAGE -> False, + BYPASSABLE_MEMORY_STAGE -> True, + RS1_USE -> True, + 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)) + )) + + } + + override def build(pipeline: VexRiscv): Unit = { + import pipeline._ + import pipeline.config._ + + + memory plug new Area { + import memory._ + val rs1 = Reg(UInt(64 bits)) + val rs2 = Reg(UInt(32 bits)) + val accumulator = Reg(UInt(64 bits)) + val mul = new Area{ + val done = rs2 === 0 + when(input(IS_MUL)){ + arbitration.haltItself setWhen(!done) + rs1 := rs1 |<< mulUnroolFactor + rs2 := rs2 |>> mulUnroolFactor + accumulator := ((0 until mulUnroolFactor).map(i => rs2(i) ? (rs1 |<< i) | U(0)) :+ accumulator).reduceBalancedTree(_ + _) + output(REGFILE_WRITE_DATA) := ((input(INSTRUCTION)(13 downto 12) === B"00") ? accumulator(31 downto 0) | accumulator(63 downto 32)).asBits + } + } + + 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((63 downto 32) -> (execute.input(IS_RS1_SIGNED) && execute.input(RS1).msb), (31 downto 0) -> execute.input(RS1)) + rs1 := twoComplement(rs1Extended, rs2NeedRevert) + rs2 := twoComplement(execute.input(RS2), rs2NeedRevert) + } + } + } +}