data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/mmu.sv
1: b"%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/mmu.sv:18: syntax error, unexpected IDENTIFIER, expecting PACKAGE-IDENTIFIER\nmodule mmu import ariane_pkg::*; #(\n                  ^~~~~~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/mmu.sv:20: syntax error, unexpected parameter, expecting IDENTIFIER\n    parameter int unsigned DATA_TLB_ENTRIES      = 4,\n    ^~~~~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/mmu.sv:21: syntax error, unexpected parameter, expecting IDENTIFIER\n    parameter int unsigned ASID_WIDTH            = 1,\n    ^~~~~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/mmu.sv:22: syntax error, unexpected parameter, expecting IDENTIFIER\n    parameter ariane_pkg::ariane_cfg_t ArianeCfg = ariane_pkg::ArianeDefaultConfig\n    ^~~~~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/mmu.sv:25: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n    input  logic                            rst_ni,\n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/mmu.sv:26: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n    input  logic                            flush_i,\n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/mmu.sv:27: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n    input  logic                            enable_translation_i,\n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/mmu.sv:28: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n    input  logic                            en_ld_st_translation_i,    \n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/mmu.sv:30: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n    input  icache_areq_o_t                  icache_areq_i,\n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/mmu.sv:37: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n    input  logic [riscv::VLEN-1:0]          lsu_vaddr_i,       \n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/mmu.sv:37: syntax error, unexpected ::, expecting ':'\n    input  logic [riscv::VLEN-1:0]          lsu_vaddr_i,       \n                       ^~\n                                                                                                       : ... Perhaps 'riscv' is a package which needs to be predeclared? (IEEE 1800-2017 26.3)\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/mmu.sv:41: syntax error, unexpected output, expecting IDENTIFIER or '=' or do or final\n    output logic                            lsu_dtlb_hit_o,    \n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/mmu.sv:42: syntax error, unexpected output, expecting IDENTIFIER or '=' or do or final\n    output logic [riscv::PPNW-1:0]          lsu_dtlb_ppn_o,    \n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/mmu.sv:42: syntax error, unexpected ::, expecting ':'\n    output logic [riscv::PPNW-1:0]          lsu_dtlb_ppn_o,    \n                       ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/mmu.sv:45: syntax error, unexpected output, expecting IDENTIFIER or '=' or do or final\n    output logic [riscv::PLEN-1:0]          lsu_paddr_o,       \n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/mmu.sv:45: syntax error, unexpected ::, expecting ':'\n    output logic [riscv::PLEN-1:0]          lsu_paddr_o,       \n                       ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/mmu.sv:51: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n    input logic                             mxr_i,\n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/mmu.sv:53: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n    input logic [riscv::PPNW-1:0]           satp_ppn_i,\n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/mmu.sv:53: syntax error, unexpected ::, expecting ':'\n    input logic [riscv::PPNW-1:0]           satp_ppn_i,\n                      ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/mmu.sv:55: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n    input logic [ASID_WIDTH-1:0]            asid_to_be_flushed_i,\n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/mmu.sv:56: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n    input logic [riscv::VLEN-1:0]           vaddr_to_be_flushed_i,\n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/mmu.sv:56: syntax error, unexpected ::, expecting ':'\n    input logic [riscv::VLEN-1:0]           vaddr_to_be_flushed_i,\n                      ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/mmu.sv:59: syntax error, unexpected output, expecting IDENTIFIER or '=' or do or final\n    output logic                            itlb_miss_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/mmu.sv:60: syntax error, unexpected output, expecting IDENTIFIER or '=' or do or final\n    output logic                            dtlb_miss_o,\n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/mmu.sv:62: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n    input  dcache_req_o_t                   req_port_i,\n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/mmu.sv:66: syntax error, unexpected ::, expecting ':'\n    input  logic [15:0][riscv::PLEN-3:0]    pmpaddr_i\n                             ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/mmu.sv:75: syntax error, unexpected ::, expecting ':'\n    logic [riscv::PLEN-1:0] ptw_bad_paddr;  \n                ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/mmu.sv:77: syntax error, unexpected ::, expecting ':'\n    logic [riscv::VLEN-1:0] update_vaddr;\n                ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/mmu.sv:81: syntax error, unexpected IDENTIFIER\n    riscv::pte_t itlb_content;\n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/mmu.sv:87: syntax error, unexpected IDENTIFIER\n    riscv::pte_t dtlb_content;\n    ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/mmu.sv:94: syntax error, unexpected assign\n    assign itlb_lu_access = icache_areq_i.fetch_req;\n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/mmu.sv:201: syntax error, unexpected always_comb\n    always_comb begin : instr_interface\n    ^~~~~~~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/mmu.sv:290: syntax error, unexpected ::, expecting ':'\n    logic [riscv::VLEN-1:0] lsu_vaddr_n,     lsu_vaddr_q;\n                ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/mmu.sv:300: syntax error, unexpected assign\n    assign lsu_dtlb_hit_o = (en_ld_st_translation_i) ? dtlb_lu_hit :  1'b1;\n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/mmu.sv:305: syntax error, unexpected ::\n    localparam   PPNWMin = (riscv::PPNW-1 > 29) ? 29 : riscv::PPNW-1;\n                                 ^~\n%Error: Exiting due to 35 error(s)\n"
module mmu import ariane_pkg::*; #(
    parameter int unsigned INSTR_TLB_ENTRIES     = 4,
    parameter int unsigned DATA_TLB_ENTRIES      = 4,
    parameter int unsigned ASID_WIDTH            = 1,
    parameter ariane_pkg::ariane_cfg_t ArianeCfg = ariane_pkg::ArianeDefaultConfig
) (
    input  logic                            clk_i,
    input  logic                            rst_ni,
    input  logic                            flush_i,
    input  logic                            enable_translation_i,
    input  logic                            en_ld_st_translation_i,

    input  icache_areq_o_t                  icache_areq_i,
    output icache_areq_i_t                  icache_areq_o,



    input  exception_t                      misaligned_ex_i,
    input  logic                            lsu_req_i,
    input  logic [riscv::VLEN-1:0]          lsu_vaddr_i,
    input  logic                            lsu_is_store_i,


    output logic                            lsu_dtlb_hit_o,
    output logic [riscv::PPNW-1:0]          lsu_dtlb_ppn_o,

    output logic                            lsu_valid_o,
    output logic [riscv::PLEN-1:0]          lsu_paddr_o,
    output exception_t                      lsu_exception_o,

    input riscv::priv_lvl_t                 priv_lvl_i,
    input riscv::priv_lvl_t                 ld_st_priv_lvl_i,
    input logic                             sum_i,
    input logic                             mxr_i,

    input logic [riscv::PPNW-1:0]           satp_ppn_i,
    input logic [ASID_WIDTH-1:0]            asid_i,
    input logic [ASID_WIDTH-1:0]            asid_to_be_flushed_i,
    input logic [riscv::VLEN-1:0]           vaddr_to_be_flushed_i,
    input logic                             flush_tlb_i,

    output logic                            itlb_miss_o,
    output logic                            dtlb_miss_o,

    input  dcache_req_o_t                   req_port_i,
    output dcache_req_i_t                   req_port_o,

    input  riscv::pmpcfg_t [15:0]           pmpcfg_i,
    input  logic [15:0][riscv::PLEN-3:0]    pmpaddr_i
);

    logic                   iaccess_err;
    logic                   daccess_err;
    logic                   ptw_active;
    logic                   walking_instr;
    logic                   ptw_error;
    logic                   ptw_access_exception;
    logic [riscv::PLEN-1:0] ptw_bad_paddr;

    logic [riscv::VLEN-1:0] update_vaddr;
    tlb_update_t update_ptw_itlb, update_ptw_dtlb;

    logic        itlb_lu_access;
    riscv::pte_t itlb_content;
    logic        itlb_is_2M;
    logic        itlb_is_1G;
    logic        itlb_lu_hit;

    logic        dtlb_lu_access;
    riscv::pte_t dtlb_content;
    logic        dtlb_is_2M;
    logic        dtlb_is_1G;
    logic        dtlb_lu_hit;



    assign itlb_lu_access = icache_areq_i.fetch_req;
    assign dtlb_lu_access = lsu_req_i;


    tlb #(
        .TLB_ENTRIES      ( INSTR_TLB_ENTRIES          ),
        .ASID_WIDTH       ( ASID_WIDTH                 )
    ) i_itlb (
        .clk_i            ( clk_i                      ),
        .rst_ni           ( rst_ni                     ),
        .flush_i          ( flush_tlb_i                ),

        .update_i         ( update_ptw_itlb            ),

        .lu_access_i      ( itlb_lu_access             ),
        .lu_asid_i        ( asid_i                     ),
        .asid_to_be_flushed_i  ( asid_to_be_flushed_i  ),
        .vaddr_to_be_flushed_i ( vaddr_to_be_flushed_i ),
        .lu_vaddr_i       ( icache_areq_i.fetch_vaddr  ),
        .lu_content_o     ( itlb_content               ),

        .lu_is_2M_o       ( itlb_is_2M                 ),
        .lu_is_1G_o       ( itlb_is_1G                 ),
        .lu_hit_o         ( itlb_lu_hit                )
    );

    tlb #(
        .TLB_ENTRIES     ( DATA_TLB_ENTRIES             ),
        .ASID_WIDTH      ( ASID_WIDTH                   )
    ) i_dtlb (
        .clk_i            ( clk_i                       ),
        .rst_ni           ( rst_ni                      ),
        .flush_i          ( flush_tlb_i                 ),

        .update_i         ( update_ptw_dtlb             ),

        .lu_access_i      ( dtlb_lu_access              ),
        .lu_asid_i        ( asid_i                      ),
	      .asid_to_be_flushed_i  ( asid_to_be_flushed_i   ),
	      .vaddr_to_be_flushed_i ( vaddr_to_be_flushed_i  ),
        .lu_vaddr_i       ( lsu_vaddr_i                 ),
        .lu_content_o     ( dtlb_content                ),

        .lu_is_2M_o       ( dtlb_is_2M                  ),
        .lu_is_1G_o       ( dtlb_is_1G                  ),
        .lu_hit_o         ( dtlb_lu_hit                 )
    );


    ptw  #(
        .ASID_WIDTH             ( ASID_WIDTH            ),
        .ArianeCfg              ( ArianeCfg             )
    ) i_ptw (
        .clk_i                  ( clk_i                 ),
        .rst_ni                 ( rst_ni                ),
        .ptw_active_o           ( ptw_active            ),
        .walking_instr_o        ( walking_instr         ),
        .ptw_error_o            ( ptw_error             ),
        .ptw_access_exception_o ( ptw_access_exception  ),
        .enable_translation_i   ( enable_translation_i  ),

        .update_vaddr_o         ( update_vaddr          ),
        .itlb_update_o          ( update_ptw_itlb       ),
        .dtlb_update_o          ( update_ptw_dtlb       ),

        .itlb_access_i          ( itlb_lu_access        ),
        .itlb_hit_i             ( itlb_lu_hit           ),
        .itlb_vaddr_i           ( icache_areq_i.fetch_vaddr ),

        .dtlb_access_i          ( dtlb_lu_access        ),
        .dtlb_hit_i             ( dtlb_lu_hit           ),
        .dtlb_vaddr_i           ( lsu_vaddr_i           ),

        .req_port_i             ( req_port_i            ),
        .req_port_o             ( req_port_o            ),
        .pmpcfg_i,
        .pmpaddr_i,
        .bad_paddr_o            ( ptw_bad_paddr         ),
        .*
    );























    logic match_any_execute_region;
    logic pmp_instr_allow;


    always_comb begin : instr_interface

        icache_areq_o.fetch_valid  = icache_areq_i.fetch_req;
        icache_areq_o.fetch_paddr  = icache_areq_i.fetch_vaddr[riscv::PLEN-1:0];



        icache_areq_o.fetch_exception      = '0;

        iaccess_err   = icache_areq_i.fetch_req && (((priv_lvl_i == riscv::PRIV_LVL_U) && ~itlb_content.u)
                                                 || ((priv_lvl_i == riscv::PRIV_LVL_S) && itlb_content.u));





        if (enable_translation_i) begin

            if (icache_areq_i.fetch_req && !((&icache_areq_i.fetch_vaddr[riscv::VLEN-1:riscv::SV-1]) == 1'b1 || (|icache_areq_i.fetch_vaddr[riscv::VLEN-1:riscv::SV-1]) == 1'b0)) begin
                icache_areq_o.fetch_exception = {riscv::INSTR_ACCESS_FAULT, {{riscv::XLEN-riscv::VLEN{1'b0}}, icache_areq_i.fetch_vaddr}, 1'b1};
            end

            icache_areq_o.fetch_valid = 1'b0;


            icache_areq_o.fetch_paddr = {itlb_content.ppn, icache_areq_i.fetch_vaddr[11:0]};

            if (itlb_is_2M) begin
                icache_areq_o.fetch_paddr[20:12] = icache_areq_i.fetch_vaddr[20:12];
            end

            if (itlb_is_1G) begin
                icache_areq_o.fetch_paddr[29:12] = icache_areq_i.fetch_vaddr[29:12];
            end





            if (itlb_lu_hit) begin
                icache_areq_o.fetch_valid = icache_areq_i.fetch_req;

                if (iaccess_err) begin

                    icache_areq_o.fetch_exception = {riscv::INSTR_PAGE_FAULT, {{riscv::XLEN-riscv::VLEN{1'b0}}, icache_areq_i.fetch_vaddr}, 1'b1};
                end else if (!pmp_instr_allow) begin
                    icache_areq_o.fetch_exception = {riscv::INSTR_ACCESS_FAULT, {{riscv::XLEN-riscv::PLEN{1'b0}}, icache_areq_i.fetch_vaddr}, 1'b1};
                end
            end else




            if (ptw_active && walking_instr) begin
                icache_areq_o.fetch_valid = ptw_error | ptw_access_exception;
                if (ptw_error) icache_areq_o.fetch_exception = {riscv::INSTR_PAGE_FAULT, {{riscv::XLEN-riscv::VLEN{1'b0}}, update_vaddr}, 1'b1};

                else icache_areq_o.fetch_exception = {riscv::INSTR_ACCESS_FAULT, {{riscv::XLEN-riscv::VLEN{1'b0}}, ptw_bad_paddr}, 1'b1};
            end
        end


        if (!match_any_execute_region || (!enable_translation_i && !pmp_instr_allow)) begin
          icache_areq_o.fetch_exception = {riscv::INSTR_ACCESS_FAULT, {{riscv::XLEN-riscv::PLEN{1'b0}}, icache_areq_o.fetch_paddr}, 1'b1};
        end
    end


    assign match_any_execute_region = ariane_pkg::is_inside_execute_regions(ArianeCfg, {{64-riscv::PLEN{1'b0}}, icache_areq_o.fetch_paddr});


    pmp #(
        .PLEN       ( riscv::PLEN            ),
        .PMP_LEN    ( riscv::PLEN - 2        ),
        .NR_ENTRIES ( ArianeCfg.NrPMPEntries )
    ) i_pmp_if (
        .addr_i        ( icache_areq_o.fetch_paddr ),
        .priv_lvl_i,

        .access_type_i ( riscv::ACCESS_EXEC        ),

        .conf_addr_i   ( pmpaddr_i                 ),
        .conf_i        ( pmpcfg_i                  ),
        .allow_o       ( pmp_instr_allow           )
    );




    logic [riscv::VLEN-1:0] lsu_vaddr_n,     lsu_vaddr_q;
    riscv::pte_t dtlb_pte_n,      dtlb_pte_q;
    exception_t  misaligned_ex_n, misaligned_ex_q;
    logic        lsu_req_n,       lsu_req_q;
    logic        lsu_is_store_n,  lsu_is_store_q;
    logic        dtlb_hit_n,      dtlb_hit_q;
    logic        dtlb_is_2M_n,    dtlb_is_2M_q;
    logic        dtlb_is_1G_n,    dtlb_is_1G_q;


    assign lsu_dtlb_hit_o = (en_ld_st_translation_i) ? dtlb_lu_hit :  1'b1;


    riscv::pmp_access_t pmp_access_type;
    logic        pmp_data_allow;
    localparam   PPNWMin = (riscv::PPNW-1 > 29) ? 29 : riscv::PPNW-1;

    always_comb begin : data_interface

        lsu_vaddr_n           = lsu_vaddr_i;
        lsu_req_n             = lsu_req_i;
        misaligned_ex_n       = misaligned_ex_i;
        dtlb_pte_n            = dtlb_content;
        dtlb_hit_n            = dtlb_lu_hit;
        lsu_is_store_n        = lsu_is_store_i;
        dtlb_is_2M_n          = dtlb_is_2M;
        dtlb_is_1G_n          = dtlb_is_1G;

        lsu_paddr_o           = lsu_vaddr_q[riscv::PLEN-1:0];
        lsu_dtlb_ppn_o        = lsu_vaddr_n[riscv::PLEN-1:12];
        lsu_valid_o           = lsu_req_q;
        lsu_exception_o       = misaligned_ex_q;
        pmp_access_type       = lsu_is_store_q ? riscv::ACCESS_WRITE : riscv::ACCESS_READ;


        misaligned_ex_n.valid = misaligned_ex_i.valid & lsu_req_i;



        daccess_err = (ld_st_priv_lvl_i == riscv::PRIV_LVL_S && !sum_i && dtlb_pte_q.u) ||
                      (ld_st_priv_lvl_i == riscv::PRIV_LVL_U && !dtlb_pte_q.u);

        if (en_ld_st_translation_i && !misaligned_ex_q.valid) begin
            lsu_valid_o = 1'b0;

            lsu_paddr_o = {dtlb_pte_q.ppn, lsu_vaddr_q[11:0]};
            lsu_dtlb_ppn_o = dtlb_content.ppn;

            if (dtlb_is_2M_q) begin
              lsu_paddr_o[20:12] = lsu_vaddr_q[20:12];
              lsu_dtlb_ppn_o[20:12] = lsu_vaddr_n[20:12];
            end

            if (dtlb_is_1G_q) begin
                lsu_paddr_o[PPNWMin:12] = lsu_vaddr_q[PPNWMin:12];
                lsu_dtlb_ppn_o[PPNWMin:12] = lsu_vaddr_n[PPNWMin:12];
            end



            if (dtlb_hit_q && lsu_req_q) begin
                lsu_valid_o = 1'b1;






                if (lsu_is_store_q) begin


                    if (!dtlb_pte_q.w || daccess_err || !dtlb_pte_q.d) begin
                        lsu_exception_o = {riscv::STORE_PAGE_FAULT, {{riscv::XLEN-riscv::VLEN{lsu_vaddr_q[riscv::VLEN-1]}},lsu_vaddr_q}, 1'b1};

                    end else if (!pmp_data_allow) begin
                        lsu_exception_o = {riscv::ST_ACCESS_FAULT, {{riscv::XLEN-riscv::PLEN{1'b0}}, lsu_paddr_o}, 1'b1};
                    end


                end else begin

                    if (daccess_err) begin
                        lsu_exception_o = {riscv::LOAD_PAGE_FAULT, {{riscv::XLEN-riscv::VLEN{lsu_vaddr_q[riscv::VLEN-1]}},lsu_vaddr_q}, 1'b1};

                    end else if (!pmp_data_allow) begin
                        lsu_exception_o = {riscv::LD_ACCESS_FAULT, {{riscv::XLEN-riscv::PLEN{1'b0}}, lsu_paddr_o}, 1'b1};
                    end
                end
            end else





            if (ptw_active && !walking_instr) begin

                if (ptw_error) begin

                    lsu_valid_o = 1'b1;

                    if (lsu_is_store_q) begin
                        lsu_exception_o = {riscv::STORE_PAGE_FAULT, {{riscv::XLEN-riscv::VLEN{lsu_vaddr_q[riscv::VLEN-1]}},update_vaddr}, 1'b1};
                    end else begin
                        lsu_exception_o = {riscv::LOAD_PAGE_FAULT, {{riscv::XLEN-riscv::VLEN{lsu_vaddr_q[riscv::VLEN-1]}},update_vaddr}, 1'b1};
                    end
                end

                if (ptw_access_exception) begin

                    lsu_valid_o = 1'b1;

                    lsu_exception_o = {riscv::LD_ACCESS_FAULT, {{riscv::XLEN-riscv::PLEN{1'b0}}, ptw_bad_paddr}, 1'b1};
                end
            end
        end

        else if (lsu_req_q && !misaligned_ex_q.valid && !pmp_data_allow) begin
            if (lsu_is_store_q) begin
                lsu_exception_o = {riscv::ST_ACCESS_FAULT, {{riscv::XLEN-riscv::PLEN{1'b0}}, lsu_paddr_o}, 1'b1};
            end else begin
                lsu_exception_o = {riscv::LD_ACCESS_FAULT, {{riscv::XLEN-riscv::PLEN{1'b0}}, lsu_paddr_o}, 1'b1};
            end
        end
    end


    pmp #(
        .PLEN       ( riscv::PLEN            ),
        .PMP_LEN    ( riscv::PLEN - 2        ),
        .NR_ENTRIES ( ArianeCfg.NrPMPEntries )
    ) i_pmp_data (
        .addr_i        ( lsu_paddr_o         ),
        .priv_lvl_i    ( ld_st_priv_lvl_i    ),
        .access_type_i ( pmp_access_type     ),

        .conf_addr_i   ( pmpaddr_i           ),
        .conf_i        ( pmpcfg_i            ),
        .allow_o       ( pmp_data_allow      )
    );




    always_ff @(posedge clk_i or negedge rst_ni) begin
        if (~rst_ni) begin
            lsu_vaddr_q      <= '0;
            lsu_req_q        <= '0;
            misaligned_ex_q  <= '0;
            dtlb_pte_q       <= '0;
            dtlb_hit_q       <= '0;
            lsu_is_store_q   <= '0;
            dtlb_is_2M_q     <= '0;
            dtlb_is_1G_q     <= '0;
        end else begin
            lsu_vaddr_q      <=  lsu_vaddr_n;
            lsu_req_q        <=  lsu_req_n;
            misaligned_ex_q  <=  misaligned_ex_n;
            dtlb_pte_q       <=  dtlb_pte_n;
            dtlb_hit_q       <=  dtlb_hit_n;
            lsu_is_store_q   <=  lsu_is_store_n;
            dtlb_is_2M_q     <=  dtlb_is_2M_n;
            dtlb_is_1G_q     <=  dtlb_is_1G_n;
        end
    end
endmodule
module mmu import ariane_pkg::*;
 #(
    parameter int unsigned INSTR_TLB_ENTRIES     = 4,
    parameter int unsigned DATA_TLB_ENTRIES      = 4,
    parameter int unsigned ASID_WIDTH            = 1,
    parameter ariane_pkg::ariane_cfg_t ArianeCfg = ariane_pkg::ArianeDefaultConfig
) (
    input  logic                            clk_i,
    input  logic                            rst_ni,
    input  logic                            flush_i,
    input  logic                            enable_translation_i,
    input  logic                            en_ld_st_translation_i,

    input  icache_areq_o_t                  icache_areq_i,
    output icache_areq_i_t                  icache_areq_o,



    input  exception_t                      misaligned_ex_i,
    input  logic                            lsu_req_i,
    input  logic [riscv::VLEN-1:0]          lsu_vaddr_i,
    input  logic                            lsu_is_store_i,


    output logic                            lsu_dtlb_hit_o,
    output logic [riscv::PPNW-1:0]          lsu_dtlb_ppn_o,

    output logic                            lsu_valid_o,
    output logic [riscv::PLEN-1:0]          lsu_paddr_o,
    output exception_t                      lsu_exception_o,

    input riscv::priv_lvl_t                 priv_lvl_i,
    input riscv::priv_lvl_t                 ld_st_priv_lvl_i,
    input logic                             sum_i,
    input logic                             mxr_i,

    input logic [riscv::PPNW-1:0]           satp_ppn_i,
    input logic [ASID_WIDTH-1:0]            asid_i,
    input logic [ASID_WIDTH-1:0]            asid_to_be_flushed_i,
    input logic [riscv::VLEN-1:0]           vaddr_to_be_flushed_i,
    input logic                             flush_tlb_i,

    output logic                            itlb_miss_o,
    output logic                            dtlb_miss_o,

    input  dcache_req_o_t                   req_port_i,
    output dcache_req_i_t                   req_port_o,

    input  riscv::pmpcfg_t [15:0]           pmpcfg_i,
    input  logic [15:0][riscv::PLEN-3:0]    pmpaddr_i
);

    logic                   iaccess_err;
    logic                   daccess_err;
    logic                   ptw_active;
    logic                   walking_instr;
    logic                   ptw_error;
    logic                   ptw_access_exception;
    logic [riscv::PLEN-1:0] ptw_bad_paddr;

    logic [riscv::VLEN-1:0] update_vaddr;
    tlb_update_t update_ptw_itlb, update_ptw_dtlb;

    logic        itlb_lu_access;
    riscv::pte_t itlb_content;
    logic        itlb_is_2M;
    logic        itlb_is_1G;
    logic        itlb_lu_hit;

    logic        dtlb_lu_access;
    riscv::pte_t dtlb_content;
    logic        dtlb_is_2M;
    logic        dtlb_is_1G;
    logic        dtlb_lu_hit;



    assign itlb_lu_access = icache_areq_i.fetch_req;
    assign dtlb_lu_access = lsu_req_i;


    tlb #(
        .TLB_ENTRIES      ( INSTR_TLB_ENTRIES          ),
        .ASID_WIDTH       ( ASID_WIDTH                 )
    ) i_itlb (
        .clk_i            ( clk_i                      ),
        .rst_ni           ( rst_ni                     ),
        .flush_i          ( flush_tlb_i                ),

        .update_i         ( update_ptw_itlb            ),

        .lu_access_i      ( itlb_lu_access             ),
        .lu_asid_i        ( asid_i                     ),
        .asid_to_be_flushed_i  ( asid_to_be_flushed_i  ),
        .vaddr_to_be_flushed_i ( vaddr_to_be_flushed_i ),
        .lu_vaddr_i       ( icache_areq_i.fetch_vaddr  ),
        .lu_content_o     ( itlb_content               ),

        .lu_is_2M_o       ( itlb_is_2M                 ),
        .lu_is_1G_o       ( itlb_is_1G                 ),
        .lu_hit_o         ( itlb_lu_hit                )
    );

    tlb #(
        .TLB_ENTRIES     ( DATA_TLB_ENTRIES             ),
        .ASID_WIDTH      ( ASID_WIDTH                   )
    ) i_dtlb (
        .clk_i            ( clk_i                       ),
        .rst_ni           ( rst_ni                      ),
        .flush_i          ( flush_tlb_i                 ),

        .update_i         ( update_ptw_dtlb             ),

        .lu_access_i      ( dtlb_lu_access              ),
        .lu_asid_i        ( asid_i                      ),
	      .asid_to_be_flushed_i  ( asid_to_be_flushed_i   ),
	      .vaddr_to_be_flushed_i ( vaddr_to_be_flushed_i  ),
        .lu_vaddr_i       ( lsu_vaddr_i                 ),
        .lu_content_o     ( dtlb_content                ),

        .lu_is_2M_o       ( dtlb_is_2M                  ),
        .lu_is_1G_o       ( dtlb_is_1G                  ),
        .lu_hit_o         ( dtlb_lu_hit                 )
    );


    ptw  #(
        .ASID_WIDTH             ( ASID_WIDTH            ),
        .ArianeCfg              ( ArianeCfg             )
    ) i_ptw (
        .clk_i                  ( clk_i                 ),
        .rst_ni                 ( rst_ni                ),
        .ptw_active_o           ( ptw_active            ),
        .walking_instr_o        ( walking_instr         ),
        .ptw_error_o            ( ptw_error             ),
        .ptw_access_exception_o ( ptw_access_exception  ),
        .enable_translation_i   ( enable_translation_i  ),

        .update_vaddr_o         ( update_vaddr          ),
        .itlb_update_o          ( update_ptw_itlb       ),
        .dtlb_update_o          ( update_ptw_dtlb       ),

        .itlb_access_i          ( itlb_lu_access        ),
        .itlb_hit_i             ( itlb_lu_hit           ),
        .itlb_vaddr_i           ( icache_areq_i.fetch_vaddr ),

        .dtlb_access_i          ( dtlb_lu_access        ),
        .dtlb_hit_i             ( dtlb_lu_hit           ),
        .dtlb_vaddr_i           ( lsu_vaddr_i           ),

        .req_port_i             ( req_port_i            ),
        .req_port_o             ( req_port_o            ),
        .pmpcfg_i,
        .pmpaddr_i,
        .bad_paddr_o            ( ptw_bad_paddr         ),
        .*
    );























    logic match_any_execute_region;
    logic pmp_instr_allow;


    always_comb begin : instr_interface

        icache_areq_o.fetch_valid  = icache_areq_i.fetch_req;
        icache_areq_o.fetch_paddr  = icache_areq_i.fetch_vaddr[riscv::PLEN-1:0];



        icache_areq_o.fetch_exception      = '0;

        iaccess_err   = icache_areq_i.fetch_req && (((priv_lvl_i == riscv::PRIV_LVL_U) && ~itlb_content.u)
                                                 || ((priv_lvl_i == riscv::PRIV_LVL_S) && itlb_content.u));





        if (enable_translation_i) begin

            if (icache_areq_i.fetch_req && !((&icache_areq_i.fetch_vaddr[riscv::VLEN-1:riscv::SV-1]) == 1'b1 || (|icache_areq_i.fetch_vaddr[riscv::VLEN-1:riscv::SV-1]) == 1'b0)) begin
                icache_areq_o.fetch_exception = {riscv::INSTR_ACCESS_FAULT, {{riscv::XLEN-riscv::VLEN{1'b0}}, icache_areq_i.fetch_vaddr}, 1'b1};
            end

            icache_areq_o.fetch_valid = 1'b0;


            icache_areq_o.fetch_paddr = {itlb_content.ppn, icache_areq_i.fetch_vaddr[11:0]};

            if (itlb_is_2M) begin
                icache_areq_o.fetch_paddr[20:12] = icache_areq_i.fetch_vaddr[20:12];
            end

            if (itlb_is_1G) begin
                icache_areq_o.fetch_paddr[29:12] = icache_areq_i.fetch_vaddr[29:12];
            end





            if (itlb_lu_hit) begin
                icache_areq_o.fetch_valid = icache_areq_i.fetch_req;

                if (iaccess_err) begin

                    icache_areq_o.fetch_exception = {riscv::INSTR_PAGE_FAULT, {{riscv::XLEN-riscv::VLEN{1'b0}}, icache_areq_i.fetch_vaddr}, 1'b1};
                end else if (!pmp_instr_allow) begin
                    icache_areq_o.fetch_exception = {riscv::INSTR_ACCESS_FAULT, {{riscv::XLEN-riscv::PLEN{1'b0}}, icache_areq_i.fetch_vaddr}, 1'b1};
                end
            end else




            if (ptw_active && walking_instr) begin
                icache_areq_o.fetch_valid = ptw_error | ptw_access_exception;
                if (ptw_error) icache_areq_o.fetch_exception = {riscv::INSTR_PAGE_FAULT, {{riscv::XLEN-riscv::VLEN{1'b0}}, update_vaddr}, 1'b1};

                else icache_areq_o.fetch_exception = {riscv::INSTR_ACCESS_FAULT, {{riscv::XLEN-riscv::VLEN{1'b0}}, ptw_bad_paddr}, 1'b1};
            end
        end


        if (!match_any_execute_region || (!enable_translation_i && !pmp_instr_allow)) begin
          icache_areq_o.fetch_exception = {riscv::INSTR_ACCESS_FAULT, {{riscv::XLEN-riscv::PLEN{1'b0}}, icache_areq_o.fetch_paddr}, 1'b1};
        end
    end


    assign match_any_execute_region = ariane_pkg::is_inside_execute_regions(ArianeCfg, {{64-riscv::PLEN{1'b0}}, icache_areq_o.fetch_paddr});


    pmp #(
        .PLEN       ( riscv::PLEN            ),
        .PMP_LEN    ( riscv::PLEN - 2        ),
        .NR_ENTRIES ( ArianeCfg.NrPMPEntries )
    ) i_pmp_if (
        .addr_i        ( icache_areq_o.fetch_paddr ),
        .priv_lvl_i,

        .access_type_i ( riscv::ACCESS_EXEC        ),

        .conf_addr_i   ( pmpaddr_i                 ),
        .conf_i        ( pmpcfg_i                  ),
        .allow_o       ( pmp_instr_allow           )
    );




    logic [riscv::VLEN-1:0] lsu_vaddr_n,     lsu_vaddr_q;
    riscv::pte_t dtlb_pte_n,      dtlb_pte_q;
    exception_t  misaligned_ex_n, misaligned_ex_q;
    logic        lsu_req_n,       lsu_req_q;
    logic        lsu_is_store_n,  lsu_is_store_q;
    logic        dtlb_hit_n,      dtlb_hit_q;
    logic        dtlb_is_2M_n,    dtlb_is_2M_q;
    logic        dtlb_is_1G_n,    dtlb_is_1G_q;


    assign lsu_dtlb_hit_o = (en_ld_st_translation_i) ? dtlb_lu_hit :  1'b1;


    riscv::pmp_access_t pmp_access_type;
    logic        pmp_data_allow;
    localparam   PPNWMin = (riscv::PPNW-1 > 29) ? 29 : riscv::PPNW-1;

    always_comb begin : data_interface

        lsu_vaddr_n           = lsu_vaddr_i;
        lsu_req_n             = lsu_req_i;
        misaligned_ex_n       = misaligned_ex_i;
        dtlb_pte_n            = dtlb_content;
        dtlb_hit_n            = dtlb_lu_hit;
        lsu_is_store_n        = lsu_is_store_i;
        dtlb_is_2M_n          = dtlb_is_2M;
        dtlb_is_1G_n          = dtlb_is_1G;

        lsu_paddr_o           = lsu_vaddr_q[riscv::PLEN-1:0];
        lsu_dtlb_ppn_o        = lsu_vaddr_n[riscv::PLEN-1:12];
        lsu_valid_o           = lsu_req_q;
        lsu_exception_o       = misaligned_ex_q;
        pmp_access_type       = lsu_is_store_q ? riscv::ACCESS_WRITE : riscv::ACCESS_READ;


        misaligned_ex_n.valid = misaligned_ex_i.valid & lsu_req_i;



        daccess_err = (ld_st_priv_lvl_i == riscv::PRIV_LVL_S && !sum_i && dtlb_pte_q.u) ||
                      (ld_st_priv_lvl_i == riscv::PRIV_LVL_U && !dtlb_pte_q.u);

        if (en_ld_st_translation_i && !misaligned_ex_q.valid) begin
            lsu_valid_o = 1'b0;

            lsu_paddr_o = {dtlb_pte_q.ppn, lsu_vaddr_q[11:0]};
            lsu_dtlb_ppn_o = dtlb_content.ppn;

            if (dtlb_is_2M_q) begin
              lsu_paddr_o[20:12] = lsu_vaddr_q[20:12];
              lsu_dtlb_ppn_o[20:12] = lsu_vaddr_n[20:12];
            end

            if (dtlb_is_1G_q) begin
                lsu_paddr_o[PPNWMin:12] = lsu_vaddr_q[PPNWMin:12];
                lsu_dtlb_ppn_o[PPNWMin:12] = lsu_vaddr_n[PPNWMin:12];
            end



            if (dtlb_hit_q && lsu_req_q) begin
                lsu_valid_o = 1'b1;






                if (lsu_is_store_q) begin


                    if (!dtlb_pte_q.w || daccess_err || !dtlb_pte_q.d) begin
                        lsu_exception_o = {riscv::STORE_PAGE_FAULT, {{riscv::XLEN-riscv::VLEN{lsu_vaddr_q[riscv::VLEN-1]}},lsu_vaddr_q}, 1'b1};

                    end else if (!pmp_data_allow) begin
                        lsu_exception_o = {riscv::ST_ACCESS_FAULT, {{riscv::XLEN-riscv::PLEN{1'b0}}, lsu_paddr_o}, 1'b1};
                    end


                end else begin

                    if (daccess_err) begin
                        lsu_exception_o = {riscv::LOAD_PAGE_FAULT, {{riscv::XLEN-riscv::VLEN{lsu_vaddr_q[riscv::VLEN-1]}},lsu_vaddr_q}, 1'b1};

                    end else if (!pmp_data_allow) begin
                        lsu_exception_o = {riscv::LD_ACCESS_FAULT, {{riscv::XLEN-riscv::PLEN{1'b0}}, lsu_paddr_o}, 1'b1};
                    end
                end
            end else





            if (ptw_active && !walking_instr) begin

                if (ptw_error) begin

                    lsu_valid_o = 1'b1;

                    if (lsu_is_store_q) begin
                        lsu_exception_o = {riscv::STORE_PAGE_FAULT, {{riscv::XLEN-riscv::VLEN{lsu_vaddr_q[riscv::VLEN-1]}},update_vaddr}, 1'b1};
                    end else begin
                        lsu_exception_o = {riscv::LOAD_PAGE_FAULT, {{riscv::XLEN-riscv::VLEN{lsu_vaddr_q[riscv::VLEN-1]}},update_vaddr}, 1'b1};
                    end
                end

                if (ptw_access_exception) begin

                    lsu_valid_o = 1'b1;

                    lsu_exception_o = {riscv::LD_ACCESS_FAULT, {{riscv::XLEN-riscv::PLEN{1'b0}}, ptw_bad_paddr}, 1'b1};
                end
            end
        end

        else if (lsu_req_q && !misaligned_ex_q.valid && !pmp_data_allow) begin
            if (lsu_is_store_q) begin
                lsu_exception_o = {riscv::ST_ACCESS_FAULT, {{riscv::XLEN-riscv::PLEN{1'b0}}, lsu_paddr_o}, 1'b1};
            end else begin
                lsu_exception_o = {riscv::LD_ACCESS_FAULT, {{riscv::XLEN-riscv::PLEN{1'b0}}, lsu_paddr_o}, 1'b1};
            end
        end
    end


    pmp #(
        .PLEN       ( riscv::PLEN            ),
        .PMP_LEN    ( riscv::PLEN - 2        ),
        .NR_ENTRIES ( ArianeCfg.NrPMPEntries )
    ) i_pmp_data (
        .addr_i        ( lsu_paddr_o         ),
        .priv_lvl_i    ( ld_st_priv_lvl_i    ),
        .access_type_i ( pmp_access_type     ),

        .conf_addr_i   ( pmpaddr_i           ),
        .conf_i        ( pmpcfg_i            ),
        .allow_o       ( pmp_data_allow      )
    );




    always_ff @(posedge clk_i or negedge rst_ni) begin
        if (~rst_ni) begin
            lsu_vaddr_q      <= '0;
            lsu_req_q        <= '0;
            misaligned_ex_q  <= '0;
            dtlb_pte_q       <= '0;
            dtlb_hit_q       <= '0;
            lsu_is_store_q   <= '0;
            dtlb_is_2M_q     <= '0;
            dtlb_is_1G_q     <= '0;
        end else begin
            lsu_vaddr_q      <=  lsu_vaddr_n;
            lsu_req_q        <=  lsu_req_n;
            misaligned_ex_q  <=  misaligned_ex_n;
            dtlb_pte_q       <=  dtlb_pte_n;
            dtlb_hit_q       <=  dtlb_hit_n;
            lsu_is_store_q   <=  lsu_is_store_n;
            dtlb_is_2M_q     <=  dtlb_is_2M_n;
            dtlb_is_1G_q     <=  dtlb_is_1G_n;
        end
    end
endmodule