data/full_repos/permissive/421030651/src/cpu/tlb.sv
1: b'%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:1: Cannot find include file: tlb_define.h\n`include "tlb_define.h" \n         ^~~~~~~~~~~~~~\n        ... Looked in:\n             data/full_repos/permissive/421030651/src/cpu,data/full_repos/permissive/421030651/tlb_define.h\n             data/full_repos/permissive/421030651/src/cpu,data/full_repos/permissive/421030651/tlb_define.h.v\n             data/full_repos/permissive/421030651/src/cpu,data/full_repos/permissive/421030651/tlb_define.h.sv\n             tlb_define.h\n             tlb_define.h.v\n             tlb_define.h.sv\n             obj_dir/tlb_define.h\n             obj_dir/tlb_define.h.v\n             obj_dir/tlb_define.h.sv\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:8: Define or directive not defined: \'`SATP_MODE_WIDTH\'\n    input        [`SATP_MODE_WIDTH-1:0] satp_mode,\n                  ^~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:11: Define or directive not defined: \'`TLB_VPN_WIDTH\'\n    input        [  `TLB_VPN_WIDTH-1:0] vpn,\n                    ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:15: Define or directive not defined: \'`TLB_PTE_WIDTH\'\n    input        [  `TLB_PTE_WIDTH-1:0] pte_in,\n                    ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:17: Define or directive not defined: \'`TLB_PTE_WIDTH\'\n    output logic [  `TLB_PTE_WIDTH-1:0] pte_out,\n                    ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:22: Define or directive not defined: \'`XLEN\'\n    input        [         `XLEN - 1:0] tlb_flush_vaddr,\n                           ^~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:23: Define or directive not defined: \'`XLEN\'\n    input        [         `XLEN - 1:0] tlb_flush_asid,\n                           ^~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:25: Define or directive not defined: \'`TLB_IDX_WIDTH\'\n    output       [`TLB_IDX_WIDTH - 1:0] idx\n                  ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:29: Define or directive not defined: \'`TLB_DEPTH\'\nlogic [          `TLB_DEPTH-1:0] valid   [`TLB_WAY_NUM];\n                 ^~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:29: Define or directive not defined: \'`TLB_WAY_NUM\'\nlogic [          `TLB_DEPTH-1:0] valid   [`TLB_WAY_NUM];\n                                          ^~~~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:30: Define or directive not defined: \'`TLB_WAY_NUM\'\nlogic [                     2:0] spg_bit [`TLB_WAY_NUM][`TLB_DEPTH];\n                                          ^~~~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:30: Define or directive not defined: \'`TLB_DEPTH\'\nlogic [                     2:0] spg_bit [`TLB_WAY_NUM][`TLB_DEPTH];\n                                                        ^~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:31: Define or directive not defined: \'`TLB_WAY_NUM\'\nlogic [$clog2(`TLB_WAY_NUM)-1:0] order   [`TLB_WAY_NUM][`TLB_DEPTH];\n              ^~~~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:31: syntax error, unexpected \')\', expecting TYPE-IDENTIFIER\nlogic [$clog2(`TLB_WAY_NUM)-1:0] order   [`TLB_WAY_NUM][`TLB_DEPTH];\n                          ^\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:31: Define or directive not defined: \'`TLB_WAY_NUM\'\nlogic [$clog2(`TLB_WAY_NUM)-1:0] order   [`TLB_WAY_NUM][`TLB_DEPTH];\n                                          ^~~~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:31: Define or directive not defined: \'`TLB_DEPTH\'\nlogic [$clog2(`TLB_WAY_NUM)-1:0] order   [`TLB_WAY_NUM][`TLB_DEPTH];\n                                                        ^~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:32: Define or directive not defined: \'`TLB_WAY_NUM\'\nlogic [$clog2(`TLB_WAY_NUM)-1:0] victim_order;\n              ^~~~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:32: syntax error, unexpected \')\', expecting TYPE-IDENTIFIER\nlogic [$clog2(`TLB_WAY_NUM)-1:0] victim_order;\n                          ^\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:33: Define or directive not defined: \'`TLB_WAY_NUM\'\nlogic [$clog2(`TLB_WAY_NUM)-1:0] hit_order;\n              ^~~~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:33: syntax error, unexpected \')\', expecting TYPE-IDENTIFIER\nlogic [$clog2(`TLB_WAY_NUM)-1:0] hit_order;\n                          ^\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:34: Define or directive not defined: \'`TLB_WAY_NUM\'\nlogic [        `TLB_WAY_NUM-1:0] hit;\n               ^~~~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:35: Define or directive not defined: \'`TLB_TAG_WIDTH\'\nlogic [      `TLB_TAG_WIDTH-1:0] tag_in;\n             ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:36: Define or directive not defined: \'`TLB_TAG_WIDTH\'\nlogic [      `TLB_TAG_WIDTH-1:0] tag_latch;\n             ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:39: Define or directive not defined: \'`TLB_WAY_NUM\'\nlogic [                     2:0] spg_latch   [`TLB_WAY_NUM];\n                                              ^~~~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:40: Define or directive not defined: \'`TLB_WAY_NUM\'\nlogic [        `TLB_WAY_NUM-1:0] victim;\n               ^~~~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:41: Define or directive not defined: \'`TLB_PTE_WIDTH\'\nlogic [      `TLB_PTE_WIDTH-1:0] pte_out_arr [`TLB_WAY_NUM];\n             ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:41: Define or directive not defined: \'`TLB_WAY_NUM\'\nlogic [      `TLB_PTE_WIDTH-1:0] pte_out_arr [`TLB_WAY_NUM];\n                                              ^~~~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:47: Define or directive not defined: \'`TLB_WAY_NUM\'\n    for (i = 0; i < `TLB_WAY_NUM; i = i + 1) begin\n                    ^~~~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:47: syntax error, unexpected \';\', expecting TYPE-IDENTIFIER\n    for (i = 0; i < `TLB_WAY_NUM; i = i + 1) begin\n                                ^\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:47: syntax error, unexpected \')\', expecting \';\'\n    for (i = 0; i < `TLB_WAY_NUM; i = i + 1) begin\n                                           ^\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:56: Define or directive not defined: \'`TLB_IDX_WIDTH\'\nassign idx     = ({`TLB_IDX_WIDTH{satp_mode == `SATP_MODE_SV32}} & vpn[10+:`TLB_IDX_WIDTH])|\n                   ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:56: Define or directive not defined: \'`SATP_MODE_SV32\'\nassign idx     = ({`TLB_IDX_WIDTH{satp_mode == `SATP_MODE_SV32}} & vpn[10+:`TLB_IDX_WIDTH])|\n                                               ^~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:56: Define or directive not defined: \'`TLB_IDX_WIDTH\'\nassign idx     = ({`TLB_IDX_WIDTH{satp_mode == `SATP_MODE_SV32}} & vpn[10+:`TLB_IDX_WIDTH])|\n                                                                           ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:57: Define or directive not defined: \'`TLB_IDX_WIDTH\'\n                 ({`TLB_IDX_WIDTH{satp_mode == `SATP_MODE_SV39}} & vpn[18+:`TLB_IDX_WIDTH])|\n                   ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:57: Define or directive not defined: \'`SATP_MODE_SV39\'\n                 ({`TLB_IDX_WIDTH{satp_mode == `SATP_MODE_SV39}} & vpn[18+:`TLB_IDX_WIDTH])|\n                                               ^~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:57: Define or directive not defined: \'`TLB_IDX_WIDTH\'\n                 ({`TLB_IDX_WIDTH{satp_mode == `SATP_MODE_SV39}} & vpn[18+:`TLB_IDX_WIDTH])|\n                                                                           ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:58: Define or directive not defined: \'`TLB_IDX_WIDTH\'\n                 ({`TLB_IDX_WIDTH{satp_mode == `SATP_MODE_SV48}} & vpn[27+:`TLB_IDX_WIDTH]);\n                   ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:58: Define or directive not defined: \'`SATP_MODE_SV48\'\n                 ({`TLB_IDX_WIDTH{satp_mode == `SATP_MODE_SV48}} & vpn[27+:`TLB_IDX_WIDTH]);\n                                               ^~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:58: Define or directive not defined: \'`TLB_IDX_WIDTH\'\n                 ({`TLB_IDX_WIDTH{satp_mode == `SATP_MODE_SV48}} & vpn[27+:`TLB_IDX_WIDTH]);\n                                                                           ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:59: Define or directive not defined: \'`TLB_TAG_WIDTH\'\nassign tag_in  = ({`TLB_TAG_WIDTH{satp_mode == `SATP_MODE_SV32}} & {vpn[`TLB_VPN_WIDTH-1:`TLB_IDX_WIDTH+10], vpn[0+10] & {10{~spage_in[0]}}})|\n                   ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:59: Define or directive not defined: \'`SATP_MODE_SV32\'\nassign tag_in  = ({`TLB_TAG_WIDTH{satp_mode == `SATP_MODE_SV32}} & {vpn[`TLB_VPN_WIDTH-1:`TLB_IDX_WIDTH+10], vpn[0+10] & {10{~spage_in[0]}}})|\n                                               ^~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:59: syntax error, unexpected \'}\', expecting TYPE-IDENTIFIER\nassign tag_in  = ({`TLB_TAG_WIDTH{satp_mode == `SATP_MODE_SV32}} & {vpn[`TLB_VPN_WIDTH-1:`TLB_IDX_WIDTH+10], vpn[0+10] & {10{~spage_in[0]}}})|\n                                                              ^\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:59: Define or directive not defined: \'`TLB_VPN_WIDTH\'\nassign tag_in  = ({`TLB_TAG_WIDTH{satp_mode == `SATP_MODE_SV32}} & {vpn[`TLB_VPN_WIDTH-1:`TLB_IDX_WIDTH+10], vpn[0+10] & {10{~spage_in[0]}}})|\n                                                                        ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:59: Define or directive not defined: \'`TLB_IDX_WIDTH\'\nassign tag_in  = ({`TLB_TAG_WIDTH{satp_mode == `SATP_MODE_SV32}} & {vpn[`TLB_VPN_WIDTH-1:`TLB_IDX_WIDTH+10], vpn[0+10] & {10{~spage_in[0]}}})|\n                                                                                         ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:60: Define or directive not defined: \'`TLB_TAG_WIDTH\'\n                 ({`TLB_TAG_WIDTH{satp_mode == `SATP_MODE_SV39}} & {vpn[`TLB_VPN_WIDTH-1:`TLB_IDX_WIDTH+18],\n                   ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:60: Define or directive not defined: \'`SATP_MODE_SV39\'\n                 ({`TLB_TAG_WIDTH{satp_mode == `SATP_MODE_SV39}} & {vpn[`TLB_VPN_WIDTH-1:`TLB_IDX_WIDTH+18],\n                                               ^~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:60: Define or directive not defined: \'`TLB_VPN_WIDTH\'\n                 ({`TLB_TAG_WIDTH{satp_mode == `SATP_MODE_SV39}} & {vpn[`TLB_VPN_WIDTH-1:`TLB_IDX_WIDTH+18],\n                                                                        ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:60: Define or directive not defined: \'`TLB_IDX_WIDTH\'\n                 ({`TLB_TAG_WIDTH{satp_mode == `SATP_MODE_SV39}} & {vpn[`TLB_VPN_WIDTH-1:`TLB_IDX_WIDTH+18],\n                                                                                         ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:63: Define or directive not defined: \'`TLB_TAG_WIDTH\'\n                 ({`TLB_TAG_WIDTH{satp_mode == `SATP_MODE_SV48}} & {vpn[`TLB_VPN_WIDTH-1:`TLB_IDX_WIDTH+27],\n                   ^~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/421030651/src/cpu/tlb.sv:63: Define or directive not defined: \'`SATP_MODE_SV48\'\n                 ({`TLB_TAG_WIDTH{satp_mode == `SATP_MODE_SV48}} & {vpn[`TLB_VPN_WIDTH-1:`TLB_IDX_WIDTH+27],\n                                               ^~~~~~~~~~~~~~~\n%Error: Exiting due to too many errors encountered; --error-limit=50\n'
module tlb (
    input                               clk,
    input                               rstn,

`ifndef RV32
    input        [`SATP_MODE_WIDTH-1:0] satp_mode,
