/* ###--------------------------------------------------------------### */
/*									*/
/* file		: vh_asimut.c						*/
/* date		: Oct 20 1993						*/
/* version	: v1.92							*/
/* author	: Pirouz BAZARGAN SABET	& VUONG Huu Nghia		*/
/* description	: VHDL compiler and simulation tool.			*/
/*									*/
/* ###--------------------------------------------------------------### */

/* ###--------------------------------------------------------------### */
/* V1.91: It's now possible to initialize the registers at '0' or '1'	*/
/*        Saving all the state of the circuit is possible at the first	*/
/*        Error encountered.						*/
/* V1.9 : Now keep auxiliary signals by default, -aux means reduce	*/
/*          the equations.						*/
/* V1.8 : Verify all the connectors to accept all mbk inputs : al,..	*/
/*        Read MBK_CATA_LIB, if VH_LIBLST doesn't exist			*/
/*        Does not accept HZ connectors					*/
/* ###--------------------------------------------------------------### */

#ident "@(#) ASIMUT : A SIMUlation Tool running on a VHDL description V2.0"
#include <stdio.h>
#include <string.h>
#include MUT_H
#include MLO_H
#include MLU_H
#include LOG_H
#include BEH_H
#include BVL_H
#include PAT_H
#include PPT_H
#include "vh_utype.h"
#include "vh_utdef.h"
#include "vh_ltype.h"
#include "vh_asimut.h"
#include "vh_asdef.h"

extern char MVL_ERRFLG;

main (argc, argv)

