/*
IBIS_AMI_RX.c

Continuous Time Filter (CTF) with fixed coefficients
C.Kumar and Ambrish Varma
July 31 2007

© 2007 Cadence Design Systems, Inc.  All rights reserved  worldwide. 
The information and computer programs ("Licensed Material") contained herein 
are protected by copyright law and international treaties. Unauthorized 
reproduction or distribution of the Licensed Material, or any portion of it, 
may result in severe civil and criminal penalties.  Cadence grants Recipient 
of the Licensed Material a limited, nonexclusive,  personal, right to use the
Licensed Material for Recipient's  internal use in evaluating Cadence software and 
hardware products.   In no event shall Recipient distribute the Licensed Material or 
use the Licensed Material for benchmarking purposes.    

The Licensed Material is provided to Recipient to use at Recipient's own risk.  
The Licensed Material may not be compatible with current or future versions of 
Cadence products.  THE LICENSED MATERIAL IS PROVIDED "AS IS" AND WITH NO WARRANTIES, 
INCLUDING WITHOUT LIMITATION ANY EXPRESS WARRANTIES OR IMPLIED WARRANTIES OF 
MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.   

IN NO EVENT SHALL CADENCE BE LIABLE TO RECIPIENT OR ANY THIRD PARTY FOR ANY INCIDENTAL, 
INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, OR ANY OTHER DAMAGES WHATSOEVER(INCLUDING, 
WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS 
OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OR INABILITY 
TO USE LICENSED MATERIAL, WHETHER OR NOT THE POSSIBILITY OR CAUSE OF SUCH DAMAGES WAS 
KNOWN TO CADENCE.
*/

#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
static long ctfilt (double *sr, long sr_size, long bitp, double *fwd, long fwd_cnt, double *bwd, long bwd_cnt)
{
  long i=0;

  if(!sr)
    return 0;

  for (i=sr_size-1; i>=0; i--)
    {
      long k=0;
      double term=0;

      for (k=0; k<fwd_cnt; k++)
	{
	  long j = i-k*bitp;

	  if(j < 0)
	    break;
	  term += fwd[k] * sr[j];
	}
      sr[i] = term;

    }

  
  for (i=0; i<sr_size; i++)
    {
      long k=0;
      double term=0;
      for (k=1; k<=bwd_cnt; k++)
	{
	  long j = i-k*bitp;

	  if(j < 0)
	    break;

	  term += bwd[k] * sr[j];
	}

      sr[i] += term;
    }

  return 1;
}

typedef struct {
  long bitp;
  long fwd;
  long bwd;
  double *fwdcf;
  double *bwdcf;
}ibisctf_type;

static void destroyctf (ibisctf_type *ctf)
{
  if(!ctf)
    return;

  if (ctf->fwdcf)
    free (ctf->fwdcf);

  if (ctf->bwdcf)
    free (ctf->bwdcf);

  free (ctf);
}

