// Copyright 2023 Google LLC
// Copyright lowRISC contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// clang-format off

${gencmd}
<%
## list renode unsupported peripherals
unsupported_peripherals = [
  "adc_ctrl", "clkmgr", "edn", "entropy_src", "keymgr", "pattgen",
  "pinmux", "pwm", "rv_core_ibex", "rv_plic", "sensor_ctrl", "spi_device",
  "sram_ctrl", "sysrst_ctrl", "usbdev"
]
unsupported_smc_peripherals = [
  "rv_core_ibex_smc", "rv_plic_smc", "rv_timer_smc", "rv_timer_smc2"
]
alert_peripheral_names = sorted({p.name for p in helper.alert_peripherals if p.inst_name not in unsupported_smc_peripherals})
%>\
#include "sw/device/lib/base/mmio.h"
% for n in sorted(alert_peripheral_names + ["alert_handler"]):
#include "sw/device/lib/dif/dif_${n}.h"
% endfor
#include "sw/device/lib/testing/alert_handler_testutils.h"
#include "sw/device/lib/testing/test_framework/FreeRTOSConfig.h"
#include "sw/device/lib/testing/test_framework/check.h"
#include "sw/device/lib/testing/test_framework/ottf_test_config.h"

#include "alert_handler_regs.h"  // Generated.
#include "hw/top_matcha/sw/autogen/top_matcha.h"

OTTF_DEFINE_TEST_CONFIG();

static dif_alert_handler_t alert_handler;
% for p in helper.alert_peripherals:
% if p.inst_name not in unsupported_smc_peripherals:
static dif_${p.name}_t ${p.inst_name};
% endif
% endfor

/**
 * Initialize the peripherals used in this test.
 */
static void init_peripherals(void) {
  mmio_region_t base_addr;
  base_addr = mmio_region_from_addr(TOP_MATCHA_ALERT_HANDLER_BASE_ADDR);
  CHECK_DIF_OK(dif_alert_handler_init(base_addr, &alert_handler));

  % for p in helper.alert_peripherals:
  % if p.inst_name not in unsupported_smc_peripherals:
  base_addr = mmio_region_from_addr(${p.base_addr_name});
  CHECK_DIF_OK(dif_${p.name}_init(base_addr, &${p.inst_name}));

  % endif
  % endfor
}

/**
 * Configure the alert handler to escalate on alerts upto phase 1 (i.e. wipe
 * secret) but not trigger reset. Then CPU can check if alert_handler triggers the correct
 * alert_cause register.
 */
static void alert_handler_config(void) {
  dif_alert_handler_alert_t alerts[ALERT_HANDLER_PARAM_N_ALERTS];
  dif_alert_handler_class_t alert_classes[ALERT_HANDLER_PARAM_N_ALERTS];

  // Enable all incoming alerts and configure them to classa.
  // This alert should never fire because we do not expect any incoming alerts.
  for (int i = 0; i < ALERT_HANDLER_PARAM_N_ALERTS; ++i) {
    alerts[i] = i;
    alert_classes[i] = kDifAlertHandlerClassA;
  }

  dif_alert_handler_escalation_phase_t esc_phases[] = {
      {.phase = kDifAlertHandlerClassStatePhase0,
       .signal = 0,
       .duration_cycles = 2000}};

  dif_alert_handler_class_config_t class_config = {
      .auto_lock_accumulation_counter = kDifToggleDisabled,
      .accumulator_threshold = 0,
      .irq_deadline_cycles = 10000,
      .escalation_phases = esc_phases,
      .escalation_phases_len = ARRAYSIZE(esc_phases),
      .crashdump_escalation_phase = kDifAlertHandlerClassStatePhase1,
  };

  dif_alert_handler_class_config_t class_configs[] = {class_config,
                                                      class_config};

  dif_alert_handler_class_t classes[] = {kDifAlertHandlerClassA,
                                         kDifAlertHandlerClassB};
  dif_alert_handler_config_t config = {
      .alerts = alerts,
      .alert_classes = alert_classes,
      .alerts_len = ARRAYSIZE(alerts),
      .classes = classes,
      .class_configs = class_configs,
      .classes_len = ARRAYSIZE(class_configs),
      .ping_timeout = 1000,
  };

  alert_handler_testutils_configure_all(&alert_handler, config,
                                        kDifToggleEnabled);
}

// Trigger alert for each module by writing one to `alert_test` register.
// Then check alert_handler's alert_cause register to make sure the correct alert reaches
// alert_handler.
static void trigger_alert_test(void) {
  bool is_cause;
  dif_alert_handler_alert_t exp_alert;
  % for p in helper.alert_peripherals:
  % if p.inst_name not in unsupported_smc_peripherals:

  % if p.name in unsupported_peripherals:
#ifndef DISABLE_RENODE_TEST
  % endif
  // Write ${p.name}'s alert_test reg and check alert_cause.
  for (int i = 0; i < ${p.num_alerts}; ++i) {
    CHECK_DIF_OK(dif_${p.name}_alert_force(&${p.inst_name}, ${p.dif_alert_name} + i));

    // Verify that alert handler received it.
    exp_alert = ${p.top_alert_name} + i;
    CHECK_DIF_OK(dif_alert_handler_alert_is_cause(
        &alert_handler, exp_alert, &is_cause));
    CHECK(is_cause, "Expect alert %d!", exp_alert);

    // Clear alert cause register
    CHECK_DIF_OK(dif_alert_handler_alert_acknowledge(
        &alert_handler, exp_alert));
  }
  % if p.name in unsupported_peripherals:
#endif
  % endif
  % endif
  % endfor
}

bool test_main(void) {
  init_peripherals();
  alert_handler_config();
  trigger_alert_test();
  return true;
}
