@@ -33,7 +33,7 @@ function readCSR csr : csreg -> xlenbits = {
33
33
(0x301, _) => misa.bits,
34
34
(0x302, _) => medeleg.bits,
35
35
(0x303, _) => mideleg.bits,
36
- (0x304, _) => mie.bits,
36
+ (0x304, _) => if haveSmclic() then { zero_extend(0b0) } else mie.bits,
37
37
(0x305, _) => get_mtvec(),
38
38
(0x306, _) => zero_extend(mcounteren.bits),
39
39
(0x30A, _) => menvcfg.bits[sizeof(xlen) - 1 .. 0],
@@ -43,9 +43,17 @@ function readCSR csr : csreg -> xlenbits = {
43
43
44
44
(0x340, _) => mscratch,
45
45
(0x341, _) => get_xret_target(Machine) & pc_alignment_mask(),
46
- (0x342, _) => mcause.bits,
46
+ (0x342, _) => if haveSmclic() then {
47
+ clicmcause.bits = mcause.bits;
48
+ clicmcause[Minhv] = minhv;
49
+ clicmcause[ClicMcauseMpp] = mstatus[MPP];
50
+ clicmcause[ClicMcauseMpie] = mstatus[MPIE];
51
+ clicmcause[Mpil] = mpil;
52
+ clicmcause.bits
53
+ } else
54
+ mcause.bits,
47
55
(0x343, _) => mtval,
48
- (0x344, _) => mip.bits,
56
+ (0x344, _) => if haveSmclic() then { zero_extend(0b0) } else mip.bits,
49
57
50
58
// pmpcfgN
51
59
(0x3A @ idx : bits(4), _) if idx[0] == bitzero | sizeof(xlen) == 32 => pmpReadCfgReg(unsigned(idx)),
@@ -77,15 +85,23 @@ function readCSR csr : csreg -> xlenbits = {
77
85
(0x100, _) => lower_mstatus(mstatus).bits,
78
86
(0x102, _) => sedeleg.bits,
79
87
(0x103, _) => sideleg.bits,
80
- (0x104, _) => lower_mie(mie, mideleg).bits,
88
+ (0x104, _) => if haveSmclic() then { zero_extend(0b0) } else lower_mie(mie, mideleg).bits,
81
89
(0x105, _) => get_stvec(),
82
90
(0x106, _) => zero_extend(scounteren.bits),
83
91
(0x10A, _) => senvcfg.bits[sizeof(xlen) - 1 .. 0],
84
92
(0x140, _) => sscratch,
85
93
(0x141, _) => get_xret_target(Supervisor) & pc_alignment_mask(),
86
- (0x142, _) => scause.bits,
94
+ (0x142, _) => if haveSmclic() then {
95
+ clicscause.bits = scause.bits;
96
+ clicscause[Sinhv] = sinhv;
97
+ clicscause[ClicScauseSpp] = mstatus[SPP];
98
+ clicscause[ClicScauseSpie] = mstatus[SPIE];
99
+ clicscause[Spil] = mpil;
100
+ clicscause.bits
101
+ } else
102
+ scause.bits,
87
103
(0x143, _) => stval,
88
- (0x144, _) => lower_mip(mip, mideleg).bits,
104
+ (0x144, _) => if haveSmclic() then { zero_extend(0b0) } else lower_mip(mip, mideleg).bits,
89
105
(0x180, _) => satp,
90
106
91
107
/* user mode counters */
@@ -119,7 +135,7 @@ function writeCSR (csr : csreg, value : xlenbits) -> unit = {
119
135
(0x301, _) => { misa = legalize_misa(misa, value); Some(misa.bits) },
120
136
(0x302, _) => { medeleg = legalize_medeleg(medeleg, value); Some(medeleg.bits) },
121
137
(0x303, _) => { mideleg = legalize_mideleg(mideleg, value); Some(mideleg.bits) },
122
- (0x304, _) => { mie = legalize_mie(mie, value); Some(mie.bits) },
138
+ (0x304, _) => { if haveSmclic() then { mie = mie; Some(mie.bits) } else { mie = legalize_mie(mie, value); Some(mie.bits) } },
123
139
(0x305, _) => { Some(set_mtvec(value)) },
124
140
(0x306, _) => { mcounteren = legalize_mcounteren(mcounteren, value); Some(zero_extend(mcounteren.bits)) },
125
141
(0x30A, 32) => { menvcfg = legalize_envcfg(menvcfg, menvcfg.bits[63 .. 32] @ value); Some(menvcfg.bits[31 .. 0]) },
@@ -129,9 +145,19 @@ function writeCSR (csr : csreg, value : xlenbits) -> unit = {
129
145
(0x320, _) => { mcountinhibit = legalize_mcountinhibit(mcountinhibit, value); Some(zero_extend(mcountinhibit.bits)) },
130
146
(0x340, _) => { mscratch = value; Some(mscratch) },
131
147
(0x341, _) => { Some(set_xret_target(Machine, value)) },
132
- (0x342, _) => { mcause.bits = value; Some(mcause.bits) },
148
+ (0x342, _) => { if haveSmclic() then {
149
+ clicmcause.bits = value;
150
+ minhv = clicmcause[Minhv];
151
+ mstatus[MPP] = clicmcause[ClicMcauseMpp];
152
+ mstatus[MPIE] = clicmcause[ClicMcauseMpie];
153
+ mpil = clicmcause[Mpil];
154
+ Some(clicmcause.bits)
155
+ } else {
156
+ mcause.bits = value; Some(mcause.bits)
157
+ }
158
+ },
133
159
(0x343, _) => { mtval = value; Some(mtval) },
134
- (0x344, _) => { mip = legalize_mip(mip, value); Some(mip.bits) },
160
+ (0x344, _) => { if haveSmclic() then { mip = mip; Some(mip.bits) } else { mip = legalize_mip(mip, value); Some(mip.bits) } },
135
161
136
162
// pmpcfgN
137
163
(0x3A @ idx : bits(4), _) if idx[0] == bitzero | sizeof(xlen) == 32 => {
@@ -158,15 +184,25 @@ function writeCSR (csr : csreg, value : xlenbits) -> unit = {
158
184
(0x100, _) => { mstatus = legalize_sstatus(mstatus, value); Some(mstatus.bits) },
159
185
(0x102, _) => { sedeleg = legalize_sedeleg(sedeleg, value); Some(sedeleg.bits) },
160
186
(0x103, _) => { sideleg.bits = value; Some(sideleg.bits) }, /* TODO: does this need legalization? */
161
- (0x104, _) => { mie = legalize_sie(mie, mideleg, value); Some(mie.bits) },
187
+ (0x104, _) => { if haveSmclic() then { mie = mie; Some(mie.bits) } else { mie = legalize_sie(mie, mideleg, value); Some(mie.bits) } },
162
188
(0x105, _) => { Some(set_stvec(value)) },
163
189
(0x106, _) => { scounteren = legalize_scounteren(scounteren, value); Some(zero_extend(scounteren.bits)) },
164
190
(0x10A, _) => { senvcfg = legalize_envcfg(senvcfg, zero_extend(value)); Some(senvcfg.bits[sizeof(xlen) - 1 .. 0]) },
165
191
(0x140, _) => { sscratch = value; Some(sscratch) },
166
192
(0x141, _) => { Some(set_xret_target(Supervisor, value)) },
167
- (0x142, _) => { scause.bits = value; Some(scause.bits) },
193
+ (0x142, _) => { if haveSmclic() then {
194
+ clicscause.bits = value;
195
+ sinhv = clicscause[Sinhv];
196
+ mstatus[SPP] = clicscause[ClicScauseSpp];
197
+ mstatus[SPIE] = clicscause[ClicScauseSpie];
198
+ spil = clicscause[Spil];
199
+ Some(clicscause.bits)
200
+ } else {
201
+ scause.bits = value; Some(scause.bits)
202
+ }
203
+ },
168
204
(0x143, _) => { stval = value; Some(stval) },
169
- (0x144, _) => { mip = legalize_sip(mip, mideleg, value); Some(mip.bits) },
205
+ (0x144, _) => { if haveSmclic() then { mip = mip; Some(mip.bits) } else { mip = legalize_sip(mip, mideleg, value); Some(mip.bits) } },
170
206
(0x180, _) => { satp = legalize_satp(cur_Architecture(), satp, value); Some(satp) },
171
207
172
208
/* user mode: seed (entropy source). writes are ignored */
@@ -201,17 +237,32 @@ function clause execute CSR(csr, rs1, rd, is_imm, op) = {
201
237
else if not(ext_check_CSR(csr, cur_privilege, isWrite))
202
238
then { ext_check_CSR_fail(); RETIRE_FAIL }
203
239
else {
204
- let csr_val = readCSR(csr); /* could have side-effects, so technically shouldn't perform for CSRW[I] with rd == 0 */
205
- if isWrite then {
206
- let new_val : xlenbits = match op {
207
- CSRRW => rs1_val,
208
- CSRRS => csr_val | rs1_val,
209
- CSRRC => csr_val & ~(rs1_val)
210
- };
211
- writeCSR(csr, new_val)
212
- };
213
- X(rd) = csr_val;
214
- RETIRE_SUCCESS
240
+ let cond_writeCSR : bool = isWrite & (op == CSRRW) & is_imm == false;
241
+ match (csr, sizeof(xlen)) {
242
+ /* special conditional write CSRs, CSRRS/C/I/read behavior reserved */
243
+ (0x348, _) => {if cond_writeCSR then {match ext_write_CSR(csr, rs1_val) {Some(res) => {X(rd) = res; RETIRE_SUCCESS},None()=>RETIRE_FAIL};}else{ext_check_CSR_fail(); RETIRE_FAIL}},
244
+ (0x349, _) => {if cond_writeCSR then {match ext_write_CSR(csr, rs1_val) {Some(res) => {X(rd) = res; RETIRE_SUCCESS},None()=>RETIRE_FAIL};}else{ext_check_CSR_fail(); RETIRE_FAIL}},
245
+ (0x148, _) => {if cond_writeCSR then {match ext_write_CSR(csr, rs1_val) {Some(res) => {X(rd) = res; RETIRE_SUCCESS},None()=>RETIRE_FAIL};}else{ext_check_CSR_fail(); RETIRE_FAIL}},
246
+ (0x149, _) => {if cond_writeCSR then {match ext_write_CSR(csr, rs1_val) {Some(res) => {X(rd) = res; RETIRE_SUCCESS},None()=>RETIRE_FAIL};}else{ext_check_CSR_fail(); RETIRE_FAIL}},
247
+ (0x049, _) => {if cond_writeCSR then {match ext_write_CSR(csr, rs1_val) {Some(res) => {X(rd) = res; RETIRE_SUCCESS},None()=>RETIRE_FAIL};}else{ext_check_CSR_fail(); RETIRE_FAIL}},
248
+ /* special Smclic nxti CSRs */
249
+ (0x345, _) => {match access_nxti_CSR(csr, rs1_val, rd, is_imm, op, isWrite, Machine) {Some(res) => {X(rd) = res; RETIRE_SUCCESS},None()=>RETIRE_FAIL};},
250
+ (0x145, _) => {match access_nxti_CSR(csr, rs1_val, rd, is_imm, op, isWrite, Supervisor) {Some(res) => {X(rd) = res; RETIRE_SUCCESS},None()=>RETIRE_FAIL};},
251
+ (0x045, _) => {match access_nxti_CSR(csr, rs1_val, rd, is_imm, op, isWrite, User) {Some(res) => {X(rd) = res; RETIRE_SUCCESS},None()=>RETIRE_FAIL};},
252
+ _ => { /* standard CSRs */
253
+ let csr_val = readCSR(csr); /* could have side-effects, so technically shouldn't perform for CSRW[I] with rd == 0 */
254
+ if isWrite then {
255
+ let new_val : xlenbits = match op {
256
+ CSRRW => rs1_val,
257
+ CSRRS => csr_val | rs1_val,
258
+ CSRRC => csr_val & ~(rs1_val)
259
+ };
260
+ writeCSR(csr, new_val)
261
+ };
262
+ X(rd) = csr_val;
263
+ RETIRE_SUCCESS
264
+ }
265
+ }
215
266
}
216
267
}
217
268
0 commit comments