Skip to content

Commit 9c0b5e0

Browse files
committed
feat: add vCLIC support (#55)
1 parent 6021105 commit 9c0b5e0

27 files changed

Lines changed: 215 additions & 29 deletions

core/csr_regfile.sv

Lines changed: 92 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,8 @@ module csr_regfile
173173
// TO_BE_COMPLETED - CLIC_CTRL
174174
output logic [7:0] sintthresh_o,
175175
// TO_BE_COMPLETED - CLIC_CTRL
176+
output logic [7:0] vsintthresh_o,
177+
// TO_BE_COMPLETED - CLIC_CTRL
176178
output logic clic_irq_ready_o,
177179
// we are in single-step mode - COMMIT_STAGE
178180
output logic single_step_o,
@@ -308,10 +310,12 @@ module csr_regfile
308310
logic [CVA6Cfg.XLEN-1:0] htval_q, htval_d;
309311

310312
logic [CVA6Cfg.XLEN-1:0] vstvec_q, vstvec_d;
313+
logic [CVA6Cfg.XLEN-1:0] vstvt_q, vstvt_d;
311314
logic [CVA6Cfg.XLEN-1:0] vsscratch_q, vsscratch_d;
312315
logic [CVA6Cfg.XLEN-1:0] vsepc_q, vsepc_d;
313316
logic [CVA6Cfg.XLEN-1:0] vscause_q, vscause_d;
314317
logic [CVA6Cfg.XLEN-1:0] vstval_q, vstval_d;
318+
riscv::intthresh_rv_t vsintthresh_q, vsintthresh_d;
315319

316320
logic [CVA6Cfg.XLEN-1:0] dcache_q, dcache_d;
317321
logic [CVA6Cfg.XLEN-1:0] icache_q, icache_d;
@@ -409,6 +413,12 @@ module csr_regfile
409413
assign clic_irq_ready_o = 1'b0;
410414
end
411415

416+
if (CVA6Cfg.RVXHCLIC) begin : gen_clic_vsintthresh_signal
417+
assign vsintthresh_o = vsintthresh_q.th;
418+
end else begin : gen_dummy_clic_vsintthresh_signal
419+
assign vsintthresh_o = '0;
420+
end
421+
412422
always_comb begin : csr_read_process
413423
// a read access exception can only occur if we attempt to read a CSR which does not exist
414424
read_access_exception = 1'b0;
@@ -497,15 +507,19 @@ module csr_regfile
497507
else read_access_exception = 1'b1;
498508
riscv::CSR_VSIE:
499509
if (CVA6Cfg.RVH)
500-
csr_rdata = (mie_q & VS_DELEG_INTERRUPTS[CVA6Cfg.XLEN-1:0] & hideleg_q) >> 1;
510+
csr_rdata = (CVA6Cfg.RVXHCLIC && clic_mode_o) ? '0 : ((mie_q & VS_DELEG_INTERRUPTS[CVA6Cfg.XLEN-1:0] & hideleg_q) >> 1);
501511
else read_access_exception = 1'b1;
502512
riscv::CSR_VSIP:
503513
if (CVA6Cfg.RVH)
504-
csr_rdata = (mip_q & VS_DELEG_INTERRUPTS[CVA6Cfg.XLEN-1:0] & hideleg_q) >> 1;
514+
csr_rdata = (CVA6Cfg.RVXHCLIC && clic_mode_o) ? '0 : ((mip_q & VS_DELEG_INTERRUPTS[CVA6Cfg.XLEN-1:0] & hideleg_q) >> 1);
505515
else read_access_exception = 1'b1;
506516
riscv::CSR_VSTVEC:
507517
if (CVA6Cfg.RVH) csr_rdata = vstvec_q;
508518
else read_access_exception = 1'b1;
519+
riscv::CSR_VSTVT:
520+
if (CVA6Cfg.RVXHCLIC)
521+
csr_rdata = clic_mode_o ? {vstvt_q, 8'b0} : '0; // vstvt reads 0 in CLINT mode
522+
else read_access_exception = 1'b1;
509523
riscv::CSR_VSSCRATCH:
510524
if (CVA6Cfg.RVH) csr_rdata = vsscratch_q;
511525
else read_access_exception = 1'b1;
@@ -527,6 +541,10 @@ module csr_regfile
527541
end else begin
528542
read_access_exception = 1'b1;
529543
end
544+
riscv::CSR_VSINTTHRESH:
545+
if (CVA6Cfg.RVXHCLIC)
546+
csr_rdata = clic_mode_o ? {{CVA6Cfg.XLEN - 8{1'b0}}, vsintthresh_q} : '0; // vsintthresh reads 0 in CLINT mode
547+
else read_access_exception = 1'b1;
530548
// supervisor registers
531549
riscv::CSR_SSTATUS: begin
532550
if (CVA6Cfg.RVS) csr_rdata = mstatus_extended & SMODE_STATUS_READ_MASK[CVA6Cfg.XLEN-1:0];
@@ -627,13 +645,16 @@ module csr_regfile
627645
if (CVA6Cfg.RVH) csr_rdata = hideleg_q;
628646
else read_access_exception = 1'b1;
629647
riscv::CSR_HIE:
630-
if (CVA6Cfg.RVH) csr_rdata = mie_q & HS_DELEG_INTERRUPTS[CVA6Cfg.XLEN-1:0];
648+
if (CVA6Cfg.RVH)
649+
csr_rdata = (CVA6Cfg.RVXHCLIC && clic_mode_o) ? (mie_q & riscv::MIP_SGEIP) : (mie_q & HS_DELEG_INTERRUPTS[CVA6Cfg.XLEN-1:0]);
631650
else read_access_exception = 1'b1;
632651
riscv::CSR_HIP:
633-
if (CVA6Cfg.RVH) csr_rdata = mip_q & HS_DELEG_INTERRUPTS[CVA6Cfg.XLEN-1:0];
652+
if (CVA6Cfg.RVH)
653+
csr_rdata = (CVA6Cfg.RVXHCLIC && clic_mode_o) ? '0 : (mip_q & HS_DELEG_INTERRUPTS[CVA6Cfg.XLEN-1:0]);
634654
else read_access_exception = 1'b1;
635655
riscv::CSR_HVIP:
636-
if (CVA6Cfg.RVH) csr_rdata = mip_q & VS_DELEG_INTERRUPTS[CVA6Cfg.XLEN-1:0];
656+
if (CVA6Cfg.RVH)
657+
csr_rdata = (CVA6Cfg.RVXHCLIC && clic_mode_o) ? '0 : (mip_q & VS_DELEG_INTERRUPTS[CVA6Cfg.XLEN-1:0]);
637658
else read_access_exception = 1'b1;
638659
riscv::CSR_HCOUNTEREN:
639660
if (CVA6Cfg.RVH) csr_rdata = hcounteren_q;
@@ -645,7 +666,7 @@ module csr_regfile
645666
if (CVA6Cfg.RVH) csr_rdata = htinst_q;
646667
else read_access_exception = 1'b1;
647668
riscv::CSR_HGEIE:
648-
if (CVA6Cfg.RVH) csr_rdata = '0;
669+
if (CVA6Cfg.RVH) csr_rdata = {hgeie_q[CVA6Cfg.XLEN-1:1], 1'b0};
649670
else read_access_exception = 1'b1;
650671
riscv::CSR_HGEIP:
651672
if (CVA6Cfg.RVH) csr_rdata = '0;
@@ -1191,6 +1212,11 @@ module csr_regfile
11911212
en_ld_st_g_translation_d = en_ld_st_g_translation_q;
11921213
end
11931214

1215+
if (CVA6Cfg.RVXHCLIC) begin
1216+
vstvt_d = vstvt_q;
1217+
vsintthresh_d = vsintthresh_q;
1218+
end
1219+
11941220
if (CVA6Cfg.RVS) begin
11951221
sepc_d = sepc_q;
11961222
scause_d = scause_q;
@@ -1360,13 +1386,19 @@ module csr_regfile
13601386
end
13611387
end
13621388
riscv::CSR_VSIE:
1363-
if (CVA6Cfg.RVH) mie_d = (mie_q & ~hideleg_q) | ((csr_wdata << 1) & hideleg_q);
1364-
else update_access_exception = 1'b1;
1389+
if (CVA6Cfg.RVH) begin
1390+
// Writes are legal but ignored in CLIC mode
1391+
if (!(CVA6Cfg.RVXHCLIC && clic_mode_o))
1392+
mie_d = (mie_q & ~hideleg_q) | ((csr_wdata << 1) & hideleg_q);
1393+
end else update_access_exception = 1'b1;
13651394
riscv::CSR_VSIP: begin
13661395
if (CVA6Cfg.RVH) begin
1367-
// only the virtual supervisor software interrupt is write-able, iff delegated
1368-
mask = CVA6Cfg.XLEN'(riscv::MIP_VSSIP) & hideleg_q;
1369-
mip_d = (mip_q & ~mask) | ((csr_wdata << 1) & mask);
1396+
// Writes are legal but ignored in CLIC mode
1397+
if (!(CVA6Cfg.RVXHCLIC && clic_mode_o)) begin
1398+
// only the virtual supervisor software interrupt is write-able, iff delegated
1399+
mask = CVA6Cfg.XLEN'(riscv::MIP_VSSIP) & hideleg_q;
1400+
mip_d = (mip_q & ~mask) | ((csr_wdata << 1) & mask);
1401+
end
13701402
end else begin
13711403
update_access_exception = 1'b1;
13721404
end
@@ -1378,6 +1410,12 @@ module csr_regfile
13781410
update_access_exception = 1'b1;
13791411
end
13801412
end
1413+
riscv::CSR_VSTVT: begin
1414+
if (CVA6Cfg.RVXHCLIC) begin
1415+
// Writes are legal but ignored in CLINT mode
1416+
if (clic_mode_o) vstvt_d = csr_wdata[CVA6Cfg.XLEN-1:8];
1417+
end else update_access_exception = 1'b1;
1418+
end
13811419
riscv::CSR_VSSCRATCH:
13821420
if (CVA6Cfg.RVH) vsscratch_d = csr_wdata;
13831421
else update_access_exception = 1'b1;
@@ -1411,6 +1449,12 @@ module csr_regfile
14111449
update_access_exception = 1'b1;
14121450
end
14131451
end
1452+
riscv::CSR_VSINTTHRESH: begin
1453+
if (CVA6Cfg.RVXHCLIC) begin
1454+
// Writes are legal but ignored in CLINT mode
1455+
if (clic_mode_o) vsintthresh_d.th = csr_wdata[7:0];
1456+
end else update_access_exception = 1'b1;
1457+
end
14141458
// sstatus is a subset of mstatus - mask it accordingly
14151459
riscv::CSR_SSTATUS: begin
14161460
if (CVA6Cfg.RVS) begin
@@ -1577,16 +1621,20 @@ module csr_regfile
15771621
end
15781622
riscv::CSR_HIE: begin
15791623
if (CVA6Cfg.RVH) begin
1580-
mask = HS_DELEG_INTERRUPTS[CVA6Cfg.XLEN-1:0];
1624+
// In CLIC mode only SGEIE bit is writable
1625+
mask = (CVA6Cfg.RVXHCLIC && clic_mode_o) ? CVA6Cfg.XLEN'(riscv::MIP_SGEIP) : HS_DELEG_INTERRUPTS[CVA6Cfg.XLEN-1:0];
15811626
mie_d = (mie_q & ~mask) | (csr_wdata & mask);
15821627
end else begin
15831628
update_access_exception = 1'b1;
15841629
end
15851630
end
15861631
riscv::CSR_HIP: begin
15871632
if (CVA6Cfg.RVH) begin
1588-
mask = CVA6Cfg.XLEN'(riscv::MIP_VSSIP);
1589-
mip_d = (mip_q & ~mask) | (csr_wdata & mask);
1633+
// Writes are legal but ignored in CLIC mode
1634+
if (!(CVA6Cfg.RVXHCLIC && clic_mode_o)) begin
1635+
mask = CVA6Cfg.XLEN'(riscv::MIP_VSSIP);
1636+
mip_d = (mip_q & ~mask) | (csr_wdata & mask);
1637+
end
15901638
end else begin
15911639
update_access_exception = 1'b1;
15921640
end
@@ -1620,12 +1668,9 @@ module csr_regfile
16201668
update_access_exception = 1'b1;
16211669
end
16221670
end
1623-
//TODO Hyp: implement hgeie write
1624-
riscv::CSR_HGEIE: begin
1625-
if (!CVA6Cfg.RVH) begin
1626-
update_access_exception = 1'b1;
1627-
end
1628-
end
1671+
riscv::CSR_HGEIE:
1672+
if (CVA6Cfg.RVH) hgeie_d = {csr_wdata[CVA6Cfg.XLEN-1:1], 1'b0};
1673+
else update_access_exception = 1'b1;
16291674
riscv::CSR_HGATP: begin
16301675
if (CVA6Cfg.RVH) begin
16311676
// intercept HGATP writes if in HS-Mode and TVM is enabled
@@ -2205,6 +2250,9 @@ module csr_regfile
22052250
trap_to_v = v_q;
22062251
end
22072252
end
2253+
end else if (ex_i.cause[CVA6Cfg.XLEN-1] && clic_mode_o) begin
2254+
trap_to_priv_lvl = riscv::priv_lvl_t'(ex_i.cause[25:24]);
2255+
if (CVA6Cfg.RVXHCLIC) trap_to_v = ex_i.cause[26];
22082256
end
22092257
end
22102258

@@ -2217,7 +2265,12 @@ module csr_regfile
22172265
// this can either be user or supervisor mode
22182266
vsstatus_d.spp = priv_lvl_q[0];
22192267
// set cause
2220-
vscause_d = ex_i.cause[CVA6Cfg.XLEN-1] ? {ex_i.cause[CVA6Cfg.XLEN-1:2], 2'b01} : ex_i.cause;
2268+
vscause_d = (~clic_mode_o && ex_i.cause[CVA6Cfg.XLEN-1]) ? {ex_i.cause[CVA6Cfg.XLEN-1:2], 2'b01} : ex_i.cause;
2269+
// update the current and previous interrupt level
2270+
if (CVA6Cfg.RVXHCLIC && clic_mode_o && ex_i.cause[CVA6Cfg.XLEN-1]) begin
2271+
mintstatus_d.vsil = ex_i.cause[23:16];
2272+
vscause_d[23:16] = mintstatus_q.vsil;
2273+
end
22212274
// set epc
22222275
vsepc_d = {{CVA6Cfg.XLEN - CVA6Cfg.VLEN{pc_i[CVA6Cfg.VLEN-1]}}, pc_i};
22232276
// set vstval
@@ -2547,6 +2600,9 @@ module csr_regfile
25472600
vsstatus_d.spp = 1'b0;
25482601
// set spie to 1
25492602
vsstatus_d.spie = 1'b1;
2603+
// restore vsintstatus
2604+
if (CVA6Cfg.RVXHCLIC && clic_mode_o && vscause_q[CVA6Cfg.XLEN-1])
2605+
mintstatus_d.vsil = vscause_q[23:16];
25502606
end
25512607
end
25522608

@@ -2626,6 +2682,8 @@ module csr_regfile
26262682
end
26272683
assign irq_ctrl_o.mideleg = (CVA6Cfg.RVS) ? mideleg_q : '0;
26282684
assign irq_ctrl_o.hideleg = (CVA6Cfg.RVH) ? hideleg_q : '0;
2685+
assign irq_ctrl_o.hgeie = (CVA6Cfg.RVH) ? hgeie_q : '0;
2686+
assign irq_ctrl_o.vgein = (CVA6Cfg.RVH) ? hstatus_q.vgein : '0;
26292687
assign irq_ctrl_o.global_enable = ~(CVA6Cfg.DebugEn & debug_mode_q)
26302688
// interrupts are enabled during single step or we are not stepping
26312689
// No need to check interrupts during single step if we don't support DEBUG mode
@@ -2795,7 +2853,11 @@ module csr_regfile
27952853
// output user mode stvec
27962854
if (CVA6Cfg.RVS && trap_to_priv_lvl == riscv::PRIV_LVL_S) begin
27972855
if (CVA6Cfg.RVSCLIC && clic_mode_o && clic_irq_shv_i && ex_i.cause[CVA6Cfg.XLEN-1]) begin
2798-
trap_vector_base_o = {stvt_q[CVA6Cfg.VLEN-1:8], 8'b0};
2856+
if (CVA6Cfg.RVSCLIC && trap_to_v) begin
2857+
trap_vector_base_o = {vstvt_q[CVA6Cfg.VLEN-1:8], 8'b0};
2858+
end else begin
2859+
trap_vector_base_o = {stvt_q[CVA6Cfg.VLEN-1:8], 8'b0};
2860+
end
27992861
end else if (CVA6Cfg.RVH && trap_to_v) begin
28002862
trap_vector_base_o = {vstvec_q[CVA6Cfg.VLEN-1:2], 2'b0};
28012863
end else begin
@@ -3043,6 +3105,10 @@ module csr_regfile
30433105
hcbie_q <= riscv::CBIE_INVAL;
30443106
hcbcfe_q <= 1'b1;
30453107
end
3108+
if (CVA6Cfg.RVXHCLIC) begin
3109+
vstvt_q <= {CVA6Cfg.XLEN{1'b0}};
3110+
vsintthresh_q <= 8'b0;
3111+
end
30463112
end
30473113
if (CVA6Cfg.SDTRIG) begin
30483114
scontext_q <= '0;
@@ -3151,6 +3217,10 @@ module csr_regfile
31513217
hcbie_q <= hcbie_d;
31523218
hcbcfe_q <= hcbcfe_d;
31533219
end
3220+
if (CVA6Cfg.RVXHCLIC) begin
3221+
vstvt_q <= vstvt_d;
3222+
vsintthresh_q <= vsintthresh_d;
3223+
end
31543224
end
31553225
if (CVA6Cfg.SDTRIG) begin
31563226
scontext_q <= scontext_d;

core/cva6.sv

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,8 @@ module cva6
147147
logic [CVA6Cfg.XLEN-1:0] mip;
148148
logic [CVA6Cfg.XLEN-1:0] mideleg;
149149
logic [CVA6Cfg.XLEN-1:0] hideleg;
150+
logic [CVA6Cfg.XLEN-1:0] hgeie;
151+
logic [5:0] vgein;
150152
logic sie;
151153
logic global_enable;
152154
},
@@ -335,6 +337,8 @@ module cva6
335337
input logic [$clog2(CVA6Cfg.CLICNumInterruptSrc)-1:0] clic_irq_id_i, // interrupt source ID
336338
input logic [7:0] clic_irq_level_i, // interrupt level is 8-bit from CLIC spec
337339
input riscv::priv_lvl_t clic_irq_priv_i, // CLIC interrupt privilege level
340+
input logic clic_irq_v_i, // CLIC interrupt virtualization bit (only for vCLIC)
341+
input logic [5:0] clic_irq_vsid_i, // CLIC interrupt Virtual Supervisor ID (only for vCLIC)
338342
input logic clic_irq_shv_i, // selective hardware vectoring bit
339343
output logic clic_irq_ready_o, // core side interrupt hanshake (ready)
340344
input logic clic_kill_req_i, // kill request
@@ -599,6 +603,7 @@ module cva6
599603
riscv::intstatus_rv_t mintstatus_csr;
600604
logic [7:0] mintthresh_csr;
601605
logic [7:0] sintthresh_csr;
606+
logic [7:0] vsintthresh_csr;
602607
logic dcache_en_csr_nbdcache;
603608
logic csr_write_fflags_commit_cs;
604609
logic icache_en_csr;
@@ -1248,6 +1253,7 @@ module cva6
12481253
.mintstatus_o (mintstatus_csr),
12491254
.mintthresh_o (mintthresh_csr),
12501255
.sintthresh_o (sintthresh_csr),
1256+
.vsintthresh_o (vsintthresh_csr),
12511257
.clic_irq_req_i (clic_irq_valid_i),
12521258
.clic_irq_shv_i (clic_irq_shv_i),
12531259
.clic_irq_ready_o (clic_irq_ready_o),
@@ -1744,16 +1750,20 @@ module cva6
17441750
.rst_ni (rst_ni),
17451751
// from CSR file
17461752
.priv_lvl_i (priv_lvl),
1753+
.v_i (v),
17471754
.irq_ctrl_i (irq_ctrl_csr_id),
17481755
.mintthresh_i (mintthresh_csr),
17491756
.sintthresh_i (sintthresh_csr),
1757+
.vsintthresh_i (vsintthresh_csr),
17501758
.mintstatus_i (mintstatus_csr),
17511759
// from/to CLIC
17521760
.clic_irq_valid_i(clic_irq_valid_i),
17531761
.clic_irq_ready_i(clic_irq_ready_o),
17541762
.clic_irq_id_i (clic_irq_id_i),
17551763
.clic_irq_level_i(clic_irq_level_i),
17561764
.clic_irq_priv_i (clic_irq_priv_i),
1765+
.clic_irq_v_i (clic_irq_v_i),
1766+
.clic_irq_vsid_i (clic_irq_vsid_i),
17571767
.clic_kill_req_i (clic_kill_req_i),
17581768
.clic_kill_ack_o (clic_kill_ack_o),
17591769
// to ID stage

0 commit comments

Comments
 (0)