/***********************************
  (C) Copyright 1992-1993; dit/upm
  Distributed under the conditions stated in the
  TOPO General Public License (see file LICENSE)
  ***********************************/

/***********************************
  
  David Larrabeiti Lopez
  
  Dec 13, 1991
  
  Definition of synchronization gate sets
  and functions to manage them.
  Unlike normal gate sets , synchronizations gate set includes the
  idea of full set : || as the whole of declared gates.
  These sgs are used in the interleaved expansion.
  
  COMPILATION OPTIONS: The behaviour of this module can be modified
  by the following compilation flags:
  
  SDEBUG : activate debugging mode
  
  ************************************/

/* LINTLIBRARY */

#include "listdh.h"
#include "baattr.h"
#include "badefca.h"
#include "limisc.h"
#include "batables.h"
#include "basynset.h"


/* file for printing */
FILE  *f;

static int new_sgs_count      = 0;
static int released_sgs_count = 0;


/* InitSS
 * Init the SS module
 */
void InitSS()
{
#ifdef SDEBUG
  new_sgs_count      = 0;
  released_sgs_count = 0;
#endif
}

/*----------------------------------------------------------------*/

/* StatSS
 * Number of asked  and released sgs nodes
 */
void StatSS( new, released )
     int * new, *released;
{
  *new      = new_sgs_count;
  *released = released_sgs_count;
}

/*----------------------------------------------------------------*/

/* CreateSS
 * Create an empty SyncGateSet.
 */
PSyncGateSetTyp CreateSS()
{
  PSyncGateSetTyp egs;
  
  egs = (PSyncGateSetTyp)NewCellM(sizeof(SyncGateSetTyp));
#ifdef SDEBUG
  new_sgs_count++;
#endif
  egs->syncKind = INTER_SYNC;
  egs->gs       = NULL;
  return egs;
}

/*----------------------------------------------------------------*/

/* FreeSS
 * Frees the memory used by the SyncGateSet egs.
 */
void FreeSS( egs )
     PSyncGateSetTyp egs; 
{
  if (egs->gs!=NULL)
    FreeGS(egs->gs);
  FreeCellM((void*)egs,sizeof(SyncGateSetTyp));
#ifdef SDEBUG
  released_sgs_count++;
#endif
}

/*----------------------------------------------------------------*/

/* CopySS
 * Copies the SyncGateSet egs.
 */
PSyncGateSetTyp CopySS( egs )
     PSyncGateSetTyp egs;
{
  PSyncGateSetTyp egs2;
  
  egs2 = CreateSS();
  egs2->syncKind = egs->syncKind;
  if ( egs->gs!=NULL )
    egs2->gs = CopyGS(egs->gs);
  
  return egs2;
}

/*----------------------------------------------------------------*/

/* IsEmptySS
 * Say whether the Sync Gate Set is empty
 */
boolean IsEmptySS( egs )
     PSyncGateSetTyp egs;
{ 
  LASSERT(egs!=NULL);
  return ( egs->syncKind==INTER_SYNC );
}

/*----------------------------------------------------------------*/

/* IsFullSS
 * Say whether the Sync Gate Set is full
 */
boolean IsFullSS( egs )
     PSyncGateSetTyp egs;
{
  return egs->syncKind==FULL_SYNC;
}

/*----------------------------------------------------------------*/

/* DrawSS
 * Print the Sync Gate Set egs.
 * "pstr" is the function used to print strings.
 */
void DrawSS( egs, pstr )
     PSyncGateSetTyp egs;
     void (*pstr)(); 
{
  switch( egs->syncKind )
    { case PART_SYNC:
	DrawGS( egs->gs, pstr );
	break;
      case FULL_SYNC:
	pstr( "||" );
	break;
      case INTER_SYNC:
	pstr( "|||" );
	break;
      }
}

/*----------------------------------------------------------------*/

/* PrintSS
 * Print the names of gates given for a mask
 * "pstr" is the function used to print strings.
 */
void PrintSS(egs,pstr)
     PSyncGateSetTyp egs;
     void (*pstr)(); 
{
  switch( egs->syncKind )
    {
    case PART_SYNC:
      PrintGS( egs->gs, pstr );
      break;
    case FULL_SYNC:
      pstr( "||" );
      break;
    case INTER_SYNC:
      pstr( "|||" );
      break;
    }
}

/*----------------------------------------------------------------*/

/* GateInSS
 * Check if an event belongs to a Sync gate set.
 * exit always belongs.
 * i never.
 * a gate sometimes.
 */
boolean GateInSS( g,egs )
     BehTyp g;
     PSyncGateSetTyp egs;
{
  LASSERT(egs!=NULL&&g!=NULL);
  switch(LookTypeB(g))
    {
    case ExitC:
      return TRUE;
    case IC:
      return FALSE;
    case GateC:
      break;
    default:
      Error("GateInSS:unexpected gate");
    }
  if ( egs->syncKind==PART_SYNC )
    return GateInGS( LookNameB(g), egs->gs );
  else
    return ( egs->syncKind==FULL_SYNC );
}

