Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion core/csr_regfile.sv
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ module csr_regfile
output logic scbcfe_o,
// hypervisor-mode clean/flush cache block invalidate enable - ID_STAGE
output logic hcbcfe_o,
// page-based memory type enable - EX_STAGE
output logic pbmte_o,
// external interrupt in - SUBSYSTEM
input logic [1:0] irq_i,
// inter processor interrupt -> connected to machine mode sw - SUBSYSTEM
Expand Down Expand Up @@ -267,6 +269,8 @@ module csr_regfile
logic [CVA6Cfg.XLEN-1:0] mtinst_q, mtinst_d;
logic [CVA6Cfg.XLEN-1:0] mtval2_q, mtval2_d;
logic fiom_d, fiom_q;
logic pbmte_d, pbmte_q;
logic hpbmte_d, hpbmte_q;

logic [CVA6Cfg.XLEN-1:0] stvec_q, stvec_d;
logic [CVA6Cfg.XLEN-1:0] scounteren_q, scounteren_d;
Expand Down Expand Up @@ -580,6 +584,9 @@ module csr_regfile
csr_rdata[5:4] = hcbie_q;
csr_rdata[6] = hcbcfe_q;
end
if (CVA6Cfg.SvpbmtEn && CVA6Cfg.IS_XLEN64) begin
csr_rdata[62] = hpbmte_q;
end
end else begin
read_access_exception = 1'b1;
end
Expand Down Expand Up @@ -636,7 +643,10 @@ module csr_regfile
csr_rdata[5:4] = mcbie_q;
csr_rdata[6] = mcbcfe_q;
end
if (!CVA6Cfg.RVU && !CVA6Cfg.RVZiCbom) begin
if (CVA6Cfg.SvpbmtEn && CVA6Cfg.IS_XLEN64) begin
csr_rdata[62] = pbmte_q;
end
if (!CVA6Cfg.RVU && !CVA6Cfg.RVZiCbom && !CVA6Cfg.SvpbmtEn) begin
read_access_exception = 1'b1;
end
end
Expand Down Expand Up @@ -1059,6 +1069,8 @@ module csr_regfile
end

fiom_d = fiom_q;
pbmte_d = pbmte_q;
hpbmte_d = hpbmte_q;
dcache_d = dcache_q;
icache_d = icache_q;
acc_cons_d = acc_cons_q;
Expand Down Expand Up @@ -1523,6 +1535,7 @@ module csr_regfile
endcase
hcbcfe_d = csr_wdata[6];
end
if (CVA6Cfg.SvpbmtEn && CVA6Cfg.IS_XLEN64) hpbmte_d = csr_wdata[62] & pbmte_q;
end else begin
update_access_exception = 1'b1;
end
Expand Down Expand Up @@ -1705,6 +1718,7 @@ module csr_regfile
endcase
mcbcfe_d = csr_wdata[6];
end
if (CVA6Cfg.SvpbmtEn && CVA6Cfg.IS_XLEN64) pbmte_d = csr_wdata[62];
end
riscv::CSR_MENVCFGH: begin
if (!CVA6Cfg.RVU || CVA6Cfg.XLEN != 32) update_access_exception = 1'b1;
Expand Down Expand Up @@ -2702,6 +2716,13 @@ module csr_regfile
assign mcbcfe_o = CVA6Cfg.RVZiCbom ? mcbcfe_q : 1'b0;
assign scbcfe_o = CVA6Cfg.RVZiCbom ? scbcfe_q : 1'b0;
assign hcbcfe_o = CVA6Cfg.RVZiCbom ? hcbcfe_q : 1'b0;

