/* * $Id: DEF_drive.c,v 1.11 2004/09/29 21:40:46 jpc 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 : "./DEF_drive.c" | * | ************************************************************** | * | U p d a t e s | * | | * \----------------------------------------------------------------/ */ # include "debugoff.h" # include "util_Defs.h" # include "DEF_drive.h" /* ------------------------------------------------------------------ * Internal types and defines. */ # define C_DIRECTION_NONE ((char)0) # define C_DIRECTION_INPUT ((char)1) # define C_DIRECTION_OUTPUT ((char)2) # define C_DIRECTION_TRISTATE ((char)3) # define C_DIRECTION_INOUT ((char)4) # define C_DIRECTION_FEEDTHRU ((char)5) # define C_USE_NONE ((char)0) # define C_USE_SIGNAL ((char)1) # define C_USE_ANALOG ((char)2) # define C_USE_POWER ((char)3) # define C_USE_GROUND ((char)4) # define C_USE_CLOCK ((char)5) # define TTERM_SIZE 1024 # define PTYPE_PHFIG 1024 # define PTYPE_LOFIG 1025 # define F_REGULAR_NET 0x00000001 # define F_SPECIAL_NET 0x00000002 # define F_SEG_WIDTH 0x00000001 # define F_SEG_STRIPE 0x00000002 /* ------------------------------------------------------------------ * Internal types. */ typedef struct row_s { char *rowName; char *rowType; long x; long y; long orient; long doNumber; long byNumber; long stepX; long stepY; struct row_s *next; } row_t; typedef struct track_s { char axisName; long start; long doNumber; long step; char *routingLayers; long x; long y; struct track_s *next; } track_t; typedef struct blockage_s { long x; long y; long width; long height; struct blockage_s *next; } blockage_t; /* ------------------------------------------------------------------ * Internal variables. */ static FILE *DEF_FILE; static long LV_Flags = 0L; static long LV_localFlags = 0L; static char *LV_name; static struct lofig *LV_lofig; static struct phfig *LV_phfig; static struct row_s *LV_row; static struct track_s *LV_track; static struct blockage_s *LV_blockage; static struct authtable *LV_htTerm; static char routingLayers3[256] = "ALU1 ALU2 ALU3"; static char routingLayers4[256] = "ALU1 ALU2 ALU3 ALU4"; static char routingLayers6[256] = "ALU1 ALU2 ALU3 ALU4 ALU5 ALU6"; /* ------------------------------------------------------------------ * Local functions. */ static struct phins *getphinslink __FP((struct loins *apLoins)); static void buildphinslinks __FP((void)); static void buildtterm __FP((void)); static void freetterm __FP((void)); static void freephinslinks __FP((void)); static void swapOrient __FP((char *apSameOrient, char *apOppositeOrient)); static char normOrient __FP((char aOrient)); static long orientPhfig __FP((struct phfig *apPhfig, char *apSameOrient, char *apOppositeOrient)); static char *DIRtoa __FP((char acDIR)); static char *USEtoa __FP((char acUSE)); static char *strLCat __FP((char *asLine, char *asEl, long *aplLine, long alMax)); static void fprintDIEAREA __FP((void)); static struct row_s *newrow __FP((void)); static void freerow __FP((void)); static void ref2ROW __FP((void)); static struct row_s *getBaseRow __FP((long aX, long aY, char aOrient)); static void fprintROWS __FP((void)); static struct track_s *newtrack __FP((void)); static void freetrack __FP((void)); static void ref2TRACK __FP((void)); static void fprintTRACKS __FP((void)); static struct blockage_s *newblockage __FP((void)); static void freeblockage __FP((void)); static void ref2BLOCKAGE __FP((void)); static void fprintBLOCKAGE __FP((void)); static void fprintVIAMATRIX __FP((char aType, long aWidth, long aHeight)); static void fprintVIAS __FP((void)); static long checkPhins __FP((struct phins *apPhins)); static void fprintCOMPONENTS __FP((void)); static void fprintPIN __FP((struct locon *apLocon, struct phcon *apPhcon, char *asState)); static void fprintPINS __FP((void)); static void fprintWIRESEG __FP((struct phseg *apPhseg, long aFlags)); static void fprintWIREVIA __FP((struct phvia *apPhvia, long aFlags)); static void fprintWIRES __FP((struct losig *apLosig)); static void fprintNET __FP((struct losig *apLoSig, char aUse)); static void fprintNETS __FP((void)); static void fprintSPECIALNETS __FP((void)); static void fprintDEF __FP((void)); /* * /----------------------------------------------------------------\ * | Functions Definitions | * \----------------------------------------------------------------/ */ /* ------------------------------------------------------------------ * Function : "getphinslink()". */ static struct phins *getphinslink(apLoins) struct loins *apLoins; { struct ptype *pType; if ((pType = getptype (apLoins->USER, PTYPE_PHFIG)) == NULL) return (NULL); return ((struct phins*)pType->DATA); } /* ------------------------------------------------------------------ * Function : "buildphinslinks()". */ static void buildphinslinks() { struct loins *pLoins; struct phins *pPhins; long flag; flag = FALSE; /* Check if there is a physical figure. */ if (!LV_phfig) return; for (pLoins = LV_lofig->LOINS; pLoins != NULL; pLoins = pLoins->NEXT) { if ((pPhins = findphins (LV_phfig, pLoins->INSNAME))) { if (pLoins->FIGNAME != pPhins->FIGNAME) { flag = TRUE; eprinth (NULL); eprintf ("Instances of \"%s\" have NOT the same physical", pLoins->INSNAME); eprintf (" and logical model :\n"); eprintf (" logical := \"%s\"", pLoins->FIGNAME); eprintf (" physical := \"%s\".\n", pPhins->FIGNAME); continue; } pLoins->USER = addptype (pLoins->USER, PTYPE_PHFIG, (void*)pPhins); pPhins->USER = addptype (pPhins->USER, PTYPE_LOFIG, (void*)pLoins); } } /* Check if all physical instances are in the netlist. */ for (pPhins = LV_phfig->PHINS; pPhins != NULL; pPhins = pPhins->NEXT) { if (!getptype (pPhins->USER, PTYPE_LOFIG)) { if (!flag) { /* Print the head error message. */ flag = TRUE; eprinth (NULL); eprintf ("The following physical instances are not in the"); eprintf (" netlist :\n"); } eprintf ("- \"%s\" (model \"%s\").\n", pPhins->INSNAME, pPhins->FIGNAME); } } if (flag) EXIT (1); } /* ------------------------------------------------------------------ * Function : "freephinslinks()". */ static void freephinslinks() { struct loins *pLoins; struct phins *pPhins; /* Check if there is a physical figure. */ if (!LV_phfig) return; for (pLoins = LV_lofig->LOINS; pLoins != NULL; pLoins = pLoins->NEXT) { if (pLoins->USER) pLoins->USER = delptype (pLoins->USER, PTYPE_PHFIG); } for (pPhins = LV_phfig->PHINS; pPhins != NULL; pPhins = pPhins->NEXT) { if (pPhins->USER) pPhins->USER = delptype (pPhins->USER, PTYPE_LOFIG); } } /* ------------------------------------------------------------------ * Function : "buildtterm()". */ static void buildtterm() { struct locon *pLocon; LV_htTerm = createauthtable (TTERM_SIZE); for (pLocon = LV_lofig->LOCON; pLocon != NULL; pLocon = pLocon->NEXT) { addauthelem (LV_htTerm, getsigname (pLocon->SIG), (long)pLocon->NAME); } } /* ------------------------------------------------------------------ * Function : "freetterm()". */ static void freetterm() { destroyauthtable (LV_htTerm); } /* ------------------------------------------------------------------ * Function : "swapOrient()". */ static void swapOrient(apSameOrient, apOppositeOrient) char *apSameOrient; char *apOppositeOrient; { char tmpOrient; tmpOrient = *apSameOrient; *apSameOrient = *apOppositeOrient; *apOppositeOrient = tmpOrient; } /* ------------------------------------------------------------------ * Function : "normOrient()". */ static char normOrient(aOrient) char aOrient; { char normOrient; switch (aOrient) { default: case DEF_N: normOrient = DEF_N; break; case DEF_FN: normOrient = DEF_N; break; case DEF_FS: normOrient = DEF_FS; break; case DEF_S: normOrient = DEF_FS; break; case DEF_W: normOrient = DEF_W; break; case DEF_FW: normOrient = DEF_W; break; case DEF_E: normOrient = DEF_FE; break; case DEF_FE: normOrient = DEF_FE; break; } return (normOrient); } /* ------------------------------------------------------------------ * Function : "getOppositeOrient()". */ static char getOppositeOrient(aOrient) char aOrient; { char oppositeOrient; switch (aOrient) { default: case DEF_N: oppositeOrient = DEF_FS; break; case DEF_FN: oppositeOrient = DEF_FS; break; case DEF_FS: oppositeOrient = DEF_N; break; case DEF_S: oppositeOrient = DEF_N; break; case DEF_W: oppositeOrient = DEF_FE; break; case DEF_FW: oppositeOrient = DEF_FE; break; case DEF_E: oppositeOrient = DEF_W; break; case DEF_FE: oppositeOrient = DEF_W; break; } return (oppositeOrient); } /* ------------------------------------------------------------------ * Function : "orientPhfig()". */ static long orientPhfig(apPhfig, apSameOrient, apOppositeOrient) struct phfig *apPhfig; char *apSameOrient; char *apOppositeOrient; { struct ePow_s *plPow; long sliceHeight; plPow = buildPow (apPhfig, ALU1, C_POWER_HORIZONTAL, ""); sliceHeight = (apPhfig->YAB2 - apPhfig->YAB1) / MBK_Y_SLICE; if (!plPow) { if (LV_Flags & F_TRUST_ORIENT) { *apSameOrient = DEF_N; *apOppositeOrient = DEF_FS; return (FALSE); } eprinth (NULL); eprintf ("\n Model \"%s\" have no horizontal ALU1 power supplies.", apPhfig->NAME); eprintf ("\n Can't guess allowed orientations.\n"); EXIT (1); } switch (plPow->Type) { default: case C_POWER_ISVSS: *apSameOrient = DEF_N; *apOppositeOrient = DEF_FS; break; case C_POWER_ISVDD: *apSameOrient = DEF_FS; *apOppositeOrient = DEF_N; break; } if (!(sliceHeight % 2)) *apOppositeOrient = *apSameOrient; freePow (plPow); return (TRUE); } /* ------------------------------------------------------------------ * Function : "DIRtoa()". */ static char *DIRtoa(acDIR) char acDIR; { switch(acDIR) { case C_DIRECTION_NONE: return((char*)NULL); case C_DIRECTION_INPUT: return("INPUT"); case C_DIRECTION_OUTPUT: return("OUTPUT"); case C_DIRECTION_TRISTATE: return("OUTPUT"); case C_DIRECTION_INOUT: return("INOUT"); case C_DIRECTION_FEEDTHRU: return("FEEDTHRU"); } return((char*)NULL); } /* ------------------------------------------------------------------ * Function : "USEtoa()". */ static char *USEtoa(acUSE) char acUSE; { switch(acUSE) { case C_USE_NONE: return((char*)NULL); case C_USE_SIGNAL: return("SIGNAL"); case C_USE_ANALOG: return("ANALOG"); case C_USE_POWER: return("POWER"); case C_USE_GROUND: return("GROUND"); case C_USE_CLOCK: return("CLOCK"); } return((char*)NULL); } /* ------------------------------------------------------------------ * Function : "strLCat()". */ static char *strLCat(asLine, asEl, aplLine, alMax) char *asLine, *asEl; long *aplLine, alMax; { long lCopy; /* Copy the string `asEl' if there is enougth place. */ lCopy = m_Min(alMax - *aplLine - 1, strlen(asEl)); strncpy(asLine + *aplLine, asEl, lCopy); *aplLine += lCopy; /* Terminate the string by a zero. */ asLine[(*aplLine)] = (char)0; return(asLine); } /* ------------------------------------------------------------------ * Function : "fprintDIEAREA()". */ static void fprintDIEAREA() { if (LV_phfig) { fprintf (DEF_FILE, "\nDIEAREA ( %ld %ld ) ( %ld %ld ) ;\n", MBK2DEF_length (LV_phfig->XAB1), MBK2DEF_length (LV_phfig->YAB1), MBK2DEF_length (LV_phfig->XAB2), MBK2DEF_length (LV_phfig->YAB2)); } } /* ------------------------------------------------------------------ * Function : "newrow()". */ static struct row_s *newrow() { struct row_s *pRow; pRow = (row_t*)mbkalloc (sizeof (row_t)); pRow->next = LV_row; return (LV_row = pRow); } /* ------------------------------------------------------------------ * Function : "freerow()". */ static void freerow() { struct row_s *pRow; while (LV_row) { pRow = LV_row->next; mbkfree (LV_row->rowName); mbkfree (LV_row->rowType); mbkfree (LV_row); LV_row = pRow; } } /* ------------------------------------------------------------------ * Function : "ref2ROW()". */ static void ref2ROW() { struct phref *pPhref; struct row_s *pRow; if (LV_phfig) { for (pPhref = LV_phfig->PHREF; pPhref != NULL; pPhref = pPhref->NEXT) { if (!strncmp (pPhref->NAME, "row_", 4)) { pRow = newrow (); MBK2DEF_row (pPhref, &pRow->rowName, &pRow->rowType, &pRow->orient, &pRow->doNumber, &pRow->byNumber, &pRow->stepX, &pRow->stepY, &pRow->x, &pRow->y); } } } } /* ------------------------------------------------------------------ * Function : "hasROW()". */ extern long hasROW(apPhfig) struct phfig *apPhfig; { struct phref *pPhref; for (pPhref = apPhfig->PHREF; pPhref != NULL; pPhref = pPhref->NEXT) { if (!strncmp (pPhref->NAME, "row_", 4)) { return (TRUE); } } return(FALSE); } /* ------------------------------------------------------------------ * Function : "buildROWS()". */ extern long buildROWS(apPhfig) struct phfig *apPhfig; { struct phins *pIns; long iRow; long rowGridX0, rowGridY0, rowGridIns, rowSizeX, rowSizeY; char sameOrient, oppositeOrient; char rowName[1024]; if (hasROW(apPhfig)) return (FALSE); pIns = NULL; rowGridX0 = apPhfig->XAB1; rowGridY0 = apPhfig->YAB1; sameOrient = DEF_N; oppositeOrient = DEF_FS; rowSizeX = (apPhfig->XAB2 - apPhfig->XAB1) / MBK_X_GRID; rowSizeY = (apPhfig->YAB2 - apPhfig->YAB1) / MBK_Y_SLICE; for (pIns = apPhfig->PHINS; pIns != NULL; pIns = pIns->NEXT) { /* Skip unpitched instances. */ if ((pIns->XINS - apPhfig->XAB1) % MBK_X_GRID) continue; if ((pIns->YINS - apPhfig->YAB1) % MBK_X_GRID) continue; if (!orientPhfig (getphfig (pIns->FIGNAME, 'A'), &sameOrient, &oppositeOrient)) continue; mprintf2 (" o Taking \"%s\" as reference for the ROW grid.\n", pIns->INSNAME); rowGridX0 = apPhfig->XAB1; rowGridY0 = apPhfig->YAB1 + (pIns->YINS - apPhfig->YAB1) % MBK_Y_SLICE; rowSizeX = (apPhfig->XAB2 - apPhfig->XAB1) / MBK_X_GRID; rowSizeY = (apPhfig->YAB2 - rowGridY0) / MBK_Y_SLICE; rowGridIns = (pIns->YINS - rowGridY0) / MBK_Y_SLICE; switch (pIns->TRANSF) { default: case SYM_X: case NOSYM: break; case SYM_Y: case SYMXY: swapOrient (&sameOrient, &oppositeOrient); break; /* We do not allow rotated instances. */ case ROT_P: case ROT_M: case SY_RP: case SY_RM: continue; } __DBG ( fflush (stdout); fprintf (stderr, "pIns->YINS := %ld.\n", pIns->YINS); fprintf (stderr, "apPhfig->YAB1 := %ld.\n", apPhfig->YAB1); fprintf (stderr, "rowGridY0 := %ld.\n", rowGridY0); fprintf (stderr, "rowGridIns := %ld.\n", rowGridIns); fflush (stderr); ) if (rowGridIns % 2) swapOrient (&sameOrient, &oppositeOrient); break; } /* Restore the opposite orient, when the cell is 2*N slices tall. */ oppositeOrient = getOppositeOrient (sameOrient); for (iRow = 0; iRow < rowSizeY; iRow++) { sprintf (rowName, "ROW_%ld", iRow); DEF2MBK_row (apPhfig, rowName, "core", (iRow % 2) ? oppositeOrient : sameOrient, rowSizeX, 1, MBK2DEF_length (MBK_X_GRID), MBK2DEF_length (MBK_Y_SLICE), rowGridX0, rowGridY0 + iRow * MBK_Y_SLICE ); } return (TRUE); } /* ------------------------------------------------------------------ * Function : "getBaseRow()". */ static struct row_s *getBaseRow(aX, aY, aOrient) long aX, aY; char aOrient; { struct row_s *pRow; long rowMax; char orient; for (pRow = LV_row; pRow != NULL; pRow = pRow->next) { orient = normOrient (aOrient); switch (aOrient) { case DEF_N: case DEF_FN: case DEF_FS: case DEF_S: if (pRow->y != aY) continue; rowMax = DEF2MBK_length (pRow->stepX) * pRow->doNumber; if ((aX < pRow->x) || (aX > pRow->x + rowMax)) continue; if (pRow->orient == orient) return (pRow); break; case DEF_W: case DEF_E: case DEF_FW: case DEF_FE: if (pRow->x != aX) continue; rowMax = DEF2MBK_length (pRow->stepY) * pRow->byNumber; if ((aY < pRow->y) || (aY > pRow->y + rowMax)) continue; if (pRow->orient == orient) return (pRow); break; } } return (NULL); } /* ------------------------------------------------------------------ * Function : "fprintROWS()". */ static void fprintROWS () { struct row_s *pRow; for (pRow = LV_row; pRow != NULL; pRow = pRow->next) { fprintf (DEF_FILE, "ROW %s %s %ld %ld %s DO %ld BY %ld STEP %ld %ld ;\n", pRow->rowName, pRow->rowType, pRow->x, pRow->y, DEF_orient2a(pRow->orient), pRow->doNumber, pRow->byNumber, pRow->stepX, pRow->stepY); } } /* ------------------------------------------------------------------ * Function : "newtrack()". */ static struct track_s *newtrack() { struct track_s *pTrack; pTrack = (track_t*)mbkalloc (sizeof (track_t)); pTrack->next = LV_track; return (LV_track = pTrack); } /* ------------------------------------------------------------------ * Function : "freetrack()". */ static void freetrack() { struct track_s *pTrack; while (LV_track) { pTrack = LV_track->next; mbkfree (LV_track->routingLayers); mbkfree (LV_track); LV_track = pTrack; } } /* ------------------------------------------------------------------ * Function : "ref2TRACK()". */ static void ref2TRACK() { struct phref *pPhref; struct track_s *pTrack; if (LV_phfig) { for (pPhref = LV_phfig->PHREF; pPhref != NULL; pPhref = pPhref->NEXT) { if (!strncmp (pPhref->NAME, "tracks.", 7)) { pTrack = newtrack (); MBK2DEF_track (pPhref, &pTrack->axisName, &pTrack->start, &pTrack->doNumber, &pTrack->step, &pTrack->routingLayers, &pTrack->x, &pTrack->y); } } } } /* ------------------------------------------------------------------ * Function : "buildTRACKS()". */ extern long buildTRACKS(apPhfig, aFlags) struct phfig *apPhfig; long aFlags; { long tracksX, tracksY, startX, startY; char *routingLayers; tracksX = ((apPhfig->XAB2 - apPhfig->XAB1) / MBK_X_GRID) - 1; tracksY = ((apPhfig->YAB2 - apPhfig->YAB1) / MBK_X_GRID) - 1; startX = apPhfig->XAB1 + MBK_X_GRID; startY = apPhfig->YAB1 + MBK_X_GRID; routingLayers = routingLayers6; if (aFlags & F_LAYERS_3) { routingLayers = routingLayers3; } if (aFlags & F_LAYERS_4) { routingLayers = routingLayers4; } /* Allocate the horizontal tracks. */ DEF2MBK_track (apPhfig, "Y", MBK2DEF_length (startY), tracksY, MBK2DEF_length (MBK_X_GRID), routingLayers, apPhfig->XAB1, apPhfig->YAB1 + MBK_X_GRID); /* Allocate the vertical tracks. */ DEF2MBK_track (apPhfig, "X", MBK2DEF_length (startX), tracksX, MBK2DEF_length (MBK_X_GRID), routingLayers, apPhfig->XAB1 + MBK_X_GRID, apPhfig->YAB1); return (TRUE); } /* ------------------------------------------------------------------ * Function : "fprintTRACKS()". */ static void fprintTRACKS () { struct track_s *pTrack; for (pTrack = LV_track; pTrack != NULL; pTrack = pTrack->next) { fprintf (DEF_FILE, "TRACKS %c %ld DO %ld STEP %ld LAYER %s ;\n", pTrack->axisName, pTrack->start, pTrack->doNumber, pTrack->step, pTrack->routingLayers); } fprintf (DEF_FILE, "\n\n"); } /* ------------------------------------------------------------------ * Function : "newblockage()". */ static struct blockage_s *newblockage() { struct blockage_s *pBlockage; pBlockage = (blockage_t*)mbkalloc (sizeof (blockage_t)); pBlockage->next = LV_blockage; return (LV_blockage = pBlockage); } /* ------------------------------------------------------------------ * Function : "freeblockage()". */ static void freeblockage() { struct blockage_s *pBlockage; while (LV_blockage) { pBlockage = LV_blockage->next; mbkfree (LV_blockage); LV_blockage = pBlockage; } } /* ------------------------------------------------------------------ * Function : "ref2BLOCKAGE()". */ static void ref2BLOCKAGE() { struct phref *pPhref; struct blockage_s *pBlockage; if (LV_phfig) { for (pPhref = LV_phfig->PHREF; pPhref != NULL; pPhref = pPhref->NEXT) { if (!strncmp (pPhref->NAME, "blockage.", 9)) { pBlockage = newblockage (); MBK2DEF_blockage (pPhref, &pBlockage->x, &pBlockage->y, &pBlockage->width, &pBlockage->height); } } } } /* ------------------------------------------------------------------ * Function : "fprintBLOCKAGE()". */ static void fprintBLOCKAGE() { struct blockage_s *pBlockage; long layer; for (pBlockage = LV_blockage; pBlockage != NULL; pBlockage = pBlockage->next) { if (pBlockage == LV_blockage) { fprintf (DEF_FILE, " - _BLOCKAGE_RESERVED"); fprintf (DEF_FILE, "\n + ROUTED "); } else { fprintf (DEF_FILE, "\n NEW "); } for (layer = 1; layer < 7; layer++) { if (layer != 1) fprintf (DEF_FILE, "\n NEW "); fprintf (DEF_FILE, "ALU%ld %ld + SHAPE BLOCKAGEWIRE ( %ld %ld ) ( %ld * )", layer, pBlockage->height, pBlockage->x, pBlockage->y + pBlockage->height / 2, pBlockage->x + pBlockage->width); } } if (LV_blockage) fprintf (DEF_FILE, "\n + SOURCE DIST + USE GROUND + WEIGHT 0 ;\n"); } /* ------------------------------------------------------------------ * Function : "fprintVIAMATRIX()". */ static void fprintVIAMATRIX (aType, aWidth, aHeight) char aType; long aWidth; long aHeight; { long xCutNB, yCutNB, xCut, yCut; xCutNB = (aWidth / MBKSCALE(5)) / 2; yCutNB = (aHeight / MBKSCALE(5)) / 2; for (xCut = - xCutNB; xCut <= xCutNB; xCut++) { for (yCut = - yCutNB; yCut <= yCutNB; yCut++) { fprintf (DEF_FILE, " + RECT %s ( %ld %ld ) ( %ld %ld )\n", DEF_layer2a (aType), MBK2DEF_length (xCut - SCALE_X / 2), MBK2DEF_length (yCut - SCALE_X / 2), MBK2DEF_length (xCut + SCALE_X / 2), MBK2DEF_length (yCut + SCALE_X / 2)); } } } /* ------------------------------------------------------------------ * Function : "fprintVIAS()". */ static void fprintVIAS() { struct tLoseg_s *pTLoseg; struct eMVIA_s *pMVIA; long nVIA, flagDefault, width, height; char viaName[1024]; pTLoseg = gettloseg (LV_phfig); if (pTLoseg) { nVIA = 0; __DBG( fflush (stdout); fprintf (stderr, "pTLoseg := 0x%08lx\n", (unsigned long)pTLoseg); fprintf (stderr, "tMVIA := 0x%08lx\n", (unsigned long)pTLoseg->tMVIA); fflush (stderr); ) for (pMVIA = pTLoseg->tMVIA; pMVIA != NULL; pMVIA = pMVIA->next) { nVIA++; } fprintf (DEF_FILE, "VIAS %ld ;\n", nVIA); for (pMVIA = pTLoseg->tMVIA; pMVIA != NULL; pMVIA = pMVIA->next) { flagDefault = (pMVIA->width <= MBKSCALE(2)) && (pMVIA->height <= MBKSCALE(2)); __DBG( if (!flagDefault) { fprintf (stderr, "macro VIA : %d (%ldx%ld)\n", (int)pMVIA->type, pMVIA->width, pMVIA->height); } ) width = MBKSCALE(2); height = MBKSCALE(2); fprintf (DEF_FILE, " - %s", DEF_via2a (pMVIA->type, pMVIA->width, pMVIA->height, viaName)); if (!flagDefault) { width = pMVIA->width; height = pMVIA->height; } fprintf (DEF_FILE, "\n + RECT %s ( %ld %ld ) ( %ld %ld )\n", DEF_layer2a (getBottomVIALayer (pMVIA->type)), DEF2MBK_length (- width / 2), DEF2MBK_length (- height / 2), DEF2MBK_length ( width / 2), DEF2MBK_length ( height / 2)); fprintVIAMATRIX (pMVIA->type, width, height); fprintf (DEF_FILE, " + RECT %s ( %ld %ld ) ( %ld %ld ) ;\n", DEF_layer2a (getTopVIALayer (pMVIA->type)), DEF2MBK_length (- width / 2), DEF2MBK_length (- height / 2), DEF2MBK_length ( width / 2), DEF2MBK_length ( height / 2)); } fprintf (DEF_FILE, "END VIAS\n\n"); } } /* ------------------------------------------------------------------ * Function : "fprintPIN()". */ static void fprintPIN(apLocon, apPhcon, asState) struct locon *apLocon; struct phcon *apPhcon; char *asState; { char sSig[1024]; long conLength; MBK2DEF_name(sSig, apLocon->NAME); fprintf(DEF_FILE, " - %s.%ld + NET %s", sSig, apPhcon->INDEX, sSig); if (isvdd(apLocon->NAME)) { /* * if (LV_Flags & F_FIXED_PINS) * fprintf(DEF_FILE, " + SPECIAL"); */ fprintf(DEF_FILE, " + DIRECTION INPUT + USE POWER"); } else if (isvss(apLocon->NAME)) { /* * if (LV_Flags & F_FIXED_PINS) * fprintf(DEF_FILE, " + SPECIAL"); */ fprintf(DEF_FILE, " + DIRECTION INPUT + USE GROUND"); } else if (isck(apLocon->NAME)) { fprintf(DEF_FILE, " + DIRECTION INPUT + USE CLOCK"); } else fprintf(DEF_FILE, " + DIRECTION %s", DIRtoa(MBK2DEF_locondir(apLocon))); if ( /* (LV_Flags & F_FIXED_PINS) */ /*&&*/ (strncmp(apLocon->NAME, "vddv", 4)) && (strncmp(apLocon->NAME, "vssv", 4)) && !isvdd (apLocon->NAME) && !isvss (apLocon->NAME)) { conLength = MBK_X_GRID; if (LV_Flags & F_EXPAND_ROUTE) conLength += FLOOR_XY_EXPAND; if (strcmp ("UNPLACED", asState)) { fprintf(DEF_FILE, "\n + %s ( %ld %ld ) %s", asState, apPhcon->XCON, apPhcon->YCON, DEF_side2a (apPhcon->ORIENT)); if (LV_Flags & F_EXPAND_PLACE) conLength += FLOOR_XY_EXPAND; } else { if (LV_Flags & F_EXPAND_PLACE) conLength += FLOOR_XY_EXPAND / 2; } fprintf(DEF_FILE, " + LAYER %s ( %ld 0 ) ( %ld %ld )", DEF_layer2a (apPhcon->LAYER), - MBK2DEF_length (apPhcon->WIDTH / 2), MBK2DEF_length (apPhcon->WIDTH / 2), MBK2DEF_length (conLength)); } fprintf(DEF_FILE, " ;\n"); } /* ------------------------------------------------------------------ * Function : "fprintPINS()". */ static void fprintPINS() { struct locon *pLoCon; struct phcon Phcon; struct eLoseg_s *pLoseg; long loconNB, phconNB; loconNB = 0; /* First : compute the number of terminals. */ for(pLoCon = LV_lofig->LOCON; pLoCon != (locon_list*)NULL; pLoCon = pLoCon->NEXT) { loconNB += 1; phconNB = 0; if (LV_phfig) { pLoseg = getloseglist (LV_phfig, getsigname (pLoCon->SIG)); for (; pLoseg != NULL; pLoseg = pLoseg->next) { if (pLoseg->type == LOSEG_CON) { phconNB += 1; } } if (phconNB > 1) loconNB += phconNB - 1; } } fprintf(DEF_FILE, "\n\nPINS %ld ;\n", loconNB); for(pLoCon = LV_lofig->LOCON; pLoCon != (locon_list*)NULL; pLoCon = pLoCon->NEXT) { phconNB = 0; if (LV_phfig) { pLoseg = getloseglist (LV_phfig, getsigname (pLoCon->SIG)); for (; pLoseg != NULL; pLoseg = pLoseg->next) { __DBG( fprintf (stderr, "sig %s pLoseg->type := %ld\n", getsigname (pLoCon->SIG), pLoseg->type); fflush (stderr); ) if (pLoseg->type == LOSEG_CON) { phconNB += 1; fprintPIN (pLoCon, (struct phcon*)(pLoseg->MBKobj), "FIXED"); } } } if (!phconNB) { Phcon.XCON = 0; Phcon.YCON = 0; Phcon.INDEX = 0; Phcon.WIDTH = MBKSCALE(2); Phcon.LAYER = ALU2; Phcon.ORIENT = SOUTH; fprintPIN (pLoCon, &Phcon, "UNPLACED"); } } fprintf(DEF_FILE, "END PINS\n"); } /* ------------------------------------------------------------------ * Function : "checkPhins()". */ static long checkPhins(apPhins) struct phins *apPhins; { struct row_s *pRow; char sameOrient, oppositeOrient, orient; orientPhfig (getphfig (apPhins->FIGNAME, 'A'), &sameOrient, &oppositeOrient); orient = DEF_N; switch (normOrient (MBK2DEF_transf (apPhins->TRANSF))) { case DEF_W: case DEF_N: orient = sameOrient; break; case DEF_FE: case DEF_FS: orient = oppositeOrient; break; } pRow = getBaseRow (apPhins->XINS, apPhins->YINS, orient); if (!pRow) { warnMBK (NULL); wprintf ("\n Instance %s of model %s at (%ld,%ld) is NOT on row grid.\n", apPhins->INSNAME, apPhins->FIGNAME, apPhins->XINS, apPhins->YINS); wprintf ( " Will be removed from the placement file.\n"); return (FALSE); } return (TRUE); } /* ------------------------------------------------------------------ * Function : "fprintCOMPONENTS()". */ static void fprintCOMPONENTS() { loins_list *pLoins; phins_list *pPhins; long loInsNB; /* First : compute the number of instances. */ for(pLoins = LV_lofig->LOINS, loInsNB = 0L; pLoins != NULL; loInsNB++, pLoins = pLoins->NEXT); fprintf(DEF_FILE, "\n\nCOMPONENTS %ld ;\n", loInsNB); /* Dump the list of instance/model pairs. */ for(pLoins = LV_lofig->LOINS; pLoins != (loins_list*)NULL; pLoins = pLoins->NEXT) { fprintf(DEF_FILE, " - %s %s ", pLoins->INSNAME, pLoins->FIGNAME); if (!(pPhins = getphinslink(pLoins)) || !checkPhins (pPhins)) { fprintf(DEF_FILE, ";\n"); } else { fprintf(DEF_FILE, "+ FIXED ( %ld %ld ) %s ;\n", MBK2DEF_length(pPhins->XINS), MBK2DEF_length(pPhins->YINS), DEF_orient2a(MBK2DEF_transf (pPhins->TRANSF))); } } fprintf(DEF_FILE, "END COMPONENTS\n"); } /* ------------------------------------------------------------------ * Function : "fprintWIRESEG()". */ static void fprintWIRESEG(apPhseg, aFlags) struct phseg *apPhseg; long aFlags; { fprintf (DEF_FILE, "%s ", DEF_layer2a (apPhseg->LAYER)); if (aFlags & F_SEG_WIDTH) fprintf (DEF_FILE, "%ld ", MBK2DEF_length (apPhseg->WIDTH)); if (aFlags & F_SEG_STRIPE) fprintf (DEF_FILE, "+ SHAPE STRIPE "); fprintf (DEF_FILE, "( %ld %ld ) ( %ld %ld ) ", MBK2DEF_length (apPhseg->X1), MBK2DEF_length (apPhseg->Y1), MBK2DEF_length (apPhseg->X2), MBK2DEF_length (apPhseg->Y2)); __DBG( fprintf (stderr, "MBK X1 := %ld, DEF X1 := %ld\n", apPhseg->X1, MBK2DEF_length (apPhseg->X1)); ) } /* ------------------------------------------------------------------ * Function : "fprintWIREVIA()". */ static void fprintWIREVIA(apPhvia, aFlags) struct phvia *apPhvia; long aFlags; { char viaName[1024]; fprintf (DEF_FILE, "%s ", DEF_layer2a (getBottomVIALayer (apPhvia->TYPE))); if (aFlags & F_SEG_WIDTH) fprintf (DEF_FILE, "%ld ", MBK2DEF_length (apPhvia->DX)); fprintf (DEF_FILE, "( %ld %ld ) %s ", MBK2DEF_length (apPhvia->XVIA), MBK2DEF_length (apPhvia->YVIA), DEF_via2a (apPhvia->TYPE, apPhvia->DX, apPhvia->DY, viaName)); } /* ------------------------------------------------------------------ * Function : "fprintWIRES()". */ static void fprintWIRES(apLosig) struct losig *apLosig; { struct eLoseg_s *pLoseg; long flagFirst, flagSeg; flagFirst = TRUE; pLoseg = getloseglist (LV_phfig, getsigname (apLosig)); flagSeg = 0L; if (LV_localFlags & F_SPECIAL_NET) { flagSeg = F_SEG_STRIPE | F_SEG_WIDTH; } if (pLoseg) { for (; pLoseg != NULL; pLoseg = pLoseg->next) { if (!flagFirst) fprintf (DEF_FILE, "\n NEW "); switch (pLoseg->type) { case LOSEG_SEG: if (flagFirst) fprintf (DEF_FILE, "\n + ROUTED "); fprintWIRESEG ((struct phseg*)pLoseg->MBKobj, flagSeg); flagFirst = FALSE; break; case LOSEG_VIA: if (flagFirst) fprintf (DEF_FILE, "\n + ROUTED "); fprintWIREVIA ((struct phvia*)pLoseg->MBKobj, flagSeg); flagFirst = FALSE; break; } } } } /* ------------------------------------------------------------------ * Function : "fprintNET()". */ static void fprintNET(apLoSig, aUse) losig_list *apLoSig; char aUse; { struct ptype *pType; struct chain *pChain; struct locon *pLoCon; struct authelem *pElem; char sLine[80], sItem[1024]; char *sSig, sSigLEF[1024], sConLEF[1024]; long lLine; /* Try to guess if this is a VST devectorized internal signal. * We first seach a loseg with the signal name, if nothing is * found we try with a vectorized name. */ sSig = getsigname (apLoSig); pElem = searchauthelem (LV_htTerm, sSig); /* In case of external signal, override with the terminal name. */ if (pElem != NULL) { sSig = (char*)pElem->VALUE; } pType = getptype(apLoSig->USER, (long)LOFIGCHAIN); if (pType == (ptype_list*)NULL) { wprinth((char*)NULL); wprintf(" Signal \"%s\" have no LOFIGCHAIN.\n", sSig); pChain = (chain_list*)NULL; } else { pChain = (chain_list*)(pType->DATA); } sSig = MBK2DEF_name(sSigLEF, sSig); /*snprintf(sItem, 79, " - %s ", sSig);*/ sprintf(sItem, " - %s ", sSig); sLine[0] = (char)0; lLine = 0L; if (strlen (sItem) > 79) fprintf(DEF_FILE, "%s\n", sItem); else strLCat(sLine, sItem, &lLine, 79); for(; pChain != (chain_list*)NULL; pChain = pChain->NEXT) { pLoCon = (locon_list*)(pChain->DATA); if (pLoCon->TYPE == INTERNAL) { /*snprintf(sItem, 79, "( %s %s ) ", * ((loins_list*)(pLoCon->ROOT))->INSNAME, * MBK2DEF_name(sConLEF, pLoCon->NAME)); */ sprintf(sItem, "( %s %s ) ", ((loins_list*)(pLoCon->ROOT))->INSNAME, MBK2DEF_name(sConLEF, pLoCon->NAME)); if (lLine + strlen(sItem) + 4 > 70) { fprintf(DEF_FILE, "%s", sLine); if (strlen (sItem) > 70) { /* sItem too long anyway... flush it immediatly. */ fprintf(DEF_FILE, " %s\n", sItem); sItem[0] = (char)0; } else { fprintf(DEF_FILE, "\n"); } lLine = 0L; strLCat(sLine, " ", &lLine, 79); } strLCat(sLine, sItem, &lLine, 79); } } if (lLine > 0) fprintf(DEF_FILE, "%s", sLine); if (LV_phfig) fprintWIRES (apLoSig); if (aUse != C_USE_NONE) fprintf(DEF_FILE, "\n + USE %s ;\n", USEtoa(aUse)); else fprintf(DEF_FILE, ";\n"); } /* ------------------------------------------------------------------ * Function : "fprintNETS()". */ static void fprintNETS() { losig_list *pLoSig; long loSigNB; char *sSig; LV_localFlags &= ~ F_SPECIAL_NET; LV_localFlags |= F_REGULAR_NET; /* First : compute the number of signals. */ for(pLoSig = LV_lofig->LOSIG, loSigNB = 0L; pLoSig != (losig_list*)NULL; pLoSig = pLoSig->NEXT) { sSig = getsigname(pLoSig); if (isvdd(sSig) || isvss(sSig) || isck(sSig)) continue; loSigNB += 1; } fprintf(DEF_FILE, "\n\nNETS %ld ;\n", loSigNB); /* Dump the list of signal connections. */ for(pLoSig = LV_lofig->LOSIG; pLoSig != (losig_list*)NULL; pLoSig = pLoSig->NEXT) { sSig = getsigname(pLoSig); if ( isvdd(sSig) || isvss(sSig) || !strcmp(sSig, "cki") || isck(sSig)) continue; fprintNET(pLoSig, C_USE_NONE); } fprintf(DEF_FILE, "END NETS\n"); } /* ------------------------------------------------------------------ * Function : "fprintSPECIALNETS()". */ static void fprintSPECIALNETS() { losig_list *pLoSig; long loSigNB; char *sSig, Use; LV_localFlags &= ~ F_REGULAR_NET; LV_localFlags |= F_SPECIAL_NET; /* First : compute the number of signals. */ for(pLoSig = LV_lofig->LOSIG, loSigNB = 0L; pLoSig != (losig_list*)NULL; pLoSig = pLoSig->NEXT) { sSig = getsigname(pLoSig); if ( !isvdd(sSig) && !isvss(sSig) && strcmp(sSig, "cki") && !isck(sSig)) continue; loSigNB += 1; } fprintf(DEF_FILE, "\n\nSPECIALNETS %ld ;\n", loSigNB + ((LV_blockage) ? 1 : 0)); /* Dump the list of signal connections. */ for(pLoSig = LV_lofig->LOSIG; pLoSig != (losig_list*)NULL; pLoSig = pLoSig->NEXT) { sSig = getsigname(pLoSig); Use = C_USE_NONE; if ( isvdd(sSig) ) Use = C_USE_POWER; if ( isvss(sSig) ) Use = C_USE_GROUND; if (!strcmp(sSig, "cki")) Use = C_USE_CLOCK; if ( isck(sSig) ) Use = C_USE_CLOCK; if (Use == C_USE_NONE) continue; fprintNET(pLoSig, Use); } fprintBLOCKAGE (); fprintf(DEF_FILE, "END SPECIALNETS\n"); } /* ------------------------------------------------------------------ * Function : "fprintDEF()". */ static void fprintDEF() { fprintf (DEF_FILE, "VERSION 5.2 ;\n"); fprintf (DEF_FILE, "NAMESCASESENSITIVE ON ;\n"); fprintf (DEF_FILE, "BUSBITCHARS \"()\" ;\n"); fprintf (DEF_FILE, "DIVIDERCHAR \".\" ;\n\n"); fprintf (DEF_FILE, "DESIGN %s ;\n\n", LV_name); fprintf (DEF_FILE, " TECHNOLOGY %s ;\n\n" , "cmos"); fprintf (DEF_FILE, " UNITS DISTANCE MICRONS %ld ;\n", DEF_UNITS_MICRONS); if (LV_phfig) { fprintDIEAREA (); ref2ROW (); if (!LV_row) { wprinth ("fprintfDEF"); wprintf ("\n Generate default rows and tracks. This may lead to"); wprintf ("\n incorrect results if the design is expanded.\n"); buildROWS (LV_phfig); buildTRACKS (LV_phfig, LV_Flags); } else { ref2TRACK (); } fprintROWS (); fprintTRACKS (); ref2BLOCKAGE(); fprintVIAS (); } fprintCOMPONENTS (); fprintPINS (); fprintNETS (); fprintSPECIALNETS (); fprintf(DEF_FILE, "\n\nEND DESIGN\n"); } /* ------------------------------------------------------------------ * Function : "defsavelophfig()". */ extern void defsavelophfig(apLofig, apPhfig, aDefName, aFlags) struct lofig *apLofig; struct phfig *apPhfig; char *aDefName; long aFlags; { LV_Flags = aFlags; LV_lofig = apLofig; LV_phfig = apPhfig; LV_name = aDefName; LV_row = NULL; LV_track = NULL; LV_blockage = NULL; if (LV_phfig) { addfeed (LV_lofig, LV_phfig); lofigchain (LV_lofig); } buildphinslinks (); buildtterm (); if (!LV_name) LV_name = apLofig->NAME; DEF_FILE = mbkfopen (LV_name, "def", "w+"); fprintDEF (); if (LV_phfig) checklosegaccess (LV_phfig); fclose (DEF_FILE); freerow (); freetrack (); freeblockage (); freetterm (); freephinslinks (); if (LV_phfig) { delfeed (LV_lofig); lofigchain (LV_lofig); } }