/*----------------------------------------------------------------*/

/* JunctionSS
 * Performs the union between two Sync gate sets.
 */
PSyncGateSetTyp JunctionSS( egs1,egs2 )
     PSyncGateSetTyp egs1,egs2;
{
  PSyncGateSetTyp egs;
  
  if ( egs1->syncKind == FULL_SYNC || egs2->syncKind == FULL_SYNC ) {
    egs = CreateSS();
    egs->syncKind = FULL_SYNC;
    egs->gs = NULL;
    return egs;
  }
  if ( egs1->syncKind == INTER_SYNC )
    egs = CopySS( egs2 );
  else
    if ( egs2->syncKind == INTER_SYNC )
      egs = CopySS( egs1 );
    else {
      egs     = CreateSS();
      egs->gs = JunctionGS( egs1->gs, egs2->gs );
      if ( IsFullGS(egs->gs,LastTableG()) ) {
	FreeGS(egs->gs);
	egs->gs = NULL;
	egs->syncKind = FULL_SYNC;
      }
      else
	egs->syncKind = PART_SYNC;
    }
  
  return egs;
}

/*----------------------------------------------------------------*/

/* IntersSS
 * Performs the intersection between two Sync gates sets
 */
PSyncGateSetTyp IntersSS( egs1, egs2 )
     PSyncGateSetTyp egs1,egs2;
{
  PSyncGateSetTyp egs;
  
  LASSERT((egs1!=NULL) && (egs2!=NULL));
  
  if ( egs1->syncKind == FULL_SYNC || egs2->syncKind == FULL_SYNC ) {
    egs = CreateSS();
    egs->syncKind = FULL_SYNC;
    egs->gs = NULL;
    return egs;
  }
  if ( egs1->syncKind == INTER_SYNC || egs2->syncKind == INTER_SYNC ) {
    egs = CreateSS();
    egs->syncKind = INTER_SYNC;
    egs->gs = NULL;
    return egs;
  }
  
  egs = CreateSS();
  egs->gs = IntersGS(egs1->gs,egs2->gs);
  if ( IsEmptyGS(egs->gs) ) {
    egs->syncKind = INTER_SYNC;
    FreeGS(egs->gs);
    egs->gs=NULL;
  }
  else
    egs->syncKind = PART_SYNC;
  
  return egs;
  
}

/*----------------------------------------------------------------*/

/* DiffsSS
 * return the difference between two Sync gates sets: egs1-egs2
 */
PSyncGateSetTyp DiffsSS(egs1,egs2)
     PSyncGateSetTyp egs1,egs2;
{
  PSyncGateSetTyp egs;
  GateSetTyp gs;
  
  if ( egs1->syncKind == INTER_SYNC ) {
    egs = CreateSS();
    egs->syncKind = INTER_SYNC;
    egs->gs = NULL;
    return egs;
  }
  
  if ( egs1->syncKind == FULL_SYNC )
    switch ( egs2->syncKind )
      {
      case FULL_SYNC:
        egs = CreateSS();
        egs->syncKind = INTER_SYNC;
        egs->gs = NULL;
        return egs;
        
      case INTER_SYNC:
        egs = CreateSS();
        egs->syncKind = FULL_SYNC;
        egs->gs = NULL;
        return egs;
        
      case PART_SYNC:
        egs = CreateSS();
        egs->syncKind = PART_SYNC;
        egs->gs = FullGS( LastTableG() );
        gs = DiffGS( egs->gs, egs2->gs );
        FreeGS( egs->gs );
        egs->gs = gs;
        return egs;
      }
  
  egs = CreateSS();
  gs  = DiffGS( egs1->gs, egs2->gs );
  if ( IsEmptyGS( gs ) ) {
    egs->syncKind = INTER_SYNC;
    egs->gs       = NULL;
    FreeGS( gs );
  }
  else {
    egs->syncKind = PART_SYNC;
    egs->gs       = gs;
  }
  
  return egs;
  
}

/*----------------------------------------------------------------*/

/* EqualSS
 * Return TRUE if the Sync gates are equal
 */
boolean EqualSS( egs1, egs2 )
     PSyncGateSetTyp egs1,egs2;
{
  if ( egs1->syncKind == egs2->syncKind )
    if ( egs1->syncKind==PART_SYNC )
      return EqualGS( egs1->gs, egs2->gs );
    else
      return TRUE;
  else
    return FALSE;
}

/*----------------------------------------------------------------*/

/* InclSS
 * Return TRUE if egs1 is included in egs2
 */
