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
|
package vexriscv.plugin
import vexriscv._
import spinal.core._
import spinal.lib._
import scala.collection.mutable
trait RegFileReadKind
object ASYNC extends RegFileReadKind
object SYNC extends RegFileReadKind
class RegFilePlugin(regFileReadyKind : RegFileReadKind,
zeroBoot : Boolean = false,
x0Init : Boolean = true,
writeRfInMemoryStage : Boolean = false,
readInExecute : Boolean = false,
syncUpdateOnStall : Boolean = true,
rv32e : Boolean = false,
withShadow : Boolean = false //shadow registers aren't transition hazard free
) extends Plugin[VexRiscv] with RegFileService{
import Riscv._
override def readStage(): Stage = if(readInExecute) pipeline.execute else pipeline.decode
override def setup(pipeline: VexRiscv): Unit = {
import pipeline.config._
val decoderService = pipeline.service(classOf[DecoderService])
decoderService.addDefault(RS1_USE,False)
decoderService.addDefault(RS2_USE,False)
decoderService.addDefault(REGFILE_WRITE_VALID,False)
}
override def build(pipeline: VexRiscv): Unit = {
import pipeline._
import pipeline.config._
val readStage = if(readInExecute) execute else decode
val writeStage = if(writeRfInMemoryStage) memory else stages.last
val numRegisters = if(rv32e) 16 else 32
def clipRange(that : Range) = if(rv32e) that.tail else that
val global = pipeline plug new Area{
val regFileSize = if(withShadow) numRegisters * 2 else numRegisters
val regFile = Mem(Bits(32 bits),regFileSize) addAttribute(Verilator.public)
if(zeroBoot) regFile.init(List.fill(regFileSize)(B(0, 32 bits)))
val shadow = ifGen(withShadow)(new Area{
val write, read, clear = RegInit(False)
read clearWhen(clear && !readStage.arbitration.isStuck)
write clearWhen(clear && !writeStage.arbitration.isStuck)
val csrService = pipeline.service(classOf[CsrInterface])
csrService.w(0x7C0,2 -> clear, 1 -> read, 0 -> write)
})
}
//Disable rd0 write in decoding stage
when(decode.input(INSTRUCTION)(rdRange) === 0) {
decode.input(REGFILE_WRITE_VALID) := False
}
if(rv32e) when(decode.input(INSTRUCTION)(rdRange.head)) {
decode.input(REGFILE_WRITE_VALID) := False
}
//Read register file
readStage plug new Area{
import readStage._
//read register file
val srcInstruction = regFileReadyKind match{
case `ASYNC` => input(INSTRUCTION)
case `SYNC` if !readInExecute => input(INSTRUCTION_ANTICIPATED)
case `SYNC` if readInExecute => if(syncUpdateOnStall) Mux(execute.arbitration.isStuck, execute.input(INSTRUCTION), decode.input(INSTRUCTION)) else decode.input(INSTRUCTION)
}
def shadowPrefix(that : Bits) = if(withShadow) global.shadow.read ## that else that
val regFileReadAddress1 = U(shadowPrefix(srcInstruction(clipRange(Riscv.rs1Range))))
val regFileReadAddress2 = U(shadowPrefix(srcInstruction(clipRange(Riscv.rs2Range))))
val (rs1Data,rs2Data) = regFileReadyKind match{
case `ASYNC` => (global.regFile.readAsync(regFileReadAddress1),global.regFile.readAsync(regFileReadAddress2))
case `SYNC` =>
val enable = if(!syncUpdateOnStall) !readStage.arbitration.isStuck else null
(global.regFile.readSync(regFileReadAddress1, enable),global.regFile.readSync(regFileReadAddress2, enable))
}
insert(RS1) := rs1Data
insert(RS2) := rs2Data
}
//Write register file
writeStage plug new Area {
import writeStage._
def shadowPrefix(that : Bits) = if(withShadow) global.shadow.write ## that else that
val regFileWrite = global.regFile.writePort.addAttribute(Verilator.public).setName("lastStageRegFileWrite")
regFileWrite.valid := output(REGFILE_WRITE_VALID) && arbitration.isFiring
regFileWrite.address := U(shadowPrefix(output(INSTRUCTION)(clipRange(rdRange))))
regFileWrite.data := output(REGFILE_WRITE_DATA)
//Ensure no boot glitches modify X0
if(!x0Init && zeroBoot) when(regFileWrite.address === 0){
regFileWrite.valid := False
}
//CPU will initialise constant register zero in the first cycle
if(x0Init) {
val boot = RegNext(False) init (True)
regFileWrite.valid setWhen (boot)
when(boot) {
regFileWrite.address := 0
regFileWrite.data := 0
}
}
}
}
}
|