@@ -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