diff --git a/Bender.yml b/Bender.yml index 5a4fc2eeb4..e3d5e2a439 100644 --- a/Bender.yml +++ b/Bender.yml @@ -37,10 +37,18 @@ sources: files: - core/include/cv64a6_imafdc_sv39_hpdcache_config_pkg.sv + - target: cv64a6_imafdchsclic_sv39_hpdcache + files: + - core/include/cv64a6_imafdchsclic_sv39_hpdcache_config_pkg.sv + - target: cv64a6_imafdc_sv39_wb files: - core/include/cv64a6_imafdc_sv39_wb_config_pkg.sv + - target: cv64a6_imafdchsclic_sv39_wb + files: + - core/include/cv64a6_imafdchsclic_sv39_hpdcache_config_pkg.sv + - target: cv64a6_imafdch_sv39 files: - core/include/cv64a6_imafdch_sv39_config_pkg.sv @@ -70,8 +78,13 @@ sources: files: - core/cva6_accel_first_pass_decoder_stub.sv + # CLIC controller + - target: any(cv64a6_imafdchsclic_sv39_hpdcache, cv64a6_imafdchsclic_sv39_wb) + files: + - core/cva6_clic_controller.sv + # MMU - - target: any(cv64a6_imafdcv_sv39, cv64a6_imafdc_sv39, cv64a6_imafdc_sv39_hpdcache, cv64a6_imafdc_sv39_wb, cv64a6_imafdch_sv39, cv64a6_imafdch_sv39_wb, cv32a6_imac_sv0, cv32a6_imac_sv32, cv32a6_imafc_sv32) + - target: any(cv64a6_imafdcv_sv39, cv64a6_imafdc_sv39, cv64a6_imafdc_sv39_hpdcache, cv64a6_imafdchsclic_sv39_hpdcache, cv64a6_imafdc_sv39_wb, cv64a6_imafdchsclic_sv39_wb, cv64a6_imafdch_sv39, cv64a6_imafdch_sv39_wb, cv32a6_imac_sv0, cv32a6_imac_sv32, cv32a6_imafc_sv32) files: - core/cva6_mmu/cva6_tlb.sv - core/cva6_mmu/cva6_shared_tlb.sv diff --git a/core/csr_regfile.sv b/core/csr_regfile.sv index 1582e30bd3..6b67f237dd 100644 --- a/core/csr_regfile.sv +++ b/core/csr_regfile.sv @@ -127,6 +127,8 @@ module csr_regfile output logic [CVA6Cfg.VMID_WIDTH-1:0] vmid_o, // external interrupt in - SUBSYSTEM input logic [1:0] irq_i, + // selective hardware vectoring bit - CLIC + input logic clic_irq_shv_i, // inter processor interrupt -> connected to machine mode sw - SUBSYSTEM input logic ipi_i, // debug request in - ID_STAGE @@ -145,6 +147,16 @@ module csr_regfile output logic hu_o, // we are in debug mode -> that will change some decoding - EX_STAGE output logic debug_mode_o, + // CLIC mode - ID_STAGE + output logic clic_mode_o, + // TO_BE_COMPLETED - CLIC_CTRL + output riscv::intstatus_rv_t mintstatus_o, + // TO_BE_COMPLETED - CLIC_CTRL + output logic [7:0] mintthresh_o, + // TO_BE_COMPLETED - CLIC_CTRL + output logic [7:0] sintthresh_o, + // TO_BE_COMPLETED - CLIC_CTRL + output logic clic_irq_ready_o, // we are in single-step mode - COMMIT_STAGE output logic single_step_o, // L1 ICache Enable - CACHE @@ -238,10 +250,13 @@ module csr_regfile 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] mtvt_q, mtvt_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; + riscv::intstatus_rv_t mintstatus_q, mintstatus_d; + riscv::intthresh_rv_t mintthresh_q, mintthresh_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; @@ -252,7 +267,9 @@ module csr_regfile logic fiom_d, fiom_q; logic [CVA6Cfg.XLEN-1:0] stvec_q, stvec_d; + riscv::intthresh_rv_t sintthresh_q, sintthresh_d; logic [CVA6Cfg.XLEN-1:0] scounteren_q, scounteren_d; + logic [CVA6Cfg.XLEN-1:0] stvt_q, stvt_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; @@ -330,6 +347,20 @@ module csr_regfile assign vsstatus_extended = '0; end + if (CVA6Cfg.RVSCLIC) begin : gen_clic_csr_signals + assign clic_mode_o = &mtvec_q[1:0]; + assign mintstatus_o = mintstatus_q; + assign mintthresh_o = mintthresh_q.th; + assign sintthresh_o = sintthresh_q.th; + assign clic_irq_ready_o = clic_mode_o & ex_i.valid & ex_i.cause[CVA6Cfg.XLEN-1]; + end else begin : gen_dummy_clic_csr_signals + assign clic_mode_o = 1'b0; + assign mintstatus_o = '0; + assign mintthresh_o = '0; + assign sintthresh_o = '0; + assign clic_irq_ready_o = 1'b0; + 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; @@ -428,27 +459,62 @@ module csr_regfile 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; + csr_rdata = clic_mode_o ? '0 : ((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; + csr_rdata = clic_mode_o ? '0 : ((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; + if (CVA6Cfg.RVS) + csr_rdata = clic_mode_o ? {stvec_q[CVA6Cfg.XLEN-1:6], 6'b11} : {stvec_q[CVA6Cfg.XLEN-1:6], 5'b0, stvec_q[0]}; else read_access_exception = 1'b1; + riscv::CSR_SINTSTATUS: begin + if (CVA6Cfg.RVS && CVA6Cfg.RVSCLIC) begin + // sintstatus reads 0 from CLINT mode + // Return a restricted view of mintstatus (sil and uil) + csr_rdata = clic_mode_o ? {{CVA6Cfg.XLEN - 16{1'b0}}, mintstatus_q[15:0]} : '0; + end else begin + read_access_exception = 1'b1; + end + end + riscv::CSR_SINTTHRESH: begin + if (CVA6Cfg.RVS && CVA6Cfg.RVSCLIC) begin + // sintthresh reads 0 from CLINT mode + csr_rdata = clic_mode_o ? {{CVA6Cfg.XLEN - 8{1'b0}}, sintthresh_q} : '0; + end else begin + read_access_exception = 1'b1; + end + end riscv::CSR_SCOUNTEREN: if (CVA6Cfg.RVS) csr_rdata = scounteren_q; else read_access_exception = 1'b1; + riscv::CSR_STVT: begin + if (CVA6Cfg.RVS && CVA6Cfg.RVSCLIC) begin + // stvt reads 0 from CLINT mode + csr_rdata = clic_mode_o ? stvt_q : '0; + end else begin + read_access_exception = 1'b1; + end + end 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_SCAUSE: begin + if (CVA6Cfg.RVS) begin + csr_rdata = scause_q; + // In CLIC mode, reading or writing mstatus fields spp/spie in mcause is + // equivalent to reading or writing the homonymous field in mstatus. + if (CVA6Cfg.RVSCLIC && clic_mode_o) begin + csr_rdata[29:27] = {1'b0, mstatus_q.spp, mstatus_q.spie}; + end + end else begin + read_access_exception = 1'b1; + end + end riscv::CSR_STVAL: if (CVA6Cfg.RVS) csr_rdata = stval_q; else read_access_exception = 1'b1; @@ -529,14 +595,22 @@ module csr_regfile 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_MIE: csr_rdata = clic_mode_o ? '0 : 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_MTVT: csr_rdata = mtvt_q; riscv::CSR_MSCRATCH: csr_rdata = mscratch_q; riscv::CSR_MEPC: csr_rdata = mepc_q; - riscv::CSR_MCAUSE: csr_rdata = mcause_q; + riscv::CSR_MCAUSE: begin + csr_rdata = mcause_q; + // In CLIC mode, reading or writing mstatus fields mpp/mpie in mcause is + // equivalent to reading or writing the homonymous field in mstatus. + if (CVA6Cfg.RVSCLIC && clic_mode_o) begin + csr_rdata[29:27] = {mstatus_q.mpp, mstatus_q.mpie}; + end + end riscv::CSR_MTVAL: if (CVA6Cfg.TvalEn) csr_rdata = mtval_q; else csr_rdata = '0; @@ -546,7 +620,23 @@ module csr_regfile 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_MIP: csr_rdata = clic_mode_o ? '0 : mip_q; + riscv::CSR_MINTSTATUS: begin + if (CVA6Cfg.RVSCLIC) begin + // mintstatus reads 0 from CLINT mode + csr_rdata = clic_mode_o ? {{CVA6Cfg.XLEN - 32{1'b0}}, mintstatus_q} : '0; + end else begin + read_access_exception = 1'b1; + end + end + riscv::CSR_MINTTHRESH: begin + if (CVA6Cfg.RVSCLIC) begin + // mintthresh reads 0 from CLINT mode + csr_rdata = clic_mode_o ? {{CVA6Cfg.XLEN - 8{1'b0}}, mintthresh_q} : '0; + end else begin + read_access_exception = 1'b1; + end + end riscv::CSR_MENVCFG: begin if (CVA6Cfg.RVU) csr_rdata = '0 | fiom_q; else read_access_exception = 1'b1; @@ -957,9 +1047,12 @@ module csr_regfile end mip_d = mip_q; mie_d = mie_q; + mintstatus_d = mintstatus_q; + mintthresh_d = mintthresh_q; mepc_d = mepc_q; mcause_d = mcause_q; mcounteren_d = mcounteren_q; + mtvt_d = mtvt_q; mscratch_d = mscratch_q; mtval_d = mtval_q; if (CVA6Cfg.RVH) begin @@ -999,7 +1092,9 @@ module csr_regfile sepc_d = sepc_q; scause_d = scause_q; stvec_d = stvec_q; + sintthresh_d = sintthresh_q; scounteren_d = scounteren_q; + stvt_d = stvt_q; sscratch_d = sscratch_q; stval_d = stval_q; satp_d = satp_q; @@ -1182,7 +1277,8 @@ module csr_regfile if (CVA6Cfg.RVS) begin mask = (CVA6Cfg.RVH) ? mideleg_q & ~HS_DELEG_INTERRUPTS[CVA6Cfg.XLEN-1:0] : mideleg_q; // the mideleg makes sure only delegate-able register (and therefore also only implemented registers) are written - mie_d = (mie_q & ~mask) | (csr_wdata & mask); + if (!clic_mode_o) mie_d = (mie_q & ~mask) | (csr_wdata & mask); + // In CLIC mode, writes to SIE are ignored. end else begin update_access_exception = 1'b1; end @@ -1190,20 +1286,44 @@ module csr_regfile riscv::CSR_SIP: begin if (CVA6Cfg.RVS) begin - // only the supervisor software interrupt is write-able, iff delegated - mask = CVA6Cfg.XLEN'(riscv::MIP_SSIP) & mideleg_q; - mip_d = (mip_q & ~mask) | (csr_wdata & mask); + // In CLIC mode, writes to SIP are ignored. + if (!clic_mode_o) begin + // only the supervisor software interrupt is write-able, iff delegated + mask = CVA6Cfg.XLEN'(riscv::MIP_SSIP) & mideleg_q; + mip_d = (mip_q & ~mask) | (csr_wdata & mask); + end end else begin update_access_exception = 1'b1; end end riscv::CSR_STVEC: - if (CVA6Cfg.RVS) stvec_d = {csr_wdata[CVA6Cfg.XLEN-1:2], 1'b0, csr_wdata[0]}; + if (CVA6Cfg.RVS) + stvec_d = clic_mode_o ? {csr_wdata[CVA6Cfg.XLEN-1:2], 2'b11} : {csr_wdata[CVA6Cfg.XLEN-1:2], 1'b0, csr_wdata[0]}; else update_access_exception = 1'b1; riscv::CSR_SCOUNTEREN: if (CVA6Cfg.RVS) scounteren_d = {{CVA6Cfg.XLEN - 32{1'b0}}, csr_wdata[31:0]}; else update_access_exception = 1'b1; + riscv::CSR_STVT: begin + if (CVA6Cfg.RVS && CVA6Cfg.RVSCLIC) begin + // Writes are legal but ignored in CLINT mode + if (clic_mode_o) begin + stvt_d = {csr_wdata[CVA6Cfg.XLEN-1:8], 8'b0}; + end + end else begin + update_access_exception = 1'b1; + end + end + riscv::CSR_SINTTHRESH: begin + if (CVA6Cfg.RVS && CVA6Cfg.RVSCLIC) begin + // Writes are legal but ignored in CLINT mode + if (clic_mode_o) begin + sintthresh_d.th = csr_wdata[7:0]; + end + end else begin + update_access_exception = 1'b1; + end + end riscv::CSR_SSCRATCH: if (CVA6Cfg.RVS) sscratch_d = csr_wdata; else update_access_exception = 1'b1; @@ -1436,29 +1556,32 @@ module csr_regfile end // mask the register so that unsupported interrupts can never be set riscv::CSR_MIE: begin - if (CVA6Cfg.RVH) begin - mask = HS_DELEG_INTERRUPTS[CVA6Cfg.XLEN-1:0] - | CVA6Cfg.XLEN'(riscv::MIP_SSIP) - | CVA6Cfg.XLEN'(riscv::MIP_STIP) - | CVA6Cfg.XLEN'(riscv::MIP_SEIP) - | CVA6Cfg.XLEN'(riscv::MIP_MSIP) - | CVA6Cfg.XLEN'(riscv::MIP_MTIP) - | CVA6Cfg.XLEN'(riscv::MIP_MEIP); - end else begin - if (CVA6Cfg.RVS) begin - mask = CVA6Cfg.XLEN'(riscv::MIP_SSIP) + // In CLIC mode, writes to MIE are ignored. + if (!clic_mode_o) begin + if (CVA6Cfg.RVH) begin + mask = HS_DELEG_INTERRUPTS[CVA6Cfg.XLEN-1:0] + | CVA6Cfg.XLEN'(riscv::MIP_SSIP) | CVA6Cfg.XLEN'(riscv::MIP_STIP) | CVA6Cfg.XLEN'(riscv::MIP_SEIP) | CVA6Cfg.XLEN'(riscv::MIP_MSIP) | CVA6Cfg.XLEN'(riscv::MIP_MTIP) | CVA6Cfg.XLEN'(riscv::MIP_MEIP); end else begin - mask = CVA6Cfg.XLEN'(riscv::MIP_MSIP) - | CVA6Cfg.XLEN'(riscv::MIP_MTIP) - | CVA6Cfg.XLEN'(riscv::MIP_MEIP); + if (CVA6Cfg.RVS) begin + mask = CVA6Cfg.XLEN'(riscv::MIP_SSIP) + | CVA6Cfg.XLEN'(riscv::MIP_STIP) + | CVA6Cfg.XLEN'(riscv::MIP_SEIP) + | CVA6Cfg.XLEN'(riscv::MIP_MSIP) + | CVA6Cfg.XLEN'(riscv::MIP_MTIP) + | CVA6Cfg.XLEN'(riscv::MIP_MEIP); + end else begin + mask = CVA6Cfg.XLEN'(riscv::MIP_MSIP) + | CVA6Cfg.XLEN'(riscv::MIP_MTIP) + | CVA6Cfg.XLEN'(riscv::MIP_MEIP); + end end + mie_d = (mie_q & ~mask) | (csr_wdata & mask); // we only support supervisor and M-mode interrupts end - mie_d = (mie_q & ~mask) | (csr_wdata & mask); // we only support supervisor and M-mode interrupts end riscv::CSR_MTVEC: begin @@ -1468,11 +1591,25 @@ module csr_regfile // we are in vector mode, this implementation requires the additional // alignment constraint of 64 * 4 bytes if (DirVecOnly) mtvec_d = {csr_wdata[CVA6Cfg.XLEN-1:8], 7'b0, DirVecOnly}; + // we are in CLIC mode. + if (CVA6Cfg.RVSCLIC && &csr_wdata[1:0]) + mtvec_d = {csr_wdata[CVA6Cfg.XLEN-1:8], 6'b0, csr_wdata[1:0]}; + end riscv::CSR_MCOUNTEREN: begin if (CVA6Cfg.RVU) mcounteren_d = {{CVA6Cfg.XLEN - 32{1'b0}}, csr_wdata[31:0]}; else update_access_exception = 1'b1; end + riscv::CSR_MTVT: begin + if (CVA6Cfg.RVSCLIC) begin + // Writes are legal but ignored in CLINT mode + if (clic_mode_o) begin + mtvt_d = {csr_wdata[CVA6Cfg.XLEN-1:8], 8'b0}; + end + end else begin + update_access_exception = 1'b1; + end + end riscv::CSR_MSCRATCH: mscratch_d = csr_wdata; riscv::CSR_MEPC: mepc_d = {csr_wdata[CVA6Cfg.XLEN-1:1], 1'b0}; @@ -1487,19 +1624,22 @@ module csr_regfile if (CVA6Cfg.RVH) mtval2_d = csr_wdata; else update_access_exception = 1'b1; riscv::CSR_MIP: begin - if (CVA6Cfg.RVH) begin - mask = CVA6Cfg.XLEN'(riscv::MIP_SSIP) - | CVA6Cfg.XLEN'(riscv::MIP_STIP) - | CVA6Cfg.XLEN'(riscv::MIP_SEIP) - | CVA6Cfg.XLEN'(riscv::MIP_VSSIP); - end else if (CVA6Cfg.RVS) begin - mask = CVA6Cfg.XLEN'(riscv::MIP_SSIP) - | CVA6Cfg.XLEN'(riscv::MIP_STIP) - | CVA6Cfg.XLEN'(riscv::MIP_SEIP); - end else begin - mask = '0; + // In CLIC mode, writes to MIP are ignored. + if (!clic_mode_o) begin + if (CVA6Cfg.RVH) begin + mask = CVA6Cfg.XLEN'(riscv::MIP_SSIP) + | CVA6Cfg.XLEN'(riscv::MIP_STIP) + | CVA6Cfg.XLEN'(riscv::MIP_SEIP) + | CVA6Cfg.XLEN'(riscv::MIP_VSSIP); + end else if (CVA6Cfg.RVS) begin + mask = CVA6Cfg.XLEN'(riscv::MIP_SSIP) + | CVA6Cfg.XLEN'(riscv::MIP_STIP) + | CVA6Cfg.XLEN'(riscv::MIP_SEIP); + end else begin + mask = '0; + end + mip_d = (mip_q & ~mask) | (csr_wdata & mask); end - mip_d = (mip_q & ~mask) | (csr_wdata & mask); end riscv::CSR_MENVCFG: if (CVA6Cfg.RVU) fiom_d = csr_wdata[0]; riscv::CSR_MENVCFGH: begin @@ -1509,6 +1649,16 @@ module csr_regfile if (CVA6Cfg.PerfCounterEn) mcountinhibit_d = {csr_wdata[MHPMCounterNum+2:2], 1'b0, csr_wdata[0]}; else mcountinhibit_d = '0; + riscv::CSR_MINTTHRESH: begin + if (CVA6Cfg.RVSCLIC) begin + // Writes are legal but ignored in CLINT mode + if (clic_mode_o) begin + mintthresh_d.th = csr_wdata[7:0]; + end + end else begin + update_access_exception = 1'b1; + end + end // performance counters riscv::CSR_MCYCLE: cycle_d[CVA6Cfg.XLEN-1:0] = csr_wdata; riscv::CSR_MCYCLEH: @@ -1811,12 +1961,13 @@ module csr_regfile // a m-mode trap might be delegated if we are taking it in S mode // first figure out if this was an exception or an interrupt e.g.: look at bit (XLEN-1) // the cause register can only be $clog2(CVA6Cfg.XLEN) bits long (as we only support XLEN exceptions) + // In CLIC mode, xideleg ceases to have effect. if (CVA6Cfg.RVH) begin if ((ex_i.cause[CVA6Cfg.XLEN-1] && mideleg_q[ex_i.cause[$clog2( CVA6Cfg.XLEN )-1:0]] && ~hideleg_q[ex_i.cause[$clog2( CVA6Cfg.XLEN - )-1:0]]) || (~ex_i.cause[CVA6Cfg.XLEN-1] && medeleg_q[ex_i.cause[$clog2( + )-1:0]] && ~clic_mode_o) || (~ex_i.cause[CVA6Cfg.XLEN-1] && medeleg_q[ex_i.cause[$clog2( CVA6Cfg.XLEN )-1:0]] && ~hedeleg_q[ex_i.cause[$clog2( CVA6Cfg.XLEN @@ -1826,7 +1977,7 @@ module csr_regfile trap_to_priv_lvl = (priv_lvl_o == riscv::PRIV_LVL_M) ? riscv::PRIV_LVL_M : riscv::PRIV_LVL_S; end else if ((ex_i.cause[CVA6Cfg.XLEN-1] && hideleg_q[ex_i.cause[$clog2( CVA6Cfg.XLEN - )-1:0]]) || (~ex_i.cause[CVA6Cfg.XLEN-1] && hedeleg_q[ex_i.cause[$clog2( + )-1:0]] && ~clic_mode_o) || (~ex_i.cause[CVA6Cfg.XLEN-1] && hedeleg_q[ex_i.cause[$clog2( CVA6Cfg.XLEN )-1:0]])) begin trap_to_priv_lvl = (priv_lvl_o == riscv::PRIV_LVL_M) ? riscv::PRIV_LVL_M : riscv::PRIV_LVL_S; @@ -1837,7 +1988,7 @@ module csr_regfile if (CVA6Cfg.RVS) begin if ((ex_i.cause[CVA6Cfg.XLEN-1] && mideleg_q[ex_i.cause[$clog2( CVA6Cfg.XLEN - )-1:0]]) || (~ex_i.cause[CVA6Cfg.XLEN-1] && medeleg_q[ex_i.cause[$clog2( + )-1:0]] && ~clic_mode_o) || (~ex_i.cause[CVA6Cfg.XLEN-1] && medeleg_q[ex_i.cause[$clog2( CVA6Cfg.XLEN )-1:0]])) begin // traps never transition from a more-privileged mode to a less privileged mode @@ -1876,6 +2027,11 @@ module csr_regfile mstatus_d.spp = priv_lvl_q[0]; // set cause scause_d = ex_i.cause; + // update the current and previous interrupt level + if (CVA6Cfg.RVSCLIC && clic_mode_o && ex_i.cause[CVA6Cfg.XLEN-1]) begin + mintstatus_d.sil = ex_i.cause[23:16]; + scause_d[23:16] = mintstatus_q.sil; + end // set epc sepc_d = {{CVA6Cfg.XLEN - CVA6Cfg.VLEN{pc_i[CVA6Cfg.VLEN-1]}}, pc_i}; // set mtval or stval @@ -1914,6 +2070,11 @@ module csr_regfile // save the previous privilege mode mstatus_d.mpp = priv_lvl_q; mcause_d = ex_i.cause; + // update the current and previous interrupt level + if (CVA6Cfg.RVSCLIC && clic_mode_o && ex_i.cause[CVA6Cfg.XLEN-1]) begin + mintstatus_d.mil = ex_i.cause[23:16]; + mcause_d[23:16] = mintstatus_q.mil; + end // set epc mepc_d = {{CVA6Cfg.XLEN - CVA6Cfg.VLEN{pc_i[CVA6Cfg.VLEN-1]}}, pc_i}; // set mtval or stval @@ -2129,6 +2290,9 @@ module csr_regfile mstatus_d.mpv = 1'b0; if (mstatus_q.mpp != riscv::PRIV_LVL_M) mstatus_d.mprv = 1'b0; end + // restore mintstatus + if (CVA6Cfg.RVSCLIC && clic_mode_o && mcause_q[CVA6Cfg.XLEN-1]) + mintstatus_d.mil = mcause_q[23:16]; end if (CVA6Cfg.RVS && sret && ((CVA6Cfg.RVH && !v_q) || !CVA6Cfg.RVH)) begin @@ -2149,6 +2313,9 @@ module csr_regfile hstatus_d.spv = 1'b0; mstatus_d.mprv = 1'b0; end + // restore sintstatus + if (CVA6Cfg.RVSCLIC && clic_mode_o && scause_q[CVA6Cfg.XLEN-1]) + mintstatus_d.sil = scause_q[23:16]; end if (CVA6Cfg.RVH) begin @@ -2392,7 +2559,7 @@ module csr_regfile wfi_d = wfi_q; // if there is any (enabled) interrupt pending un-stall the core // also un-stall if we want to enter debug mode - if (|(mip_q & mie_q) || (CVA6Cfg.DebugEn && debug_req_i) || irq_i[1]) begin + if ((CVA6Cfg.DebugEn && debug_req_i) || (!clic_mode_o && (|(mip_q & mie_q) || irq_i[1])) || clic_irq_ready_o) begin wfi_d = 1'b0; // or alternatively if there is no exception pending and we are not in debug mode wait here // for the interrupt @@ -2403,10 +2570,16 @@ module csr_regfile // output assignments dependent on privilege mode always_comb begin : priv_output - trap_vector_base_o = {mtvec_q[CVA6Cfg.VLEN-1:2], 2'b0}; + trap_vector_base_o = (CVA6Cfg.RVSCLIC && clic_mode_o && clic_irq_shv_i && ex_i.cause[CVA6Cfg.XLEN-1]) ? {mtvt_q[CVA6Cfg.VLEN-1:8], 8'b0} : {mtvec_q[CVA6Cfg.VLEN-1:2], 2'b0}; // output user mode stvec if (CVA6Cfg.RVS && trap_to_priv_lvl == riscv::PRIV_LVL_S) begin - trap_vector_base_o = (CVA6Cfg.RVH && trap_to_v) ? {vstvec_q[CVA6Cfg.VLEN-1:2], 2'b0} : {stvec_q[CVA6Cfg.VLEN-1:2], 2'b0}; + if (CVA6Cfg.RVSCLIC && clic_mode_o && clic_irq_shv_i && ex_i.cause[CVA6Cfg.XLEN-1]) begin + trap_vector_base_o = {stvt_q[CVA6Cfg.VLEN-1:8], 8'b0}; + end else if (CVA6Cfg.RVH && trap_to_v) begin + trap_vector_base_o = {vstvec_q[CVA6Cfg.VLEN-1:2], 2'b0}; + end else begin + trap_vector_base_o = {stvec_q[CVA6Cfg.VLEN-1:2], 2'b0}; + end end // if we are in debug mode jump to a specific address @@ -2419,9 +2592,14 @@ module csr_regfile // we want to spare the costly addition. Furthermore check to which // privilege level we are jumping and whether the vectored mode is // activated for _that_ privilege level. + // Note for CLIC mode: according to the spec, we should actually jump to the address + // stored at trap_vector_base. Since this would have significant HW implications and no + // significant benefit, we conciously diverge from the spec here by jumping to + // trap_vector_base instead. if (ex_i.cause[CVA6Cfg.XLEN-1] && ((((CVA6Cfg.RVS || CVA6Cfg.RVU) && trap_to_priv_lvl == riscv::PRIV_LVL_M && (!CVA6Cfg.DirectVecOnly && mtvec_q[0])) || (!CVA6Cfg.RVS && !CVA6Cfg.RVU && (!CVA6Cfg.DirectVecOnly && mtvec_q[0]))) - || (CVA6Cfg.RVS && trap_to_priv_lvl == riscv::PRIV_LVL_S && !trap_to_v && stvec_q[0]))) begin + || (CVA6Cfg.RVS && trap_to_priv_lvl == riscv::PRIV_LVL_S && !trap_to_v && stvec_q[0]) + || (CVA6Cfg.RVSCLIC && clic_mode_o && clic_irq_shv_i))) begin trap_vector_base_o[7:2] = ex_i.cause[5:0]; end if (ex_i.cause[CVA6Cfg.XLEN-1] && @@ -2559,9 +2737,12 @@ module csr_regfile mtvec_q <= '0; mip_q <= {CVA6Cfg.XLEN{1'b0}}; mie_q <= {CVA6Cfg.XLEN{1'b0}}; + mintstatus_q <= 32'b0; + mintthresh_q <= 8'b0; mepc_q <= {CVA6Cfg.XLEN{1'b0}}; mcause_q <= {CVA6Cfg.XLEN{1'b0}}; mcounteren_q <= {CVA6Cfg.XLEN{1'b0}}; + mtvt_q <= {CVA6Cfg.XLEN{1'b0}}; mscratch_q <= {CVA6Cfg.XLEN{1'b0}}; mtval_q <= {CVA6Cfg.XLEN{1'b0}}; fiom_q <= '0; @@ -2641,9 +2822,12 @@ module csr_regfile mtvec_q <= mtvec_d; mip_q <= mip_d; mie_q <= mie_d; + mintstatus_q <= mintstatus_d; + mintthresh_q <= mintthresh_d; mepc_q <= mepc_d; mcause_q <= mcause_d; mcounteren_q <= mcounteren_d; + mtvt_q <= mtvt_d; mscratch_q <= mscratch_d; if (CVA6Cfg.TvalEn) mtval_q <= mtval_d; fiom_q <= fiom_d; diff --git a/core/cva6.sv b/core/cva6.sv index f7cb510f14..cd9af3b0a5 100644 --- a/core/cva6.sv +++ b/core/cva6.sv @@ -306,6 +306,15 @@ module cva6 input logic time_irq_i, // Debug (async) request - SUBSYSTEM input logic debug_req_i, + // CLIC interface + input logic clic_irq_valid_i, // CLIC interrupt request + input logic [$clog2(CVA6Cfg.CLICNumInterruptSrc)-1:0] clic_irq_id_i, // interrupt source ID + input logic [7:0] clic_irq_level_i, // interrupt level is 8-bit from CLIC spec + input riscv::priv_lvl_t clic_irq_priv_i, // CLIC interrupt privilege level + input logic clic_irq_shv_i, // selective hardware vectoring bit + output logic clic_irq_ready_o, // core side interrupt hanshake (ready) + input logic clic_kill_req_i, // kill request + output logic clic_kill_ack_o, // kill acknowledge // Probes to build RVFI, can be left open when not used - RVFI output rvfi_probes_t rvfi_probes_o, // CVXIF request - SUBSYSTEM @@ -549,6 +558,10 @@ module cva6 logic tsr_csr_id; logic hu; irq_ctrl_t irq_ctrl_csr_id; + logic clic_mode; + riscv::intstatus_rv_t mintstatus_csr; + logic [7:0] mintthresh_csr; + logic [7:0] sintthresh_csr; logic dcache_en_csr_nbdcache; logic csr_write_fflags_commit_cs; logic icache_en_csr; @@ -645,6 +658,12 @@ module cva6 end end + // ---------------------- + // CLIC Controller <-> ID + // ---------------------- + logic clic_irq_req_id; + logic [CVA6Cfg.XLEN-1:0] clic_irq_cause_id; + // -------------- // Frontend // -------------- @@ -717,6 +736,9 @@ module cva6 .vs_i (vs), .irq_i (irq_i), .irq_ctrl_i (irq_ctrl_csr_id), + .clic_mode_i (clic_mode), + .clic_irq_req_i (clic_irq_req_id), + .clic_irq_cause_i (clic_irq_cause_id), .debug_mode_i (debug_mode), .tvm_i (tvm_csr_id), .tw_i (tw_csr_id), @@ -1127,6 +1149,12 @@ module cva6 .fprec_o (fprec_csr_ex), .vs_o (vs), .irq_ctrl_o (irq_ctrl_csr_id), + .clic_mode_o (clic_mode), + .mintstatus_o (mintstatus_csr), + .mintthresh_o (mintthresh_csr), + .sintthresh_o (sintthresh_csr), + .clic_irq_shv_i (clic_irq_shv_i), + .clic_irq_ready_o (clic_irq_ready_o), .ld_st_priv_lvl_o (ld_st_priv_lvl_csr_ex), .ld_st_v_o (ld_st_v_csr_ex), .csr_hs_ld_st_inst_i (csr_hs_ld_st_inst_ex), @@ -1563,6 +1591,40 @@ module cva6 assign cvxif_req_o = cvxif_req; end : gen_no_accelerator + // ------------------- + // CLIC Controller + // ------------------- + if (CVA6Cfg.RVSCLIC) begin : gen_clic_controller + cva6_clic_controller #( + .CVA6Cfg(CVA6Cfg), + .irq_ctrl_t(irq_ctrl_t) + ) i_clic_controller ( + .clk_i (clk_i), + .rst_ni (rst_ni), + // from CSR file + .priv_lvl_i (priv_lvl), + .irq_ctrl_i (irq_ctrl_csr_id), + .mintthresh_i (mintthresh_csr), + .sintthresh_i (sintthresh_csr), + .mintstatus_i (mintstatus_csr), + // from/to CLIC + .clic_irq_valid_i(clic_irq_valid_i), + .clic_irq_ready_i(clic_irq_ready_o), + .clic_irq_id_i (clic_irq_id_i), + .clic_irq_level_i(clic_irq_level_i), + .clic_irq_priv_i (clic_irq_priv_i), + .clic_kill_req_i (clic_kill_req_i), + .clic_kill_ack_o (clic_kill_ack_o), + // to ID stage + .clic_irq_req_o (clic_irq_req_id), + .clic_irq_cause_o(clic_irq_cause_id) + ); + end else begin : gen_dummy_clic_controller + assign clic_kill_ack_o = 1'b0; + assign clic_irq_req_id = 1'b0; + assign clic_irq_cause_id = '0; + end + // ------------------- // Parameter Check // ------------------- diff --git a/core/cva6_clic_controller.sv b/core/cva6_clic_controller.sv new file mode 100644 index 0000000000..3bb4821eba --- /dev/null +++ b/core/cva6_clic_controller.sv @@ -0,0 +1,99 @@ +// Copyright 2023 ETH Zurich and University of Bologna. +// Solderpad Hardware License, Version 0.51, see LICENSE for details. +// SPDX-License-Identifier: SHL-0.51 +// +// Author: Nils Wistoff + +module cva6_clic_controller #( + parameter config_pkg::cva6_cfg_t CVA6Cfg = config_pkg::cva6_cfg_empty, + parameter type irq_ctrl_t = logic +) ( + input logic clk_i, + input logic rst_ni, + // from CSR file + input riscv::priv_lvl_t priv_lvl_i, // current privilege level + input irq_ctrl_t irq_ctrl_i, + input logic [7:0] mintthresh_i, // M-mode interrupt threshold + input logic [7:0] sintthresh_i, // S-mode interrupt threshold + input riscv::intstatus_rv_t mintstatus_i, // interrupt status + // from/to CLIC + input logic clic_irq_valid_i, // interrupt is valid + input logic clic_irq_ready_i, // interrupt is acknowledged + input logic [$clog2(CVA6Cfg.CLICNumInterruptSrc)-1:0] clic_irq_id_i, // interrupt ID + input logic [7:0] clic_irq_level_i, // interrupt level + input riscv::priv_lvl_t clic_irq_priv_i, // interrupt privilege level + input logic clic_kill_req_i, // kill request + output logic clic_kill_ack_o, // kill acknowledge + // to ID stage + output logic clic_irq_req_o, + output logic [CVA6Cfg.XLEN-1:0] clic_irq_cause_o +); + // ------- + // Trigger + // ------- + // Check if the interrupt level of the current interrupt exceeds the current + // irq threshold and global interrupt are enabled (otherwise it won't fire). + // The effective interrupt threshold is the maximum of mintstatus.mil and + // mintthresh, because interrupts with higher level have priority. + logic [7:0] max_mthresh, max_sthresh; + + assign max_mthresh = mintthresh_i > mintstatus_i.mil ? mintthresh_i : mintstatus_i.mil; + assign max_sthresh = sintthresh_i > mintstatus_i.sil ? sintthresh_i : mintstatus_i.sil; + + // Determine if CLIC interrupt shall be accepted + always_comb begin : clic_irq_accept + clic_irq_req_o = 1'b0; + unique case (priv_lvl_i) + riscv::PRIV_LVL_M: begin + // Take M-mode interrupts with higher level + if (clic_irq_priv_i == riscv::PRIV_LVL_M) begin + clic_irq_req_o = (clic_irq_level_i > max_mthresh) && (clic_irq_valid_i); + end + end + riscv::PRIV_LVL_S: begin + // Take all M-mode interrupts + if (clic_irq_priv_i == riscv::PRIV_LVL_M) begin + clic_irq_req_o = clic_irq_valid_i; + // Take S-mode interrupts with higher level + end else if (clic_irq_priv_i == riscv::PRIV_LVL_S) begin + clic_irq_req_o = (clic_irq_level_i > max_sthresh) && (clic_irq_valid_i) && irq_ctrl_i.sie; + end + end + riscv::PRIV_LVL_U: begin + // Take all M-mode and S-mode interrupts + clic_irq_req_o = clic_irq_valid_i; + end + default: ; + endcase + end + + // ------------------ + // Interrupt Packager + // ------------------ + // Pack interrupt cause to be inserted into the pipeline + assign clic_irq_cause_o = { + 1'b1, // This is an irq + {CVA6Cfg.XLEN - 25{1'b0}}, // XLEN-2...24 + clic_irq_level_i, // to mintstatus.mil + {16 - $clog2(CVA6Cfg.CLICNumInterruptSrc) {1'b0}}, // 15...IDWidth + clic_irq_id_i + }; // to mcause + + // ------------ + // Kill Control + // ------------ + // Track whether an irq was inserted into the pipeline (accepted) but not acknowlegded yet + logic irq_inflight_d, irq_inflight_q; + // Set when accepting irq, clear when acknowledging or killing + assign irq_inflight_d = irq_inflight_q ? ~(clic_irq_ready_i | clic_kill_ack_o) : clic_irq_req_o; + // Acknowledge kill if no irq is inflight and irq is not accepted this cycle + assign clic_kill_ack_o = clic_kill_req_i & ~irq_inflight_q & ~clic_irq_req_o; + + always_ff @(posedge clk_i or negedge rst_ni) begin + if (!rst_ni) begin + irq_inflight_q <= 1'b0; + end else begin + irq_inflight_q <= irq_inflight_d; + end + end +endmodule diff --git a/core/decoder.sv b/core/decoder.sv index 1cbb499f13..f8860eb0b8 100644 --- a/core/decoder.sv +++ b/core/decoder.sv @@ -56,6 +56,12 @@ module decoder input logic [1:0] irq_i, // Interrupt control status - CSR_REGFILE input irq_ctrl_t irq_ctrl_i, + // TO_BE_COMPLETED - CLIC_CTRL + input logic clic_mode_i, + // TO_BE_COMPLETED - CLIC_CTRL + input logic clic_irq_req_i, + // TO_BE_COMPLETED - CLIC_CTRL + input logic [CVA6Cfg.XLEN-1:0] clic_irq_cause_i, // Current privilege level - CSR_REGFILE input riscv::priv_lvl_t priv_lvl_i, // Current virtualization mode - CSR_REGFILE @@ -1603,57 +1609,63 @@ module decoder // we have three interrupt sources: external interrupts, software interrupts, timer interrupts (order of precedence) // for two privilege levels: Supervisor and Machine Mode // Virtual Supervisor Timer Interrupt - if (CVA6Cfg.RVH) begin - if (irq_ctrl_i.mie[riscv::IRQ_VS_TIMER] && irq_ctrl_i.mip[riscv::IRQ_VS_TIMER]) begin - interrupt_cause = INTERRUPTS.VS_TIMER; + if (CVA6Cfg.RVSCLIC && clic_mode_i) begin + if (clic_irq_req_i) begin + interrupt_cause = clic_irq_cause_i; end - // Virtual Supervisor Software Interrupt - if (irq_ctrl_i.mie[riscv::IRQ_VS_SOFT] && irq_ctrl_i.mip[riscv::IRQ_VS_SOFT]) begin - interrupt_cause = INTERRUPTS.VS_SW; - end - // Virtual Supervisor External Interrupt - if (irq_ctrl_i.mie[riscv::IRQ_VS_EXT] && (irq_ctrl_i.mip[riscv::IRQ_VS_EXT])) begin - interrupt_cause = INTERRUPTS.VS_EXT; + end else begin + if (CVA6Cfg.RVH) begin + if (irq_ctrl_i.mie[riscv::IRQ_VS_TIMER] && irq_ctrl_i.mip[riscv::IRQ_VS_TIMER]) begin + interrupt_cause = INTERRUPTS.VS_TIMER; + end + // Virtual Supervisor Software Interrupt + if (irq_ctrl_i.mie[riscv::IRQ_VS_SOFT] && irq_ctrl_i.mip[riscv::IRQ_VS_SOFT]) begin + interrupt_cause = INTERRUPTS.VS_SW; + end + // Virtual Supervisor External Interrupt + if (irq_ctrl_i.mie[riscv::IRQ_VS_EXT] && (irq_ctrl_i.mip[riscv::IRQ_VS_EXT])) begin + interrupt_cause = INTERRUPTS.VS_EXT; + end + // Hypervisor Guest External Interrupts + if (irq_ctrl_i.mie[riscv::IRQ_HS_EXT] && irq_ctrl_i.mip[riscv::IRQ_HS_EXT]) begin + interrupt_cause = INTERRUPTS.HS_EXT; + end end - // Hypervisor Guest External Interrupts - if (irq_ctrl_i.mie[riscv::IRQ_HS_EXT] && irq_ctrl_i.mip[riscv::IRQ_HS_EXT]) begin - interrupt_cause = INTERRUPTS.HS_EXT; + if (CVA6Cfg.RVS) begin + // Supervisor Timer Interrupt + if (irq_ctrl_i.mie[riscv::IRQ_S_TIMER] && irq_ctrl_i.mip[riscv::IRQ_S_TIMER]) begin + interrupt_cause = INTERRUPTS.S_TIMER; + end + // Supervisor Software Interrupt + if (irq_ctrl_i.mie[riscv::IRQ_S_SOFT] && irq_ctrl_i.mip[riscv::IRQ_S_SOFT]) begin + interrupt_cause = INTERRUPTS.S_SW; + end + // Supervisor External Interrupt + // The logical-OR of the software-writable bit and the signal from the external interrupt controller is + // used to generate external interrupts to the supervisor + if (irq_ctrl_i.mie[riscv::IRQ_S_EXT] && (irq_ctrl_i.mip[riscv::IRQ_S_EXT] | irq_i[ariane_pkg::SupervisorIrq])) begin + interrupt_cause = INTERRUPTS.S_EXT; + end end - end - if (CVA6Cfg.RVS) begin - // Supervisor Timer Interrupt - if (irq_ctrl_i.mie[riscv::IRQ_S_TIMER] && irq_ctrl_i.mip[riscv::IRQ_S_TIMER]) begin - interrupt_cause = INTERRUPTS.S_TIMER; + // Machine Timer Interrupt + if (irq_ctrl_i.mip[riscv::IRQ_M_TIMER] && irq_ctrl_i.mie[riscv::IRQ_M_TIMER]) begin + interrupt_cause = INTERRUPTS.M_TIMER; end - // Supervisor Software Interrupt - if (irq_ctrl_i.mie[riscv::IRQ_S_SOFT] && irq_ctrl_i.mip[riscv::IRQ_S_SOFT]) begin - interrupt_cause = INTERRUPTS.S_SW; + // Machine Mode Software Interrupt + if (irq_ctrl_i.mip[riscv::IRQ_M_SOFT] && irq_ctrl_i.mie[riscv::IRQ_M_SOFT]) begin + interrupt_cause = INTERRUPTS.M_SW; end - // Supervisor External Interrupt - // The logical-OR of the software-writable bit and the signal from the external interrupt controller is - // used to generate external interrupts to the supervisor - if (irq_ctrl_i.mie[riscv::IRQ_S_EXT] && (irq_ctrl_i.mip[riscv::IRQ_S_EXT] | irq_i[ariane_pkg::SupervisorIrq])) begin - interrupt_cause = INTERRUPTS.S_EXT; + // Machine Mode External Interrupt + if (irq_ctrl_i.mip[riscv::IRQ_M_EXT] && irq_ctrl_i.mie[riscv::IRQ_M_EXT]) begin + interrupt_cause = INTERRUPTS.M_EXT; end end - // Machine Timer Interrupt - if (irq_ctrl_i.mip[riscv::IRQ_M_TIMER] && irq_ctrl_i.mie[riscv::IRQ_M_TIMER]) begin - interrupt_cause = INTERRUPTS.M_TIMER; - end - // Machine Mode Software Interrupt - if (irq_ctrl_i.mip[riscv::IRQ_M_SOFT] && irq_ctrl_i.mie[riscv::IRQ_M_SOFT]) begin - interrupt_cause = INTERRUPTS.M_SW; - end - // Machine Mode External Interrupt - if (irq_ctrl_i.mip[riscv::IRQ_M_EXT] && irq_ctrl_i.mie[riscv::IRQ_M_EXT]) begin - interrupt_cause = INTERRUPTS.M_EXT; - end - if (interrupt_cause[CVA6Cfg.XLEN-1] && irq_ctrl_i.global_enable) begin // However, if bit i in mideleg is set, interrupts are considered to be globally enabled if the hart’s current privilege // mode equals the delegated privilege mode (S or U) and that mode’s interrupt enable bit // (SIE or UIE in mstatus) is set, or if the current privilege mode is less than the delegated privilege mode. - if (irq_ctrl_i.mideleg[interrupt_cause[$clog2(CVA6Cfg.XLEN)-1:0]]) begin + // In CLIC mode, xideleg ceases to have effect. + if (irq_ctrl_i.mideleg[interrupt_cause[$clog2(CVA6Cfg.XLEN)-1:0]] && !clic_mode_i) begin if (CVA6Cfg.RVH) begin : hyp_int_gen if (v_i && irq_ctrl_i.hideleg[interrupt_cause[$clog2(CVA6Cfg.XLEN)-1:0]]) begin if ((irq_ctrl_i.sie && priv_lvl_i == riscv::PRIV_LVL_S) || priv_lvl_i == riscv::PRIV_LVL_U) begin diff --git a/core/id_stage.sv b/core/id_stage.sv index 79c9031a2c..bb2aa29299 100644 --- a/core/id_stage.sv +++ b/core/id_stage.sv @@ -67,6 +67,12 @@ module id_stage #( input logic [1:0] irq_i, // Interrupt control status - CSR_REGFILE input irq_ctrl_t irq_ctrl_i, + // TO_BE_COMPLETED - CLIC_CTRL + input logic clic_mode_i, + // TO_BE_COMPLETED - CLIC_CTRL + input logic clic_irq_req_i, + // TO_BE_COMPLETED - CLIC_CTRL + input logic [CVA6Cfg.XLEN-1:0] clic_irq_cause_i, // Is current mode debug ? - CSR_REGFILE input logic debug_mode_i, // Trap virtual memory - CSR_REGFILE @@ -232,6 +238,9 @@ module id_stage #( ) decoder_i ( .debug_req_i, .irq_ctrl_i, + .clic_mode_i (clic_mode_i), + .clic_irq_req_i (clic_irq_req_i), + .clic_irq_cause_i (clic_irq_cause_i), .irq_i, .pc_i (fetch_entry_i[i].address), .is_compressed_i (is_compressed_cmp[i]), diff --git a/core/include/build_config_pkg.sv b/core/include/build_config_pkg.sv index af72dedd60..1005cdac0a 100644 --- a/core/include/build_config_pkg.sv +++ b/core/include/build_config_pkg.sv @@ -69,6 +69,7 @@ package build_config_pkg; cfg.RVH = CVA6Cfg.RVH; cfg.RVZCB = CVA6Cfg.RVZCB; cfg.RVZCMP = CVA6Cfg.RVZCMP; + cfg.RVSCLIC = CVA6Cfg.RVSCLIC; cfg.XFVec = CVA6Cfg.XFVec; cfg.CvxifEn = CVA6Cfg.CvxifEn; cfg.RVZiCond = CVA6Cfg.RVZiCond; @@ -108,6 +109,7 @@ package build_config_pkg; cfg.PMPAddrRstVal = CVA6Cfg.PMPAddrRstVal; cfg.PMPEntryReadOnly = CVA6Cfg.PMPEntryReadOnly; cfg.NOCType = CVA6Cfg.NOCType; + cfg.CLICNumInterruptSrc = CVA6Cfg.CLICNumInterruptSrc; cfg.NrNonIdempotentRules = CVA6Cfg.NrNonIdempotentRules; cfg.NonIdempotentAddrBase = CVA6Cfg.NonIdempotentAddrBase; cfg.NonIdempotentLength = CVA6Cfg.NonIdempotentLength; diff --git a/core/include/config_pkg.sv b/core/include/config_pkg.sv index 456a2db746..dcdd0e5957 100644 --- a/core/include/config_pkg.sv +++ b/core/include/config_pkg.sv @@ -62,6 +62,8 @@ package config_pkg; bit RVZCB; // Zcmp RISC-V extension bit RVZCMP; + // CLIC extension + bit RVSCLIC; // Zicond RISC-V extension bit RVZiCond; // Zicntr RISC-V extension @@ -130,6 +132,8 @@ package config_pkg; bit CvxifEn; // NOC bus type noc_type_e NOCType; + // Number of interrupt signals from the CLIC. + int unsigned CLICNumInterruptSrc; // AXI address width int unsigned AxiAddrWidth; // AXI data width @@ -240,6 +244,7 @@ package config_pkg; bit RVH; bit RVZCB; bit RVZCMP; + bit RVSCLIC; bit XFVec; bit CvxifEn; bit RVZiCond; @@ -285,6 +290,7 @@ package config_pkg; logic [63:0][63:0] PMPAddrRstVal; bit [63:0] PMPEntryReadOnly; noc_type_e NOCType; + int unsigned CLICNumInterruptSrc; int unsigned NrNonIdempotentRules; logic [NrMaxRules-1:0][63:0] NonIdempotentAddrBase; logic [NrMaxRules-1:0][63:0] NonIdempotentLength; diff --git a/core/include/cv32a60x_config_pkg_deprecated.sv b/core/include/cv32a60x_config_pkg_deprecated.sv index c2637baf1e..b53db73bcf 100644 --- a/core/include/cv32a60x_config_pkg_deprecated.sv +++ b/core/include/cv32a60x_config_pkg_deprecated.sv @@ -27,6 +27,7 @@ package cva6_config_pkg; localparam CVA6ConfigBExtEn = 1; localparam CVA6ConfigVExtEn = 0; localparam CVA6ConfigRVZiCond = 1; + localparam CVA6ConfigSclicExtEn = 0; localparam CVA6ConfigAxiIdWidth = 4; localparam CVA6ConfigAxiAddrWidth = 64; @@ -100,6 +101,7 @@ package cva6_config_pkg; XFVec: bit'(CVA6ConfigFVecEn), CvxifEn: bit'(CVA6ConfigCvxifEn), RVZiCond: bit'(CVA6ConfigRVZiCond), + RVSCLIC: bit'(CVA6ConfigSclicExtEn), RVZicntr: bit'(1), RVZihpm: bit'(1), NrScoreboardEntries: unsigned'(CVA6ConfigNrScoreboardEntries), @@ -120,6 +122,7 @@ package cva6_config_pkg; PMPAddrRstVal: {64{64'h0}}, PMPEntryReadOnly: 64'd0, NOCType: config_pkg::NOC_TYPE_AXI4_ATOP, + CLICNumInterruptSrc: unsigned'(256), NrNonIdempotentRules: unsigned'(2), NonIdempotentAddrBase: 1024'({64'b0, 64'b0}), NonIdempotentLength: 1024'({64'b0, 64'b0}), diff --git a/core/include/cv32a6_embedded_config_pkg_deprecated.sv b/core/include/cv32a6_embedded_config_pkg_deprecated.sv index b8990ae566..8593f386c7 100644 --- a/core/include/cv32a6_embedded_config_pkg_deprecated.sv +++ b/core/include/cv32a6_embedded_config_pkg_deprecated.sv @@ -26,6 +26,7 @@ package cva6_config_pkg; localparam CVA6ConfigBExtEn = 1; localparam CVA6ConfigVExtEn = 0; localparam CVA6ConfigRVZiCond = 0; + localparam CVA6ConfigSclicExtEn = 0; localparam CVA6ConfigAxiIdWidth = 4; localparam CVA6ConfigAxiAddrWidth = 64; @@ -99,6 +100,7 @@ package cva6_config_pkg; XFVec: bit'(CVA6ConfigFVecEn), CvxifEn: bit'(CVA6ConfigCvxifEn), RVZiCond: bit'(CVA6ConfigRVZiCond), + RVSCLIC: bit'(CVA6ConfigSclicExtEn), RVZicntr: bit'(1), RVZihpm: bit'(1), NrScoreboardEntries: unsigned'(CVA6ConfigNrScoreboardEntries), @@ -119,6 +121,7 @@ package cva6_config_pkg; PMPAddrRstVal: {64{64'h0}}, PMPEntryReadOnly: 64'd0, NOCType: config_pkg::NOC_TYPE_AXI4_ATOP, + CLICNumInterruptSrc: unsigned'(256), NrNonIdempotentRules: unsigned'(2), NonIdempotentAddrBase: 1024'({64'b0, 64'b0}), NonIdempotentLength: 1024'({64'b0, 64'b0}), diff --git a/core/include/cv32a6_ima_sv32_fpga_config_pkg.sv b/core/include/cv32a6_ima_sv32_fpga_config_pkg.sv index 0e6510ba5c..f377ac2c6f 100644 --- a/core/include/cv32a6_ima_sv32_fpga_config_pkg.sv +++ b/core/include/cv32a6_ima_sv32_fpga_config_pkg.sv @@ -27,6 +27,7 @@ package cva6_config_pkg; localparam CVA6ConfigBExtEn = 0; localparam CVA6ConfigVExtEn = 0; localparam CVA6ConfigRVZiCond = 0; + localparam CVA6ConfigSclicExtEn = 0; localparam CVA6ConfigAxiIdWidth = 4; localparam CVA6ConfigAxiAddrWidth = 64; @@ -99,6 +100,7 @@ package cva6_config_pkg; XFVec: bit'(CVA6ConfigFVecEn), CvxifEn: bit'(CVA6ConfigCvxifEn), RVZiCond: bit'(CVA6ConfigRVZiCond), + RVSCLIC: bit'(CVA6ConfigSclicExtEn), RVZicntr: bit'(1), RVZihpm: bit'(1), NrScoreboardEntries: unsigned'(CVA6ConfigNrScoreboardEntries), @@ -119,6 +121,7 @@ package cva6_config_pkg; PMPAddrRstVal: {64{64'h0}}, PMPEntryReadOnly: 64'd0, NOCType: config_pkg::NOC_TYPE_AXI4_ATOP, + CLICNumInterruptSrc: unsigned'(256), NrNonIdempotentRules: unsigned'(2), NonIdempotentAddrBase: 1024'({64'b0, 64'b0}), NonIdempotentLength: 1024'({64'b0, 64'b0}), diff --git a/core/include/cv32a6_imac_sv0_config_pkg.sv b/core/include/cv32a6_imac_sv0_config_pkg.sv index 1fe4d3f551..b9eec5351e 100644 --- a/core/include/cv32a6_imac_sv0_config_pkg.sv +++ b/core/include/cv32a6_imac_sv0_config_pkg.sv @@ -27,6 +27,7 @@ package cva6_config_pkg; localparam CVA6ConfigBExtEn = 0; localparam CVA6ConfigVExtEn = 0; localparam CVA6ConfigRVZiCond = 0; + localparam CVA6ConfigSclicExtEn = 0; localparam CVA6ConfigAxiIdWidth = 4; localparam CVA6ConfigAxiAddrWidth = 64; @@ -99,6 +100,7 @@ package cva6_config_pkg; XFVec: bit'(CVA6ConfigFVecEn), CvxifEn: bit'(CVA6ConfigCvxifEn), RVZiCond: bit'(CVA6ConfigRVZiCond), + RVSCLIC: bit'(CVA6ConfigSclicExtEn), RVZicntr: bit'(1), RVZihpm: bit'(1), NrScoreboardEntries: unsigned'(CVA6ConfigNrScoreboardEntries), @@ -119,6 +121,7 @@ package cva6_config_pkg; PMPAddrRstVal: {64{64'h0}}, PMPEntryReadOnly: 64'd0, NOCType: config_pkg::NOC_TYPE_AXI4_ATOP, + CLICNumInterruptSrc: unsigned'(256), NrNonIdempotentRules: unsigned'(2), NonIdempotentAddrBase: 1024'({64'b0, 64'b0}), NonIdempotentLength: 1024'({64'b0, 64'b0}), diff --git a/core/include/cv32a6_imac_sv32_config_pkg.sv b/core/include/cv32a6_imac_sv32_config_pkg.sv index 27ad32d10c..3b326a921e 100644 --- a/core/include/cv32a6_imac_sv32_config_pkg.sv +++ b/core/include/cv32a6_imac_sv32_config_pkg.sv @@ -27,6 +27,7 @@ package cva6_config_pkg; localparam CVA6ConfigBExtEn = 0; localparam CVA6ConfigVExtEn = 0; localparam CVA6ConfigRVZiCond = 0; + localparam CVA6ConfigSclicExtEn = 0; localparam CVA6ConfigAxiIdWidth = 4; localparam CVA6ConfigAxiAddrWidth = 64; @@ -99,6 +100,7 @@ package cva6_config_pkg; XFVec: bit'(CVA6ConfigFVecEn), CvxifEn: bit'(CVA6ConfigCvxifEn), RVZiCond: bit'(CVA6ConfigRVZiCond), + RVSCLIC: bit'(CVA6ConfigSclicExtEn), RVZicntr: bit'(1), RVZihpm: bit'(1), NrScoreboardEntries: unsigned'(CVA6ConfigNrScoreboardEntries), @@ -119,6 +121,7 @@ package cva6_config_pkg; PMPAddrRstVal: {64{64'h0}}, PMPEntryReadOnly: 64'd0, NOCType: config_pkg::NOC_TYPE_AXI4_ATOP, + CLICNumInterruptSrc: unsigned'(256), NrNonIdempotentRules: unsigned'(2), NonIdempotentAddrBase: 1024'({64'b0, 64'b0}), NonIdempotentLength: 1024'({64'b0, 64'b0}), diff --git a/core/include/cv32a6_imafc_sv32_config_pkg.sv b/core/include/cv32a6_imafc_sv32_config_pkg.sv index e00ba727fd..5d5ed71006 100644 --- a/core/include/cv32a6_imafc_sv32_config_pkg.sv +++ b/core/include/cv32a6_imafc_sv32_config_pkg.sv @@ -27,6 +27,7 @@ package cva6_config_pkg; localparam CVA6ConfigBExtEn = 0; localparam CVA6ConfigVExtEn = 0; localparam CVA6ConfigRVZiCond = 0; + localparam CVA6ConfigSclicExtEn = 0; localparam CVA6ConfigAxiIdWidth = 4; localparam CVA6ConfigAxiAddrWidth = 64; @@ -99,6 +100,7 @@ package cva6_config_pkg; XFVec: bit'(CVA6ConfigFVecEn), CvxifEn: bit'(CVA6ConfigCvxifEn), RVZiCond: bit'(CVA6ConfigRVZiCond), + RVSCLIC: bit'(CVA6ConfigSclicExtEn), RVZicntr: bit'(1), RVZihpm: bit'(1), NrScoreboardEntries: unsigned'(CVA6ConfigNrScoreboardEntries), @@ -119,6 +121,7 @@ package cva6_config_pkg; PMPAddrRstVal: {64{64'h0}}, PMPEntryReadOnly: 64'd0, NOCType: config_pkg::NOC_TYPE_AXI4_ATOP, + CLICNumInterruptSrc: unsigned'(256), NrNonIdempotentRules: unsigned'(2), NonIdempotentAddrBase: 1024'({64'b0, 64'b0}), NonIdempotentLength: 1024'({64'b0, 64'b0}), diff --git a/core/include/cv64a6_imadfcv_sv39_polara_config_pkg.sv b/core/include/cv64a6_imadfcv_sv39_polara_config_pkg.sv index 96315e873d..f2cf8f4ccb 100644 --- a/core/include/cv64a6_imadfcv_sv39_polara_config_pkg.sv +++ b/core/include/cv64a6_imadfcv_sv39_polara_config_pkg.sv @@ -27,6 +27,7 @@ package cva6_config_pkg; localparam CVA6ConfigHExtEn = 0; localparam CVA6ConfigVExtEn = 1; localparam CVA6ConfigRVZiCond = 0; + localparam CVA6ConfigSclicExtEn = 0; localparam CVA6ConfigAxiIdWidth = 4; localparam CVA6ConfigAxiAddrWidth = 64; @@ -99,6 +100,7 @@ package cva6_config_pkg; XFVec: bit'(CVA6ConfigFVecEn), CvxifEn: bit'(CVA6ConfigCvxifEn), RVZiCond: bit'(CVA6ConfigRVZiCond), + RVSCLIC: bit'(CVA6ConfigSclicExtEn), RVZicntr: bit'(1), RVZihpm: bit'(1), NrScoreboardEntries: unsigned'(CVA6ConfigNrScoreboardEntries), @@ -119,6 +121,7 @@ package cva6_config_pkg; PMPAddrRstVal: {64{64'h0}}, PMPEntryReadOnly: 64'd0, NOCType: config_pkg::NOC_TYPE_L15_BIG_ENDIAN, + CLICNumInterruptSrc: unsigned'(256), NrNonIdempotentRules: unsigned'(2), NonIdempotentAddrBase: 1024'({64'b0, 64'b0}), NonIdempotentLength: 1024'({64'b0, 64'b0}), diff --git a/core/include/cv64a6_imafdc_sv39_config_pkg.sv b/core/include/cv64a6_imafdc_sv39_config_pkg.sv index 0f02d00657..bb7403c9bb 100644 --- a/core/include/cv64a6_imafdc_sv39_config_pkg.sv +++ b/core/include/cv64a6_imafdc_sv39_config_pkg.sv @@ -27,6 +27,7 @@ package cva6_config_pkg; localparam CVA6ConfigBExtEn = 1; localparam CVA6ConfigVExtEn = 0; localparam CVA6ConfigRVZiCond = 1; + localparam CVA6ConfigSclicExtEn = 0; localparam CVA6ConfigAxiIdWidth = 4; localparam CVA6ConfigAxiAddrWidth = 64; @@ -99,6 +100,7 @@ package cva6_config_pkg; XFVec: bit'(CVA6ConfigFVecEn), CvxifEn: bit'(CVA6ConfigCvxifEn), RVZiCond: bit'(CVA6ConfigRVZiCond), + RVSCLIC: bit'(CVA6ConfigSclicExtEn), RVZicntr: bit'(1), RVZihpm: bit'(1), NrScoreboardEntries: unsigned'(CVA6ConfigNrScoreboardEntries), @@ -119,6 +121,7 @@ package cva6_config_pkg; PMPAddrRstVal: {64{64'h0}}, PMPEntryReadOnly: 64'd0, NOCType: config_pkg::NOC_TYPE_AXI4_ATOP, + CLICNumInterruptSrc: unsigned'(256), NrNonIdempotentRules: unsigned'(2), NonIdempotentAddrBase: 1024'({64'b0, 64'b0}), NonIdempotentLength: 1024'({64'b0, 64'b0}), diff --git a/core/include/cv64a6_imafdc_sv39_hpdcache_config_pkg.sv b/core/include/cv64a6_imafdc_sv39_hpdcache_config_pkg.sv index 32369a3ab8..0bbe0bf760 100644 --- a/core/include/cv64a6_imafdc_sv39_hpdcache_config_pkg.sv +++ b/core/include/cv64a6_imafdc_sv39_hpdcache_config_pkg.sv @@ -34,6 +34,7 @@ package cva6_config_pkg; localparam CVA6ConfigVExtEn = 0; localparam CVA6ConfigHExtEn = 0; localparam CVA6ConfigRVZiCond = 1; + localparam CVA6ConfigSclicExtEn = 0; localparam CVA6ConfigAxiIdWidth = 4; localparam CVA6ConfigAxiAddrWidth = 64; @@ -106,6 +107,7 @@ package cva6_config_pkg; XFVec: bit'(CVA6ConfigFVecEn), CvxifEn: bit'(CVA6ConfigCvxifEn), RVZiCond: bit'(CVA6ConfigRVZiCond), + RVSCLIC: bit'(CVA6ConfigSclicExtEn), RVZicntr: bit'(1), RVZihpm: bit'(1), NrScoreboardEntries: unsigned'(CVA6ConfigNrScoreboardEntries), @@ -126,6 +128,7 @@ package cva6_config_pkg; PMPAddrRstVal: {64{64'h0}}, PMPEntryReadOnly: 64'd0, NOCType: config_pkg::NOC_TYPE_AXI4_ATOP, + CLICNumInterruptSrc: unsigned'(256), NrNonIdempotentRules: unsigned'(2), NonIdempotentAddrBase: 1024'({64'b0, 64'b0}), NonIdempotentLength: 1024'({64'b0, 64'b0}), diff --git a/core/include/cv64a6_imafdc_sv39_openpiton_config_pkg.sv b/core/include/cv64a6_imafdc_sv39_openpiton_config_pkg.sv index ae6d9abd9c..a1eb739d55 100644 --- a/core/include/cv64a6_imafdc_sv39_openpiton_config_pkg.sv +++ b/core/include/cv64a6_imafdc_sv39_openpiton_config_pkg.sv @@ -27,6 +27,7 @@ package cva6_config_pkg; localparam CVA6ConfigBExtEn = 0; localparam CVA6ConfigVExtEn = 0; localparam CVA6ConfigRVZiCond = 0; + localparam CVA6ConfigSclicExtEn = 0; localparam CVA6ConfigAxiIdWidth = 4; localparam CVA6ConfigAxiAddrWidth = 64; @@ -99,6 +100,7 @@ package cva6_config_pkg; XFVec: bit'(CVA6ConfigFVecEn), CvxifEn: bit'(CVA6ConfigCvxifEn), RVZiCond: bit'(CVA6ConfigRVZiCond), + RVSCLIC: bit'(CVA6ConfigSclicExtEn), RVZicntr: bit'(1), RVZihpm: bit'(1), NrScoreboardEntries: unsigned'(CVA6ConfigNrScoreboardEntries), @@ -119,6 +121,7 @@ package cva6_config_pkg; PMPAddrRstVal: {64{64'h0}}, PMPEntryReadOnly: 64'd0, NOCType: config_pkg::NOC_TYPE_L15_BIG_ENDIAN, + CLICNumInterruptSrc: unsigned'(256), NrNonIdempotentRules: unsigned'(2), NonIdempotentAddrBase: 1024'({64'b0, 64'b0}), NonIdempotentLength: 1024'({64'b0, 64'b0}), diff --git a/core/include/cv64a6_imafdc_sv39_wb_config_pkg.sv b/core/include/cv64a6_imafdc_sv39_wb_config_pkg.sv index 339a5803c7..9917de55b4 100644 --- a/core/include/cv64a6_imafdc_sv39_wb_config_pkg.sv +++ b/core/include/cv64a6_imafdc_sv39_wb_config_pkg.sv @@ -27,6 +27,7 @@ package cva6_config_pkg; localparam CVA6ConfigVExtEn = 0; localparam CVA6ConfigHExtEn = 0; localparam CVA6ConfigRVZiCond = 1; + localparam CVA6ConfigSclicExtEn = 0; localparam CVA6ConfigAxiIdWidth = 4; localparam CVA6ConfigAxiAddrWidth = 64; @@ -99,6 +100,7 @@ package cva6_config_pkg; XFVec: bit'(CVA6ConfigFVecEn), CvxifEn: bit'(CVA6ConfigCvxifEn), RVZiCond: bit'(CVA6ConfigRVZiCond), + RVSCLIC: bit'(CVA6ConfigSclicExtEn), RVZicntr: bit'(1), RVZihpm: bit'(1), NrScoreboardEntries: unsigned'(CVA6ConfigNrScoreboardEntries), @@ -119,6 +121,7 @@ package cva6_config_pkg; PMPAddrRstVal: {64{64'h0}}, PMPEntryReadOnly: 64'd0, NOCType: config_pkg::NOC_TYPE_AXI4_ATOP, + CLICNumInterruptSrc: unsigned'(256), NrNonIdempotentRules: unsigned'(2), NonIdempotentAddrBase: 1024'({64'b0, 64'b0}), NonIdempotentLength: 1024'({64'b0, 64'b0}), diff --git a/core/include/cv64a6_imafdch_sv39_config_pkg.sv b/core/include/cv64a6_imafdch_sv39_config_pkg.sv index 560b0b8468..efc048d14a 100644 --- a/core/include/cv64a6_imafdch_sv39_config_pkg.sv +++ b/core/include/cv64a6_imafdch_sv39_config_pkg.sv @@ -27,6 +27,7 @@ package cva6_config_pkg; localparam CVA6ConfigBExtEn = 1; localparam CVA6ConfigVExtEn = 0; localparam CVA6ConfigRVZiCond = 1; + localparam CVA6ConfigSclicExtEn = 0; localparam CVA6ConfigAxiIdWidth = 4; localparam CVA6ConfigAxiAddrWidth = 64; @@ -99,6 +100,7 @@ package cva6_config_pkg; XFVec: bit'(CVA6ConfigFVecEn), CvxifEn: bit'(CVA6ConfigCvxifEn), RVZiCond: bit'(CVA6ConfigRVZiCond), + RVSCLIC: bit'(CVA6ConfigSclicExtEn), RVZicntr: bit'(1), RVZihpm: bit'(1), NrScoreboardEntries: unsigned'(CVA6ConfigNrScoreboardEntries), @@ -119,6 +121,7 @@ package cva6_config_pkg; PMPAddrRstVal: {64{64'h0}}, PMPEntryReadOnly: 64'd0, NOCType: config_pkg::NOC_TYPE_AXI4_ATOP, + CLICNumInterruptSrc: unsigned'(256), NrNonIdempotentRules: unsigned'(2), NonIdempotentAddrBase: 1024'({64'b0, 64'b0}), NonIdempotentLength: 1024'({64'b0, 64'b0}), diff --git a/core/include/cv64a6_imafdch_sv39_wb_config_pkg.sv b/core/include/cv64a6_imafdch_sv39_wb_config_pkg.sv index 7a05878ce6..e9903a326c 100644 --- a/core/include/cv64a6_imafdch_sv39_wb_config_pkg.sv +++ b/core/include/cv64a6_imafdch_sv39_wb_config_pkg.sv @@ -27,6 +27,7 @@ package cva6_config_pkg; localparam CVA6ConfigVExtEn = 0; localparam CVA6ConfigHExtEn = 1; localparam CVA6ConfigRVZiCond = 1; + localparam CVA6ConfigSclicExtEn = 0; localparam CVA6ConfigAxiIdWidth = 4; localparam CVA6ConfigAxiAddrWidth = 64; @@ -99,6 +100,7 @@ package cva6_config_pkg; XFVec: bit'(CVA6ConfigFVecEn), CvxifEn: bit'(CVA6ConfigCvxifEn), RVZiCond: bit'(CVA6ConfigRVZiCond), + RVSCLIC: bit'(CVA6ConfigSclicExtEn), RVZicntr: bit'(1), RVZihpm: bit'(1), NrScoreboardEntries: unsigned'(CVA6ConfigNrScoreboardEntries), @@ -119,6 +121,7 @@ package cva6_config_pkg; PMPAddrRstVal: {64{64'h0}}, PMPEntryReadOnly: 64'd0, NOCType: config_pkg::NOC_TYPE_AXI4_ATOP, + CLICNumInterruptSrc: unsigned'(256), NrNonIdempotentRules: unsigned'(2), NonIdempotentAddrBase: 1024'({64'b0, 64'b0}), NonIdempotentLength: 1024'({64'b0, 64'b0}), diff --git a/core/include/cv64a6_imafdchsclic_sv39_hpdcache_config_pkg.sv b/core/include/cv64a6_imafdchsclic_sv39_hpdcache_config_pkg.sv new file mode 100644 index 0000000000..3d22433781 --- /dev/null +++ b/core/include/cv64a6_imafdchsclic_sv39_hpdcache_config_pkg.sv @@ -0,0 +1,164 @@ +// Copyright 2021 Thales DIS design services SAS +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 +// You may obtain a copy of the License at https://solderpad.org/licenses/ +// +// Original Author: Jean-Roch COULON - Thales +// +// Copyright 2023 Commissariat a l'Energie Atomique et aux Energies +// Alternatives (CEA) +// +// Author: Cesar Fuguet - CEA +// Date: August, 2023 +// Description: CVA6 configuration package using the HPDcache as cache subsystem (CLIC variant) + + +package cva6_config_pkg; + + localparam CVA6ConfigXlen = 64; + + localparam CVA6ConfigRVF = 1; + localparam CVA6ConfigF16En = 0; + localparam CVA6ConfigF16AltEn = 0; + localparam CVA6ConfigF8En = 0; + localparam CVA6ConfigFVecEn = 0; + + localparam CVA6ConfigCvxifEn = 0; + localparam CVA6ConfigCExtEn = 1; + localparam CVA6ConfigZcbExtEn = 1; + localparam CVA6ConfigZcmpExtEn = 0; + localparam CVA6ConfigAExtEn = 1; + localparam CVA6ConfigHExtEn = 1; + localparam CVA6ConfigBExtEn = 0; + localparam CVA6ConfigVExtEn = 0; + localparam CVA6ConfigRVZiCond = 1; + localparam CVA6ConfigSclicExtEn = 1; + + localparam CVA6ConfigAxiIdWidth = 4; + localparam CVA6ConfigAxiAddrWidth = 64; + localparam CVA6ConfigAxiDataWidth = 64; + localparam CVA6ConfigFetchUserEn = 0; + localparam CVA6ConfigFetchUserWidth = CVA6ConfigXlen; + localparam CVA6ConfigDataUserEn = 0; + localparam CVA6ConfigDataUserWidth = 1; + + localparam CVA6ConfigIcacheByteSize = 16384; + localparam CVA6ConfigIcacheSetAssoc = 4; + localparam CVA6ConfigIcacheLineWidth = 128; + localparam CVA6ConfigDcacheByteSize = 32768; + localparam CVA6ConfigDcacheSetAssoc = 8; + localparam CVA6ConfigDcacheLineWidth = 128; + + localparam CVA6ConfigDcacheIdWidth = 3; + localparam CVA6ConfigMemTidWidth = CVA6ConfigAxiIdWidth; + + localparam CVA6ConfigWtDcacheWbufDepth = 8; + + localparam CVA6ConfigNrScoreboardEntries = 8; + + localparam CVA6ConfigFpgaEn = 0; + + localparam CVA6ConfigNrLoadPipeRegs = 1; + localparam CVA6ConfigNrStorePipeRegs = 0; + localparam CVA6ConfigNrLoadBufEntries = 8; + + localparam CVA6ConfigRASDepth = 2; + localparam CVA6ConfigBTBEntries = 32; + localparam CVA6ConfigBHTEntries = 128; + + localparam CVA6ConfigTvalEn = 1; + + localparam CVA6ConfigNrPMPEntries = 8; + + localparam CVA6ConfigPerfCounterEn = 1; + + localparam config_pkg::cache_type_t CVA6ConfigDcacheType = config_pkg::HPDCACHE; + + localparam CVA6ConfigMmuPresent = 1; + + localparam CVA6ConfigRvfiTrace = 1; + + localparam config_pkg::cva6_user_cfg_t cva6_cfg = '{ + XLEN: unsigned'(CVA6ConfigXlen), + FpgaEn: bit'(CVA6ConfigFpgaEn), + TechnoCut: bit'(0), + SuperscalarEn: bit'(0), + NrCommitPorts: unsigned'(2), + AxiAddrWidth: unsigned'(CVA6ConfigAxiAddrWidth), + AxiDataWidth: unsigned'(CVA6ConfigAxiDataWidth), + AxiIdWidth: unsigned'(CVA6ConfigAxiIdWidth), + AxiUserWidth: unsigned'(CVA6ConfigDataUserWidth), + MemTidWidth: unsigned'(CVA6ConfigMemTidWidth), + NrLoadBufEntries: unsigned'(CVA6ConfigNrLoadBufEntries), + RVF: bit'(CVA6ConfigRVF), + RVD: bit'(CVA6ConfigRVF), + XF16: bit'(CVA6ConfigF16En), + XF16ALT: bit'(CVA6ConfigF16AltEn), + XF8: bit'(CVA6ConfigF8En), + RVA: bit'(CVA6ConfigAExtEn), + RVB: bit'(CVA6ConfigBExtEn), + RVV: bit'(CVA6ConfigVExtEn), + RVC: bit'(CVA6ConfigCExtEn), + RVH: bit'(CVA6ConfigHExtEn), + RVZCB: bit'(CVA6ConfigZcbExtEn), + RVZCMP: bit'(CVA6ConfigZcmpExtEn), + XFVec: bit'(CVA6ConfigFVecEn), + CvxifEn: bit'(CVA6ConfigCvxifEn), + RVZiCond: bit'(CVA6ConfigRVZiCond), + RVSCLIC: bit'(CVA6ConfigSclicExtEn), + RVZicntr: bit'(1), + RVZihpm: bit'(1), + NrScoreboardEntries: unsigned'(CVA6ConfigNrScoreboardEntries), + PerfCounterEn: bit'(CVA6ConfigPerfCounterEn), + MmuPresent: bit'(CVA6ConfigMmuPresent), + RVS: bit'(1), + RVU: bit'(1), + HaltAddress: 64'h800, + ExceptionAddress: 64'h808, + RASDepth: unsigned'(CVA6ConfigRASDepth), + BTBEntries: unsigned'(CVA6ConfigBTBEntries), + BHTEntries: unsigned'(CVA6ConfigBHTEntries), + DmBaseAddress: 64'h0, + TvalEn: bit'(CVA6ConfigTvalEn), + DirectVecOnly: bit'(0), + NrPMPEntries: unsigned'(CVA6ConfigNrPMPEntries), + PMPCfgRstVal: {64{64'h0}}, + PMPAddrRstVal: {64{64'h0}}, + PMPEntryReadOnly: 64'd0, + NOCType: config_pkg::NOC_TYPE_AXI4_ATOP, + CLICNumInterruptSrc: unsigned'(256), + NrNonIdempotentRules: unsigned'(2), + NonIdempotentAddrBase: 1024'({64'b0, 64'b0}), + NonIdempotentLength: 1024'({64'b0, 64'b0}), + NrExecuteRegionRules: unsigned'(3), + ExecuteRegionAddrBase: 1024'({64'h8000_0000, 64'h1_0000, 64'h0}), + ExecuteRegionLength: 1024'({64'h40000000, 64'h10000, 64'h1000}), + NrCachedRegionRules: unsigned'(1), + CachedRegionAddrBase: 1024'({64'h8000_0000}), + CachedRegionLength: 1024'({64'h40000000}), + MaxOutstandingStores: unsigned'(7), + DebugEn: bit'(1), + AxiBurstWriteEn: bit'(0), + IcacheByteSize: unsigned'(CVA6ConfigIcacheByteSize), + IcacheSetAssoc: unsigned'(CVA6ConfigIcacheSetAssoc), + IcacheLineWidth: unsigned'(CVA6ConfigIcacheLineWidth), + DCacheType: CVA6ConfigDcacheType, + DcacheByteSize: unsigned'(CVA6ConfigDcacheByteSize), + DcacheSetAssoc: unsigned'(CVA6ConfigDcacheSetAssoc), + DcacheLineWidth: unsigned'(CVA6ConfigDcacheLineWidth), + DataUserEn: unsigned'(CVA6ConfigDataUserEn), + WtDcacheWbufDepth: int'(CVA6ConfigWtDcacheWbufDepth), + FetchUserWidth: unsigned'(CVA6ConfigFetchUserWidth), + FetchUserEn: unsigned'(CVA6ConfigFetchUserEn), + InstrTlbEntries: int'(16), + DataTlbEntries: int'(16), + UseSharedTlb: bit'(0), + SharedTlbDepth: int'(64), + NrLoadPipeRegs: int'(CVA6ConfigNrLoadPipeRegs), + NrStorePipeRegs: int'(CVA6ConfigNrStorePipeRegs), + DcacheIdWidth: int'(CVA6ConfigDcacheIdWidth) + }; + +endpackage diff --git a/core/include/cv64a6_imafdchsclic_sv39_wb_config_pkg.sv b/core/include/cv64a6_imafdchsclic_sv39_wb_config_pkg.sv new file mode 100644 index 0000000000..9a107097b8 --- /dev/null +++ b/core/include/cv64a6_imafdchsclic_sv39_wb_config_pkg.sv @@ -0,0 +1,157 @@ +// Copyright 2021 Thales DIS design services SAS +// +// Licensed under the Solderpad Hardware Licence, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// SPDX-License-Identifier: Apache-2.0 WITH SHL-2.0 +// You may obtain a copy of the License at https://solderpad.org/licenses/ +// +// Original Author: Jean-Roch COULON - Thales + + +package cva6_config_pkg; + + localparam CVA6ConfigXlen = 64; + + localparam CVA6ConfigRVF = 1; + localparam CVA6ConfigF16En = 0; + localparam CVA6ConfigF16AltEn = 0; + localparam CVA6ConfigF8En = 0; + localparam CVA6ConfigFVecEn = 0; + + localparam CVA6ConfigCvxifEn = 0; + localparam CVA6ConfigCExtEn = 1; + localparam CVA6ConfigZcbExtEn = 1; + localparam CVA6ConfigZcmpExtEn = 0; + localparam CVA6ConfigAExtEn = 1; + localparam CVA6ConfigHExtEn = 1; + localparam CVA6ConfigBExtEn = 0; + localparam CVA6ConfigVExtEn = 0; + localparam CVA6ConfigRVZiCond = 1; + localparam CVA6ConfigSclicExtEn = 1; + + localparam CVA6ConfigAxiIdWidth = 4; + localparam CVA6ConfigAxiAddrWidth = 64; + localparam CVA6ConfigAxiDataWidth = 64; + localparam CVA6ConfigFetchUserEn = 0; + localparam CVA6ConfigFetchUserWidth = CVA6ConfigXlen; + localparam CVA6ConfigDataUserEn = 0; + localparam CVA6ConfigDataUserWidth = 1; + + localparam CVA6ConfigIcacheByteSize = 16384; + localparam CVA6ConfigIcacheSetAssoc = 4; + localparam CVA6ConfigIcacheLineWidth = 128; + localparam CVA6ConfigDcacheByteSize = 32768; + localparam CVA6ConfigDcacheSetAssoc = 8; + localparam CVA6ConfigDcacheLineWidth = 128; + + localparam CVA6ConfigDcacheIdWidth = 1; + localparam CVA6ConfigMemTidWidth = 2; + + localparam CVA6ConfigWtDcacheWbufDepth = 8; + + localparam CVA6ConfigNrScoreboardEntries = 8; + + localparam CVA6ConfigFpgaEn = 0; + + localparam CVA6ConfigNrLoadPipeRegs = 1; + localparam CVA6ConfigNrStorePipeRegs = 0; + localparam CVA6ConfigNrLoadBufEntries = 2; + + localparam CVA6ConfigRASDepth = 2; + localparam CVA6ConfigBTBEntries = 32; + localparam CVA6ConfigBHTEntries = 128; + + localparam CVA6ConfigTvalEn = 1; + + localparam CVA6ConfigNrPMPEntries = 8; + + localparam CVA6ConfigPerfCounterEn = 1; + + localparam config_pkg::cache_type_t CVA6ConfigDcacheType = config_pkg::WB; + + localparam CVA6ConfigMmuPresent = 1; + + localparam CVA6ConfigRvfiTrace = 1; + + localparam config_pkg::cva6_user_cfg_t cva6_cfg = '{ + XLEN: unsigned'(CVA6ConfigXlen), + FpgaEn: bit'(CVA6ConfigFpgaEn), + TechnoCut: bit'(0), + SuperscalarEn: bit'(0), + NrCommitPorts: unsigned'(2), + AxiAddrWidth: unsigned'(CVA6ConfigAxiAddrWidth), + AxiDataWidth: unsigned'(CVA6ConfigAxiDataWidth), + AxiIdWidth: unsigned'(CVA6ConfigAxiIdWidth), + AxiUserWidth: unsigned'(CVA6ConfigDataUserWidth), + MemTidWidth: unsigned'(CVA6ConfigMemTidWidth), + NrLoadBufEntries: unsigned'(CVA6ConfigNrLoadBufEntries), + RVF: bit'(CVA6ConfigRVF), + RVD: bit'(CVA6ConfigRVF), + XF16: bit'(CVA6ConfigF16En), + XF16ALT: bit'(CVA6ConfigF16AltEn), + XF8: bit'(CVA6ConfigF8En), + RVA: bit'(CVA6ConfigAExtEn), + RVB: bit'(CVA6ConfigBExtEn), + RVV: bit'(CVA6ConfigVExtEn), + RVC: bit'(CVA6ConfigCExtEn), + RVH: bit'(CVA6ConfigHExtEn), + RVZCB: bit'(CVA6ConfigZcbExtEn), + RVZCMP: bit'(CVA6ConfigZcmpExtEn), + XFVec: bit'(CVA6ConfigFVecEn), + CvxifEn: bit'(CVA6ConfigCvxifEn), + RVZiCond: bit'(CVA6ConfigRVZiCond), + RVSCLIC: bit'(CVA6ConfigSclicExtEn), + RVZicntr: bit'(1), + RVZihpm: bit'(1), + NrScoreboardEntries: unsigned'(CVA6ConfigNrScoreboardEntries), + PerfCounterEn: bit'(CVA6ConfigPerfCounterEn), + MmuPresent: bit'(CVA6ConfigMmuPresent), + RVS: bit'(1), + RVU: bit'(1), + HaltAddress: 64'h800, + ExceptionAddress: 64'h808, + RASDepth: unsigned'(CVA6ConfigRASDepth), + BTBEntries: unsigned'(CVA6ConfigBTBEntries), + BHTEntries: unsigned'(CVA6ConfigBHTEntries), + DmBaseAddress: 64'h0, + TvalEn: bit'(CVA6ConfigTvalEn), + DirectVecOnly: bit'(0), + NrPMPEntries: unsigned'(CVA6ConfigNrPMPEntries), + PMPCfgRstVal: {64{64'h0}}, + PMPAddrRstVal: {64{64'h0}}, + PMPEntryReadOnly: 64'd0, + NOCType: config_pkg::NOC_TYPE_AXI4_ATOP, + CLICNumInterruptSrc: unsigned'(256), + NrNonIdempotentRules: unsigned'(2), + NonIdempotentAddrBase: 1024'({64'b0, 64'b0}), + NonIdempotentLength: 1024'({64'b0, 64'b0}), + NrExecuteRegionRules: unsigned'(3), + ExecuteRegionAddrBase: 1024'({64'h8000_0000, 64'h1_0000, 64'h0}), + ExecuteRegionLength: 1024'({64'h40000000, 64'h10000, 64'h1000}), + NrCachedRegionRules: unsigned'(1), + CachedRegionAddrBase: 1024'({64'h8000_0000}), + CachedRegionLength: 1024'({64'h40000000}), + MaxOutstandingStores: unsigned'(7), + DebugEn: bit'(1), + AxiBurstWriteEn: bit'(0), + IcacheByteSize: unsigned'(CVA6ConfigIcacheByteSize), + IcacheSetAssoc: unsigned'(CVA6ConfigIcacheSetAssoc), + IcacheLineWidth: unsigned'(CVA6ConfigIcacheLineWidth), + DCacheType: CVA6ConfigDcacheType, + DcacheByteSize: unsigned'(CVA6ConfigDcacheByteSize), + DcacheSetAssoc: unsigned'(CVA6ConfigDcacheSetAssoc), + DcacheLineWidth: unsigned'(CVA6ConfigDcacheLineWidth), + DataUserEn: unsigned'(CVA6ConfigDataUserEn), + WtDcacheWbufDepth: int'(CVA6ConfigWtDcacheWbufDepth), + FetchUserWidth: unsigned'(CVA6ConfigFetchUserWidth), + FetchUserEn: unsigned'(CVA6ConfigFetchUserEn), + InstrTlbEntries: int'(16), + DataTlbEntries: int'(16), + UseSharedTlb: bit'(0), + SharedTlbDepth: int'(64), + NrLoadPipeRegs: int'(CVA6ConfigNrLoadPipeRegs), + NrStorePipeRegs: int'(CVA6ConfigNrStorePipeRegs), + DcacheIdWidth: int'(CVA6ConfigDcacheIdWidth) + }; + +endpackage diff --git a/core/include/cv64a6_imafdcv_sv39_config_pkg.sv b/core/include/cv64a6_imafdcv_sv39_config_pkg.sv index c31c2b3819..4119e5d6fe 100644 --- a/core/include/cv64a6_imafdcv_sv39_config_pkg.sv +++ b/core/include/cv64a6_imafdcv_sv39_config_pkg.sv @@ -27,6 +27,7 @@ package cva6_config_pkg; localparam CVA6ConfigHExtEn = 0; localparam CVA6ConfigVExtEn = 1; localparam CVA6ConfigRVZiCond = 0; + localparam CVA6ConfigSclicExtEn = 0; localparam CVA6ConfigAxiIdWidth = 4; localparam CVA6ConfigAxiAddrWidth = 64; @@ -99,6 +100,7 @@ package cva6_config_pkg; XFVec: bit'(CVA6ConfigFVecEn), CvxifEn: bit'(CVA6ConfigCvxifEn), RVZiCond: bit'(CVA6ConfigRVZiCond), + RVSCLIC: bit'(CVA6ConfigSclicExtEn), RVZicntr: bit'(1), RVZihpm: bit'(1), NrScoreboardEntries: unsigned'(CVA6ConfigNrScoreboardEntries), @@ -119,6 +121,7 @@ package cva6_config_pkg; PMPAddrRstVal: {64{64'h0}}, PMPEntryReadOnly: 64'd0, NOCType: config_pkg::NOC_TYPE_AXI4_ATOP, + CLICNumInterruptSrc: unsigned'(256), NrNonIdempotentRules: unsigned'(2), NonIdempotentAddrBase: 1024'({64'b0, 64'b0}), NonIdempotentLength: 1024'({64'b0, 64'b0}), diff --git a/core/include/riscv_pkg.sv b/core/include/riscv_pkg.sv index fab0cb86d7..cd6cc58513 100644 --- a/core/include/riscv_pkg.sv +++ b/core/include/riscv_pkg.sv @@ -132,6 +132,15 @@ package riscv; logic fiom; // fence of I/O implies memory } envcfg_rv_t; + typedef struct packed { + logic [7:0] mil; + logic [7:0] wpri; + logic [7:0] sil; + logic [7:0] uil; + } intstatus_rv_t; + + typedef struct packed {logic [7:0] th;} intthresh_rv_t; + // -------------------- // Instruction Types // -------------------- @@ -410,12 +419,14 @@ package riscv; CSR_SIE = 12'h104, CSR_STVEC = 12'h105, CSR_SCOUNTEREN = 12'h106, + CSR_STVT = 12'h107, CSR_SENVCFG = 12'h10A, CSR_SSCRATCH = 12'h140, CSR_SEPC = 12'h141, CSR_SCAUSE = 12'h142, CSR_STVAL = 12'h143, CSR_SIP = 12'h144, + CSR_SINTTHRESH = 12'h147, CSR_SATP = 12'h180, // Hypervisor-extended Supervisor Mode CSRs CSR_HSTATUS = 12'h600, @@ -474,11 +485,14 @@ package riscv; CSR_MHPM_EVENT_29 = 12'h33D, //Reserved CSR_MHPM_EVENT_30 = 12'h33E, //Reserved CSR_MHPM_EVENT_31 = 12'h33F, //Reserved + CSR_MTVT = 12'h307, CSR_MSCRATCH = 12'h340, CSR_MEPC = 12'h341, CSR_MCAUSE = 12'h342, CSR_MTVAL = 12'h343, CSR_MIP = 12'h344, + CSR_MINTSTATUS = 12'h346, + CSR_MINTTHRESH = 12'h347, CSR_MTINST = 12'h34A, CSR_MTVAL2 = 12'h34B, CSR_MENVCFG = 12'h30A, @@ -714,7 +728,9 @@ package riscv; CSR_HPM_COUNTER_28H = 12'hC9C, // reserved CSR_HPM_COUNTER_29H = 12'hC9D, // reserved CSR_HPM_COUNTER_30H = 12'hC9E, // reserved - CSR_HPM_COUNTER_31H = 12'hC9F // reserved + CSR_HPM_COUNTER_31H = 12'hC9F, // reserved + // CLIC CSRs (Supervisor Mode) + CSR_SINTSTATUS = 12'hDB1 } csr_reg_t; localparam logic [63:0] SSTATUS_UIE = 'h00000001; diff --git a/corev_apu/src/ariane.sv b/corev_apu/src/ariane.sv index 866c6d6369..4257ec7cbc 100644 --- a/corev_apu/src/ariane.sv +++ b/corev_apu/src/ariane.sv @@ -101,6 +101,14 @@ module ariane import ariane_pkg::*; #( .ipi_i ( ipi_i ), .time_irq_i ( time_irq_i ), .debug_req_i ( debug_req_i ), + .clic_irq_valid_i ( 1'b0 ), + .clic_irq_id_i ( '0 ), + .clic_irq_level_i ( '0 ), + .clic_irq_priv_i ( '0 ), + .clic_irq_shv_i ( 1'b0 ), + .clic_irq_ready_o ( ), + .clic_kill_req_i ( 1'b0 ), + .clic_kill_ack_o ( ), .rvfi_probes_o ( rvfi_probes_o ), .cvxif_req_o ( cvxif_req ), .cvxif_resp_i ( cvxif_resp ),