// ***************** main.c ******************************************
//                 Risc entry point into program
//
// Sample code for calling and handling dsp elcore processor from mips
//
// (c) multicore.ru
//
// *******************************************************************
#include <unistd.h>

#include "risc_runtime/mcom02.h"
#include "risc_runtime/overlay.h"
#include "risc_runtime/init.h"

extern int __dsp_main;

//
// @name: benchmark
// @description: prepare dsp core run it
// @input int i - parameter for send to dsp function
// @output - value, returned by dsp function
//
int benchmark(int i)
{
      // setup initial values for dsp registers from overlay descriptions
      int DSP_PC = (unsigned int)&__dsp_main;
      struct ovl_ctx *ctx = find_overlay_ctx(DSP_PC);
      int DSP_NUM =    ctx->dsp_info->num;
      int QSTR_STOP = ctx->dsp_info->qstr_stop;

      // load program into dsp memory
      if(!load_overlay(ctx)) return 0;

      // setup dsp registers
      DCSR(DSP_NUM)   = 0;
      SR(DSP_NUM)     = 0;
      SS(DSP_NUM)     = (*ctx).__exit_dsp;
      SP(DSP_NUM)     = 1;
      PC(DSP_NUM)=(DSP_PC - (unsigned int)((*ctx).__text_src) + ((*ctx).__text_offset))>>2;
      A7(DSP_NUM)=0x7ffc;
      A6(DSP_NUM)=0x7ffc;

      // it has no sense in this example, you can send parameter to dsp function via register
      // see "calling convention" in clang documentation
      R0_L(DSP_NUM) = i;
      R1_L(DSP_NUM) = 0;

      DCSR(DSP_NUM) = 0x4000;

      // run dsp
      const unsigned qstr_mask = (0xf << (DSP_NUM * 8));
      const unsigned stop_mask = (1<<QSTR_STOP);
      while(1)
      {
          unsigned qstr =  QSTR_DSP;
          if((qstr & qstr_mask) == stop_mask) break;
      }

      // receive value from dsp
      // see "calling convention" in clang documentation
      return R0_L(DSP_NUM);
}

main()
{
    config_overlay(0,0);

    int dsp_ret = benchmark(0);

    while (1);
};