// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
//
module tb;
  // dep packages (test)
  import uvm_pkg::*;
  import dv_utils_pkg::*;
  import mem_bkdr_util_pkg::mem_bkdr_util;
  import otbn_env_pkg::*;
  import otbn_test_pkg::*;
  import otbn_pkg::NGpr, otbn_pkg::NWdr;

  // dep packages (rtl)
  import otbn_reg_pkg::*;
  import edn_pkg::*;
  import otp_ctrl_pkg::*;
  import keymgr_pkg::*;

  // macro includes
  `include "uvm_macros.svh"
  `include "dv_macros.svh"

  wire clk, rst_n;
  wire intr_done;
  wire [NUM_MAX_INTERRUPTS-1:0] interrupts;

  // interfaces
  clk_rst_if                    clk_rst_if  (.clk(clk), .rst_n(rst_n));
  tl_if                         tl_if       (.clk(clk), .rst_n(rst_n));
  otbn_escalate_if              escalate_if (.clk_i (clk), .rst_ni (rst_n));
  pins_if #(NUM_MAX_INTERRUPTS) intr_if     (interrupts);
  assign interrupts[0] = {intr_done};

  otbn_key_req_t sideload_key;
  key_sideload_if#(keymgr_pkg::otbn_key_req_t) keymgr_if (
    .clk_i        (clk),
    .rst_ni       (rst_n),
    .sideload_key (sideload_key)
  );

  otbn_model_if #(
    .ImemSizeByte (ImemSizeByte)
  ) model_if (
    .clk_i         (clk),
    .rst_ni        (rst_n),
    .keymgr_key_i  (sideload_key)
  );

  // OTP Interface related connections
  localparam logic [127:0] TestScrambleKey = 128'h48ecf6c738f0f108a5b08620695ffd4d;
  localparam logic [63:0]  TestScrambleNonce = 64'hf88c2578fa4cd123;

  otbn_otp_key_req_t otp_key_req;
  otbn_otp_key_rsp_t otp_key_rsp;

  otp_ctrl_pkg::otbn_key_t   key;
  otp_ctrl_pkg::otbn_nonce_t nonce;
  wire seed_valid;

  wire otp_rst_n = rst_n;
  wire otp_clk;

  clk_rst_if otp_clk_rst_if(.clk(otp_clk), .rst_n(otp_rst_n));

  // Initiate push pull interface for the OTP<->OTBN connections
  push_pull_if #(
    .DeviceDataWidth(KEY_RSP_DATA_SIZE)
  ) otp_key_if (
    .clk(otp_clk),
    .rst_n(otp_rst_n)
  );

  // OTP Key interface assignments
  assign otp_key_if.req         = otp_key_req.req;
  assign otp_key_rsp.ack        = otp_key_if.ack;
  assign otp_key_rsp.key        = key;
  assign otp_key_rsp.nonce      = nonce;
  assign otp_key_rsp.seed_valid = seed_valid;
  // key, nonce, seed_valid all driven by push_pull Device interface
  assign {key, nonce, seed_valid} = otp_key_if.d_data;

  // edn_clk, edn_rst_n and edn_if is defined and driven in below macro
  `DV_EDN_IF_CONNECT

  `DV_ALERT_IF_CONNECT()

  // dut
  otbn # (
    .RndCnstOtbnKey(TestScrambleKey),
    .RndCnstOtbnNonce(TestScrambleNonce)
  ) dut (
    .clk_i (clk),
    .rst_ni(rst_n),

    .tl_i(tl_if.h2d),
    .tl_o(tl_if.d2h),

    // Correct behaviour of the idle output is ensured by the bound-in otbn_idle_checker instance.
    .idle_o(),

    .intr_done_o(intr_done),

    .alert_rx_i(alert_rx),
    .alert_tx_o(alert_tx),

    .lc_escalate_en_i(escalate_if.enable),
    .lc_rma_req_i    (escalate_if.req),
    .lc_rma_ack_o    (escalate_if.ack),

    .ram_cfg_i('0),

    .clk_edn_i (edn_clk),
    .rst_edn_ni(edn_rst_n),

    .edn_rnd_o (edn_if[RndEdnIdx].req),
    .edn_rnd_i ({edn_if[RndEdnIdx].ack, edn_if[RndEdnIdx].d_data}),

    .edn_urnd_o(edn_if[UrndEdnIdx].req),
    .edn_urnd_i({edn_if[UrndEdnIdx].ack, edn_if[UrndEdnIdx].d_data}),

    .clk_otp_i     (otp_clk),
    .rst_otp_ni    (otp_rst_n),
    .otbn_otp_key_o(otp_key_req),
    .otbn_otp_key_i(otp_key_rsp),

    .keymgr_key_i(sideload_key)
  );

  bind dut.u_otbn_core otbn_trace_if #(
    .ImemAddrWidth (ImemAddrWidth),
    .DmemAddrWidth (DmemAddrWidth)
  ) i_otbn_trace_if (.*);

  assign dut.u_otbn_core.i_otbn_trace_if.scramble_state_err_i = dut.otbn_scramble_state_error;
  assign dut.u_otbn_core.i_otbn_trace_if.ext_mubi_err_i = dut.mubi_err;
  assign dut.u_otbn_core.i_otbn_trace_if.missed_gnt_i.imem_gnt_missed_err = dut.imem_missed_gnt;
  assign dut.u_otbn_core.i_otbn_trace_if.missed_gnt_i.dmem_gnt_missed_err = dut.dmem_missed_gnt;

  bind dut.u_otbn_core otbn_tracer u_otbn_tracer(.*, .otbn_trace(i_otbn_trace_if));

  bind dut.u_otbn_core.u_otbn_controller.u_otbn_loop_controller
    otbn_loop_if i_otbn_loop_if (
      .clk_i,
      .rst_ni,
      // The insn_addr_i signal in the loop controller is of width ImemAddrWidth. We expand it to a
      // 32-bit address here to avoid having to parameterise the type of the interface.
      .insn_addr_i (32'(insn_addr_i)),
      .at_current_loop_end_insn,
      .current_loop_valid,
      .loop_stack_full,
      .current_loop_finish,
      .next_loop_valid,
      .loop_start_req_i,
      .loop_start_commit_i,
      .loop_iterations_i,
      .otbn_stall_i,

      // These addresses are start/end addresses for entries in the loop stack. As with insn_addr_i,
      // we expand them to 32 bits. Also the loop stack entries have a type that's not exposed
      // outside of the loop controller module so we need to extract the fields here.
      .current_loop_start (32'(current_loop.loop_addr_info.loop_start)),
      .current_loop_end   (32'(current_loop.loop_addr_info.loop_end)),
      .next_loop_end      (32'(prefetch_loop_end_addr_o)),

      // These counts are used by the loop warping code.
      .current_loop_d_iterations (prefetch_loop_iterations_o),
      .current_loop_q_iterations (current_loop.loop_iterations),

      .loop_stack_rd_idx
    );

  bind dut.u_otbn_core.u_otbn_alu_bignum otbn_alu_bignum_if i_otbn_alu_bignum_if (.*);
  bind dut.u_otbn_core.u_otbn_controller otbn_controller_if i_otbn_controller_if (.*);
  bind dut.u_otbn_core.u_otbn_mac_bignum otbn_mac_bignum_if i_otbn_mac_bignum_if (.*);
  bind dut.u_otbn_core.u_otbn_rf_base otbn_rf_base_if i_otbn_rf_base_if (.*);

  bind dut.u_otbn_core.u_otbn_rnd otbn_rnd_if i_otbn_rnd_if (.*);

  // OTBN model, wrapping an ISS.
  //
  // Note that we pull the "start" signal out of the DUT. This is because it's much more difficult
  // to grab the decoded signal from TL transactions on the cycle it happens. We have an explicit
  // check in the scoreboard to ensure that this gets asserted at the time we expect (to spot any
  // decoding errors).
  assign model_if.cmd_q = dut.reg2hw.cmd.q;
  assign model_if.cmd_qe = dut.reg2hw.cmd.qe;

  // Valid signals below are set when DUT finishes processing incoming 32b packages and constructs
  // 256b EDN data. Model checks if the processing of the packages are done in maximum of 5 cycles
  logic edn_rnd_cdc_done, edn_rnd_req_model;
  logic edn_urnd_cdc_done, edn_urnd_req_model;
  logic otp_key_cdc_done;

  assign edn_rnd_cdc_done = dut.edn_rnd_req & dut.edn_rnd_ack;
  assign edn_urnd_cdc_done = dut.edn_urnd_req & dut.edn_urnd_ack;
  assign otp_key_cdc_done = dut.u_otbn_scramble_ctrl.otp_key_ack;

  bit [31:0] model_insn_cnt;

  otbn_core_model #(
    .MemScope     ("..dut"),
    .DesignScope  ("..dut.u_otbn_core")
  ) u_model (
    .clk_i     (model_if.clk_i),
    .clk_edn_i (edn_clk),
    .rst_ni    (model_if.rst_ni),
    .rst_edn_ni(edn_rst_n),

    .cmd_i   (model_if.cmd_q),
    .cmd_en_i(model_if.cmd_qe),

    .lc_escalate_en_i(escalate_if.enable),
    .lc_rma_req_i    (escalate_if.req),

    .err_bits_o(model_if.err_bits),

    .edn_rnd_i         ({edn_if[RndEdnIdx].ack, edn_if[RndEdnIdx].d_data}),
    .edn_rnd_o         (edn_rnd_req_model),
    .edn_rnd_cdc_done_i(edn_rnd_cdc_done),

    .edn_urnd_i         ({edn_if[UrndEdnIdx].ack, edn_if[UrndEdnIdx].d_data}),
    .edn_urnd_o         (edn_urnd_req_model),
    .edn_urnd_cdc_done_i(edn_urnd_cdc_done),

    .init_sec_wipe_done_i(dut.u_otbn_core.i_otbn_trace_if.initial_secure_wipe_done),

    .otp_key_cdc_done_i(otp_key_cdc_done),

    .status_o  (model_if.status),
    .insn_cnt_o(model_insn_cnt),

    .done_rr_o(),

    .err_o(model_if.err),

    .keymgr_key_i(model_if.keymgr_key_i)
  );

  // Pull the final PC and the OtbnModel handle out of the SV model wrapper.
  assign model_if.stop_pc = u_model.stop_pc_q;
  // The always_ff is because the spec doesn't allow continuous assignments for chandles. The value
  // is populated in an init block and we'll only read this when the start signal is asserted, which
  // will be much more than 1 cycle later, so we shouldn't need to worry about a stale value.
  always_ff @(posedge model_if.clk_i) begin
    model_if.handle <= u_model.model_handle;
  end

  otbn_insn_cnt_if insn_cnt_if (
   .clk_i            (clk),
   .rst_ni           (rst_n),

   .insn_cnt_i       (dut.insn_cnt),
   .insn_executing_i (dut.u_otbn_core.u_otbn_controller.insn_executing),
   .stall_i          (dut.u_otbn_core.u_otbn_controller.stall),

   .model_insn_cnt_i (model_insn_cnt)
  );

  //////////////////////////////////////////////////////////////////////////////
  // Model/RTL consistency checks
  //
  // These are the sort of checks that are easier to state at the design level than in terms of UVM
  // transactions.

  // Check that the status output from the model exactly matches the register from the dut. In
  // theory, we could see mismatches by probing the STATUS register over the TL bus, but we have to
  // be lucky with exactly when the reads happen if we want to see off-by-one cycle errors. This
  // assertion gives a continuous check.
  `ASSERT(MatchingStatus_A, dut.u_reg.u_status.q == model_if.status, clk, !rst_n)

  // Check that if the modelled EDN requests are matching with the requests from DUT
  `ASSERT(MatchingReqRND_A, dut.u_otbn_core.edn_rnd_req_o == edn_rnd_req_model, clk, !rst_n)
  // Disable checking URND in the case of Locked status since it's modelling is not exactly accurate
  // for that state.
  // TODO (#15710): Fix modelling of URND in the locked state.
  `ASSERT(MatchingReqURND_A, dut.u_otbn_core.edn_urnd_req_o == edn_urnd_req_model,
    clk, !rst_n || model_if.status == otbn_pkg::StatusLocked)

  initial begin
    mem_bkdr_util imem_util, dmem_util;

    // drive clk and rst_n from clk_if
    clk_rst_if.set_active();
    otp_clk_rst_if.set_active(.drive_rst_n_val(1'b0));

    uvm_config_db#(virtual clk_rst_if)::set(null, "*.env", "otp_clk_rst_vif", otp_clk_rst_if);
    uvm_config_db#(virtual clk_rst_if)::set(null, "*.env", "clk_rst_vif", clk_rst_if);
    uvm_config_db#(virtual tl_if)::set(null, "*.env.m_tl_agent*", "vif", tl_if);
    uvm_config_db#(escalate_vif)::set(null, "*.env", "escalate_vif", escalate_if);
    uvm_config_db#(intr_vif)::set(null, "*.env", "intr_vif", intr_if);
    uvm_config_db#(virtual otbn_model_if)::set(null, "*.env.model_agent", "vif", model_if);
    uvm_config_db#(virtual key_sideload_if#(keymgr_pkg::otbn_key_req_t))::set(
      null, "*.env.keymgr_sideload_agent", "vif", keymgr_if);

    uvm_config_db#(otp_key_vif)::set(
      null, "*.env.key_agent*", "vif", otp_key_if);

    uvm_config_db#(virtual otbn_trace_if)::set(null, "*.env", "trace_vif",
                                               dut.u_otbn_core.i_otbn_trace_if);
    uvm_config_db#(virtual otbn_loop_if)::set(
      null, "*.env", "loop_vif",
      dut.u_otbn_core.u_otbn_controller.u_otbn_loop_controller.i_otbn_loop_if);
    uvm_config_db#(virtual otbn_alu_bignum_if)::set(
      null, "*.env", "alu_bignum_vif",
      dut.u_otbn_core.u_otbn_alu_bignum.i_otbn_alu_bignum_if);
    uvm_config_db#(virtual otbn_controller_if)::set(
      null, "*.env", "controller_vif",
      dut.u_otbn_core.u_otbn_controller.i_otbn_controller_if);
    uvm_config_db#(virtual otbn_mac_bignum_if)::set(
      null, "*.env", "mac_bignum_vif",
      dut.u_otbn_core.u_otbn_mac_bignum.i_otbn_mac_bignum_if);
    uvm_config_db#(virtual otbn_rf_base_if)::set(
      null, "*.env", "rf_base_vif",
      dut.u_otbn_core.u_otbn_rf_base.i_otbn_rf_base_if);
    uvm_config_db#(virtual otbn_rnd_if)::set(
      null, "*.env", "rnd_vif",
      dut.u_otbn_core.u_otbn_rnd.i_otbn_rnd_if);

    // Instantiate mem_bkdr_util objects to allow access to IMEM and DMEM
    //
    // Note that n_bits is the number of bits in the memory, including ECC check bits.
    imem_util = new(.name ("imem_util"),
                    .path ({"tb.dut.u_imem.u_prim_ram_1p_adv.",
                            "u_mem.gen_generic.u_impl_generic.mem"}),
                    .depth (ImemSizeByte / 4),
                    .n_bits (ImemSizeByte / 4 * 39),
                    .err_detection_scheme (mem_bkdr_util_pkg::EccInv_39_32));

    // DMEM is twice as big as the bus-accessible part
    dmem_util = new(.name ("dmem_util"),
                    .path ({"tb.dut.u_dmem.u_prim_ram_1p_adv.",
                            "u_mem.gen_generic.u_impl_generic.mem"}),
                    .depth (DmemSizeByte / 32),
                    .n_bits (DmemSizeByte / 32 * 312),
                    .err_detection_scheme (mem_bkdr_util_pkg::EccInv_39_32));

    uvm_config_db#(mem_bkdr_util)::set(null, "*.env", imem_util.get_name(), imem_util);
    uvm_config_db#(mem_bkdr_util)::set(null, "*.env", dmem_util.get_name(), dmem_util);

    $timeformat(-12, 0, " ps", 12);
    run_test();
  end

  // Assertion controls for turning them on/off easily

  // A hook to allow sequences to enable or disable the MatchingStatus_A assertion below. This is
  // needed for sequences that trigger alerts (locking OTBN) without telling the model.
  `DV_ASSERT_CTRL("otbn_status_assert_en", tb.MatchingStatus_A)

  // We need to turn off DMEM related assertions in the tests where we force internals of DMEM to generate errors
  `DV_ASSERT_CTRL("DMemAsserts", tb.dut.u_otbn_core.u_otbn_lsu.DMemRValidAfterReq)
  `DV_ASSERT_CTRL("DMemAsserts", tb.dut.u_otbn_core.OnlyWriteLoadDataBaseWhenDMemValid_A)
  `DV_ASSERT_CTRL("DMemAsserts", tb.dut.u_otbn_core.OnlyWriteLoadDataBignumWhenDMemValid_A)

endmodule
