VexRiscv/src/main/scala/SpinalRiscv/Plugin/ShiftPlugins.scala
Charles Papon efb27390a7 Better IntAluPlugin
Better SrcPlugin
Better DBusCachedPlugin
2017-04-06 01:28:52 +02:00

171 lines
No EOL
5.6 KiB
Scala

package SpinalRiscv.Plugin
import SpinalRiscv._
import spinal.core._
import spinal.lib.Reverse
class FullBarrielShifterPlugin extends Plugin[VexRiscv]{
object ShiftCtrlEnum extends SpinalEnum(binarySequential){
val DISABLE, SLL, SRL, SRA = newElement()
}
object SHIFT_CTRL extends Stageable(ShiftCtrlEnum())
object SHIFT_RIGHT extends Stageable(Bits(32 bits))
override def setup(pipeline: VexRiscv): Unit = {
import Riscv._
import pipeline.config._
val immediateActions = List[(Stageable[_ <: BaseType],Any)](
SRC1_CTRL -> Src1CtrlEnum.RS,
SRC2_CTRL -> Src2CtrlEnum.IMI,
REGFILE_WRITE_VALID -> True,
BYPASSABLE_EXECUTE_STAGE -> False,
BYPASSABLE_MEMORY_STAGE -> True,
REG1_USE -> True
)
val nonImmediateActions = List[(Stageable[_ <: BaseType],Any)](
SRC1_CTRL -> Src1CtrlEnum.RS,
SRC2_CTRL -> Src2CtrlEnum.RS,
REGFILE_WRITE_VALID -> True,
BYPASSABLE_EXECUTE_STAGE -> False,
BYPASSABLE_MEMORY_STAGE -> True,
REG1_USE -> True,
REG2_USE -> True
)
val decoderService = pipeline.service(classOf[DecoderService])
decoderService.addDefault(SHIFT_CTRL, ShiftCtrlEnum.DISABLE)
decoderService.add(List(
SLL -> (nonImmediateActions ++ List(SHIFT_CTRL -> ShiftCtrlEnum.SLL)),
SRL -> (nonImmediateActions ++ List(SHIFT_CTRL -> ShiftCtrlEnum.SRL)),
SRA -> (nonImmediateActions ++ List(SHIFT_CTRL -> ShiftCtrlEnum.SRA))
))
decoderService.add(List(
SLLI -> (immediateActions ++ List(SHIFT_CTRL -> ShiftCtrlEnum.SLL)),
SRLI -> (immediateActions ++ List(SHIFT_CTRL -> ShiftCtrlEnum.SRL)),
SRAI -> (immediateActions ++ List(SHIFT_CTRL -> ShiftCtrlEnum.SRA))
))
}
override def build(pipeline: VexRiscv): Unit = {
import pipeline._
import pipeline.config._
execute plug new Area{
import execute._
val amplitude = input(SRC2)(4 downto 0).asUInt
val reversed = Mux(input(SHIFT_CTRL) === ShiftCtrlEnum.SLL, Reverse(input(SRC1)), input(SRC1))
insert(SHIFT_RIGHT) := (Cat(input(SHIFT_CTRL) === ShiftCtrlEnum.SRA & reversed.msb, reversed).asSInt >> amplitude)(31 downto 0).asBits
}
memory plug new Area{
import memory._
switch(input(SHIFT_CTRL)){
is(ShiftCtrlEnum.SLL){
output(REGFILE_WRITE_DATA) := Reverse(input(SHIFT_RIGHT))
}
is(ShiftCtrlEnum.SRL,ShiftCtrlEnum.SRA){
output(REGFILE_WRITE_DATA) := input(SHIFT_RIGHT)
}
}
}
}
}
class LightShifterPlugin extends Plugin[VexRiscv]{
object ShiftCtrlEnum extends SpinalEnum(binarySequential){
val DISABLE, SLL, SRL, SRA = newElement()
}
object SHIFT_CTRL extends Stageable(ShiftCtrlEnum())
override def setup(pipeline: VexRiscv): Unit = {
import Riscv._
import pipeline.config._
import IntAluPlugin._
val immediateActions = List[(Stageable[_ <: BaseType],Any)](
SRC1_CTRL -> Src1CtrlEnum.RS,
SRC2_CTRL -> Src2CtrlEnum.IMI,
ALU_CTRL -> AluCtrlEnum.BITWISE,
ALU_BITWISE_CTRL -> AluBitwiseCtrlEnum.SRC1,
REGFILE_WRITE_VALID -> True,
BYPASSABLE_EXECUTE_STAGE -> True,
BYPASSABLE_MEMORY_STAGE -> True,
REG1_USE -> True
)
val nonImmediateActions = List[(Stageable[_ <: BaseType],Any)](
SRC1_CTRL -> Src1CtrlEnum.RS,
SRC2_CTRL -> Src2CtrlEnum.RS,
ALU_CTRL -> AluCtrlEnum.BITWISE,
ALU_BITWISE_CTRL -> AluBitwiseCtrlEnum.SRC1,
REGFILE_WRITE_VALID -> True,
BYPASSABLE_EXECUTE_STAGE -> True,
BYPASSABLE_MEMORY_STAGE -> True,
REG1_USE -> True,
REG2_USE -> True
)
val decoderService = pipeline.service(classOf[DecoderService])
decoderService.addDefault(SHIFT_CTRL, ShiftCtrlEnum.DISABLE)
decoderService.add(List(
SLL -> (nonImmediateActions ++ List(SHIFT_CTRL -> ShiftCtrlEnum.SLL)),
SRL -> (nonImmediateActions ++ List(SHIFT_CTRL -> ShiftCtrlEnum.SRL)),
SRA -> (nonImmediateActions ++ List(SHIFT_CTRL -> ShiftCtrlEnum.SRA))
))
decoderService.add(List(
SLLI -> (immediateActions ++ List(SHIFT_CTRL -> ShiftCtrlEnum.SLL)),
SRLI -> (immediateActions ++ List(SHIFT_CTRL -> ShiftCtrlEnum.SRL)),
SRAI -> (immediateActions ++ List(SHIFT_CTRL -> ShiftCtrlEnum.SRA))
))
}
override def build(pipeline: VexRiscv): Unit = {
import pipeline._
import pipeline.config._
execute plug new Area{
import execute._
val isActive = RegInit(False)
val isShift = input(SHIFT_CTRL) =/= ShiftCtrlEnum.DISABLE
val amplitudeReg = Reg(UInt(5 bits))
val amplitude = isActive ? amplitudeReg | input(SRC2)(4 downto 0).asUInt
val shiftInput = isActive ? memory.input(REGFILE_WRITE_DATA) | input(SRC1)
val done = amplitude(4 downto 1) === 0
when(arbitration.isValid && isShift && input(SRC2)(4 downto 0) =/= 0){
output(REGFILE_WRITE_DATA) := input(SHIFT_CTRL).mux(
ShiftCtrlEnum.SLL -> (shiftInput |<< 1),
default -> (((input(SHIFT_CTRL) === ShiftCtrlEnum.SRA && shiftInput.msb) ## shiftInput).asSInt >> 1).asBits //ALU.SRL,ALU.SRA
)
when(!arbitration.isStuckByOthers){
isActive := True
amplitudeReg := amplitude - 1
when(done){
isActive := False
} otherwise{
arbitration.haltIt := True
}
}
}
when(arbitration.removeIt){
isActive := False
}
}
}
}