data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv
1: b"%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv:17: syntax error, unexpected IDENTIFIER, expecting PACKAGE-IDENTIFIER\nmodule wt_dcache_missunit 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_missunit.sv:19: syntax error, unexpected parameter, expecting IDENTIFIER\n  parameter logic [CACHE_ID_WIDTH-1:0]  AmoTxId            = 1,     \n  ^~~~~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv:20: 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_missunit.sv:21: 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_missunit.sv:23: 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_missunit.sv:25: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  logic                                       enable_i,     \n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.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/cache_subsystem/wt_dcache_missunit.sv:27: syntax error, unexpected output, expecting IDENTIFIER or '=' or do or final\n  output logic                                       flush_ack_o,  \n  ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv:28: syntax error, unexpected output, expecting IDENTIFIER or '=' or do or final\n  output logic                                       miss_o,       \n  ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv:30: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  logic                                       wbuffer_empty_i,\n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv:31: syntax error, unexpected output, expecting IDENTIFIER or '=' or do or final\n  output logic                                       cache_en_o,   \n  ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv:33: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  amo_req_t                                   amo_req_i,\n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv:37: syntax error, unexpected output, expecting IDENTIFIER or '=' or do or final\n  output logic [NumPorts-1:0]                        miss_ack_o,\n  ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv:38: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  logic [NumPorts-1:0]                        miss_nc_i,\n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv:39: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  logic [NumPorts-1:0]                        miss_we_i,\n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv:40: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  logic [NumPorts-1:0][63:0]                  miss_wdata_i,\n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv:41: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  logic [NumPorts-1:0][riscv::PLEN-1:0]       miss_paddr_i,\n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv:41: syntax error, unexpected ::, expecting ':'\n  input  logic [NumPorts-1:0][riscv::PLEN-1:0]       miss_paddr_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/cache_subsystem/wt_dcache_missunit.sv:43: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  logic [NumPorts-1:0][2:0]                   miss_size_i,\n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv:44: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  logic [NumPorts-1:0][CACHE_ID_WIDTH-1:0]    miss_id_i,           \n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv:46: syntax error, unexpected output, expecting IDENTIFIER or '=' or do or final\n  output logic [NumPorts-1:0]                        miss_replay_o,\n  ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv:48: syntax error, unexpected output, expecting IDENTIFIER or '=' or do or final\n  output logic [NumPorts-1:0]                        miss_rtrn_vld_o,\n  ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv:49: syntax error, unexpected output, expecting IDENTIFIER or '=' or do or final\n  output logic [CACHE_ID_WIDTH-1:0]                  miss_rtrn_id_o,      \n  ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv:51: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  logic [DCACHE_MAX_TX-1:0][riscv::PLEN-1:0]  tx_paddr_i,          \n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv:51: syntax error, unexpected ::, expecting ':'\n  input  logic [DCACHE_MAX_TX-1:0][riscv::PLEN-1:0]  tx_paddr_i,          \n                                        ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv:54: syntax error, unexpected output, expecting IDENTIFIER or '=' or do or final\n  output logic                                       wr_cl_vld_o,         \n  ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv:55: syntax error, unexpected output, expecting IDENTIFIER or '=' or do or final\n  output logic                                       wr_cl_nc_o,          \n  ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv:56: syntax error, unexpected output, expecting IDENTIFIER or '=' or do or final\n  output logic [DCACHE_SET_ASSOC-1:0]                wr_cl_we_o,          \n  ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv:57: syntax error, unexpected output, expecting IDENTIFIER or '=' or do or final\n  output logic [DCACHE_TAG_WIDTH-1:0]                wr_cl_tag_o,\n  ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv:58: syntax error, unexpected output, expecting IDENTIFIER or '=' or do or final\n  output logic [DCACHE_CL_IDX_WIDTH-1:0]             wr_cl_idx_o,\n  ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv:59: syntax error, unexpected output, expecting IDENTIFIER or '=' or do or final\n  output logic [DCACHE_OFFSET_WIDTH-1:0]             wr_cl_off_o,\n  ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv:60: syntax error, unexpected output, expecting IDENTIFIER or '=' or do or final\n  output logic [DCACHE_LINE_WIDTH-1:0]               wr_cl_data_o,\n  ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv:61: syntax error, unexpected output, expecting IDENTIFIER or '=' or do or final\n  output logic [DCACHE_LINE_WIDTH/8-1:0]             wr_cl_data_be_o,\n  ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv:62: syntax error, unexpected output, expecting IDENTIFIER or '=' or do or final\n  output logic [DCACHE_SET_ASSOC-1:0]                wr_vld_bits_o,\n  ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv:64: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  logic                                       mem_rtrn_vld_i,\n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv:65: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  dcache_rtrn_t                               mem_rtrn_i,\n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv:67: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  logic                                       mem_data_ack_i,\n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv:68: syntax error, unexpected output, expecting IDENTIFIER or '=' or do or final\n  output dcache_req_t                                mem_data_o\n  ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv:77: syntax error, unexpected ::, expecting ':'\n    logic [riscv::PLEN-1:0]              paddr   ;\n                ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv:84: syntax error, unexpected '}'\n  } mshr_t;\n  ^\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv:99: syntax error, unexpected ::, expecting ':'\n  logic [riscv::PLEN-1:0] tmp_paddr;\n              ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv:115: syntax error, unexpected assign\n  assign cache_en_o      = enable_q;\n  ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv:193: syntax error, unexpected IDENTIFIER\n    for(int k=0; k<DCACHE_MAX_TX; k++) begin\n                 ^\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv:237: syntax error, unexpected IDENTIFIER\n  exp_backoff #(\n  ^~~~~~~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/cache_subsystem/wt_dcache_missunit.sv:254: syntax error, unexpected ::\n  logic [$clog2(wt_cache_pkg::DCACHE_MAX_TX + 1)-1:0] stores_inflight_d, stores_inflight_q;\n                            ^~\n%Error: Exiting due to 45 error(s)\n"
module wt_dcache_missunit import ariane_pkg::*; import wt_cache_pkg::*; #(
  parameter bit                         Axi64BitCompliant  = 1'b0,
  parameter logic [CACHE_ID_WIDTH-1:0]  AmoTxId            = 1,
  parameter int unsigned                NumPorts           = 3
) (
  input  logic                                       clk_i,
  input  logic                                       rst_ni,

  input  logic                                       enable_i,
  input  logic                                       flush_i,
  output logic                                       flush_ack_o,
  output logic                                       miss_o,

  input  logic                                       wbuffer_empty_i,
  output logic                                       cache_en_o,

  input  amo_req_t                                   amo_req_i,
  output amo_resp_t                                  amo_resp_o,

  input  logic [NumPorts-1:0]                        miss_req_i,
  output logic [NumPorts-1:0]                        miss_ack_o,
  input  logic [NumPorts-1:0]                        miss_nc_i,
  input  logic [NumPorts-1:0]                        miss_we_i,
  input  logic [NumPorts-1:0][63:0]                  miss_wdata_i,
  input  logic [NumPorts-1:0][riscv::PLEN-1:0]       miss_paddr_i,
  input  logic [NumPorts-1:0][DCACHE_SET_ASSOC-1:0]  miss_vld_bits_i,
  input  logic [NumPorts-1:0][2:0]                   miss_size_i,
  input  logic [NumPorts-1:0][CACHE_ID_WIDTH-1:0]    miss_id_i,

  output logic [NumPorts-1:0]                        miss_replay_o,

  output logic [NumPorts-1:0]                        miss_rtrn_vld_o,
  output logic [CACHE_ID_WIDTH-1:0]                  miss_rtrn_id_o,

  input  logic [DCACHE_MAX_TX-1:0][riscv::PLEN-1:0]  tx_paddr_i,
  input  logic [DCACHE_MAX_TX-1:0]                   tx_vld_i,

  output logic                                       wr_cl_vld_o,
  output logic                                       wr_cl_nc_o,
  output logic [DCACHE_SET_ASSOC-1:0]                wr_cl_we_o,
  output logic [DCACHE_TAG_WIDTH-1:0]                wr_cl_tag_o,
  output logic [DCACHE_CL_IDX_WIDTH-1:0]             wr_cl_idx_o,
  output logic [DCACHE_OFFSET_WIDTH-1:0]             wr_cl_off_o,
  output logic [DCACHE_LINE_WIDTH-1:0]               wr_cl_data_o,
  output logic [DCACHE_LINE_WIDTH/8-1:0]             wr_cl_data_be_o,
  output logic [DCACHE_SET_ASSOC-1:0]                wr_vld_bits_o,

  input  logic                                       mem_rtrn_vld_i,
  input  dcache_rtrn_t                               mem_rtrn_i,
  output logic                                       mem_data_req_o,
  input  logic                                       mem_data_ack_i,
  output dcache_req_t                                mem_data_o
);


  typedef enum logic[2:0] {IDLE, DRAIN, AMO,  FLUSH, STORE_WAIT, LOAD_WAIT, AMO_WAIT} state_e;
  state_e state_d, state_q;


  typedef struct packed {
    logic [riscv::PLEN-1:0]              paddr   ;
    logic [2:0]                          size    ;
    logic [DCACHE_SET_ASSOC-1:0]         vld_bits;
    logic [CACHE_ID_WIDTH-1:0]          id      ;
    logic                                nc      ;
    logic [$clog2(DCACHE_SET_ASSOC)-1:0] repl_way;
    logic [$clog2(NumPorts)-1:0]        miss_port_idx;
  } mshr_t;

  mshr_t mshr_d, mshr_q;
  logic [$clog2(DCACHE_SET_ASSOC)-1:0] repl_way, inv_way, rnd_way;
  logic mshr_vld_d, mshr_vld_q, mshr_vld_q1;
  logic mshr_allocate;
  logic update_lfsr, all_ways_valid;

  logic enable_d, enable_q;
  logic flush_ack_d, flush_ack_q;
  logic flush_en, flush_done;
  logic mask_reads, lock_reqs;
  logic amo_sel, miss_is_write;
  logic amo_req_d, amo_req_q;
  logic [63:0] amo_data, amo_rtrn_mux;
  logic [riscv::PLEN-1:0] tmp_paddr;
  logic [$clog2(NumPorts)-1:0] miss_port_idx;
  logic [DCACHE_CL_IDX_WIDTH-1:0] cnt_d, cnt_q;
  logic [NumPorts-1:0] miss_req_masked_d, miss_req_masked_q;

  logic inv_vld, inv_vld_all, cl_write_en;
  logic load_ack, store_ack, amo_ack;

  logic [NumPorts-1:0] mshr_rdrd_collision_d, mshr_rdrd_collision_q;
  logic [NumPorts-1:0] mshr_rdrd_collision;
  logic tx_rdwr_collision, mshr_rdwr_collision;





  assign cache_en_o      = enable_q;
  assign cnt_d           = (flush_en) ? cnt_q + 1 : '0;
  assign flush_done      = (cnt_q == wt_cache_pkg::DCACHE_NUM_WORDS-1);

  assign miss_req_masked_d = (lock_reqs)  ? miss_req_masked_q      :
                             (mask_reads) ? miss_we_i & miss_req_i : miss_req_i;
  assign miss_is_write     = miss_we_i[miss_port_idx];


  lzc #(
    .WIDTH ( NumPorts )
  ) i_lzc_reqs (
    .in_i    ( miss_req_masked_d ),
    .cnt_o   ( miss_port_idx     ),
    .empty_o (                   )
  );

  always_comb begin : p_ack
    miss_ack_o = '0;
    if (!amo_sel) begin
      miss_ack_o[miss_port_idx] = mem_data_ack_i & mem_data_req_o;
    end
  end






  lzc #(
    .WIDTH ( ariane_pkg::DCACHE_SET_ASSOC )
  ) i_lzc_inv (
    .in_i    ( ~miss_vld_bits_i[miss_port_idx] ),
    .cnt_o   ( inv_way                         ),
    .empty_o ( all_ways_valid                  )
  );


  lfsr_8bit #(
    .WIDTH ( ariane_pkg::DCACHE_SET_ASSOC )
  ) i_lfsr_inv (
    .clk_i          ( clk_i       ),
    .rst_ni         ( rst_ni      ),
    .en_i           ( update_lfsr ),
    .refill_way_oh  (             ),
    .refill_way_bin ( rnd_way     )
  );

  assign repl_way               = (all_ways_valid) ? rnd_way : inv_way;

  assign mshr_d.size            = (mshr_allocate)  ? miss_size_i    [miss_port_idx] : mshr_q.size;
  assign mshr_d.paddr           = (mshr_allocate)  ? miss_paddr_i   [miss_port_idx] : mshr_q.paddr;
  assign mshr_d.vld_bits        = (mshr_allocate)  ? miss_vld_bits_i[miss_port_idx] : mshr_q.vld_bits;
  assign mshr_d.id              = (mshr_allocate)  ? miss_id_i      [miss_port_idx] : mshr_q.id;
  assign mshr_d.nc              = (mshr_allocate)  ? miss_nc_i      [miss_port_idx] : mshr_q.nc;
  assign mshr_d.repl_way        = (mshr_allocate)  ? repl_way                       : mshr_q.repl_way;
  assign mshr_d.miss_port_idx   = (mshr_allocate)  ? miss_port_idx                  : mshr_q.miss_port_idx;


  assign mshr_vld_d = (mshr_allocate) ? 1'b1 :
                      (load_ack)      ? 1'b0 :
                                        mshr_vld_q;

  assign miss_o     = (mshr_allocate) ? ~miss_nc_i[miss_port_idx] : 1'b0;


  for(genvar k=0; k<NumPorts; k++) begin : gen_rdrd_collision
    assign mshr_rdrd_collision[k]   = (mshr_q.paddr[riscv::PLEN-1:DCACHE_OFFSET_WIDTH] == miss_paddr_i[k][riscv::PLEN-1:DCACHE_OFFSET_WIDTH]) && (mshr_vld_q | mshr_vld_q1);
    assign mshr_rdrd_collision_d[k] = (!miss_req_i[k]) ? 1'b0 : mshr_rdrd_collision_q[k] | mshr_rdrd_collision[k];
  end



  assign mshr_rdwr_collision = (mshr_q.paddr[riscv::PLEN-1:DCACHE_OFFSET_WIDTH] == miss_paddr_i[NumPorts-1][riscv::PLEN-1:DCACHE_OFFSET_WIDTH]) && mshr_vld_q;


  always_comb begin : p_tx_coll
    tx_rdwr_collision = 1'b0;
    for(int k=0; k<DCACHE_MAX_TX; k++) begin
      tx_rdwr_collision |= (miss_paddr_i[miss_port_idx][riscv::PLEN-1:DCACHE_OFFSET_WIDTH] == tx_paddr_i[k][riscv::PLEN-1:DCACHE_OFFSET_WIDTH]) && tx_vld_i[k];
    end
  end






  assign amo_data = (amo_req_i.size==2'b10) ? {amo_req_i.operand_b[0 +: 32],
                                               amo_req_i.operand_b[0 +: 32]} :
                                               amo_req_i.operand_b;


  if (Axi64BitCompliant) begin : gen_axi_rtrn_mux
    assign amo_rtrn_mux = mem_rtrn_i.data[0 +: 64];
  end else begin : gen_piton_rtrn_mux
    assign amo_rtrn_mux = mem_rtrn_i.data[amo_req_i.operand_a[DCACHE_OFFSET_WIDTH-1:3]*64 +: 64];
  end


  assign amo_resp_o.result = (amo_req_i.size==2'b10) ? {{32{amo_rtrn_mux[amo_req_i.operand_a[2]*32 + 31]}},
                                                            amo_rtrn_mux[amo_req_i.operand_a[2]*32 +: 32]} :
                                                       amo_rtrn_mux;

  assign amo_req_d = amo_req_i.req;


  assign mem_data_o.tid    = (amo_sel) ? AmoTxId             : miss_id_i[miss_port_idx];
  assign mem_data_o.nc     = (amo_sel) ? 1'b1                : miss_nc_i[miss_port_idx];
  assign mem_data_o.way    = (amo_sel) ? '0                  : repl_way;
  assign mem_data_o.data   = (amo_sel) ? amo_data            : miss_wdata_i[miss_port_idx];
  assign mem_data_o.size   = (amo_sel) ? amo_req_i.size      : miss_size_i [miss_port_idx];
  assign mem_data_o.amo_op = (amo_sel) ? amo_req_i.amo_op    : AMO_NONE;

  assign tmp_paddr         = (amo_sel) ? amo_req_i.operand_a[riscv::PLEN-1:0] : miss_paddr_i[miss_port_idx];
  assign mem_data_o.paddr  = wt_cache_pkg::paddrSizeAlign(tmp_paddr, mem_data_o.size);





  logic sc_fail, sc_pass, sc_backoff_over;
  exp_backoff #(
    .Seed(3),
    .MaxExp(16)
  ) i_exp_backoff (
    .clk_i,
    .rst_ni,
    .set_i     ( sc_fail         ),
    .clr_i     ( sc_pass         ),
    .is_zero_o ( sc_backoff_over )
  );






  logic store_sent;
  logic [$clog2(wt_cache_pkg::DCACHE_MAX_TX + 1)-1:0] stores_inflight_d, stores_inflight_q;
  assign store_sent = mem_data_req_o   & mem_data_ack_i & (mem_data_o.rtype == DCACHE_STORE_REQ);

  assign stores_inflight_d = (store_ack && store_sent) ? stores_inflight_q     :
                             (store_ack)               ? stores_inflight_q - 1 :
                             (store_sent)              ? stores_inflight_q + 1 :
                                                         stores_inflight_q;


  always_comb begin : p_rtrn_logic
    load_ack        = 1'b0;
    store_ack       = 1'b0;
    amo_ack         = 1'b0;
    inv_vld         = 1'b0;
    inv_vld_all     = 1'b0;
    sc_fail         = 1'b0;
    sc_pass         = 1'b0;
    miss_rtrn_vld_o ='0;
    if (mem_rtrn_vld_i) begin
      unique case (mem_rtrn_i.rtype)
        DCACHE_LOAD_ACK: begin
          if (mshr_vld_q) begin
            load_ack = 1'b1;
            miss_rtrn_vld_o[mshr_q.miss_port_idx] = 1'b1;
          end
        end
        DCACHE_STORE_ACK: begin
          if (stores_inflight_q) begin
            store_ack = 1'b1;
            miss_rtrn_vld_o[NumPorts-1] = 1'b1;
          end
        end
        DCACHE_ATOMIC_ACK: begin
          if (amo_req_q) begin
            amo_ack = 1'b1;


            if (amo_req_i.amo_op == AMO_SC) begin
              if (amo_resp_o.result) begin
                sc_fail = 1'b1;
              end else begin
                sc_pass = 1'b1;
              end
            end
          end
        end
        DCACHE_INV_REQ: begin
          inv_vld     = mem_rtrn_i.inv.vld | mem_rtrn_i.inv.all;
          inv_vld_all = mem_rtrn_i.inv.all;
        end



        default : begin
        end
      endcase
    end
  end


  assign miss_rtrn_id_o           = mem_rtrn_i.tid;






  assign wr_cl_nc_o      = mshr_q.nc;
  assign wr_cl_vld_o     = load_ack | (| wr_cl_we_o);

  assign wr_cl_we_o      = (flush_en   )  ? '1                                    :
                           (inv_vld_all)   ? '1                                    :
                           (inv_vld    )   ? dcache_way_bin2oh(mem_rtrn_i.inv.way) :
                           (cl_write_en)   ? dcache_way_bin2oh(mshr_q.repl_way)    :
                                             '0;

  assign wr_vld_bits_o   = (flush_en   )   ? '0                                    :
                           (inv_vld    )   ? '0                                    :
                           (cl_write_en)   ? dcache_way_bin2oh(mshr_q.repl_way)    :
                                              '0;

  assign wr_cl_idx_o     = (flush_en) ? cnt_q                                                        :
                           (inv_vld)  ? mem_rtrn_i.inv.idx[DCACHE_INDEX_WIDTH-1:DCACHE_OFFSET_WIDTH] :
                                        mshr_q.paddr[DCACHE_INDEX_WIDTH-1:DCACHE_OFFSET_WIDTH];

  assign wr_cl_tag_o     = mshr_q.paddr[DCACHE_TAG_WIDTH+DCACHE_INDEX_WIDTH-1:DCACHE_INDEX_WIDTH];
  assign wr_cl_off_o     = mshr_q.paddr[DCACHE_OFFSET_WIDTH-1:0];
  assign wr_cl_data_o    = mem_rtrn_i.data;
  assign wr_cl_data_be_o = (cl_write_en) ? '1 : '0;


  assign cl_write_en     = load_ack & ~mshr_q.nc;





  always_comb begin : p_fsm

    state_d          = state_q;

    flush_ack_o      = 1'b0;
    mem_data_o.rtype = DCACHE_LOAD_REQ;
    mem_data_req_o   = 1'b0;
    amo_resp_o.ack   = 1'b0;
    miss_replay_o    = '0;


    enable_d         = enable_q & enable_i;
    flush_ack_d      = flush_ack_q;
    flush_en         = 1'b0;
    amo_sel          = 1'b0;
    update_lfsr      = 1'b0;
    mshr_allocate    = 1'b0;
    lock_reqs        = 1'b0;
    mask_reads       = mshr_vld_q;


    unique case (state_q)


      IDLE: begin
        if (flush_i || (enable_i && !enable_q)) begin
          if (wbuffer_empty_i && !mshr_vld_q) begin
            flush_ack_d = flush_i;
            state_d     = FLUSH;
          end else begin
            state_d     = DRAIN;
          end
        end else if (amo_req_i.req) begin
          if (wbuffer_empty_i && !mshr_vld_q) begin
            state_d     = AMO;
          end else begin
            state_d     = DRAIN;
          end

        end else if (|miss_req_masked_d) begin

          if (miss_is_write) begin

            if (!mshr_rdwr_collision) begin
              mem_data_req_o            = 1'b1;
              mem_data_o.rtype          = DCACHE_STORE_REQ;
              if (!mem_data_ack_i) begin
                state_d = STORE_WAIT;
              end
            end


          end else if (!mshr_vld_q || load_ack) begin


            if (mshr_rdrd_collision_d[miss_port_idx]) begin
              miss_replay_o[miss_port_idx] = 1'b1;

            end else if (!tx_rdwr_collision) begin
              mem_data_req_o            = 1'b1;
              mem_data_o.rtype          = DCACHE_LOAD_REQ;
              update_lfsr               = all_ways_valid & mem_data_ack_i;
              mshr_allocate             = mem_data_ack_i;
              if (!mem_data_ack_i) begin
                state_d = LOAD_WAIT;
              end
            end
          end
        end
      end


      STORE_WAIT: begin
        lock_reqs                 = 1'b1;
        mem_data_req_o            = 1'b1;
        mem_data_o.rtype          = DCACHE_STORE_REQ;
        if (mem_data_ack_i) begin
          state_d = IDLE;
        end
      end


      LOAD_WAIT: begin
        lock_reqs                 = 1'b1;
        mem_data_req_o            = 1'b1;
        mem_data_o.rtype          = DCACHE_LOAD_REQ;
        if (mem_data_ack_i) begin
          update_lfsr   = all_ways_valid;
          mshr_allocate = 1'b1;
          state_d       = IDLE;
        end
      end



      DRAIN: begin
        mask_reads = 1'b1;

        if (|miss_req_masked_d && !mshr_rdwr_collision) begin
          mem_data_req_o            = 1'b1;
          mem_data_o.rtype          = DCACHE_STORE_REQ;
        end

        if (wbuffer_empty_i && !mshr_vld_q) begin
          state_d = IDLE;
        end
      end


      FLUSH: begin

        flush_en   = 1'b1;
        if (flush_done) begin
          state_d     = IDLE;
          flush_ack_o = flush_ack_q;
          flush_ack_d = 1'b0;
          enable_d    = enable_i;
        end
      end


      AMO: begin
        mem_data_o.rtype = DCACHE_ATOMIC_REQ;
        amo_sel          = 1'b1;

        if ((amo_req_i.amo_op != AMO_LR) || sc_backoff_over) begin
          mem_data_req_o   = 1'b1;
          if (mem_data_ack_i) begin
            state_d = AMO_WAIT;
          end
        end
      end


      AMO_WAIT: begin
        amo_sel = 1'b1;
        if (amo_ack) begin
          amo_resp_o.ack = 1'b1;
          state_d        = IDLE;
        end
      end

      default: begin

        state_d = IDLE;
      end
    endcase
  end





