Skip to content

Commit 19787ee

Browse files
committed
feat: add csr reg
1 parent a83cfd4 commit 19787ee

File tree

1 file changed

+243
-0
lines changed

1 file changed

+243
-0
lines changed

rtl/tc_l3/src/main/scala/core/CSR.scala

Lines changed: 243 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,3 +87,246 @@ object CSR {
8787
mstatus
8888
)
8989
}
90+
91+
object Cause {
92+
val InstAddrMisaligned = 0x0.U
93+
val IllegalInst = 0x2.U
94+
val Breakpoint = 0x3.U
95+
val LoadAddrMisaligned = 0x4.U
96+
val StoreAddrMisaligned = 0x6.U
97+
val Ecall = 0x8.U
98+
}
99+
100+
class CSRIO(implicit p: Parameters) extends Bundle {
101+
val stall = Input(Bool())
102+
val cmd = Input(UInt(3.W))
103+
val in = Input(UInt(xlen.W))
104+
val out = Output(UInt(xlen.W))
105+
// excpetion
106+
val pc = Input(UInt(xlen.W))
107+
val addr = Input(UInt(xlen.W))
108+
val inst = Input(UInt(xlen.W))
109+
val illegal = Input(Bool())
110+
val st_type = Input(UInt(2.W))
111+
val ld_type = Input(UInt(3.W))
112+
val pc_check = Input(Bool())
113+
val expt = Output(Bool())
114+
val evec = Output(UInt(xlen.W))
115+
val epc = Output(UInt(xlen.W))
116+
// HTIF
117+
val host = new HostIO
118+
}
119+
120+
class CSR(implicit val p: Parameters) extends Module {
121+
val io = IO(new CSRIO)
122+
123+
val csr_addr = io.inst(31, 20)
124+
val rs1_addr = io.inst(19, 15)
125+
126+
// user counters
127+
val time = RegInit(0.U(xlen.W))
128+
val timeh = RegInit(0.U(xlen.W))
129+
val cycle = RegInit(0.U(xlen.W))
130+
val cycleh = RegInit(0.U(xlen.W))
131+
val instret = RegInit(0.U(xlen.W))
132+
val instreth = RegInit(0.U(xlen.W))
133+
134+
val mcpuid = Cat(
135+
0.U(2.W) /* RV32I */,
136+
0.U((xlen - 28).W),
137+
(1 << ('I' - 'A') /* Base ISA */ |
138+
1 << ('U' - 'A') /* User Mode */ ).U(26.W)
139+
)
140+
val mimpid = 0.U(xlen.W) // not implemented
141+
val mhartid = 0.U(xlen.W) // only one hart
142+
143+
// interrupt enable stack
144+
val PRV = RegInit(CSR.PRV_M)
145+
val PRV1 = RegInit(CSR.PRV_M)
146+
val PRV2 = 0.U(2.W)
147+
val PRV3 = 0.U(2.W)
148+
val IE = RegInit(false.B)
149+
val IE1 = RegInit(false.B)
150+
val IE2 = false.B
151+
val IE3 = false.B
152+
// virtualization management field
153+
val VM = 0.U(5.W)
154+
// memory privilege
155+
val MPRV = false.B
156+
// extention context status
157+
val XS = 0.U(2.W)
158+
val FS = 0.U(2.W)
159+
val SD = 0.U(1.W)
160+
val mstatus = Cat(SD, 0.U((xlen - 23).W), VM, MPRV, XS, FS, PRV3, IE3, PRV2, IE2, PRV1, IE1, PRV, IE)
161+
val mtvec = Const.PC_EVEC.U(xlen.W)
162+
val mtdeleg = 0x0.U(xlen.W)
163+
164+
// interrupt registers
165+
val MTIP = RegInit(false.B)
166+
val HTIP = false.B
167+
val STIP = false.B
168+
val MTIE = RegInit(false.B)
169+
val HTIE = false.B
170+
val STIE = false.B
171+
val MSIP = RegInit(false.B)
172+
val HSIP = false.B
173+
val SSIP = false.B
174+
val MSIE = RegInit(false.B)
175+
val HSIE = false.B
176+
val SSIE = false.B
177+
val mip = Cat(0.U((xlen - 8).W), MTIP, HTIP, STIP, false.B, MSIP, HSIP, SSIP, false.B)
178+
val mie = Cat(0.U((xlen - 8).W), MTIE, HTIE, STIE, false.B, MSIE, HSIE, SSIE, false.B)
179+
180+
val mtimecmp = Reg(UInt(xlen.W))
181+
182+
val mscratch = Reg(UInt(xlen.W))
183+
184+
val mepc = Reg(UInt(xlen.W))
185+
val mcause = Reg(UInt(xlen.W))
186+
val mbadaddr = Reg(UInt(xlen.W))
187+
188+
val mtohost = RegInit(0.U(xlen.W))
189+
val mfromhost = Reg(UInt(xlen.W))
190+
io.host.tohost := mtohost
191+
when(io.host.fromhost.valid) {
192+
mfromhost := io.host.fromhost.bits
193+
}
194+
195+
val csrFile = Seq(
196+
BitPat(CSR.cycle) -> cycle,
197+
BitPat(CSR.time) -> time,
198+
BitPat(CSR.instret) -> instret,
199+
BitPat(CSR.cycleh) -> cycleh,
200+
BitPat(CSR.timeh) -> timeh,
201+
BitPat(CSR.instreth) -> instreth,
202+
BitPat(CSR.cyclew) -> cycle,
203+
BitPat(CSR.timew) -> time,
204+
BitPat(CSR.instretw) -> instret,
205+
BitPat(CSR.cyclehw) -> cycleh,
206+
BitPat(CSR.timehw) -> timeh,
207+
BitPat(CSR.instrethw) -> instreth,
208+
BitPat(CSR.mcpuid) -> mcpuid,
209+
BitPat(CSR.mimpid) -> mimpid,
210+
BitPat(CSR.mhartid) -> mhartid,
211+
BitPat(CSR.mtvec) -> mtvec,
212+
BitPat(CSR.mtdeleg) -> mtdeleg,
213+
BitPat(CSR.mie) -> mie,
214+
BitPat(CSR.mtimecmp) -> mtimecmp,
215+
BitPat(CSR.mtime) -> time,
216+
BitPat(CSR.mtimeh) -> timeh,
217+
BitPat(CSR.mscratch) -> mscratch,
218+
BitPat(CSR.mepc) -> mepc,
219+
BitPat(CSR.mcause) -> mcause,
220+
BitPat(CSR.mbadaddr) -> mbadaddr,
221+
BitPat(CSR.mip) -> mip,
222+
BitPat(CSR.mtohost) -> mtohost,
223+
BitPat(CSR.mfromhost) -> mfromhost,
224+
BitPat(CSR.mstatus) -> mstatus
225+
)
226+
227+
io.out := Lookup(csr_addr, 0.U, csrFile).asUInt
228+
229+
val privValid = csr_addr(9, 8) <= PRV
230+
val privInst = io.cmd === CSR.P
231+
val isEcall = privInst && !csr_addr(0) && !csr_addr(8)
232+
val isEbreak = privInst && csr_addr(0) && !csr_addr(8)
233+
val isEret = privInst && !csr_addr(0) && csr_addr(8)
234+
val csrValid = csrFile.map(_._1 === csr_addr).reduce(_ || _)
235+
val csrRO = csr_addr(11, 10).andR || csr_addr === CSR.mtvec || csr_addr === CSR.mtdeleg
236+
val wen = io.cmd === CSR.W || io.cmd(1) && rs1_addr.orR
237+
val wdata = MuxLookup(
238+
io.cmd,
239+
0.U,
240+
Seq(
241+
CSR.W -> io.in,
242+
CSR.S -> (io.out | io.in),
243+
CSR.C -> (io.out & ~io.in)
244+
)
245+
)
246+
val iaddrInvalid = io.pc_check && io.addr(1)
247+
val laddrInvalid = MuxLookup(
248+
io.ld_type,
249+
false.B,
250+
Seq(
251+
Control.LD_LW -> io.addr(1, 0).orR,
252+
Control.LD_LH -> io.addr(0),
253+
Control.LD_LHU -> io.addr(0)
254+
)
255+
)
256+
257+
val saddrInvalid = MuxLookup(
258+
io.st_type,
259+
false.B,
260+
Seq(
261+
Control.ST_SW -> io.addr(1, 0).orR,
262+
Control.ST_SH -> io.addr(0)
263+
)
264+
)
265+
266+
io.expt := io.illegal || iaddrInvalid || laddrInvalid || saddrInvalid ||
267+
io.cmd(1, 0).orR && (!csrValid || !privValid) || wen && csrRO ||
268+
(privInst && !privValid) || isEcall || isEbreak
269+
io.evec := mtvec + (PRV << 6)
270+
io.epc := mepc
271+
272+
// Counters
273+
time := time + 1.U
274+
when(time.andR) { timeh := timeh + 1.U }
275+
cycle := cycle + 1.U
276+
when(cycle.andR) { cycleh := cycleh + 1.U }
277+
val isInstRet = io.inst =/= Instructions.NOP && (!io.expt || isEcall || isEbreak) && !io.stall
278+
when(isInstRet) { instret := instret + 1.U }
279+
when(isInstRet && instret.andR) { instreth := instreth + 1.U }
280+
281+
when(!io.stall) {
282+
when(io.expt) {
283+
mepc := io.pc >> 2 << 2
284+
mcause := Mux(
285+
iaddrInvalid,
286+
Cause.InstAddrMisaligned,
287+
Mux(
288+
laddrInvalid,
289+
Cause.LoadAddrMisaligned,
290+
Mux(saddrInvalid, Cause.StoreAddrMisaligned, Mux(isEcall, Cause.Ecall + PRV, Mux(isEbreak, Cause.Breakpoint, Cause.IllegalInst)))
291+
)
292+
)
293+
PRV := CSR.PRV_M
294+
IE := false.B
295+
PRV1 := PRV
296+
IE1 := IE
297+
when(iaddrInvalid || laddrInvalid || saddrInvalid) { mbadaddr := io.addr }
298+
}.elsewhen(isEret) {
299+
PRV := PRV1
300+
IE := IE1
301+
PRV1 := CSR.PRV_U
302+
IE1 := true.B
303+
}.elsewhen(wen) {
304+
when(csr_addr === CSR.mstatus) {
305+
PRV1 := wdata(5, 4)
306+
IE1 := wdata(3)
307+
PRV := wdata(2, 1)
308+
IE := wdata(0)
309+
}.elsewhen(csr_addr === CSR.mip) {
310+
MTIP := wdata(7)
311+
MSIP := wdata(3)
312+
}.elsewhen(csr_addr === CSR.mie) {
313+
MTIE := wdata(7)
314+
MSIE := wdata(3)
315+
}.elsewhen(csr_addr === CSR.mtime) { time := wdata }
316+
.elsewhen(csr_addr === CSR.mtimeh) { timeh := wdata }
317+
.elsewhen(csr_addr === CSR.mtimecmp) { mtimecmp := wdata }
318+
.elsewhen(csr_addr === CSR.mscratch) { mscratch := wdata }
319+
.elsewhen(csr_addr === CSR.mepc) { mepc := wdata >> 2.U << 2.U }
320+
.elsewhen(csr_addr === CSR.mcause) { mcause := wdata & (BigInt(1) << (xlen - 1) | 0xf).U }
321+
.elsewhen(csr_addr === CSR.mbadaddr) { mbadaddr := wdata }
322+
.elsewhen(csr_addr === CSR.mtohost) { mtohost := wdata }
323+
.elsewhen(csr_addr === CSR.mfromhost) { mfromhost := wdata }
324+
.elsewhen(csr_addr === CSR.cyclew) { cycle := wdata }
325+
.elsewhen(csr_addr === CSR.timew) { time := wdata }
326+
.elsewhen(csr_addr === CSR.instretw) { instret := wdata }
327+
.elsewhen(csr_addr === CSR.cyclehw) { cycleh := wdata }
328+
.elsewhen(csr_addr === CSR.timehw) { timeh := wdata }
329+
.elsewhen(csr_addr === CSR.instrethw) { instreth := wdata }
330+
}
331+
}
332+
}

0 commit comments

Comments
 (0)