/*------------------------------------------------------------\
|                                                             |
| Tool    :                   LYNX                            |
|                                                             |
| File    :                  netlist.c                        |
|                                                             |
| Author  :               Jacomme Ludovic                     |
|                                                             |
| Date    :                  01.08.93                         |
|                                                             |
\------------------------------------------------------------*/

/*------------------------------------------------------------\
|                                                             |
|                         Include Files                       |
|                                                             |
\------------------------------------------------------------*/

# include <stdio.h>

# include MUT_H
# include MLO_H
# include MPH_H
# include RDS_H
# include RUT_H
# include RPR_H
# include RFM_H
# include RWI_H

# include "share.h"
# include "parse.h"
# include "mbkrds.h"
# include "extract.h"
# include "netlist.h"

/*------------------------------------------------------------\
|                                                             |
|                           Constants                         |
|                                                             |
\------------------------------------------------------------*/
/*------------------------------------------------------------\
|                                                             |
|                            Types                            |
|                                                             |
\------------------------------------------------------------*/
/*------------------------------------------------------------\
|                                                             |
|                          Variables                          |
|                                                             |
\------------------------------------------------------------*/
/*------------------------------------------------------------\
|                                                             |
|                          Functions                          |
|                                                             |
\------------------------------------------------------------*/
/*------------------------------------------------------------\
|                                                             |
|                     LynxBuildLogicalSignal                  |
|                                                             |
\------------------------------------------------------------*/

   long LynxBuildLogicalSignal( FigureRds, HeadEqui, LogicalFigure, Core )

     rdsfig_list *FigureRds;
     rdsrec_list *HeadEqui;
     lofig_list  *LogicalFigure;
     char         Core;
   {
     phfig_list  *FigureDumpFloat;
     phfig_list  *FigureDumpEqui;
     phfig_list  *FigureDumpScan;

     losig_list  *Signal;
     losig_list  *ScanSignal;
     chain_list  *SignalChain;
     float        SignalCapa;
     float        Capa;
     char         SignalFloat;
     char         FoundFloat;
     char         FoundScan;
     long         SignalIndex;
     char         SignalType;

     chain_list  *ScanSignalChain;
     chain_list  *DeleteChain;
     ptype_list  *SignalPtype;
     ptype_list  *ScanPtype;

     char         LayerMbk;
     char         LayerRds;
     char         Scan;

     char        *ConnectorName;
     locon_list  *LogicalConnector;

     rdsrec_list *ScanEqui;
     rdsrec_list *FirstEqui;
     rdsrec_list *IndexEqui;

     long         Counter;

     SignalIndex = 1;
     SignalPtype = (ptype_list *)NULL;
     SignalType  = INTERNAL;
     SignalCapa  = 0.0;
     SignalFloat = Core;
     FoundFloat  = 0;
     FoundScan   = 0;

     FigureDumpFloat = addphfig( "core_float" );
     FigureDumpEqui  = addphfig( "core_equi"  );
     FigureDumpScan  = addphfig( "lynx_equi"  );

     Lynxrecrdsmbk( FigureDumpFloat, FigureRds->LAYERTAB[ RDS_ABOX ] );
     Lynxrecrdsmbk( FigureDumpEqui,  FigureRds->LAYERTAB[ RDS_ABOX ] );
     Lynxrecrdsmbk( FigureDumpScan,  FigureRds->LAYERTAB[ RDS_ABOX ] );

     for ( FirstEqui = ScanEqui = HeadEqui;
           ScanEqui != (rdsrec_list *)NULL;
           ScanEqui  = LYNX_EQUI( ScanEqui ) )
     {
       Capa = GET_LYNX_CAPA_LAYER( GetRdsLayer( ScanEqui ) );

       if ( Capa != RDS_LYNX_CAPA_EMPTY ) 
       {
         SignalCapa += ( ScanEqui->DX * ScanEqui->DY ) * Capa;
       }

       if ( ScanEqui->NAME != (char *)NULL )
       {
         if ( ( ! IsRdsConInter( ScanEqui ) ) &&
              ( ( IsRdsFigRec( ScanEqui ) ) ||
                ( ! IsRdsRefCon( ScanEqui ) ) ) )
         {
           if ( ( IsRdsConExter( ScanEqui ) ) ||
                ( ( IsRdsFigRec( ScanEqui ) ) &&
                  ( IsRdsRefCon( ScanEqui ) ) ) )
           {
             SignalType    = EXTERNAL;
             ConnectorName = ScanEqui->NAME;
           }

           for ( ScanPtype  = SignalPtype;
                 ScanPtype != (ptype_list *)NULL;
                 ScanPtype  = ScanPtype->NEXT )
           {
             if ( (char *)(ScanPtype->DATA) == ScanEqui->NAME ) break;
           }

           if ( ScanPtype == (ptype_list *)NULL )
           {
             SignalPtype = addptype
             (
               SignalPtype, LYNX_GOOD,
               (void *)( ScanEqui->NAME )
             );
           }
         }
       }

       if ( Core )
       {
         if ( IsRdsSegment( ScanEqui ) )
         {
           LayerMbk = GetLynxAttribute( ScanEqui );
           LayerRds = GetRdsLayer( ScanEqui );

           if ( ( ( LayerMbk == NTRANS ) ||
                  ( LayerMbk == PTRANS ) ) &&
                  ( LayerRds != RDS_GATE ) )
           {
             SignalFloat = 0;
           }
         }
         else
         if ( ( IsRdsConnector( ScanEqui ) ) ||
              ( IsRdsReference( ScanEqui ) ) )
         {
           SignalFloat = 0;
         }
       }

       if ( IsLynxEndEqui( ScanEqui ) )
       {
         if ( SignalFloat )
         {
           LynxDumpEqui( FigureDumpFloat, FirstEqui );
           FoundFloat = 1;
         }
 
         if ( SignalPtype != (ptype_list *)NULL )
         {
           for ( Signal  = LogicalFigure->LOSIG;
                 Signal != (losig_list *)NULL;
                 Signal  = Signal->NEXT )
           {
             for ( ScanPtype  = SignalPtype;
                   ScanPtype != (ptype_list *)NULL;
                   ScanPtype  = ScanPtype->NEXT )
             {
               ScanSignalChain = Signal->NAMECHAIN;

               while ( ScanSignalChain != (chain_list *)NULL )
               {
                 if ( ScanPtype->DATA == ScanSignalChain->DATA )
                 {
                    DeleteChain     = ScanSignalChain;
                    ScanSignalChain = ScanSignalChain->NEXT;
                    ScanPtype->TYPE = LYNX_BAD;

                    Signal->NAMECHAIN = delchain
                    (
                      Signal->NAMECHAIN,
                      DeleteChain
                    );
                 }
                 else
                 {
                   ScanSignalChain  = ScanSignalChain->NEXT;
                 }
               }
             }
           }
         }

         SignalChain = (chain_list *)NULL;

         for ( ScanPtype  = SignalPtype;
               ScanPtype != (ptype_list *)NULL;
               ScanPtype  = ScanPtype->NEXT )
         {
           if ( ScanPtype->TYPE == LYNX_GOOD )
           {
             SignalChain = addchain( SignalChain, ScanPtype->DATA );
           }
         }

         freeptype ( SignalPtype );

         Signal  = addlosig
         (
           LogicalFigure,
           SignalIndex++,
           SignalChain,
           SignalType,
           SignalCapa
         );

         if ( ( Signal->NAMECHAIN       != (chain_list *)NULL ) &&
              ( Signal->NAMECHAIN->NEXT != (chain_list *)NULL ) )
         {
           Signal->NAMECHAIN->DATA = (void *)getsigname( Signal );
           freechain( Signal->NAMECHAIN->NEXT );
           Signal->NAMECHAIN->NEXT = (chain_list *)NULL;
         }

         if ( SignalType == EXTERNAL )
         {
           for ( LogicalConnector  = LogicalFigure->LOCON;
                 LogicalConnector != (locon_list *)NULL;
                 LogicalConnector  = LogicalConnector->NEXT )
           {
             if ( LogicalConnector->NAME == ConnectorName ) break;
           }

           if ( LogicalConnector == (locon_list *)NULL)
           {
             LogicalConnector = addlocon
             (
               LogicalFigure, ConnectorName,
               Signal, UNKNOWN
             );

             LogicalConnector->USER = (ptype_list *)FirstEqui;
           }
           else
           {
             ErrorPhysicalConnector( ConnectorName, Core );

             if ( Core )
             {
               LynxDumpEqui( FigureDumpEqui, 
                             FirstEqui );
               LynxDumpEqui( FigureDumpEqui, 
                             (rdsrec_list *)(LogicalConnector->USER) );
               savephfig( FigureDumpEqui );
             }
             exit( 1 );
           }

           IndexEqui = FirstEqui;

           Scan = (LynxScanEqui != (chain_list *)NULL);

           for ( IndexEqui  = FirstEqui;
                 IndexEqui != LYNX_EQUI( ScanEqui );
                 IndexEqui  = LYNX_EQUI( IndexEqui ) )
           {
             if ( ( IsRdsConExter( IndexEqui ) ) ||
                  ( ( IsRdsFigRec( IndexEqui ) ) &&
                    ( IsRdsRefCon( IndexEqui ) ) ) )
             {
               if ( Scan )
               {
                 if ( IsLynxScanEqui( LynxScanEqui, IndexEqui->NAME ) )
                 {
                   LynxDumpEqui( FigureDumpScan, FirstEqui );
                   Scan      = 0;
                   FoundScan = 1;
                 }
               }

               if ( IndexEqui->NAME != ConnectorName )
               {
                 ErrorPhysicalConnectors( IndexEqui->NAME, ConnectorName, Core );

                 if ( Core )
                 {
                   LynxDumpEqui( FigureDumpEqui, FirstEqui );
                   savephfig( FigureDumpEqui );
                 }
                 exit ( 1 );
               }
             }

             IndexEqui->USER = (void *)Signal;
           }
         }
         else
         {
           for ( IndexEqui  =  FirstEqui;
                 IndexEqui != LYNX_EQUI( ScanEqui );
                 IndexEqui  = LYNX_EQUI( IndexEqui ) )
           {
             IndexEqui->USER = (void *)Signal;
           }
         }

         SignalCapa  = 0.0;
         SignalPtype = (ptype_list *)NULL;
         SignalType  = INTERNAL;
         SignalFloat = Core;

         FirstEqui = LYNX_EQUI( ScanEqui );
       }
     }
 
     SignalIndex = SignalIndex - 1;

     if ( FoundScan ) savephfig( FigureDumpScan );

     if ( FoundFloat )
     {
       savephfig( FigureDumpFloat );
       SignalIndex = - SignalIndex;
     }

     return( SignalIndex );
   }