boolean InclSS ( egs1, egs2 )
     PSyncGateSetTyp egs1,egs2;
{
  PSyncGateSetTyp m;
  
  m = DiffsSS( egs1, egs2 );
  if ( IsEmptySS(m) ) {
    FreeSS( m );
    return TRUE;
  }
  FreeSS( m );
  return FALSE;                
}

/*----------------------------------------------------------------*/

/* ClearSS
 * sets a sync set to empty 
 */
PSyncGateSetTyp  ClearSS( egs )
     PSyncGateSetTyp egs;
{
  egs->syncKind = INTER_SYNC;
  if ( egs->gs!=NULL ) {
    FreeGS( egs->gs );
    egs->gs = NULL;
  }
  return egs;
}

/*----------------------------------------------------------------*/

/* AddSS
 * Add a gate to a Sync gate set
 */
PSyncGateSetTyp AddSS( egs, g ) 
     PSyncGateSetTyp egs;
     DescriptorTyp g; 
{
  LASSERT((g <= MAX_GATE_TABLE) && (egs!=NULL));
  switch ( egs->syncKind )
    {
    case INTER_SYNC:
      egs->syncKind = PART_SYNC;
      egs->gs = NewGS();
    case PART_SYNC:
      egs->gs = AddGS( egs->gs, g );
      if ( IsFullGS( egs->gs, LastTableG() ) ) {
	FreeGS( egs->gs );
	egs->gs = NULL;
	egs->syncKind = FULL_SYNC;
      }
      break;
      
    case FULL_SYNC:
      break;
      
    default:
      break;
    }
  
  return egs; 
}

/*----------------------------------------------------------------*/

/* RemoveSS
 * Remove a gate from a mask
 */
PSyncGateSetTyp RemoveSS( egs, g )
     PSyncGateSetTyp egs;
     DescriptorTyp g;
{
  LASSERT((g <= MAX_GATE_TABLE) && (egs!=NULL));
  
  switch ( egs->syncKind )
    {
    case FULL_SYNC:
      egs->gs = FullGS(LastTableG());
      egs->syncKind = PART_SYNC;
    case PART_SYNC:
      egs->gs = RemoveGS( egs->gs, g );
      break;
      
    case INTER_SYNC:
      break;
      
    default:
      Error("RemoveSS: Unexpected synchronization kind.");
    }
  
  return egs;
}

/*----------------------------------------------------------------*/

/* SS_to_Parallel
 * return the parallel cell referred to by an egs
 */
BehTyp SS_to_Parallel( egs )
     PSyncGateSetTyp egs;
{
  BehTyp b;
  
  b = MakeB( egs->syncKind, ParallelC );
  if ( egs->syncKind==PART_SYNC )
    PutA( b, MakeA( (AttrValueTyp)CopyGS(egs->gs),GSA ) );
  
  return b;
}

/*----------------------------------------------------------------*/

/* Parallel_to_SS
 * return the Sync gate set associated to a parallel cell.
 */
PSyncGateSetTyp Parallel_to_SS ( b )
     BehTyp b;
{
  PSyncGateSetTyp egs;
  
  egs = CreateSS();
  egs->syncKind = LookNameB(b);
  if ( egs->syncKind == PART_SYNC )
    egs->gs = CopyGS( (GateSetTyp)LookAInfo(LookA(b,GSA)) );
  return egs;
}

/*----------------------------------------------------------------*/

/* GateSet_to_SS
 * return the Sync gate set associated to a gate set gs.
 */
PSyncGateSetTyp GateSet_to_SS ( gs )
     GateSetTyp gs;
{
  PSyncGateSetTyp hegs;
  
  hegs = CreateSS();
  hegs->syncKind = PART_SYNC;
  hegs->gs = CopyGS( gs );
  
  return hegs;
}

/*----------------------------------------------------------------*/

/* IsFullSyncSS
 */
boolean IsFullSyncSS( egs )
     PSyncGateSetTyp egs;
{
  return egs->syncKind==FULL_SYNC;
}

/*----------------------------------------------------------------*/

/* IsPureInterleavingSS
 */
boolean IsPureInterleavingSS( egs )
     PSyncGateSetTyp egs;
{
  return egs->syncKind==INTER_SYNC;
}

/*----------------------------------------------------------------*/

/* IsPartialSyncSS
 */
boolean IsPartialSyncSS( egs )
     PSyncGateSetTyp egs;
{
  return egs->syncKind==PART_SYNC;
}

/*----------------------------------------------------------------*/

/* FullSS
 * return a full ss.
 */
PSyncGateSetTyp FullSS()
{
  PSyncGateSetTyp egs;
  
  egs            = CreateSS();
  egs->syncKind = FULL_SYNC;
  egs->gs       = NULL;
  return egs;
}

/*----------------------------------------------------------------*/
