-
Notifications
You must be signed in to change notification settings - Fork 10
Expand file tree
/
Copy pathcsr_regfile.sv
More file actions
3145 lines (3023 loc) · 131 KB
/
Copy pathcsr_regfile.sv
File metadata and controls
3145 lines (3023 loc) · 131 KB
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 2025 Bruno Sá and Zero-Day Labs.
// Copyright 2025 Capabilities Limited.
// 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::*;
import cva6_cheri_pkg::*;
#(
parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty,
parameter type exception_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 [CVA6Cfg.NrCommitPorts-1:0] 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,
// Boot Address from which to start booting, mtvec is set to the same address - SUBSYSTEM
input logic [CVA6Cfg.PCLEN-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 are taking an exception
// 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.REGLEN-1:0] csr_wdata_i,
// Read data out - COMMIT_STAGE
output logic [CVA6Cfg.REGLEN-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.PCLEN-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.REGLEN-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.REGLEN-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,
// Default Data Capability
output logic [CVA6Cfg.REGLEN-1:0] ddc_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,
// Performance Counter
// 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 16 PMPs - ACC_DISPATCHER
output riscv::pmpcfg_t [15:0] pmpcfg_o,
// PMP addresses - ACC_DISPATCHER
output logic [15: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
);
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 cheri_read_access_exception, cheri_update_access_exception, cheri_access_violation;
logic csr_we, csr_read;
logic [CVA6Cfg.XLEN-1:0] csr_wdata, csr_rdata;
cva6_cheri_pkg::scr_reg_t scr_addr;
logic scr_we;
logic scr_read;
cva6_cheri_pkg::cap_reg_t scr_wdata, scr_rdata;
logic [CVA6Cfg.REGLEN-1:0] dbg_wdata, dbg_rdata;
cva6_cheri_pkg::addrw_t cap_offset;
cva6_cheri_pkg::cap_pcc_t pcc;
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;
cva6_cheri_pkg::cap_reg_t dpc_cap_q, dpc_cap_d;
cva6_cheri_pkg::cap_meta_data_t dpc_cap_meta_data;
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
// TODO-cheri(ninolomata): There should be the CHERI extended registers for debug module
logic [CVA6Cfg.XLEN-1:0] dpc_q, dpc_d;
logic [CVA6Cfg.REGLEN-1:0] dscratch0_q, dscratch0_d;
logic [CVA6Cfg.REGLEN-1:0] dscratch1_q, dscratch1_d;
logic [CVA6Cfg.REGLEN-1:0] dscratch2_q, dscratch2_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 [CVA6Cfg.XLEN-1:0] mccsr_q, mccsr_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] sccsr_q, sccsr_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] vsccsr_q, vsccsr_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;
// Default data capability
cap_pcc_t pcc_d, pcc_q;
cap_reg_t ddc_d, ddc_q;
// Virtual Supervisor mode SCRs
cap_reg_t vstcc_q, vstcc_d;
cap_reg_t vstdc_q, vstdc_d;
cap_reg_t vsscratchc_q, vsscratchc_d;
cap_reg_t vsepcc_q, vsepcc_d;
// Supervisor mode SCRs
cap_reg_t stcc_q, stcc_d;
cap_reg_t stdc_q, stdc_d;
cap_reg_t sscratchc_q, sscratchc_d;
cap_reg_t sepcc_q, sepcc_d;
// Machine mode SCRs
cap_reg_t mtcc_q, mtcc_d;
cap_reg_t mtdc_q, mtdc_d;
cap_reg_t mscratchc_q, mscratchc_d;
cap_reg_t mepcc_q, mepcc_d;
logic wfi_d, wfi_q;
logic [63:0] cycle_q, cycle_d;
logic [63:0] instret_q, instret_d;
riscv::pmpcfg_t [15:0] pmpcfg_q, pmpcfg_d, pmpcfg_next;
logic [15:0][CVA6Cfg.PLEN-3:0] pmpaddr_q, pmpaddr_d, pmpaddr_next;
logic [MHPMCounterNum+3-1:0] mcountinhibit_d, mcountinhibit_q;
logic [3:0] index;
localparam logic [CVA6Cfg.XLEN-1:0] XCCSR = (CVA6Cfg.XLEN'(CVA6Cfg.RVFI_DII) << 0)
| (CVA6Cfg.XLEN'(1) << 30) // NR - no-relocation for integer addresses
| (CVA6Cfg.XLEN'(1) << 31); // TC - attempt to update a capability non-monotonically clears the tag
localparam logic [CVA6Cfg.XLEN-1:0] IsaCode = (CVA6Cfg.XLEN'(CVA6Cfg.RVA) << 0) // A - Atomic Instructions extension
| (CVA6Cfg.XLEN'(CVA6Cfg.RVB) << 1) // C - 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[15:0];
assign pmpaddr_o = pmpaddr_q;
assign dpc_cap_meta_data = get_cap_reg_meta_data(dpc_cap_q);
assign pcc = cva6_cheri_pkg::cap_pcc_t'(pc_i);
riscv::fcsr_t fcsr_q, fcsr_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 scr_addr = (CVA6Cfg.RVH) ? convert_vs_access_scr(scr_reg_t'(csr_addr_i[4:0]), v_q) : scr_reg_t'(csr_addr_i[4:0]);
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
// ----------------
// SCRs
// ----------------
// Logic to read and write to cap CSRs:
// 1) operation write must set the capability address;
cva6_cheri_pkg::cap_reg_t wr_cap_csr_result;
if (CVA6Cfg.CheriPresent) begin
always_comb begin : csr_write_cap_offset
automatic cva6_cheri_pkg::cap_reg_t wr_cap;
automatic cva6_cheri_pkg::cap_meta_data_t wr_cap_meta_data;
automatic cva6_cheri_pkg::addrw_t wr_cap_addr;
wr_cap_addr = '0;
wr_cap_meta_data = '0;
wr_cap = mepcc_q;
if (csr_we) begin
unique case (conv_csr_addr.address)
riscv::CSR_MEPC: begin
wr_cap = mepcc_q;
wr_cap_addr = {csr_wdata[riscv::XLEN-1:1], 1'b0};
end
riscv::CSR_MTVEC: begin
wr_cap = mtcc_q;
wr_cap_addr = {csr_wdata[riscv::XLEN-1:2], 1'b0, csr_wdata[0]};
// we are in vector mode, this implementation requires the additional
// alignment constraint of 64 * 4 bytes
if (csr_wdata[0]) begin
wr_cap_addr = {csr_wdata[riscv::XLEN-1:8], 7'b0, csr_wdata[0]};
end
end
riscv::CSR_MSCRATCH: begin
wr_cap = mscratchc_q;
wr_cap_addr = csr_wdata;
end
riscv::CSR_SEPC: begin
wr_cap = sepcc_q;
wr_cap_addr = {csr_wdata[riscv::XLEN-1:1], 1'b0};
end
riscv::CSR_STVEC: begin
wr_cap = stcc_q;
wr_cap_addr = {csr_wdata[riscv::XLEN-1:2], 1'b0, csr_wdata[0]};
// we are in vector mode, this implementation requires the additional
// alignment constraint of 64 * 4 bytes
if (csr_wdata[0]) begin
wr_cap_addr = {csr_wdata[riscv::XLEN-1:8], 7'b0, csr_wdata[0]};
end
end
riscv::CSR_SSCRATCH: begin
wr_cap = sscratchc_q;
wr_cap_addr = csr_wdata;
end
riscv::CSR_VSEPC: begin
wr_cap = vsepcc_q;
wr_cap_addr = {csr_wdata[riscv::XLEN-1:1], 1'b0};
end
riscv::CSR_VSTVEC: begin
wr_cap = vstcc_q;
wr_cap_addr = {csr_wdata[riscv::XLEN-1:2], 1'b0, csr_wdata[0]};
// we are in vector mode, this implementation requires the additional
// alignment constraint of 64 * 4 bytes
if (csr_wdata[0]) begin
wr_cap_addr = {csr_wdata[riscv::XLEN-1:8], 7'b0, csr_wdata[0]};
end
end
riscv::CSR_VSSCRATCH: begin
wr_cap = vsscratchc_q;
wr_cap_addr = csr_wdata;
end
endcase
end
wr_cap_meta_data = get_cap_reg_meta_data(wr_cap);
wr_cap_csr_result = set_cap_reg_address(wr_cap, wr_cap_addr, wr_cap_meta_data);
// if not representable set capability to NULL
if (!wr_cap_csr_result.tag) begin
wr_cap_csr_result = REG_NULL_CAP;
wr_cap_csr_result.addr = wr_cap_addr;
end
// if capibility is sealed, clear the tag bit
if(wr_cap.otype != UNSEALED_CAP )
wr_cap_csr_result.tag = 1'b0;
end
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;
dbg_rdata = '0;
perf_addr_o = csr_addr.address[11:0];
index = '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
// 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) dbg_rdata = dscratch0_q;
else read_access_exception = 1'b1;
riscv::CSR_DSCRATCH1:
if (CVA6Cfg.DebugEn) dbg_rdata = dscratch1_q;
else read_access_exception = 1'b1;
riscv::CSR_DSCRATCH2:
if (CVA6Cfg.DebugEn) dbg_rdata = dscratch2_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) begin
if (CVA6Cfg.CheriPresent) begin
csr_rdata = vstcc_q[CVA6Cfg.XLEN-1:0];
end else begin
csr_rdata = {{CVA6Cfg.REGLEN-CVA6Cfg.XLEN{1'b0}},vstvec_q};
end
end else read_access_exception = 1'b1;
riscv::CSR_VSSCRATCH:
if (CVA6Cfg.RVH) begin
if (CVA6Cfg.CheriPresent) csr_rdata = vsscratchc_q[CVA6Cfg.XLEN-1:0];
else csr_rdata = vsscratch_q;
end else read_access_exception = 1'b1;
riscv::CSR_VSEPC:
if (CVA6Cfg.RVH) begin
if (CVA6Cfg.CheriPresent) begin
csr_rdata = vsepcc_q[CVA6Cfg.XLEN-1:0];
end else begin
csr_rdata = {{CVA6Cfg.REGLEN-CVA6Cfg.XLEN{1'b0}},vsepc_q};
end
end
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
riscv::CSR_VSCCSR:
if (CVA6Cfg.CheriPresent) csr_rdata = vsccsr_q;
else read_access_exception = 1'b1;
// 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) begin
if (CVA6Cfg.CheriPresent) begin
csr_rdata = stcc_q[CVA6Cfg.XLEN-1:0];
end else begin
csr_rdata = {{CVA6Cfg.REGLEN-CVA6Cfg.XLEN{1'b0}},stvec_q};
end
end 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) begin
if (CVA6Cfg.CheriPresent) csr_rdata = sscratchc_q[CVA6Cfg.XLEN-1:0];
else csr_rdata = sscratch_q;
end else read_access_exception = 1'b1;
riscv::CSR_SEPC:
if (CVA6Cfg.RVS) begin
if (CVA6Cfg.CheriPresent) begin
csr_rdata = sepcc_q[CVA6Cfg.XLEN-1:0];
end else begin
csr_rdata = {{CVA6Cfg.REGLEN-CVA6Cfg.XLEN{1'b0}},sepc_q};
end
end 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;
riscv::CSR_SCCSR:
if (CVA6Cfg.CheriPresent) csr_rdata = sccsr_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:
if (CVA6Cfg.CheriPresent) csr_rdata = mtcc_q[CVA6Cfg.XLEN-1:0];
else csr_rdata = mtvec_q;
riscv::CSR_MCOUNTEREN: csr_rdata = mcounteren_q;
riscv::CSR_MSCRATCH:
if (CVA6Cfg.CheriPresent) csr_rdata = mscratchc_q[CVA6Cfg.XLEN-1:0];
else csr_rdata = mscratch_q;
riscv::CSR_MEPC:
if (CVA6Cfg.CheriPresent) csr_rdata = mepcc_q[CVA6Cfg.XLEN-1:0];
else csr_rdata = mepc_q;
riscv::CSR_MCAUSE: csr_rdata = mcause_q;
riscv::CSR_MTVAL: csr_rdata = mtval_q;
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_MCCSR:
if (CVA6Cfg.CheriPresent) csr_rdata = mccsr_q;
else read_access_exception = 1'b1;
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:
if (CVA6Cfg.PerfCounterEn)
csr_rdata = {{(CVA6Cfg.XLEN - (MHPMCounterNum + 3)) {1'b0}}, mcountinhibit_q};
else read_access_exception = 1'b1;
// 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: csr_rdata = cycle_q[CVA6Cfg.XLEN-1:0];
riscv::CSR_CYCLEH:
if (CVA6Cfg.XLEN == 32) csr_rdata = cycle_q[63:32];
else read_access_exception = 1'b1;
riscv::CSR_INSTRET: csr_rdata = instret_q[CVA6Cfg.XLEN-1:0];
riscv::CSR_INSTRETH:
if (CVA6Cfg.XLEN == 32) csr_rdata = instret_q[63:32];
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 :
csr_rdata = perf_data_i;
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.XLEN == 32) csr_rdata = perf_data_i;
else read_access_exception = 1'b1;
// 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: csr_rdata = pmpcfg_q[CVA6Cfg.XLEN/8-1:0];
riscv::CSR_PMPCFG1:
if (CVA6Cfg.XLEN == 32) csr_rdata = pmpcfg_q[7:4];
else read_access_exception = 1'b1;
riscv::CSR_PMPCFG2: csr_rdata = pmpcfg_q[8+:CVA6Cfg.XLEN/8];
riscv::CSR_PMPCFG3:
if (CVA6Cfg.XLEN == 32) csr_rdata = pmpcfg_q[15:12];
else read_access_exception = 1'b1;
// 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: begin
// index is specified by the last byte in the address
index = csr_addr.csr_decode.address[3:0];
// 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:0];
else csr_rdata = {pmpaddr_q[index][CVA6Cfg.PLEN-3:1], 1'b0};
end
default: read_access_exception = 1'b1;
endcase
end
end
if ((CVA6Cfg.CheriPresent)) begin
always_comb begin : scr_read_process
// a read access exception can only occur if we attempt to read a CSR which does not exist
cheri_read_access_exception = 1'b0;
scr_rdata = REG_NULL_CAP;
if (scr_read) begin
unique case (scr_addr)
cva6_cheri_pkg::SCR_PCC: begin
scr_rdata = cap_pcc_to_cap_reg(pcc);
end
cva6_cheri_pkg::SCR_DDC: begin
scr_rdata = ddc_q;
end
cva6_cheri_pkg::SCR_VSTCC: begin
scr_rdata = vstcc_q;
end
cva6_cheri_pkg::SCR_VSTDC: begin
scr_rdata = vstdc_q;
end
cva6_cheri_pkg::SCR_VSSCRATCHC: begin
scr_rdata = vsscratchc_q;
end
cva6_cheri_pkg::SCR_VSEPCC: begin
scr_rdata = vsepcc_q;
end
cva6_cheri_pkg::SCR_STCC: begin
scr_rdata = stcc_q;
end
cva6_cheri_pkg::SCR_STDC: begin
scr_rdata = stdc_q;
end
cva6_cheri_pkg::SCR_SSCRATCHC: begin
scr_rdata = sscratchc_q;
end
cva6_cheri_pkg::SCR_SEPCC: begin