`endif
    input                               cs,
    input        [  `TLB_VPN_WIDTH-1:0] vpn,
    input                               we,
    output logic                        pte_hit,
    input        [                 2:0] spage_in,
    input        [  `TLB_PTE_WIDTH-1:0] pte_in,
    output logic [                 2:0] spage_out,
    output logic [  `TLB_PTE_WIDTH-1:0] pte_out,
    
    input                               tlb_flush_req,
    input                               tlb_flush_all_vaddr,
    input                               tlb_flush_all_asid,
    input        [         `XLEN - 1:0] tlb_flush_vaddr,
    input        [         `XLEN - 1:0] tlb_flush_asid,

    output       [`TLB_IDX_WIDTH - 1:0] idx
);


logic [          `TLB_DEPTH-1:0] valid   [`TLB_WAY_NUM];
logic [                     2:0] spg_bit [`TLB_WAY_NUM][`TLB_DEPTH];
logic [$clog2(`TLB_WAY_NUM)-1:0] order   [`TLB_WAY_NUM][`TLB_DEPTH];
logic [$clog2(`TLB_WAY_NUM)-1:0] victim_order;
logic [$clog2(`TLB_WAY_NUM)-1:0] hit_order;
logic [        `TLB_WAY_NUM-1:0] hit;
logic [      `TLB_TAG_WIDTH-1:0] tag_in;
logic [      `TLB_TAG_WIDTH-1:0] tag_latch;
logic                            cs_latch;
logic [                    26:0] vpn0_latch;
logic [                     2:0] spg_latch   [`TLB_WAY_NUM];
logic [        `TLB_WAY_NUM-1:0] victim;
logic [      `TLB_PTE_WIDTH-1:0] pte_out_arr [`TLB_WAY_NUM];

assign pte_hit   = |hit;
always_comb begin
    integer i;
    spage_out = 3'b0;
    for (i = 0; i < `TLB_WAY_NUM; i = i + 1) begin
        spage_out = spage_out | ({3{hit[i]}} & spg_latch[i]);
    end