int   argc;
char **argv;

  {
  int                i , j , patindx;
  char               asimut_err_flg;
  int                actual_err;
  int                max_delta   = VHX_DLTDFN;	/* max # of delta cyc.	*/

  char               usage_flg   = 0;		/* print usage		*/
  char               help_flg    = 0;		/* display help		*/
  char               aux_flg     = 1;		/* simplify inter. sig.	*/
  char               init_flg    = 0;		/* description's init.	*/
  char               core_flg    = 0;		/* core file at error	*/
  char               sdebug_flg  = 0;		/* debug structural	*/
  char               bdebug_flg  = 0;		/* debug behavioural	*/
  char               pdebug_flg  = 0;		/* debug pattern	*/
  char               ldebug_flg  = 0;		/* debug linker		*/
  char               cdebug_flg  = 0;		/* dbeug cycle by cycle	*/
  char               ddebug_flg  = 0;		/* debug delta by delta	*/
  char               behav_flg   = 0;		/* behav. description	*/
  char               nosim_flg   = 0;		/* no simulation	*/
  char               nores_flg   = 0;		/* no result file	*/
  char               makbdd_flg  = 0;		/* trace bdd making	*/
  char               sav_end;			/* saved end flag	*/
  unsigned int       max_err     = 10;		/* # of simul. errors	*/
  unsigned int       max_pat     = 0;		/* # of patterns	*/
  unsigned int       labelsiz    = 15;		/* longest patt. label	*/
  char              *arg_flg     = NULL;	/* recongnized arg. flg	*/
  unsigned int       last_opt    = 0;		/* last option's index	*/
  unsigned int       frst_fil    = 0;		/* first file's index	*/
  unsigned int       init_val    = 0;		/* init. constant	*/

  struct lofig      *ptlofig;
  struct befig      *ptbefig = NULL;
  struct befig      *ptbef;
  struct chain      *ptchain;
  struct papat      *pt_papat;
  struct paseq      *pt_paseq;
  char              *str;
  char               filename [200];
  FILE              *filepnt;
  struct dct_entry **hshtab;

  FAST_MODE = 'Y';

	/* ###------------------------------------------------------### */
	/*    analyse the command line, set option flags and find the	*/
	/* first file in the argument list				*/
	/* ###------------------------------------------------------### */

  arg_flg = (char *) mbkalloc (argc * sizeof (char));

  arg_flg [0] = 1;
  for (i=1 ; i<argc ; i++)
    arg_flg [i] = 0;

  for (i=1 ; i<argc ; i++)
    {
    if (arg_flg [i] == 0)
      {
      if (!strcmp (argv[i], "-h"))
        {
        help_flg    = 1;
        arg_flg [i] = 1;
        }

      if (!strcmp (argv[i], "-p"))
        {
        sscanf (argv[i+1], "%u", &max_pat);
        arg_flg [i  ] = 1;
        arg_flg [i+1] = 1;
        }

      if (!strcmp (argv[i], "-l"))
        {
        sscanf (argv[i+1], "%u", &labelsiz);
        arg_flg [i  ] = 1;
        arg_flg [i+1] = 1;
        }

      if (!strcmp (argv[i], "-t"))
        {
        makbdd_flg  = 1;
        arg_flg [i] = 1;
        }

      if (!strcmp (argv[i], "-aux"))
        {
        aux_flg     = 0;
        arg_flg [i] = 1;
        }

      if (!strcmp (argv[i], "-i"))
        {
        init_flg      = i + 1;
        arg_flg [i  ] = 1;
        arg_flg [i+1] = 1;
        }

      if (!strcmp (argv[i], "-core"))
        {
        core_flg      = i + 1;
        arg_flg [i  ] = 1;
        arg_flg [i+1] = 1;
        }

      if (!strcmp (argv[i], "-nores"))
        {
        nores_flg   = 1;
        arg_flg [i] = 1;
        }

      if (!strcmp (argv[i], "-c"))
        {
        nosim_flg   = 1;
        arg_flg [i] = 1;
        }

      if (!strcmp (argv[i], "-b"))
        {
        behav_flg   = 1;
        arg_flg [i] = 1;
        }

      if (!strncmp (argv[i], "-d", 2))
        {
        arg_flg [i] = 1;
        for (j=2 ; argv[i][j]!='\0' ; j++)
          {
          switch (argv[i][j])
            {
            case 's':
              sdebug_flg = 1; break;
            case 'b':
              bdebug_flg = 1; break;
            case 'l':
              ldebug_flg = 1; break;
            case 'p':
              pdebug_flg = 1; break;
            case 'c':
              cdebug_flg = 1; break;
            case 'd':
              ddebug_flg = 1; break;
            }
          }
        }
      }
    }

  for (i=0 ; i<argc ; i++)
    {
    if (arg_flg [i] == 1)
      last_opt = i;
    }

  for (frst_fil=0; frst_fil<argc; frst_fil++)
    {
    if (arg_flg [frst_fil] == 0)
      break;
    }

	/* ###------------------------------------------------------### */
	/* cases of error in the command line:				*/
	/*   - no argument						*/
	/*   - argument unrecognized as an option			*/
	/*   - number of files do not match:				*/
	/*       - simulation with result    => 3 files needed		*/
	/*       - simulation without result => 2 files needed		*/
	/*       - no simulation             => 1 file  needed		*/
	/* ###------------------------------------------------------### */

  if (help_flg == 1)
    {
    vhu_message (0, NULL, 0);
    system      ("man asimut");
    exit (0);
    }

  if ((argc == 1) || (last_opt != (frst_fil - 1)))
    usage_flg = 1;

  if (((nosim_flg == 0) && (nores_flg == 0) && (argc != (frst_fil + 3))) ||
      ((nosim_flg == 0) && (nores_flg == 1) && (argc != (frst_fil + 2))) ||
      ((nosim_flg == 1) &&                     (argc != (frst_fil + 1))))
    usage_flg = 1;

  if (usage_flg == 1)
    {
    vhu_message (0, NULL, 0);
    vhu_message (1, NULL, 0);
    exit (0);
    }

  alliancebanner ("ASimuT", vhu_avers(), "A SIMUlation Tool", "1991,1992,1993",
                  "2.0");

  fprintf (stdout, "\tParis, FRANCE, Europe, Earth, Solar system, Milky Way, ...\n");

	/* ###------------------------------------------------------### */
	/*    Initialize :						*/
	/*      - BDD hash tables					*/
	/*      - get MBK environment variables				*/
	/* ###------------------------------------------------------### */

  vhu_message (2, NULL, 0);
  initializeBdd (0);
  mbkenv ();

	/* ###------------------------------------------------------### */
	/*    Read the maximum number of simulation errors from the	*/
	/* environment variable VH_MAXERR				*/
	/* ###------------------------------------------------------### */

  str = getenv ("VH_MAXERR");
  if (str != NULL)
    {
    if (sscanf (str, "%u", &max_err) == 0)
      max_err = 10;
    }

	/* ###------------------------------------------------------### */
	/*    Searching the root file					*/
	/* ###------------------------------------------------------### */

  vhu_message (5, argv[frst_fil], 0);
  
	/* ###------------------------------------------------------### */
	/*    If there is no structural level call directly the		*/
	/* behaviour compiler						*/
	/* ###------------------------------------------------------### */

  if (behav_flg == 1)
    {

	/* ###------------------------------------------------------### */
	/*    Running the behavioural compiler on the current file	*/
	/* ###------------------------------------------------------### */

    ptbefig = vhdlloadbefig (ptbefig, argv[frst_fil], 3);
    asimut_err_flg = ptbefig->ERRFLG;

    if (bdebug_flg == 1)
      dast_dbg (ptbefig, "befig");

    if (asimut_err_flg == 0)
      {
      vhu_message (15, NULL, 0);
      beh_makbdd  (ptbefig, aux_flg, makbdd_flg);
      beh_freabl  (ptbefig);
      asimut_err_flg = ptbefig->ERRFLG;
      }

    }
  else
    {
	/* ###------------------------------------------------------### */
	/*    Running the structural compiler on the root file		*/
	/* ###------------------------------------------------------### */

    vhu_message (4, argv[frst_fil], 0);
    
    VHS_LOFPNT = getlofig (argv[frst_fil], 'A');
    asimut_err_flg = MVL_ERRFLG;
    if (sdebug_flg == 1)
      dast_dbg (HEAD_LOFIG, "lofig");

    if (asimut_err_flg != 0)
      {
      asimut_err_flg = vhu_error (200, NULL);
      exit (1);
      }

    vhu_message (18, NULL, 0);
    rflattenlofig (VHS_LOFPNT, YES, YES);

    if (sdebug_flg == 1)
      dast_dbg (HEAD_LOFIG, "lofig");

    ptchain = VHS_LOFPNT->MODELCHAIN;
    while (ptchain != NULL)
      {

	/* ###------------------------------------------------------### */
	/*    Searching behaviour files					*/
	/* ###------------------------------------------------------### */

      vhu_message (5, ptchain->DATA, 0);

	/* ###------------------------------------------------------### */
	/*    Running the behavioural compiler on the current file	*/
	/* ###------------------------------------------------------### */

      ptbef           = ptbefig;
      ptbefig         = vhdlloadbefig (ptbefig, (char *)ptchain->DATA, 3);
      ptbefig->NEXT   = ptbef;
      asimut_err_flg += ptbefig->ERRFLG;

      if (asimut_err_flg == 0)
        {
        vhu_message (15, NULL, 0);

        beh_makbdd  (ptbefig, aux_flg, makbdd_flg);
        beh_freabl  (ptbefig);
        asimut_err_flg = ptbefig->ERRFLG;
        }
      ptchain = ptchain->NEXT;
      }
    }

  if (bdebug_flg == 1)
    dast_dbg (ptbefig, "befig");

  if (asimut_err_flg != 0)
    {
    asimut_err_flg = vhu_error (200, NULL);
    exit (1);
    }

  if (nosim_flg == 1)
    exit (0);

	/* ###------------------------------------------------------### */
	/*    Running the pattern description compiler on the current	*/
	/* file								*/
	/* ###------------------------------------------------------### */

  vhu_message (6, argv[frst_fil + 1], 0);

  pt_paseq = pat_lodpaseq (argv[frst_fil + 1], NULL, max_pat);

  if (pdebug_flg == 1)
    dast_dbg (pt_paseq, "paseq");

  if ((pt_paseq == NULL) || (pt_paseq->ERRFLG != 0))
    {
    asimut_err_flg = vhu_error (200, NULL);
    exit (1);
    }

	/* ###------------------------------------------------------### */
	/*    Link previous structures to create the simulator's data	*/
	/* base structures						*/
	/* ###------------------------------------------------------### */

  hshtab = vhu_initab ();

  vhu_message (16, NULL, 0);


  if (behav_flg == 1)
    ptlofig = vhl_makgst (ptbefig);

  vhl_resord (hshtab, HEAD_LOFIG, ptbefig);
  if (sdebug_flg == 1)
    dast_dbg (HEAD_LOFIG, "lofig");

  vhl_restor (hshtab, HEAD_LOFIG, ptbefig);
  if (sdebug_flg == 1)
    dast_dbg (HEAD_LOFIG, "lofig");

  if (asimut_err_flg != 0)
    {
    asimut_err_flg = vhu_error (200, NULL);
    exit (1);
    }

  vhu_message (9, NULL, 0);

  asimut_err_flg = vhl_linker (hshtab, pt_paseq, aux_flg);

  if (asimut_err_flg != 0)
    {
    asimut_err_flg = vhu_error (200, NULL);
    exit (1);
    }

	/* ###------------------------------------------------------### */
	/*    Initialize the circuit with a .sav file or a const.	*/
	/* ###------------------------------------------------------### */

  if (init_flg != 0)
    {
    if ((sscanf (argv[init_flg], "%u", &init_val) == 1) && (init_val <= 1))
      vhx_initval (VHL_HEDLKF, init_val);
    else
      {
      if ((filepnt = fopen (argv[init_flg], "r")) == NULL)
        vhu_error (116, argv[init_flg]);
      else
        {
        asimut_err_flg = vhx_initfig (VHL_HEDLKF, filepnt);
        fclose (filepnt);
        }
      }
    }

  if (ldebug_flg == 1)
    dast_dbg (VHL_HEDLKF, "lkdfig");
  if (pdebug_flg == 1)
    dast_dbg (pt_paseq, "paseq");

  if (asimut_err_flg != 0)
    {
    asimut_err_flg = vhu_error (200, NULL);
    exit (1);
    }

  /* ###------------------------------------------------------------### */
  /*    Simulating the current figure					*/
  /* ###------------------------------------------------------------### */

  patindx  = 0;

  actual_err = max_err;

  while (1)
    {
    pt_papat = pt_paseq->CURPAT;

    while ((pt_papat   != NULL) && (pt_papat != pt_paseq->NXTPAT) &&
           (actual_err >  0))
      {
      max_delta = VHX_DLTDFN;

	/* ###------------------------------------------------------### */
	/*    Read a new pattern					*/
	/* ###------------------------------------------------------### */

      vhu_message (10, NULL, patindx);
      if (pt_papat->ACTFLAG == 'I')
        vhx_inireg (hshtab, pt_papat->PAINI);

      vhx_redpat  (pt_paseq, pt_papat);

	/* ###------------------------------------------------------### */
	/*    Start the execution of the pattern			*/
	/* ###------------------------------------------------------### */

      vhx_update ();

      if (ddebug_flg == 1)
        dast_dbg (VHL_HEDLKF, "lkdfig");

      while ((VHX_EVENT != NULL) && (max_delta > 0))
        {
        vhx_execute ();

        vhx_update  ();
        max_delta--;

        if (ddebug_flg == 1)
          dast_dbg (VHL_HEDLKF, "lkdfig");
        }

      if (cdebug_flg == 1)
        dast_dbg (VHL_HEDLKF, "lkdfig");

      if (max_delta <= 0)
        break;

      actual_err -= vhx_wrtpat (pt_paseq, pt_papat);

    /* ###----------------------------------------------------------### */
    /*    Creating a core file at the first error encountered		*/
    /* ###----------------------------------------------------------### */

      if ((core_flg != 0) && (max_err != actual_err))
        {
        vhu_message (17, NULL, 0);

        if ((filepnt = mbkfopen (argv[core_flg], "cor", WRITE_TEXT)) == NULL)
          {
          sprintf (filename, "%s.cor", argv[core_flg]);
          asimut_err_flg = vhu_error (116, filename);
          exit (1);
          }
        vhx_core (filepnt, VHL_HEDLKF);
        fclose (filepnt);

        if ((filepnt = mbkfopen (argv[core_flg], "sav", WRITE_TEXT)) == NULL)
          {
          sprintf (filename, "%s.sav", argv[core_flg]);
          asimut_err_flg = vhu_error (116, filename);
          exit (1);
          }

        vhx_savall (filepnt, VHL_HEDLKF);
        fclose (filepnt);

        if (nores_flg == 1)
          {
          sav_end          = pt_paseq->ENDFLG;
          pt_paseq->ENDFLG = 'Y';

          pat_savpaseq (argv[core_flg], pt_paseq, labelsiz);
          pt_paseq->ENDFLG = sav_end;
          }

        core_flg = 0;
        }

      if (vhx_chkerr () == 1)
        break;
      pt_papat = pt_papat->NEXT;
      patindx++;
      }

    if (pdebug_flg == 1)
      dast_dbg (pt_paseq, "paseq");

    if (nores_flg == 0)
      pat_savpaseq (argv[frst_fil + 2], pt_paseq, labelsiz);

    if ((pt_paseq->ENDFLG != 'Y') && (pt_paseq->ERRFLG == 0))
      {
      pt_paseq = pat_lodpaseq (argv[frst_fil + 1], pt_paseq, max_pat);
      if (pdebug_flg == 1)
        dast_dbg (pt_paseq, "paseq");
      }
    else
      break;

    }

  if (max_delta <= 0)
    asimut_err_flg = vhu_error (105, NULL);

  if (actual_err < 0)
    asimut_err_flg = vhu_error (106, NULL);

  /* ###------------------------------------------------------------### */
  /*    if the save flag is set create a save file			*/
  /* ###------------------------------------------------------------### */

  if (nores_flg == 0)
    {
    if (pt_paseq->SAVFLG == 'Y')
      {
      if ((filepnt = mbkfopen (argv[frst_fil + 1], "sav", WRITE_TEXT)) == NULL)
        {
        sprintf (filename, "%s.sav", argv[frst_fil + 1]);
        asimut_err_flg = vhu_error (116, filename);
        exit (1);
        }
      vhx_savall (filepnt, VHL_HEDLKF);
      fclose (filepnt);
      }
    }

  exit (0);
  }
