// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0

#include "sw/device/lib/testing/rstmgr_testutils.h"

#include <stdbool.h>
#include <stdint.h>

#include "sw/device/lib/base/mmio.h"
#include "sw/device/lib/dif/dif_rstmgr.h"
#include "sw/device/lib/testing/test_framework/check.h"

bool rstmgr_testutils_is_reset_info(const dif_rstmgr_t *rstmgr,
                                    dif_rstmgr_reset_info_bitfield_t info) {
  dif_rstmgr_reset_info_bitfield_t actual_info;
  CHECK_DIF_OK(dif_rstmgr_reset_info_get(rstmgr, &actual_info));
  return actual_info == info;
}

bool rstmgr_testutils_reset_info_any(const dif_rstmgr_t *rstmgr,
                                     dif_rstmgr_reset_info_bitfield_t info) {
  dif_rstmgr_reset_info_bitfield_t actual_info;
  CHECK_DIF_OK(dif_rstmgr_reset_info_get(rstmgr, &actual_info));
  return (actual_info & info) != 0;
}

void rstmgr_testutils_compare_alert_info(
    const dif_rstmgr_t *rstmgr,
    dif_rstmgr_alert_info_dump_segment_t *expected_alert_dump,
    size_t dump_size) {
  size_t size_read;
  dif_rstmgr_alert_info_dump_segment_t
      actual_alert_dump[DIF_RSTMGR_ALERT_INFO_MAX_SIZE];

  CHECK_DIF_OK(dif_rstmgr_alert_info_dump_read(
      rstmgr, actual_alert_dump, DIF_RSTMGR_ALERT_INFO_MAX_SIZE, &size_read));
  CHECK_ARRAYS_EQ(actual_alert_dump, expected_alert_dump, dump_size);
}

void rstmgr_testutils_compare_cpu_info(
    const dif_rstmgr_t *rstmgr,
    dif_rstmgr_cpu_info_dump_segment_t *expected_cpu_dump, size_t dump_size) {
  size_t size_read;
  dif_rstmgr_cpu_info_dump_segment_t
      actual_cpu_dump[DIF_RSTMGR_CPU_INFO_MAX_SIZE];

  CHECK_DIF_OK(dif_rstmgr_cpu_info_dump_read(
      rstmgr, actual_cpu_dump, DIF_RSTMGR_CPU_INFO_MAX_SIZE, &size_read));
  CHECK_ARRAYS_EQ(actual_cpu_dump, expected_cpu_dump, dump_size);
}

void rstmgr_testutils_pre_reset(const dif_rstmgr_t *rstmgr) {
  // Clear reset_info.
  CHECK_DIF_OK(dif_rstmgr_reset_info_clear(rstmgr));

  // Enable alert and cpu dump capture, even if the test doesn't read it.
  CHECK_DIF_OK(dif_rstmgr_alert_info_set_enabled(rstmgr, kDifToggleEnabled));
  CHECK_DIF_OK(dif_rstmgr_cpu_info_set_enabled(rstmgr, kDifToggleEnabled));
}

void rstmgr_testutils_post_reset(
    const dif_rstmgr_t *rstmgr,
    dif_rstmgr_reset_info_bitfield_t expected_reset_info,
    dif_rstmgr_alert_info_dump_segment_t *expected_alert_dump,
    size_t alert_dump_size,
    dif_rstmgr_cpu_info_dump_segment_t *expected_cpu_dump,
    size_t cpu_dump_size) {
  // Read and compare reset_info.
  dif_rstmgr_reset_info_bitfield_t actual_reset_info;
  CHECK_DIF_OK(dif_rstmgr_reset_info_get(rstmgr, &actual_reset_info));
  CHECK(expected_reset_info == actual_reset_info,
        "Unexpected reset_info CSR mismatch, expected 0x%x, got 0x%x",
        expected_reset_info, actual_reset_info);

  if (expected_alert_dump != NULL && alert_dump_size != 0) {
    rstmgr_testutils_compare_alert_info(rstmgr, expected_alert_dump,
                                        alert_dump_size);
  }
  if (expected_cpu_dump != NULL && cpu_dump_size != 0) {
    rstmgr_testutils_compare_cpu_info(rstmgr, expected_cpu_dump, cpu_dump_size);
  }
}
