/* ###--------------------------------------------------------------### */
/*									*/
/* file		: mvl_drive.c						*/
/* date		: Sep 24 1993						*/
/* author	: VUONG Huu Nghia					*/
/* description	: This file contains a MBK-->VHDL driver :		*/
/* functions    : vhdlsavelofig()					*/
/*									*/
/* ###--------------------------------------------------------------### */

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
#include "../mvl_include.h"
#include "../util/mvl_utype.h"
#include "../util/mvl_utdef.h"
#include "mvl_drive.h"

/* ###--------------------------------------------------------------### */
/* function	: vhdlsavelofig						*/
/* description	: print out a texte file containing a structural VHDL	*/
/*		  description						*/
/* called func.	: mvl_vhdlname   , getsigname, mvl_message, mvl_error  ,*/
/*		  mvl_toolbug, getptype, mvl_reverse, mvl_abl2str	*/
/*									*/
/* ###--------------------------------------------------------------### */
void vhdlsavelofig (ptfig)
lofig_list	*ptfig;
  {
  struct loins *ptins    = NULL;
  struct locon *ptcon    = NULL;
  struct locon *ptscan   = NULL;
  struct losig *ptsig    = NULL;
  struct chain *ptmodel  = NULL;
  struct chain *ptchain  = NULL;
  FILE	       *ptfile;
  time_t        clock;
  char         *getsigname();
  char 	       *mode = NULL;
  char         *name;
  char         *sig_name;
  int           left,right;
  struct locon *tmp_ptcon = NULL;
  int           i;
  char   first = 1;
  chain_list   *sig_list = NULL;
  char   new_name[200];

  if (ptfig == NULL)
    mvl_toolbug (10,"mvl_decomp","",0);

	/* ###------------------------------------------------------### */
	/*    Opening result file					*/
	/* ###------------------------------------------------------### */

  /* sprintf (filename,"%s.vst",ptfig->NAME); */

  if ((ptfile = mbkfopen (ptfig->NAME,"vst","w")) == NULL)
    {
    mvl_error (107,"");
    exit (1);
    }

  time (&clock);
  (void) fprintf (ptfile,"-- VHDL structural description generated from `%s`\n",
           ptfig->NAME);
  (void) fprintf (ptfile,"--\t\tdate : %s\n\n",ctime(&clock));

	/* ###------------------------------------------------------### */
	/*    Entity declaration					*/
	/* ###------------------------------------------------------### */

  (void) fprintf (ptfile,"-- Entity Declaration\n\n");
  (void) fprintf (ptfile,"ENTITY %s IS\n", mvl_vhdlname (ptfig->NAME));

	/* ###------------------------------------------------------### */
	/*    Port declaration						*/
	/* ###------------------------------------------------------### */

  if (ptfig->LOCON != NULL)
    {
    (void) fprintf (ptfile,"  PORT (\n");
    ptfig->LOCON = (struct locon *) mvl_reverse ((chain_list *)ptfig->LOCON);
    ptcon = ptfig->LOCON;
    while (ptcon != NULL)
      {
      switch (ptcon->DIRECTION)
        {
        case 'I':
          mode = namealloc("IN");
          break;
        case 'O':
          mode = namealloc("OUT");
          break;
        case 'B':
          mode = namealloc("INOUT");
          break;
        case 'Z':
        case 'T':
        case 'X':
          mode = namealloc("LINKAGE");
          break;
        }
      ptcon = (locon_list *)mvl_vectnam(ptcon,&left,&right,&name,1);
      if(left != -1)
        {
        (void) fprintf(ptfile,"  %s : %s BIT_VECTOR(%d %s %d)",
                      mvl_vhdlname(name), mode, left,
                      (left >= right)? "DOWNTO":"TO",right);
        }
      else
        {
        (void)fprintf(ptfile,"  %s : %s BIT",mvl_vhdlname(name),mode);
        }
      if (ptcon->NEXT != NULL)
        (void) fprintf (ptfile,";\t-- %s\n",name);
      else
        (void) fprintf (ptfile,"\t-- %s\n",name);
      ptcon = ptcon->NEXT;
      mbkfree(name);
      }
    (void) fprintf (ptfile, "  );\n");
    }
  (void) fprintf (ptfile,"END %s;\n\n",mvl_vhdlname(ptfig->NAME));
  ptfig->LOCON = (struct locon *) mvl_reverse ((chain_list *)ptfig->LOCON);

	/* ###------------------------------------------------------### */
	/*    Architecture declaration					*/
	/* ###------------------------------------------------------### */

  (void) fprintf (ptfile,"-- Architecture Declaration\n\n");
  (void) fprintf (ptfile,"ARCHITECTURE structural_view OF %s IS\n",
                  mvl_vhdlname(ptfig->NAME));

	/* ###------------------------------------------------------### */
	/*    Component declaration : first make a list of models, then	*/
	/* for each model print out a "component declaration"		*/
	/* ###------------------------------------------------------### */

  ptmodel = NULL;
  for (ptins = ptfig->LOINS; ptins; ptins = ptins->NEXT)
    {
    for (ptchain = ptmodel ; ptchain ; ptchain = ptchain->NEXT)
      {
      if (((struct loins *)ptchain->DATA)->FIGNAME == ptins->FIGNAME)
        break;
      }
    if (ptchain == NULL)
      ptmodel = addchain(ptmodel,ptins);
    }

  for (ptchain = ptmodel ; ptchain ; ptchain = ptchain->NEXT)
    {
    ptins = (struct loins *)ptchain->DATA;
    (void) fprintf (ptfile,"  COMPONENT %s\n    port (\n",
                    mvl_vhdlname(ptins->FIGNAME));

    ptins->LOCON = (struct locon *) mvl_reverse ((chain_list *)ptins->LOCON);
    ptcon = ptins->LOCON;
    while(ptcon != NULL)
      {
      switch (ptcon->DIRECTION)
        {
        case 'I':
          mode = namealloc("IN");
          break;
        case 'O':
          mode = namealloc("OUT");
          break;
        case 'B':
          mode = namealloc("INOUT");
          break;
        case 'Z':
        case 'T':
        case 'X':
          mode = namealloc("LINKAGE");
          break;
        }
      ptcon = (locon_list *)mvl_vectnam(ptcon,&left,&right,&name,1);
      if(left != -1)
        {
        (void)fprintf(ptfile,"    %s : %s BIT_VECTOR(%d %s %d)",
                     mvl_vhdlname(name), mode, left,
                     (left >= right)?"DOWNTO":"TO",right);
        }
      else
        (void)fprintf(ptfile,"    %s : %s BIT", mvl_vhdlname(name),mode);
      if (ptcon->NEXT != NULL)
        (void) fprintf(ptfile, ";\t-- %s\n",name);
      else
        (void) fprintf(ptfile, "\t-- %s\n",name);
      ptcon = ptcon->NEXT;
      free(name);
      }
    ptins->LOCON = (struct locon *) mvl_reverse ((chain_list *)ptins->LOCON);
    (void) fprintf (ptfile, "    );\n  END COMPONENT;\n\n");
    }

  freechain(ptmodel);

	/* ###------------------------------------------------------### */
	/*    Signal declaration					*/
	/* ###------------------------------------------------------### */

    ptsig = ptfig->LOSIG;
    while(ptsig != NULL)
      {
      if(ptsig->TYPE == 'I')
        {
        (void) fprintf (ptfile,"  SIGNAL %s : BIT;\t-- %s\n",
                      mvl_vhdlname(getsigname(ptsig)),getsigname(ptsig));
        }
      ptsig = ptsig->NEXT;       
      }

	/* ###------------------------------------------------------### */
	/*    Description block						*/
	/* ###------------------------------------------------------### */

  (void) fprintf (ptfile,"\nBEGIN\n\n");
  ptfig->LOINS = (struct loins *) mvl_reverse ((chain_list *)ptfig->LOINS);
  for (ptins = ptfig->LOINS; ptins; ptins = ptins->NEXT)
    {
	/* ###------------------------------------------------------### */
        /*   Instantiation of a model					*/
	/* ###------------------------------------------------------### */

    (void) fprintf (ptfile,"  %s : %s\n    PORT MAP (\n",
                    mvl_vhdlname(ptins->INSNAME),mvl_vhdlname(ptins->FIGNAME));
    ptcon = ptins->LOCON; 
    while(ptcon != NULL)
      {
      tmp_ptcon = (locon_list *)mvl_vectnam(ptcon,&left,&right,&name,1);
      (void) fprintf (ptfile,"    %s => ",mvl_vhdlname (name));
      if(left != -1)
	/* ###------------------------------------------------------### */
        /*    The connected signals are bused				*/
	/* ###------------------------------------------------------### */
        {
        for(i=abs(left-right);i>=0;i--)
          {
          ptsig = ptcon->SIG;
          if (ptsig->TYPE == 'I')
            {
	    /* ###-------------------------------------------------### */
            /*    The signal is internal			       */
	    /* ###-------------------------------------------------### */
/*            sig_name = namealloc(mvl_name(getsigname(ptsig))); */
            sig_name = namealloc(mvl_vhdlname(getsigname(ptsig)));
            sig_list = addchain(sig_list,(char *)sig_name);
            }
          else
            {
	    /* ###-------------------------------------------------### */
            /*    The signal is external                               */
	    /* ###-------------------------------------------------### */
            for (ptscan = ptfig->LOCON ; ptscan ; ptscan = ptscan->NEXT)
	      {
	      if (ptscan->SIG == ptsig) 
                break;
	      }
            if (ptscan == NULL)
              {
	      (void) printf("\n*** mbk error *** no external connector  \n");
	      (void) printf("     driving vhdl file %s\n", ptfig->NAME);
	      }
            else
              {
              mvl_name(ptscan->NAME,new_name);
              sig_name = namealloc(new_name);
              sig_list = addchain(sig_list,(char *)sig_name);
	      }
            }
          if(i>0)
            ptcon = ptcon->NEXT;
          }
        first = 1;
        while(sig_list != NULL)
          {
          if(first!=1)
            {
            (void)fprintf(ptfile,"& %s",(char *)(sig_list->DATA));
            }
          else
            {
            (void)fprintf(ptfile,"%s",(char *)(sig_list->DATA));
            first = 0;
            }
          sig_list = sig_list->NEXT;
          }
        }
      else
        {
	/* ###------------------------------------------------------### */
        /*    The connected signals is simple				*/
	/* ###------------------------------------------------------### */
	    /* ###-------------------------------------------------### */
        ptsig = ptcon->SIG;
        if (ptsig->TYPE == 'I')
          {
          (void) fprintf(ptfile, "%s", mvl_vhdlname (getsigname(ptsig)));
          }
        else
          {
          for (ptscan = ptfig->LOCON ; ptscan ; ptscan = ptscan->NEXT)
	    {
	    if (ptscan->SIG == ptsig) 
              break;
	    }
          if (ptscan == NULL)
            {
	    (void) printf("\n*** mbk error *** no external connector  \n");
	    (void) printf("     driving vhdl file %s\n", ptfig->NAME);
	    }
          else
            {
	    mvl_name (ptscan->NAME,new_name);
	    (void) fprintf(ptfile, "%s", new_name);
	    }
          }
        }
      if (ptcon->NEXT != NULL)
        (void) fprintf (ptfile, ",\n");
      ptcon = ptcon->NEXT;
      free(name);
      }
    (void) fprintf(ptfile, ");\n");
    }
  ptfig->LOINS = (struct loins *) mvl_reverse ((chain_list *)ptfig->LOINS);
  (void) fprintf (ptfile, "\nend structural_view;\n");
  (void) fclose  (ptfile);
  }
