MulPlugin fix buffer interraction with partial regfile bypass
This commit is contained in:
parent
8b2a2afb6f
commit
06b7a91de4
|
@ -31,29 +31,62 @@ class HazardSimplePlugin(bypassExecute : Boolean = false,
|
||||||
override def build(pipeline: VexRiscv): Unit = {
|
override def build(pipeline: VexRiscv): Unit = {
|
||||||
import pipeline._
|
import pipeline._
|
||||||
import pipeline.config._
|
import pipeline.config._
|
||||||
val src0Hazard = False
|
|
||||||
val src1Hazard = False
|
|
||||||
|
|
||||||
val readStage = service(classOf[RegFileService]).readStage()
|
pipeline plug new Area {
|
||||||
|
val src0Hazard = False
|
||||||
|
val src1Hazard = False
|
||||||
|
|
||||||
def trackHazardWithStage(stage : Stage,bypassable : Boolean, runtimeBypassable : Stageable[Bool]): Unit ={
|
val readStage = service(classOf[RegFileService]).readStage()
|
||||||
val runtimeBypassableValue = if(runtimeBypassable != null) stage.input(runtimeBypassable) else True
|
|
||||||
val addr0Match = if(pessimisticAddressMatch) True else stage.input(INSTRUCTION)(rdRange) === readStage.input(INSTRUCTION)(rs1Range)
|
def trackHazardWithStage(stage: Stage, bypassable: Boolean, runtimeBypassable: Stageable[Bool]): Unit = {
|
||||||
val addr1Match = if(pessimisticAddressMatch) True else stage.input(INSTRUCTION)(rdRange) === readStage.input(INSTRUCTION)(rs2Range)
|
val runtimeBypassableValue = if (runtimeBypassable != null) stage.input(runtimeBypassable) else True
|
||||||
when(stage.arbitration.isValid && stage.input(REGFILE_WRITE_VALID)) {
|
val addr0Match = if (pessimisticAddressMatch) True else stage.input(INSTRUCTION)(rdRange) === readStage.input(INSTRUCTION)(rs1Range)
|
||||||
if (bypassable) {
|
val addr1Match = if (pessimisticAddressMatch) True else stage.input(INSTRUCTION)(rdRange) === readStage.input(INSTRUCTION)(rs2Range)
|
||||||
when(runtimeBypassableValue) {
|
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) {
|
when(addr0Match) {
|
||||||
readStage.input(RS1) := stage.output(REGFILE_WRITE_DATA)
|
src0Hazard := True
|
||||||
}
|
}
|
||||||
when(addr1Match) {
|
when(addr1Match) {
|
||||||
readStage.input(RS2) := stage.output(REGFILE_WRITE_DATA)
|
src1Hazard := True
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
when(stage.arbitration.isValid && (if(pessimisticWriteRegFile) True else stage.input(REGFILE_WRITE_VALID))) {
|
|
||||||
when((Bool(!bypassable) || !runtimeBypassableValue)) {
|
|
||||||
|
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) {
|
when(addr0Match) {
|
||||||
src0Hazard := True
|
src0Hazard := True
|
||||||
}
|
}
|
||||||
|
@ -62,54 +95,24 @@ class HazardSimplePlugin(bypassExecute : Boolean = false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
|
||||||
val writeBackWrites = Flow(cloneable(new Bundle{
|
if (!pessimisticUseSrc) {
|
||||||
val address = Bits(5 bits)
|
when(!readStage.input(RS1_USE)) {
|
||||||
val data = Bits(32 bits)
|
src0Hazard := False
|
||||||
}))
|
|
||||||
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) {
|
when(!readStage.input(RS2_USE)) {
|
||||||
readStage.input(RS2) := writeBackBuffer.data
|
src1Hazard := False
|
||||||
}
|
|
||||||
} else {
|
|
||||||
when(addr0Match) {
|
|
||||||
src0Hazard := True
|
|
||||||
}
|
|
||||||
when(addr1Match) {
|
|
||||||
src1Hazard := True
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if(withWriteBackStage) trackHazardWithStage(writeBack,bypassWriteBack,null)
|
when(readStage.arbitration.isValid && (src0Hazard || src1Hazard)) {
|
||||||
if(withMemoryStage) trackHazardWithStage(memory ,bypassMemory, if(stages.last == memory) null else BYPASSABLE_MEMORY_STAGE)
|
readStage.arbitration.haltByOther := True
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,10 +61,9 @@ class MulPlugin(var inputBuffer : Boolean = false,
|
||||||
when(arbitration.isValid && input(IS_MUL) && counter =/= delay){
|
when(arbitration.isValid && input(IS_MUL) && counter =/= delay){
|
||||||
arbitration.haltItself := True
|
arbitration.haltItself := True
|
||||||
}
|
}
|
||||||
when(!arbitration.isStuckByOthers){
|
|
||||||
counter := counter + 1
|
counter := counter + 1
|
||||||
}
|
when(!arbitration.isStuck || arbitration.isStuckByOthers){
|
||||||
when(!arbitration.isStuck){
|
|
||||||
counter := 0
|
counter := 0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue