/*
 * 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.
 */


#include "hw/top_matcha/sw/autogen/top_matcha.h"
#include "sensor_ctrl_regs.h"  // Generated.
#include "sw/device/lib/base/abs_mmio.h"
#include "sw/device/lib/base/mmio.h"
#include "sw/device/lib/dif/dif_alert_handler.h"
#include "sw/device/lib/dif/dif_flash_ctrl.h"
#include "sw/device/lib/dif/dif_rstmgr.h"
#include "sw/device/lib/dif/dif_rv_plic.h"
#include "sw/device/lib/dif/dif_sensor_ctrl.h"
#include "sw/device/lib/runtime/ibex.h"
#include "sw/device/lib/runtime/irq.h"
#include "sw/device/lib/runtime/log.h"
#include "sw/device/lib/testing/flash_ctrl_testutils.h"
#include "sw/device/lib/testing/pwrmgr_testutils.h"
#include "sw/device/lib/testing/rand_testutils.h"
#include "sw/device/lib/testing/test_framework/check.h"
#include "sw/device/lib/testing/test_framework/ottf_main.h"

OTTF_DEFINE_TEST_CONFIG();

/**
 * This test checks that incoming ast events can be
 * configured as both recoverable and fatal.
 * Further, this test checks that recoverable and fatal
 * events are able to reach their proper alert_handler
 * destination.
 *
 * Since fatal events do not stop firing once asserted,
 * this test performs a self reset after every fatal
 * event.  In order to keep track of how far the test
 * has advanced, a non-volatile counter in flash is
 * used to track current progress.
 */
static dif_rstmgr_t rstmgr;
static dif_flash_ctrl_state_t flash_ctrl;
static dif_sensor_ctrl_t sensor_ctrl;
static dif_alert_handler_t alert_handler;

/**
 *  Clear event trigger and recoverable status.
 */
static void clear_event(uint32_t idx, dif_toggle_t fatal) {
  CHECK_DIF_OK(dif_sensor_ctrl_set_ast_event_trigger(&sensor_ctrl, idx,
                                                     kDifToggleDisabled));

  if (!dif_toggle_to_bool(fatal)) {
    CHECK_DIF_OK(dif_sensor_ctrl_clear_recov_event(&sensor_ctrl, idx));
  }
}

static uint32_t get_events(dif_toggle_t fatal) {
  dif_sensor_ctrl_events_t events = 0;
  if (dif_toggle_to_bool(fatal)) {
    CHECK_DIF_OK(dif_sensor_ctrl_get_fatal_events(&sensor_ctrl, &events));
  } else {
    CHECK_DIF_OK(dif_sensor_ctrl_get_recov_events(&sensor_ctrl, &events));
  }
  return events;
}

/**
 *  Check alert cause registers are correctly set
 */
static void check_alert_state(dif_toggle_t fatal) {
  bool fatal_cause = false;
  bool recov_cause = false;

  CHECK_DIF_OK(dif_alert_handler_alert_is_cause(
      &alert_handler, kTopMatchaAlertIdSensorCtrlFatalAlert, &fatal_cause));

  CHECK_DIF_OK(dif_alert_handler_alert_is_cause(
      &alert_handler, kTopMatchaAlertIdSensorCtrlRecovAlert, &recov_cause));

  if (dif_toggle_to_bool(fatal)) {
    CHECK(fatal_cause & !recov_cause,
          "Fatal alert not correctly observed in alert handler");
  } else {
    CHECK(recov_cause & !fatal_cause,
          "Recov alert not correctly observed in alert handler");
  }

  CHECK_DIF_OK(dif_alert_handler_alert_acknowledge(
      &alert_handler, kTopMatchaAlertIdSensorCtrlRecovAlert));
  CHECK_DIF_OK(dif_alert_handler_alert_acknowledge(
      &alert_handler, kTopMatchaAlertIdSensorCtrlFatalAlert));
};

/**
 *  First configure fatality of the desired event.
 *  Then trigger the event from sensor_ctrl to ast.
 *  Next poll for setting of correct events inside sensor_ctrl status.
 *  When a recoverable event is triggerd, make sure only recoverable
 *  status is seen, likewise for fatal events.
 *  Finally, check for correct capture of cause in alert handler.
 */
static void test_event(uint32_t idx, dif_toggle_t fatal) {
  // Configure event fatality
  CHECK_DIF_OK(dif_sensor_ctrl_set_alert_fatal(&sensor_ctrl, idx, fatal));

  // Trigger event
  CHECK_DIF_OK(dif_sensor_ctrl_set_ast_event_trigger(&sensor_ctrl, idx,
                                                     kDifToggleEnabled));

  // wait for events to set
  IBEX_SPIN_FOR(get_events(fatal) > 0, 1);

  // Check for the event in ast sensor_ctrl
  // if the event is not set, error
  CHECK(((get_events(fatal) >> idx) & 0x1) == 1, "Event %d not observed in AST",
        idx);

  // check the opposite fatality setting, should not be set
  CHECK(((get_events(!fatal) >> idx) & 0x1) == 0,
        "Event %d observed in AST when it should not be", idx);

  // clear event trigger
  clear_event(idx, fatal);

  // check whether alert handler captured the event
  check_alert_state(fatal);
};

enum {
  // Counter for event index.
  kCounterEventIdx,
  // Counter for number of events tested.
  kCounterNumTests,
  // Max number of events to test per run.
  kNumTestsMax = SENSOR_CTRL_PARAM_NUM_ALERT_EVENTS >> 1,
};

static uint32_t get_next_event_to_test(void) {
  uint32_t event_idx;
  // Reseed so that we don't see the same sequence after each reset.
  rand_testutils_reseed();
  do {
    event_idx = flash_ctrl_testutils_counter_get(kCounterEventIdx);
    flash_ctrl_testutils_counter_increment(&flash_ctrl, kCounterEventIdx);
    // Drop each event randomly to reduce run time.
  } while (rand_testutils_gen32() <= UINT32_MAX >> 1 &&
           event_idx < SENSOR_CTRL_PARAM_NUM_ALERT_EVENTS);
  return event_idx;
}

bool test_main(void) {
  // Initialize flash_ctrl
  CHECK_DIF_OK(dif_flash_ctrl_init_state(
      &flash_ctrl,
      mmio_region_from_addr(TOP_MATCHA_FLASH_CTRL_CORE_BASE_ADDR)));

  // Initialize sensor_ctrl
  CHECK_DIF_OK(dif_sensor_ctrl_init(
      mmio_region_from_addr(TOP_MATCHA_SENSOR_CTRL_BASE_ADDR), &sensor_ctrl));

  // Initialize alert_handler
  CHECK_DIF_OK(dif_alert_handler_init(
      mmio_region_from_addr(TOP_MATCHA_ALERT_HANDLER_BASE_ADDR),
      &alert_handler));

  CHECK_DIF_OK(dif_rstmgr_init(
      mmio_region_from_addr(TOP_MATCHA_RSTMGR_AON_BASE_ADDR), &rstmgr));

  // Enable both recoverable and fatal alerts
  CHECK_DIF_OK(dif_alert_handler_configure_alert(
      &alert_handler, kTopMatchaAlertIdSensorCtrlRecovAlert,
      kDifAlertHandlerClassA, kDifToggleEnabled, kDifToggleEnabled));
  CHECK_DIF_OK(dif_alert_handler_configure_alert(
      &alert_handler, kTopMatchaAlertIdSensorCtrlFatalAlert,
      kDifAlertHandlerClassA, kDifToggleEnabled, kDifToggleEnabled));

  // Enable flash access
  flash_ctrl_testutils_default_region_access(&flash_ctrl,
                                             /*rd_en*/ true,
                                             /*prog_en*/ true,
                                             /*erase_en*/ true,
                                             /*scramble_en*/ false,
                                             /*ecc_en*/ false,
                                             /*he_en*/ false);

  // Make sure we do not try to test more than half of all available events
  // in a single test.  Testing too many would just make the run time too
  // long.
  uint32_t event_idx = get_next_event_to_test();
  if (event_idx == SENSOR_CTRL_PARAM_NUM_ALERT_EVENTS ||
      flash_ctrl_testutils_counter_get(kCounterNumTests) >= kNumTestsMax) {
    LOG_INFO("Tested all events");
    return true;
  } else {
    LOG_INFO("Testing event %d", event_idx);
  }

  // test recoverable event
  test_event(event_idx, /*fatal*/ kDifToggleDisabled);

  // test fatal event
  test_event(event_idx, /*fatal*/ kDifToggleEnabled);

  // increment flash counter to know where we are
  flash_ctrl_testutils_counter_increment(&flash_ctrl, kCounterNumTests);

  // Now request system to reset and test again
  LOG_INFO("Rebooting system");
  CHECK_DIF_OK(dif_rstmgr_software_device_reset(&rstmgr));
  wait_for_interrupt();

  return false;
}
