/* * $Id: util_RTU.c,v 1.2 2002/09/30 16:21:19 czo Exp $ * * /----------------------------------------------------------------\ * | | * | A l l i a n c e C A D S y s t e m | * | S i l i c o n E n s e m b l e / A l l i a n c e | * | | * | Author : Jean-Paul CHAPUT | * | E-mail : alliance-users@asim.lip6.fr | * | ============================================================== | * | C Module : "./util_RTU.c" | * | ************************************************************** | * | U p d a t e s | * | | * \----------------------------------------------------------------/ */ # include "util_Defs.h" # include "debugoff.h" # define LAYERS_NUMBER 6 # define LAYERS_ALIAS 3 # define TRACK_PITCH MBKSCALE(5) # define F_PITCH_INF 0x00000001 # define F_PITCH_SUP 0x00000002 # define HT_TERM_SIZE 1024 # define STRING_OBSTACLE "obs" /* ------------------------------------------------------------------ * Internal types. */ typedef struct obsTrack_s { long min; long max; } obsTrack_t; /* ------------------------------------------------------------------ * Local variables (prefix 'LV_'). */ static struct phfig *LV_phfig; static struct obsTrack_s *LV_ttObs[LAYERS_NUMBER]; static char LV_tLayersNames[LAYERS_NUMBER][LAYERS_ALIAS]; static long LV_hTracksNumber; static long LV_vTracksNumber; static long LV_hTracksMax; static long LV_vTracksMax; static authtable *LV_htTerm; /* ------------------------------------------------------------------ * Internal functions. */ # define SETMIN(v,m) ((v) = m_Min((v),(m))) # define SETMAX(v,m) ((v) = m_Max((v),(m))) # define LAMBDA2TRACKS(l) (lambda2pitch((l), F_PITCH_INF)) # define TRACKS2LAMBDA(t) ((t) * TRACK_PITCH) # define NORMVIASIDE(s) (((s) > MBK_VIA_SIDE) ? (s) : 0L) static void buildHTTerm __FP((struct phseg *apSeg)); static void delHTTerm __FP((void)); static long lambda2pitch __FP((long aLength, long aFlags)); static long getLayerTable __FP((char aLayer)); static void allocTableLayers __FP((void)); static void allocTableObs __FP((void)); static void addObs __FP((long aiTable, long aX1, long aY1, long aX2, long aY2)); static void seg2obs __FP((struct phseg *apSeg)); static void via2obs __FP((struct phvia *apVIA)); static void instance2obs __FP((struct phins *pIns)); extern void instances2obs __FP((void)); static void wiring2obs __FP((void)); static void obs2layers __FP((void)); /* * /----------------------------------------------------------------\ * | Functions Definitions | * \----------------------------------------------------------------/ */ /* ------------------------------------------------------------------ * Function : "buildHTTerm()". */ static void buildHTTerm(apSeg) struct phseg *apSeg; { struct phseg *pSeg; LV_htTerm = createauthtable (HT_TERM_SIZE); for (pSeg = apSeg; pSeg != NULL; pSeg = pSeg->NEXT) { if (pSeg->NAME == NULL) { eprinth ("rtu"); eprintf ("\n Segment (%ld,%ld) (%ld,%ld) width %ld layer id %d", pSeg->X1, pSeg->Y1, pSeg->X2, pSeg->Y2, pSeg->WIDTH, (int)pSeg->LAYER); eprintf ("\n doesn't have a name.\n"); EXIT (1); } if (!isCALU (pSeg->LAYER)) continue; if (searchauthelem (LV_htTerm, pSeg->NAME)) continue; addauthelem (LV_htTerm, pSeg->NAME, 0); } } /* ------------------------------------------------------------------ * Function : "delHTTerm()". */ static void delHTTerm() { destroyauthtable (LV_htTerm); } /* ------------------------------------------------------------------ * Function : "lambda2pitch()". */ static long lambda2pitch(aLength, aFlags) long aLength; long aFlags; { long pitch; pitch = aLength / TRACK_PITCH; if (aFlags & F_PITCH_SUP) pitch += (aLength % TRACK_PITCH) ? 1 : 0; return (pitch); } /* ------------------------------------------------------------------ * Function : "getLayerTable()". */ static long getLayerTable(aLayer) char aLayer; { long iTable, iAlias; for (iTable = 1; iTable < LAYERS_NUMBER; iTable++) { for (iAlias = 0; iAlias < LAYERS_ALIAS; iAlias++) { if (LV_tLayersNames[iTable][iAlias] == aLayer) { return (iTable); } } } /* No table found : return LAYERS_NUMBER. */ return (LAYERS_NUMBER); } /* ------------------------------------------------------------------ * Function : "allocTableLayers()". */ static void allocTableLayers() { /* Base layer. */ LV_tLayersNames[0][0] = ALU1; LV_tLayersNames[1][0] = ALU2; LV_tLayersNames[2][0] = ALU3; LV_tLayersNames[3][0] = ALU4; LV_tLayersNames[4][0] = ALU5; LV_tLayersNames[5][0] = ALU6; /* Associated obstacles layer. */ LV_tLayersNames[0][1] = TALU1; LV_tLayersNames[1][1] = TALU2; LV_tLayersNames[2][1] = TALU3; LV_tLayersNames[3][1] = TALU4; LV_tLayersNames[4][1] = TALU5; LV_tLayersNames[5][1] = TALU6; /* Associated terminal layer. */ LV_tLayersNames[0][2] = CALU1; LV_tLayersNames[1][2] = CALU2; LV_tLayersNames[2][2] = CALU3; LV_tLayersNames[3][2] = CALU4; LV_tLayersNames[4][2] = CALU5; LV_tLayersNames[5][2] = CALU6; } /* ------------------------------------------------------------------ * Function : "allocTableObs()". */ static void allocTableObs() { long iTable, iTrack; long tracksNumber, trackMax; LV_hTracksNumber = LAMBDA2TRACKS (LV_phfig->YAB2 - LV_phfig->YAB1) + 1; LV_hTracksMax = LAMBDA2TRACKS (LV_phfig->XAB2 - LV_phfig->XAB1) + 1; LV_vTracksNumber = LAMBDA2TRACKS (LV_phfig->XAB2 - LV_phfig->XAB1) + 1; LV_vTracksMax = LAMBDA2TRACKS (LV_phfig->YAB2 - LV_phfig->YAB1) + 1; for (iTable = 0; iTable < LAYERS_NUMBER; iTable++) { if (!(iTable % 2)) { /* i.e. ALU1, ALU3 & ALU5 : vertical tracks. */ tracksNumber = LV_vTracksNumber; trackMax = LV_vTracksMax; } else { /* i.e. ALU2, ALU4 & ALU6 : horizontal tracks. */ tracksNumber = LV_hTracksNumber; trackMax = LV_hTracksMax; } LV_ttObs[iTable] = (struct obsTrack_s*)mbkalloc ( sizeof (struct obsTrack_s) * tracksNumber); /* Initialize table boundaries. */ for (iTrack = 0; iTrack < tracksNumber; iTrack++) { LV_ttObs[iTable][iTrack].min = trackMax; LV_ttObs[iTable][iTrack].max = 0L; } } } /* ------------------------------------------------------------------ * Function : "addObs()". */ static void addObs(aiTable, aX1, aY1, aX2, aY2) long aiTable; long aX1, aY1, aX2, aY2; { long iTrack, ivTrackMin, ivTrackMax; long hTrackMin, hTrackMax; if (!(aiTable % 2)) { /* i.e. ALU1, ALU3 & ALU5 : vertical tracks. */ hTrackMin = lambda2pitch (aY1 - LV_phfig->YAB1, F_PITCH_INF); hTrackMax = lambda2pitch (aY2 - LV_phfig->YAB1, F_PITCH_SUP); ivTrackMin = lambda2pitch (aX1 - LV_phfig->XAB1, F_PITCH_INF); ivTrackMax = lambda2pitch (aX2 - LV_phfig->XAB1, F_PITCH_SUP); } else { /* i.e. ALU2, ALU4 & ALU6 : horizontal tracks. */ hTrackMin = lambda2pitch (aX1 - LV_phfig->XAB1, F_PITCH_INF); hTrackMax = lambda2pitch (aX2 - LV_phfig->XAB1, F_PITCH_SUP); ivTrackMin = lambda2pitch (aY1 - LV_phfig->YAB1, F_PITCH_INF); ivTrackMax = lambda2pitch (aY2 - LV_phfig->YAB1, F_PITCH_SUP); } for (iTrack = ivTrackMin; iTrack <= ivTrackMax; iTrack++) { SETMIN (LV_ttObs[aiTable][iTrack].min, hTrackMin); SETMAX (LV_ttObs[aiTable][iTrack].max, hTrackMax); } } /* ------------------------------------------------------------------ * Function : "seg2obs()". */ static void seg2obs(apSeg) struct phseg *apSeg; { long iTable, X1, Y1, X2, Y2, trackWidth; /* Special policy for xALU1 layers : segments are all passed "as is" * in TALU1. */ switch (apSeg->LAYER) { case ALU1: case CALU1: case TALU1: /* Do nothing. *addphseg (LV_phfig, * TALU1, * apSeg->WIDTH, * apSeg->X1, * apSeg->Y1, * apSeg->X2, * apSeg->Y2, * STRING_OBSTACLE * ); */ return; } iTable = getLayerTable (apSeg->LAYER); if (iTable == LAYERS_NUMBER) return; trackWidth = getLayerTrackWidth (apSeg->LAYER); switch (apSeg->TYPE) { case UP: case DOWN: X1 = apSeg->X1 - (apSeg->WIDTH - trackWidth) / 2; X2 = apSeg->X2 + (apSeg->WIDTH - trackWidth) / 2; Y1 = apSeg->Y1; Y2 = apSeg->Y2; break; case LEFT: case RIGHT: default: X1 = apSeg->X1; X2 = apSeg->X2; Y1 = apSeg->Y1 - (apSeg->WIDTH - trackWidth) / 2; Y2 = apSeg->Y2 + (apSeg->WIDTH - trackWidth) / 2; break; } addObs (iTable, X1, Y1, X2, Y2); } /* ------------------------------------------------------------------ * Function : "via2obs()". */ static void via2obs(apVIA) struct phvia *apVIA; { long iTable, X1, Y1, X2, Y2, trackWidth; char layer; # if 0 char topLayer; # endif if (apVIA->NAME == NULL) { eprinth ("rtu"); eprintf ("\n VIA (%ld,%ld) size (%ld,%ld) type id %d", MBKUNSCALE (apVIA->XVIA), MBKUNSCALE (apVIA->YVIA), MBKUNSCALE (apVIA->DX), MBKUNSCALE (apVIA->DY), (int)apVIA->TYPE); eprintf ("\n doesn't have a name.\n"); EXIT (1); } __DBG( fprintf (stderr, "via2obs(): VIA at %ld %ld.\n", apVIA->XVIA, apVIA->YVIA); ) /* Check if this VIA belongs to an terminal net. */ /* if (searchauthelem (LV_htTerm, apVIA->NAME)) return; */ for (layer = getBottomVIALayer (apVIA->TYPE); TRUE; layer = getUpVIALayer (apVIA->TYPE, layer)) { iTable = getLayerTable (layer); if ((!isvdd (apVIA->NAME) && !isvss (apVIA->NAME)) || (iTable % 2)) { if (iTable != LAYERS_NUMBER) { __DBG (fprintf (stderr, " OBS Layer %d\n", (int)layer); ) trackWidth = getLayerTrackWidth (layer); X1 = apVIA->XVIA - (NORMVIASIDE(apVIA->DX) - trackWidth) / 2; X2 = apVIA->XVIA + (NORMVIASIDE(apVIA->DX) - trackWidth) / 2; Y1 = apVIA->YVIA - (NORMVIASIDE(apVIA->DY) - trackWidth) / 2; Y2 = apVIA->YVIA + (NORMVIASIDE(apVIA->DY) - trackWidth) / 2; addObs (iTable, X1, Y1, X2, Y2); } } if (layer == getTopVIALayer (apVIA->TYPE)) break; } # if 0 fprintf (stderr, " Intermediate layers :\n"); layer = getUpVIALayer (apVIA->TYPE, getBottomVIALayer (apVIA->TYPE)); topLayer = getTopVIALayer (apVIA->TYPE); while (layer != topLayer) { iTable = getLayerTable (layer); if (iTable != LAYERS_NUMBER) { fprintf (stderr, " OBS Layer %d\n", (int)layer); trackWidth = getLayerTrackWidth (layer); X1 = apVIA->XVIA - (NORMVIASIDE(apVIA->DX) - trackWidth) / 2; X2 = apVIA->XVIA + (NORMVIASIDE(apVIA->DX) - trackWidth) / 2; Y1 = apVIA->YVIA - (NORMVIASIDE(apVIA->DY) - trackWidth) / 2; Y2 = apVIA->YVIA + (NORMVIASIDE(apVIA->DY) - trackWidth) / 2; addObs (iTable, X1, Y1, X2, Y2); } layer = getUpVIALayer (apVIA->TYPE, layer); } # endif } /* ------------------------------------------------------------------ * Function : "instance2obs()". */ static void instance2obs(apIns) struct phins *apIns; { struct phfig *pFig; struct phseg *pSeg, flatSeg; # if 0 struct phvia *pVIA, flatVIA; char *viaName = STRING_OBSTACLE; # endif pFig = getphfig (apIns->FIGNAME, 'A'); for (pSeg = pFig->PHSEG; pSeg != NULL; pSeg = pSeg->NEXT) { if ( isvdd (pSeg->NAME ) || isvss (pSeg->NAME )) continue; if (!isCALU (pSeg->LAYER) && !isobs (pSeg)) continue; /*if (isCALU (pSeg->LAYER) || !isobs (pSeg)) continue;*/ xyflatseg (&flatSeg, pSeg, apIns->XINS, apIns->YINS, pFig->XAB1, pFig->YAB1, pFig->XAB2, pFig->YAB2, apIns->TRANSF); seg2obs (&flatSeg); } # if 0 for (pVIA = pFig->PHVIA; pVIA != NULL; pVIA = pVIA->NEXT) { if (isvdd (pVIA->NAME) || isvss (pVIA->NAME)) continue; xyflatvia (&flatVIA, pVIA, apIns->XINS, apIns->YINS, pFig->XAB1, pFig->YAB1, pFig->XAB2, pFig->YAB2, apIns->TRANSF); flatVIA.NAME = (pVIA->NAME != NULL) ? pVIA->NAME : viaName; via2obs (&flatVIA); } # endif } /* ------------------------------------------------------------------ * Function : "wiring2obs()". */ static void wiring2obs() { struct phseg *pSeg; struct phvia *pVIA; for (pSeg = LV_phfig->PHSEG; pSeg != NULL; pSeg = pSeg->NEXT) { /* Terminals (i.e. segments in CALUx layers) are not to be * considered as obstacles. */ /*if (!isCALU (pSeg->LAYER)) seg2obs (pSeg);*/ if (!isvdd (pSeg->NAME) && !isvss (pSeg->NAME)) seg2obs (pSeg); } for (pVIA = LV_phfig->PHVIA; pVIA != NULL; pVIA = pVIA->NEXT) { /* Skip default VIA, as they belongs to regular wiring. */ if (pVIA->DX || pVIA->DY) via2obs (pVIA); } } /* ------------------------------------------------------------------ * Function : "instances2obs()". */ extern void instances2obs() { struct phins *pIns; for (pIns = LV_phfig->PHINS; pIns != NULL; pIns = pIns->NEXT) { instance2obs (pIns); } } /* ------------------------------------------------------------------ * Function : "obs2layers()". */ static void obs2layers() { long iTable, iTrack, tracksNumber; long X1, Y1, X2, Y2, width; char layer; for (iTable = 0; iTable < LAYERS_NUMBER; iTable++) { layer = getTALU (LV_tLayersNames[iTable][0]); width = getLayerTrackWidth (layer); if (!(iTable % 2)) { /* i.e. ALU1, ALU3 & ALU5 : vertical tracks. */ tracksNumber = LV_vTracksNumber; } else { /* i.e. ALU2, ALU4 & ALU6 : horizontal tracks. */ tracksNumber = LV_hTracksNumber; } for (iTrack = 0; iTrack < tracksNumber; iTrack++) { /* Skip empty tracks. */ if (LV_ttObs[iTable][iTrack].min >= LV_ttObs[iTable][iTrack].max) continue; if (!(iTable % 2)) { /* i.e. ALU1, ALU3 & ALU5 : vertical tracks. */ X1 = X2 = LV_phfig->XAB1 + TRACKS2LAMBDA (iTrack); Y1 = LV_phfig->YAB1 + TRACKS2LAMBDA (LV_ttObs[iTable][iTrack].min); Y2 = LV_phfig->YAB1 + TRACKS2LAMBDA (LV_ttObs[iTable][iTrack].max); } else { /* i.e. ALU2, ALU4 & ALU6 : horizontal tracks. */ Y1 = Y2 = LV_phfig->YAB1 + TRACKS2LAMBDA (iTrack); X1 = LV_phfig->XAB1 + TRACKS2LAMBDA (LV_ttObs[iTable][iTrack].min); X2 = LV_phfig->XAB1 + TRACKS2LAMBDA (LV_ttObs[iTable][iTrack].max); } addphseg (LV_phfig, layer, width, X1, Y1, X2, Y2, STRING_OBSTACLE); } /* End of "for (iTrack ...)". */ } /* End of "for (iTable ...)". */ } /* ------------------------------------------------------------------ * Function : "rtu()". */ extern void rtu(aPhfig) struct phfig *aPhfig; { LV_phfig = aPhfig; allocTableLayers (); allocTableObs (); buildHTTerm (aPhfig->PHSEG); instances2obs (); wiring2obs (); obs2layers (); delHTTerm (); }