static ibisctf_type *newctf (void)
{
  return (calloc (1, sizeof (ibisctf_type)));
}
static long loadparams (ibisctf_type *ctf, char *sparams)
{
  char buff2[4000];
  char * x;
  int flag=0;
  double fwd_coeff[1001];
  double bwd_coeff[1001];  
  
  int i,j =0;
  int t=0;


  if(!ctf || !sparams)
    return 0;

  x = strtok(sparams," \n()"); 

  while(x!=NULL)  
  {
   x=strtok(NULL," \n()");

   if(x!=NULL)
     {
       strcpy(buff2,x);
     if(strcmp (x,"fwd")==0)
       flag=1;

     if(strcmp (x,"bwd")==0)
       flag=2;

     if((flag==1)&&(atof(buff2)!=0))
       {
       fwd_coeff[i]=atof(buff2);
       i++;
       }
     if((flag==2)&&(atof(buff2)!=0))
       {
       bwd_coeff[j]=atof(buff2);
       j++;
       }
     }
  }
   ctf->bwd = j;
   ctf->fwd = i;
   ctf->fwdcf = calloc (ctf->fwd, sizeof (double));
   
   if(!ctf->fwdcf)
     return 0;
   
   while(i!=0)
   {
   ctf->fwdcf[i-1] = fwd_coeff[i-1];
   i--;
   }   
   
   ctf->bwdcf = calloc (ctf->bwd, sizeof (double));
   
   if(!ctf->bwdcf)
     return 0;

   while(j!=0)
   {
   ctf->bwdcf[j-1] = bwd_coeff[j-1];
   j--;
   }   
  return 1;
}
__declspec(dllexport) long AMI_Init (double *impulse_matrix,

               long row_size,

               long aggressors, 

               double sample_interval,

               double bit_time,

               char *AMI_dll_parameters_in, 

               char **AMI_dll_parameters_out, 

               void **AMI_dll_memory_handle,

               char **msg)
{
char temp_msg[2000];
ibisctf_type *ctf=0;

Cadence_Licence();



  if(!impulse_matrix)
    return 0;

  if(!AMI_dll_memory_handle)
    return 0;  

  ctf = newctf ();

  if(!ctf)
    return 0;

  ctf->bitp = bit_time/sample_interval;

  sprintf(temp_msg," AMI_dll_parameters_in: '%s' \n",AMI_dll_parameters_in);
  *msg = temp_msg;  

  if(!loadparams (ctf, AMI_dll_parameters_in))
    return 0;

  *AMI_dll_memory_handle = ctf;

  return 1;
}

__declspec(dllexport) long AMI_GetWave (double *wave,

                  long wave_size,

                  double *clock_times,

                  char **AMI_dll_parameters_out,

                  void *AMI_dll_memory)
{
  ibisctf_type *ctf=0;
  long status = 0;
  if(!wave)
    return 0;

  ctf = AMI_dll_memory;

  if(!ctf)
    return 0;
  
  status = ctfilt (wave, wave_size, ctf->bitp, ctf->fwdcf, ctf->fwd, ctf->bwdcf, ctf->bwd);

  return 1;
}

__declspec(dllexport) long AMI_Close(void * AMI_dll_memory)
{
  destroyctf (AMI_dll_memory);
  return 1;
}

int Cadence_Licence(void)
{
printf(" © 2007 Cadence Design Systems, Inc.  All rights reserved  worldwide.\n" 
"The information and computer programs (\"Licensed Material\") contained herein \n"
"are protected by copyright law and international treaties. Unauthorized \n"
"reproduction or distribution of the Licensed Material, or any portion of it, \n"
"may result in severe civil and criminal penalties.  Cadence grants Recipient \n"
"of the Licensed Material a limited, nonexclusive,  personal, right to use the \n"
"Licensed Material for Recipient's  internal use in evaluating Cadence software and \n"
"hardware products.   In no event shall Recipient distribute the Licensed Material or \n"
"use the Licensed Material for benchmarking purposes.   \n\n"
"The Licensed Material is provided to Recipient to use at Recipient's own risk.  \n"
"The Licensed Material may not be compatible with current or future versions of \n"
"Cadence products.  THE LICENSED MATERIAL IS PROVIDED \"AS IS\" AND WITH NO WARRANTIES, \n"
"INCLUDING WITHOUT LIMITATION ANY EXPRESS WARRANTIES OR IMPLIED WARRANTIES OF \n"
"MERCHANTABILITY OR FITNESS FOR A PARTICULAR USE.  \n\n"
"IN NO EVENT SHALL CADENCE BE LIABLE TO RECIPIENT OR ANY THIRD PARTY FOR ANY INCIDENTAL, \n"
"INDIRECT, SPECIAL OR CONSEQUENTIAL DAMAGES, OR ANY OTHER DAMAGES WHATSOEVER(INCLUDING, \n"
"WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS \n"
"OF BUSINESS INFORMATION, OR OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OR INABILITY \n"
"TO USE LICENSED MATERIAL, WHETHER OR NOT THE POSSIBILITY OR CAUSE OF SUCH DAMAGES WAS \n"
"KNOWN TO CADENCE. \n");
return 0;
}