// Svpbmt: effective PBMTE depends on virtualization mode.
// In HS-mode (v=0): effective = menvcfg.PBMTE
// In VS/VU-mode (v=1): effective = menvcfg.PBMTE AND henvcfg.PBMTE
assign pbmte_o = CVA6Cfg.SvpbmtEn ?
(CVA6Cfg.RVH ? (pbmte_q & (v_q ? hpbmte_q : 1'b1)) : pbmte_q) :
1'b0;
// we support bare memory addressing and SV39
if (CVA6Cfg.RVH) begin
assign en_translation_o = (((config_pkg::vm_mode_t'(satp_q.mode) == CVA6Cfg.MODE_SV && !v_q) || (config_pkg::vm_mode_t'(vsatp_q.mode) == CVA6Cfg.MODE_SV && v_q)) &&
Expand Down Expand Up @@ -2780,6 +2801,8 @@ module csr_regfile
mscratch_q <= {CVA6Cfg.XLEN{1'b0}};
if (CVA6Cfg.TvalEn) mtval_q <= {CVA6Cfg.XLEN{1'b0}};
fiom_q <= '0;
pbmte_q <= '0;
hpbmte_q <= '0;
dcache_q <= {{CVA6Cfg.XLEN - 1{1'b0}}, 1'b1};
icache_q <= {{CVA6Cfg.XLEN - 1{1'b0}}, 1'b1};
mcountinhibit_q <= '0;
Expand Down Expand Up @@ -2878,6 +2901,8 @@ module csr_regfile
mscratch_q <= mscratch_d;
if (CVA6Cfg.TvalEn) mtval_q <= mtval_d;
fiom_q <= fiom_d;
pbmte_q <= pbmte_d;
hpbmte_q <= hpbmte_d;
dcache_q <= dcache_d;
icache_q <= icache_d;
mcountinhibit_q <= mcountinhibit_d;
Expand Down
3 changes: 3 additions & 0 deletions core/cva6.sv
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,7 @@ module cva6
logic vs_sum_csr_ex;
logic mxr_csr_ex;
logic vmxr_csr_ex;
logic pbmte_csr_ex;
logic [CVA6Cfg.PPNW-1:0] satp_ppn_csr_ex;
logic [CVA6Cfg.ASID_WIDTH-1:0] asid_csr_ex;
logic [CVA6Cfg.PPNW-1:0] vsatp_ppn_csr_ex;
Expand Down Expand Up @@ -1085,6 +1086,7 @@ module cva6
.vs_sum_i (vs_sum_csr_ex), // from CSR
.mxr_i (mxr_csr_ex), // from CSR
.vmxr_i (vmxr_csr_ex), // from CSR
.pbmte_i (pbmte_csr_ex), // from CSR
.satp_ppn_i (satp_ppn_csr_ex), // from CSR
.asid_i (asid_csr_ex), // from CSR
.vsatp_ppn_i (vsatp_ppn_csr_ex), // from CSR
Expand Down Expand Up @@ -1215,6 +1217,7 @@ module cva6
.vs_sum_o (vs_sum_csr_ex),
.mxr_o (mxr_csr_ex),
.vmxr_o (vmxr_csr_ex),
.pbmte_o (pbmte_csr_ex),
.satp_ppn_o (satp_ppn_csr_ex),
.asid_o (asid_csr_ex),
.vsatp_ppn_o (vsatp_ppn_csr_ex),
Expand Down
20 changes: 19 additions & 1 deletion core/cva6_mmu/cva6_mmu.sv
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ module cva6_mmu
output logic lsu_valid_o, // translation is valid
output logic [CVA6Cfg.PLEN-1:0] lsu_paddr_o, // translated address
output exception_t lsu_exception_o, // address translation threw an exception
// Svpbmt: page-based memory type for data accesses - EX_STAGE
output logic [1:0] lsu_pbmt_o,
// General control signals
input riscv::priv_lvl_t priv_lvl_i,
input logic v_i,
Expand All @@ -72,6 +74,7 @@ module cva6_mmu
input logic vs_sum_i,
input logic mxr_i,
input logic vmxr_i,
input logic pbmte_i,
input logic mbe_i,
input logic hlvx_inst_i,
input logic hs_ld_st_inst_i,
Expand Down Expand Up @@ -108,7 +111,8 @@ module cva6_mmu
// memory management, pte for cva6
localparam type pte_cva6_t = struct packed {
logic n;
logic [8:0] reserved;
logic [1:0] pbmt; // bits [62:61] -- PBMT field (Svpbmt, currently unused)
logic [6:0] reserved; // bits [60:54] -- truly reserved, must be zero
logic [CVA6Cfg.PPNW-1:0] ppn; // PPN length for
logic [1:0] rsw;
logic d;
Expand All @@ -124,6 +128,7 @@ module cva6_mmu
localparam type tlb_update_cva6_t = struct packed {
logic valid;
logic is_napot_64k; // Svnapot: Flag indicating a 64KiB NAPOT page
logic [1:0] pbmt; // Svpbmt: Page-based memory type (bits [62:61] of PTE)
logic [CVA6Cfg.PtLevels-2:0][HYP_EXT:0] is_page;
logic [CVA6Cfg.VpnLen-1:0] vpn;
logic [CVA6Cfg.ASID_WIDTH-1:0] asid;
Expand Down Expand Up @@ -168,6 +173,10 @@ module cva6_mmu
logic dtlb_lu_hit;
logic [ CVA6Cfg.GPLEN-1:0] dtlb_gpaddr;

// Svpbmt: PBMT value from TLB lookup
logic [ 1:0] itlb_pbmt;
logic [ 1:0] dtlb_pbmt;

logic shared_tlb_access, shared_tlb_miss;
logic shared_tlb_hit, itlb_req;

Expand Down Expand Up @@ -207,6 +216,7 @@ module cva6_mmu
.vaddr_to_be_flushed_i,
.gpaddr_to_be_flushed_i,
.lu_is_page_o (itlb_is_page),
.lu_pbmt_o (itlb_pbmt),
.lu_hit_o (itlb_lu_hit)
);

Expand Down Expand Up @@ -238,6 +248,7 @@ module cva6_mmu
.vaddr_to_be_flushed_i,
.gpaddr_to_be_flushed_i,
.lu_is_page_o (dtlb_is_page),
.lu_pbmt_o (dtlb_pbmt),
.lu_hit_o (dtlb_lu_hit)
);

Expand Down Expand Up @@ -345,6 +356,7 @@ module cva6_mmu
.hgatp_ppn_i,
.mxr_i,
.vmxr_i,
.pbmte_i,
.mbe_i(mbe_i),
// Performance counters
.shared_tlb_miss_o(shared_tlb_miss), //open for now
Expand Down Expand Up @@ -499,6 +511,7 @@ module cva6_mmu
logic lsu_is_store_n, lsu_is_store_q;
logic dtlb_hit_n, dtlb_hit_q;
logic [CVA6Cfg.PtLevels-2:0] dtlb_is_page_n, dtlb_is_page_q;
logic [1:0] dtlb_pbmt_n, dtlb_pbmt_q; // Svpbmt: registered PBMT from DTLB
exception_t misaligned_ex_n, misaligned_ex_q;

// check if we need to do translation or if we are always ready (e.g.: we are not translating anything)
Expand All @@ -514,10 +527,12 @@ module cva6_mmu
dtlb_hit_n = dtlb_lu_hit;
lsu_is_store_n = lsu_is_store_i;
dtlb_is_page_n = dtlb_is_page;
dtlb_pbmt_n = dtlb_pbmt;
misaligned_ex_n = misaligned_ex_i;

lsu_valid_o = lsu_req_q;
lsu_exception_o = misaligned_ex_q;
lsu_pbmt_o = 2'b00; // Svpbmt: default to PMA (no override)

// mute misaligned exceptions if there is no request otherwise they will throw accidental exceptions
misaligned_ex_n.valid = misaligned_ex_i.valid & lsu_req_i;
Expand Down Expand Up @@ -547,6 +562,7 @@ module cva6_mmu
// translation is enabled and no misaligned exception occurred
if ((en_ld_st_translation_i || en_ld_st_g_translation_i) && !misaligned_ex_q.valid) begin
lsu_valid_o = 1'b0;
lsu_pbmt_o = CVA6Cfg.SvpbmtEn ? dtlb_pbmt_q : 2'b00;

lsu_dtlb_ppn_o = (en_ld_st_g_translation_i && CVA6Cfg.RVH) ? dtlb_g_content.ppn : dtlb_content.ppn;
lsu_paddr_o = {
Expand Down Expand Up @@ -745,6 +761,7 @@ module cva6_mmu
dtlb_hit_q <= '0;
lsu_is_store_q <= '0;
dtlb_is_page_q <= '0;
dtlb_pbmt_q <= '0;
lsu_tinst_q <= '0;
hs_ld_st_inst_q <= '0;
misaligned_ex_q <= '0;
Expand All @@ -755,6 +772,7 @@ module cva6_mmu
dtlb_hit_q <= dtlb_hit_n;
lsu_is_store_q <= lsu_is_store_n;
dtlb_is_page_q <= dtlb_is_page_n;
dtlb_pbmt_q <= dtlb_pbmt_n;
misaligned_ex_q <= misaligned_ex_n;

if (CVA6Cfg.RVH) begin
Expand Down
26 changes: 24 additions & 2 deletions core/cva6_mmu/cva6_ptw.sv
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ module cva6_ptw
input logic [CVA6Cfg.PPNW-1:0] hgatp_ppn_i, // ppn from hgatp
input logic mxr_i,
input logic vmxr_i,
input logic pbmte_i,
input logic mbe_i,

// Performance counters
Expand Down Expand Up @@ -204,6 +205,7 @@ module cva6_ptw
always_comb begin : tlb_update
shared_tlb_update_o.valid = shared_tlb_update_valid;
shared_tlb_update_o.is_napot_64k = is_napot_64k;
shared_tlb_update_o.pbmt = CVA6Cfg.SvpbmtEn ? pte.pbmt : 2'b00;

// update the correct page table level
for (int unsigned y = 0; y < HYP_EXT + 1; y++) begin
Expand Down Expand Up @@ -426,8 +428,11 @@ module cva6_ptw
// -------------
// Invalid PTE
// -------------
// If pte.v = 0, or if pte.r = 0 and pte.w = 1, or if pte.reserved !=0 in sv39 and sv39x4, stop and raise a page-fault exception.
if (!pte.v || (!pte.r && pte.w) || (|pte.reserved && CVA6Cfg.XLEN == 64) || (!CVA6Cfg.SvnapotEn && pte.n) || (CVA6Cfg.SvnapotEn && !(pte.r || pte.x) && pte.n))
// If pte.v = 0, or if pte.r = 0 and pte.w = 1, or if pte.reserved != 0
// (bits [60:54] in sv39/sv39x4), stop and raise a page-fault exception.
// Note: pte.pbmt (bits [62:61]) is intentionally excluded from this
// check per the Svpbmt extension (RISC-V Priv. Spec v1.12, 12.3).
if (!pte.v || (!pte.r && pte.w) || (|pte.reserved && CVA6Cfg.XLEN == 64) || (!CVA6Cfg.SvpbmtEn && |pte.pbmt && CVA6Cfg.XLEN == 64) || (!CVA6Cfg.SvnapotEn && pte.n) || (CVA6Cfg.SvnapotEn && !(pte.r || pte.x) && pte.n))
state_d = PROPAGATE_ERROR;
// -----------
// Valid PTE
Expand All @@ -447,6 +452,15 @@ module cva6_ptw
end
end

// Validate PBMT encoding on leaf PTEs
if (CVA6Cfg.SvpbmtEn) begin
if (pte.pbmt == 2'b11) begin
state_d = PROPAGATE_ERROR;
end else if (!pbmte_i && (pte.pbmt != 2'b00)) begin
state_d = PROPAGATE_ERROR;
end
end

if (CVA6Cfg.RVH) begin
case (ptw_stage_q)
S_STAGE: begin
Expand Down Expand Up @@ -577,6 +591,14 @@ module cva6_ptw
endcase
end else ptw_pptr_n = {pte.ppn, vaddr_lvl[0][ptw_lvl_q[0]], (CVA6Cfg.PtLevels)'(0)};

// Svpbmt: non-leaf PTEs must have pbmt == 0 (reserved per spec).
// Placed after the RVH case block so ptw_stage_d is correctly
// preserved when both a stage transition and PBMT error apply.
if (CVA6Cfg.SvpbmtEn && pte.pbmt != 2'b00) begin
state_d = PROPAGATE_ERROR;
if (CVA6Cfg.RVH) ptw_stage_d = ptw_stage_q;
end

if (CVA6Cfg.RVH && (pte.a || pte.d || pte.u)) begin
state_d = PROPAGATE_ERROR;
ptw_stage_d = ptw_stage_q;
Expand Down
4 changes: 4 additions & 0 deletions core/cva6_mmu/cva6_shared_tlb.sv
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,7 @@ module cva6_shared_tlb #(
itlb_update_o.asid = shared_tlb_update_i.asid;
itlb_update_o.vmid = shared_tlb_update_i.vmid;
itlb_update_o.is_napot_64k = shared_tlb_update_i.is_napot_64k;
itlb_update_o.pbmt = shared_tlb_update_i.pbmt;

end else if (dtlb_req_q) begin
dtlb_update_o.valid = 1'b1;
Expand All @@ -306,6 +307,7 @@ module cva6_shared_tlb #(
dtlb_update_o.asid = shared_tlb_update_i.asid;
dtlb_update_o.vmid = shared_tlb_update_i.vmid;
dtlb_update_o.is_napot_64k = shared_tlb_update_i.is_napot_64k;
dtlb_update_o.pbmt = shared_tlb_update_i.pbmt;
end
end
end else begin
Expand Down Expand Up @@ -342,6 +344,7 @@ module cva6_shared_tlb #(
itlb_update_o.asid = tlb_update_asid_q;
itlb_update_o.vmid = tlb_update_vmid_q;
itlb_update_o.is_napot_64k = CVA6Cfg.SvnapotEn ? shared_tag_rd[i].is_napot_64k : 1'b0;
itlb_update_o.pbmt = CVA6Cfg.SvpbmtEn ? pte[i][0].pbmt : 2'b00;
end else if (dtlb_req_q) begin
dtlb_update_o.valid = 1'b1;
dtlb_update_o.vpn = dtlb_vpn_q;
Expand All @@ -352,6 +355,7 @@ module cva6_shared_tlb #(
dtlb_update_o.asid = tlb_update_asid_q;
dtlb_update_o.vmid = tlb_update_vmid_q;
dtlb_update_o.is_napot_64k = CVA6Cfg.SvnapotEn ? shared_tag_rd[i].is_napot_64k : 1'b0;
dtlb_update_o.pbmt = CVA6Cfg.SvpbmtEn ? pte[i][0].pbmt : 2'b00;
end
end
end
Expand Down
7 changes: 6 additions & 1 deletion core/cva6_mmu/cva6_tlb.sv
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ module cva6_tlb
input logic [CVA6Cfg.VLEN-1:0] vaddr_to_be_flushed_i,
input logic [CVA6Cfg.GPLEN-1:0] gpaddr_to_be_flushed_i,
output logic [CVA6Cfg.PtLevels-2:0] lu_is_page_o,
output logic [1:0] lu_pbmt_o, // Svpbmt: page-based memory type from TLB hit
output logic lu_hit_o
);
localparam GPPN2 = (CVA6Cfg.XLEN == 32) ? CVA6Cfg.VLEN - 33 : 10;
Expand All @@ -70,6 +71,7 @@ module cva6_tlb
logic [HYP_EXT*2:0] v_st_enbl; // v_i, g-stage enabled, s-stage enabled
logic valid;
logic is_napot_64k; // Svnapot: Flag indicating a 64KiB NAPOT page
logic [1:0] pbmt; // Svpbmt: page-based memory type (bits [62:61] of PTE)
} [TLB_ENTRIES-1:0]
tags_q, tags_n;

Expand Down Expand Up @@ -190,6 +192,7 @@ module cva6_tlb
lu_content_o = '{default: 0};
lu_g_content_o = '{default: 0};
lu_is_page_o = '{default: 0};
lu_pbmt_o = 2'b00;
match_asid = '{default: 0};
match_vmid = CVA6Cfg.RVH ? '{default: 0} : '{default: 1};
match_stage = '{default: 0};
Expand Down Expand Up @@ -253,6 +256,7 @@ module cva6_tlb
end
if (|level_match[i] || napot_tag_match[i]) begin
lu_is_page_o = is_page_o[i];
lu_pbmt_o = CVA6Cfg.SvpbmtEn ? tags_q[i].pbmt : 2'b00;
lu_hit_o = 1'b1;
lu_hit[i] = 1'b1;
// Patch the PPN on every TLB hit if this entry is a 64 KiB Svnapot page
Expand Down Expand Up @@ -392,7 +396,8 @@ module cva6_tlb
update_i.is_page,
update_i.v_st_enbl,
1'b1,
CVA6Cfg.SvnapotEn ? update_i.is_napot_64k : 1'b0 // Svnapot: Propagate the NAPOT flag into the TLB entry
CVA6Cfg.SvnapotEn ? update_i.is_napot_64k : 1'b0, // Svnapot: Propagate the NAPOT flag
CVA6Cfg.SvpbmtEn ? update_i.pbmt : 2'b00 // Svpbmt: Propagate the PBMT field
};
// update content as well
content_n[i].pte = update_i.content;
Expand Down
2 changes: 2 additions & 0 deletions core/ex_stage.sv
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ module ex_stage
input logic mxr_i,
// Make executable readable Virtual Supervisor - CSR_REGFILE
input logic vmxr_i,
input logic pbmte_i,
// TO_BE_COMPLETED - CSR_REGFILE
input logic [CVA6Cfg.PPNW-1:0] satp_ppn_i,
// TO_BE_COMPLETED - CSR_REGFILE
Expand Down Expand Up @@ -586,6 +587,7 @@ module ex_stage
.vs_sum_i,
.mxr_i,
.vmxr_i,
.pbmte_i,
.satp_ppn_i,
.vsatp_ppn_i,
.hgatp_ppn_i,
Expand Down
1 change: 1 addition & 0 deletions core/include/build_config_pkg.sv
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ package build_config_pkg;
cfg.DataTlbEntries = CVA6Cfg.DataTlbEntries;
cfg.UseSharedTlb = CVA6Cfg.UseSharedTlb;
cfg.SvnapotEn = CVA6Cfg.SvnapotEn;
cfg.SvpbmtEn = CVA6Cfg.SvpbmtEn;
cfg.SharedTlbDepth = CVA6Cfg.SharedTlbDepth;
cfg.VpnLen = VpnLen;
cfg.PtLevels = PtLevels;
Expand Down
Loading
Loading