data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/instr_queue.sv
1: b"%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/instr_queue.sv:50: syntax error, unexpected ::, expecting ':'\n  input  logic [ariane_pkg::INSTR_PER_FETCH-1:0][31:0]       instr_i,\n                          ^~\n                                                                                                                        : ... Perhaps 'ariane_pkg' 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/frontend/instr_queue.sv:51: syntax error, unexpected ::, expecting ':'\n  input  logic [ariane_pkg::INSTR_PER_FETCH-1:0][riscv::VLEN-1:0] addr_i,\n                          ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/instr_queue.sv:52: syntax error, unexpected ::, expecting ':'\n  input  logic [ariane_pkg::INSTR_PER_FETCH-1:0]             valid_i,\n                          ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/instr_queue.sv:54: syntax error, unexpected output, expecting IDENTIFIER or '=' or do or final\n  output logic [ariane_pkg::INSTR_PER_FETCH-1:0]             consumed_o,\n  ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/instr_queue.sv:54: syntax error, unexpected ::, expecting ':'\n  output logic [ariane_pkg::INSTR_PER_FETCH-1:0]             consumed_o,\n                          ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/instr_queue.sv:57: syntax error, unexpected ::, expecting ':'\n  input  logic [riscv::VLEN-1:0]                             exception_addr_i,\n                     ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/instr_queue.sv:59: syntax error, unexpected ::, expecting ':'\n  input  logic [riscv::VLEN-1:0]                             predict_address_i,\n                     ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/instr_queue.sv:63: syntax error, unexpected output, expecting IDENTIFIER or '=' or do or final\n  output logic [riscv::VLEN-1:0]                             replay_addr_o,  \n  ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/instr_queue.sv:63: syntax error, unexpected ::, expecting ':'\n  output logic [riscv::VLEN-1:0]                             replay_addr_o,  \n                     ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/instr_queue.sv:67: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  logic                                               fetch_entry_ready_i\n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/instr_queue.sv:72: syntax error, unexpected IDENTIFIER, expecting TYPE-IDENTIFIER\n    ariane_pkg::cf_t cf;     \n    ^~~~~~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/instr_queue.sv:74: syntax error, unexpected ::, expecting ':'\n    logic [riscv::VLEN-1:0] ex_vaddr;        \n                ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/instr_queue.sv:77: syntax error, unexpected ::\n  logic [$clog2(ariane_pkg::INSTR_PER_FETCH)-1:0] branch_index;\n                          ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/instr_queue.sv:79: syntax error, unexpected ::, expecting ':'\n  logic [ariane_pkg::INSTR_PER_FETCH-1:0]\n                   ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/instr_queue.sv:82: syntax error, unexpected ::, expecting ':'\n  logic [ariane_pkg::INSTR_PER_FETCH-1:0]          push_instr, push_instr_fifo;\n                   ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/instr_queue.sv:83: syntax error, unexpected ::, expecting ':'\n  logic [ariane_pkg::INSTR_PER_FETCH-1:0]          pop_instr;\n                   ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/instr_queue.sv:84: syntax error, unexpected ::, expecting ':'\n  logic [ariane_pkg::INSTR_PER_FETCH-1:0]          instr_queue_full;\n                   ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/instr_queue.sv:85: syntax error, unexpected ::, expecting ':'\n  logic [ariane_pkg::INSTR_PER_FETCH-1:0]          instr_queue_empty;\n                   ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/instr_queue.sv:88: syntax error, unexpected ::\n  logic [$clog2(ariane_pkg::FETCH_FIFO_DEPTH)-1:0] address_queue_usage;\n                          ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/instr_queue.sv:89: syntax error, unexpected ::, expecting ':'\n  logic [riscv::VLEN-1:0] address_out;\n              ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/instr_queue.sv:96: syntax error, unexpected ::\n  logic [$clog2(ariane_pkg::INSTR_PER_FETCH)-1:0] idx_is_d, idx_is_q;\n                          ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/instr_queue.sv:99: syntax error, unexpected ::, expecting ':'\n  logic [ariane_pkg::INSTR_PER_FETCH-1:0] idx_ds_d, idx_ds_q;\n                   ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/instr_queue.sv:100: syntax error, unexpected ::, expecting ':'\n  logic [riscv::VLEN-1:0] pc_d, pc_q;  \n              ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/instr_queue.sv:103: syntax error, unexpected ::, expecting ':'\n  logic [ariane_pkg::INSTR_PER_FETCH*2-2:0] branch_mask_extended;\n                   ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/instr_queue.sv:104: syntax error, unexpected ::, expecting ':'\n  logic [ariane_pkg::INSTR_PER_FETCH-1:0] branch_mask;\n                   ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/instr_queue.sv:106: syntax error, unexpected ::, expecting ':'\n  logic [ariane_pkg::INSTR_PER_FETCH-1:0] taken;\n                   ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/instr_queue.sv:108: syntax error, unexpected ::\n  logic [$clog2(ariane_pkg::INSTR_PER_FETCH):0] popcount;\n                          ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/instr_queue.sv:109: syntax error, unexpected ::\n  logic [$clog2(ariane_pkg::INSTR_PER_FETCH)-1:0] shamt;\n                          ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/instr_queue.sv:110: syntax error, unexpected ::, expecting ':'\n  logic [ariane_pkg::INSTR_PER_FETCH-1:0] valid;\n                   ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/instr_queue.sv:111: syntax error, unexpected ::, expecting ':'\n  logic [ariane_pkg::INSTR_PER_FETCH*2-1:0] consumed_extended;\n                   ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/instr_queue.sv:113: syntax error, unexpected ::, expecting ':'\n  logic [ariane_pkg::INSTR_PER_FETCH*2-1:0] fifo_pos_extended;\n                   ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/instr_queue.sv:114: syntax error, unexpected ::, expecting ':'\n  logic [ariane_pkg::INSTR_PER_FETCH-1:0] fifo_pos;\n                   ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/instr_queue.sv:115: syntax error, unexpected ::, expecting ':'\n  logic [ariane_pkg::INSTR_PER_FETCH*2-1:0][31:0] instr;\n                   ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/instr_queue.sv:118: syntax error, unexpected ::, expecting ':'\n  logic [ariane_pkg::INSTR_PER_FETCH-1:0] instr_overflow_fifo;\n                   ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/instr_queue.sv:228: syntax error, unexpected IDENTIFIER\n    for (int unsigned i = 0; i < ariane_pkg::INSTR_PER_FETCH; i++) begin\n                             ^\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/instr_queue.sv:301: syntax error, unexpected IDENTIFIER\n    for (int i = 0; i < ariane_pkg::INSTR_PER_FETCH; i++) begin\n                    ^\n%Error: Exiting due to 36 error(s)\n"
module instr_queue (
  input  logic                                               clk_i,
  input  logic                                               rst_ni,
  input  logic                                               flush_i,
  input  logic [ariane_pkg::INSTR_PER_FETCH-1:0][31:0]       instr_i,
  input  logic [ariane_pkg::INSTR_PER_FETCH-1:0][riscv::VLEN-1:0] addr_i,
  input  logic [ariane_pkg::INSTR_PER_FETCH-1:0]             valid_i,
  output logic                                               ready_o,
  output logic [ariane_pkg::INSTR_PER_FETCH-1:0]             consumed_o,

  input  ariane_pkg::frontend_exception_t                    exception_i,
  input  logic [riscv::VLEN-1:0]                             exception_addr_i,

  input  logic [riscv::VLEN-1:0]                             predict_address_i,
  input  ariane_pkg::cf_t  [ariane_pkg::INSTR_PER_FETCH-1:0] cf_type_i,

  output logic                                               replay_o,
  output logic [riscv::VLEN-1:0]                             replay_addr_o,

  output ariane_pkg::fetch_entry_t                           fetch_entry_o,
  output logic                                               fetch_entry_valid_o,
  input  logic                                               fetch_entry_ready_i
);

  typedef struct packed {
    logic [31:0]     instr;
    ariane_pkg::cf_t cf;
    ariane_pkg::frontend_exception_t ex;
    logic [riscv::VLEN-1:0] ex_vaddr;
  } instr_data_t;

  logic [$clog2(ariane_pkg::INSTR_PER_FETCH)-1:0] branch_index;

  logic [ariane_pkg::INSTR_PER_FETCH-1:0]
        [$clog2(ariane_pkg::FETCH_FIFO_DEPTH)-1:0] instr_queue_usage;
  instr_data_t [ariane_pkg::INSTR_PER_FETCH-1:0]   instr_data_in, instr_data_out;
  logic [ariane_pkg::INSTR_PER_FETCH-1:0]          push_instr, push_instr_fifo;
  logic [ariane_pkg::INSTR_PER_FETCH-1:0]          pop_instr;
  logic [ariane_pkg::INSTR_PER_FETCH-1:0]          instr_queue_full;
  logic [ariane_pkg::INSTR_PER_FETCH-1:0]          instr_queue_empty;
  logic instr_overflow;

  logic [$clog2(ariane_pkg::FETCH_FIFO_DEPTH)-1:0] address_queue_usage;
  logic [riscv::VLEN-1:0] address_out;
  logic pop_address;
  logic push_address;
  logic full_address;
  logic empty_address;
  logic address_overflow;

  logic [$clog2(ariane_pkg::INSTR_PER_FETCH)-1:0] idx_is_d, idx_is_q;


  logic [ariane_pkg::INSTR_PER_FETCH-1:0] idx_ds_d, idx_ds_q;
  logic [riscv::VLEN-1:0] pc_d, pc_q;
  logic reset_address_d, reset_address_q;

  logic [ariane_pkg::INSTR_PER_FETCH*2-2:0] branch_mask_extended;
  logic [ariane_pkg::INSTR_PER_FETCH-1:0] branch_mask;
  logic branch_empty;
  logic [ariane_pkg::INSTR_PER_FETCH-1:0] taken;

  logic [$clog2(ariane_pkg::INSTR_PER_FETCH):0] popcount;
  logic [$clog2(ariane_pkg::INSTR_PER_FETCH)-1:0] shamt;
  logic [ariane_pkg::INSTR_PER_FETCH-1:0] valid;
  logic [ariane_pkg::INSTR_PER_FETCH*2-1:0] consumed_extended;

  logic [ariane_pkg::INSTR_PER_FETCH*2-1:0] fifo_pos_extended;
  logic [ariane_pkg::INSTR_PER_FETCH-1:0] fifo_pos;
  logic [ariane_pkg::INSTR_PER_FETCH*2-1:0][31:0] instr;
  ariane_pkg::cf_t [ariane_pkg::INSTR_PER_FETCH*2-1:0] cf;

  logic [ariane_pkg::INSTR_PER_FETCH-1:0] instr_overflow_fifo;

  assign ready_o = ~(|instr_queue_full) & ~full_address;

  for (genvar i = 0; i < ariane_pkg::INSTR_PER_FETCH; i++) begin : gen_unpack_taken
    assign taken[i] = cf_type_i[i] != ariane_pkg::NoCF;
  end

  lzc #(
    .WIDTH   ( ariane_pkg::INSTR_PER_FETCH ),
    .MODE    ( 0                           )
  ) i_lzc_branch_index (
    .in_i    ( taken          ),
    .cnt_o   ( branch_index   ),
    .empty_o ( branch_empty   )
  );






  assign branch_mask_extended = {{{ariane_pkg::INSTR_PER_FETCH-1}{1'b0}}, {{ariane_pkg::INSTR_PER_FETCH}{1'b1}}} << branch_index;
  assign branch_mask = branch_mask_extended[ariane_pkg::INSTR_PER_FETCH * 2 - 2:ariane_pkg::INSTR_PER_FETCH - 1];


  assign valid = valid_i & branch_mask;

  assign consumed_extended = {push_instr_fifo, push_instr_fifo} >> idx_is_q;
  assign consumed_o = consumed_extended[ariane_pkg::INSTR_PER_FETCH-1:0];

  popcount #(
    .INPUT_WIDTH   ( ariane_pkg::INSTR_PER_FETCH )
  ) i_popcount (
    .data_i     ( push_instr_fifo ),
    .popcount_o ( popcount        )
  );
  assign shamt = popcount[$bits(shamt)-1:0];


  assign idx_is_d = idx_is_q + shamt;





  assign fifo_pos_extended = { valid, valid } << idx_is_q;

  assign fifo_pos = fifo_pos_extended[ariane_pkg::INSTR_PER_FETCH*2-1:ariane_pkg::INSTR_PER_FETCH];


  assign push_instr = fifo_pos & ~instr_queue_full;


  for (genvar i = 0; i < ariane_pkg::INSTR_PER_FETCH; i++) begin : gen_duplicate_instr_input
    assign instr[i] = instr_i[i];
    assign instr[i + ariane_pkg::INSTR_PER_FETCH] = instr_i[i];
    assign cf[i] = cf_type_i[i];
    assign cf[i + ariane_pkg::INSTR_PER_FETCH] = cf_type_i[i];
  end


  for (genvar i = 0; i < ariane_pkg::INSTR_PER_FETCH; i++) begin : gen_fifo_input_select

    assign instr_data_in[i].instr = instr[i + idx_is_q];
    assign instr_data_in[i].cf = cf[i + idx_is_q];
    assign instr_data_in[i].ex = exception_i;
    assign instr_data_in[i].ex_vaddr = exception_addr_i;

  end









  assign instr_overflow_fifo = instr_queue_full & fifo_pos;
  assign instr_overflow = |instr_overflow_fifo;
  assign address_overflow = full_address & push_address;
  assign replay_o = instr_overflow | address_overflow;





  assign replay_addr_o = (address_overflow) ? addr_i[0] : addr_i[shamt];





  assign fetch_entry_valid_o = ~(&instr_queue_empty);

  always_comb begin
    idx_ds_d = idx_ds_q;

    pop_instr = '0;

    fetch_entry_o.instruction = '0;
    fetch_entry_o.address = pc_q;
    fetch_entry_o.ex.valid = 1'b0;
    fetch_entry_o.ex.cause = '0;

    fetch_entry_o.ex.tval = '0;
    fetch_entry_o.branch_predict.predict_address = address_out;
    fetch_entry_o.branch_predict.cf = ariane_pkg::NoCF;

    for (int unsigned i = 0; i < ariane_pkg::INSTR_PER_FETCH; i++) begin
      if (idx_ds_q[i]) begin
        if (instr_data_out[i].ex == ariane_pkg::FE_INSTR_ACCESS_FAULT) begin
            fetch_entry_o.ex.cause = riscv::INSTR_ACCESS_FAULT;
        end else begin
            fetch_entry_o.ex.cause = riscv::INSTR_PAGE_FAULT;
        end
        fetch_entry_o.instruction = instr_data_out[i].instr;
        fetch_entry_o.ex.valid = instr_data_out[i].ex != ariane_pkg::FE_NONE;
        fetch_entry_o.ex.tval  = {{64-riscv::VLEN{1'b0}}, instr_data_out[i].ex_vaddr};
        fetch_entry_o.branch_predict.cf = instr_data_out[i].cf;
        pop_instr[i] = fetch_entry_valid_o & fetch_entry_ready_i;
      end
    end

    if (fetch_entry_ready_i) begin
      idx_ds_d = {idx_ds_q[ariane_pkg::INSTR_PER_FETCH-2:0], idx_ds_q[ariane_pkg::INSTR_PER_FETCH-1]};
    end
  end



  assign pop_address = ((fetch_entry_o.branch_predict.cf != ariane_pkg::NoCF) & |pop_instr);




  always_comb begin
    pc_d = pc_q;
    reset_address_d = flush_i ? 1'b1 : reset_address_q;

    if (fetch_entry_ready_i) begin


      pc_d =  pc_q + ((fetch_entry_o.instruction[1:0] != 2'b11) ? 'd2 : 'd4);
    end

    if (pop_address) pc_d = address_out;


    if (valid_i[0] && reset_address_q) begin

      pc_d = addr_i[0];
      reset_address_d = 1'b0;
    end
  end


  for (genvar i = 0; i < ariane_pkg::INSTR_PER_FETCH; i++) begin : gen_instr_fifo

    assign push_instr_fifo[i] = push_instr[i] & ~address_overflow;
    fifo_v3 #(
      .DEPTH      ( ariane_pkg::FETCH_FIFO_DEPTH ),
      .dtype      ( instr_data_t                 )
    ) i_fifo_instr_data (
      .clk_i      ( clk_i                ),
      .rst_ni     ( rst_ni               ),
      .flush_i    ( flush_i              ),
      .testmode_i ( 1'b0                 ),
      .full_o     ( instr_queue_full[i]  ),
      .empty_o    ( instr_queue_empty[i] ),
      .usage_o    ( instr_queue_usage[i] ),
      .data_i     ( instr_data_in[i]     ),
      .push_i     ( push_instr_fifo[i]   ),
      .data_o     ( instr_data_out[i]    ),
      .pop_i      ( pop_instr[i]         )
    );
  end


  always_comb begin
    push_address = 1'b0;

    for (int i = 0; i < ariane_pkg::INSTR_PER_FETCH; i++) begin
      push_address |= push_instr[i] & (instr_data_in[i].cf != ariane_pkg::NoCF);
    end
  end

  fifo_v3 #(
    .DEPTH      ( ariane_pkg::FETCH_FIFO_DEPTH ),
    .DATA_WIDTH ( riscv::VLEN                  )
  ) i_fifo_address (
    .clk_i      ( clk_i                        ),
    .rst_ni     ( rst_ni                       ),
    .flush_i    ( flush_i                      ),
    .testmode_i ( 1'b0                         ),
    .full_o     ( full_address                 ),
    .empty_o    ( empty_address                ),
    .usage_o    ( address_queue_usage          ),
    .data_i     ( predict_address_i            ),
    .push_i     ( push_address & ~full_address ),
    .data_o     ( address_out                  ),
    .pop_i      ( pop_address                  )
  );

  unread i_unread_address_fifo (.d_i(|{empty_address, address_queue_usage}));
  unread i_unread_branch_mask (.d_i(|branch_mask_extended));
  unread i_unread_lzc (.d_i(|{branch_empty}));
  unread i_unread_fifo_pos (.d_i(|fifo_pos_extended));
  unread i_unread_instr_fifo (.d_i(|instr_queue_usage));

  always_ff @(posedge clk_i or negedge rst_ni) begin
    if (!rst_ni) begin
      idx_ds_q        <= 'b1;
      idx_is_q        <= '0;
      pc_q            <= '0;
      reset_address_q <= 1'b1;
    end else begin
      pc_q            <= pc_d;
      reset_address_q <= reset_address_d;
      if (flush_i) begin

          idx_ds_q        <= 'b1;

          idx_is_q        <= '0;
          reset_address_q <= 1'b1;
      end else begin
          idx_ds_q        <= idx_ds_d;
          idx_is_q        <= idx_is_d;
      end
    end
  end


  `ifndef VERILATOR
      replay_address_fifo: assert property (
        @(posedge clk_i) disable iff (!rst_ni) replay_o |-> !i_fifo_address.push_i
      ) else $fatal(1,"[instr_queue] Pushing address although replay asserted");

      output_select_onehot: assert property (
        @(posedge clk_i) $onehot0(idx_ds_q)
      ) else begin $error("Output select should be one-hot encoded"); $stop(); end
  `endif

endmodule
module instr_queue (
  input  logic                                               clk_i,
  input  logic                                               rst_ni,
  input  logic                                               flush_i,
  input  logic [ariane_pkg::INSTR_PER_FETCH-1:0][31:0]       instr_i,
  input  logic [ariane_pkg::INSTR_PER_FETCH-1:0][riscv::VLEN-1:0] addr_i,
  input  logic [ariane_pkg::INSTR_PER_FETCH-1:0]             valid_i,
  output logic                                               ready_o,
  output logic [ariane_pkg::INSTR_PER_FETCH-1:0]             consumed_o,

  input  ariane_pkg::frontend_exception_t                    exception_i,
  input  logic [riscv::VLEN-1:0]                             exception_addr_i,

  input  logic [riscv::VLEN-1:0]                             predict_address_i,
  input  ariane_pkg::cf_t  [ariane_pkg::INSTR_PER_FETCH-1:0] cf_type_i,

  output logic                                               replay_o,
  output logic [riscv::VLEN-1:0]                             replay_addr_o,

  output ariane_pkg::fetch_entry_t                           fetch_entry_o,
  output logic                                               fetch_entry_valid_o,
  input  logic                                               fetch_entry_ready_i
);


  typedef struct packed {
    logic [31:0]     instr;
    ariane_pkg::cf_t cf;
    ariane_pkg::frontend_exception_t ex;
    logic [riscv::VLEN-1:0] ex_vaddr;
  } instr_data_t;

  logic [$clog2(ariane_pkg::INSTR_PER_FETCH)-1:0] branch_index;

  logic [ariane_pkg::INSTR_PER_FETCH-1:0]
        [$clog2(ariane_pkg::FETCH_FIFO_DEPTH)-1:0] instr_queue_usage;
  instr_data_t [ariane_pkg::INSTR_PER_FETCH-1:0]   instr_data_in, instr_data_out;
  logic [ariane_pkg::INSTR_PER_FETCH-1:0]          push_instr, push_instr_fifo;
  logic [ariane_pkg::INSTR_PER_FETCH-1:0]          pop_instr;
  logic [ariane_pkg::INSTR_PER_FETCH-1:0]          instr_queue_full;
  logic [ariane_pkg::INSTR_PER_FETCH-1:0]          instr_queue_empty;
  logic instr_overflow;

  logic [$clog2(ariane_pkg::FETCH_FIFO_DEPTH)-1:0] address_queue_usage;
  logic [riscv::VLEN-1:0] address_out;
  logic pop_address;
  logic push_address;
  logic full_address;
  logic empty_address;
  logic address_overflow;

  logic [$clog2(ariane_pkg::INSTR_PER_FETCH)-1:0] idx_is_d, idx_is_q;


  logic [ariane_pkg::INSTR_PER_FETCH-1:0] idx_ds_d, idx_ds_q;
  logic [riscv::VLEN-1:0] pc_d, pc_q;
  logic reset_address_d, reset_address_q;

  logic [ariane_pkg::INSTR_PER_FETCH*2-2:0] branch_mask_extended;
  logic [ariane_pkg::INSTR_PER_FETCH-1:0] branch_mask;
  logic branch_empty;
  logic [ariane_pkg::INSTR_PER_FETCH-1:0] taken;

  logic [$clog2(ariane_pkg::INSTR_PER_FETCH):0] popcount;
  logic [$clog2(ariane_pkg::INSTR_PER_FETCH)-1:0] shamt;
  logic [ariane_pkg::INSTR_PER_FETCH-1:0] valid;
  logic [ariane_pkg::INSTR_PER_FETCH*2-1:0] consumed_extended;

  logic [ariane_pkg::INSTR_PER_FETCH*2-1:0] fifo_pos_extended;
  logic [ariane_pkg::INSTR_PER_FETCH-1:0] fifo_pos;
  logic [ariane_pkg::INSTR_PER_FETCH*2-1:0][31:0] instr;
  ariane_pkg::cf_t [ariane_pkg::INSTR_PER_FETCH*2-1:0] cf;

  logic [ariane_pkg::INSTR_PER_FETCH-1:0] instr_overflow_fifo;

  assign ready_o = ~(|instr_queue_full) & ~full_address;

  for (genvar i = 0; i < ariane_pkg::INSTR_PER_FETCH; i++) begin : gen_unpack_taken
    assign taken[i] = cf_type_i[i] != ariane_pkg::NoCF;
  end

  lzc #(
    .WIDTH   ( ariane_pkg::INSTR_PER_FETCH ),
    .MODE    ( 0                           )
  ) i_lzc_branch_index (
    .in_i    ( taken          ),
    .cnt_o   ( branch_index   ),
    .empty_o ( branch_empty   )
  );






  assign branch_mask_extended = {{{ariane_pkg::INSTR_PER_FETCH-1}{1'b0}}, {{ariane_pkg::INSTR_PER_FETCH}{1'b1}}} << branch_index;
  assign branch_mask = branch_mask_extended[ariane_pkg::INSTR_PER_FETCH * 2 - 2:ariane_pkg::INSTR_PER_FETCH - 1];


  assign valid = valid_i & branch_mask;

  assign consumed_extended = {push_instr_fifo, push_instr_fifo} >> idx_is_q;
  assign consumed_o = consumed_extended[ariane_pkg::INSTR_PER_FETCH-1:0];

  popcount #(
    .INPUT_WIDTH   ( ariane_pkg::INSTR_PER_FETCH )
  ) i_popcount (
    .data_i     ( push_instr_fifo ),
    .popcount_o ( popcount        )
  );
  assign shamt = popcount[$bits(shamt)-1:0];


  assign idx_is_d = idx_is_q + shamt;





  assign fifo_pos_extended = { valid, valid } << idx_is_q;

  assign fifo_pos = fifo_pos_extended[ariane_pkg::INSTR_PER_FETCH*2-1:ariane_pkg::INSTR_PER_FETCH];


  assign push_instr = fifo_pos & ~instr_queue_full;


  for (genvar i = 0; i < ariane_pkg::INSTR_PER_FETCH; i++) begin : gen_duplicate_instr_input
    assign instr[i] = instr_i[i];
    assign instr[i + ariane_pkg::INSTR_PER_FETCH] = instr_i[i];
    assign cf[i] = cf_type_i[i];
    assign cf[i + ariane_pkg::INSTR_PER_FETCH] = cf_type_i[i];
  end


  for (genvar i = 0; i < ariane_pkg::INSTR_PER_FETCH; i++) begin : gen_fifo_input_select

    assign instr_data_in[i].instr = instr[i + idx_is_q];
    assign instr_data_in[i].cf = cf[i + idx_is_q];
    assign instr_data_in[i].ex = exception_i;
    assign instr_data_in[i].ex_vaddr = exception_addr_i;

  end









  assign instr_overflow_fifo = instr_queue_full & fifo_pos;
  assign instr_overflow = |instr_overflow_fifo;
  assign address_overflow = full_address & push_address;
  assign replay_o = instr_overflow | address_overflow;





  assign replay_addr_o = (address_overflow) ? addr_i[0] : addr_i[shamt];





  assign fetch_entry_valid_o = ~(&instr_queue_empty);

  always_comb begin
    idx_ds_d = idx_ds_q;

    pop_instr = '0;

    fetch_entry_o.instruction = '0;
    fetch_entry_o.address = pc_q;
    fetch_entry_o.ex.valid = 1'b0;
    fetch_entry_o.ex.cause = '0;

    fetch_entry_o.ex.tval = '0;
    fetch_entry_o.branch_predict.predict_address = address_out;
    fetch_entry_o.branch_predict.cf = ariane_pkg::NoCF;

    for (int unsigned i = 0; i < ariane_pkg::INSTR_PER_FETCH; i++) begin
      if (idx_ds_q[i]) begin
        if (instr_data_out[i].ex == ariane_pkg::FE_INSTR_ACCESS_FAULT) begin
            fetch_entry_o.ex.cause = riscv::INSTR_ACCESS_FAULT;
        end else begin
            fetch_entry_o.ex.cause = riscv::INSTR_PAGE_FAULT;
        end
        fetch_entry_o.instruction = instr_data_out[i].instr;
        fetch_entry_o.ex.valid = instr_data_out[i].ex != ariane_pkg::FE_NONE;
        fetch_entry_o.ex.tval  = {{64-riscv::VLEN{1'b0}}, instr_data_out[i].ex_vaddr};
        fetch_entry_o.branch_predict.cf = instr_data_out[i].cf;
        pop_instr[i] = fetch_entry_valid_o & fetch_entry_ready_i;
      end
    end

    if (fetch_entry_ready_i) begin
      idx_ds_d = {idx_ds_q[ariane_pkg::INSTR_PER_FETCH-2:0], idx_ds_q[ariane_pkg::INSTR_PER_FETCH-1]};
    end
  end



  assign pop_address = ((fetch_entry_o.branch_predict.cf != ariane_pkg::NoCF) & |pop_instr);




  always_comb begin
    pc_d = pc_q;
    reset_address_d = flush_i ? 1'b1 : reset_address_q;

    if (fetch_entry_ready_i) begin


      pc_d =  pc_q + ((fetch_entry_o.instruction[1:0] != 2'b11) ? 'd2 : 'd4);
    end

    if (pop_address) pc_d = address_out;


    if (valid_i[0] && reset_address_q) begin

      pc_d = addr_i[0];
      reset_address_d = 1'b0;
    end
  end


  for (genvar i = 0; i < ariane_pkg::INSTR_PER_FETCH; i++) begin : gen_instr_fifo

    assign push_instr_fifo[i] = push_instr[i] & ~address_overflow;
    fifo_v3 #(
      .DEPTH      ( ariane_pkg::FETCH_FIFO_DEPTH ),
      .dtype      ( instr_data_t                 )
    ) i_fifo_instr_data (
      .clk_i      ( clk_i                ),
      .rst_ni     ( rst_ni               ),
      .flush_i    ( flush_i              ),
      .testmode_i ( 1'b0                 ),
      .full_o     ( instr_queue_full[i]  ),
      .empty_o    ( instr_queue_empty[i] ),
      .usage_o    ( instr_queue_usage[i] ),
      .data_i     ( instr_data_in[i]     ),
      .push_i     ( push_instr_fifo[i]   ),
      .data_o     ( instr_data_out[i]    ),
      .pop_i      ( pop_instr[i]         )
    );
  end


  always_comb begin
    push_address = 1'b0;

    for (int i = 0; i < ariane_pkg::INSTR_PER_FETCH; i++) begin
      push_address |= push_instr[i] & (instr_data_in[i].cf != ariane_pkg::NoCF);
    end
  end

  fifo_v3 #(
    .DEPTH      ( ariane_pkg::FETCH_FIFO_DEPTH ),
    .DATA_WIDTH ( riscv::VLEN                  )
  ) i_fifo_address (
    .clk_i      ( clk_i                        ),
    .rst_ni     ( rst_ni                       ),
    .flush_i    ( flush_i                      ),
    .testmode_i ( 1'b0                         ),
    .full_o     ( full_address                 ),
    .empty_o    ( empty_address                ),
    .usage_o    ( address_queue_usage          ),
    .data_i     ( predict_address_i            ),
    .push_i     ( push_address & ~full_address ),
    .data_o     ( address_out                  ),
    .pop_i      ( pop_address                  )
  );

  unread i_unread_address_fifo (.d_i(|{empty_address, address_queue_usage}));
  unread i_unread_branch_mask (.d_i(|branch_mask_extended));
  unread i_unread_lzc (.d_i(|{branch_empty}));
  unread i_unread_fifo_pos (.d_i(|fifo_pos_extended));
  unread i_unread_instr_fifo (.d_i(|instr_queue_usage));

  always_ff @(posedge clk_i or negedge rst_ni) begin
    if (!rst_ni) begin
      idx_ds_q        <= 'b1;
      idx_is_q        <= '0;
      pc_q            <= '0;
      reset_address_q <= 1'b1;
    end else begin
      pc_q            <= pc_d;
      reset_address_q <= reset_address_d;
      if (flush_i) begin

          idx_ds_q        <= 'b1;

          idx_is_q        <= '0;
          reset_address_q <= 1'b1;
      end else begin
          idx_ds_q        <= idx_ds_d;
          idx_is_q        <= idx_is_d;
      end
    end
  end


  `ifndef VERILATOR
      replay_address_fifo: assert property (
        @(posedge clk_i) disable iff (!rst_ni) replay_o |-> !i_fifo_address.push_i
      ) else $fatal(1,"[instr_queue] Pushing address although replay asserted");

      output_select_onehot: assert property (
        @(posedge clk_i) $onehot0(idx_ds_q)
      ) else begin $error("Output select should be one-hot encoded"); $stop(); end
  `endif

endmodule