/* ###--------------------------------------------------------------### */
/*																		*/
/* file		: syf_drive.c												*/
/* date		: Nouv 05 1992												*/
/* version	: v100														*/
/* author	: VUONG H.N., M.HANAFI										*/
/* description	: This file contains VHDL drivers :						*/
/*		  vhdlsavebefig()												*/
/*																		*/
/* ###--------------------------------------------------------------### */

#include <stdio.h>
#include <sys/types.h>
#include <time.h>
#include MUT_H
#include"../../beh104/beh104.h"
#include "../util/syf_utype.h"
#include "../util/syf_utdef.h"
#include "syf_drive.h"

/* ###--------------------------------------------------------------### */
/* function	: vhdlsavebefig						*/
/* description	: print out a text file containing a data-flow VHDL	*/
/*		  description						*/
/* called func.	: syf_vhdlname, mbkalloc, syf_message, syf_error  ,	*/
/*		  syf_toolbug , getptype, reverse    , syf_abl2str	*/
/*									*/
/* ###--------------------------------------------------------------### */

void syf_vhdlsavebefig (pthedbefig)

syf_befig_list	*pthedbefig;

  {
  char         *mode;
  char         *type_mark;
  int           nrlabel = 0;
  int           buff_size = 200;
  char         *buffer;
  FILE         *fd;
  time_t        clock;
  int           left,right;
  char         *name;
  char         *bus;

  struct syf_begen *ptgeneric = NULL;	/* current ptype pnt (generic)	*/
  struct ptype *ptptype   = NULL;	/* current ptype pointer (USER)	*/
  struct syf_bereg *ptbereg   = NULL;	/* current BEREG pointer	*/
  struct syf_bemsg *ptbemsg   = NULL;	/* current BEMSG pointer	*/
  struct syf_beout *ptbeout   = NULL;	/* current BEOUT pointer	*/
  struct syf_bebus *ptbebus   = NULL;	/* current BEBUS pointer	*/
  struct syf_beaux *ptbeaux   = NULL;	/* current BEAUX pointer	*/
  struct syf_bebux *ptbebux   = NULL;	/* current BEBUX pointer	*/
  struct syf_bepor *ptbepor   = NULL;	/* correctly ordered port list	*/
  struct biabl *ptbiabl   = NULL;	/* current BIABL pointer   	*/

  if (pthedbefig == NULL)
    syf_toolbug (10,"syf_decomp",NULL,0);

  buffer    = (char *)mbkalloc (buff_size);
  buffer[0] = '\0';

  syf_message (11,NULL,0);

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

  if ((fd = mbkfopen (pthedbefig->NAME,"vbe",WRITE_TEXT)) == NULL)
    {
    syf_error (107,NULL);
    exit (1);
    }

  syf_message (12,pthedbefig->NAME,0);
  syf_message (13,pthedbefig->NAME,0);

  time (&clock);
  (void) fprintf (fd,"-- VHDL data flow description generated from `%s`\n",
                  pthedbefig->NAME);
  (void) fprintf (fd,"--\t\tdate : %s\n\n",ctime(&clock));

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

  (void) fprintf (fd,"-- Entity Declaration\n\n");
  (void) fprintf (fd,"ENTITY %s IS\n",syf_vhdlname(pthedbefig->NAME));

	/* ###------------------------------------------------------### */
	/*    Generic declaration					*/
	/* ###------------------------------------------------------### */

  ptptype = getptype (pthedbefig->USER,BEH_GENERIC);
  if (ptptype != NULL)
    {
    ptptype->DATA = (void *)reverse (ptptype->DATA);
    ptgeneric     = (struct syf_begen *)ptptype->DATA;
    (void) fprintf (fd,"  GENERIC (\n");
    while (ptgeneric != NULL)
      {
      (void) fprintf (fd,"    CONSTANT %s : NATURAL := %ld",
                     syf_vhdlname(ptgeneric->NAME),*((long *)ptgeneric->VALUE));
      if (ptgeneric->NEXT != NULL)
        (void)fprintf(fd,";\t-- %s\n",(char *)ptgeneric->NAME);
      else
        (void)fprintf(fd,"\t-- %s\n",(char *)ptgeneric->NAME);

      ptgeneric = ptgeneric->NEXT;
      }
    (void) fprintf (fd,"  );\n");
    ptptype->DATA = (void *)reverse (ptptype->DATA);
    }

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

  ptbepor = pthedbefig->BEPOR;
  if (ptbepor != NULL)
    {
    (void) fprintf (fd,"  PORT (\n");
    pthedbefig->BEPOR = (struct syf_bepor *)reverse (pthedbefig->BEPOR);

    ptbepor = pthedbefig->BEPOR;
    while (ptbepor != NULL)
      {
      switch (ptbepor->DIRECTION)
        {
        case 'I':
          mode = namealloc("IN"); 
          break;
        case 'O':
        case 'Z':
          mode = namealloc("OUT"); 
          break;
        case 'B':
        case 'T':
          mode = namealloc("INOUT"); 
          break;
        default :
          syf_error (69,NULL);
        }
      ptbepor = (syf_bepor_list *)syf_vectnam(ptbepor,&left,&right,&name,0);

      if(left != -1)
        {
        switch (ptbepor->TYPE)
          {
          case 'B':
            type_mark = namealloc("BIT_VECTOR"); 
            bus = "";
            break;
          case 'W':
            type_mark = namealloc("WOR_VECTOR"); 
            bus = namealloc("BUS");
            break;
          case 'M':
            type_mark = namealloc("MUX_VECTOR"); 
            bus = namealloc("BUS");
            break;
          default :
            syf_error (68,NULL);
          }
        (void)fprintf(fd,"  %s : %s %s(%d %s %d) %s",syf_vhdlname(name), mode,
                      type_mark, left, (left>=right)?"DOWNTO":"TO",right,bus);
        }
      else
        {
        switch (ptbepor->TYPE)
          {
          case 'B':
            type_mark = "BIT"; break;
          case 'W':
            type_mark = "WOR_BIT BUS"; break;
          case 'M':
            type_mark = "MUX_BIT BUS"; break;
          default :
            syf_error (68,NULL);
          }

        (void) fprintf (fd,"  %s : %s %s",syf_vhdlname(name),
                                          mode,type_mark);
        }

      if (ptbepor->NEXT != NULL)
        (void) fprintf (fd,";\t-- %s\n",name);
      else
        (void) fprintf (fd,"\t-- %s\n  );\n",name);

      ptbepor = ptbepor->NEXT;
      }

    pthedbefig->BEPOR = (struct syf_bepor *)reverse (pthedbefig->BEPOR);
    }

  (void) fprintf (fd,"END %s;\n\n\n",syf_vhdlname(pthedbefig->NAME));

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

  (void) fprintf (fd,"-- Architecture Declaration\n\n");
  (void) fprintf (fd,"ARCHITECTURE behaviour_data_flow OF %s IS\n",
                  syf_vhdlname(pthedbefig->NAME));

	/* ###------------------------------------------------------### */
        /*  Treatment of the BEREG list					*/
	/* ###------------------------------------------------------### */

  pthedbefig->BEREG = (struct syf_bereg *)reverse(pthedbefig->BEREG);
  ptbereg = pthedbefig->BEREG;
  while (ptbereg != NULL)
    {
    ptbereg = (syf_bereg_list *)syf_vectnam(ptbereg,&left,&right,&name,2);
    if(left != -1)
      {
      (void)fprintf(fd,"  SIGNAL %s : REG_VECTOR(%d %s %d) REGISTER;\t-- %s\n",
                    syf_vhdlname(name),left,(left>=right)?"DOWNTO":"TO",
                    right,name);
      }
    else
      {
      (void) fprintf (fd,"  SIGNAL %s : REG_BIT REGISTER;\t-- %s\n",
                    syf_vhdlname(name),name);
      }
    ptbereg = ptbereg->NEXT;
    }
  pthedbefig->BEREG = (struct syf_bereg *)reverse(pthedbefig->BEREG);

	/* ###------------------------------------------------------### */
        /*  Treatment of the BEBUX list					*/
	/* ###------------------------------------------------------### */

  pthedbefig->BEBUX = (struct syf_bebux *)reverse(pthedbefig->BEBUX);
  ptbebux = pthedbefig->BEBUX;
  while (ptbebux != NULL)
    {
    ptbebux = (syf_bebux_list *)syf_vectnam(ptbebux,&left,&right,&name,1);
    if(left != -1)
      {
      switch (ptbebux->TYPE)
        {
        case 'W':
          type_mark = namealloc("WOR_VECTOR"); 
          break;
        case 'M':
          type_mark = namealloc("MUX_VECTOR"); 
          break;
        }
      (void)fprintf(fd,"  SIGNAL %s : %s(%d %s %d) BUS;\t-- %s\n",
                    syf_vhdlname(name),type_mark,left,(left>=right)?"DOWNTO":"TO",
                    right,name);
      }
    else
      {
      switch (ptbebux->TYPE)
        {
        case 'W':
          type_mark = namealloc("WOR_BIT"); 
          break;
        case 'M':
          type_mark = namealloc("MUX_BIT"); 
          break;
        }
      (void) fprintf (fd,"  SIGNAL %s : %s BUS;\t\t-- %s\n",syf_vhdlname(name),
                      type_mark,name);
      }
    ptbebux = ptbebux->NEXT;
    }
  pthedbefig->BEBUX = (struct syf_bebux *)reverse(pthedbefig->BEBUX);

  pthedbefig->BEAUX = (struct syf_beaux *)reverse(pthedbefig->BEAUX);
  ptbeaux = pthedbefig->BEAUX;
  while (ptbeaux != NULL)
    {
    ptbeaux = (syf_beaux_list *)syf_vectnam(ptbeaux,&left,&right,&name,3);
    if(left != -1)
      {
      (void)fprintf(fd,"  SIGNAL %s : BIT_VECTOR(%d %s %d);\t-- %s\n",
                    syf_vhdlname(name),left,(left>=right)?"DOWNTO":"TO",
                    right,name);
      }
    else
      {
      (void) fprintf (fd,"  SIGNAL %s : BIT;\t\t-- %s\n",
                    syf_vhdlname(name),name);
      }
    ptbeaux = ptbeaux->NEXT;
    }
  pthedbefig->BEAUX = (struct syf_beaux *)reverse(pthedbefig->BEAUX);

  (void) fprintf (fd,"\nBEGIN\n");

	/* ###------------------------------------------------------### */
	/*    Print out a concurrent assert statement for each BEMSG	*/
	/* ###------------------------------------------------------### */

  ptbemsg = pthedbefig->BEMSG;
  while (ptbemsg != NULL)
    {
    if (ptbemsg->LABEL != NULL)
      (void)fprintf(fd,"  %s :",ptbemsg->LABEL);

    buffer = syf_abl2str(ptbemsg->ABL,buffer,&buff_size); 
    (void) fprintf (fd,"  ASSERT (%s = '1')\n",syf_printabl(buffer));
    buffer[0] = '\0';

    if (ptbemsg->MESSAGE != NULL)
      (void) fprintf (fd,"    REPORT \"%s\"\n",ptbemsg->MESSAGE);

    if (ptbemsg->LEVEL == 'W')
      (void) fprintf (fd,"    SEVERITY WARNING;");
    else
      (void) fprintf (fd,"    SEVERITY ERROR;");

    (void) fprintf (fd,"\n\n");
    ptbemsg = ptbemsg->NEXT;
    }

	/* ###------------------------------------------------------### */
	/*    Print out a concurrent signal assignment for each BEAUX	*/
	/* ###------------------------------------------------------### */

  ptbeaux = pthedbefig->BEAUX;
  while (ptbeaux != NULL)
    {
    if (ptbeaux->ABL != NULL)
      {
      buffer = syf_abl2str (ptbeaux->ABL,buffer,&buff_size);
      (void) fprintf (fd,"  %s <= %s;\n",syf_vectorize(ptbeaux->NAME),syf_printabl(buffer));
      buffer[0] = '\0';
      }
    else
      syf_error (40,ptbeaux->NAME);
    ptbeaux = ptbeaux->NEXT;
    }

	/* ###------------------------------------------------------### */
	/*    Print out a block statement  with one guarded concurrent	*/
	/* signal assignment for each BIABL of each BEREG		*/
	/* ###------------------------------------------------------### */

  ptbereg = pthedbefig->BEREG;
  while (ptbereg != NULL)
    {
    ptbiabl = ptbereg->BIABL;
    while (ptbiabl != NULL)
      {
      (void) fprintf (fd,"  label%d : BLOCK ",nrlabel);
      if (ptbiabl->CNDABL  != NULL)
        {
        buffer = syf_abl2str (ptbiabl->CNDABL,buffer,&buff_size);
        (void) fprintf (fd,"(%s = '1')\n",syf_printabl(buffer));
        buffer[0] = '\0';
        }
      else
        syf_toolbug (19,"syf_decomp",ptbereg->NAME,0);
  
      (void) fprintf (fd,"  BEGIN\n    %s <= GUARDED ",syf_vectorize(ptbereg->NAME));
      if (ptbiabl->VALABL  != NULL)
        {
        buffer = syf_abl2str (ptbiabl->VALABL,buffer,&buff_size);
        (void) fprintf (fd,"%s;\n",syf_printabl(buffer));
        buffer[0] = '\0';
        }
      else
        syf_toolbug (20,"syf_decomp",ptbereg->NAME,0);

      (void) fprintf ( fd,"  END BLOCK label%d;\n",nrlabel);
      ptbiabl = ptbiabl->NEXT;
      nrlabel++;
      }
  
    ptbereg = ptbereg->NEXT;
    }

	/* ###------------------------------------------------------### */
	/*    Print out a block statement  with one guarded concurrent	*/
	/* signal assignment for each BIABL of each BEBUX		*/
	/* ###------------------------------------------------------### */

  ptbebux = pthedbefig->BEBUX;
  while (ptbebux != NULL)
    {
    ptbiabl = ptbebux->BIABL;
    while (ptbiabl != NULL)
      {
      (void) fprintf (fd,"  label%d : BLOCK (",nrlabel);
      if (ptbiabl->CNDABL != NULL)
        {
        buffer = syf_abl2str (ptbiabl->CNDABL,buffer,&buff_size);
        (void) fprintf (fd,"%s = '1')\n",syf_printabl(buffer));
        buffer[0] = '\0';
        }
      else
        syf_toolbug (19,"syf_decomp",ptbebux->NAME,0);
  
      (void) fprintf (fd,"  BEGIN\n    %s <= GUARDED ",
                      syf_vectorize(ptbebux->NAME));
      if (ptbiabl->VALABL != NULL)
        {
        buffer = syf_abl2str (ptbiabl->VALABL,buffer,&buff_size);
        (void) fprintf (fd,"%s;\n",syf_printabl(buffer));
        buffer[0] = '\0';
        }
      else
        syf_toolbug (20,"syf_decomp",ptbebux->NAME,0);

      (void) fprintf (fd,"  END BLOCK label%d;\n",nrlabel);
      ptbiabl = ptbiabl->NEXT;
      nrlabel++;
      }
  
    ptbebux = ptbebux->NEXT;
    }

	/* ###------------------------------------------------------### */
	/*    Print out a block statement  with one guarded concurrent	*/
	/* signal assignment for each BIABL of each BEBUS		*/
	/* ###------------------------------------------------------### */

  ptbebus = pthedbefig->BEBUS;
  while (ptbebus != NULL)
    {
    ptbiabl = ptbebus->BIABL;
    while (ptbiabl != NULL)
      {
      (void) fprintf (fd,"\tlabel%d : BLOCK (",nrlabel);
      if (ptbiabl->CNDABL != NULL)
        {
        buffer = syf_abl2str (ptbiabl->CNDABL,buffer,&buff_size);
        (void) fprintf (fd,"%s = '1')\n",syf_printabl(buffer));
        buffer[0] = '\0';
        }
      else
        syf_toolbug (19,"syf_decomp",ptbebus->NAME,0);
  
      (void) fprintf (fd,"\tBEGIN\n\t%s <= GUARDED ",syf_vectorize(ptbebus->NAME));
      if (ptbiabl->VALABL != NULL)
        {
        buffer = syf_abl2str (ptbiabl->VALABL,buffer,&buff_size);
        (void) fprintf (fd,"%s;\n",syf_printabl(buffer));
        buffer[0] = '\0';
        }
      else
        syf_toolbug (20,"syf_decomp",ptbebus->NAME,0);

      (void) fprintf (fd,"\tEND BLOCK label%d;\n",nrlabel);
      ptbiabl = ptbiabl->NEXT;
      nrlabel++;
      }
  
    ptbebus = ptbebus->NEXT;
    }

	/* ###------------------------------------------------------### */
	/*    Print out a concurrent signal assignment for each BEOUT	*/
	/* ###------------------------------------------------------### */

  ptbeout = pthedbefig->BEOUT;
  while (ptbeout != NULL)
    {
    if (ptbeout->ABL != NULL)
      {
      buffer = syf_abl2str(ptbeout->ABL,buffer,&buff_size);
      (void) fprintf (fd,"\n%s <= %s;\n",syf_vectorize(ptbeout->NAME), syf_printabl(buffer));
      buffer[0] = '\0';
      }
    else
      syf_error (40,ptbeout->NAME);

    ptbeout = ptbeout->NEXT;
    }
  
  (void) fprintf (fd,"END;\n");
  syf_message    (14,pthedbefig->NAME,0);
  (void) fclose  (fd);
  }