end

`ifdef RV32
assign idx     = vpn[10+:`TLB_IDX_WIDTH];
assign tag_in  = {vpn[`TLB_VPN_WIDTH-1:`TLB_IDX_WIDTH+10], vpn[0+:10] & {10{~spage_in[0]}}};
`else
assign idx     = ({`TLB_IDX_WIDTH{satp_mode == `SATP_MODE_SV32}} & vpn[10+:`TLB_IDX_WIDTH])|
                 ({`TLB_IDX_WIDTH{satp_mode == `SATP_MODE_SV39}} & vpn[18+:`TLB_IDX_WIDTH])|
                 ({`TLB_IDX_WIDTH{satp_mode == `SATP_MODE_SV48}} & vpn[27+:`TLB_IDX_WIDTH]);
assign tag_in  = ({`TLB_TAG_WIDTH{satp_mode == `SATP_MODE_SV32}} & {vpn[`TLB_VPN_WIDTH-1:`TLB_IDX_WIDTH+10], vpn[0+10] & {10{~spage_in[0]}}})|
                 ({`TLB_TAG_WIDTH{satp_mode == `SATP_MODE_SV39}} & {vpn[`TLB_VPN_WIDTH-1:`TLB_IDX_WIDTH+18],
                                                                    vpn[ 9+:9] & {9{~spage_in[1]}},
                                                                    vpn[ 0+:9] & {9{~spage_in[0]}}})|
                 ({`TLB_TAG_WIDTH{satp_mode == `SATP_MODE_SV48}} & {vpn[`TLB_VPN_WIDTH-1:`TLB_IDX_WIDTH+27],
                                                                    vpn[18+:9] & {9{~spage_in[2]}},
                                                                    vpn[ 9+:9] & {9{~spage_in[1]}},
                                                                    vpn[ 0+:9] & {9{~spage_in[0]}}});
