data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_mem.sv
1: b"%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_mem.sv:29: syntax error, unexpected IDENTIFIER, expecting PACKAGE-IDENTIFIER\nmodule wt_dcache_mem import ariane_pkg::*; import wt_cache_pkg::*; #(\n                            ^~~~~~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_mem.sv:31: syntax error, unexpected parameter, expecting IDENTIFIER\n  parameter int unsigned NumPorts           = 3\n  ^~~~~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_mem.sv:32: syntax error, unexpected ')', expecting ';'\n) (\n^\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_mem.sv:34: 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/cache_subsystem/wt_dcache_mem.sv:37: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  logic  [NumPorts-1:0][DCACHE_TAG_WIDTH-1:0]        rd_tag_i,            \n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_mem.sv:38: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  logic  [NumPorts-1:0][DCACHE_CL_IDX_WIDTH-1:0]     rd_idx_i,\n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_mem.sv:39: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  logic  [NumPorts-1:0][DCACHE_OFFSET_WIDTH-1:0]     rd_off_i,\n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_mem.sv:40: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  logic  [NumPorts-1:0]                              rd_req_i,            \n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_mem.sv:41: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  logic  [NumPorts-1:0]                              rd_tag_only_i,       \n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_mem.sv:42: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  logic  [NumPorts-1:0]                              rd_prio_i,           \n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_mem.sv:43: syntax error, unexpected output, expecting IDENTIFIER or '=' or do or final\n  output logic  [NumPorts-1:0]                              rd_ack_o,\n  ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_mem.sv:44: syntax error, unexpected output, expecting IDENTIFIER or '=' or do or final\n  output logic                [DCACHE_SET_ASSOC-1:0]        rd_vld_bits_o,\n  ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_mem.sv:45: syntax error, unexpected output, expecting IDENTIFIER or '=' or do or final\n  output logic                [DCACHE_SET_ASSOC-1:0]        rd_hit_oh_o,\n  ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_mem.sv:46: syntax error, unexpected output, expecting IDENTIFIER or '=' or do or final\n  output logic                [63:0]                        rd_data_o,\n  ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_mem.sv:49: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  logic                                              wr_cl_vld_i,\n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_mem.sv:50: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  logic                                              wr_cl_nc_i,          \n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_mem.sv:51: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  logic                [DCACHE_SET_ASSOC-1:0]        wr_cl_we_i,          \n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_mem.sv:52: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  logic                [DCACHE_TAG_WIDTH-1:0]        wr_cl_tag_i,\n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_mem.sv:53: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  logic                [DCACHE_CL_IDX_WIDTH-1:0]     wr_cl_idx_i,\n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_mem.sv:54: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  logic                [DCACHE_OFFSET_WIDTH-1:0]     wr_cl_off_i,\n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_mem.sv:55: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  logic                [DCACHE_LINE_WIDTH-1:0]       wr_cl_data_i,\n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_mem.sv:56: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  logic                [DCACHE_LINE_WIDTH/8-1:0]     wr_cl_data_be_i,\n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_mem.sv:57: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  logic                [DCACHE_SET_ASSOC-1:0]        wr_vld_bits_i,\n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_mem.sv:60: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  logic                [DCACHE_SET_ASSOC-1:0]        wr_req_i,            \n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_mem.sv:61: syntax error, unexpected output, expecting IDENTIFIER or '=' or do or final\n  output logic                                              wr_ack_o,\n  ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_mem.sv:62: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  logic                [DCACHE_CL_IDX_WIDTH-1:0]     wr_idx_i,\n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_mem.sv:63: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  logic                [DCACHE_OFFSET_WIDTH-1:0]     wr_off_i,\n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_mem.sv:64: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  logic                [63:0]                        wr_data_i,\n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_mem.sv:65: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  logic                [7:0]                         wr_data_be_i,\n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_mem.sv:68: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input wbuffer_t             [DCACHE_WBUF_DEPTH-1:0]       wbuffer_data_i\n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_mem.sv:112: syntax error, unexpected for\n  for (genvar k=0;k<DCACHE_NUM_BANKS;k++) begin : gen_bank\n  ^~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_mem.sv:137: syntax error, unexpected IDENTIFIER\n  rr_arb_tree #(\n  ^~~~~~~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_mem.sv:163: syntax error, unexpected IDENTIFIER\n    for(int k=0; k<NumPorts; k++) begin\n                 ^\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_mem.sv:197: syntax error, unexpected assign\n  assign cmp_en_d = (|vld_req) & ~vld_we;\n  ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_mem.sv:253: syntax error, unexpected for\n  for (genvar k = 0; k < DCACHE_NUM_BANKS; k++) begin : gen_data_banks\n  ^~~\n%Error: Exiting due to 35 error(s)\n"
module wt_dcache_mem import ariane_pkg::*; import wt_cache_pkg::*; #(
  parameter bit          Axi64BitCompliant  = 1'b0,
  parameter int unsigned NumPorts           = 3
) (
  input  logic                                              clk_i,
  input  logic                                              rst_ni,


  input  logic  [NumPorts-1:0][DCACHE_TAG_WIDTH-1:0]        rd_tag_i,
  input  logic  [NumPorts-1:0][DCACHE_CL_IDX_WIDTH-1:0]     rd_idx_i,
  input  logic  [NumPorts-1:0][DCACHE_OFFSET_WIDTH-1:0]     rd_off_i,
  input  logic  [NumPorts-1:0]                              rd_req_i,
  input  logic  [NumPorts-1:0]                              rd_tag_only_i,
  input  logic  [NumPorts-1:0]                              rd_prio_i,
  output logic  [NumPorts-1:0]                              rd_ack_o,
  output logic                [DCACHE_SET_ASSOC-1:0]        rd_vld_bits_o,
  output logic                [DCACHE_SET_ASSOC-1:0]        rd_hit_oh_o,
  output logic                [63:0]                        rd_data_o,


  input  logic                                              wr_cl_vld_i,
  input  logic                                              wr_cl_nc_i,
  input  logic                [DCACHE_SET_ASSOC-1:0]        wr_cl_we_i,
  input  logic                [DCACHE_TAG_WIDTH-1:0]        wr_cl_tag_i,
  input  logic                [DCACHE_CL_IDX_WIDTH-1:0]     wr_cl_idx_i,
  input  logic                [DCACHE_OFFSET_WIDTH-1:0]     wr_cl_off_i,
  input  logic                [DCACHE_LINE_WIDTH-1:0]       wr_cl_data_i,
  input  logic                [DCACHE_LINE_WIDTH/8-1:0]     wr_cl_data_be_i,
  input  logic                [DCACHE_SET_ASSOC-1:0]        wr_vld_bits_i,


  input  logic                [DCACHE_SET_ASSOC-1:0]        wr_req_i,
  output logic                                              wr_ack_o,
  input  logic                [DCACHE_CL_IDX_WIDTH-1:0]     wr_idx_i,
  input  logic                [DCACHE_OFFSET_WIDTH-1:0]     wr_off_i,
  input  logic                [63:0]                        wr_data_i,
  input  logic                [7:0]                         wr_data_be_i,


  input wbuffer_t             [DCACHE_WBUF_DEPTH-1:0]       wbuffer_data_i
);

  logic [DCACHE_NUM_BANKS-1:0]                                  bank_req;
  logic [DCACHE_NUM_BANKS-1:0]                                  bank_we;
  logic [DCACHE_NUM_BANKS-1:0][DCACHE_SET_ASSOC-1:0][7:0]       bank_be;
  logic [DCACHE_NUM_BANKS-1:0][DCACHE_CL_IDX_WIDTH-1:0]         bank_idx;
  logic [DCACHE_CL_IDX_WIDTH-1:0]                               bank_idx_d, bank_idx_q;
  logic [DCACHE_OFFSET_WIDTH-1:0]                               bank_off_d, bank_off_q;

  logic [DCACHE_NUM_BANKS-1:0][DCACHE_SET_ASSOC-1:0][63:0]      bank_wdata;
  logic [DCACHE_NUM_BANKS-1:0][DCACHE_SET_ASSOC-1:0][63:0]      bank_rdata;
  logic [DCACHE_SET_ASSOC-1:0][63:0]                            rdata_cl;

  logic [DCACHE_TAG_WIDTH-1:0]                                  rd_tag;
  logic [DCACHE_SET_ASSOC-1:0]                                  vld_req;
  logic                                                         vld_we;
  logic [DCACHE_SET_ASSOC-1:0]                                  vld_wdata;
  logic [DCACHE_SET_ASSOC-1:0][DCACHE_TAG_WIDTH-1:0]            tag_rdata;
  logic                       [DCACHE_CL_IDX_WIDTH-1:0]         vld_addr;

  logic [$clog2(NumPorts)-1:0]                                  vld_sel_d, vld_sel_q;

  logic [DCACHE_WBUF_DEPTH-1:0]                                 wbuffer_hit_oh;
  logic [7:0]                                                   wbuffer_be;
  logic [63:0]                                                  wbuffer_rdata, rdata;
  logic [63:0]                                                  wbuffer_cmp_addr;

  logic                                                         cmp_en_d, cmp_en_q;
  logic                                                         rd_acked;
  logic [NumPorts-1:0]                                          bank_collision, rd_req_masked, rd_req_prio;













  for (genvar k=0;k<DCACHE_NUM_BANKS;k++) begin : gen_bank
    for (genvar j=0;j<DCACHE_SET_ASSOC;j++) begin : gen_bank_way
      assign bank_be[k][j]   = (wr_cl_we_i[j] & wr_cl_vld_i)  ? wr_cl_data_be_i[k*8 +: 8] :
                               (wr_req_i[j]   & wr_ack_o)     ? wr_data_be_i              :
                                                                '0;

      assign bank_wdata[k][j] = (wr_cl_we_i[j] & wr_cl_vld_i) ?  wr_cl_data_i[k*64 +: 64] :
                                                                 wr_data_i;
    end
  end

  assign vld_wdata  = wr_vld_bits_i;
  assign vld_addr   = (wr_cl_vld_i) ? wr_cl_idx_i   : rd_idx_i[vld_sel_d];
  assign rd_tag     = rd_tag_i[vld_sel_q];
  assign bank_off_d = (wr_cl_vld_i) ? wr_cl_off_i   : rd_off_i[vld_sel_d];
  assign bank_idx_d = (wr_cl_vld_i) ? wr_cl_idx_i   : rd_idx_i[vld_sel_d];
  assign vld_req    = (wr_cl_vld_i) ? wr_cl_we_i    : (rd_acked) ? '1 : '0;




  assign rd_req_prio   = rd_req_i & rd_prio_i;
  assign rd_req_masked = (|rd_req_prio) ? rd_req_prio : rd_req_i;

  logic rd_req;
  rr_arb_tree #(
    .NumIn     (NumPorts),
    .DataWidth (1)
  ) i_rr_arb_tree (
    .clk_i  (clk_i   ),
    .rst_ni (rst_ni  ),
    .flush_i('0      ),
    .rr_i   ('0      ),
    .req_i  (rd_req_masked ),
    .gnt_o  (rd_ack_o      ),
    .data_i ('0            ),
    .gnt_i  (~wr_cl_vld_i  ),
    .req_o  (rd_req        ),
    .data_o (              ),
    .idx_o  (vld_sel_d     )
  );

  assign rd_acked = rd_req & ~wr_cl_vld_i;

  always_comb begin : p_bank_req
    vld_we   = wr_cl_vld_i;
    bank_req = '0;
    wr_ack_o = '0;
    bank_we  = '0;
    bank_idx = '{default:wr_idx_i};

    for(int k=0; k<NumPorts; k++) begin
      bank_collision[k] = rd_off_i[k][DCACHE_OFFSET_WIDTH-1:3] == wr_off_i[DCACHE_OFFSET_WIDTH-1:3];
    end

    if(wr_cl_vld_i & |wr_cl_we_i) begin
      bank_req = '1;
      bank_we  = '1;
      bank_idx = '{default:wr_cl_idx_i};
    end else begin
      if(rd_acked) begin
        if(!rd_tag_only_i[vld_sel_d]) begin
          bank_req                                               = dcache_cl_bin2oh(rd_off_i[vld_sel_d][DCACHE_OFFSET_WIDTH-1:3]);
          bank_idx[rd_off_i[vld_sel_d][DCACHE_OFFSET_WIDTH-1:3]] = rd_idx_i[vld_sel_d];
        end
      end

      if(|wr_req_i) begin
        if(rd_tag_only_i[vld_sel_d] || !(rd_ack_o[vld_sel_d] && bank_collision[vld_sel_d])) begin
          wr_ack_o = 1'b1;
          bank_req |= dcache_cl_bin2oh(wr_off_i[DCACHE_OFFSET_WIDTH-1:3]);
          bank_we   = dcache_cl_bin2oh(wr_off_i[DCACHE_OFFSET_WIDTH-1:3]);
        end
      end
    end
  end





  logic [DCACHE_OFFSET_WIDTH-1:0]       wr_cl_off;
  logic [$clog2(DCACHE_WBUF_DEPTH)-1:0] wbuffer_hit_idx;
  logic [$clog2(DCACHE_SET_ASSOC)-1:0]  rd_hit_idx;

  assign cmp_en_d = (|vld_req) & ~vld_we;


  assign wbuffer_cmp_addr = (wr_cl_vld_i) ? {wr_cl_tag_i, wr_cl_idx_i, wr_cl_off_i} :
                                            {rd_tag, bank_idx_q, bank_off_q};

  for (genvar i=0;i<DCACHE_SET_ASSOC;i++) begin : gen_tag_cmpsel

    assign rd_hit_oh_o[i] = (rd_tag == tag_rdata[i]) & rd_vld_bits_o[i]  & cmp_en_q;

    assign rdata_cl[i] = bank_rdata[bank_off_q[DCACHE_OFFSET_WIDTH-1:3]][i];
  end

  for(genvar k=0; k<DCACHE_WBUF_DEPTH; k++) begin : gen_wbuffer_hit
    assign wbuffer_hit_oh[k] = (|wbuffer_data_i[k].valid) & (wbuffer_data_i[k].wtag == (wbuffer_cmp_addr >> 3));
  end

  lzc #(
    .WIDTH ( DCACHE_WBUF_DEPTH )
  ) i_lzc_wbuffer_hit (
    .in_i    ( wbuffer_hit_oh   ),
    .cnt_o   ( wbuffer_hit_idx  ),
    .empty_o (                  )
  );

  lzc #(
    .WIDTH ( DCACHE_SET_ASSOC )
  ) i_lzc_rd_hit (
    .in_i    ( rd_hit_oh_o  ),
    .cnt_o   ( rd_hit_idx   ),
    .empty_o (              )
  );

  assign wbuffer_rdata = wbuffer_data_i[wbuffer_hit_idx].data;
  assign wbuffer_be    = (|wbuffer_hit_oh) ? wbuffer_data_i[wbuffer_hit_idx].valid : '0;

  if (Axi64BitCompliant) begin : gen_axi_off
      assign wr_cl_off     = (wr_cl_nc_i) ? '0 : wr_cl_off_i[DCACHE_OFFSET_WIDTH-1:3];
  end else begin  : gen_piton_off
      assign wr_cl_off     = wr_cl_off_i[DCACHE_OFFSET_WIDTH-1:3];
  end

  assign rdata         = (wr_cl_vld_i)  ? wr_cl_data_i[wr_cl_off*64 +: 64] :
                                          rdata_cl[rd_hit_idx];


  for(genvar k=0; k<8; k++) begin : gen_rd_data
    assign rd_data_o[8*k +: 8] = (wbuffer_be[k]) ? wbuffer_rdata[8*k +: 8] : rdata[8*k +: 8];
  end





  logic [DCACHE_TAG_WIDTH:0] vld_tag_rdata [DCACHE_SET_ASSOC-1:0];

  for (genvar k = 0; k < DCACHE_NUM_BANKS; k++) begin : gen_data_banks

    sram #(
      .DATA_WIDTH ( ariane_pkg::DCACHE_SET_ASSOC * 64 ),
      .NUM_WORDS  ( wt_cache_pkg::DCACHE_NUM_WORDS    )
    ) i_data_sram (
      .clk_i      ( clk_i               ),
      .rst_ni     ( rst_ni              ),
      .req_i      ( bank_req   [k]      ),
      .we_i       ( bank_we    [k]      ),
      .addr_i     ( bank_idx   [k]      ),
      .wdata_i    ( bank_wdata [k]      ),
      .be_i       ( bank_be    [k]      ),
      .rdata_o    ( bank_rdata [k]      )
    );
  end

  for (genvar i = 0; i < DCACHE_SET_ASSOC; i++) begin : gen_tag_srams

    assign tag_rdata[i]     = vld_tag_rdata[i][DCACHE_TAG_WIDTH-1:0];
    assign rd_vld_bits_o[i] = vld_tag_rdata[i][DCACHE_TAG_WIDTH];


    sram #(

      .DATA_WIDTH ( ariane_pkg::DCACHE_TAG_WIDTH + 1 ),
      .NUM_WORDS  ( wt_cache_pkg::DCACHE_NUM_WORDS   )
    ) i_tag_sram (
      .clk_i     ( clk_i               ),
      .rst_ni    ( rst_ni              ),
      .req_i     ( vld_req[i]          ),
      .we_i      ( vld_we              ),
      .addr_i    ( vld_addr            ),
      .wdata_i   ( {vld_wdata[i], wr_cl_tag_i} ),
      .be_i      ( '1                  ),
      .rdata_o   ( vld_tag_rdata[i]    )
    );
  end

  always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
    if(!rst_ni) begin
      bank_idx_q <= '0;
      bank_off_q <= '0;
      vld_sel_q  <= '0;
      cmp_en_q   <= '0;
    end else begin
      bank_idx_q <= bank_idx_d;
      bank_off_q <= bank_off_d;
      vld_sel_q  <= vld_sel_d ;
      cmp_en_q   <= cmp_en_d;
    end
  end






`ifndef VERILATOR

  hit_hot1: assert property (
    @(posedge clk_i) disable iff (!rst_ni) &vld_req |-> !vld_we |=> $onehot0(rd_hit_oh_o))
      else $fatal(1,"[l1 dcache] rd_hit_oh_o signal must be hot1");

  word_write_hot1: assert property (
    @(posedge clk_i) disable iff (!rst_ni) wr_ack_o |-> $onehot0(wr_req_i))
      else $fatal(1,"[l1 dcache] wr_req_i signal must be hot1");

  wbuffer_hit_hot1: assert property (
    @(posedge clk_i) disable iff (!rst_ni) &vld_req |-> !vld_we |=> $onehot0(wbuffer_hit_oh))
      else $fatal(1,"[l1 dcache] wbuffer_hit_oh signal must be hot1");


  logic                                    vld_mirror[wt_cache_pkg::DCACHE_NUM_WORDS-1:0][ariane_pkg::DCACHE_SET_ASSOC-1:0];
  logic [ariane_pkg::DCACHE_TAG_WIDTH-1:0] tag_mirror[wt_cache_pkg::DCACHE_NUM_WORDS-1:0][ariane_pkg::DCACHE_SET_ASSOC-1:0];
  logic [ariane_pkg::DCACHE_SET_ASSOC-1:0] tag_write_duplicate_test;

  always_ff @(posedge clk_i or negedge rst_ni) begin : p_mirror
    if(!rst_ni) begin
      vld_mirror <= '{default:'0};
      tag_mirror <= '{default:'0};
    end else begin
      for (int i = 0; i < DCACHE_SET_ASSOC; i++) begin
        if(vld_req[i] & vld_we) begin
          vld_mirror[vld_addr][i] <= vld_wdata[i];
          tag_mirror[vld_addr][i] <= wr_cl_tag_i;
        end
      end
    end
  end

  for (genvar i = 0; i < DCACHE_SET_ASSOC; i++) begin : gen_tag_dubl_test
      assign tag_write_duplicate_test[i] = (tag_mirror[vld_addr][i] == wr_cl_tag_i) & vld_mirror[vld_addr][i] & (|vld_wdata);
  end

  tag_write_duplicate: assert property (
    @(posedge clk_i) disable iff (!rst_ni) |vld_req |-> vld_we |-> !(|tag_write_duplicate_test))
      else $fatal(1,"[l1 dcache] cannot allocate a CL that is already present in the cache");

`endif


endmodule
module wt_dcache_mem import ariane_pkg::*;
 import wt_cache_pkg::*; #(
  parameter bit          Axi64BitCompliant  = 1'b0,
  parameter int unsigned NumPorts           = 3
) (
  input  logic                                              clk_i,
  input  logic                                              rst_ni,


  input  logic  [NumPorts-1:0][DCACHE_TAG_WIDTH-1:0]        rd_tag_i,
  input  logic  [NumPorts-1:0][DCACHE_CL_IDX_WIDTH-1:0]     rd_idx_i,
  input  logic  [NumPorts-1:0][DCACHE_OFFSET_WIDTH-1:0]     rd_off_i,
  input  logic  [NumPorts-1:0]                              rd_req_i,
  input  logic  [NumPorts-1:0]                              rd_tag_only_i,
  input  logic  [NumPorts-1:0]                              rd_prio_i,
  output logic  [NumPorts-1:0]                              rd_ack_o,
  output logic                [DCACHE_SET_ASSOC-1:0]        rd_vld_bits_o,
  output logic                [DCACHE_SET_ASSOC-1:0]        rd_hit_oh_o,
  output logic                [63:0]                        rd_data_o,


  input  logic                                              wr_cl_vld_i,
  input  logic                                              wr_cl_nc_i,
  input  logic                [DCACHE_SET_ASSOC-1:0]        wr_cl_we_i,
  input  logic                [DCACHE_TAG_WIDTH-1:0]        wr_cl_tag_i,
  input  logic                [DCACHE_CL_IDX_WIDTH-1:0]     wr_cl_idx_i,
  input  logic                [DCACHE_OFFSET_WIDTH-1:0]     wr_cl_off_i,
  input  logic                [DCACHE_LINE_WIDTH-1:0]       wr_cl_data_i,
  input  logic                [DCACHE_LINE_WIDTH/8-1:0]     wr_cl_data_be_i,
  input  logic                [DCACHE_SET_ASSOC-1:0]        wr_vld_bits_i,


  input  logic                [DCACHE_SET_ASSOC-1:0]        wr_req_i,
  output logic                                              wr_ack_o,
  input  logic                [DCACHE_CL_IDX_WIDTH-1:0]     wr_idx_i,
  input  logic                [DCACHE_OFFSET_WIDTH-1:0]     wr_off_i,
  input  logic                [63:0]                        wr_data_i,
  input  logic                [7:0]                         wr_data_be_i,


  input wbuffer_t             [DCACHE_WBUF_DEPTH-1:0]       wbuffer_data_i
);

  logic [DCACHE_NUM_BANKS-1:0]                                  bank_req;
  logic [DCACHE_NUM_BANKS-1:0]                                  bank_we;
  logic [DCACHE_NUM_BANKS-1:0][DCACHE_SET_ASSOC-1:0][7:0]       bank_be;
  logic [DCACHE_NUM_BANKS-1:0][DCACHE_CL_IDX_WIDTH-1:0]         bank_idx;
  logic [DCACHE_CL_IDX_WIDTH-1:0]                               bank_idx_d, bank_idx_q;
  logic [DCACHE_OFFSET_WIDTH-1:0]                               bank_off_d, bank_off_q;

  logic [DCACHE_NUM_BANKS-1:0][DCACHE_SET_ASSOC-1:0][63:0]      bank_wdata;
  logic [DCACHE_NUM_BANKS-1:0][DCACHE_SET_ASSOC-1:0][63:0]      bank_rdata;
  logic [DCACHE_SET_ASSOC-1:0][63:0]                            rdata_cl;

  logic [DCACHE_TAG_WIDTH-1:0]                                  rd_tag;
  logic [DCACHE_SET_ASSOC-1:0]                                  vld_req;
  logic                                                         vld_we;
  logic [DCACHE_SET_ASSOC-1:0]                                  vld_wdata;
  logic [DCACHE_SET_ASSOC-1:0][DCACHE_TAG_WIDTH-1:0]            tag_rdata;
  logic                       [DCACHE_CL_IDX_WIDTH-1:0]         vld_addr;

  logic [$clog2(NumPorts)-1:0]                                  vld_sel_d, vld_sel_q;

  logic [DCACHE_WBUF_DEPTH-1:0]                                 wbuffer_hit_oh;
  logic [7:0]                                                   wbuffer_be;
  logic [63:0]                                                  wbuffer_rdata, rdata;
  logic [63:0]                                                  wbuffer_cmp_addr;

  logic                                                         cmp_en_d, cmp_en_q;
  logic                                                         rd_acked;
  logic [NumPorts-1:0]                                          bank_collision, rd_req_masked, rd_req_prio;













  for (genvar k=0;k<DCACHE_NUM_BANKS;k++) begin : gen_bank
    for (genvar j=0;j<DCACHE_SET_ASSOC;j++) begin : gen_bank_way
      assign bank_be[k][j]   = (wr_cl_we_i[j] & wr_cl_vld_i)  ? wr_cl_data_be_i[k*8 +: 8] :
                               (wr_req_i[j]   & wr_ack_o)     ? wr_data_be_i              :
                                                                '0;

      assign bank_wdata[k][j] = (wr_cl_we_i[j] & wr_cl_vld_i) ?  wr_cl_data_i[k*64 +: 64] :
                                                                 wr_data_i;
    end
  end

  assign vld_wdata  = wr_vld_bits_i;
  assign vld_addr   = (wr_cl_vld_i) ? wr_cl_idx_i   : rd_idx_i[vld_sel_d];
  assign rd_tag     = rd_tag_i[vld_sel_q];
  assign bank_off_d = (wr_cl_vld_i) ? wr_cl_off_i   : rd_off_i[vld_sel_d];
  assign bank_idx_d = (wr_cl_vld_i) ? wr_cl_idx_i   : rd_idx_i[vld_sel_d];
  assign vld_req    = (wr_cl_vld_i) ? wr_cl_we_i    : (rd_acked) ? '1 : '0;




  assign rd_req_prio   = rd_req_i & rd_prio_i;
  assign rd_req_masked = (|rd_req_prio) ? rd_req_prio : rd_req_i;

  logic rd_req;
  rr_arb_tree #(
    .NumIn     (NumPorts),
    .DataWidth (1)
  ) i_rr_arb_tree (
    .clk_i  (clk_i   ),
    .rst_ni (rst_ni  ),
    .flush_i('0      ),
    .rr_i   ('0      ),
    .req_i  (rd_req_masked ),
    .gnt_o  (rd_ack_o      ),
    .data_i ('0            ),
    .gnt_i  (~wr_cl_vld_i  ),
    .req_o  (rd_req        ),
    .data_o (              ),
    .idx_o  (vld_sel_d     )
  );

  assign rd_acked = rd_req & ~wr_cl_vld_i;

  always_comb begin : p_bank_req
    vld_we   = wr_cl_vld_i;
    bank_req = '0;
    wr_ack_o = '0;
    bank_we  = '0;
    bank_idx = '{default:wr_idx_i};

    for(int k=0; k<NumPorts; k++) begin
      bank_collision[k] = rd_off_i[k][DCACHE_OFFSET_WIDTH-1:3] == wr_off_i[DCACHE_OFFSET_WIDTH-1:3];
    end

    if(wr_cl_vld_i & |wr_cl_we_i) begin
      bank_req = '1;
      bank_we  = '1;
      bank_idx = '{default:wr_cl_idx_i};
    end else begin
      if(rd_acked) begin
        if(!rd_tag_only_i[vld_sel_d]) begin
          bank_req                                               = dcache_cl_bin2oh(rd_off_i[vld_sel_d][DCACHE_OFFSET_WIDTH-1:3]);
          bank_idx[rd_off_i[vld_sel_d][DCACHE_OFFSET_WIDTH-1:3]] = rd_idx_i[vld_sel_d];
        end
      end

      if(|wr_req_i) begin
        if(rd_tag_only_i[vld_sel_d] || !(rd_ack_o[vld_sel_d] && bank_collision[vld_sel_d])) begin
          wr_ack_o = 1'b1;
          bank_req |= dcache_cl_bin2oh(wr_off_i[DCACHE_OFFSET_WIDTH-1:3]);
          bank_we   = dcache_cl_bin2oh(wr_off_i[DCACHE_OFFSET_WIDTH-1:3]);
        end
      end
    end
  end





  logic [DCACHE_OFFSET_WIDTH-1:0]       wr_cl_off;
  logic [$clog2(DCACHE_WBUF_DEPTH)-1:0] wbuffer_hit_idx;
  logic [$clog2(DCACHE_SET_ASSOC)-1:0]  rd_hit_idx;

  assign cmp_en_d = (|vld_req) & ~vld_we;


  assign wbuffer_cmp_addr = (wr_cl_vld_i) ? {wr_cl_tag_i, wr_cl_idx_i, wr_cl_off_i} :
                                            {rd_tag, bank_idx_q, bank_off_q};

  for (genvar i=0;i<DCACHE_SET_ASSOC;i++) begin : gen_tag_cmpsel

    assign rd_hit_oh_o[i] = (rd_tag == tag_rdata[i]) & rd_vld_bits_o[i]  & cmp_en_q;

    assign rdata_cl[i] = bank_rdata[bank_off_q[DCACHE_OFFSET_WIDTH-1:3]][i];
  end

  for(genvar k=0; k<DCACHE_WBUF_DEPTH; k++) begin : gen_wbuffer_hit
    assign wbuffer_hit_oh[k] = (|wbuffer_data_i[k].valid) & (wbuffer_data_i[k].wtag == (wbuffer_cmp_addr >> 3));
  end

  lzc #(
    .WIDTH ( DCACHE_WBUF_DEPTH )
  ) i_lzc_wbuffer_hit (
    .in_i    ( wbuffer_hit_oh   ),
    .cnt_o   ( wbuffer_hit_idx  ),
    .empty_o (                  )
  );

  lzc #(
    .WIDTH ( DCACHE_SET_ASSOC )
  ) i_lzc_rd_hit (
    .in_i    ( rd_hit_oh_o  ),
    .cnt_o   ( rd_hit_idx   ),
    .empty_o (              )
  );

  assign wbuffer_rdata = wbuffer_data_i[wbuffer_hit_idx].data;
  assign wbuffer_be    = (|wbuffer_hit_oh) ? wbuffer_data_i[wbuffer_hit_idx].valid : '0;

  if (Axi64BitCompliant) begin : gen_axi_off
      assign wr_cl_off     = (wr_cl_nc_i) ? '0 : wr_cl_off_i[DCACHE_OFFSET_WIDTH-1:3];
  end else begin  : gen_piton_off
      assign wr_cl_off     = wr_cl_off_i[DCACHE_OFFSET_WIDTH-1:3];
  end

  assign rdata         = (wr_cl_vld_i)  ? wr_cl_data_i[wr_cl_off*64 +: 64] :
                                          rdata_cl[rd_hit_idx];


  for(genvar k=0; k<8; k++) begin : gen_rd_data
    assign rd_data_o[8*k +: 8] = (wbuffer_be[k]) ? wbuffer_rdata[8*k +: 8] : rdata[8*k +: 8];
  end





  logic [DCACHE_TAG_WIDTH:0] vld_tag_rdata [DCACHE_SET_ASSOC-1:0];

  for (genvar k = 0; k < DCACHE_NUM_BANKS; k++) begin : gen_data_banks

    sram #(
      .DATA_WIDTH ( ariane_pkg::DCACHE_SET_ASSOC * 64 ),
      .NUM_WORDS  ( wt_cache_pkg::DCACHE_NUM_WORDS    )
    ) i_data_sram (
      .clk_i      ( clk_i               ),
      .rst_ni     ( rst_ni              ),
      .req_i      ( bank_req   [k]      ),
      .we_i       ( bank_we    [k]      ),
      .addr_i     ( bank_idx   [k]      ),
      .wdata_i    ( bank_wdata [k]      ),
      .be_i       ( bank_be    [k]      ),
      .rdata_o    ( bank_rdata [k]      )
    );
  end

  for (genvar i = 0; i < DCACHE_SET_ASSOC; i++) begin : gen_tag_srams

    assign tag_rdata[i]     = vld_tag_rdata[i][DCACHE_TAG_WIDTH-1:0];
    assign rd_vld_bits_o[i] = vld_tag_rdata[i][DCACHE_TAG_WIDTH];


    sram #(

      .DATA_WIDTH ( ariane_pkg::DCACHE_TAG_WIDTH + 1 ),
      .NUM_WORDS  ( wt_cache_pkg::DCACHE_NUM_WORDS   )
    ) i_tag_sram (
      .clk_i     ( clk_i               ),
      .rst_ni    ( rst_ni              ),
      .req_i     ( vld_req[i]          ),
      .we_i      ( vld_we              ),
      .addr_i    ( vld_addr            ),
      .wdata_i   ( {vld_wdata[i], wr_cl_tag_i} ),
      .be_i      ( '1                  ),
      .rdata_o   ( vld_tag_rdata[i]    )
    );
  end

  always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
    if(!rst_ni) begin
      bank_idx_q <= '0;
      bank_off_q <= '0;
      vld_sel_q  <= '0;
      cmp_en_q   <= '0;
    end else begin
      bank_idx_q <= bank_idx_d;
      bank_off_q <= bank_off_d;
      vld_sel_q  <= vld_sel_d ;
      cmp_en_q   <= cmp_en_d;
    end
  end






`ifndef VERILATOR

  hit_hot1: assert property (
    @(posedge clk_i) disable iff (!rst_ni) &vld_req |-> !vld_we |=> $onehot0(rd_hit_oh_o))
      else $fatal(1,"[l1 dcache] rd_hit_oh_o signal must be hot1");

  word_write_hot1: assert property (
    @(posedge clk_i) disable iff (!rst_ni) wr_ack_o |-> $onehot0(wr_req_i))
      else $fatal(1,"[l1 dcache] wr_req_i signal must be hot1");

  wbuffer_hit_hot1: assert property (
    @(posedge clk_i) disable iff (!rst_ni) &vld_req |-> !vld_we |=> $onehot0(wbuffer_hit_oh))
      else $fatal(1,"[l1 dcache] wbuffer_hit_oh signal must be hot1");


  logic                                    vld_mirror[wt_cache_pkg::DCACHE_NUM_WORDS-1:0][ariane_pkg::DCACHE_SET_ASSOC-1:0];
  logic [ariane_pkg::DCACHE_TAG_WIDTH-1:0] tag_mirror[wt_cache_pkg::DCACHE_NUM_WORDS-1:0][ariane_pkg::DCACHE_SET_ASSOC-1:0];
  logic [ariane_pkg::DCACHE_SET_ASSOC-1:0] tag_write_duplicate_test;

  always_ff @(posedge clk_i or negedge rst_ni) begin : p_mirror
    if(!rst_ni) begin
      vld_mirror <= '{default:'0};
      tag_mirror <= '{default:'0};
    end else begin
      for (int i = 0; i < DCACHE_SET_ASSOC; i++) begin
        if(vld_req[i] & vld_we) begin
          vld_mirror[vld_addr][i] <= vld_wdata[i];
          tag_mirror[vld_addr][i] <= wr_cl_tag_i;
        end
      end
    end
  end

  for (genvar i = 0; i < DCACHE_SET_ASSOC; i++) begin : gen_tag_dubl_test
      assign tag_write_duplicate_test[i] = (tag_mirror[vld_addr][i] == wr_cl_tag_i) & vld_mirror[vld_addr][i] & (|vld_wdata);
  end

  tag_write_duplicate: assert property (
    @(posedge clk_i) disable iff (!rst_ni) |vld_req |-> vld_we |-> !(|tag_write_duplicate_test))
      else $fatal(1,"[l1 dcache] cannot allocate a CL that is already present in the cache");

`endif


endmodule