/*------------------------------------------------------------\
|                                                             |
|                     LynxBuildLogicalInstance                |
|                                                             |
\------------------------------------------------------------*/

   long LynxBuildLogicalInstance( FigureRds, LogicalFigure )

      rdsfig_list *FigureRds; 
      lofig_list  *LogicalFigure;
   {
     chain_list  *SignalChain;
     chain_list  *ScanChain;
     chain_list  *NameChain;

     lofig_list  *Model;
     lofig_list  *HeadModel;
     loins_list  *LogicalInstance;
     rdsins_list *InstanceRds;

     rdsrec_list *Rec;
     char        *RecName;

     char         Layer;
     char         BuildModel;
     long         Counter;

     Counter = 0;

     for ( InstanceRds  = FigureRds->INSTANCE;
           InstanceRds != (rdsins_list *)NULL;
           InstanceRds  = InstanceRds->NEXT )
     {
       SignalChain  = (chain_list *)NULL;
       NameChain    = (chain_list *)NULL;
       Model        = (lofig_list *)NULL;
       HeadModel    = (lofig_list *)NULL;

       if ( ! ( BuildModel = ( HeadModel == (lofig_list *)NULL )))
       {
         Model = getlomodel
         (  
           HeadModel, 
           InstanceRds->FIGNAME 
         );

         BuildModel = ( Model == (lofig_list *)NULL);
       }

       if ( BuildModel )
       {
         Model = HeadModel = addlomodel 
         (  
           HeadModel, 
           InstanceRds->FIGNAME 
         );
       }
      
       for ( Layer = 0; Layer < RWI_MAX_LAYER; Layer++ )
       {
         for ( Rec  = InstanceRds->LAYERTAB[ Layer ];
               Rec != (rdsrec_list *)NULL;
               Rec  = Rec->NEXT )
         {
           if ( ( ! IsRdsConInter( Rec ) ) &&
                ( ! IsRdsRefCon( Rec )   ) )   continue; 

           RecName = Rec->NAME;

           for ( ScanChain  = NameChain;
                 ScanChain != (chain_list *)NULL;
                 ScanChain  = ScanChain->NEXT )
           {
               if ( (char *)ScanChain->DATA  == RecName ) break;
           }

           if ( ScanChain == (chain_list *)NULL )
           {
             NameChain = addchain
             ( 
               NameChain, 
               RecName
             );

             if ( BuildModel )
             {
               addlocon
               ( 
                 Model, RecName, 
                 (losig_list *)NULL,
                 UNKNOWN
               );
             }

             SignalChain = addchain
             ( 
               SignalChain, 
               Rec->USER 
             );
           }
         }
       }

       Counter         = Counter + 1;
       LogicalInstance = addloins
       (
         LogicalFigure,
         InstanceRds->INSNAME,
         Model, SignalChain
       );

       freechain( NameChain );
    }

    return( Counter );
  }