`endif

always_ff @(posedge clk or negedge rstn) begin
    if (~rstn) tag_latch <= {`TLB_TAG_WIDTH{1'b0}};
    else       tag_latch <=
`ifdef RV32
                            {vpn[`TLB_VPN_WIDTH-1:`TLB_IDX_WIDTH+10], vpn[9:0]};
`else
                            ({`TLB_TAG_WIDTH{satp_mode == `SATP_MODE_SV32}} & {vpn[`TLB_VPN_WIDTH-1:`TLB_IDX_WIDTH+10], vpn[ 9:0]})|
                            ({`TLB_TAG_WIDTH{satp_mode == `SATP_MODE_SV39}} & {vpn[`TLB_VPN_WIDTH-1:`TLB_IDX_WIDTH+18], vpn[17:0]})|
                            ({`TLB_TAG_WIDTH{satp_mode == `SATP_MODE_SV48}} & {vpn[`TLB_VPN_WIDTH-1:`TLB_IDX_WIDTH+27], vpn[26:0]});
`endif
end

always_ff @(posedge clk or negedge rstn) begin
    if (~rstn) cs_latch <= 1'b0;
    else       cs_latch <= cs && ~we;
end

always_ff @(posedge clk or negedge rstn) begin
    if (~rstn) vpn0_latch <= 27'b0;
    else       vpn0_latch <= vpn[26:0];
end

always_comb begin
    integer i;

    victim_order = {$clog2(`TLB_WAY_NUM){1'b0}};
    for (i = 0; i < `TLB_WAY_NUM; i = i + 1) begin
        victim_order = victim_order | {$clog2(`TLB_WAY_NUM){victim[i]}} & order[i][idx];
    end

    hit_order    = {$clog2(`TLB_WAY_NUM){1'b0}};
    for (i = 0; i < `TLB_WAY_NUM; i = i + 1) begin
        hit_order    = hit_order    | {$clog2(`TLB_WAY_NUM){hit[i]}}    & order[i][idx];
    end
end

always_comb begin
    integer i;

    pte_out = `TLB_PTE_WIDTH'b0;
    for (i = 0; i < `TLB_WAY_NUM; i = i + 1) begin
        pte_out = pte_out | ({`TLB_PTE_WIDTH{hit[i]}} & pte_out_arr[i])
`ifdef RV32
                          | {{`TLB_PTE_WIDTH-10-10{1'b0}}, vpn0_latch[0+:10] & {10{|(hit[i] & spg_latch[i][0])}}, 10'b0};
`else
                          | ({`TLB_PTE_WIDTH{~satp_mode[3]}} &
                             {{`TLB_PTE_WIDTH-10-10{1'b0}}, vpn0_latch[0+:10] & {10{|(hit[i] & spg_latch[i][0])}}, 10'b0})
                          | ({`TLB_PTE_WIDTH{ satp_mode[3]}} &
                             {{`TLB_PTE_WIDTH-10-27{1'b0}},
                               vpn0_latch[18+:9] & {9{|(hit[i] & spg_latch[i][2])}},
                               vpn0_latch[ 9+:9] & {9{|(hit[i] & spg_latch[i][1])}},
                               vpn0_latch[ 0+:9] & {9{|(hit[i] & spg_latch[i][0])}}, 10'b0});
`endif
    end
end

genvar g;
generate
    for (g = 0; g < `TLB_WAY_NUM; g = g + 1) begin: g_tlb_array
        logic                            valid_latch;
        logic [      `TLB_TAG_WIDTH-1:0] tag_out;

        parameter [$clog2(`TLB_WAY_NUM)-1:0] DEFAULT_ORDER = {$clog2(`TLB_WAY_NUM){1'b0}} - {{($clog2(`TLB_WAY_NUM)-1){1'b0}}, 1'b1};

        always_ff @(posedge clk or negedge rstn) begin
            integer i;
            if (~rstn) begin
                for (i = 0; i < `TLB_DEPTH; i = i + 1) begin
                    valid[g][i]   <= 1'b0;
                    spg_bit[g][i] <= 3'b0;
                    order[g][i]   <= g[$clog2(`TLB_WAY_NUM)-1:0];
                end
            end
            else if (tlb_flush_req) begin
                for (i = 0; i < `TLB_DEPTH; i = i + 1) begin
                    valid[g][i]   <= 1'b0;
                    order[g][i]   <= g[$clog2(`TLB_WAY_NUM)-1:0];
                end
            end
            else if (cs && we) begin
                if (victim[g]) begin
                    valid[g][idx]   <= 1'b1;
                    spg_bit[g][idx] <= spage_in;
                    order[g][idx]   <= DEFAULT_ORDER;
                end
                else if (order[g][idx] > victim_order) begin
                    order[g][idx] <= order[g][idx] - {{($clog2(`TLB_WAY_NUM)-1){1'b0}}, 1'b1};
                end
            end
            else if (cs_latch && pte_hit) begin
                if (hit[g]) begin
                    order[g][idx] <= DEFAULT_ORDER;
                end
                else if (order[g][idx] > hit_order) begin
                    order[g][idx] <= order[g][idx] - {{($clog2(`TLB_WAY_NUM)-1){1'b0}}, 1'b1};
                end
            end
        end

        always_ff @(posedge clk or negedge rstn) begin
            if (~rstn) valid_latch <= 1'b0;
            else       valid_latch <= valid[g][idx] && ~tlb_flush_req;
        end

        always_ff @(posedge clk or negedge rstn) begin
            if (~rstn) spg_latch[g] <= 3'b0;
            else       spg_latch[g] <= spg_bit[g][idx];
        end

        assign victim[g] = cs && we && ~|(order[g][idx]);
        assign hit[g]    = valid_latch &&
                           tag_out ==
`ifdef RV32
                           {tag_latch[`TLB_TAG_WIDTH-1:10], tag_latch[0+:10] & {10{~spg_latch[g][0]}}};
`else
                           (({`TLB_PTE_WIDTH{~satp_mode[3]}} &
                             {tag_latch[`TLB_TAG_WIDTH-1:10], tag_latch[0+:10] & {10{~spg_latch[g][0]}}})|
                            ({`TLB_PTE_WIDTH{ satp_mode[3]}} &
                             {tag_latch[`TLB_TAG_WIDTH-1:27],
                              tag_latch[18+:9] & {9{~spg_latch[g][2]}},
                              tag_latch[ 9+:9] & {9{~spg_latch[g][1]}},
                              tag_latch[ 0+:9] & {9{~spg_latch[g][0]}}}));
`endif



















        logic [`TLB_TAG_WIDTH-1:0] tag_array [`TLB_DEPTH];
        logic [`TLB_PTE_WIDTH-1:0] pte_array [`TLB_DEPTH];

        always_ff @(posedge clk or negedge rstn) begin
            integer i;
            if (~rstn)
                for (i = 0; i < `TLB_DEPTH; i = i + 1)
                    tag_array[i] <= {`TLB_TAG_WIDTH{1'b0}};
            else if (cs & we & victim[g])
                tag_array[idx] <= tag_in;
        end

        always_ff @(posedge clk or negedge rstn) begin
            if (~rstn) tag_out <= {`TLB_TAG_WIDTH{1'b0}};
            else       tag_out <= tag_array[idx];
        end

        always_ff @(posedge clk or negedge rstn) begin
            integer i;
            if (~rstn)
                for (i = 0; i < `TLB_DEPTH; i = i + 1)
                    pte_array[i] <= {`TLB_PTE_WIDTH{1'b0}};
            else if (cs & we & victim[g])
                pte_array[idx] <= pte_in;
        end

        always_ff @(posedge clk or negedge rstn) begin
            if (~rstn) pte_out_arr[g] <= {`TLB_PTE_WIDTH{1'b0}};
            else       pte_out_arr[g] <= pte_array[idx];
        end


    end
endgenerate

endmodule
module tlb (
    input                               clk,
    input                               rstn,

`ifndef RV32
    input        [`SATP_MODE_WIDTH-1:0] satp_mode,
`endif
    input                               cs,
    input        [  `TLB_VPN_WIDTH-1:0] vpn,
    input                               we,
    output logic                        pte_hit,
    input        [                 2:0] spage_in,
    input        [  `TLB_PTE_WIDTH-1:0] pte_in,
    output logic [                 2:0] spage_out,
    output logic [  `TLB_PTE_WIDTH-1:0] pte_out,
    
    input                               tlb_flush_req,
    input                               tlb_flush_all_vaddr,
    input                               tlb_flush_all_asid,
    input        [         `XLEN - 1:0] tlb_flush_vaddr,
    input        [         `XLEN - 1:0] tlb_flush_asid,

    output       [`TLB_IDX_WIDTH - 1:0] idx
);



logic [          `TLB_DEPTH-1:0] valid   [`TLB_WAY_NUM];
logic [                     2:0] spg_bit [`TLB_WAY_NUM][`TLB_DEPTH];
logic [$clog2(`TLB_WAY_NUM)-1:0] order   [`TLB_WAY_NUM][`TLB_DEPTH];
logic [$clog2(`TLB_WAY_NUM)-1:0] victim_order;
logic [$clog2(`TLB_WAY_NUM)-1:0] hit_order;
logic [        `TLB_WAY_NUM-1:0] hit;
logic [      `TLB_TAG_WIDTH-1:0] tag_in;
logic [      `TLB_TAG_WIDTH-1:0] tag_latch;
logic                            cs_latch;
logic [                    26:0] vpn0_latch;
logic [                     2:0] spg_latch   [`TLB_WAY_NUM];
logic [        `TLB_WAY_NUM-1:0] victim;
logic [      `TLB_PTE_WIDTH-1:0] pte_out_arr [`TLB_WAY_NUM];

assign pte_hit   = |hit;
always_comb begin
    integer i;
    spage_out = 3'b0;
    for (i = 0; i < `TLB_WAY_NUM; i = i + 1) begin
        spage_out = spage_out | ({3{hit[i]}} & spg_latch[i]);
    end
end

`ifdef RV32
assign idx     = vpn[10+:`TLB_IDX_WIDTH];
assign tag_in  = {vpn[`TLB_VPN_WIDTH-1:`TLB_IDX_WIDTH+10], vpn[0+:10] & {10{~spage_in[0]}}};
`else
assign idx     = ({`TLB_IDX_WIDTH{satp_mode == `SATP_MODE_SV32}} & vpn[10+:`TLB_IDX_WIDTH])|
                 ({`TLB_IDX_WIDTH{satp_mode == `SATP_MODE_SV39}} & vpn[18+:`TLB_IDX_WIDTH])|
                 ({`TLB_IDX_WIDTH{satp_mode == `SATP_MODE_SV48}} & vpn[27+:`TLB_IDX_WIDTH]);
assign tag_in  = ({`TLB_TAG_WIDTH{satp_mode == `SATP_MODE_SV32}} & {vpn[`TLB_VPN_WIDTH-1:`TLB_IDX_WIDTH+10], vpn[0+10] & {10{~spage_in[0]}}})|
                 ({`TLB_TAG_WIDTH{satp_mode == `SATP_MODE_SV39}} & {vpn[`TLB_VPN_WIDTH-1:`TLB_IDX_WIDTH+18],
                                                                    vpn[ 9+:9] & {9{~spage_in[1]}},
                                                                    vpn[ 0+:9] & {9{~spage_in[0]}}})|
                 ({`TLB_TAG_WIDTH{satp_mode == `SATP_MODE_SV48}} & {vpn[`TLB_VPN_WIDTH-1:`TLB_IDX_WIDTH+27],
                                                                    vpn[18+:9] & {9{~spage_in[2]}},
                                                                    vpn[ 9+:9] & {9{~spage_in[1]}},
                                                                    vpn[ 0+:9] & {9{~spage_in[0]}}});
`endif

always_ff @(posedge clk or negedge rstn) begin
    if (~rstn) tag_latch <= {`TLB_TAG_WIDTH{1'b0}};
    else       tag_latch <=
`ifdef RV32
                            {vpn[`TLB_VPN_WIDTH-1:`TLB_IDX_WIDTH+10], vpn[9:0]};
`else
                            ({`TLB_TAG_WIDTH{satp_mode == `SATP_MODE_SV32}} & {vpn[`TLB_VPN_WIDTH-1:`TLB_IDX_WIDTH+10], vpn[ 9:0]})|
                            ({`TLB_TAG_WIDTH{satp_mode == `SATP_MODE_SV39}} & {vpn[`TLB_VPN_WIDTH-1:`TLB_IDX_WIDTH+18], vpn[17:0]})|
                            ({`TLB_TAG_WIDTH{satp_mode == `SATP_MODE_SV48}} & {vpn[`TLB_VPN_WIDTH-1:`TLB_IDX_WIDTH+27], vpn[26:0]});
