diff --git a/core/cva6_mmu/cva6_mmu.sv b/core/cva6_mmu/cva6_mmu.sv index a7a17ff40..0de14b9b6 100644 --- a/core/cva6_mmu/cva6_mmu.sv +++ b/core/cva6_mmu/cva6_mmu.sv @@ -99,7 +99,6 @@ module cva6_mmu output dcache_req_i_t req_port_o, // PMP - input riscv::pmpcfg_t [avoid_neg(CVA6Cfg.NrPMPEntries-1):0] pmpcfg_i, input logic [avoid_neg(CVA6Cfg.NrPMPEntries-1):0][CVA6Cfg.PLEN-3:0] pmpaddr_i ); @@ -400,16 +399,15 @@ module cva6_mmu }; if (CVA6Cfg.PtLevels == 3 && itlb_is_page[CVA6Cfg.PtLevels-2]) begin - + // Strange 9+PtLevels to avoid CI errors on (purely syntactic) checks on Sv32, where + // `PPNWMin-(CVA6Cfg.VpnLen/CVA6Cfg.PtLevels)` equals `11` and would lead to `icache_areq_i.fetch_vaddr[11:12]` icache_areq_o.fetch_paddr[PPNWMin-(CVA6Cfg.VpnLen/CVA6Cfg.PtLevels):9+CVA6Cfg.PtLevels] = icache_areq_i.fetch_vaddr[PPNWMin-(CVA6Cfg.VpnLen/CVA6Cfg.PtLevels):9+CVA6Cfg.PtLevels]; - end if (itlb_is_page[0]) begin - icache_areq_o.fetch_paddr[PPNWMin:12] = icache_areq_i.fetch_vaddr[PPNWMin:12]; - end + // ---------// // ITLB Hit // --------// @@ -453,7 +451,7 @@ module cva6_mmu if (CVA6Cfg.TvalEn) icache_areq_o.fetch_exception.tval = CVA6Cfg.XLEN'(update_vaddr); if (CVA6Cfg.RVH) begin icache_areq_o.fetch_exception.tval2 = ptw_bad_gpaddr[CVA6Cfg.GPLEN-1:0]; - icache_areq_o.fetch_exception.tinst=(ptw_err_at_g_int_st ? (CVA6Cfg.IS_XLEN64 ? riscv::READ_64_PSEUDOINSTRUCTION : riscv::READ_32_PSEUDOINSTRUCTION) : '0); + icache_areq_o.fetch_exception.tinst = (ptw_err_at_g_int_st ? (CVA6Cfg.IS_XLEN64 ? riscv::READ_64_PSEUDOINSTRUCTION : riscv::READ_32_PSEUDOINSTRUCTION) : '0); icache_areq_o.fetch_exception.gva = v_i; end end else begin @@ -551,8 +549,10 @@ module cva6_mmu }; if (CVA6Cfg.PtLevels == 3 && dtlb_is_page_q[CVA6Cfg.PtLevels-2]) begin - lsu_paddr_o[PPNWMin-(CVA6Cfg.VpnLen/CVA6Cfg.PtLevels):12] = lsu_vaddr_q[PPNWMin-(CVA6Cfg.VpnLen/CVA6Cfg.PtLevels):12]; - lsu_dtlb_ppn_o[PPNWMin-(CVA6Cfg.VpnLen/CVA6Cfg.PtLevels):12] = lsu_vaddr_n[PPNWMin-(CVA6Cfg.VpnLen/CVA6Cfg.PtLevels):12]; + // Strange 9+PtLevels to avoid CI errors on (purely syntactic) checks on Sv32, where + // `PPNWMin-(CVA6Cfg.VpnLen/CVA6Cfg.PtLevels)` equals `11` and would lead to `lsu_paddr_o[11:12]` + lsu_paddr_o[PPNWMin-(CVA6Cfg.VpnLen/CVA6Cfg.PtLevels):9+CVA6Cfg.PtLevels] = lsu_vaddr_q[PPNWMin-(CVA6Cfg.VpnLen/CVA6Cfg.PtLevels):9+CVA6Cfg.PtLevels]; + lsu_dtlb_ppn_o[PPNWMin-(CVA6Cfg.VpnLen/CVA6Cfg.PtLevels):9+CVA6Cfg.PtLevels] = lsu_vaddr_n[PPNWMin-(CVA6Cfg.VpnLen/CVA6Cfg.PtLevels):9+CVA6Cfg.PtLevels]; end if (dtlb_is_page_q[0]) begin @@ -652,7 +652,7 @@ module cva6_mmu }; if (CVA6Cfg.RVH) begin lsu_exception_o.tval2 = ptw_bad_gpaddr[CVA6Cfg.GPLEN-1:0]; - lsu_exception_o.tinst= (ptw_err_at_g_int_st ? (CVA6Cfg.IS_XLEN64 ? riscv::READ_64_PSEUDOINSTRUCTION : riscv::READ_32_PSEUDOINSTRUCTION) : '0); + lsu_exception_o.tinst = (ptw_err_at_g_int_st ? (CVA6Cfg.IS_XLEN64 ? riscv::READ_64_PSEUDOINSTRUCTION : riscv::READ_32_PSEUDOINSTRUCTION) : '0); lsu_exception_o.gva = ld_st_v_i; end end else begin @@ -678,7 +678,7 @@ module cva6_mmu }; if (CVA6Cfg.RVH) begin lsu_exception_o.tval2 = ptw_bad_gpaddr[CVA6Cfg.GPLEN-1:0]; - lsu_exception_o.tinst= (ptw_err_at_g_int_st ? (CVA6Cfg.IS_XLEN64 ? riscv::READ_64_PSEUDOINSTRUCTION : riscv::READ_32_PSEUDOINSTRUCTION) : '0); + lsu_exception_o.tinst = (ptw_err_at_g_int_st ? (CVA6Cfg.IS_XLEN64 ? riscv::READ_64_PSEUDOINSTRUCTION : riscv::READ_32_PSEUDOINSTRUCTION) : '0); lsu_exception_o.gva = ld_st_v_i; end end else begin diff --git a/core/cva6_mmu/cva6_ptw.sv b/core/cva6_mmu/cva6_ptw.sv index 17ba7b2bb..853471766 100644 --- a/core/cva6_mmu/cva6_ptw.sv +++ b/core/cva6_mmu/cva6_ptw.sv @@ -48,9 +48,9 @@ module cva6_ptw input logic v_i, // current virtualization mode bit input logic ld_st_v_i, // load/store virtualization mode bit input logic hlvx_inst_i, // is a HLVX load/store instruction - input logic lsu_is_store_i, // this translation was triggered by a store + input logic lsu_is_store_i, // this translation was triggered by a store // PTW memory interface - input dcache_req_o_t req_port_i, + input dcache_req_o_t req_port_i, output dcache_req_i_t req_port_o, // to TLBs, update logic @@ -194,14 +194,14 @@ module cva6_ptw // update the correct page table level for (int unsigned y = 0; y < HYP_EXT + 1; y++) begin for (int unsigned x = 0; x < CVA6Cfg.PtLevels - 1; x++) begin - // VS + G-Translation if(((enable_g_translation_i && enable_translation_i) || (en_ld_st_g_translation_i && en_ld_st_translation_i)) && CVA6Cfg.RVH) begin - shared_tlb_update_o.is_page[x][y] = (ptw_lvl_q[y==1?0:1] == x); - // Non-V, S-Translation + // VS + G-Translation + shared_tlb_update_o.is_page[x][y] = (ptw_lvl_q[y==1?0 : 1] == x); end else if (enable_translation_i || en_ld_st_translation_i || !CVA6Cfg.RVH) begin + // Non-V, S-Translation shared_tlb_update_o.is_page[x][y] = y == 0 ? (ptw_lvl_q[0] == x) : 1'b0; - // G-Translation end else begin + // G-Translation shared_tlb_update_o.is_page[x][y] = y != 0 ? (ptw_lvl_q[0] == x) : 1'b0; end end @@ -217,9 +217,9 @@ module cva6_ptw end // output the correct ASIDs - shared_tlb_update_o.asid = tlb_update_asid_q; - shared_tlb_update_o.vmid = CVA6Cfg.RVH ? tlb_update_vmid_q : '0; - shared_tlb_update_o.vpn = vaddr_q[12+CVA6Cfg.VpnLen-1:12]; + shared_tlb_update_o.asid = tlb_update_asid_q; + shared_tlb_update_o.vmid = CVA6Cfg.RVH ? tlb_update_vmid_q : '0; + shared_tlb_update_o.vpn = vaddr_q[12+CVA6Cfg.VpnLen-1:12]; shared_tlb_update_o.valid = 1'b1; end else begin shared_tlb_update_o.valid = 1'b0; @@ -470,11 +470,11 @@ module cva6_ptw // entry into the TLB. if ( (pte.a && ((pte.r && !hlvx_inst_i) || (pte.x && (mxr_i || hlvx_inst_i || (ptw_stage_q == S_STAGE && vmxr_i && ld_st_v_i && CVA6Cfg.RVH))))) - // Request is a store: perform some additional checks - // If the request was a store and the page is not write-able, raise an error - // the same applies if the dirty flag is not set - // g-intermediate nodes however never need write-permission - && (!lsu_is_store_i || (pte.w && pte.d) || (ptw_stage_q == G_INTERMED_STAGE && CVA6Cfg.RVH)) + // Request is a store: perform some additional checks + // If the request was a store and the page is not write-able, raise an error + // the same applies if the dirty flag is not set + // g-intermediate nodes however never need write-permission + && (!lsu_is_store_i || (pte.w && pte.d) || (ptw_stage_q == G_INTERMED_STAGE && CVA6Cfg.RVH)) ) begin if ((CVA6Cfg.RVH && ((ptw_stage_q == G_FINAL_STAGE) || !en_ld_st_g_translation_i)) || !CVA6Cfg.RVH) tlb_update_valid = 1'b1; @@ -493,7 +493,7 @@ module cva6_ptw // Check if 63:41 are all zeros if (CVA6Cfg.RVH) begin - if (((v_i && is_instr_ptw_q) || (ld_st_v_i && !is_instr_ptw_q)) && ptw_stage_q == S_STAGE && !((|pte.ppn[CVA6Cfg.PPNW-1:CVA6Cfg.GPPNW-1+HYP_EXT]) == 1'b0)) begin + if (((v_i && is_instr_ptw_q) || (ld_st_v_i && !is_instr_ptw_q)) && ptw_stage_q == S_STAGE && !((|pte.ppn[CVA6Cfg.PPNW-1:CVA6Cfg.GPPNW]) == 1'b0)) begin state_d = PROPAGATE_ERROR; ptw_stage_d = G_FINAL_STAGE; end @@ -551,7 +551,7 @@ module cva6_ptw // Check if 63:41 are all zeros if (CVA6Cfg.RVH) begin - if (((v_i && is_instr_ptw_q) || (ld_st_v_i && !is_instr_ptw_q)) && ptw_stage_q == S_STAGE && !((|pte.ppn[CVA6Cfg.PPNW-1:CVA6Cfg.GPPNW-1+HYP_EXT]) == 1'b0)) begin + if (((v_i && is_instr_ptw_q) || (ld_st_v_i && !is_instr_ptw_q)) && ptw_stage_q == S_STAGE && !((|pte.ppn[CVA6Cfg.PPNW-1:CVA6Cfg.GPPNW]) == 1'b0)) begin state_d = PROPAGATE_ERROR; ptw_stage_d = ptw_stage_q; end diff --git a/core/cva6_mmu/cva6_tlb.sv b/core/cva6_mmu/cva6_tlb.sv index 306f3e7d7..29f63bcb7 100644 --- a/core/cva6_mmu/cva6_tlb.sv +++ b/core/cva6_mmu/cva6_tlb.sv @@ -45,7 +45,7 @@ module cva6_tlb input logic [CVA6Cfg.ASID_WIDTH-1:0] lu_asid_i, input logic [CVA6Cfg.VMID_WIDTH-1:0] lu_vmid_i, input logic [CVA6Cfg.VLEN-1:0] lu_vaddr_i, - output logic [CVA6Cfg.GPLEN-1:0] lu_gpaddr_o, // FIXME + output logic [CVA6Cfg.GPLEN-1:0] lu_gpaddr_o, output pte_cva6_t lu_content_o, output pte_cva6_t lu_g_content_o, input logic [CVA6Cfg.ASID_WIDTH-1:0] asid_to_be_flushed_i, @@ -73,8 +73,8 @@ module cva6_tlb tags_q, tags_n; struct packed { - pte_cva6_t pte; // Result of S-translation of the input - pte_cva6_t gpte; // Output of G-translation of the (possibly S-translated) input + pte_cva6_t pte; // Result of S-translation of the input + pte_cva6_t gpte; // Output of G-translation of the (possibly S-translated) input } [TLB_ENTRIES-1:0] content_q, content_n; @@ -115,29 +115,29 @@ module cva6_tlb // WARNING: `x` goes in the order {0 = 4K, 1 = 2M, 2 = 1G}. // Identify page_match for all TLB Entries: - // `page_match[i][x] == 1` if the entry `i` represent a page of (non-stricly) bigger length than + // `page_match[i][x] == 1` if the entry `i` represents a page of (non-stricly) bigger length than // requested. // 4K is always a match // In case of H-mode, the length of a page in the TLB is the smallest of S-translation and // G-translation - if (x==0) begin + if (x == 0) begin assign page_match[i][x] = 1; end else begin - if (HYP_EXT==0 || x==(CVA6Cfg.PtLevels-1)) begin + if (HYP_EXT == 0 || x == (CVA6Cfg.PtLevels - 1)) begin // No H-mode or Giga page. Then both condition must be true: // - G-stage translation is *not* enabled or G-entry is a matching page (bit 1) // - S-translation is *not* enabled or S-entry i is a matching page (bit 0) assign page_match[i][x] = &(tags_q[i].is_page[CVA6Cfg.PtLevels-1-x][HYP_EXT:0] | (~v_st_enbl[HYP_EXT:0])); end else begin // Other cases: H-mode and mega page - assign page_match[i][x] = (&v_st_enbl[HYP_EXT:0])? - // If S-translation and G-translation are active, then either: - // - S-translation matchs and G-translation is Mega or Giga - // - G-translation matchs and S-translation is Mega or Giga - ((tags_q[i].is_page[CVA6Cfg.PtLevels-1-x][0] && (tags_q[i].is_page[CVA6Cfg.PtLevels-2-x][HYP_EXT] || tags_q[i].is_page[CVA6Cfg.PtLevels-1-x][HYP_EXT])) - || (tags_q[i].is_page[CVA6Cfg.PtLevels-1-x][HYP_EXT] && (tags_q[i].is_page[CVA6Cfg.PtLevels-2-x][0] || tags_q[i].is_page[CVA6Cfg.PtLevels-1-x][0]))) + assign page_match[i][x] = (&v_st_enbl[HYP_EXT:0]) ? + // If S-translation and G-translation are active, then either: + // - S-translation matchs and G-translation is Mega or Giga + // - G-translation matchs and S-translation is Mega or Giga + ((tags_q[i].is_page[CVA6Cfg.PtLevels-1-x][0] && (tags_q[i].is_page[CVA6Cfg.PtLevels-2-x][HYP_EXT] || tags_q[i].is_page[CVA6Cfg.PtLevels-1-x][HYP_EXT])) + || (tags_q[i].is_page[CVA6Cfg.PtLevels-1-x][HYP_EXT] && (tags_q[i].is_page[CVA6Cfg.PtLevels-2-x][0] || tags_q[i].is_page[CVA6Cfg.PtLevels-1-x][0]))) : // Else, either S or G-level must match depending which is active - ((tags_q[i].is_page[CVA6Cfg.PtLevels-1-x][0] && s_st_enbl_i) || (tags_q[i].is_page[CVA6Cfg.PtLevels-1-x][HYP_EXT] && g_st_enbl_i)); + ((tags_q[i].is_page[CVA6Cfg.PtLevels-1-x][0] && s_st_enbl_i) || (tags_q[i].is_page[CVA6Cfg.PtLevels-1-x][HYP_EXT] && g_st_enbl_i)); end end @@ -167,12 +167,12 @@ module cva6_tlb // Reorganise the output structure to match `is_page` tag order: [1G, 2M] for (w = 0; w < CVA6Cfg.PtLevels - 1; w++) begin - assign is_page_o[i][w] = page_match[i][CVA6Cfg.PtLevels - 1 - w]; + assign is_page_o[i][w] = page_match[i][CVA6Cfg.PtLevels-1-w]; end end endgenerate - always_comb begin: translation + always_comb begin : translation // default assignment lu_hit = '{default: 0}; lu_hit_o = 1'b0; @@ -243,8 +243,8 @@ module cva6_tlb end end - logic [HYP_EXT:0] asid_to_be_flushed_is0; // indicates that the ASID provided by SFENCE.VMA (rs2)is 0, active high - logic [HYP_EXT:0] vaddr_to_be_flushed_is0; // indicates that the VADDR provided by SFENCE.VMA (rs1)is 0, active high + logic [HYP_EXT:0] asid_to_be_flushed_is0; // indicates that the ASID provided by SFENCE.VMA (rs2) is 0, active high + logic [HYP_EXT:0] vaddr_to_be_flushed_is0; // indicates that the VADDR provided by SFENCE.VMA (rs1) is 0, active high logic vmid_to_be_flushed_is0; // indicates that the VMID provided is 0, active high logic gpaddr_to_be_flushed_is0; // indicates that the GPADDR provided is 0, active high @@ -269,9 +269,7 @@ module cva6_tlb gppn[i][CVA6Cfg.VpnLen/CVA6Cfg.PtLevels-1:0] = tags_q[i].vpn[0]; // Giga Page if (tags_q[i].is_page[0][0]) - gppn[i][2*(CVA6Cfg.VpnLen/CVA6Cfg.PtLevels)-1:0] = { - tags_q[i].vpn[1], tags_q[i].vpn[0] - }; + gppn[i][2*(CVA6Cfg.VpnLen/CVA6Cfg.PtLevels)-1:0] = {tags_q[i].vpn[1], tags_q[i].vpn[0]}; end else begin gppn[i][CVA6Cfg.VpnLen-1:0] = CVA6Cfg.VpnLen'(tags_q[i].vpn); end