-
Notifications
You must be signed in to change notification settings - Fork 719
/
Copy pathcsr_regfile.sv
2784 lines (2686 loc) · 114 KB
/
csr_regfile.sv
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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
// Copyright 2018 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
// CONDITIONS OF ANY KIND, either express or implied. See the License for the
// specific language governing permissions and limitations under the License.
//
// Author: Florian Zaruba, ETH Zurich
// Date: 05.05.2017
// Description: CSR Register File as specified by RISC-V
module csr_regfile
import ariane_pkg::*;
#(
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty,
parameter type exception_t = logic,
parameter type jvt_t = logic,
parameter type irq_ctrl_t = logic,
parameter type scoreboard_entry_t = logic,
parameter type rvfi_probes_csr_t = logic,
parameter int VmidWidth = 1,
parameter int unsigned MHPMCounterNum = 6
) (
// Subsystem Clock - SUBSYSTEM
input logic clk_i,
// Asynchronous reset active low - SUBSYSTEM
input logic rst_ni,
// Timer threw a interrupt - SUBSYSTEM
input logic time_irq_i,
// send a flush request out when a CSR with a side effect changes - CONTROLLER
output logic flush_o,
// halt requested - CONTROLLER
output logic halt_csr_o,
// Instruction to be committed - ID_STAGE
input scoreboard_entry_t commit_instr_i,
// Commit acknowledged a instruction -> increase instret CSR - COMMIT_STAGE
input logic [CVA6Cfg.NrCommitPorts-1:0] commit_ack_i,
// Address from which to start booting, mtvec is set to the same address - SUBSYSTEM
input logic [CVA6Cfg.VLEN-1:0] boot_addr_i,
// Hart id in a multicore environment (reflected in a CSR) - SUBSYSTEM
input logic [CVA6Cfg.XLEN-1:0] hart_id_i,
// We've got an exception from the commit stage, take it - COMMIT_STAGE
input exception_t ex_i,
// Operation to perform on the CSR file - COMMIT_STAGE
input fu_op csr_op_i,
// Address of the register to read/write - EX_STAGE
input logic [11:0] csr_addr_i,
// Write data in - COMMIT_STAGE
input logic [CVA6Cfg.XLEN-1:0] csr_wdata_i,
// Read data out - COMMIT_STAGE
output logic [CVA6Cfg.XLEN-1:0] csr_rdata_o,
// Mark the FP sate as dirty - COMMIT_STAGE
input logic dirty_fp_state_i,
// Write fflags register e.g.: we are retiring a floating point instruction - COMMIT_STAGE
input logic csr_write_fflags_i,
// Mark the V state as dirty - ACC_DISPATCHER
input logic dirty_v_state_i,
// PC of instruction accessing the CSR - COMMIT_STAGE
input logic [CVA6Cfg.VLEN-1:0] pc_i,
// attempts to access a CSR without appropriate privilege - COMMIT_STAGE
output exception_t csr_exception_o,
// Output the exception PC to PC Gen, the correct CSR (mepc, sepc) is set accordingly - FRONTEND
output logic [CVA6Cfg.VLEN-1:0] epc_o,
// Return from exception, set the PC of epc_o - FRONTEND
output logic eret_o,
// Output base of exception vector, correct CSR is output (mtvec, stvec) - FRONTEND
output logic [CVA6Cfg.VLEN-1:0] trap_vector_base_o,
// Current privilege level the CPU is in - EX_STAGE
output riscv::priv_lvl_t priv_lvl_o,
// Current virtualization mode state the CPU is in - EX_STAGE
output logic v_o,
// Imprecise FP exception from the accelerator (fcsr.fflags format) - ACC_DISPATCHER
input logic [4:0] acc_fflags_ex_i,
// An FP exception from the accelerator occurred - ACC_DISPATCHER
input logic acc_fflags_ex_valid_i,
// Floating point extension status - ID_STAGE
output riscv::xs_t fs_o,
// Floating point extension virtual status - ID_STAGE
output riscv::xs_t vfs_o,
// Floating-Point Accured Exceptions - COMMIT_STAGE
output logic [4:0] fflags_o,
// Floating-Point Dynamic Rounding Mode - EX_STAGE
output logic [2:0] frm_o,
// Floating-Point Precision Control - EX_STAGE
output logic [6:0] fprec_o,
// Vector extension status - ID_STAGE
output riscv::xs_t vs_o,
// interrupt management to id stage - ID_STAGE
output irq_ctrl_t irq_ctrl_o,
// Enable virtual address translation - EX_STAGE
output logic en_translation_o,
// Enable G-Stage address translation - EX_STAGE
output logic en_g_translation_o,
// Enable virtual address translation for load and stores - EX_STAGE
output logic en_ld_st_translation_o,
// Enable G-Stage address translation for load and stores - EX_STAGE
output logic en_ld_st_g_translation_o,
// Privilege level at which load and stores should happen - EX_STAGE
output riscv::priv_lvl_t ld_st_priv_lvl_o,
// Virtualization mode at which load and stores should happen - EX_STAGE
output logic ld_st_v_o,
// Current instruction is a Hypervisor Load/Store Instruction - EX_STAGE
input logic csr_hs_ld_st_inst_i,
// Supervisor User Memory - EX_STAGE
output logic sum_o,
// Virtual Supervisor User Memory - EX_STAGE
output logic vs_sum_o,
// Make Executable Readable - EX_STAGE
output logic mxr_o,
// Make Executable Readable for VS-mode - EX_STAGE
output logic vmxr_o,
// TO_BE_COMPLETED - EX_STAGE
output logic [CVA6Cfg.PPNW-1:0] satp_ppn_o,
// TO_BE_COMPLETED - EX_STAGE
output logic [CVA6Cfg.ASID_WIDTH-1:0] asid_o,
// TO_BE_COMPLETED - EX_STAGE
output logic [CVA6Cfg.PPNW-1:0] vsatp_ppn_o,
// TO_BE_COMPLETED - EX_STAGE
output logic [CVA6Cfg.ASID_WIDTH-1:0] vs_asid_o,
// TO_BE_COMPLETED - EX_STAGE
output logic [CVA6Cfg.PPNW-1:0] hgatp_ppn_o,
// TO_BE_COMPLETED - EX_STAGE
output logic [CVA6Cfg.VMID_WIDTH-1:0] vmid_o,
// external interrupt in - SUBSYSTEM
input logic [1:0] irq_i,
// inter processor interrupt -> connected to machine mode sw - SUBSYSTEM
input logic ipi_i,
// debug request in - ID_STAGE
input logic debug_req_i,
// TO_BE_COMPLETED - FRONTEND
output logic set_debug_pc_o,
// trap virtual memory - ID_STAGE
output logic tvm_o,
// timeout wait - ID_STAGE
output logic tw_o,
// virtual timeout wait - ID_STAGE
output logic vtw_o,
// trap sret - ID_STAGE
output logic tsr_o,
// hypervisor user mode - ID_STAGE
output logic hu_o,
// we are in debug mode -> that will change some decoding - EX_STAGE
output logic debug_mode_o,
// we are in single-step mode - COMMIT_STAGE
output logic single_step_o,
// L1 ICache Enable - CACHE
output logic icache_en_o,
// L1 DCache Enable - CACHE
output logic dcache_en_o,
// Accelerator memory consistent mode - ACC_DISPATCHER
output logic acc_cons_en_o,
// read/write address to performance counter module - PERF_COUNTERS
output logic [11:0] perf_addr_o,
// write data to performance counter module - PERF_COUNTERS
output logic [CVA6Cfg.XLEN-1:0] perf_data_o,
// read data from performance counter module - PERF_COUNTERS
input logic [CVA6Cfg.XLEN-1:0] perf_data_i,
// TO_BE_COMPLETED - PERF_COUNTERS
output logic perf_we_o,
// PMP configuration containing pmpcfg for max 64 PMPs - ACC_DISPATCHER
output riscv::pmpcfg_t [(CVA6Cfg.NrPMPEntries > 0 ? CVA6Cfg.NrPMPEntries-1 : 0):0] pmpcfg_o,
// PMP addresses - ACC_DISPATCHER
output logic [(CVA6Cfg.NrPMPEntries > 0 ? CVA6Cfg.NrPMPEntries-1 : 0):0][CVA6Cfg.PLEN-3:0] pmpaddr_o,
// TO_BE_COMPLETED - PERF_COUNTERS
output logic [31:0] mcountinhibit_o,
// RVFI
output rvfi_probes_csr_t rvfi_csr_o,
//jvt output
output jvt_t jvt_o
);
localparam logic [63:0] SMODE_STATUS_READ_MASK = ariane_pkg::smode_status_read_mask(CVA6Cfg);
localparam logic [63:0] HS_DELEG_INTERRUPTS = {
{32{1'b0}}, ariane_pkg::hs_deleg_interrupts(CVA6Cfg)
};
localparam logic [63:0] VS_DELEG_INTERRUPTS = {
{32{1'b0}}, ariane_pkg::vs_deleg_interrupts(CVA6Cfg)
};
localparam int SELECT_COUNTER_WIDTH = CVA6Cfg.IS_XLEN64 ? 6 : 5;
typedef struct packed {
logic [CVA6Cfg.ModeW-1:0] mode;
logic [CVA6Cfg.ASIDW-1:0] asid;
logic [CVA6Cfg.PPNW-1:0] ppn;
} satp_t;
typedef struct packed {
logic [CVA6Cfg.ModeW-1:0] mode;
logic [1:0] warl0;
logic [CVA6Cfg.VMIDW-1:0] vmid;
logic [CVA6Cfg.PPNW-1:0] ppn;
} hgatp_t;
// internal signal to keep track of access exceptions
logic read_access_exception, update_access_exception, privilege_violation;
logic virtual_read_access_exception, virtual_update_access_exception, virtual_privilege_violation;
logic csr_we, csr_read;
logic [CVA6Cfg.XLEN-1:0] csr_wdata, csr_rdata;
riscv::priv_lvl_t trap_to_priv_lvl;
logic trap_to_v;
// register for enabling load store address translation, this is critical, hence the register
logic en_ld_st_translation_d, en_ld_st_translation_q;
logic en_ld_st_g_translation_d, en_ld_st_g_translation_q;
logic mprv;
logic mret; // return from M-mode exception
logic sret; // return from S-mode exception
logic dret; // return from debug mode
// CSR write causes us to mark the FPU state as dirty
logic dirty_fp_state_csr;
riscv::mstatus_rv_t mstatus_q, mstatus_d;
riscv::hstatus_rv_t hstatus_q, hstatus_d;
riscv::mstatus_rv_t vsstatus_q, vsstatus_d;
logic [CVA6Cfg.XLEN-1:0] mstatus_extended;
logic [CVA6Cfg.XLEN-1:0] vsstatus_extended;
satp_t satp_q, satp_d;
satp_t vsatp_q, vsatp_d;
hgatp_t hgatp_q, hgatp_d;
riscv::dcsr_t dcsr_q, dcsr_d;
riscv::csr_t csr_addr;
riscv::csr_t conv_csr_addr;
// privilege level register
riscv::priv_lvl_t priv_lvl_d, priv_lvl_q;
logic v_q, v_d; // virtualization mode
// we are in debug
logic debug_mode_q, debug_mode_d;
logic mtvec_rst_load_q; // used to determine whether we came out of reset
logic [CVA6Cfg.XLEN-1:0] dpc_q, dpc_d;
logic [CVA6Cfg.XLEN-1:0] dscratch0_q, dscratch0_d;
logic [CVA6Cfg.XLEN-1:0] dscratch1_q, dscratch1_d;
logic [CVA6Cfg.XLEN-1:0] mtvec_q, mtvec_d;
logic [CVA6Cfg.XLEN-1:0] medeleg_q, medeleg_d;
logic [CVA6Cfg.XLEN-1:0] mideleg_q, mideleg_d;
logic [CVA6Cfg.XLEN-1:0] mip_q, mip_d;
logic [CVA6Cfg.XLEN-1:0] mie_q, mie_d;
logic [CVA6Cfg.XLEN-1:0] mcounteren_q, mcounteren_d;
logic [CVA6Cfg.XLEN-1:0] mscratch_q, mscratch_d;
logic [CVA6Cfg.XLEN-1:0] mepc_q, mepc_d;
logic [CVA6Cfg.XLEN-1:0] mcause_q, mcause_d;
logic [CVA6Cfg.XLEN-1:0] mtval_q, mtval_d;
logic [CVA6Cfg.XLEN-1:0] mtinst_q, mtinst_d;
logic [CVA6Cfg.XLEN-1:0] mtval2_q, mtval2_d;
logic fiom_d, fiom_q;
logic [CVA6Cfg.XLEN-1:0] stvec_q, stvec_d;
logic [CVA6Cfg.XLEN-1:0] scounteren_q, scounteren_d;
logic [CVA6Cfg.XLEN-1:0] sscratch_q, sscratch_d;
logic [CVA6Cfg.XLEN-1:0] sepc_q, sepc_d;
logic [CVA6Cfg.XLEN-1:0] scause_q, scause_d;
logic [CVA6Cfg.XLEN-1:0] stval_q, stval_d;
logic [CVA6Cfg.XLEN-1:0] hedeleg_q, hedeleg_d;
logic [CVA6Cfg.XLEN-1:0] hideleg_q, hideleg_d;
logic [CVA6Cfg.XLEN-1:0] hcounteren_q, hcounteren_d;
logic [CVA6Cfg.XLEN-1:0] hgeie_q, hgeie_d;
logic [CVA6Cfg.XLEN-1:0] htinst_q, htinst_d;
logic [CVA6Cfg.XLEN-1:0] htval_q, htval_d;
logic [CVA6Cfg.XLEN-1:0] vstvec_q, vstvec_d;
logic [CVA6Cfg.XLEN-1:0] vsscratch_q, vsscratch_d;
logic [CVA6Cfg.XLEN-1:0] vsepc_q, vsepc_d;
logic [CVA6Cfg.XLEN-1:0] vscause_q, vscause_d;
logic [CVA6Cfg.XLEN-1:0] vstval_q, vstval_d;
logic [CVA6Cfg.XLEN-1:0] dcache_q, dcache_d;
logic [CVA6Cfg.XLEN-1:0] icache_q, icache_d;
logic [CVA6Cfg.XLEN-1:0] acc_cons_q, acc_cons_d;
logic wfi_d, wfi_q;
logic [63:0] cycle_q, cycle_d;
logic [63:0] instret_q, instret_d;
riscv::pmpcfg_t [63:0] pmpcfg_q, pmpcfg_d, pmpcfg_next;
logic [63:0][CVA6Cfg.PLEN-3:0] pmpaddr_q, pmpaddr_d, pmpaddr_next;
logic [MHPMCounterNum+3-1:0] mcountinhibit_d, mcountinhibit_q;
localparam logic [CVA6Cfg.XLEN-1:0] IsaCode = (CVA6Cfg.XLEN'(CVA6Cfg.RVA) << 0) // A - Atomic Instructions extension
| (CVA6Cfg.XLEN'(CVA6Cfg.RVB) << 1) // B - Bitmanip extension
| (CVA6Cfg.XLEN'(CVA6Cfg.RVC) << 2) // C - Compressed extension
| (CVA6Cfg.XLEN'(CVA6Cfg.RVD) << 3) // D - Double precision floating-point extension
| (CVA6Cfg.XLEN'(CVA6Cfg.RVF) << 5) // F - Single precision floating-point extension
| (CVA6Cfg.XLEN'(CVA6Cfg.RVH) << 7) // H - Hypervisor extension
| (CVA6Cfg.XLEN'(1) << 8) // I - RV32I/64I/128I base ISA
| (CVA6Cfg.XLEN'(1) << 12) // M - Integer Multiply/Divide extension
| (CVA6Cfg.XLEN'(0) << 13) // N - User level interrupts supported
| (CVA6Cfg.XLEN'(CVA6Cfg.RVS) << 18) // S - Supervisor mode implemented
| (CVA6Cfg.XLEN'(CVA6Cfg.RVU) << 20) // U - User mode implemented
| (CVA6Cfg.XLEN'(CVA6Cfg.RVV) << 21) // V - Vector extension
| (CVA6Cfg.XLEN'(CVA6Cfg.NSX) << 23) // X - Non-standard extensions present
| ((CVA6Cfg.XLEN == 64 ? 2 : 1) << CVA6Cfg.XLEN - 2); // MXL
assign pmpcfg_o = pmpcfg_q[(CVA6Cfg.NrPMPEntries>0?CVA6Cfg.NrPMPEntries-1 : 0):0];
assign pmpaddr_o = pmpaddr_q[(CVA6Cfg.NrPMPEntries>0?CVA6Cfg.NrPMPEntries-1 : 0):0];
riscv::fcsr_t fcsr_q, fcsr_d;
jvt_t jvt_q, jvt_d;
// ----------------
// Assignments
// ----------------
assign csr_addr = riscv::csr_t'(csr_addr_i);
assign conv_csr_addr = (CVA6Cfg.RVH) ? riscv::convert_vs_access_csr(
(riscv::csr_t'(csr_addr_i)), v_q
) : csr_addr;
assign fs_o = mstatus_q.fs;
assign vfs_o = (CVA6Cfg.RVH) ? vsstatus_q.fs : riscv::Off;
assign vs_o = mstatus_q.vs;
// ----------------
// CSR Read logic
// ----------------
assign mstatus_extended = CVA6Cfg.IS_XLEN64 ? mstatus_q[CVA6Cfg.XLEN-1:0] :
{mstatus_q.sd, mstatus_q.wpri3[7:0], mstatus_q[22:0]};
if (CVA6Cfg.RVH) begin
if (CVA6Cfg.IS_XLEN64) begin : gen_vsstatus_64read
assign vsstatus_extended = vsstatus_q[CVA6Cfg.XLEN-1:0];
end else begin : gen_vsstatus_32read
assign vsstatus_extended = {vsstatus_q.sd, vsstatus_q.wpri3[7:0], vsstatus_q[22:0]};
end
end else begin
assign vsstatus_extended = '0;
end
always_comb begin : csr_read_process
// a read access exception can only occur if we attempt to read a CSR which does not exist
read_access_exception = 1'b0;
virtual_read_access_exception = 1'b0;
csr_rdata = '0;
perf_addr_o = csr_addr.address[11:0];
if (csr_read) begin
unique case (conv_csr_addr.address)
riscv::CSR_FFLAGS: begin
if (CVA6Cfg.FpPresent && !(mstatus_q.fs == riscv::Off || (CVA6Cfg.RVH && v_q && vsstatus_q.fs == riscv::Off))) begin
csr_rdata = {{CVA6Cfg.XLEN - 5{1'b0}}, fcsr_q.fflags};
end else begin
read_access_exception = 1'b1;
end
end
riscv::CSR_FRM: begin
if (CVA6Cfg.FpPresent && !(mstatus_q.fs == riscv::Off || (CVA6Cfg.RVH && v_q && vsstatus_q.fs == riscv::Off))) begin
csr_rdata = {{CVA6Cfg.XLEN - 3{1'b0}}, fcsr_q.frm};
end else begin
read_access_exception = 1'b1;
end
end
riscv::CSR_FCSR: begin
if (CVA6Cfg.FpPresent && !(mstatus_q.fs == riscv::Off || (CVA6Cfg.RVH && v_q && vsstatus_q.fs == riscv::Off))) begin
csr_rdata = {{CVA6Cfg.XLEN - 8{1'b0}}, fcsr_q.frm, fcsr_q.fflags};
end else begin
read_access_exception = 1'b1;
end
end
riscv::CSR_JVT: begin
if (CVA6Cfg.RVZCMT) begin
csr_rdata = {jvt_q.base, jvt_q.mode};
end else begin
read_access_exception = 1'b1;
end
end
// non-standard extension
riscv::CSR_FTRAN: begin
if (CVA6Cfg.FpPresent && !(mstatus_q.fs == riscv::Off || (CVA6Cfg.RVH && v_q && vsstatus_q.fs == riscv::Off))) begin
csr_rdata = {{CVA6Cfg.XLEN - 7{1'b0}}, fcsr_q.fprec};
end else begin
read_access_exception = 1'b1;
end
end
// debug registers
riscv::CSR_DCSR:
if (CVA6Cfg.DebugEn) csr_rdata = {{CVA6Cfg.XLEN - 32{1'b0}}, dcsr_q};
else read_access_exception = 1'b1;
riscv::CSR_DPC:
if (CVA6Cfg.DebugEn) csr_rdata = dpc_q;
else read_access_exception = 1'b1;
riscv::CSR_DSCRATCH0:
if (CVA6Cfg.DebugEn) csr_rdata = dscratch0_q;
else read_access_exception = 1'b1;
riscv::CSR_DSCRATCH1:
if (CVA6Cfg.DebugEn) csr_rdata = dscratch1_q;
else read_access_exception = 1'b1;
// trigger module registers
riscv::CSR_TSELECT: read_access_exception = 1'b1; // not implemented
riscv::CSR_TDATA1: read_access_exception = 1'b1; // not implemented
riscv::CSR_TDATA2: read_access_exception = 1'b1; // not implemented
riscv::CSR_TDATA3: read_access_exception = 1'b1; // not implemented
riscv::CSR_VSSTATUS:
if (CVA6Cfg.RVH) csr_rdata = vsstatus_extended;
else read_access_exception = 1'b1;
riscv::CSR_VSIE:
if (CVA6Cfg.RVH)
csr_rdata = (mie_q & VS_DELEG_INTERRUPTS[CVA6Cfg.XLEN-1:0] & hideleg_q) >> 1;
else read_access_exception = 1'b1;
riscv::CSR_VSIP:
if (CVA6Cfg.RVH)
csr_rdata = (mip_q & VS_DELEG_INTERRUPTS[CVA6Cfg.XLEN-1:0] & hideleg_q) >> 1;
else read_access_exception = 1'b1;
riscv::CSR_VSTVEC:
if (CVA6Cfg.RVH) csr_rdata = vstvec_q;
else read_access_exception = 1'b1;
riscv::CSR_VSSCRATCH:
if (CVA6Cfg.RVH) csr_rdata = vsscratch_q;
else read_access_exception = 1'b1;
riscv::CSR_VSEPC:
if (CVA6Cfg.RVH) csr_rdata = vsepc_q;
else read_access_exception = 1'b1;
riscv::CSR_VSCAUSE:
if (CVA6Cfg.RVH) csr_rdata = vscause_q;
else read_access_exception = 1'b1;
riscv::CSR_VSTVAL:
if (CVA6Cfg.RVH) csr_rdata = vstval_q;
else read_access_exception = 1'b1;
riscv::CSR_VSATP:
// intercept reads to VSATP if in VS-Mode and VTVM is enabled
if (CVA6Cfg.RVH) begin
if (priv_lvl_o == riscv::PRIV_LVL_S && hstatus_q.vtvm && v_q)
virtual_read_access_exception = 1'b1;
else csr_rdata = vsatp_q;
end else begin
read_access_exception = 1'b1;
end
// supervisor registers
riscv::CSR_SSTATUS: begin
if (CVA6Cfg.RVS) csr_rdata = mstatus_extended & SMODE_STATUS_READ_MASK[CVA6Cfg.XLEN-1:0];
else read_access_exception = 1'b1;
end
riscv::CSR_SIE:
if (CVA6Cfg.RVS)
csr_rdata = (CVA6Cfg.RVH) ? mie_q & mideleg_q & ~HS_DELEG_INTERRUPTS[CVA6Cfg.XLEN-1:0] : mie_q & mideleg_q;
else read_access_exception = 1'b1;
riscv::CSR_SIP:
if (CVA6Cfg.RVS)
csr_rdata = (CVA6Cfg.RVH) ? mip_q & mideleg_q & ~HS_DELEG_INTERRUPTS[CVA6Cfg.XLEN-1:0] : mip_q & mideleg_q;
else read_access_exception = 1'b1;
riscv::CSR_STVEC:
if (CVA6Cfg.RVS) csr_rdata = stvec_q;
else read_access_exception = 1'b1;
riscv::CSR_SCOUNTEREN:
if (CVA6Cfg.RVS) csr_rdata = scounteren_q;
else read_access_exception = 1'b1;
riscv::CSR_SSCRATCH:
if (CVA6Cfg.RVS) csr_rdata = sscratch_q;
else read_access_exception = 1'b1;
riscv::CSR_SEPC:
if (CVA6Cfg.RVS) csr_rdata = sepc_q;
else read_access_exception = 1'b1;
riscv::CSR_SCAUSE:
if (CVA6Cfg.RVS) csr_rdata = scause_q;
else read_access_exception = 1'b1;
riscv::CSR_STVAL:
if (CVA6Cfg.RVS) csr_rdata = stval_q;
else read_access_exception = 1'b1;
riscv::CSR_SATP: begin
if (CVA6Cfg.RVS) begin
// intercept reads to SATP if in S-Mode and TVM is enabled
if (priv_lvl_o == riscv::PRIV_LVL_S && mstatus_q.tvm) begin
read_access_exception = 1'b1;
end else begin
csr_rdata = satp_q;
end
end else begin
read_access_exception = 1'b1;
end
end
riscv::CSR_SENVCFG:
if (CVA6Cfg.RVS) csr_rdata = '0 | fiom_q;
else read_access_exception = 1'b1;
// hypervisor mode registers
riscv::CSR_HSTATUS:
if (CVA6Cfg.RVH) csr_rdata = hstatus_q[CVA6Cfg.XLEN-1:0];
else read_access_exception = 1'b1;
riscv::CSR_HEDELEG:
if (CVA6Cfg.RVH) csr_rdata = hedeleg_q;
else read_access_exception = 1'b1;
riscv::CSR_HIDELEG:
if (CVA6Cfg.RVH) csr_rdata = hideleg_q;
else read_access_exception = 1'b1;
riscv::CSR_HIE:
if (CVA6Cfg.RVH) csr_rdata = mie_q & HS_DELEG_INTERRUPTS[CVA6Cfg.XLEN-1:0];
else read_access_exception = 1'b1;
riscv::CSR_HIP:
if (CVA6Cfg.RVH) csr_rdata = mip_q & HS_DELEG_INTERRUPTS[CVA6Cfg.XLEN-1:0];
else read_access_exception = 1'b1;
riscv::CSR_HVIP:
if (CVA6Cfg.RVH) csr_rdata = mip_q & VS_DELEG_INTERRUPTS[CVA6Cfg.XLEN-1:0];
else read_access_exception = 1'b1;
riscv::CSR_HCOUNTEREN:
if (CVA6Cfg.RVH) csr_rdata = hcounteren_q;
else read_access_exception = 1'b1;
riscv::CSR_HTVAL:
if (CVA6Cfg.RVH) csr_rdata = htval_q;
else read_access_exception = 1'b1;
riscv::CSR_HTINST:
if (CVA6Cfg.RVH) csr_rdata = htinst_q;
else read_access_exception = 1'b1;
riscv::CSR_HGEIE:
if (CVA6Cfg.RVH) csr_rdata = '0;
else read_access_exception = 1'b1;
riscv::CSR_HGEIP:
if (CVA6Cfg.RVH) csr_rdata = '0;
else read_access_exception = 1'b1;
riscv::CSR_HENVCFG:
if (CVA6Cfg.RVH) csr_rdata = '0 | {{CVA6Cfg.XLEN - 1{1'b0}}, fiom_q};
else read_access_exception = 1'b1;
riscv::CSR_HGATP: begin
if (CVA6Cfg.RVH) begin
// intercept reads to HGATP if in HS-Mode and TVM is enabled
if (priv_lvl_o == riscv::PRIV_LVL_S && !v_q && mstatus_q.tvm) begin
read_access_exception = 1'b1;
end else begin
csr_rdata = hgatp_q;
end
end else begin
read_access_exception = 1'b1;
end
end
// machine mode registers
riscv::CSR_MSTATUS: csr_rdata = mstatus_extended;
riscv::CSR_MSTATUSH:
if (CVA6Cfg.XLEN == 32) csr_rdata = '0;
else read_access_exception = 1'b1;
riscv::CSR_MISA: csr_rdata = IsaCode;
riscv::CSR_MEDELEG:
if (CVA6Cfg.RVS) csr_rdata = medeleg_q;
else read_access_exception = 1'b1;
riscv::CSR_MIDELEG:
if (CVA6Cfg.RVS) csr_rdata = mideleg_q;
else read_access_exception = 1'b1;
riscv::CSR_MIE: csr_rdata = mie_q;
riscv::CSR_MTVEC: csr_rdata = mtvec_q;
riscv::CSR_MCOUNTEREN:
if (CVA6Cfg.RVU) csr_rdata = mcounteren_q;
else read_access_exception = 1'b1;
riscv::CSR_MSCRATCH: csr_rdata = mscratch_q;
riscv::CSR_MEPC: csr_rdata = mepc_q;
riscv::CSR_MCAUSE: csr_rdata = mcause_q;
riscv::CSR_MTVAL:
if (CVA6Cfg.TvalEn) csr_rdata = mtval_q;
else csr_rdata = '0;
riscv::CSR_MTINST:
if (CVA6Cfg.RVH) csr_rdata = mtinst_q;
else read_access_exception = 1'b1;
riscv::CSR_MTVAL2:
if (CVA6Cfg.RVH) csr_rdata = mtval2_q;
else read_access_exception = 1'b1;
riscv::CSR_MIP: csr_rdata = mip_q;
riscv::CSR_MENVCFG: begin
if (CVA6Cfg.RVU) csr_rdata = '0 | fiom_q;
else read_access_exception = 1'b1;
end
riscv::CSR_MENVCFGH: begin
if (CVA6Cfg.RVU && CVA6Cfg.XLEN == 32) csr_rdata = '0;
else read_access_exception = 1'b1;
end
riscv::CSR_MVENDORID: csr_rdata = {{CVA6Cfg.XLEN - 32{1'b0}}, OPENHWGROUP_MVENDORID};
riscv::CSR_MARCHID: csr_rdata = {{CVA6Cfg.XLEN - 32{1'b0}}, ARIANE_MARCHID};
riscv::CSR_MIMPID: csr_rdata = '0; // not implemented
riscv::CSR_MHARTID: csr_rdata = hart_id_i;
riscv::CSR_MCONFIGPTR: csr_rdata = '0; // not implemented
riscv::CSR_MCOUNTINHIBIT:
csr_rdata = {{(CVA6Cfg.XLEN - (MHPMCounterNum + 3)) {1'b0}}, mcountinhibit_q};
// Counters and Timers
riscv::CSR_MCYCLE: csr_rdata = cycle_q[CVA6Cfg.XLEN-1:0];
riscv::CSR_MCYCLEH:
if (CVA6Cfg.XLEN == 32) csr_rdata = cycle_q[63:32];
else read_access_exception = 1'b1;
riscv::CSR_MINSTRET: csr_rdata = instret_q[CVA6Cfg.XLEN-1:0];
riscv::CSR_MINSTRETH:
if (CVA6Cfg.XLEN == 32) csr_rdata = instret_q[63:32];
else read_access_exception = 1'b1;
riscv::CSR_CYCLE:
if (CVA6Cfg.RVZicntr) csr_rdata = cycle_q[CVA6Cfg.XLEN-1:0];
else read_access_exception = 1'b1;
riscv::CSR_CYCLEH:
if (CVA6Cfg.RVZicntr)
if (CVA6Cfg.XLEN == 32) csr_rdata = cycle_q[63:32];
else read_access_exception = 1'b1;
else read_access_exception = 1'b1;
riscv::CSR_INSTRET:
if (CVA6Cfg.RVZicntr) csr_rdata = instret_q[CVA6Cfg.XLEN-1:0];
else read_access_exception = 1'b1;
riscv::CSR_INSTRETH:
if (CVA6Cfg.RVZicntr)
if (CVA6Cfg.XLEN == 32) csr_rdata = instret_q[63:32];
else read_access_exception = 1'b1;
else read_access_exception = 1'b1;
//Event Selector
riscv::CSR_MHPM_EVENT_3,
riscv::CSR_MHPM_EVENT_4,
riscv::CSR_MHPM_EVENT_5,
riscv::CSR_MHPM_EVENT_6,
riscv::CSR_MHPM_EVENT_7,
riscv::CSR_MHPM_EVENT_8,
riscv::CSR_MHPM_EVENT_9,
riscv::CSR_MHPM_EVENT_10,
riscv::CSR_MHPM_EVENT_11,
riscv::CSR_MHPM_EVENT_12,
riscv::CSR_MHPM_EVENT_13,
riscv::CSR_MHPM_EVENT_14,
riscv::CSR_MHPM_EVENT_15,
riscv::CSR_MHPM_EVENT_16,
riscv::CSR_MHPM_EVENT_17,
riscv::CSR_MHPM_EVENT_18,
riscv::CSR_MHPM_EVENT_19,
riscv::CSR_MHPM_EVENT_20,
riscv::CSR_MHPM_EVENT_21,
riscv::CSR_MHPM_EVENT_22,
riscv::CSR_MHPM_EVENT_23,
riscv::CSR_MHPM_EVENT_24,
riscv::CSR_MHPM_EVENT_25,
riscv::CSR_MHPM_EVENT_26,
riscv::CSR_MHPM_EVENT_27,
riscv::CSR_MHPM_EVENT_28,
riscv::CSR_MHPM_EVENT_29,
riscv::CSR_MHPM_EVENT_30,
riscv::CSR_MHPM_EVENT_31 :
csr_rdata = perf_data_i;
riscv::CSR_MHPM_COUNTER_3,
riscv::CSR_MHPM_COUNTER_4,
riscv::CSR_MHPM_COUNTER_5,
riscv::CSR_MHPM_COUNTER_6,
riscv::CSR_MHPM_COUNTER_7,
riscv::CSR_MHPM_COUNTER_8,
riscv::CSR_MHPM_COUNTER_9,
riscv::CSR_MHPM_COUNTER_10,
riscv::CSR_MHPM_COUNTER_11,
riscv::CSR_MHPM_COUNTER_12,
riscv::CSR_MHPM_COUNTER_13,
riscv::CSR_MHPM_COUNTER_14,
riscv::CSR_MHPM_COUNTER_15,
riscv::CSR_MHPM_COUNTER_16,
riscv::CSR_MHPM_COUNTER_17,
riscv::CSR_MHPM_COUNTER_18,
riscv::CSR_MHPM_COUNTER_19,
riscv::CSR_MHPM_COUNTER_20,
riscv::CSR_MHPM_COUNTER_21,
riscv::CSR_MHPM_COUNTER_22,
riscv::CSR_MHPM_COUNTER_23,
riscv::CSR_MHPM_COUNTER_24,
riscv::CSR_MHPM_COUNTER_25,
riscv::CSR_MHPM_COUNTER_26,
riscv::CSR_MHPM_COUNTER_27,
riscv::CSR_MHPM_COUNTER_28,
riscv::CSR_MHPM_COUNTER_29,
riscv::CSR_MHPM_COUNTER_30,
riscv::CSR_MHPM_COUNTER_31 :
csr_rdata = perf_data_i;
riscv::CSR_MHPM_COUNTER_3H,
riscv::CSR_MHPM_COUNTER_4H,
riscv::CSR_MHPM_COUNTER_5H,
riscv::CSR_MHPM_COUNTER_6H,
riscv::CSR_MHPM_COUNTER_7H,
riscv::CSR_MHPM_COUNTER_8H,
riscv::CSR_MHPM_COUNTER_9H,
riscv::CSR_MHPM_COUNTER_10H,
riscv::CSR_MHPM_COUNTER_11H,
riscv::CSR_MHPM_COUNTER_12H,
riscv::CSR_MHPM_COUNTER_13H,
riscv::CSR_MHPM_COUNTER_14H,
riscv::CSR_MHPM_COUNTER_15H,
riscv::CSR_MHPM_COUNTER_16H,
riscv::CSR_MHPM_COUNTER_17H,
riscv::CSR_MHPM_COUNTER_18H,
riscv::CSR_MHPM_COUNTER_19H,
riscv::CSR_MHPM_COUNTER_20H,
riscv::CSR_MHPM_COUNTER_21H,
riscv::CSR_MHPM_COUNTER_22H,
riscv::CSR_MHPM_COUNTER_23H,
riscv::CSR_MHPM_COUNTER_24H,
riscv::CSR_MHPM_COUNTER_25H,
riscv::CSR_MHPM_COUNTER_26H,
riscv::CSR_MHPM_COUNTER_27H,
riscv::CSR_MHPM_COUNTER_28H,
riscv::CSR_MHPM_COUNTER_29H,
riscv::CSR_MHPM_COUNTER_30H,
riscv::CSR_MHPM_COUNTER_31H :
if (CVA6Cfg.XLEN == 32) csr_rdata = perf_data_i;
else read_access_exception = 1'b1;
// Performance counters (User Mode - R/O Shadows)
riscv::CSR_HPM_COUNTER_3,
riscv::CSR_HPM_COUNTER_4,
riscv::CSR_HPM_COUNTER_5,
riscv::CSR_HPM_COUNTER_6,
riscv::CSR_HPM_COUNTER_7,
riscv::CSR_HPM_COUNTER_8,
riscv::CSR_HPM_COUNTER_9,
riscv::CSR_HPM_COUNTER_10,
riscv::CSR_HPM_COUNTER_11,
riscv::CSR_HPM_COUNTER_12,
riscv::CSR_HPM_COUNTER_13,
riscv::CSR_HPM_COUNTER_14,
riscv::CSR_HPM_COUNTER_15,
riscv::CSR_HPM_COUNTER_16,
riscv::CSR_HPM_COUNTER_17,
riscv::CSR_HPM_COUNTER_18,
riscv::CSR_HPM_COUNTER_19,
riscv::CSR_HPM_COUNTER_20,
riscv::CSR_HPM_COUNTER_21,
riscv::CSR_HPM_COUNTER_22,
riscv::CSR_HPM_COUNTER_23,
riscv::CSR_HPM_COUNTER_24,
riscv::CSR_HPM_COUNTER_25,
riscv::CSR_HPM_COUNTER_26,
riscv::CSR_HPM_COUNTER_27,
riscv::CSR_HPM_COUNTER_28,
riscv::CSR_HPM_COUNTER_29,
riscv::CSR_HPM_COUNTER_30,
riscv::CSR_HPM_COUNTER_31 :
if (CVA6Cfg.RVZihpm) begin
csr_rdata = perf_data_i;
end else begin
read_access_exception = 1'b1;
end
riscv::CSR_HPM_COUNTER_3H,
riscv::CSR_HPM_COUNTER_4H,
riscv::CSR_HPM_COUNTER_5H,
riscv::CSR_HPM_COUNTER_6H,
riscv::CSR_HPM_COUNTER_7H,
riscv::CSR_HPM_COUNTER_8H,
riscv::CSR_HPM_COUNTER_9H,
riscv::CSR_HPM_COUNTER_10H,
riscv::CSR_HPM_COUNTER_11H,
riscv::CSR_HPM_COUNTER_12H,
riscv::CSR_HPM_COUNTER_13H,
riscv::CSR_HPM_COUNTER_14H,
riscv::CSR_HPM_COUNTER_15H,
riscv::CSR_HPM_COUNTER_16H,
riscv::CSR_HPM_COUNTER_17H,
riscv::CSR_HPM_COUNTER_18H,
riscv::CSR_HPM_COUNTER_19H,
riscv::CSR_HPM_COUNTER_20H,
riscv::CSR_HPM_COUNTER_21H,
riscv::CSR_HPM_COUNTER_22H,
riscv::CSR_HPM_COUNTER_23H,
riscv::CSR_HPM_COUNTER_24H,
riscv::CSR_HPM_COUNTER_25H,
riscv::CSR_HPM_COUNTER_26H,
riscv::CSR_HPM_COUNTER_27H,
riscv::CSR_HPM_COUNTER_28H,
riscv::CSR_HPM_COUNTER_29H,
riscv::CSR_HPM_COUNTER_30H,
riscv::CSR_HPM_COUNTER_31H :
if (CVA6Cfg.RVZihpm) begin
if (CVA6Cfg.XLEN == 32) csr_rdata = perf_data_i;
else read_access_exception = 1'b1;
end else begin
read_access_exception = 1'b1;
end
// custom (non RISC-V) cache control
riscv::CSR_DCACHE: csr_rdata = dcache_q;
riscv::CSR_ICACHE: csr_rdata = icache_q;
// custom (non RISC-V) accelerator memory consistency mode
riscv::CSR_ACC_CONS: begin
if (CVA6Cfg.EnableAccelerator) begin
csr_rdata = acc_cons_q;
end else begin
read_access_exception = 1'b1;
end
end
// PMPs
riscv::CSR_PMPCFG0,
riscv::CSR_PMPCFG1,
riscv::CSR_PMPCFG2,
riscv::CSR_PMPCFG3,
riscv::CSR_PMPCFG4,
riscv::CSR_PMPCFG5,
riscv::CSR_PMPCFG6,
riscv::CSR_PMPCFG7,
riscv::CSR_PMPCFG8,
riscv::CSR_PMPCFG9,
riscv::CSR_PMPCFG10,
riscv::CSR_PMPCFG11,
riscv::CSR_PMPCFG12,
riscv::CSR_PMPCFG13,
riscv::CSR_PMPCFG14,
riscv::CSR_PMPCFG15: begin
// index is calculated using PMPCFG0 as the offset
automatic logic [11:0] index = csr_addr.address[11:0] - riscv::CSR_PMPCFG0;
// if index is not even and XLEN==64, raise exception
if (CVA6Cfg.XLEN == 64 && index[0] == 1'b1) read_access_exception = 1'b1;
else begin
csr_rdata = pmpcfg_q[index*4+:CVA6Cfg.XLEN/8];
end
end
// PMPADDR
riscv::CSR_PMPADDR0,
riscv::CSR_PMPADDR1,
riscv::CSR_PMPADDR2,
riscv::CSR_PMPADDR3,
riscv::CSR_PMPADDR4,
riscv::CSR_PMPADDR5,
riscv::CSR_PMPADDR6,
riscv::CSR_PMPADDR7,
riscv::CSR_PMPADDR8,
riscv::CSR_PMPADDR9,
riscv::CSR_PMPADDR10,
riscv::CSR_PMPADDR11,
riscv::CSR_PMPADDR12,
riscv::CSR_PMPADDR13,
riscv::CSR_PMPADDR14,
riscv::CSR_PMPADDR15,
riscv::CSR_PMPADDR16,
riscv::CSR_PMPADDR17,
riscv::CSR_PMPADDR18,
riscv::CSR_PMPADDR19,
riscv::CSR_PMPADDR20,
riscv::CSR_PMPADDR21,
riscv::CSR_PMPADDR22,
riscv::CSR_PMPADDR23,
riscv::CSR_PMPADDR24,
riscv::CSR_PMPADDR25,
riscv::CSR_PMPADDR26,
riscv::CSR_PMPADDR27,
riscv::CSR_PMPADDR28,
riscv::CSR_PMPADDR29,
riscv::CSR_PMPADDR30,
riscv::CSR_PMPADDR31,
riscv::CSR_PMPADDR32,
riscv::CSR_PMPADDR33,
riscv::CSR_PMPADDR34,
riscv::CSR_PMPADDR35,
riscv::CSR_PMPADDR36,
riscv::CSR_PMPADDR37,
riscv::CSR_PMPADDR38,
riscv::CSR_PMPADDR39,
riscv::CSR_PMPADDR40,
riscv::CSR_PMPADDR41,
riscv::CSR_PMPADDR42,
riscv::CSR_PMPADDR43,
riscv::CSR_PMPADDR44,
riscv::CSR_PMPADDR45,
riscv::CSR_PMPADDR46,
riscv::CSR_PMPADDR47,
riscv::CSR_PMPADDR48,
riscv::CSR_PMPADDR49,
riscv::CSR_PMPADDR50,
riscv::CSR_PMPADDR51,
riscv::CSR_PMPADDR52,
riscv::CSR_PMPADDR53,
riscv::CSR_PMPADDR54,
riscv::CSR_PMPADDR55,
riscv::CSR_PMPADDR56,
riscv::CSR_PMPADDR57,
riscv::CSR_PMPADDR58,
riscv::CSR_PMPADDR59,
riscv::CSR_PMPADDR60,
riscv::CSR_PMPADDR61,
riscv::CSR_PMPADDR62,
riscv::CSR_PMPADDR63: begin
// index is calculated using PMPADDR0 as the offset
automatic logic [11:0] index = csr_addr.address[11:0] - riscv::CSR_PMPADDR0;
// Important: we only support granularity 8 bytes (G=1)
// -> last bit of pmpaddr must be set 0/1 based on the mode:
// NA4, NAPOT: 1
// TOR, OFF: 0
if (pmpcfg_q[index].addr_mode[1] == 1'b1)
csr_rdata = {pmpaddr_q[index][CVA6Cfg.PLEN-3:1], 1'b1};
else csr_rdata = {pmpaddr_q[index][CVA6Cfg.PLEN-3:1], 1'b0};
end
default: read_access_exception = 1'b1;
endcase
end
end
// ---------------------------
// CSR Write and update logic
// ---------------------------
logic [CVA6Cfg.XLEN-1:0] mask;
always_comb begin : csr_update
automatic satp_t satp;
automatic satp_t vsatp;
automatic hgatp_t hgatp;
automatic logic [63:0] instret;
if (CVA6Cfg.RVS) begin
satp = satp_q;
end
if (CVA6Cfg.RVH) begin
hgatp = hgatp_q;
vsatp = vsatp_q;
end
instret = instret_q;
mcountinhibit_d = mcountinhibit_q;
// --------------------
// Counters
// --------------------
cycle_d = cycle_q;
instret_d = instret_q;
if (!(CVA6Cfg.DebugEn && debug_mode_q)) begin
// increase instruction retired counter
for (int i = 0; i < CVA6Cfg.NrCommitPorts; i++) begin
if (commit_ack_i[i] && !ex_i.valid && (!CVA6Cfg.PerfCounterEn || (CVA6Cfg.PerfCounterEn && !mcountinhibit_q[2])))
instret++;
end
instret_d = instret;
// increment the cycle count
if (!CVA6Cfg.PerfCounterEn || (CVA6Cfg.PerfCounterEn && !mcountinhibit_q[0]))
cycle_d = cycle_q + 1'b1;
else cycle_d = cycle_q;
end
eret_o = 1'b0;
flush_o = 1'b0;
update_access_exception = 1'b0;
virtual_update_access_exception = 1'b0;
set_debug_pc_o = 1'b0;
perf_we_o = 1'b0;
perf_data_o = 'b0;
if (CVA6Cfg.RVZCMT) begin
jvt_d = jvt_q;
end
fcsr_d = fcsr_q;
priv_lvl_d = priv_lvl_q;
v_d = v_q;
debug_mode_d = debug_mode_q;
if (CVA6Cfg.DebugEn) begin
dcsr_d = dcsr_q;
dpc_d = dpc_q;
dscratch0_d = dscratch0_q;
dscratch1_d = dscratch1_q;
end
mstatus_d = mstatus_q;
if (CVA6Cfg.RVH) begin
hstatus_d = hstatus_q;
vsstatus_d = vsstatus_q;
end
// check whether we come out of reset
// this is a workaround. some tools have issues
// having boot_addr_i in the asynchronous
// reset assignment to mtvec_d, even though
// boot_addr_i will be assigned a constant
// on the top-level.
if (mtvec_rst_load_q) begin
mtvec_d = {{CVA6Cfg.XLEN - CVA6Cfg.VLEN{1'b0}}, boot_addr_i} + 'h40;
end else begin
mtvec_d = mtvec_q;
end
if (CVA6Cfg.RVS) begin
medeleg_d = medeleg_q;
mideleg_d = mideleg_q;
end
mip_d = mip_q;
mie_d = mie_q;
mepc_d = mepc_q;
mcause_d = mcause_q;
mcounteren_d = mcounteren_q;
mscratch_d = mscratch_q;
if (CVA6Cfg.TvalEn) mtval_d = mtval_q;
if (CVA6Cfg.RVH) begin
mtinst_d = mtinst_q;
mtval2_d = mtval2_q;
end
fiom_d = fiom_q;
dcache_d = dcache_q;
icache_d = icache_q;
acc_cons_d = acc_cons_q;
if (CVA6Cfg.RVH) begin
vstvec_d = vstvec_q;
vsscratch_d = vsscratch_q;
vsepc_d = vsepc_q;
vscause_d = vscause_q;
vstval_d = vstval_q;
vsatp_d = vsatp_q;
hgatp_d = hgatp_q;
hedeleg_d = hedeleg_q;
hideleg_d = hideleg_q;
hgeie_d = hgeie_q;
hcounteren_d = hcounteren_q;
htinst_d = htinst_q;
htval_d = htval_q;
en_ld_st_g_translation_d = en_ld_st_g_translation_q;
end
if (CVA6Cfg.RVS) begin
sepc_d = sepc_q;
scause_d = scause_q;
stvec_d = stvec_q;
scounteren_d = scounteren_q;
sscratch_d = sscratch_q;
stval_d = stval_q;
satp_d = satp_q;