diff options
Diffstat (limited to 'VexRiscv/src/main/scala/vexriscv/plugin/HazardSimplePlugin.scala')
-rw-r--r-- | VexRiscv/src/main/scala/vexriscv/plugin/HazardSimplePlugin.scala | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/VexRiscv/src/main/scala/vexriscv/plugin/HazardSimplePlugin.scala b/VexRiscv/src/main/scala/vexriscv/plugin/HazardSimplePlugin.scala new file mode 100644 index 0000000..1b650e3 --- /dev/null +++ b/VexRiscv/src/main/scala/vexriscv/plugin/HazardSimplePlugin.scala @@ -0,0 +1,125 @@ +package vexriscv.plugin + +import vexriscv._ +import spinal.core._ +import spinal.lib._ + +trait HazardService{ + def hazardOnExecuteRS : Bool +} + +class HazardSimplePlugin(bypassExecute : Boolean = false, + bypassMemory: Boolean = false, + bypassWriteBack: Boolean = false, + bypassWriteBackBuffer : Boolean = false, + pessimisticUseSrc : Boolean = false, + pessimisticWriteRegFile : Boolean = false, + pessimisticAddressMatch : Boolean = false) extends Plugin[VexRiscv] with HazardService{ + import Riscv._ + + + def hazardOnExecuteRS = { + if(pipeline.service(classOf[RegFileService]).readStage() == pipeline.execute) pipeline.execute.arbitration.isStuckByOthers else False //TODO not so nice + } + + override def setup(pipeline: VexRiscv): Unit = { + import pipeline.config._ + val decoderService = pipeline.service(classOf[DecoderService]) + decoderService.addDefault(HAS_SIDE_EFFECT, False) //TODO implement it in each plugin + } + + override def build(pipeline: VexRiscv): Unit = { + import pipeline._ + import pipeline.config._ + + pipeline plug new Area { + val src0Hazard = False + val src1Hazard = False + + val readStage = service(classOf[RegFileService]).readStage() + + def trackHazardWithStage(stage: Stage, bypassable: Boolean, runtimeBypassable: Stageable[Bool]): Unit = { + val runtimeBypassableValue = if (runtimeBypassable != null) stage.input(runtimeBypassable) else True + val addr0Match = if (pessimisticAddressMatch) True else stage.input(INSTRUCTION)(rdRange) === readStage.input(INSTRUCTION)(rs1Range) + val addr1Match = if (pessimisticAddressMatch) True else stage.input(INSTRUCTION)(rdRange) === readStage.input(INSTRUCTION)(rs2Range) + when(stage.arbitration.isValid && stage.input(REGFILE_WRITE_VALID)) { + if (bypassable) { + when(runtimeBypassableValue) { + when(addr0Match) { + readStage.input(RS1) := stage.output(REGFILE_WRITE_DATA) + } + when(addr1Match) { + readStage.input(RS2) := stage.output(REGFILE_WRITE_DATA) + } + } + } + } + when(stage.arbitration.isValid && (if (pessimisticWriteRegFile) True else stage.input(REGFILE_WRITE_VALID))) { + when((Bool(!bypassable) || !runtimeBypassableValue)) { + when(addr0Match) { + src0Hazard := True + } + when(addr1Match) { + src1Hazard := True + } + } + } + } + + + val writeBackWrites = Flow(cloneable(new Bundle { + val address = Bits(5 bits) + val data = Bits(32 bits) + })) + writeBackWrites.valid := stages.last.output(REGFILE_WRITE_VALID) && stages.last.arbitration.isFiring + writeBackWrites.address := stages.last.output(INSTRUCTION)(rdRange) + writeBackWrites.data := stages.last.output(REGFILE_WRITE_DATA) + val writeBackBuffer = writeBackWrites.stage() + + val addr0Match = if (pessimisticAddressMatch) True else writeBackBuffer.address === readStage.input(INSTRUCTION)(rs1Range) + val addr1Match = if (pessimisticAddressMatch) True else writeBackBuffer.address === readStage.input(INSTRUCTION)(rs2Range) + when(writeBackBuffer.valid) { + if (bypassWriteBackBuffer) { + when(addr0Match) { + readStage.input(RS1) := writeBackBuffer.data + } + when(addr1Match) { + readStage.input(RS2) := writeBackBuffer.data + } + } else { + when(addr0Match) { + src0Hazard := True + } + when(addr1Match) { + src1Hazard := True + } + } + } + + if (withWriteBackStage) trackHazardWithStage(writeBack, bypassWriteBack, null) + if (withMemoryStage) trackHazardWithStage(memory, bypassMemory, if (stages.last == memory) null else BYPASSABLE_MEMORY_STAGE) + if (readStage != execute) trackHazardWithStage(execute, bypassExecute, if (stages.last == execute) null else BYPASSABLE_EXECUTE_STAGE) + + + if (!pessimisticUseSrc) { + when(!readStage.input(RS1_USE)) { + src0Hazard := False + } + when(!readStage.input(RS2_USE)) { + src1Hazard := False + } + } + + when(readStage.arbitration.isValid && (src0Hazard || src1Hazard)) { + readStage.arbitration.haltByOther := True + } + } + } +} + + +class NoHazardPlugin extends Plugin[VexRiscv] with HazardService { + override def build(pipeline: VexRiscv): Unit = {} + + def hazardOnExecuteRS = False +}
\ No newline at end of file |