// Copyright 2017 ETH Zurich and University of Bologna.
// Copyright and related rights are licensed under the Solderpad Hardware
// License, Version 0.51 (the “License”); you may not use this file except in
// compliance with the License.  You may obtain a copy of the License at
// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law
// or agreed to in writing, software, hardware and materials distributed under
// this 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 "spr-defs.h"
#include <utils.h>
#include <pulpino.h>
#include <stdint.h>
#include <string_lib.h>
#include <uart.h>
#include <gpio.h>

// exit loop
void exit (int i) {
  eoc(i);
  while (1);
}

// signal end of computation
void eoc(int i) {
  if (i != 0)
    RES_STATUS = 1;
  else
    RES_STATUS = 0;

  // activate GPIO
  CGREG |= (1 << CGGPIO);
  // setup GPIO
  set_pin_function(8, 1);
  set_gpio_pin_direction(8, 1);
  set_gpio_pin_value(8, 1);
}

// sleep for 'iter' iterations. each iteration is approx 10 cycles
void sleep_busy(volatile int iter)
{
  for (int i=0;i<iter;i++)
    asm volatile ("nop");
}

#ifdef __riscv__
/* Set the specified counter to the specified value */
void cpu_perf_set(unsigned int counterId, unsigned int value) {
  printf("cpu_perf_set: not implemented yet\n");
}

unsigned int cpu_perf_get(unsigned int counterId) {
  uint32_t value = 0;
  // This is stupid! But I really don't know how else we could do that
  switch (counterId) {
  case  0: asm volatile ("csrr %0, 0x780" : "=r" (value)); break;
  case  1: asm volatile ("csrr %0, 0x781" : "=r" (value)); break;
  case  2: asm volatile ("csrr %0, 0x782" : "=r" (value)); break;
  case  3: asm volatile ("csrr %0, 0x783" : "=r" (value)); break;
  case  4: asm volatile ("csrr %0, 0x784" : "=r" (value)); break;
  case  5: asm volatile ("csrr %0, 0x785" : "=r" (value)); break;
  case  6: asm volatile ("csrr %0, 0x786" : "=r" (value)); break;
  case  7: asm volatile ("csrr %0, 0x787" : "=r" (value)); break;
  case  8: asm volatile ("csrr %0, 0x788" : "=r" (value)); break;
  case  9: asm volatile ("csrr %0, 0x789" : "=r" (value)); break;
  case 10: asm volatile ("csrr %0, 0x78A" : "=r" (value)); break;
  case 11: asm volatile ("csrr %0, 0x78B" : "=r" (value)); break;
  case 12: asm volatile ("csrr %0, 0x78C" : "=r" (value)); break;
  case 13: asm volatile ("csrr %0, 0x78D" : "=r" (value)); break;
  case 14: asm volatile ("csrr %0, 0x78E" : "=r" (value)); break;
  case 15: asm volatile ("csrr %0, 0x78F" : "=r" (value)); break;
  default: printf("CSR %d not yet supported\n", counterId); break;
  }
  return value;
}
#endif
