data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/frontend.sv
1: b"%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/frontend.sv:18: syntax error, unexpected IDENTIFIER, expecting PACKAGE-IDENTIFIER\nmodule frontend import ariane_pkg::*; #(\n                       ^~~~~~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/frontend.sv:22: 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/frontend/frontend.sv:23: 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/frontend/frontend.sv:24: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  logic               flush_bp_i,          \n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/frontend.sv:25: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  logic               debug_mode_i,\n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/frontend.sv:27: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  logic [riscv::VLEN-1:0]        boot_addr_i,\n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/frontend.sv:27: syntax error, unexpected ::, expecting ':'\n  input  logic [riscv::VLEN-1:0]        boot_addr_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/frontend/frontend.sv:33: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  logic [riscv::VLEN-1:0] pc_commit_i,         \n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/frontend.sv:33: syntax error, unexpected ::, expecting ':'\n  input  logic [riscv::VLEN-1:0] pc_commit_i,         \n                     ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/frontend.sv:35: syntax error, unexpected ::, expecting ':'\n  input  logic [riscv::VLEN-1:0] epc_i,               \n                     ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/frontend.sv:37: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  logic [riscv::VLEN-1:0] trap_vector_base_i,  \n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/frontend.sv:37: syntax error, unexpected ::, expecting ':'\n  input  logic [riscv::VLEN-1:0] trap_vector_base_i,  \n                     ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/frontend.sv:39: syntax error, unexpected input, expecting IDENTIFIER or '=' or do or final\n  input  logic               set_debug_pc_i,      \n  ^~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/frontend.sv:41: syntax error, unexpected output, expecting IDENTIFIER or '=' or do or final\n  output icache_dreq_i_t     icache_dreq_o,\n  ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/frontend.sv:46: 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/frontend.sv:51: syntax error, unexpected IDENTIFIER\n    ariane_pkg::frontend_exception_t icache_ex_valid_q;\n    ^~~~~~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/frontend.sv:52: syntax error, unexpected ::, expecting ':'\n    logic [riscv::VLEN-1:0] icache_vaddr_q;\n                ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/frontend.sv:54: syntax error, unexpected ::, expecting ':'\n    logic [ariane_pkg::INSTR_PER_FETCH-1:0] instr_queue_consumed;\n                     ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/frontend.sv:60: syntax error, unexpected ::, expecting ':'\n    logic [riscv::VLEN-1:0] npc_d, npc_q;  \n                ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/frontend.sv:66: syntax error, unexpected ::, expecting ':'\n    logic [riscv::VLEN-1:0] replay_addr;\n                ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/frontend.sv:69: 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/frontend.sv:79: syntax error, unexpected ::, expecting ':'\n    logic [INSTR_PER_FETCH-1:0][riscv::VLEN-1:0] rvi_imm;\n                                     ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/frontend.sv:83: syntax error, unexpected ::, expecting ':'\n    logic [INSTR_PER_FETCH-1:0][riscv::VLEN-1:0] rvc_imm;\n                                     ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/frontend.sv:86: syntax error, unexpected ::, expecting ':'\n    logic [INSTR_PER_FETCH-1:0][riscv::VLEN-1:0] addr;\n                                     ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/frontend.sv:89: syntax error, unexpected IDENTIFIER\n    bht_prediction_t [INSTR_PER_FETCH-1:0] bht_prediction;\n    ^~~~~~~~~~~~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/frontend.sv:98: syntax error, unexpected ::, expecting ':'\n    logic [riscv::VLEN-1:0]     ras_update;\n                ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/frontend.sv:101: syntax error, unexpected ::, expecting ':'\n    logic [riscv::VLEN-1:0]                 predict_address;\n                ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/frontend.sv:103: syntax error, unexpected ::, expecting ':'\n    logic [ariane_pkg::INSTR_PER_FETCH-1:0] taken_rvi_cf;\n                     ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/frontend.sv:104: syntax error, unexpected ::, expecting ':'\n    logic [ariane_pkg::INSTR_PER_FETCH-1:0] taken_rvc_cf;\n                     ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/frontend.sv:108: syntax error, unexpected IDENTIFIER\n    instr_realign i_instr_realign (\n    ^~~~~~~~~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/frontend.sv:144: syntax error, unexpected for\n    for (genvar i = 0; i < INSTR_PER_FETCH; i++) begin\n    ^~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/frontend.sv:163: syntax error, unexpected IDENTIFIER\n      for (int i = 0; i < INSTR_PER_FETCH; i++)  cf_type[i] = ariane_pkg::NoCF;\n                      ^\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/frontend.sv:170: syntax error, unexpected IDENTIFIER\n      for (int i = INSTR_PER_FETCH - 1; i >= 0 ; i--) begin\n                                        ^\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/frontend.sv:235: syntax error, unexpected IDENTIFIER\n      for (int i = 0; i < INSTR_PER_FETCH; i++) bp_valid |= ((cf_type[i] != NoCF & cf_type[i] != Return) | ((cf_type[i] == Return) & ras_predict.valid));\n                      ^\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/frontend.sv:257: syntax error, unexpected assign\n    assign speculative_d = (speculative_q && !resolved_branch_i.valid || |is_branch || |is_return || |is_jalr) && !flush_i;\n    ^~~~~~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/frontend.sv:284: syntax error, unexpected ::, expecting ':'\n      automatic logic [riscv::VLEN-1:0] fetch_address;\n                            ^~\n%Error: data/full_repos/permissive/509468557/generators/cva6/src/main/resources/vsrc/cva6/src/frontend/frontend.sv:330: syntax error, unexpected assign\n    assign icache_data = icache_dreq_i.data >> {shamt, 4'b0};\n    ^~~~~~\n%Error: Exiting due to 37 error(s)\n"
module frontend import ariane_pkg::*; #(
  parameter ariane_pkg::ariane_cfg_t ArianeCfg = ariane_pkg::ArianeDefaultConfig
) (
  input  logic               clk_i,
  input  logic               rst_ni,
  input  logic               flush_i,
  input  logic               flush_bp_i,
  input  logic               debug_mode_i,

  input  logic [riscv::VLEN-1:0]        boot_addr_i,


  input  bp_resolve_t        resolved_branch_i,

  input  logic               set_pc_commit_i,
  input  logic [riscv::VLEN-1:0] pc_commit_i,

  input  logic [riscv::VLEN-1:0] epc_i,
  input  logic               eret_i,
  input  logic [riscv::VLEN-1:0] trap_vector_base_i,
  input  logic               ex_valid_i,
  input  logic               set_debug_pc_i,

  output icache_dreq_i_t     icache_dreq_o,
  input  icache_dreq_o_t     icache_dreq_i,

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

    logic [FETCH_WIDTH-1:0] icache_data_q;
    logic                   icache_valid_q;
    ariane_pkg::frontend_exception_t icache_ex_valid_q;
    logic [riscv::VLEN-1:0] icache_vaddr_q;
    logic                   instr_queue_ready;
    logic [ariane_pkg::INSTR_PER_FETCH-1:0] instr_queue_consumed;

    btb_prediction_t        btb_q;
    bht_prediction_t        bht_q;

    logic                   if_ready;
    logic [riscv::VLEN-1:0] npc_d, npc_q;


    logic                   npc_rst_load_q;

    logic                   replay;
    logic [riscv::VLEN-1:0] replay_addr;


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

    assign shamt = icache_dreq_i.vaddr[$clog2(ariane_pkg::INSTR_PER_FETCH):1];





    logic [INSTR_PER_FETCH-1:0]       rvi_return, rvi_call, rvi_branch,
                                      rvi_jalr, rvi_jump;
    logic [INSTR_PER_FETCH-1:0][riscv::VLEN-1:0] rvi_imm;

    logic [INSTR_PER_FETCH-1:0]       rvc_branch, rvc_jump, rvc_jr, rvc_return,
                                      rvc_jalr, rvc_call;
    logic [INSTR_PER_FETCH-1:0][riscv::VLEN-1:0] rvc_imm;

    logic [INSTR_PER_FETCH-1:0][31:0] instr;
    logic [INSTR_PER_FETCH-1:0][riscv::VLEN-1:0] addr;
    logic [INSTR_PER_FETCH-1:0]       instruction_valid;

    bht_prediction_t [INSTR_PER_FETCH-1:0] bht_prediction;
    btb_prediction_t [INSTR_PER_FETCH-1:0] btb_prediction;
    bht_prediction_t [INSTR_PER_FETCH-1:0] bht_prediction_shifted;
    btb_prediction_t [INSTR_PER_FETCH-1:0] btb_prediction_shifted;
    ras_t            ras_predict;


    logic            is_mispredict;
    logic            ras_push, ras_pop;
    logic [riscv::VLEN-1:0]     ras_update;


    logic [riscv::VLEN-1:0]                 predict_address;
    cf_t  [ariane_pkg::INSTR_PER_FETCH-1:0] cf_type;
    logic [ariane_pkg::INSTR_PER_FETCH-1:0] taken_rvi_cf;
    logic [ariane_pkg::INSTR_PER_FETCH-1:0] taken_rvc_cf;

    logic serving_unaligned;

    instr_realign i_instr_realign (
      .clk_i               ( clk_i                 ),
      .rst_ni              ( rst_ni                ),
      .flush_i             ( icache_dreq_o.kill_s2 ),
      .valid_i             ( icache_valid_q        ),
      .serving_unaligned_o ( serving_unaligned     ),
      .address_i           ( icache_vaddr_q        ),
      .data_i              ( icache_data_q         ),
      .valid_o             ( instruction_valid     ),
      .addr_o              ( addr                  ),
      .instr_o             ( instr                 )
    );






    assign bht_prediction_shifted[0] = (serving_unaligned) ? bht_q : bht_prediction[0];
    assign btb_prediction_shifted[0] = (serving_unaligned) ? btb_q : btb_prediction[0];


    for (genvar i = 1; i < INSTR_PER_FETCH; i++) begin : gen_prediction_address
      assign bht_prediction_shifted[i] = bht_prediction[addr[i][$clog2(INSTR_PER_FETCH):1]];
      assign btb_prediction_shifted[i] = btb_prediction[addr[i][$clog2(INSTR_PER_FETCH):1]];
    end


    logic bp_valid;

    logic [INSTR_PER_FETCH-1:0] is_branch;
    logic [INSTR_PER_FETCH-1:0] is_call;
    logic [INSTR_PER_FETCH-1:0] is_jump;
    logic [INSTR_PER_FETCH-1:0] is_return;
    logic [INSTR_PER_FETCH-1:0] is_jalr;

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

      assign is_branch[i] =  instruction_valid[i] & (rvi_branch[i] | rvc_branch[i]);

      assign is_call[i] = instruction_valid[i] & (rvi_call[i] | rvc_call[i]);

      assign is_return[i] = instruction_valid[i] & (rvi_return[i] | rvc_return[i]);

      assign is_jump[i] = instruction_valid[i] & (rvi_jump[i] | rvc_jump[i]);

      assign is_jalr[i] = instruction_valid[i] & ~is_return[i] & ~is_call[i] & (rvi_jalr[i] | rvc_jalr[i] | rvc_jr[i]);
    end


    always_comb begin
      taken_rvi_cf = '0;
      taken_rvc_cf = '0;
      predict_address = '0;

      for (int i = 0; i < INSTR_PER_FETCH; i++)  cf_type[i] = ariane_pkg::NoCF;

      ras_push = 1'b0;
      ras_pop = 1'b0;
      ras_update = '0;


      for (int i = INSTR_PER_FETCH - 1; i >= 0 ; i--) begin
        unique case ({is_branch[i], is_return[i], is_jump[i], is_jalr[i]})
          4'b0000:;

          4'b0001: begin
            ras_pop = 1'b0;
            ras_push = 1'b0;
            if (btb_prediction_shifted[i].valid) begin
              predict_address = btb_prediction_shifted[i].target_address;
              cf_type[i] = ariane_pkg::JumpR;
            end
          end

          4'b0010: begin
            ras_pop = 1'b0;
            ras_push = 1'b0;
            taken_rvi_cf[i] = rvi_jump[i];
            taken_rvc_cf[i] = rvc_jump[i];
            cf_type[i] = ariane_pkg::Jump;
          end

          4'b0100: begin

            ras_pop = ras_predict.valid & instr_queue_consumed[i];
            ras_push = 1'b0;
            predict_address = ras_predict.ra;
            cf_type[i] = ariane_pkg::Return;
          end

          4'b1000: begin
            ras_pop = 1'b0;
            ras_push = 1'b0;

            if (bht_prediction_shifted[i].valid) begin
              taken_rvi_cf[i] = rvi_branch[i] & bht_prediction_shifted[i].taken;
              taken_rvc_cf[i] = rvc_branch[i] & bht_prediction_shifted[i].taken;

            end else begin

              taken_rvi_cf[i] = rvi_branch[i] & rvi_imm[i][riscv::VLEN-1];
              taken_rvc_cf[i] = rvc_branch[i] & rvc_imm[i][riscv::VLEN-1];
            end
            if (taken_rvi_cf[i] || taken_rvc_cf[i]) cf_type[i] = ariane_pkg::Branch;
          end
          default:;

        endcase


          if (is_call[i]) begin
            ras_push = instr_queue_consumed[i];
            ras_update = addr[i] + (rvc_call[i] ? 2 : 4);
          end

          if (taken_rvc_cf[i] || taken_rvi_cf[i]) begin
            predict_address = addr[i] + (taken_rvc_cf[i] ? rvc_imm[i] : rvi_imm[i]);
          end
      end
    end

    always_comb begin
      bp_valid = 1'b0;



      for (int i = 0; i < INSTR_PER_FETCH; i++) bp_valid |= ((cf_type[i] != NoCF & cf_type[i] != Return) | ((cf_type[i] == Return) & ras_predict.valid));
    end
    assign is_mispredict = resolved_branch_i.valid & resolved_branch_i.is_mispredict;


    assign icache_dreq_o.req = instr_queue_ready;
    assign if_ready = icache_dreq_i.ready & instr_queue_ready;




    assign icache_dreq_o.kill_s1 = is_mispredict | flush_i | replay;


    assign icache_dreq_o.kill_s2 = icache_dreq_o.kill_s1 | bp_valid;


    bht_update_t bht_update;
    btb_update_t btb_update;


    logic speculative_q,speculative_d;
    assign speculative_d = (speculative_q && !resolved_branch_i.valid || |is_branch || |is_return || |is_jalr) && !flush_i;
    assign icache_dreq_o.spec = speculative_d;

    assign bht_update.valid = resolved_branch_i.valid
                                & (resolved_branch_i.cf_type == ariane_pkg::Branch);
    assign bht_update.pc    = resolved_branch_i.pc;
    assign bht_update.taken = resolved_branch_i.is_taken;

    assign btb_update.valid = resolved_branch_i.valid
                                & resolved_branch_i.is_mispredict
                                & (resolved_branch_i.cf_type == ariane_pkg::JumpR);
    assign btb_update.pc    = resolved_branch_i.pc;
    assign btb_update.target_address = resolved_branch_i.target_address;













    always_comb begin : npc_select
      automatic logic [riscv::VLEN-1:0] fetch_address;






      if (npc_rst_load_q) begin
        npc_d         = boot_addr_i;
        fetch_address = boot_addr_i;
      end else begin
        fetch_address    = npc_q;

        npc_d            = npc_q;
      end

      if (bp_valid) begin
        fetch_address = predict_address;
        npc_d = predict_address;
      end

      if (if_ready) npc_d = {fetch_address[riscv::VLEN-1:2], 2'b0}  + 'h4;

      if (replay) npc_d = replay_addr;

      if (is_mispredict) npc_d = resolved_branch_i.target_address;

      if (eret_i) npc_d = epc_i;

      if (ex_valid_i) npc_d = trap_vector_base_i;







      if (set_pc_commit_i) npc_d = pc_commit_i + {{riscv::VLEN-3{1'b0}}, 3'b100};


      if (set_debug_pc_i) npc_d = ArianeCfg.DmBaseAddress[riscv::VLEN-1:0] + dm::HaltAddress[riscv::VLEN-1:0];
      icache_dreq_o.vaddr = fetch_address;
    end

    logic [FETCH_WIDTH-1:0] icache_data;

    assign icache_data = icache_dreq_i.data >> {shamt, 4'b0};

    always_ff @(posedge clk_i or negedge rst_ni) begin
      if (!rst_ni) begin
        npc_rst_load_q    <= 1'b1;
        npc_q             <= '0;
        speculative_q     <= '0;
        icache_data_q     <= '0;
        icache_valid_q    <= 1'b0;
        icache_vaddr_q    <= 'b0;
        icache_ex_valid_q <= ariane_pkg::FE_NONE;
        btb_q             <= '0;
        bht_q             <= '0;
      end else begin
        npc_rst_load_q    <= 1'b0;
        npc_q             <= npc_d;
        speculative_q    <= speculative_d;
        icache_valid_q    <= icache_dreq_i.valid;
        if (icache_dreq_i.valid) begin
          icache_data_q        <= icache_data;
          icache_vaddr_q       <= icache_dreq_i.vaddr;

          if (icache_dreq_i.ex.cause == riscv::INSTR_PAGE_FAULT) begin
            icache_ex_valid_q <= ariane_pkg::FE_INSTR_PAGE_FAULT;
          end else if (icache_dreq_i.ex.cause == riscv::INSTR_ACCESS_FAULT) begin
            icache_ex_valid_q <= ariane_pkg::FE_INSTR_ACCESS_FAULT;
          end else icache_ex_valid_q <= ariane_pkg::FE_NONE;

          btb_q                <= btb_prediction[INSTR_PER_FETCH-1];
          bht_q                <= bht_prediction[INSTR_PER_FETCH-1];
        end
      end
    end

    ras #(
      .DEPTH  ( ArianeCfg.RASDepth  )
    ) i_ras (
      .clk_i,
      .rst_ni,
      .flush_i( flush_bp_i  ),
      .push_i ( ras_push    ),
      .pop_i  ( ras_pop     ),
      .data_i ( ras_update  ),
      .data_o ( ras_predict )
    );

    btb #(
      .NR_ENTRIES       ( ArianeCfg.BTBEntries   )
    ) i_btb (
      .clk_i,
      .rst_ni,
      .flush_i          ( flush_bp_i       ),
      .debug_mode_i,
      .vpc_i            ( icache_vaddr_q   ),
      .btb_update_i     ( btb_update       ),
      .btb_prediction_o ( btb_prediction   )
    );

    bht #(
      .NR_ENTRIES       ( ArianeCfg.BHTEntries   )
    ) i_bht (
      .clk_i,
      .rst_ni,
      .flush_i          ( flush_bp_i       ),
      .debug_mode_i,
      .vpc_i            ( icache_vaddr_q   ),
      .bht_update_i     ( bht_update       ),
      .bht_prediction_o ( bht_prediction   )
    );



    for (genvar i = 0; i < INSTR_PER_FETCH; i++) begin : gen_instr_scan
      instr_scan i_instr_scan (
        .instr_i      ( instr[i]      ),
        .rvi_return_o ( rvi_return[i] ),
        .rvi_call_o   ( rvi_call[i]   ),
        .rvi_branch_o ( rvi_branch[i] ),
        .rvi_jalr_o   ( rvi_jalr[i]   ),
        .rvi_jump_o   ( rvi_jump[i]   ),
        .rvi_imm_o    ( rvi_imm[i]    ),
        .rvc_branch_o ( rvc_branch[i] ),
        .rvc_jump_o   ( rvc_jump[i]   ),
        .rvc_jr_o     ( rvc_jr[i]     ),
        .rvc_return_o ( rvc_return[i] ),
        .rvc_jalr_o   ( rvc_jalr[i]   ),
        .rvc_call_o   ( rvc_call[i]   ),
        .rvc_imm_o    ( rvc_imm[i]    )
      );
    end

    instr_queue i_instr_queue (
      .clk_i               ( clk_i                ),
      .rst_ni              ( rst_ni               ),
      .flush_i             ( flush_i              ),
      .instr_i             ( instr                ),
      .addr_i              ( addr                 ),
      .exception_i         ( icache_ex_valid_q    ),
      .exception_addr_i    ( icache_vaddr_q       ),
      .predict_address_i   ( predict_address      ),
      .cf_type_i           ( cf_type              ),
      .valid_i             ( instruction_valid    ),
      .consumed_o          ( instr_queue_consumed ),
      .ready_o             ( instr_queue_ready    ),
      .replay_o            ( replay               ),
      .replay_addr_o       ( replay_addr          ),
      .fetch_entry_o       ( fetch_entry_o        ),
      .fetch_entry_valid_o ( fetch_entry_valid_o  ),
      .fetch_entry_ready_i ( fetch_entry_ready_i  )
    );


    `ifndef VERILATOR
      initial begin
        assert (FETCH_WIDTH == 32 || FETCH_WIDTH == 64) else $fatal(1, "[frontend] fetch width != not supported");
      end
    `endif

endmodule
module frontend import ariane_pkg::*;
 #(
  parameter ariane_pkg::ariane_cfg_t ArianeCfg = ariane_pkg::ArianeDefaultConfig
) (
  input  logic               clk_i,
  input  logic               rst_ni,
  input  logic               flush_i,
  input  logic               flush_bp_i,
  input  logic               debug_mode_i,

  input  logic [riscv::VLEN-1:0]        boot_addr_i,


  input  bp_resolve_t        resolved_branch_i,

  input  logic               set_pc_commit_i,
  input  logic [riscv::VLEN-1:0] pc_commit_i,

  input  logic [riscv::VLEN-1:0] epc_i,
  input  logic               eret_i,
  input  logic [riscv::VLEN-1:0] trap_vector_base_i,
  input  logic               ex_valid_i,
  input  logic               set_debug_pc_i,

  output icache_dreq_i_t     icache_dreq_o,
  input  icache_dreq_o_t     icache_dreq_i,

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

    logic [FETCH_WIDTH-1:0] icache_data_q;
    logic                   icache_valid_q;
    ariane_pkg::frontend_exception_t icache_ex_valid_q;
    logic [riscv::VLEN-1:0] icache_vaddr_q;
    logic                   instr_queue_ready;
    logic [ariane_pkg::INSTR_PER_FETCH-1:0] instr_queue_consumed;

    btb_prediction_t        btb_q;
    bht_prediction_t        bht_q;

    logic                   if_ready;
    logic [riscv::VLEN-1:0] npc_d, npc_q;


    logic                   npc_rst_load_q;

    logic                   replay;
    logic [riscv::VLEN-1:0] replay_addr;


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

    assign shamt = icache_dreq_i.vaddr[$clog2(ariane_pkg::INSTR_PER_FETCH):1];





    logic [INSTR_PER_FETCH-1:0]       rvi_return, rvi_call, rvi_branch,
                                      rvi_jalr, rvi_jump;
    logic [INSTR_PER_FETCH-1:0][riscv::VLEN-1:0] rvi_imm;

    logic [INSTR_PER_FETCH-1:0]       rvc_branch, rvc_jump, rvc_jr, rvc_return,
                                      rvc_jalr, rvc_call;
    logic [INSTR_PER_FETCH-1:0][riscv::VLEN-1:0] rvc_imm;

    logic [INSTR_PER_FETCH-1:0][31:0] instr;
    logic [INSTR_PER_FETCH-1:0][riscv::VLEN-1:0] addr;
    logic [INSTR_PER_FETCH-1:0]       instruction_valid;

    bht_prediction_t [INSTR_PER_FETCH-1:0] bht_prediction;
    btb_prediction_t [INSTR_PER_FETCH-1:0] btb_prediction;
    bht_prediction_t [INSTR_PER_FETCH-1:0] bht_prediction_shifted;
    btb_prediction_t [INSTR_PER_FETCH-1:0] btb_prediction_shifted;
    ras_t            ras_predict;


    logic            is_mispredict;
    logic            ras_push, ras_pop;
    logic [riscv::VLEN-1:0]     ras_update;


    logic [riscv::VLEN-1:0]                 predict_address;
    cf_t  [ariane_pkg::INSTR_PER_FETCH-1:0] cf_type;
    logic [ariane_pkg::INSTR_PER_FETCH-1:0] taken_rvi_cf;
    logic [ariane_pkg::INSTR_PER_FETCH-1:0] taken_rvc_cf;

    logic serving_unaligned;

    instr_realign i_instr_realign (
      .clk_i               ( clk_i                 ),
      .rst_ni              ( rst_ni                ),
      .flush_i             ( icache_dreq_o.kill_s2 ),
      .valid_i             ( icache_valid_q        ),
      .serving_unaligned_o ( serving_unaligned     ),
      .address_i           ( icache_vaddr_q        ),
      .data_i              ( icache_data_q         ),
      .valid_o             ( instruction_valid     ),
      .addr_o              ( addr                  ),
      .instr_o             ( instr                 )
    );






    assign bht_prediction_shifted[0] = (serving_unaligned) ? bht_q : bht_prediction[0];
    assign btb_prediction_shifted[0] = (serving_unaligned) ? btb_q : btb_prediction[0];


    for (genvar i = 1; i < INSTR_PER_FETCH; i++) begin : gen_prediction_address
      assign bht_prediction_shifted[i] = bht_prediction[addr[i][$clog2(INSTR_PER_FETCH):1]];
      assign btb_prediction_shifted[i] = btb_prediction[addr[i][$clog2(INSTR_PER_FETCH):1]];
    end


    logic bp_valid;

    logic [INSTR_PER_FETCH-1:0] is_branch;
    logic [INSTR_PER_FETCH-1:0] is_call;
    logic [INSTR_PER_FETCH-1:0] is_jump;
    logic [INSTR_PER_FETCH-1:0] is_return;
    logic [INSTR_PER_FETCH-1:0] is_jalr;

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

      assign is_branch[i] =  instruction_valid[i] & (rvi_branch[i] | rvc_branch[i]);

      assign is_call[i] = instruction_valid[i] & (rvi_call[i] | rvc_call[i]);

      assign is_return[i] = instruction_valid[i] & (rvi_return[i] | rvc_return[i]);

      assign is_jump[i] = instruction_valid[i] & (rvi_jump[i] | rvc_jump[i]);

      assign is_jalr[i] = instruction_valid[i] & ~is_return[i] & ~is_call[i] & (rvi_jalr[i] | rvc_jalr[i] | rvc_jr[i]);
    end


    always_comb begin
      taken_rvi_cf = '0;
      taken_rvc_cf = '0;
      predict_address = '0;

      for (int i = 0; i < INSTR_PER_FETCH; i++)  cf_type[i] = ariane_pkg::NoCF;

      ras_push = 1'b0;
      ras_pop = 1'b0;
      ras_update = '0;


      for (int i = INSTR_PER_FETCH - 1; i >= 0 ; i--) begin
        unique case ({is_branch[i], is_return[i], is_jump[i], is_jalr[i]})
          4'b0000:;

          4'b0001: begin
            ras_pop = 1'b0;
            ras_push = 1'b0;
            if (btb_prediction_shifted[i].valid) begin
              predict_address = btb_prediction_shifted[i].target_address;
              cf_type[i] = ariane_pkg::JumpR;
            end
          end

          4'b0010: begin
            ras_pop = 1'b0;
            ras_push = 1'b0;
            taken_rvi_cf[i] = rvi_jump[i];
            taken_rvc_cf[i] = rvc_jump[i];
            cf_type[i] = ariane_pkg::Jump;
          end

          4'b0100: begin

            ras_pop = ras_predict.valid & instr_queue_consumed[i];
            ras_push = 1'b0;
            predict_address = ras_predict.ra;
            cf_type[i] = ariane_pkg::Return;
          end

          4'b1000: begin
            ras_pop = 1'b0;
            ras_push = 1'b0;

            if (bht_prediction_shifted[i].valid) begin
              taken_rvi_cf[i] = rvi_branch[i] & bht_prediction_shifted[i].taken;
              taken_rvc_cf[i] = rvc_branch[i] & bht_prediction_shifted[i].taken;

            end else begin

              taken_rvi_cf[i] = rvi_branch[i] & rvi_imm[i][riscv::VLEN-1];
              taken_rvc_cf[i] = rvc_branch[i] & rvc_imm[i][riscv::VLEN-1];
            end
            if (taken_rvi_cf[i] || taken_rvc_cf[i]) cf_type[i] = ariane_pkg::Branch;
          end
          default:;

        endcase


          if (is_call[i]) begin
            ras_push = instr_queue_consumed[i];
            ras_update = addr[i] + (rvc_call[i] ? 2 : 4);
          end

          if (taken_rvc_cf[i] || taken_rvi_cf[i]) begin
            predict_address = addr[i] + (taken_rvc_cf[i] ? rvc_imm[i] : rvi_imm[i]);
          end
      end
    end

    always_comb begin
      bp_valid = 1'b0;



      for (int i = 0; i < INSTR_PER_FETCH; i++) bp_valid |= ((cf_type[i] != NoCF & cf_type[i] != Return) | ((cf_type[i] == Return) & ras_predict.valid));
    end
    assign is_mispredict = resolved_branch_i.valid & resolved_branch_i.is_mispredict;


    assign icache_dreq_o.req = instr_queue_ready;
    assign if_ready = icache_dreq_i.ready & instr_queue_ready;




    assign icache_dreq_o.kill_s1 = is_mispredict | flush_i | replay;


    assign icache_dreq_o.kill_s2 = icache_dreq_o.kill_s1 | bp_valid;


    bht_update_t bht_update;
    btb_update_t btb_update;


    logic speculative_q,speculative_d;
    assign speculative_d = (speculative_q && !resolved_branch_i.valid || |is_branch || |is_return || |is_jalr) && !flush_i;
    assign icache_dreq_o.spec = speculative_d;

    assign bht_update.valid = resolved_branch_i.valid
                                & (resolved_branch_i.cf_type == ariane_pkg::Branch);
    assign bht_update.pc    = resolved_branch_i.pc;
    assign bht_update.taken = resolved_branch_i.is_taken;

    assign btb_update.valid = resolved_branch_i.valid
                                & resolved_branch_i.is_mispredict
                                & (resolved_branch_i.cf_type == ariane_pkg::JumpR);
    assign btb_update.pc    = resolved_branch_i.pc;
    assign btb_update.target_address = resolved_branch_i.target_address;













    always_comb begin : npc_select
      automatic logic [riscv::VLEN-1:0] fetch_address;






      if (npc_rst_load_q) begin
        npc_d         = boot_addr_i;
        fetch_address = boot_addr_i;
      end else begin
        fetch_address    = npc_q;

        npc_d            = npc_q;
      end

      if (bp_valid) begin
        fetch_address = predict_address;
        npc_d = predict_address;
      end

      if (if_ready) npc_d = {fetch_address[riscv::VLEN-1:2], 2'b0}  + 'h4;

      if (replay) npc_d = replay_addr;

      if (is_mispredict) npc_d = resolved_branch_i.target_address;

      if (eret_i) npc_d = epc_i;

      if (ex_valid_i) npc_d = trap_vector_base_i;







      if (set_pc_commit_i) npc_d = pc_commit_i + {{riscv::VLEN-3{1'b0}}, 3'b100};


      if (set_debug_pc_i) npc_d = ArianeCfg.DmBaseAddress[riscv::VLEN-1:0] + dm::HaltAddress[riscv::VLEN-1:0];
      icache_dreq_o.vaddr = fetch_address;
    end

    logic [FETCH_WIDTH-1:0] icache_data;

    assign icache_data = icache_dreq_i.data >> {shamt, 4'b0};

    always_ff @(posedge clk_i or negedge rst_ni) begin
      if (!rst_ni) begin
        npc_rst_load_q    <= 1'b1;
        npc_q             <= '0;
        speculative_q     <= '0;
        icache_data_q     <= '0;
        icache_valid_q    <= 1'b0;
        icache_vaddr_q    <= 'b0;
        icache_ex_valid_q <= ariane_pkg::FE_NONE;
        btb_q             <= '0;
        bht_q             <= '0;
      end else begin
        npc_rst_load_q    <= 1'b0;
        npc_q             <= npc_d;
        speculative_q    <= speculative_d;
        icache_valid_q    <= icache_dreq_i.valid;
        if (icache_dreq_i.valid) begin
          icache_data_q        <= icache_data;
          icache_vaddr_q       <= icache_dreq_i.vaddr;

          if (icache_dreq_i.ex.cause == riscv::INSTR_PAGE_FAULT) begin
            icache_ex_valid_q <= ariane_pkg::FE_INSTR_PAGE_FAULT;
          end else if (icache_dreq_i.ex.cause == riscv::INSTR_ACCESS_FAULT) begin
            icache_ex_valid_q <= ariane_pkg::FE_INSTR_ACCESS_FAULT;
          end else icache_ex_valid_q <= ariane_pkg::FE_NONE;

          btb_q                <= btb_prediction[INSTR_PER_FETCH-1];
          bht_q                <= bht_prediction[INSTR_PER_FETCH-1];
        end
      end
    end

    ras #(
      .DEPTH  ( ArianeCfg.RASDepth  )
    ) i_ras (
      .clk_i,
      .rst_ni,
      .flush_i( flush_bp_i  ),
      .push_i ( ras_push    ),
      .pop_i  ( ras_pop     ),
      .data_i ( ras_update  ),
      .data_o ( ras_predict )
    );

    btb #(
      .NR_ENTRIES       ( ArianeCfg.BTBEntries   )
    ) i_btb (
      .clk_i,
      .rst_ni,
      .flush_i          ( flush_bp_i       ),
      .debug_mode_i,
      .vpc_i            ( icache_vaddr_q   ),
      .btb_update_i     ( btb_update       ),
      .btb_prediction_o ( btb_prediction   )
    );

    bht #(
      .NR_ENTRIES       ( ArianeCfg.BHTEntries   )
    ) i_bht (
      .clk_i,
      .rst_ni,
      .flush_i          ( flush_bp_i       ),
      .debug_mode_i,
      .vpc_i            ( icache_vaddr_q   ),
      .bht_update_i     ( bht_update       ),
      .bht_prediction_o ( bht_prediction   )
    );



    for (genvar i = 0; i < INSTR_PER_FETCH; i++) begin : gen_instr_scan
      instr_scan i_instr_scan (
        .instr_i      ( instr[i]      ),
        .rvi_return_o ( rvi_return[i] ),
        .rvi_call_o   ( rvi_call[i]   ),
        .rvi_branch_o ( rvi_branch[i] ),
        .rvi_jalr_o   ( rvi_jalr[i]   ),
        .rvi_jump_o   ( rvi_jump[i]   ),
        .rvi_imm_o    ( rvi_imm[i]    ),
        .rvc_branch_o ( rvc_branch[i] ),
        .rvc_jump_o   ( rvc_jump[i]   ),
        .rvc_jr_o     ( rvc_jr[i]     ),
        .rvc_return_o ( rvc_return[i] ),
        .rvc_jalr_o   ( rvc_jalr[i]   ),
        .rvc_call_o   ( rvc_call[i]   ),
        .rvc_imm_o    ( rvc_imm[i]    )
      );
    end

    instr_queue i_instr_queue (
      .clk_i               ( clk_i                ),
      .rst_ni              ( rst_ni               ),
      .flush_i             ( flush_i              ),
      .instr_i             ( instr                ),
      .addr_i              ( addr                 ),
      .exception_i         ( icache_ex_valid_q    ),
      .exception_addr_i    ( icache_vaddr_q       ),
      .predict_address_i   ( predict_address      ),
      .cf_type_i           ( cf_type              ),
      .valid_i             ( instruction_valid    ),
      .consumed_o          ( instr_queue_consumed ),
      .ready_o             ( instr_queue_ready    ),
      .replay_o            ( replay               ),
      .replay_addr_o       ( replay_addr          ),
      .fetch_entry_o       ( fetch_entry_o        ),
      .fetch_entry_valid_o ( fetch_entry_valid_o  ),
      .fetch_entry_ready_i ( fetch_entry_ready_i  )
    );


    `ifndef VERILATOR
      initial begin
        assert (FETCH_WIDTH == 32 || FETCH_WIDTH == 64) else $fatal(1, "[frontend] fetch width != not supported");
      end
    `endif

endmodule