diff options
Diffstat (limited to 'VexRiscv/src/main/scala/vexriscv/plugin/SrcPlugin.scala')
-rw-r--r-- | VexRiscv/src/main/scala/vexriscv/plugin/SrcPlugin.scala | 83 |
1 files changed, 83 insertions, 0 deletions
diff --git a/VexRiscv/src/main/scala/vexriscv/plugin/SrcPlugin.scala b/VexRiscv/src/main/scala/vexriscv/plugin/SrcPlugin.scala new file mode 100644 index 0000000..d67e7cc --- /dev/null +++ b/VexRiscv/src/main/scala/vexriscv/plugin/SrcPlugin.scala @@ -0,0 +1,83 @@ +package vexriscv.plugin + +import vexriscv._ +import spinal.core._ +import spinal.lib.KeepAttribute + + +class SrcPlugin(separatedAddSub : Boolean = false, executeInsertion : Boolean = false, decodeAddSub : Boolean = false) extends Plugin[VexRiscv]{ + object SRC2_FORCE_ZERO extends Stageable(Bool) + + + override def setup(pipeline: VexRiscv): Unit = { + import pipeline.config._ + + val decoderService = pipeline.service(classOf[DecoderService]) + decoderService.addDefault(SRC_ADD_ZERO, False) //TODO avoid this default to simplify decoding ? + } + + override def build(pipeline: VexRiscv): Unit = { + import pipeline._ + import pipeline.config._ + + decode.insert(SRC2_FORCE_ZERO) := decode.input(SRC_ADD_ZERO) && !decode.input(SRC_USE_SUB_LESS) + + val insertionStage = if(executeInsertion) execute else decode + insertionStage plug new Area{ + import insertionStage._ + + val imm = Riscv.IMM(input(INSTRUCTION)) + insert(SRC1) := input(SRC1_CTRL).mux( + Src1CtrlEnum.RS -> output(RS1), + Src1CtrlEnum.PC_INCREMENT -> (if(pipeline.config.withRvc) Mux(input(IS_RVC), B(2), B(4)) else B(4)).resized, + Src1CtrlEnum.IMU -> imm.u.resized, + Src1CtrlEnum.URS1 -> input(INSTRUCTION)(Riscv.rs1Range).resized + ) + insert(SRC2) := input(SRC2_CTRL).mux( + Src2CtrlEnum.RS -> output(RS2), + Src2CtrlEnum.IMI -> imm.i_sext.resized, + Src2CtrlEnum.IMS -> imm.s_sext.resized, + Src2CtrlEnum.PC -> output(PC).asBits + ) + } + + val addSubStage = if(decodeAddSub) decode else execute + if(separatedAddSub) { + addSubStage plug new Area { + import addSubStage._ + + // ADD, SUB + val add = (U(input(SRC1)) + U(input(SRC2))).asBits.addAttribute("keep") + val sub = (U(input(SRC1)) - U(input(SRC2))).asBits.addAttribute("keep") + when(input(SRC_ADD_ZERO)){ add := input(SRC1) } + + // SLT, SLTU + val less = Mux(input(SRC1).msb === input(SRC2).msb, sub.msb, + Mux(input(SRC_LESS_UNSIGNED), input(SRC2).msb, input(SRC1).msb)) + + insert(SRC_ADD_SUB) := input(SRC_USE_SUB_LESS) ? sub | add + insert(SRC_ADD) := add + insert(SRC_SUB) := sub + insert(SRC_LESS) := less + } + }else{ + addSubStage plug new Area { + import addSubStage._ + + // ADD, SUB + val addSub = (input(SRC1).asSInt + Mux(input(SRC_USE_SUB_LESS), ~input(SRC2), input(SRC2)).asSInt + Mux(input(SRC_USE_SUB_LESS), S(1, 32 bits), S(0, 32 bits))).asBits + when(input(SRC2_FORCE_ZERO)){ addSub := input(SRC1) } + + + // SLT, SLTU + val less = Mux(input(SRC1).msb === input(SRC2).msb, addSub.msb, + Mux(input(SRC_LESS_UNSIGNED), input(SRC2).msb, input(SRC1).msb)) + + insert(SRC_ADD_SUB) := addSub + insert(SRC_ADD) := addSub + insert(SRC_SUB) := addSub + insert(SRC_LESS) := less + } + } + } +} |