`endif
end

always_ff @(posedge clk or negedge rstn) begin
    if (~rstn) cs_latch <= 1'b0;
    else       cs_latch <= cs && ~we;
end

always_ff @(posedge clk or negedge rstn) begin
    if (~rstn) vpn0_latch <= 27'b0;
    else       vpn0_latch <= vpn[26:0];
end

always_comb begin
    integer i;

    victim_order = {$clog2(`TLB_WAY_NUM){1'b0}};
    for (i = 0; i < `TLB_WAY_NUM; i = i + 1) begin
        victim_order = victim_order | {$clog2(`TLB_WAY_NUM){victim[i]}} & order[i][idx];
    end

    hit_order    = {$clog2(`TLB_WAY_NUM){1'b0}};
    for (i = 0; i < `TLB_WAY_NUM; i = i + 1) begin
        hit_order    = hit_order    | {$clog2(`TLB_WAY_NUM){hit[i]}}    & order[i][idx];
    end
end

always_comb begin
    integer i;

    pte_out = `TLB_PTE_WIDTH'b0;
    for (i = 0; i < `TLB_WAY_NUM; i = i + 1) begin
        pte_out = pte_out | ({`TLB_PTE_WIDTH{hit[i]}} & pte_out_arr[i])
`ifdef RV32
                          | {{`TLB_PTE_WIDTH-10-10{1'b0}}, vpn0_latch[0+:10] & {10{|(hit[i] & spg_latch[i][0])}}, 10'b0};
`else
                          | ({`TLB_PTE_WIDTH{~satp_mode[3]}} &
                             {{`TLB_PTE_WIDTH-10-10{1'b0}}, vpn0_latch[0+:10] & {10{|(hit[i] & spg_latch[i][0])}}, 10'b0})
                          | ({`TLB_PTE_WIDTH{ satp_mode[3]}} &
                             {{`TLB_PTE_WIDTH-10-27{1'b0}},
                               vpn0_latch[18+:9] & {9{|(hit[i] & spg_latch[i][2])}},
                               vpn0_latch[ 9+:9] & {9{|(hit[i] & spg_latch[i][1])}},
                               vpn0_latch[ 0+:9] & {9{|(hit[i] & spg_latch[i][0])}}, 10'b0});
`endif
    end
end

genvar g;
generate
    for (g = 0; g < `TLB_WAY_NUM; g = g + 1) begin: g_tlb_array
        logic                            valid_latch;
        logic [      `TLB_TAG_WIDTH-1:0] tag_out;

        parameter [$clog2(`TLB_WAY_NUM)-1:0] DEFAULT_ORDER = {$clog2(`TLB_WAY_NUM){1'b0}} - {{($clog2(`TLB_WAY_NUM)-1){1'b0}}, 1'b1};

        always_ff @(posedge clk or negedge rstn) begin
            integer i;
            if (~rstn) begin
                for (i = 0; i < `TLB_DEPTH; i = i + 1) begin
                    valid[g][i]   <= 1'b0;
                    spg_bit[g][i] <= 3'b0;
                    order[g][i]   <= g[$clog2(`TLB_WAY_NUM)-1:0];
                end
            end
            else if (tlb_flush_req) begin
                for (i = 0; i < `TLB_DEPTH; i = i + 1) begin
                    valid[g][i]   <= 1'b0;
                    order[g][i]   <= g[$clog2(`TLB_WAY_NUM)-1:0];
                end
            end
            else if (cs && we) begin
                if (victim[g]) begin
                    valid[g][idx]   <= 1'b1;
                    spg_bit[g][idx] <= spage_in;
                    order[g][idx]   <= DEFAULT_ORDER;
                end
                else if (order[g][idx] > victim_order) begin
                    order[g][idx] <= order[g][idx] - {{($clog2(`TLB_WAY_NUM)-1){1'b0}}, 1'b1};
                end
            end
            else if (cs_latch && pte_hit) begin
                if (hit[g]) begin
                    order[g][idx] <= DEFAULT_ORDER;
                end
                else if (order[g][idx] > hit_order) begin
                    order[g][idx] <= order[g][idx] - {{($clog2(`TLB_WAY_NUM)-1){1'b0}}, 1'b1};
                end
            end
        end

        always_ff @(posedge clk or negedge rstn) begin
            if (~rstn) valid_latch <= 1'b0;
            else       valid_latch <= valid[g][idx] && ~tlb_flush_req;
        end

        always_ff @(posedge clk or negedge rstn) begin
            if (~rstn) spg_latch[g] <= 3'b0;
            else       spg_latch[g] <= spg_bit[g][idx];
        end

        assign victim[g] = cs && we && ~|(order[g][idx]);
        assign hit[g]    = valid_latch &&
                           tag_out ==
`ifdef RV32
                           {tag_latch[`TLB_TAG_WIDTH-1:10], tag_latch[0+:10] & {10{~spg_latch[g][0]}}};
`else
                           (({`TLB_PTE_WIDTH{~satp_mode[3]}} &
                             {tag_latch[`TLB_TAG_WIDTH-1:10], tag_latch[0+:10] & {10{~spg_latch[g][0]}}})|
                            ({`TLB_PTE_WIDTH{ satp_mode[3]}} &
                             {tag_latch[`TLB_TAG_WIDTH-1:27],
                              tag_latch[18+:9] & {9{~spg_latch[g][2]}},
                              tag_latch[ 9+:9] & {9{~spg_latch[g][1]}},
                              tag_latch[ 0+:9] & {9{~spg_latch[g][0]}}}));
`endif



















        logic [`TLB_TAG_WIDTH-1:0] tag_array [`TLB_DEPTH];
        logic [`TLB_PTE_WIDTH-1:0] pte_array [`TLB_DEPTH];

        always_ff @(posedge clk or negedge rstn) begin
            integer i;
            if (~rstn)
                for (i = 0; i < `TLB_DEPTH; i = i + 1)
                    tag_array[i] <= {`TLB_TAG_WIDTH{1'b0}};
            else if (cs & we & victim[g])
                tag_array[idx] <= tag_in;
        end

        always_ff @(posedge clk or negedge rstn) begin
            if (~rstn) tag_out <= {`TLB_TAG_WIDTH{1'b0}};
            else       tag_out <= tag_array[idx];
        end

        always_ff @(posedge clk or negedge rstn) begin
            integer i;
            if (~rstn)
                for (i = 0; i < `TLB_DEPTH; i = i + 1)
                    pte_array[i] <= {`TLB_PTE_WIDTH{1'b0}};
            else if (cs & we & victim[g])
                pte_array[idx] <= pte_in;
        end

        always_ff @(posedge clk or negedge rstn) begin
            if (~rstn) pte_out_arr[g] <= {`TLB_PTE_WIDTH{1'b0}};
            else       pte_out_arr[g] <= pte_array[idx];
        end


    end
endgenerate

endmodule