1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
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
}
|