704db61db0bcae10d024b359319b8d8a37d9b55f
[shakti-core.git] / src / core / csr.bsv
1 /*
2 Copyright (c) 2013, IIT Madras
3 All rights reserved.
4
5 Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
6
7 * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
8 * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
9 * Neither the name of IIT Madras nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
10
11 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
12 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
13 */
14 package csr;
15
16 /* ############################ changes from 1.9.1 ############################
17 1. base field in misa is changed to readOnlyfield of mxl as per the encoding
18 and the same is reflected in sxl and uxl fields of mstatus
19 2. change of fields in mstatus.
20 */
21
22 import defined_types::*;
23 `include "defined_parameters.bsv"
24 import ConfigReg::*;
25 import GetPut ::*;
26 import ConcatReg ::*;
27 import Vector::*;
28
29 interface Ifc_csr;
30 method Bit#(3) roundingmode;
31 method Action set_external_interrupt(Tuple2#(Bool,Bool) i);
32 method Action flush;
33 (*always_ready,always_enabled*)
34 method Action boot_sequence(Bit#(1) bootseq);
35 /*======= MMU related interfaces ===== */
36 `ifdef MMU
37 method Bit#(`Reg_width) send_satp;
38 method Chmod perm_to_TLB;
39 `endif
40 method Bit#(`Reg_width) mmu_cache_disable;
41 /*=========================================== */
42 /*=========== Debug related interfaces ====== */
43 `ifdef Debug
44 method Bool halted;
45 method ActionValue#(Bit#(`Reg_width)) rw_debug_csr(Bit#(12) r, Bool write, Bit#(`Reg_width) data);
46 method TriggerData load_triggerdata;
47 method TriggerData store_triggerdata;
48 method Bool step_now;
49 method Bool reset_mode;
50 `endif
51 /*=========================================== */
52 method ActionValue#(Tuple2#(Bit#(3),Trap_type)) check_for_trap(`ifdef Debug Bool haltreq, Bool resumereq, Bool resetreq, `endif Bit#(`VADDR) pc, Bit#(32) instruction);
53 method ActionValue#(Tuple4#(Bool,Bit#(`VADDR),Bit#(`Reg_width),Bool)) system_instruction(WriteBackType wbdata ,Bit#(`VADDR) pc, Bit#(`PERFMONITORS) perfmonitor_incr `ifdef simulate , Bit#(32) instruction, Operand_type rd_type, Bit#(5) destination `endif );
54 method ActionValue#(Tuple2#(Bit#(`VADDR), Bool)) take_trap(Trap_type exception, Bit#(3) lv_debugcause, Bit#(`VADDR) pc, Bit#(`VADDR) badaddr);
55 method Bit#(`Reg_width) misa;
56 method Bit#(2) powercontrol;
57 method Action poweracknowledge(Bit#(2) pa);
58 `ifdef CLINT
59 method Action clint_msip(Bit#(1) intrpt);
60 method Action clint_mtip(Bit#(1) intrpt);
61 method Action clint_mtime(Bit#(`Reg_width) c_mtime);
62 `endif
63 method Bit#(2) inferred_xlen;
64 endinterface
65
66 function String csr_funct(Bit#(3) funct3);
67 case(funct3)
68 'd1:return "CSRRW";
69 'd2:return "CSRRS";
70 'd3:return "CSRRC";
71 'd5:return "CSRRWI" ;
72 'd6:return "CSRRSI";
73 'd7:return "CSRRCI" ;
74 default: return "NOIDEA";
75 endcase
76 endfunction
77
78 function Reg#(t) readOnlyReg(t r);
79 return (interface Reg;
80 method t _read = r;
81 method Action _write(t x) = noAction;
82 endinterface);
83 endfunction
84
85 function Reg#(Bit#(a)) extInterruptReg(Reg#(Bit#(a)) r1, Reg#(Bit#(a)) r2);
86 return (interface Reg;
87 method Bit#(a) _read = r1 | r2;
88 method Action _write(Bit#(a) x);
89 r1._write(x);
90 endmethod
91 endinterface);
92 endfunction
93
94 function Reg#(t) writeSideEffect(Reg#(t) r, Action a);
95 return (interface Reg;
96 method t _read = r._read;
97 method Action _write(t x);
98 r._write(x);
99 a;
100 endmethod
101 endinterface);
102 endfunction
103
104 (*synthesize*)
105 (*conflict_free="take_trap, set_external_interrupt"*)
106 (*conflict_free="check_for_trap,system_instruction"*)
107 module mkcsr(Ifc_csr);
108
109 Reg#(Bool) rg_initialize[2]<-mkCReg(2,False);
110 Reg#(Bit#(12)) rg_index<-mkReg(0);
111 `ifdef simulate
112 Reg#(Bool) wr_endsimulation <-mkReg(False);
113 Reg#(Bit#(1)) rg_cnt <-mkReg(0);
114 let dump <- mkReg(InvalidFile) ;
115 rule open_file(rg_cnt==0);
116 String dumpFile = "rtl.dump" ;
117 File lfh <- $fopen( dumpFile, "w" ) ;
118 if ( lfh == InvalidFile )begin
119 `ifdef verbose $display("cannot open %s", dumpFile); `endif
120 $finish(0);
121 end
122 dump <= lfh ;
123 rg_cnt <= 1 ;
124 endrule
125 `endif
126 /////////////////////////////// Machine level register /////////////////////////
127 // Current Privilege Level
128 Reg#(Privilege_mode) rg_prv <- mkConfigReg(Machine); // resets to machine mode
129
130
131 Reg#(Bit#(`Reg_width)) csr_mvendorid = readOnlyReg(0);
132 Reg#(Bit#(`Reg_width)) csr_marchid = readOnlyReg(0);
133 Reg#(Bit#(`Reg_width)) csr_mimpid = readOnlyReg(0);
134 Reg#(Bit#(`Reg_width)) csr_mhartid = readOnlyReg(0);
135 //misa fields
136 Reg#(Bit#(2)) rg_mxl <- mkReg(2);
137 Bit#(26) temp_misa='d0;
138 temp_misa[8]=1;
139 temp_misa[20]=1;
140 `ifdef atomic temp_misa[0]=1; `endif
141 `ifdef dpfpu temp_misa[3]=1; `endif
142 `ifdef spfpu temp_misa[5]=1; `endif
143 `ifdef muldiv temp_misa[12]=1; `endif
144 `ifdef MMU temp_misa[18]=1; `endif
145 `ifdef Openocd
146 Reg#(Bit#(26)) rg_misa <- mkReg(temp_misa);
147 `else
148 Reg#(Bit#(26)) rg_misa <- mkReg(`MISA_BITS);
149 `endif
150 Reg#(Bit#(`Reg_width)) csr_misa = concatReg3(rg_mxl,readOnlyReg(0),rg_misa);
151
152 // trap vector fields (same as CSR without bottom 2 bits)
153 Reg#(Bit#(2)) rg_mode_m <- mkReg(0); //default value 0 if pc to base or 1 if pc to base + 4xcause
154 Reg#(Bit#(TSub#(`PADDR,2))) rg_mtvec <- mkReg(`MTVEC_DEFAULT);
155 Reg#(Bit#(`Reg_width)) csr_mtvec=concatReg3(readOnlyReg(0),rg_mtvec, rg_mode_m);
156
157 // mstatus fields
158 Reg#(Bit#(1)) rg_tsr <- mkReg(0); // WARL
159 Reg#(Bit#(1)) rg_tw <- mkReg(0); // WARL
160 Reg#(Bit#(1)) rg_tvm <- mkReg(0); // WARL
161 Reg#(Bit#(1)) rg_mxr <- mkReg(0); // Not required
162 Reg#(Bit#(1)) rg_sum <- mkReg(0); // Not required
163 Reg#(Bit#(1)) rg_mprv <- mkReg(0);
164 Reg#(Bit#(2)) rg_xs = readOnlyReg(0);
165 Reg#(Bit#(2)) rg_fs <- mkReg(2'b00);
166 Reg#(Bit#(2)) rg_mpp <- mkReg(2'b0);
167 Reg#(Bit#(2)) rg_hpp = readOnlyReg(0);
168 Reg#(Bit#(1)) rg_spp <- mkReg(0);
169 Reg#(Bit#(1)) rg_mpie <- mkReg(0);
170 Reg#(Bit#(1)) rg_hpie = readOnlyReg(0);
171 Reg#(Bit#(1)) rg_spie <- mkReg(0);
172 Reg#(Bit#(1)) rg_upie <- mkReg(0);
173 `ifdef Openocd
174 Reg#(Bit#(1)) rg_mie <- mkReg(1);
175 `else
176 Reg#(Bit#(1)) rg_mie <- mkReg(0);
177 `endif
178 Reg#(Bit#(1)) rg_hie = readOnlyReg(0);
179 Reg#(Bit#(1)) rg_sie <- mkReg(0);
180 Reg#(Bit#(1)) rg_uie <- mkReg(0);
181 Reg#(Bit#(1)) rg_sd = readOnlyReg(pack((rg_xs == 2'b11) || (rg_fs == 2'b11)));
182 Reg#(Bit#(`Reg_width)) csr_mstatus = concatReg24(
183 rg_sd,
184 readOnlyReg(0),
185 readOnlyReg(rg_mxl), readOnlyReg(rg_mxl), //sxl and uxl fields are hardwired to mxl in misa
186 readOnlyReg(9'b0),
187 rg_tsr, rg_tw, rg_tvm,
188 rg_mxr, rg_sum, rg_mprv, // memory privilege
189 rg_xs, rg_fs, // coprocessor states
190 rg_mpp, rg_hpp, rg_spp, // previous privileges
191 rg_mpie, rg_hpie, rg_spie, rg_upie, // previous interrupt enables
192 rg_mie, rg_hie, rg_sie, rg_uie); // interrupt enables
193
194 // trap delegation fields
195 Reg#(Bit#(16)) rg_medeleg<-mkReg(0);
196 Reg#(Bit#(15)) rg_mideleg<-mkReg(0);
197 Reg#(Bit#(`Reg_width)) csr_medeleg = concatReg2(readOnlyReg(0),rg_medeleg);
198 Reg#(Bit#(`Reg_width)) csr_mideleg = concatReg2(readOnlyReg(0),rg_mideleg);
199
200 // mie fields
201 Reg#(Bit#(1)) rg_meie <- mkReg(0);
202 Reg#(Bit#(1)) rg_heie = readOnlyReg(0);
203 Reg#(Bit#(1)) rg_seie <- mkReg(0);
204 Reg#(Bit#(1)) rg_ueie <- mkReg(0);
205 Reg#(Bit#(1)) rg_mtie <- mkReg(0);
206 Reg#(Bit#(1)) rg_htie = readOnlyReg(0);
207 Reg#(Bit#(1)) rg_stie <- mkReg(0);
208 Reg#(Bit#(1)) rg_utie <- mkReg(0);
209 Reg#(Bit#(1)) rg_msie <- mkReg(0);
210 Reg#(Bit#(1)) rg_hsie = readOnlyReg(0);
211 Reg#(Bit#(1)) rg_ssie <- mkReg(0);
212 Reg#(Bit#(1)) rg_usie <- mkReg(0);
213 `ifdef Openocd
214 Reg#(Bit#(1)) rg_dhalt<-mkReg(1);
215 Reg#(Bit#(1)) rg_dresume<-mkReg(1);
216 `else
217 Reg#(Bit#(1)) rg_dhalt<-mkReg(0);
218 Reg#(Bit#(1)) rg_dresume<-mkReg(0);
219 `endif
220 Reg#(Bit#(1)) rg_dreset<-mkReg(0);
221 Reg#(Bit#(`Reg_width)) csr_mie = concatReg16(
222 readOnlyReg(0),
223 rg_dreset,rg_dresume,rg_dhalt,
224 rg_meie, rg_heie, rg_seie, readOnlyReg(rg_ueie),
225 rg_mtie, rg_htie, rg_stie, readOnlyReg(rg_utie),
226 rg_msie, rg_hsie, rg_ssie, readOnlyReg(rg_usie));
227 Reg#(Bool) rg_nmi <- mkReg(True);
228
229 // mip fields
230 Reg#(Bit#(1)) rg_meip <- mkConfigReg(0);
231 Reg#(Bit#(1)) rg_heip = readOnlyReg(0);
232 Reg#(Bit#(1)) rg_seips <- mkReg(0);
233 Reg#(Bit#(1)) rg_seipe <- mkReg(0);
234 Reg#(Bit#(1)) rg_ueips <- mkReg(0);
235 Reg#(Bit#(1)) rg_ueipe <- mkReg(0);
236 Reg#(Bit#(1)) rg_seip = extInterruptReg(rg_seips,rg_seipe);
237 Reg#(Bit#(1)) rg_ueip = extInterruptReg(rg_ueips,rg_ueipe);
238 Reg#(Bit#(1)) rg_mtip <-mkReg(0);
239 Reg#(Bit#(1)) rg_htip = readOnlyReg(0);
240 Reg#(Bit#(1)) rg_stip <- mkReg(0);
241 Reg#(Bit#(1)) rg_utip <- mkReg(0);
242 Reg#(Bit#(1)) rg_msip <- mkReg(0);
243 Reg#(Bit#(1)) rg_hsip = readOnlyReg(0);
244 Reg#(Bit#(1)) rg_ssip <- mkReg(0);
245 Reg#(Bit#(1)) rg_usip <- mkReg(0);
246
247 `ifdef RV64
248 Reg#(Bit#(`Reg_width)) csr_mcycle[2]<-mkCReg(2,0);
249 Reg#(Bit#(`Reg_width)) csr_minstret[2]<-mkCReg(2,0);
250 `else
251 Reg#(Bit#(`Reg_width)) csr_mcycle[2]<-mkCReg(2,0);
252 Reg#(Bit#(`Reg_width)) csr_minstret[2]<-mkCReg(2,0);
253 Reg#(Bit#(`Reg_width)) csr_mcycleh[2]<-mkCReg(2,0);
254 Reg#(Bit#(`Reg_width)) csr_minstreth[2]<-mkCReg(2,0);
255 `endif
256
257 // Machine Trap Handling
258 Reg#(Bit#(`Reg_width)) rg_mepc <- mkReg(0);
259 Reg#(Bit#(`VADDR)) rg_mtval <- mkReg(0);
260 Reg#(Bit#(`Reg_width)) csr_mscratch <- mkReg(0);
261 Reg#(Bit#(`Reg_width)) csr_mepc = rg_mepc;
262 Reg#(Bit#(1)) rg_interrupt <- mkReg(0);
263 Reg#(Bit#(31)) rg_lower_cause <- mkReg(0);
264 Reg#(Bit#(32)) rg_upper_cause <- mkReg(0);
265 Reg#(Bit#(`Reg_width)) csr_mcause= concatReg3(rg_interrupt, rg_upper_cause, rg_lower_cause);
266 Reg#(Bit#(`Reg_width)) csr_mtval = concatReg2(readOnlyReg(0), rg_mtval);
267 Reg#(Bit#(`Reg_width)) csr_mip = concatReg13(
268 readOnlyReg(0),
269 readOnlyReg(rg_meip), readOnlyReg(rg_heip), rg_seip, rg_ueip,
270 readOnlyReg(rg_mtip), readOnlyReg(rg_htip), rg_stip, rg_utip,
271 readOnlyReg(rg_msip), readOnlyReg(rg_hsip), rg_ssip, rg_usip);
272
273 Reg#(Bit#(`Reg_width)) mip = concatReg13(
274 readOnlyReg(0),
275 rg_meip, rg_heip, rg_seip, rg_ueip,
276 rg_mtip, rg_htip, rg_stip, rg_utip,
277 rg_msip, rg_hsip, rg_ssip, rg_usip);
278 //////////////////////////////////////////////////////////////////////////////////////////
279 ///////////////////////////////////Physical Memory Protection////////////////////////////
280 Reg#(Bit#(`Reg_width)) csr_pmpcfg0 <- mkReg(0);
281 `ifndef RV64
282 Reg#(Bit#(`Reg_width)) csr_pmpcfg1 <- mkReg(0);
283 `endif
284 Reg#(Bit#(`Reg_width)) csr_pmpcfg2 <- mkReg(0);
285 `ifndef RV64
286 Reg#(Bit#(`Reg_width)) csr_pmpcfg3 <- mkReg(0);
287 `endif
288
289 Reg#(Bit#(TSub#(`PADDR,2))) rg_pmpaddr[`PMPADDREND - `PMPADDRSTART +1];
290 Reg#(Bit#(`Reg_width)) csr_pmpaddr[`PMPADDREND - `PMPADDRSTART +1];
291 for(Integer i=0; i<(`PMPADDREND - `PMPADDRSTART +1); i =i+1) begin
292 rg_pmpaddr[i] <- mkReg(0);
293 csr_pmpaddr[i] = concatReg2(readOnlyReg(0), rg_pmpaddr[i]);
294 end
295 //////////////////////////////////////////////////////////////////////////////////////////
296 // Counter enables
297 Reg#(Bit#(1)) rg_u_ir <- mkReg(0);
298 Reg#(Bit#(1)) rg_u_tm <- mkReg(0);
299 Reg#(Bit#(1)) rg_u_cy <- mkReg(0);
300 // Machine Counter Setup
301 Reg#(Bit#(32)) reg_mcounteren<-mkReg(0);
302 Reg#(Bit#(`Reg_width)) csr_mcounteren=concatReg2(readOnlyReg(32'd0),reg_mcounteren);
303 Reg#(Bit#(1)) rg_boot_seq<-mkReg(0);
304 Reg#(Bit#(`Reg_width)) csr_boot_seq =concatReg2(readOnlyReg(0),readOnlyReg(rg_boot_seq));
305 Reg#(Bit#(2)) power_control_out <-mkReg(0);
306 Reg#(Bit#(2)) power_control_in <-mkReg(0);
307 Reg#(Bit#(`Reg_width)) csr_power_control = concatReg3(readOnlyReg(0),readOnlyReg(power_control_in),power_control_out);
308
309 //////////////////////////////////////////////////////////////////////////////////////////
310 //////////////////////////////SUPERVISOR LEVEL REGISTERS//////////////////////////////////
311 `ifdef MMU
312 Reg#(Bit#(`Reg_width)) csr_sstatus = concatReg20(
313 rg_sd,
314 readOnlyReg(0), readOnlyReg(rg_mxl), readOnlyReg(12'b0), //uxl field
315 rg_mxr, rg_sum, readOnlyReg(1'b0), // memory privilege //
316 rg_xs, rg_fs, // coprocessor states
317 readOnlyReg(2'b0), readOnlyReg(2'b0), rg_spp, // previous privileges
318 readOnlyReg(1'b0), readOnlyReg(1'b0), rg_spie, rg_upie, // previous interrupt enables
319 readOnlyReg(1'b0), readOnlyReg(1'b0), rg_sie, rg_uie); // interrupt enables
320
321 Reg#(Bit#(12)) rg_sedeleg<-mkReg(0);
322 Reg#(Bit#(15)) rg_sideleg<-mkReg(0);
323 Reg#(Bit#(`Reg_width)) csr_sedeleg = concatReg2(readOnlyReg(0),rg_sedeleg);
324 Reg#(Bit#(`Reg_width)) csr_sideleg = concatReg2(readOnlyReg(0),rg_sideleg);
325
326 Reg#(Bit#(`Reg_width)) csr_sie = concatReg13(
327 readOnlyReg(0),
328 readOnlyReg(1'b0), readOnlyReg(1'b0), rg_seie, readOnlyReg(rg_ueie),
329 readOnlyReg(1'b0), readOnlyReg(1'b0), rg_stie, readOnlyReg(rg_utie),
330 readOnlyReg(1'b0), readOnlyReg(1'b0), rg_ssie, readOnlyReg(rg_usie));
331
332 Reg#(Bit#(2)) rg_mode_s <- mkReg(0); //default value 0 if pc to base or 1 if pc to base + 4xcause
333 Reg#(Bit#(TSub#(`Reg_width,2))) rg_stvec <- mkReg(`STVEC_DEFAULT);
334 Reg#(Bit#(`Reg_width)) csr_stvec=concatReg2(rg_stvec,rg_mode_s);
335 Reg#(Bit#(32)) rg_scounteren <- mkReg(0);
336 Reg#(Bit#(`Reg_width)) csr_scounteren = concatReg2(readOnlyReg(0),rg_scounteren);
337
338 //Supervisor Trap Handling Register
339 Reg#(Bit#(`VADDR)) rg_stval <- mkReg(0);
340 Reg#(Bit#(`Reg_width)) csr_sscratch <- mkReg(0);
341 Reg#(Bit#(`Reg_width)) csr_sepc <- mkReg(0);
342 Reg#(Bit#(`Reg_width)) csr_scause <- mkReg(0);
343 Reg#(Bit#(`Reg_width)) csr_stval = concatReg2(readOnlyReg(0), rg_stval);
344 Reg#(Bit#(`Reg_width)) csr_sip = concatReg13(
345 readOnlyReg(0),
346 readOnlyReg(1'b0), readOnlyReg(1'b0), readOnlyReg(rg_seip), rg_ueip,
347 readOnlyReg(1'b0), readOnlyReg(1'b0), readOnlyReg(rg_stip), readOnlyReg(rg_utip),
348 readOnlyReg(1'b0), readOnlyReg(1'b0), rg_ssip, readOnlyReg(rg_usip));
349
350 //Supervisor Protection and Translation
351 Reg#(Bit#(`Reg_width)) csr_satp <- mkReg(0);
352 `endif
353 //////////////////////////////////////////////////////////////////////////////////////////
354 //////////////////////////////// User level registers ///////////////////////////////////
355 `ifdef RV64
356 Reg#(Bit#(`Reg_width)) csr_uinstret=readOnlyReg(csr_minstret[1]);
357 Reg#(Bit#(`Reg_width)) csr_ucycle=readOnlyReg(csr_mcycle[1]);
358 `else
359 Reg#(Bit#(`Reg_width)) csr_uinstret=readOnlyReg(csr_minstret[1]);
360 Reg#(Bit#(`Reg_width)) csr_ucycle=readOnlyReg(csr_mcycle[1]);
361 Reg#(Bit#(`Reg_width)) csr_uinstreth=readOnlyReg(csr_minstreth[1]);
362 Reg#(Bit#(`Reg_width)) csr_ucycleh=readOnlyReg(csr_mcycleh[1]);
363 `endif
364
365 Reg#(Bit#(`Reg_width)) rg_clint_mtime <-mkReg(0);
366 Reg#(Bit#(5)) rg_fflags<-mkReg(0);
367 Reg#(Bit#(3)) rg_frm<-mkReg(0);
368 Reg#(Bit#(`Reg_width)) csr_fcsr = writeSideEffect(concatReg3(readOnlyReg(0),rg_frm,rg_fflags),rg_fs._write(2'b11));
369 Reg#(Bit#(`Reg_width)) csr_fflags=writeSideEffect(concatReg2(readOnlyReg(0),rg_fflags),rg_fs._write(2'b11));
370 Reg#(Bit#(`Reg_width)) csr_frm = writeSideEffect(concatReg2(readOnlyReg(0),rg_frm),rg_fs._write(2'b11));
371 Reg#(Bit#(4)) rg_memse <- mkReg(0); //0th-bit set -> immu disable,1th-bit set -> icache,2nd-bit -> dmmu, 3rd bit -> dcache
372 Reg#(Bit#(`Reg_width)) csr_memse = concatReg2(readOnlyReg(0),rg_memse);
373
374 //////////////////////////////////////////////////////////////////////////////////////////
375 ///////////////////////////////////////// PErformance Counters //////////////////////////
376 `ifdef perf
377 Array#(Reg#(Bit#(64))) csr_mhpmcounter[`MHPMCOUNTEND-`MHPMCOUNTSTART+1];
378 Reg#(Bit#(`Reg_width)) csr_mhpmevent[`MHPMCOUNTEND-`MHPMCOUNTSTART+1];
379 for(Integer i=0;i<=(`MHPMCOUNTEND-`MHPMCOUNTSTART);i=i+1)begin
380 csr_mhpmcounter[i]<-mkCReg(2,0);
381 end
382 csr_mhpmevent[0]<-mkReg('h20000000);
383 csr_mhpmevent[1]<-mkReg('h20000);
384 csr_mhpmevent[2]<-mkReg('h4000);
385 `endif
386
387 //////////////////////////////////////////////////////////////////////////////////////////
388 ///////////////////////////////////////// Debug Registers /////////////////////////////////
389 `ifdef Debug
390 `ifdef Openocd
391 Reg#(Bool) resetmode[2]<-mkCReg(2,False); // TODO
392 Reg#(Bit#(1)) ebreakm<-mkReg(1);
393 Reg#(Bit#(1)) ebreaks<-mkReg(1);
394 Reg#(Bit#(1)) ebreaku<-mkReg(1);
395 `else
396 Reg#(Bool) resetmode[2]<-mkCReg(2,False); // TODO
397 Reg#(Bit#(1)) ebreakm<-mkReg(0);
398 Reg#(Bit#(1)) ebreaks<-mkReg(0);
399 Reg#(Bit#(1)) ebreaku<-mkReg(0);
400 `endif
401 Reg#(Bit#(1)) stopcount<-mkReg(0);
402 Reg#(Bit#(1)) stoptime <-mkReg(0);
403 Reg#(Bit#(3)) debugcause<-mkReg(0);
404 Reg#(Bit#(1)) step<-mkReg(0);
405 Reg#(Bit#(2)) debugprv<-mkReg(0);
406 Reg#(Bit#(32)) dcsr=concatReg13(readOnlyReg(4'd4), readOnlyReg(12'd0),
407 ebreakm,readOnlyReg(1'b0),ebreaks,ebreaku,
408 readOnlyReg(1'b0),
409 stopcount,stoptime,
410 readOnlyReg(debugcause),readOnlyReg(3'd0),
411 step,debugprv);
412 Reg#(Bit#(`VADDR)) dpc <-mkReg(0);
413 Reg#(Bit#(`Reg_width)) csr_dpc=concatReg2(readOnlyReg('d0),dpc);
414 Reg#(Bit#(`Reg_width)) dscratch0<-mkReg(0);
415 Reg#(Bool) debugmode_active[2]<-mkCReg(2,False);
416 Reg#(Bit#(`Reg_width)) debugentry<-mkReg(`DebugBase);
417 //////////////////////////////////////////////////////////////////////////////////////////
418 //////////////////////// Trigger Registers ////////////////////////////////////////
419 Reg#(Bit#(`Reg_width)) tselect=readOnlyReg('d0);
420 Reg#(Bit#(4)) trigger_type=readOnlyReg('d2);
421 Reg#(Bit#(1)) dmode=readOnlyReg(1'd0);
422 Reg#(Bit#(6)) maskmax=readOnlyReg(6'd0);
423 Reg#(Bit#(1)) select<-mkReg(0);
424 Reg#(Bit#(1)) timing=readOnlyReg(1'b0);
425 Reg#(Bit#(6)) triggeraction=readOnlyReg(6'd0); // always enter debug mode.
426 Reg#(Bit#(1)) chain<-mkReg(0);
427 Reg#(Bit#(4)) triggermatch<-mkReg(0);
428 Reg#(Bit#(1)) triggerm<-mkReg(0);
429 Reg#(Bit#(1)) triggers<-mkReg(0);
430 Reg#(Bit#(1)) triggeru<-mkReg(0);
431 Reg#(Bit#(1)) execute<-mkReg(0);
432 Reg#(Bit#(1)) store<-mkReg(0);
433 Reg#(Bit#(1)) load<-mkReg(0);
434 Reg#(Bit#(`Reg_width)) tdata1=concatReg16(trigger_type,dmode,maskmax,
435 readOnlyReg(33'd0),select,timing,
436 triggeraction,chain,triggermatch,
437 triggerm,readOnlyReg(1'b0),triggers,triggeru,
438 execute,store,load);
439 Reg#(Bit#(`Reg_width)) tdata2<-mkReg(0);
440 Wire#(TriggerData) executetrigger<-mkDWire(TriggerData{ttype:tagged None,matchscheme:0});
441 Wire#(TriggerData) loadtrigger<-mkDWire(TriggerData{ttype:tagged None,matchscheme:0});
442 Wire#(TriggerData) storetrigger<-mkDWire(TriggerData{ttype:tagged None,matchscheme:0});
443 Reg#(Bool) rg_step_now<-mkReg(False);
444 rule generate_trigger_info_decode;
445 if(execute==1 && ((rg_prv==User &&triggeru==1)||(rg_prv==Supervisor &&triggers==1)||(rg_prv==Machine &&triggerm==1)) )
446 executetrigger<=TriggerData{ttype:select==0?tagged Address tdata2:tagged Data tdata2,matchscheme:triggermatch};
447 if(load==1&& ((rg_prv==User &&triggeru==1)||(rg_prv==Supervisor &&triggers==1)||(rg_prv==Machine &&triggerm==1)) )
448 loadtrigger<=TriggerData{ttype:select==0?tagged Address tdata2:tagged Data tdata2,matchscheme:triggermatch};
449 if(store==1&& ((rg_prv==User &&triggeru==1)||(rg_prv==Supervisor &&triggers==1)||(rg_prv==Machine &&triggerm==1)) )
450 storetrigger<=TriggerData{ttype:select==0?tagged Address tdata2:tagged Data tdata2,matchscheme:triggermatch};
451 endrule
452 `endif
453 `ifdef Debug
454 function Bool checktrigger(TriggerData tdata, Bit#(`VADDR) pc1, Bit#(32) instruction);
455 Bit#(`Reg_width) pc=zeroExtend(pc1);
456 if(tdata.ttype matches tagged Address .addr)
457 if(tdata.matchscheme==0 && addr==pc)
458 return True;
459 else if(tdata.matchscheme==2 && addr>=pc)
460 return True;
461 else if(tdata.matchscheme==3 && addr<=pc)
462 return True;
463 else if(tdata.matchscheme==4 && addr[31:0]==(addr[63:32]&pc[31:0]))
464 return True;
465 else if(tdata.matchscheme==5 && addr[31:0]==(addr[`Reg_width-1:32]&pc[`Reg_width-1:32]))
466 return True;
467 else
468 return False;
469 else if(tdata.ttype matches tagged Data .data)
470 if(data[31:0]==instruction)
471 return True;
472 else
473 return False;
474 else
475 return False;
476 endfunction
477 `endif
478 /////////// Functions to access CSRs /////////////////////////////////////////////////////////////
479 function Reg#(Bit#(`Reg_width)) read_user_sro_registers(Bit#(8) addr);
480 Reg#(Bit#(`Reg_width)) csr=(case(addr)
481 `UCYCLE :csr_ucycle;
482 `UTIME :readOnlyReg(rg_clint_mtime);
483 `UINSTRET :csr_uinstret;
484 `ifndef RV64
485 `UCYCLEH :csr_ucycleh;
486 `UINSTRETH :csr_uinstreth;
487 `endif
488 default:readOnlyReg(0);
489 endcase);
490 return csr;
491 endfunction
492 function Reg#(Bit#(`Reg_width)) read_user_srw_registers(Bit#(8) addr);
493 Reg#(Bit#(`Reg_width)) csr=(case(addr)
494 `FFLAGS :csr_fflags ;
495 `FRM :csr_frm ;
496 `FCSR :csr_fcsr ;
497 `UMEMSE :csr_memse;
498 default: readOnlyReg(0);
499 endcase);
500 return csr;
501 endfunction
502 `ifdef MMU
503 function Reg#(Bit#(`Reg_width)) read_supervisor_srw_registers(Bit#(8) addr);
504 Reg#(Bit#(`Reg_width)) csr=(case(addr)
505 `SSTATUS :csr_sstatus;
506 `SEDELEG :csr_sedeleg;
507 `SIDELEG :csr_sideleg;
508 `SIE :csr_sie;
509 `STVEC :csr_stvec;
510 `SCOUNTEREN :csr_scounteren;
511 `SSCRATCH :csr_sscratch;
512 `SEPC :csr_sepc;
513 `SCAUSE :csr_scause;
514 `STVAL :csr_stval;
515 `SIP :csr_sip;
516 `SATP :csr_satp;
517 default:readOnlyReg(0);
518 endcase);
519 return csr;
520 endfunction
521 `endif
522 function Reg#(Bit#(`Reg_width)) read_machine_srw_registers(Bit#(8) address);
523 Reg#(Bit#(`Reg_width)) csr=(case(address)
524 `MSTATUS :csr_mstatus;
525 `MISA :csr_misa;
526 `MEDELEG :csr_medeleg;
527 `MIDELEG :csr_mideleg;
528 `MIE :csr_mie;
529 `MTVEC :csr_mtvec;
530 `MCOUNTEREN :csr_mcounteren;
531 `MSCRATCH :csr_mscratch;
532 `MEPC :csr_mepc;
533 `MCAUSE :((rg_mxl==1)?concatReg3(readOnlyReg(32'd0), rg_interrupt, rg_lower_cause):csr_mcause);
534 `MTVAL :csr_mtval;
535 `MIP :csr_mip;
536 `MPOWERCONTROL :csr_power_control;
537 `PMPCFG0 :csr_pmpcfg0;
538 `ifndef RV64
539 `PMPCFG1 :csr_pmpcfg1;
540 `endif
541 `PMPCFG2 :csr_pmpcfg2;
542 `ifndef RV64
543 `PMPCFG3 :csr_pmpcfg3;
544 `endif
545 default: begin
546 `ifdef perf
547 if(address>=`PMPADDRSTART && address<=`PMPADDREND) // lower 4 bits of the counter
548 csr_pmpaddr[address[3:0]];
549 else if(address>=`MHPMEVENTSTART && address<=`MHPMEVENTEND) // lower 32 bits of the counter
550 csr_mhpmcounter[(address-3)[1:0]][1];
551 else
552 `endif
553 readOnlyReg(0);
554 end
555 endcase);
556 return csr;
557 endfunction
558 function Reg#(Bit#(`Reg_width))read_machine_sro_registers(Bit#(8) address);
559 Reg#(Bit#(`Reg_width)) csr=(case(address)
560 `MVENDORID:csr_mvendorid;
561 `MARCHID :csr_marchid;
562 `MIMPID :csr_mimpid;
563 `MHARTID :csr_mhartid;
564 `MBOOTSEQ : csr_boot_seq;
565 default:readOnlyReg(0);
566 endcase);
567 return csr;
568 endfunction
569
570 function Reg#(Bit#(`Reg_width)) read_machine_counters(Bit#(8) address);
571 Reg#(Bit#(`Reg_width)) csr=(case(address)
572 `MCYCLE :csr_mcycle[1];
573 `MINSTRET :csr_minstret[1];
574 `ifndef RV64
575 `MCYCLEH :csr_mcycleh[1];
576 `MINSTRETH :csr_minstreth[1];
577 `endif
578 default: begin
579 `ifdef perf
580 if(address>=`MHPMCOUNTSTART && address<=`MHPMCOUNTEND) // lower 32 bits of the counter
581 csr_mhpmcounter[(address-3)[1:0]][1];
582 else
583 `endif
584 readOnlyReg(0);
585 end
586 endcase);
587 return csr;
588 endfunction
589 `ifdef Debug
590 function Reg#(Bit#(`Reg_width)) read_debug_registers(Bit#(8) address);
591 Reg#(Bit#(`Reg_width)) csr=(case(address)
592 `DCSR: concatReg2(readOnlyReg(32'd0),dcsr);
593 `DPC: csr_dpc;
594 `DSCRATCH0: dscratch0;
595 `DENTRY : debugentry;
596 `TSELECT : tselect;
597 `TDATA1 : tdata1;
598 `TDATA2 : tdata2;
599 default:readOnlyReg(0);
600 endcase);
601 return csr;
602 endfunction
603 `endif
604 function Reg#(Bit#(`Reg_width)) read_csr(Bit#(12) addr);
605 Reg#(Bit#(`Reg_width)) csr=(
606 case(addr[11:8])
607 'h0: read_user_srw_registers(truncate(addr)); // user standard read-write
608 'hC: read_user_sro_registers(truncate(addr)); // user standard read-only
609 `ifdef MMU 'h1: read_supervisor_srw_registers(truncate(addr)); `endif // supervisor read-write
610 'h3: read_machine_srw_registers(truncate(addr)); // machine standard read-write
611 'hF: read_machine_sro_registers(truncate(addr)); // machine standard read-only
612 'hB: read_machine_counters(truncate(addr)); // machine standard counters
613 `ifdef Debug 'h7: read_debug_registers(truncate(addr)); `endif
614 default: readOnlyReg(0);//read_perfcounter(address);
615 endcase
616 );
617 return csr;
618 endfunction
619
620 function Bool hasCSRPermission(Bit#(12) address, Bool write);
621 Bit#(12) csr_index = pack(address);
622 Bool check_counter_permission = True;
623 if(address >= 12'hB00 && address <= 12'hB1F) begin
624 check_counter_permission = False;
625 if(pack(rg_prv) == 3)
626 check_counter_permission = True;
627 else if(pack(rg_prv) == 1 && csr_mcounteren[address[4:0]]==1)
628 check_counter_permission = True;
629 `ifdef MMU
630 else if(pack(rg_prv) == 0 && csr_scounteren[address[4:0]]==1)
631 check_counter_permission = True;
632 `endif
633 end
634 return ((pack(rg_prv) >= csr_index[9:8]) && check_counter_permission && !(write && csr_index[11:10]==2'b11) );//(!write || (csr_index[11:10] != 2'b11))) || check_counter_permission);
635 endfunction
636
637 // if the operand is not 0 then the instruction will perform a write on the CSR.
638 function Bool valid_csr_access(Bit#(12) csr_addr, Bit#(5) operand, Bit#(2) operation);
639 Bool ret = hasCSRPermission(unpack(csr_addr), (operand != 0 || operation=='b01) ? True:False);
640 return ret;
641 endfunction
642
643 function Bool address_valid(Bit#(12) csr_address);
644 case(csr_address[11:8])
645 'h0: begin
646 if((csr_address[7:0]>'h5 && csr_address[7:0]<'h40) ||
647 (csr_address[7:0]>'h44))
648 return False;
649 else
650 return True;
651 end
652 'h1:begin
653 if((csr_address[7:0]==1)||
654 (csr_address[7:0]>'h6 && csr_address[7:0]<'h40) ||
655 (csr_address[7:0]>'h44 && csr_address[7:0]!='h80))
656 return False;
657 else
658 return True;
659 end
660 'h3: begin // machine read-write registers
661 if((csr_address[7:0]>'h6 && csr_address[7:0]<'h23) ||
662 (csr_address[7:0]>'h26 && csr_address[7:0]<'h40) ||
663 (csr_address[7:0]>'h44 && csr_address[7:0]<='hA0) ||
664 (csr_address[7:0]>'hA3 && csr_address[7:0]<'hB8) ||
665 (csr_address[7:0]>'hbf))
666 return False;
667 else
668 return True;
669 end
670 'h7: begin
671 if((csr_address[7:0]<'hA0)||
672 (csr_address[7:0]>'hA3 && csr_address[7:0]<'hB0)||
673 (csr_address[7:0]>'hB2))
674 return False;
675 else
676 return True;
677 end
678 'hB:begin
679 if((csr_address[7:0]>'h6 && csr_address[7:0]<'h80 && csr_address[7:0]!='h20)||
680 (csr_address[7:0]>'h86 && csr_address[7:0]<'hA0)||
681 (csr_address[7:0]>'hA6))
682 return False;
683 else
684 return True;
685 end
686 'hC:begin
687 if((csr_address[7:0]>'h6 && csr_address[7:0]<'h83)||
688 (csr_address[7:0]>'h86))
689 return False;
690 else
691 return True;
692 end
693 'hF:begin
694 if(csr_address[7:0]<'h11 || csr_address[7:0]>'h15)
695 return False;
696 else
697 return True;
698 end
699 default:return False;
700 endcase
701 endfunction
702
703 rule increment_cycle_counter `ifdef Debug (stopcount==0) `endif ;
704 `ifdef RV64
705 csr_mcycle[0]<=csr_mcycle[0]+1;
706 `else
707 Bit#(64) new_cycle={csr_mcycleh[0],csr_mcycle[0]);
708 new_cycle=new_cycle+1;
709 csr_mcycle[0]<=new_cycle[31:0];
710 csr_mcycleh[0]<=new_cycle[63:32];
711 `endif
712 endrule
713
714
715 // Check pending interrupts
716 function ActionValue#(Trap_type) fn_chk_pending_interrupt(`ifdef Debug Bool haltreq, Bool resumereq , Bool resetreq`endif )=
717 actionvalue
718 `ifdef Debug
719 Bit#(15) pending_debug_interrupt=0;
720 if(haltreq && !debugmode_active[0] && !resetmode[0])
721 pending_debug_interrupt[12]=1;
722 if(resumereq && debugmode_active[0] && !resetmode[0])
723 pending_debug_interrupt[13]=1;
724 if(resetreq && !resetmode[0] && debugmode_active[0])
725 pending_debug_interrupt[14]=1;
726 `endif
727 Bit#(`Reg_width) lv_csr_mip = csr_mip;
728 lv_csr_mip[11]=lv_csr_mip[11]|pack(rg_nmi);
729 Bit#(15) pending_interrupts = (truncate(csr_mip)`ifdef Debug |pending_debug_interrupt `endif ) & truncate(csr_mie) ;
730 `ifdef verbose $display("Pending_interrupts in the beginning csr_mip : %b pending_interrupt: %b", csr_mip, pending_interrupts); `endif
731 // machine mode
732 let pending_machine_interrupts = pending_interrupts & ~truncate(csr_mideleg);
733 let machine_interrupts_enabled = (rg_mie == 1) || (pack(rg_prv) < pack(Machine));
734 //supervisor mode
735 `ifdef MMU
736 let pending_supervisor_interrupts = pending_interrupts & truncate(csr_mideleg) & ~truncate(csr_sideleg);
737 let supervisor_interrupts_enabled = (rg_sie == 1) && (pack(rg_prv) <= pack(Supervisor));
738 `endif
739 // user mode
740 // combined
741 pending_interrupts = (machine_interrupts_enabled ? pending_machine_interrupts : 0)
742 `ifdef MMU |(supervisor_interrupts_enabled ? pending_supervisor_interrupts : 0) `endif ;
743
744 // format pendingInterrupt value to return
745 Trap_type ret = tagged None;
746 if (pending_interrupts != 0) begin
747 ret = tagged Interrupt unpack(zeroExtend(pack(countZerosLSB(pending_interrupts))));
748 end
749 `ifdef verbose $display("Debug interrupts: %h pending_interrupt: %h csr_mie: %h rg_mie: %b ret: ",`ifdef Debug pending_debug_interrupt `else 0 `endif ,pending_interrupts,csr_mie,rg_mie,fshow(ret)); `endif
750 return ret;
751 endactionvalue;
752
753
754 method ActionValue#(Tuple2#(Bit#(3),Trap_type)) check_for_trap(`ifdef Debug Bool haltreq, Bool resumereq, Bool resetreq, `endif Bit#(`VADDR) pc, Bit#(32) instruction)if(!rg_initialize[1] `ifdef simulate && !wr_endsimulation `endif );
755 Trap_type trap_type=tagged None;
756 Bit#(3) lv_debugcause=0;
757 let opcode=instruction[6:2];
758 if(opcode==`CSR_op)begin
759 case(instruction[14:12])
760 'd0:case (instruction[31:20])
761 'h000: // ECALL
762 trap_type=tagged Exception(case(rg_prv) User: Ecall_from_user; Supervisor:Ecall_from_supervisor;Machine:Ecall_from_machine;endcase);
763 'h001:begin // EBREAK
764 `ifdef Debug
765 Bit#(4) ebreak={ebreakm,0,ebreaks,ebreaku};
766 if((ebreak)[pack(rg_prv)]==1)
767 trap_type=tagged Interrupt DebugInterrupt;
768 else
769 `endif
770 trap_type=tagged Exception Breakpoint;
771 lv_debugcause=1;
772 end
773 'h102:begin // SRET
774 if(pack(rg_prv)<pack(Supervisor)) trap_type=tagged Exception Illegal_inst;
775 end
776 'h302:begin // MRET
777 if(pack(rg_prv)<pack(Machine)) trap_type= tagged Exception Illegal_inst;
778 end
779 endcase
780 default: begin
781 Bool address_is_valid=address_valid(instruction[31:20]);
782 Bool access_is_valid=valid_csr_access(instruction[31:20],instruction[19:15], instruction[13:12]);
783 `ifdef verbose $display($time,"\tCSR: Address: %h AddressValid: %b AccessValid: %b",instruction[31:20],address_is_valid,access_is_valid); `endif
784 if(!(address_is_valid && access_is_valid))
785 trap_type=tagged Exception Illegal_inst;
786 end
787 endcase
788 end
789 if(opcode==`FMADD_op || opcode==`FNMSUB_op || opcode==`FNMADD_op || opcode==`FMSUB_op || opcode==`FLOAT_op)begin
790 if(instruction[14:12]=='b111 && rg_frm>4)
791 trap_type=tagged Exception Illegal_inst;
792 end
793 if((opcode[4:3]=='b10 || opcode==`FSTORE_op || opcode==`FLOAD_op) && rg_fs==0)
794 trap_type=tagged Exception Illegal_inst;
795 `ifdef Debug
796 if(checktrigger(executetrigger,pc,instruction))begin
797 `ifdef verbose $display("TRAP: Trigger Fired Debug Interupt"); `endif
798 trap_type=tagged Exception Breakpoint;
799 lv_debugcause=2;
800 end
801 `endif
802 let pending_interrupt <- fn_chk_pending_interrupt(`ifdef Debug haltreq,resumereq, resetreq `endif );// TODO but resume request here
803 if(pending_interrupt matches tagged Interrupt .interrupt) begin
804 `ifdef verbose $display($time,"\tinterrupt injected in to pipeline"); `endif
805 trap_type=tagged Interrupt interrupt;
806 `ifdef Debug
807 if(interrupt ==DebugInterrupt)
808 lv_debugcause=(step==1)?4:3;
809 `endif
810 end
811 return tuple2(lv_debugcause,trap_type);
812 endmethod
813
814 method ActionValue#(Tuple4#(Bool,Bit#(`VADDR),Bit#(`Reg_width),Bool)) system_instruction(WriteBackType wbdata ,Bit#(`VADDR) pc, Bit#(`PERFMONITORS) perfmonitor_incr `ifdef simulate , Bit#(32) instruction, Operand_type rd_type, Bit#(5) destination `endif )if(!rg_initialize[1] `ifdef simulate && !wr_endsimulation `endif );
815 Bool flush=True; // TODO flush for only writting on certain csr registers
816 Bool commit=False;
817 Bit#(`VADDR) jump_address=pc+4;
818 Bit#(`Reg_width) destination_value=0;
819 /*====== Execute the current instruction and generate a halt interrupt on the next ===== */
820 `ifdef Debug
821 `ifdef verbose $display($time,"CSR: STEP_NOW : %b",rg_step_now); `endif
822 if(step==1 && !debugmode_active[0] && !rg_step_now)
823 rg_step_now<=True;
824 else
825 rg_step_now<=False;
826 `endif
827 /*======================================================================================= */
828 if(wbdata matches tagged SYSTEM .csr)begin
829 let csr_reg=read_csr(csr.csr_address);
830 if(csr.funct3==0)begin
831 case (csr.csr_address[11:8]) matches
832 'h3:begin // MRET
833 Privilege_mode next_prv =unpack(rg_mpp);
834 rg_mpie <= 1;
835 rg_mpp <= pack(User);
836 rg_prv <= next_prv;
837 jump_address=truncate(csr_mepc);
838 rg_mie<=rg_mpie;
839 end
840 `ifdef MMU
841 'h1:begin // SRET
842 if(csr.csr_address[5]==0)begin
843 Privilege_mode next_prv =unpack({1'b0,rg_spp});
844 rg_spie <= 1;
845 rg_spp <= pack(User)[0];
846 rg_prv <= next_prv;
847 jump_address=truncate(csr_sepc);
848 rg_sie<=rg_spie;
849 end
850 else begin // SFENCE
851 jump_address=pc+4;
852 `ifdef simulate
853 Bit#(64) pc1=signExtend(pc[38:0]);
854 $fwrite(dump, rg_prv," 0x%16h",pc1, " (0x%8h", instruction,")" );
855 $fwrite(dump," x%d",destination," 0x%16h",destination_value,"\n");
856 `endif
857 `ifdef Debug
858 if(resetmode[0])
859 resetmode[0]<=False;
860 `endif
861 end
862 end
863 `endif
864 `ifdef Debug
865 'h7:begin // DRET
866 jump_address=dpc;
867 rg_prv<=unpack(debugprv);
868 debugmode_active[0]<=False;
869 end
870 `endif
871 endcase
872 `ifdef Debug
873 if(stopcount==0 && !debugmode_active[0]) begin
874 csr_minstret[0]<=csr_minstret[0]+1;
875 end
876 `endif
877 for(Integer i=0;i<=(`MHPMCOUNTEND-`MHPMCOUNTSTART);i=i+1)
878 if((csr_mhpmevent[i]&perfmonitor_incr)!=0 `ifdef Debug && stopcount==0 `endif )
879 csr_mhpmcounter[i][1]<=csr_mhpmcounter[i][1]+1;
880 `ifdef verbose
881 for(Integer i=0;i<=(`MHPMCOUNTEND-`MHPMCOUNTSTART);i=i+1)begin
882 $display($time,"\tEVENT: :%h %s",csr_mhpmevent[i],event_name(csr_mhpmevent[i])," : %d",csr_mhpmcounter[i][1]);
883 end
884 `endif
885 end
886 else begin
887 destination_value=csr_reg;
888 `ifdef verbose $display($time,"\tCSR: Dest: %h Value: %h rs1: %h funct3: %d rs1_addr: %d",csr.csr_address,csr_reg,csr.rs1,csr.funct3,csr.rs1_addr); `endif
889 commit=True;
890 case(csr.funct3)
891 'd1: csr_reg <= csr.rs1; // CSRRW
892 'd2:if(csr.rs1_addr!=0) csr_reg <= csr.rs1 | csr_reg; // CSRRS
893 'd3:if(csr.rs1_addr!=0) csr_reg <= ~(csr.rs1) & csr_reg; // CSRRC
894 'd5: csr_reg <= zeroExtend(csr.rs1_addr); // CSRRWI
895 'd6:if(csr.rs1_addr!=0) csr_reg <= zeroExtend(csr.rs1_addr) | csr_reg; // CSRRSI
896 'd7:if(csr.rs1_addr!=0) csr_reg <= ~(zeroExtend(csr.rs1_addr)) & csr_reg; //CSRRCI
897 endcase
898 `ifdef simulate
899 Bit#(64) pc1=signExtend(pc[38:0]);
900 $fwrite(dump, rg_prv," 0x%16h",pc1, " (0x%8h", instruction,")" );
901 $fwrite(dump," x%d",destination," 0x%16h",destination_value);
902 $fwrite(dump,"\n");
903 `endif
904 end
905 end
906 else if(wbdata matches tagged RESULT .res)begin
907 for(Integer i=0;i<=(`MHPMCOUNTEND-`MHPMCOUNTSTART);i=i+1)
908 if((csr_mhpmevent[i]&perfmonitor_incr)!=0 `ifdef Debug && stopcount==0 `endif )
909 csr_mhpmcounter[i][1]<=csr_mhpmcounter[i][1]+1;
910 `ifdef verbose
911 for(Integer i=0;i<=(`MHPMCOUNTEND-`MHPMCOUNTSTART);i=i+1)begin
912 $display($time,"\tEVENT: :%h %s",csr_mhpmevent[i],event_name(csr_mhpmevent[i])," : %d",csr_mhpmcounter[i][1]);
913 end
914 `endif
915 `ifdef simulate
916 Bit#(64) pc1=signExtend(pc[38:0]);
917 $fwrite(dump, rg_prv," 0x%16h",pc1, " (0x%8h", instruction,")" );
918 `endif
919 commit=True;
920 `ifdef Debug
921 if(stopcount==0 && !debugmode_active[0])begin
922 csr_minstret[0]<=csr_minstret[0]+1;
923 end
924 `endif
925 flush=False;
926 destination_value=res.aluresult;
927 let newfflags=res.fflags;
928 let fpudirty=False;
929 if((newfflags|rg_fflags)!=rg_fflags)begin
930 rg_fflags<=newfflags|rg_fflags;
931 fpudirty=True;
932 end
933 if(fpudirty)
934 if(rg_fs==2'b0)begin
935 `ifdef verbose $display("Error: FPU id Dirty and FX field is 0"); `endif
936 end
937 `ifdef simulate
938 Bit#(64) dat=signExtend(res.aluresult);
939 `ifdef spfpu
940 if(rd_type==FloatingRF)
941 `ifdef dpfpu
942 $fwrite(dump," f%d",destination," 0x%16h",dat);
943 `else
944 $fwrite(dump," f%d",destination," 0x%16h",{32'hffffffff,dat[31:0]});
945 `endif
946 else
947 `endif
948 $fwrite(dump," x%d",destination," 0x%16h",dat);
949 $fwrite(dump,"\n");
950 `endif
951 end
952 return tuple4(flush,jump_address,destination_value, commit);
953 endmethod
954
955 method ActionValue#(Tuple2#(Bit#(`VADDR), Bool)) take_trap(Trap_type exception, Bit#(3) lv_debugcause, Bit#(`VADDR) pc, Bit#(`VADDR) badaddr)if(!rg_initialize[1]);
956 Bit#(`VADDR) jump_address=0;
957 Bool flush=True;
958 if(exception matches tagged Exception .ex)begin
959 if(ex==Inst_addr_misaligned || ex==Inst_access_fault || ex==Inst_pagefault)
960 badaddr=pc;
961 else if(ex==Illegal_inst)
962 badaddr=0;
963 else if(ex!=Load_pagefault && ex!=Load_access_fault && ex!=Load_addr_misaligned && ex!=Store_addr_misaligned && ex!=Store_pagefault && ex!=Store_access_fault)
964 badaddr=0;
965 end
966 else
967 badaddr=0;
968 `ifdef verbose $display($time,"\tTrap Type: ",fshow(exception)," debugcause: %d",lv_debugcause," BaddAddr: %h",badaddr); `endif
969 `ifdef Debug
970 if(exception matches tagged Interrupt .in &&& in==DebugResume)begin
971 if(debugmode_active[0])begin
972 rg_prv<=unpack(debugprv);
973 debugmode_active[0]<=False;
974 jump_address=truncate(dpc);
975 end
976 end
977 else if(exception matches tagged Interrupt .in &&& in==DebugInterrupt)begin
978 debugmode_active[0]<=True;
979 if(!debugmode_active[0])begin
980 dpc<=pc;
981 debugcause<=lv_debugcause;
982 debugprv<=pack(rg_prv);
983 rg_prv<=Machine;
984 if(lv_debugcause==4)
985 rg_step_now<=False;
986 end
987 jump_address=truncate(debugentry);
988 end
989 else if(exception matches tagged Interrupt .in &&& in==DebugReset)begin
990 resetmode[0]<=True;
991 jump_address='h1000;
992 rg_prv<=Machine;
993 end
994 else if(!debugmode_active[0] && !resetmode[0])begin
995 `endif
996 Bit#(`Reg_width) cause = 0;
997 Bit #(TSub #(`Reg_width, 1)) cause_code = 0;
998 Bit #(1) cause_type = 0;
999 case (exception) matches
1000 tagged Interrupt .i: begin cause_type = 1; cause_code = zeroExtend(pack(i)); end
1001 tagged Exception .e: begin cause_type = 0; cause_code = zeroExtend(pack(e));
1002 `ifdef simulate if(e==Endsimulation) begin
1003 for(Integer i=0;i<=(`MHPMCOUNTEND-`MHPMCOUNTSTART);i=i+1)begin
1004 $display($time,"\tEVENT: %s",event_name(csr_mhpmevent[i])," : %d",csr_mhpmcounter[i][1]);
1005 end
1006 $finish(0) /*wr_endsimulation <=True*/ ;
1007 end
1008 `endif
1009 end
1010 endcase
1011 cause = {cause_type, cause_code};
1012 `ifdef MMU
1013 Bool delegToS = (pack(rg_prv) <= pack(Supervisor)) && (case (exception) matches
1014 tagged Exception .exceptionCause:begin (((csr_medeleg >> pack(exceptionCause)) & 1) != 0);end
1015 tagged Interrupt .interruptCause: (((csr_mideleg >> pack(interruptCause)) & 1) != 0);
1016 endcase);
1017 if(delegToS)begin
1018 //if(exception matches tagged Exception .ex)
1019 // if(ex==Inst_addr_misaligned || ex==Inst_access_fault || ex==Inst_pagefault || ex==Illegal_inst
1020 // || ex==Load_access_fault || ex==Load_addr_misaligned || ex==Load_pagefault
1021 // || ex==Store_addr_misaligned || ex==Store_access_fault || ex==Store_pagefault)
1022 csr_stval<=zeroExtend(badaddr);
1023 csr_sepc<=signExtend(pc);
1024 csr_scause<=cause;
1025 rg_spp <= pack(rg_prv)[0];
1026 rg_sie <=0;
1027 rg_spie <= rg_sie;//(case (rg_prv) User: rg_uie; Supervisor : rg_sie; endcase);
1028 jump_address=truncate(csr_stvec);
1029 rg_prv <= Supervisor;
1030 end
1031 else begin
1032 `endif
1033 rg_prv <= Machine;
1034 if(exception matches tagged Exception .ex)
1035 if(ex==Inst_addr_misaligned || ex==Inst_access_fault || ex==Inst_pagefault || ex==Illegal_inst
1036 || ex==Load_access_fault || ex==Load_addr_misaligned || ex==Load_pagefault
1037 || ex==Store_addr_misaligned || ex==Store_access_fault || ex==Store_pagefault)
1038 csr_mtval<=zeroExtend(badaddr);
1039 csr_mepc<=signExtend(pc);
1040 if(rg_mxl==1)
1041 csr_mcause<= zeroExtend({cause[63], cause[30:1]});
1042 else
1043 csr_mcause<=cause;
1044 rg_mie <= 0;
1045 rg_mpp <= pack(rg_prv);
1046 jump_address=truncate(csr_mtvec);
1047 rg_mpie <= rg_mie;//(case (rg_prv) User: rg_uie; `ifdef MMU Supervisor : rg_sie; `endif Machine: rg_mie; endcase);
1048 `ifdef MMU
1049 end
1050 `endif
1051
1052 `ifdef Debug
1053 end
1054 else begin
1055 flush=False;
1056 end
1057 `endif
1058 return tuple2(jump_address,flush);
1059 endmethod
1060 method Bit#(3) roundingmode if(!rg_initialize[1] `ifdef simulate && !wr_endsimulation `endif );
1061 return rg_frm;
1062 endmethod
1063 method Action set_external_interrupt(Tuple2#(Bool,Bool) ex_i) if(!rg_initialize[1] `ifdef simulate && !wr_endsimulation `endif );
1064 let {i,j} = ex_i;
1065 rg_nmi <= j;
1066 if(rg_prv == Machine) begin
1067 `ifdef verbose $display("CSR : Machine external interrupt pending"); `endif
1068 rg_meip <= pack(i);
1069 end
1070 else if(rg_prv == Supervisor) begin
1071 rg_seipe <= pack(i);
1072 end
1073 else if(rg_prv == User) begin
1074 rg_ueipe <= pack(i);
1075 end
1076 endmethod
1077 method Action flush;
1078 rg_initialize[0]<=True;
1079 endmethod
1080 `ifdef MMU
1081 method Bit#(`Reg_width) send_satp;
1082 return csr_satp;
1083 endmethod
1084 method Chmod perm_to_TLB;
1085 return Chmod {mprv : rg_mprv, sum : rg_sum, mxr : rg_mxr, mpp : unpack(rg_mpp), prv : rg_prv};
1086 endmethod
1087 `endif
1088 method Bit#(`Reg_width) mmu_cache_disable;
1089 return csr_memse;
1090 endmethod
1091 `ifdef Debug
1092 method Bool halted;
1093 return debugmode_active[1];
1094 endmethod
1095 method load_triggerdata=loadtrigger;
1096 method store_triggerdata=storetrigger;
1097 method ActionValue#(Bit#(`Reg_width)) rw_debug_csr(Bit#(12) r, Bool write, Bit#(`Reg_width) data) if(!rg_initialize[1]);
1098 let y=read_csr(r);
1099 if(write)
1100 y<=data;
1101 return y._read;
1102 endmethod
1103 method Bool step_now=rg_step_now;
1104 method Bool reset_mode=resetmode[1];
1105 `endif
1106 method Bit#(`Reg_width) misa=csr_misa._read;
1107 method Action boot_sequence(Bit#(1) bootseq);
1108 rg_boot_seq<=bootseq;
1109 endmethod
1110 method Bit#(2) powercontrol=power_control_out;
1111 method Action poweracknowledge(Bit#(2) pa);
1112 power_control_in<=pa;
1113 endmethod
1114 `ifdef CLINT
1115 method Action clint_msip(Bit#(1) intrpt);
1116 rg_msip<=intrpt;
1117 endmethod
1118 method Action clint_mtip(Bit#(1) intrpt);
1119 rg_mtip<=intrpt;
1120 endmethod
1121 method Action clint_mtime(Bit#(`Reg_width) c_mtime);
1122 rg_clint_mtime<=c_mtime;
1123 endmethod
1124 `endif
1125 method inferred_xlen=rg_mxl;
1126
1127 endmodule
1128 endpackage
1129