/*------------------------------------------------------------\
|                                                             |
|                      LynxTreatTransistor                    |
|                                                             |
\------------------------------------------------------------*/

  void LynxTreatTransistor( Rectangle )

    rdsrec_list *Rectangle;
  {
    rdsrec_list *ScanRec;

    ScanRec = Rectangle;

    do
    {
      SetLynxTreatTransistor( ScanRec );

      ScanRec = LYNX_LINK( ScanRec );
    }
    while ( ScanRec != Rectangle );
  }

/*------------------------------------------------------------\
|                                                             |
|                     LynxBuildLogicalTransistor              |
|                                                             |
\------------------------------------------------------------*/


  long LynxBuildLogicalTransistor( FigureRds, LogicalFigure )

     rdsfig_list *FigureRds;
     lofig_list  *LogicalFigure;
  {
    rdsrec_list *Gate;
    rdsrec_list *Source;
    rdsrec_list *Drain;
    rdsrec_list *Diff;
    char         GateLayer;
    char         MbkLayer;
    char         Orient;
    long         Width;
    long         Length;
    long         Ps;
    long         Pd;
    long         Xs;
    long         Xd;
    long         Counter;
    
    Counter   = 0;
    GateLayer = GET_SEGMENT_LAYER( NTRANS, 0 );

    for ( Gate  = FigureRds->LAYERTAB[ GateLayer ];
          Gate != (rdsrec_list *)NULL;
          Gate  = Gate->NEXT )
    {
      if ( ( ! IsLynxTreatTransistor( Gate ) ) &&
           (   IsRdsSegment( Gate )          ) )
      {
        MbkLayer = GetLynxAttribute( Gate );

        if ( MbkLayer == NTRANS )
        {
          LynxTreatTransistor( Gate );

          Orient = GetLynxOrient( Gate );
          Source = (rdsrec_list *)NULL;
          Drain  = (rdsrec_list *)NULL;

          if ( ( Orient == LYNX_NORTH ) || 
               ( Orient == LYNX_SOUTH ) )
          {
            Length = Gate->DX;
            Width  = 0;
            Diff   = LYNX_LINK( Gate );

            while( Diff != Gate )
            {
              if ( GetRdsLayer( Diff ) != GateLayer ) 
              {
                if ( Source == (rdsrec_list *)NULL ) 
                {
                  Source = Diff;
                }
                else
                if ( Drain == (rdsrec_list *)NULL )
                {
                  Drain = Diff;
                }
         
                if ( Width < Diff->DY ) 
                {
                  Width = Diff->DY;
                }
              } 
              else
              {
                if ( Length < Diff->DX ) Length = Diff->DX;
              }

              Diff = LYNX_LINK( Diff );
            }
          }
          else
          {
            Length = Gate->DY;
            Width  = 0;
            Diff   = LYNX_LINK( Gate );

            while( Diff != Gate )
            {
              if ( GetRdsLayer( Diff ) != GateLayer ) 
              {
                if ( Source == (rdsrec_list *)NULL ) 
                {
                  Source = Diff;
                }
                else
                if ( Drain == (rdsrec_list *)NULL )
                {
                  Drain = Diff;
                }

                if ( Width < Diff->DX ) 
                {
                  Width = Diff->DX;
                }
              } 
              else
              {
                if ( Length < Diff->DY ) Length = Diff->DY;
              }

              Diff = LYNX_LINK( Diff );
            } 
          }

          if ( ( Source != (rdsrec_list *)NULL ) &&
               ( Drain  != (rdsrec_list *)NULL ) )
          {
            Ps = ( Source->DX << 1 ) + ( Source->DY << 1 );
            Pd = ( Drain->DX  << 1 ) + ( Drain->DY  << 1 );
            Xs = ( Source->DX * Source->DY ) / Width;
            Xd = ( Drain->DX  * Drain->DY  ) / Width;

            addlotrs
            (
              LogicalFigure,
              TRANSN,
              ( Gate->X + ( Gate->DX >> 1 ) ) * SCALE_X / RDS_LAMBDA,
              ( Gate->Y + ( Gate->DY >> 1 ) ) * SCALE_X / RDS_LAMBDA,
              Width  * SCALE_X / RDS_LAMBDA, 
              Length * SCALE_X / RDS_LAMBDA, 
              Ps     * SCALE_X / RDS_LAMBDA,
              Pd     * SCALE_X / RDS_LAMBDA, 
              Xs     * SCALE_X / RDS_LAMBDA, 
              Xd     * SCALE_X / RDS_LAMBDA, 
              (losig_list *)Gate->USER,
              (losig_list *)Source->USER,
              (losig_list *)Drain->USER
            );

            Counter = Counter + 1;
          }
        }
      }
    }

    GateLayer = GET_SEGMENT_LAYER( PTRANS, 0 );

    for ( Gate  = FigureRds->LAYERTAB[ GateLayer ];
          Gate != (rdsrec_list *)NULL;
          Gate  = Gate->NEXT )
    {
      if ( ( ! IsLynxTreatTransistor( Gate ) ) &&
           (   IsRdsSegment( Gate )          ) )
      {
        MbkLayer = GetLynxAttribute( Gate );

        if ( MbkLayer == PTRANS )
        {
          LynxTreatTransistor( Gate );

          Orient = GetLynxOrient( Gate );
          Source = (rdsrec_list *)NULL;
          Drain  = (rdsrec_list *)NULL;

          if ( ( Orient == LYNX_NORTH ) || 
               ( Orient == LYNX_SOUTH ) )
          {
            Length = Gate->DX;
            Width  = 0;
            Diff   = LYNX_LINK( Gate );

            while( Diff != Gate )
            {
              if ( GetRdsLayer( Diff ) != GateLayer ) 
              {
                if ( Source == (rdsrec_list *)NULL ) 
                {
                  Source = Diff;
                }
                else
                if ( Drain == (rdsrec_list *)NULL )
                {
                  Drain = Diff;
                }
         
                if ( Width < Diff->DY ) 
                {
                  Width = Diff->DY;
                }
              } 
              else
              {
                if ( Length < Diff->DX ) Length = Diff->DX;
              }

              Diff = LYNX_LINK( Diff );
            }
          }
          else
          {
            Length = Gate->DY;
            Width  = 0;
            Diff   = LYNX_LINK( Gate );

            while( Diff != Gate )
            {
              if ( GetRdsLayer( Diff ) != GateLayer ) 
              {
                if ( Source == (rdsrec_list *)NULL ) 
                {
                  Source = Diff;
                }
                else
                if ( Drain == (rdsrec_list *)NULL )
                {
                  Drain = Diff;
                }

                if ( Width < Diff->DX ) 
                {
                  Width = Diff->DX;
                }
              } 
              else
              {
                if ( Length < Diff->DY ) Length = Diff->DY;
              }

              Diff = LYNX_LINK( Diff );
            } 
          }

          if ( ( Source != (rdsrec_list *)NULL ) &&
               ( Drain  != (rdsrec_list *)NULL ) )
          {
            Ps = ( Source->DX << 1 ) + ( Source->DY << 1 );
            Pd = ( Drain->DX  << 1 ) + ( Drain->DY  << 1 );
            Xs = ( Source->DX * Source->DY ) / Width;
            Xd = ( Drain->DX  * Drain->DY  ) / Width;

            addlotrs
            (
              LogicalFigure,
              TRANSP,
              ( Gate->X + ( Gate->DX >> 1 ) ) * SCALE_X / RDS_LAMBDA,
              ( Gate->Y + ( Gate->DY >> 1 ) ) * SCALE_X / RDS_LAMBDA,
              Width  * SCALE_X / RDS_LAMBDA, 
              Length * SCALE_X / RDS_LAMBDA, 
              Ps     * SCALE_X / RDS_LAMBDA,
              Pd     * SCALE_X / RDS_LAMBDA, 
              Xs     * SCALE_X / RDS_LAMBDA, 
              Xd     * SCALE_X / RDS_LAMBDA, 
              (losig_list *)Gate->USER,
              (losig_list *)Source->USER,
              (losig_list *)Drain->USER
            );

            Counter = Counter + 1;
          }
        }
      }
    }

    return( Counter );
  }

/*------------------------------------------------------------\

/*------------------------------------------------------------\
|                                                             |
|                       LynxVectorizeConnector                |
|                                                             |
\------------------------------------------------------------*/

   char *LynxVectorizeConnector( LogicalFigure )
 
     lofig_list *LogicalFigure;
   {
     loins_list *Instance;

     if ( LogicalFigure->LOCON == (locon_list *)NULL ) 
     {
       return( LogicalFigure->NAME );
     }

     sortlocon( &LogicalFigure->LOCON );

     for ( Instance  = LogicalFigure->LOINS;
           Instance != (loins_list *)NULL;
           Instance  = Instance->NEXT )
     {
       if ( Instance->LOCON == (locon_list *)NULL ) 
       {
         return( Instance->INSNAME );
       }

       sortlocon( &Instance->LOCON );
     }

     return( (char *)NULL );
   }