always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
  if (!rst_ni) begin
    state_q               <= FLUSH;
    cnt_q                 <= '0;
    enable_q              <= '0;
    flush_ack_q           <= '0;
    mshr_vld_q            <= '0;
    mshr_vld_q1           <= '0;
    mshr_q                <= '0;
    mshr_rdrd_collision_q <= '0;
    miss_req_masked_q     <= '0;
    amo_req_q             <= '0;
    stores_inflight_q     <= '0;
  end else begin
    state_q               <= state_d;
    cnt_q                 <= cnt_d;
    enable_q              <= enable_d;
    flush_ack_q           <= flush_ack_d;
    mshr_vld_q            <= mshr_vld_d;
    mshr_vld_q1           <= mshr_vld_q;
    mshr_q                <= mshr_d;
    mshr_rdrd_collision_q <= mshr_rdrd_collision_d;
    miss_req_masked_q     <= miss_req_masked_d;
    amo_req_q             <= amo_req_d;
    stores_inflight_q     <= stores_inflight_d;
  end
end






`ifndef VERILATOR

  read_tid : assert property (
    @(posedge clk_i) disable iff (!rst_ni) mshr_vld_q |-> mem_rtrn_vld_i |-> load_ack |-> mem_rtrn_i.tid == mshr_q.id)
      else $fatal(1,"[l1 dcache missunit] TID of load response doesn't match");

  read_ports : assert property (
    @(posedge clk_i) disable iff (!rst_ni) |miss_req_i[NumPorts-2:0] |-> miss_we_i[NumPorts-2:0] == 0)
      else $fatal(1,"[l1 dcache missunit] only last port can issue write requests");

  write_port : assert property (
    @(posedge clk_i) disable iff (!rst_ni) miss_req_i[NumPorts-1] |-> miss_we_i[NumPorts-1])
      else $fatal(1,"[l1 dcache missunit] last port can only issue write requests");

 initial begin

    assert (NumPorts>=2)
      else $fatal(1,"[l1 dcache missunit] at least two ports are required (one read port, one write port)");
 end
`endif


