blob: 2d70ebd8e53e31b4b4af8ad7064ecb4bb62abaf7 (
plain)
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
126
127
128
129
130
131
132
133
134
135
|
package vexriscv.plugin
import spinal.core._
import spinal.lib._
import vexriscv.VexRiscv
case class RvfiPortRsRead() extends Bundle{
val addr = UInt(5 bits)
val rdata = Bits(32 bits)
}
case class RvfiPortRsWrite() extends Bundle{
val addr = UInt(5 bits)
val wdata = Bits(32 bits)
}
case class RvfiPortPc() extends Bundle{
val rdata = UInt(32 bits)
val wdata = UInt(32 bits)
}
case class RvfiPortMem() extends Bundle{
val addr = UInt(32 bits)
val rmask = Bits(4 bits)
val wmask = Bits(4 bits)
val rdata = Bits(32 bits)
val wdata = Bits(32 bits)
}
case class RvfiPort() extends Bundle with IMasterSlave {
val valid = Bool
val order = UInt(64 bits)
val insn = Bits(32 bits)
val trap = Bool
val halt = Bool
val intr = Bool
val mode = Bits(2 bits)
val ixl = Bits(2 bits)
val rs1 = RvfiPortRsRead()
val rs2 = RvfiPortRsRead()
val rd = RvfiPortRsWrite()
val pc = RvfiPortPc()
val mem = RvfiPortMem()
override def asMaster(): Unit = out(this)
}
//Tool stuff
//https://www.reddit.com/r/yosys/comments/77g5hn/unsupported_cell_type_error_adff/
//rd_addr == 0 => no rd_wdata check
//instruction that doesn't use RSx have to force the formal port address to zero
//feature added
//Halt CPU on decoding exception
//VexRiscv changes
//
//VexRiscv bug
//1) pcManagerService.createJumpInterface(pipeline.execute)
// pcManagerService.createJumpInterface(if(earlyBranch) pipeline.execute else pipeline.memory)
//2) JALR => clear PC(0)
//3) input(INSTRUCTION)(5) REGFILE_WRITE_VALID memory read with exception would not fire properly
class FormalPlugin extends Plugin[VexRiscv]{
var rvfi : RvfiPort = null
override def setup(pipeline: VexRiscv): Unit = {
rvfi = master(RvfiPort()).setName("rvfi")
}
override def build(pipeline: VexRiscv): Unit = {
import pipeline._
import pipeline.config._
import vexriscv.Riscv._
writeBack plug new Area{
import writeBack._
val order = Reg(UInt(64 bits)) init(0)
when(arbitration.isFiring){
order := order + 1
}
rvfi.valid := arbitration.isFiring
rvfi.order := order
rvfi.insn := output(FORMAL_INSTRUCTION)
rvfi.trap := False
rvfi.halt := False
rvfi.intr := False
rvfi.mode := 3
rvfi.ixl := 1
// rvfi.rs1.addr := output(INSTRUCTION)(rs1Range).asUInt
// rvfi.rs2.addr := output(INSTRUCTION)(rs2Range).asUInt
// rvfi.rs1.rdata := output(RS1)
// rvfi.rs2.rdata := output(RS2)
rvfi.rs1.addr := output(RS1_USE) ? output(INSTRUCTION)(rs1Range).asUInt | U(0)
rvfi.rs2.addr := output(RS2_USE) ? output(INSTRUCTION)(rs2Range).asUInt | U(0)
rvfi.rs1.rdata := output(RS1_USE) ? output(RS1) | B(0)
rvfi.rs2.rdata := output(RS2_USE) ? output(RS2) | B(0)
rvfi.rd.addr := output(REGFILE_WRITE_VALID) ? (output(INSTRUCTION)(rdRange).asUInt) | U(0)
rvfi.rd.wdata := output(REGFILE_WRITE_VALID) ? output(REGFILE_WRITE_DATA) | B(0)
rvfi.pc.rdata := output(PC)
rvfi.pc.wdata := output(FORMAL_PC_NEXT)
rvfi.mem.addr := output(FORMAL_MEM_ADDR)
rvfi.mem.rmask := output(FORMAL_MEM_RMASK)
rvfi.mem.wmask := output(FORMAL_MEM_WMASK)
rvfi.mem.rdata := output(FORMAL_MEM_RDATA)
rvfi.mem.wdata := output(FORMAL_MEM_WDATA)
val haltRequest = False
stages.map(s => {
when(s.arbitration.isValid && s.output(FORMAL_HALT)){ //Stage is exception halted
when(stages.drop(indexOf(s) + 1).map(!_.arbitration.isValid).foldLeft(True)(_ && _)){ //There nothing in futher stages
haltRequest := True
}
}
})
when(Delay(haltRequest, 5, init=False)){ //Give time for value propagation from decode stage to writeback stage
rvfi.valid := True
rvfi.trap := True
rvfi.halt := True
}
val haltFired = RegInit(False) setWhen(rvfi.valid && rvfi.halt)
rvfi.valid clearWhen(haltFired)
}
}
}
|