#include <stdint.h>
#include "common.h"

void failure(unsigned v)
{
  SUPERVISOR->dram_scrub_period = v;
  while (1)
    SUPERVISOR->wd_key = WD_KEY;
}

static unsigned step;

volatile unsigned vvar;

int
main (void)
{
  unsigned cpu;

  SUPERVISOR->wd_period = 5000;

  /* Clear recovery bit.  */
  SUPERVISOR->cpu = 0;

  switch (step) {
  case 0:
    step = 1;

    if (SUPERVISOR->reset_cause != 0) {
      /* Fresh reset */
      failure(__LINE__);
    }

    if (SUPERVISOR->cpu_iaddr_err != 0) {
      failure(__LINE__);
    }

    /* Test cpu-fault.  */
    if (SUPERVISOR->force_divergence != 1) {
      /* Multi instruction code, to generate iaddr divergence (cpu #1).  */
      vvar++;
    }

    if (SUPERVISOR->cpu_iaddr_err != 1) {
      /* So iaddr error expected.  */
      failure(__LINE__);
    }

    /* Check cpu #1 is under reset  */
    cpu = SUPERVISOR->cpu;
    if (cpu != 1)
      failure(__LINE__);

    /* Recovery */
    asm volatile ("");
    SUPERVISOR->cpu = HYDRA_SUPERVISOR_REGS_CPU_RECOVERY;
    failure(__LINE__);
    break;

  case 1:
    step = 2;
    if (SUPERVISOR->reset_cause != 0x11)
      failure(__LINE__);

    /* Try restart */
    REGS->restart_cfg = 0;  /* No iram copy, no dram clear.  */
    REGS->restart = 0x8e51a610;
    failure(__LINE__);
    break;

  case 2:
    if (SUPERVISOR->reset_cause != 0)
      failure(__LINE__);
    break;

  default:
    failure(__LINE__);
  }

  /* Done. */
  failure(-1);
}