endmodule
module wt_dcache_missunit import ariane_pkg::*;
 import wt_cache_pkg::*; #(
  parameter bit                         Axi64BitCompliant  = 1'b0,
  parameter logic [CACHE_ID_WIDTH-1:0]  AmoTxId            = 1,
  parameter int unsigned                NumPorts           = 3
) (
  input  logic                                       clk_i,
  input  logic                                       rst_ni,

  input  logic                                       enable_i,
  input  logic                                       flush_i,
  output logic                                       flush_ack_o,
  output logic                                       miss_o,

  input  logic                                       wbuffer_empty_i,
  output logic                                       cache_en_o,

  input  amo_req_t                                   amo_req_i,
  output amo_resp_t                                  amo_resp_o,

  input  logic [NumPorts-1:0]                        miss_req_i,
  output logic [NumPorts-1:0]                        miss_ack_o,
  input  logic [NumPorts-1:0]                        miss_nc_i,
  input  logic [NumPorts-1:0]                        miss_we_i,
  input  logic [NumPorts-1:0][63:0]                  miss_wdata_i,
  input  logic [NumPorts-1:0][riscv::PLEN-1:0]       miss_paddr_i,
  input  logic [NumPorts-1:0][DCACHE_SET_ASSOC-1:0]  miss_vld_bits_i,
  input  logic [NumPorts-1:0][2:0]                   miss_size_i,
  input  logic [NumPorts-1:0][CACHE_ID_WIDTH-1:0]    miss_id_i,

  output logic [NumPorts-1:0]                        miss_replay_o,

  output logic [NumPorts-1:0]                        miss_rtrn_vld_o,
  output logic [CACHE_ID_WIDTH-1:0]                  miss_rtrn_id_o,

  input  logic [DCACHE_MAX_TX-1:0][riscv::PLEN-1:0]  tx_paddr_i,
  input  logic [DCACHE_MAX_TX-1:0]                   tx_vld_i,

  output logic                                       wr_cl_vld_o,
  output logic                                       wr_cl_nc_o,
  output logic [DCACHE_SET_ASSOC-1:0]                wr_cl_we_o,
  output logic [DCACHE_TAG_WIDTH-1:0]                wr_cl_tag_o,
  output logic [DCACHE_CL_IDX_WIDTH-1:0]             wr_cl_idx_o,
  output logic [DCACHE_OFFSET_WIDTH-1:0]             wr_cl_off_o,
  output logic [DCACHE_LINE_WIDTH-1:0]               wr_cl_data_o,
  output logic [DCACHE_LINE_WIDTH/8-1:0]             wr_cl_data_be_o,
  output logic [DCACHE_SET_ASSOC-1:0]                wr_vld_bits_o,

  input  logic                                       mem_rtrn_vld_i,
  input  dcache_rtrn_t                               mem_rtrn_i,
  output logic                                       mem_data_req_o,
  input  logic                                       mem_data_ack_i,
  output dcache_req_t                                mem_data_o
);


  typedef enum logic[2:0] {IDLE, DRAIN, AMO,  FLUSH, STORE_WAIT, LOAD_WAIT, AMO_WAIT} state_e;
  state_e state_d, state_q;


  typedef struct packed {
    logic [riscv::PLEN-1:0]              paddr   ;
    logic [2:0]                          size    ;
    logic [DCACHE_SET_ASSOC-1:0]         vld_bits;
    logic [CACHE_ID_WIDTH-1:0]          id      ;
    logic                                nc      ;
    logic [$clog2(DCACHE_SET_ASSOC)-1:0] repl_way;
    logic [$clog2(NumPorts)-1:0]        miss_port_idx;
  } mshr_t;

  mshr_t mshr_d, mshr_q;
  logic [$clog2(DCACHE_SET_ASSOC)-1:0] repl_way, inv_way, rnd_way;
  logic mshr_vld_d, mshr_vld_q, mshr_vld_q1;
  logic mshr_allocate;
  logic update_lfsr, all_ways_valid;

  logic enable_d, enable_q;
  logic flush_ack_d, flush_ack_q;
  logic flush_en, flush_done;
  logic mask_reads, lock_reqs;
  logic amo_sel, miss_is_write;
  logic amo_req_d, amo_req_q;
  logic [63:0] amo_data, amo_rtrn_mux;
  logic [riscv::PLEN-1:0] tmp_paddr;
  logic [$clog2(NumPorts)-1:0] miss_port_idx;
  logic [DCACHE_CL_IDX_WIDTH-1:0] cnt_d, cnt_q;
  logic [NumPorts-1:0] miss_req_masked_d, miss_req_masked_q;

  logic inv_vld, inv_vld_all, cl_write_en;
  logic load_ack, store_ack, amo_ack;

  logic [NumPorts-1:0] mshr_rdrd_collision_d, mshr_rdrd_collision_q;
  logic [NumPorts-1:0] mshr_rdrd_collision;
  logic tx_rdwr_collision, mshr_rdwr_collision;





  assign cache_en_o      = enable_q;
  assign cnt_d           = (flush_en) ? cnt_q + 1 : '0;
  assign flush_done      = (cnt_q == wt_cache_pkg::DCACHE_NUM_WORDS-1);

  assign miss_req_masked_d = (lock_reqs)  ? miss_req_masked_q      :
                             (mask_reads) ? miss_we_i & miss_req_i : miss_req_i;
  assign miss_is_write     = miss_we_i[miss_port_idx];


  lzc #(
    .WIDTH ( NumPorts )
  ) i_lzc_reqs (
    .in_i    ( miss_req_masked_d ),
    .cnt_o   ( miss_port_idx     ),
    .empty_o (                   )
  );

  always_comb begin : p_ack
    miss_ack_o = '0;
    if (!amo_sel) begin
      miss_ack_o[miss_port_idx] = mem_data_ack_i & mem_data_req_o;
    end
  end






  lzc #(
    .WIDTH ( ariane_pkg::DCACHE_SET_ASSOC )
  ) i_lzc_inv (
    .in_i    ( ~miss_vld_bits_i[miss_port_idx] ),
    .cnt_o   ( inv_way                         ),
    .empty_o ( all_ways_valid                  )
  );


  lfsr_8bit #(
    .WIDTH ( ariane_pkg::DCACHE_SET_ASSOC )
  ) i_lfsr_inv (
    .clk_i          ( clk_i       ),
    .rst_ni         ( rst_ni      ),
    .en_i           ( update_lfsr ),
    .refill_way_oh  (             ),
    .refill_way_bin ( rnd_way     )
  );

  assign repl_way               = (all_ways_valid) ? rnd_way : inv_way;

  assign mshr_d.size            = (mshr_allocate)  ? miss_size_i    [miss_port_idx] : mshr_q.size;
  assign mshr_d.paddr           = (mshr_allocate)  ? miss_paddr_i   [miss_port_idx] : mshr_q.paddr;
  assign mshr_d.vld_bits        = (mshr_allocate)  ? miss_vld_bits_i[miss_port_idx] : mshr_q.vld_bits;
  assign mshr_d.id              = (mshr_allocate)  ? miss_id_i      [miss_port_idx] : mshr_q.id;
  assign mshr_d.nc              = (mshr_allocate)  ? miss_nc_i      [miss_port_idx] : mshr_q.nc;
  assign mshr_d.repl_way        = (mshr_allocate)  ? repl_way                       : mshr_q.repl_way;
  assign mshr_d.miss_port_idx   = (mshr_allocate)  ? miss_port_idx                  : mshr_q.miss_port_idx;


  assign mshr_vld_d = (mshr_allocate) ? 1'b1 :
                      (load_ack)      ? 1'b0 :
                                        mshr_vld_q;

  assign miss_o     = (mshr_allocate) ? ~miss_nc_i[miss_port_idx] : 1'b0;


  for(genvar k=0; k<NumPorts; k++) begin : gen_rdrd_collision
    assign mshr_rdrd_collision[k]   = (mshr_q.paddr[riscv::PLEN-1:DCACHE_OFFSET_WIDTH] == miss_paddr_i[k][riscv::PLEN-1:DCACHE_OFFSET_WIDTH]) && (mshr_vld_q | mshr_vld_q1);
    assign mshr_rdrd_collision_d[k] = (!miss_req_i[k]) ? 1'b0 : mshr_rdrd_collision_q[k] | mshr_rdrd_collision[k];
  end



  assign mshr_rdwr_collision = (mshr_q.paddr[riscv::PLEN-1:DCACHE_OFFSET_WIDTH] == miss_paddr_i[NumPorts-1][riscv::PLEN-1:DCACHE_OFFSET_WIDTH]) && mshr_vld_q;


  always_comb begin : p_tx_coll
    tx_rdwr_collision = 1'b0;
    for(int k=0; k<DCACHE_MAX_TX; k++) begin
      tx_rdwr_collision |= (miss_paddr_i[miss_port_idx][riscv::PLEN-1:DCACHE_OFFSET_WIDTH] == tx_paddr_i[k][riscv::PLEN-1:DCACHE_OFFSET_WIDTH]) && tx_vld_i[k];
    end
  end






  assign amo_data = (amo_req_i.size==2'b10) ? {amo_req_i.operand_b[0 +: 32],
                                               amo_req_i.operand_b[0 +: 32]} :
                                               amo_req_i.operand_b;


  if (Axi64BitCompliant) begin : gen_axi_rtrn_mux
    assign amo_rtrn_mux = mem_rtrn_i.data[0 +: 64];
  end else begin : gen_piton_rtrn_mux
    assign amo_rtrn_mux = mem_rtrn_i.data[amo_req_i.operand_a[DCACHE_OFFSET_WIDTH-1:3]*64 +: 64];
  end


  assign amo_resp_o.result = (amo_req_i.size==2'b10) ? {{32{amo_rtrn_mux[amo_req_i.operand_a[2]*32 + 31]}},
                                                            amo_rtrn_mux[amo_req_i.operand_a[2]*32 +: 32]} :
                                                       amo_rtrn_mux;

  assign amo_req_d = amo_req_i.req;


  assign mem_data_o.tid    = (amo_sel) ? AmoTxId             : miss_id_i[miss_port_idx];
  assign mem_data_o.nc     = (amo_sel) ? 1'b1                : miss_nc_i[miss_port_idx];
  assign mem_data_o.way    = (amo_sel) ? '0                  : repl_way;
  assign mem_data_o.data   = (amo_sel) ? amo_data            : miss_wdata_i[miss_port_idx];
  assign mem_data_o.size   = (amo_sel) ? amo_req_i.size      : miss_size_i [miss_port_idx];
  assign mem_data_o.amo_op = (amo_sel) ? amo_req_i.amo_op    : AMO_NONE;

  assign tmp_paddr         = (amo_sel) ? amo_req_i.operand_a[riscv::PLEN-1:0] : miss_paddr_i[miss_port_idx];
  assign mem_data_o.paddr  = wt_cache_pkg::paddrSizeAlign(tmp_paddr, mem_data_o.size);





  logic sc_fail, sc_pass, sc_backoff_over;
  exp_backoff #(
    .Seed(3),
    .MaxExp(16)
  ) i_exp_backoff (
    .clk_i,
    .rst_ni,
    .set_i     ( sc_fail         ),
    .clr_i     ( sc_pass         ),
    .is_zero_o ( sc_backoff_over )
  );






  logic store_sent;
  logic [$clog2(wt_cache_pkg::DCACHE_MAX_TX + 1)-1:0] stores_inflight_d, stores_inflight_q;
  assign store_sent = mem_data_req_o   & mem_data_ack_i & (mem_data_o.rtype == DCACHE_STORE_REQ);

  assign stores_inflight_d = (store_ack && store_sent) ? stores_inflight_q     :
                             (store_ack)               ? stores_inflight_q - 1 :
                             (store_sent)              ? stores_inflight_q + 1 :
                                                         stores_inflight_q;


  always_comb begin : p_rtrn_logic
    load_ack        = 1'b0;
    store_ack       = 1'b0;
    amo_ack         = 1'b0;
    inv_vld         = 1'b0;
    inv_vld_all     = 1'b0;
    sc_fail         = 1'b0;
    sc_pass         = 1'b0;
    miss_rtrn_vld_o ='0;
    if (mem_rtrn_vld_i) begin
      unique case (mem_rtrn_i.rtype)
        DCACHE_LOAD_ACK: begin
          if (mshr_vld_q) begin
            load_ack = 1'b1;
            miss_rtrn_vld_o[mshr_q.miss_port_idx] = 1'b1;
          end
        end
        DCACHE_STORE_ACK: begin
          if (stores_inflight_q) begin
            store_ack = 1'b1;
            miss_rtrn_vld_o[NumPorts-1] = 1'b1;
          end
        end
        DCACHE_ATOMIC_ACK: begin
          if (amo_req_q) begin
            amo_ack = 1'b1;


            if (amo_req_i.amo_op == AMO_SC) begin
              if (amo_resp_o.result) begin
                sc_fail = 1'b1;
              end else begin
                sc_pass = 1'b1;
              end
            end
          end
        end
        DCACHE_INV_REQ: begin
          inv_vld     = mem_rtrn_i.inv.vld | mem_rtrn_i.inv.all;
          inv_vld_all = mem_rtrn_i.inv.all;
        end



        default : begin
        end
      endcase
    end
  end


  assign miss_rtrn_id_o           = mem_rtrn_i.tid;






  assign wr_cl_nc_o      = mshr_q.nc;
  assign wr_cl_vld_o     = load_ack | (| wr_cl_we_o);

  assign wr_cl_we_o      = (flush_en   )  ? '1                                    :
                           (inv_vld_all)   ? '1                                    :
                           (inv_vld    )   ? dcache_way_bin2oh(mem_rtrn_i.inv.way) :
                           (cl_write_en)   ? dcache_way_bin2oh(mshr_q.repl_way)    :
                                             '0;

  assign wr_vld_bits_o   = (flush_en   )   ? '0                                    :
                           (inv_vld    )   ? '0                                    :
                           (cl_write_en)   ? dcache_way_bin2oh(mshr_q.repl_way)    :
                                              '0;

  assign wr_cl_idx_o     = (flush_en) ? cnt_q                                                        :
                           (inv_vld)  ? mem_rtrn_i.inv.idx[DCACHE_INDEX_WIDTH-1:DCACHE_OFFSET_WIDTH] :
                                        mshr_q.paddr[DCACHE_INDEX_WIDTH-1:DCACHE_OFFSET_WIDTH];

  assign wr_cl_tag_o     = mshr_q.paddr[DCACHE_TAG_WIDTH+DCACHE_INDEX_WIDTH-1:DCACHE_INDEX_WIDTH];
  assign wr_cl_off_o     = mshr_q.paddr[DCACHE_OFFSET_WIDTH-1:0];
  assign wr_cl_data_o    = mem_rtrn_i.data;
  assign wr_cl_data_be_o = (cl_write_en) ? '1 : '0;


  assign cl_write_en     = load_ack & ~mshr_q.nc;





  always_comb begin : p_fsm

    state_d          = state_q;

    flush_ack_o      = 1'b0;
    mem_data_o.rtype = DCACHE_LOAD_REQ;
    mem_data_req_o   = 1'b0;
    amo_resp_o.ack   = 1'b0;
    miss_replay_o    = '0;


    enable_d         = enable_q & enable_i;
    flush_ack_d      = flush_ack_q;
    flush_en         = 1'b0;
    amo_sel          = 1'b0;
    update_lfsr      = 1'b0;
    mshr_allocate    = 1'b0;
    lock_reqs        = 1'b0;
    mask_reads       = mshr_vld_q;


    unique case (state_q)


      IDLE: begin
        if (flush_i || (enable_i && !enable_q)) begin
          if (wbuffer_empty_i && !mshr_vld_q) begin
            flush_ack_d = flush_i;
            state_d     = FLUSH;
          end else begin
            state_d     = DRAIN;
          end
        end else if (amo_req_i.req) begin
          if (wbuffer_empty_i && !mshr_vld_q) begin
            state_d     = AMO;
          end else begin
            state_d     = DRAIN;
          end

        end else if (|miss_req_masked_d) begin

          if (miss_is_write) begin

            if (!mshr_rdwr_collision) begin
              mem_data_req_o            = 1'b1;
              mem_data_o.rtype          = DCACHE_STORE_REQ;
              if (!mem_data_ack_i) begin
                state_d = STORE_WAIT;
              end
            end


          end else if (!mshr_vld_q || load_ack) begin


            if (mshr_rdrd_collision_d[miss_port_idx]) begin
              miss_replay_o[miss_port_idx] = 1'b1;

            end else if (!tx_rdwr_collision) begin
              mem_data_req_o            = 1'b1;
              mem_data_o.rtype          = DCACHE_LOAD_REQ;
              update_lfsr               = all_ways_valid & mem_data_ack_i;
              mshr_allocate             = mem_data_ack_i;
              if (!mem_data_ack_i) begin
                state_d = LOAD_WAIT;
              end
            end
          end
        end
      end


      STORE_WAIT: begin
        lock_reqs                 = 1'b1;
        mem_data_req_o            = 1'b1;
        mem_data_o.rtype          = DCACHE_STORE_REQ;
        if (mem_data_ack_i) begin
          state_d = IDLE;
        end
      end


      LOAD_WAIT: begin
        lock_reqs                 = 1'b1;
        mem_data_req_o            = 1'b1;
        mem_data_o.rtype          = DCACHE_LOAD_REQ;
        if (mem_data_ack_i) begin
          update_lfsr   = all_ways_valid;
          mshr_allocate = 1'b1;
          state_d       = IDLE;
        end
      end



      DRAIN: begin
        mask_reads = 1'b1;

        if (|miss_req_masked_d && !mshr_rdwr_collision) begin
          mem_data_req_o            = 1'b1;
          mem_data_o.rtype          = DCACHE_STORE_REQ;
        end

        if (wbuffer_empty_i && !mshr_vld_q) begin
          state_d = IDLE;
        end
      end


      FLUSH: begin

        flush_en   = 1'b1;
        if (flush_done) begin
          state_d     = IDLE;
          flush_ack_o = flush_ack_q;
          flush_ack_d = 1'b0;
          enable_d    = enable_i;
        end
      end


      AMO: begin
        mem_data_o.rtype = DCACHE_ATOMIC_REQ;
        amo_sel          = 1'b1;

        if ((amo_req_i.amo_op != AMO_LR) || sc_backoff_over) begin
          mem_data_req_o   = 1'b1;
          if (mem_data_ack_i) begin
            state_d = AMO_WAIT;
          end
        end
      end


      AMO_WAIT: begin
        amo_sel = 1'b1;
        if (amo_ack) begin
          amo_resp_o.ack = 1'b1;
          state_d        = IDLE;
        end
      end

      default: begin

        state_d = IDLE;
      end
    endcase
  end





always_ff @(posedge clk_i or negedge rst_ni) begin : p_regs
  if (!rst_ni) begin
    state_q               <= FLUSH;
    cnt_q                 <= '0;
    enable_q              <= '0;
    flush_ack_q           <= '0;
    mshr_vld_q            <= '0;
    mshr_vld_q1           <= '0;
    mshr_q                <= '0;
    mshr_rdrd_collision_q <= '0;
    miss_req_masked_q     <= '0;
    amo_req_q             <= '0;
    stores_inflight_q     <= '0;
  end else begin
    state_q               <= state_d;
    cnt_q                 <= cnt_d;
    enable_q              <= enable_d;
    flush_ack_q           <= flush_ack_d;
    mshr_vld_q            <= mshr_vld_d;
    mshr_vld_q1           <= mshr_vld_q;
    mshr_q                <= mshr_d;
    mshr_rdrd_collision_q <= mshr_rdrd_collision_d;
    miss_req_masked_q     <= miss_req_masked_d;
    amo_req_q             <= amo_req_d;
    stores_inflight_q     <= stores_inflight_d;
  end
end






`ifndef VERILATOR

  read_tid : assert property (
    @(posedge clk_i) disable iff (!rst_ni) mshr_vld_q |-> mem_rtrn_vld_i |-> load_ack |-> mem_rtrn_i.tid == mshr_q.id)
      else $fatal(1,"[l1 dcache missunit] TID of load response doesn't match");

  read_ports : assert property (
    @(posedge clk_i) disable iff (!rst_ni) |miss_req_i[NumPorts-2:0] |-> miss_we_i[NumPorts-2:0] == 0)
      else $fatal(1,"[l1 dcache missunit] only last port can issue write requests");

  write_port : assert property (
    @(posedge clk_i) disable iff (!rst_ni) miss_req_i[NumPorts-1] |-> miss_we_i[NumPorts-1])
      else $fatal(1,"[l1 dcache missunit] last port can only issue write requests");

 initial begin

    assert (NumPorts>=2)
      else $fatal(1,"[l1 dcache missunit] at least two ports are required (one read port, one write port)");
 end
`endif


endmodule