Modified the configure scripts and makefile per Proppy's comments

in github issue #149.  This causes magic to no longer write log files
for "make" and "make install" but will properly exit with a non-zero
return code on any error during compile.

Also:  Corrected the command "tech drc surround <type1> <type2>" so
that it now returns the correct value when <type1> and <type2> are in
the same plane.  Added new command "tech drc directional <type1> <type2>"
which works the same way as "tech drc surround" except for directional
surround rules.  Used this to generate vias from "def write" with the
correct metal surround amounts included in the via definiton.  The
route analysis then ignores tile slivers that make up the surrounding
material around contacts.  Also implemented a method that handles
routes that are made of multiple thin tiles due to the maximum horizontal
stripes rule.  Now magic handles "def write" well except for not dealing
with non-minimum-width routes unless they're specifically called out as
"special" nets.
This commit is contained in:
Tim Edwards 2022-03-29 16:52:01 -04:00
parent 3bc80a9869
commit 0c584f9e77
8 changed files with 392 additions and 43 deletions

View File

@ -19,11 +19,11 @@ all: $(ALL_TARGET)
standard:
@echo --- errors and warnings logged in file make.log
@${MAKE} mains 2>&1 | tee -a make.log | egrep -i "(.c:|Stop.|---)"
@${MAKE} mains
tcl:
@echo --- errors and warnings logged in file make.log
@${MAKE} tcllibrary 2>&1 | tee -a make.log | egrep -i "(.c:|Stop.|---)"
@${MAKE} tcllibrary
force: clean all
@ -36,12 +36,12 @@ config:
tcllibrary: database/database.h modules
@echo --- making Tcl shared libraries
for dir in ${PROGRAMS}; do \
(cd $$dir && ${MAKE} tcl-main); done
(cd $$dir && ${MAKE} tcl-main) || exit 1; done
mains: database/database.h modules libs
@echo --- making main programs
for dir in ${PROGRAMS}; do \
(cd $$dir && ${MAKE} main); done
(cd $$dir && ${MAKE} main) || exit 1; done
database/database.h: database/database.h.in
@echo --- making header file database/database.h
@ -50,25 +50,25 @@ database/database.h: database/database.h.in
modules: database/database.h depend
@echo --- making modules
for dir in ${MODULES} ${PROGRAMS}; do \
(cd $$dir && ${MAKE} module); done
(cd $$dir && ${MAKE} module) || exit 1; done
libs:
@echo --- making libraries
for dir in ${LIBRARIES}; do \
(cd $$dir && ${MAKE} lib); done
(cd $$dir && ${MAKE} lib) || exit 1; done
depend: database/database.h
@echo --- making dependencies
${RM} */Depend
for dir in ${MODULES} ${UNUSED_MODULES} ${PROGRAMS}; do \
(cd $$dir && ${MAKE} depend); done
(cd $$dir && ${MAKE} depend) || exit 1; done
install: $(INSTALL_TARGET)
install-magic:
@echo --- installing executable to $(DESTDIR)${INSTALL_BINDIR}
@echo --- installing runtime files to $(DESTDIR)${INSTALL_LIBDIR}
@${MAKE} install-real 2>&1 >> install.log
@${MAKE} install-real
install-real: install-dirs
for dir in ${INSTALL_CAD_DIRS}; do \
@ -89,7 +89,7 @@ install-dirs:
install-tcl:
@echo --- installing executable to $(DESTDIR)${INSTALL_BINDIR}
@echo --- installing runtime files to $(DESTDIR)${INSTALL_LIBDIR}
@${MAKE} install-tcl-real 2>&1 >> install.log
@${MAKE} install-tcl-real
install-tcl-real: install-tcl-dirs
for dir in ${INSTALL_CAD_DIRS} ${PROGRAMS}; do \

View File

@ -1 +1 @@
8.3.282
8.3.283

View File

@ -497,6 +497,29 @@ CmdTech(w, cmd)
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(tresult));
#else
TxPrintf("Minimum surround is %d\n", tresult);
#endif
}
else if (!strncmp(cmd->tx_argv[2], "direc", 5))
{
if (cmd->tx_argc >= 5)
{
t2 = DBTechNoisyNameType(cmd->tx_argv[4]);
if (t2 < 0) {
TxError("No such layer %s\n", cmd->tx_argv[4]);
break;
}
}
else
{
TxError("Requires two layer types.\n");
break;
}
tresult = DRCGetDirectionalLayerSurround(t1, t2);
#ifdef MAGIC_WRAPPER
Tcl_SetObjResult(magicinterp, Tcl_NewIntObj(tresult));
#else
TxPrintf("Minimum surround (in one orientation) is %d\n", tresult);
#endif
}
}

View File

@ -4115,7 +4115,7 @@ DRCGetDefaultLayerSurround(ttype1, ttype2)
{
int layerSurround = 0;
DRCCookie *cptr;
TileTypeBitMask *set;
TileTypeBitMask *set, *cset;
for (cptr = DRCCurStyle->DRCRulesTbl[ttype1][TT_SPACE]; cptr != (DRCCookie *) NULL;
cptr = cptr->drcc_next)
@ -4137,6 +4137,81 @@ DRCGetDefaultLayerSurround(ttype1, ttype2)
}
}
}
if (layerSurround > 0) return layerSurround;
for (cptr = DRCCurStyle->DRCRulesTbl[TT_SPACE][ttype1]; cptr != (DRCCookie *) NULL;
cptr = cptr->drcc_next)
{
if ((cptr->drcc_flags & DRC_REVERSE) == 0) /* FORWARD only */
{
set = &cptr->drcc_mask;
cset = &cptr->drcc_corner;
if (TTMaskHasType(set, TT_SPACE) && !TTMaskHasType(set, ttype1))
if ((TTMaskHasType(cset, ttype2)) &&
(cptr->drcc_flags && DRC_BOTHCORNERS) &&
(cptr->drcc_edgeplane == cptr->drcc_plane) &&
(cptr->drcc_dist == cptr->drcc_cdist))
{
layerSurround = cptr->drcc_dist;
/* Diagnostic */
/*
TxPrintf("DRC: Layer %s has default surround %d over layer %s\n",
DBTypeLongNameTbl[ttype2], layerSurround,
DBTypeLongNameTbl[ttype1]);
*/
}
}
}
return layerSurround;
}
/*
*-----------------------------------------------------------------------------
* DRCGetDirectionalLayerSurround ---
*
* Determine the minimum required surround amount of layer type 2
* around layer type 1 for a directional surround rule (rule
* applies for two opposing sides of layer type 1).
*
* Results:
* The minimum spacing between the specified magic layer types,
* in magic internal units
*
* Side effects:
* None.
*
*-----------------------------------------------------------------------------
*/
int
DRCGetDirectionalLayerSurround(ttype1, ttype2)
TileType ttype1, ttype2;
{
int layerSurround = 0;
DRCCookie *cptr, *cnext;
TileTypeBitMask *set, *cset;
for (cptr = DRCCurStyle->DRCRulesTbl[ttype1][TT_SPACE]; cptr != (DRCCookie *) NULL;
cptr = cptr->drcc_next)
{
if (cptr->drcc_flags & DRC_TRIGGER)
{
set = &cptr->drcc_mask;
if (!TTMaskHasType(set, TT_SPACE) && TTMaskHasType(set, ttype2))
if ((cptr->drcc_plane == cptr->drcc_edgeplane) &&
(cptr->drcc_cdist == 0))
{
layerSurround = cptr->drcc_dist;
/* Diagnostic */
/*
TxPrintf("DRC: Layer %s has default surround %d over layer %s\n",
DBTypeLongNameTbl[ttype2], layerSurround,
DBTypeLongNameTbl[ttype1]);
*/
}
cnext = cptr->drcc_next;
}
}
return layerSurround;
}

View File

@ -249,6 +249,7 @@ extern int DRCGetDefaultLayerWidth();
extern int DRCGetDefaultLayerSpacing();
extern int DRCGetDefaultWideLayerSpacing();
extern int DRCGetDefaultLayerSurround();
extern int DRCGetDirectionalLayerSurround();
extern int DRCInteractionCheck();
extern int drcArrayFunc();

View File

@ -48,6 +48,7 @@ typedef struct {
unsigned char orient;
LefMapping *MagicToLefTbl;
HashTable *defViaTable;
int outcolumn; /* Current column of output in file */
unsigned char specialmode; /* What nets to write as SPECIALNETS */
} DefData;
@ -61,11 +62,12 @@ typedef struct {
} DefObsData;
typedef struct {
CellDef *def;
float scale;
int total;
int plane;
TileTypeBitMask *mask;
LefMapping *MagicToLefTbl;
HashTable *defViaTable;
} CViaData;
/*----------------------------------------------------------------------*/
@ -595,11 +597,12 @@ defWriteCoord(defdata, x, y, orient)
*/
void
defWriteNets(f, rootDef, oscale, MagicToLefTable, specialmode)
defWriteNets(f, rootDef, oscale, MagicToLefTable, defViaTable, specialmode)
FILE *f; /* File to write to */
CellDef *rootDef; /* Cell definition to use */
float oscale; /* Output scale factor */
LefMapping *MagicToLefTable; /* Magic to LEF layer mapping */
HashTable *defViaTable; /* Hash table of contact positions */
unsigned char specialmode; /* What to write as a SPECIALNET */
{
DefData defdata;
@ -611,6 +614,7 @@ defWriteNets(f, rootDef, oscale, MagicToLefTable, specialmode)
defdata.MagicToLefTbl = MagicToLefTable;
defdata.outcolumn = 0;
defdata.specialmode = specialmode;
defdata.defViaTable = defViaTable;
EFVisitNodes(defnodeVisit, (ClientData)&defdata);
}
@ -769,6 +773,30 @@ defnodeVisit(node, res, cap, defdata)
return 0; /* Keep going */
}
/* Callback function for defNetGeometryFunc(). Determines if any tile */
/* sets the lower bound of the clip line for extending a wire upward */
int
defMaxWireFunc(tile, yclip)
Tile *tile;
int *yclip;
{
if (BOTTOM(tile) < (*yclip)) *yclip = BOTTOM(tile);
return 0;
}
/* Callback function for defNetGeometryFunc(). Determines if any tile */
/* sets the upper bound of the clip line for extending a wire downward */
int
defMinWireFunc(tile, yclip)
Tile *tile;
int *yclip;
{
if (TOP(tile) > (*yclip)) *yclip = TOP(tile);
return 0;
}
/* Callback function for DBTreeSrUniqueTiles. When no routed areas */
/* were found, we assume that there was no routing material overlapping */
/* the port. So, we need to find the area of a tile defining the port */
@ -810,13 +838,15 @@ defNetGeometryFunc(tile, plane, defdata)
float oscale = defdata->scale;
TileTypeBitMask *rMask, *r2Mask;
TileType rtype, r2type, ttype = TiGetType(tile);
Rect r;
Rect r, rorig;
unsigned char orient;
bool sameroute = FALSE;
int routeWidth, w, h, midlinex2;
int routeWidth, w, h, midlinex2, topClip, botClip;
float x1, y1, x2, y2, extlen;
lefLayer *lefType;
char *lefName, viaName[24];
lefLayer *lefType, *lefl;
char *lefName, viaName[128], posstr[24];
HashEntry *he;
HashTable *defViaTable = defdata->defViaTable;
LefMapping *MagicToLefTable = defdata->MagicToLefTbl;
if (ttype == TT_SPACE) return 0;
@ -923,6 +953,7 @@ defNetGeometryFunc(tile, plane, defdata)
}
}
}
rorig = r;
/* Layer names are taken from the LEF database. */
@ -970,6 +1001,43 @@ defNetGeometryFunc(tile, plane, defdata)
/* This means a regular net should have been a special net. */
if ((h != routeWidth) && (w != routeWidth))
{
/* Handle slivers. There are two main cases:
* (1) Sliver is part of a via extension, so it can be ignored.
* (2) Sliver is a route split into several tiles due to geometry
* to the left. Expand up and down to include all tiles.
*/
if (w < routeWidth) return 0;
if (h < routeWidth)
{
/* Check upward */
r = rorig;
r.r_ytop = r.r_ybot + routeWidth;
r.r_ybot = rorig.r_ytop;
topClip = r.r_ytop;
DBSrPaintArea(tile, def->cd_planes[plane],
&r, &DBNotConnectTbl[ttype],
defMaxWireFunc, (ClientData)&topClip);
/* Check downward */
r = rorig;
r.r_ybot = r.r_ytop - routeWidth;
r.r_ytop = rorig.r_ybot;
botClip = r.r_ybot;
DBSrPaintArea(tile, def->cd_planes[plane],
&r, &DBNotConnectTbl[ttype],
defMinWireFunc, (ClientData)&botClip);
r = rorig;
if (topClip > r.r_ytop) r.r_ytop = topClip;
if (botClip < r.r_ybot) r.r_ybot = botClip;
/* If height is still less that a route width, bail */
h = r.r_ytop - r.r_ybot;
if (h < routeWidth) return 0;
}
/* Diagnostic */
TxPrintf("Net at (%d, %d) has width %d, default width is %d\n",
r.r_xbot, r.r_ybot,
@ -981,6 +1049,8 @@ defNetGeometryFunc(tile, plane, defdata)
orient = GEO_NORTH;
midlinex2 = (r.r_xtop + r.r_xbot);
}
else
midlinex2 = (r.r_ytop + r.r_ybot);
}
/* Find the route orientation and centerline endpoint coordinates */
@ -1145,10 +1215,23 @@ defNetGeometryFunc(tile, plane, defdata)
}
/* Via type continues route */
snprintf(viaName, (size_t)24, "_%.10g_%.10g",
sprintf(posstr, "%s_%d_%d", DBPlaneShortName(DBPlane(ttype)),
rorig.r_xbot, rorig.r_ybot);
he = HashLookOnly(defViaTable, posstr);
if (he != NULL)
{
lefl = (lefLayer *)HashGetValue(he);
defCheckForBreak(strlen(lefl->canonName) + 2, defdata);
fprintf(f, " %s ", lefl->canonName);
}
else
{
TxError("Cannot find via name %s in table!\n", posstr);
snprintf(viaName, (size_t)24, "_%.10g_%.10g",
((float)w * oscale), ((float)h * oscale));
defCheckForBreak(strlen(lefName) + strlen(viaName) + 2, defdata);
fprintf(f, " %s%s ", lefName, viaName);
defCheckForBreak(strlen(lefName) + strlen(viaName) + 2, defdata);
fprintf(f, " %s%s ", lefName, viaName);
}
}
else
{
@ -1196,10 +1279,24 @@ defNetGeometryFunc(tile, plane, defdata)
if (defdata->specialmode != DO_REGULAR)
defWriteRouteWidth(defdata, routeWidth);
defWriteCoord(defdata, x1, y1, GEO_CENTER);
snprintf(viaName, (size_t)24, "_%.10g_%.10g",
((float)w * oscale), ((float)h * oscale));
defCheckForBreak(strlen(lefName) + strlen(viaName) + 2, defdata);
fprintf(f, " %s%s ", lefName, viaName);
sprintf(posstr, "%s_%d_%d", DBPlaneShortName(DBPlane(ttype)),
rorig.r_xbot, rorig.r_ybot);
he = HashLookOnly(defViaTable, posstr);
if (he != NULL)
{
lefl = (lefLayer *)HashGetValue(he);
defCheckForBreak(strlen(lefl->canonName) + 2, defdata);
fprintf(f, " %s ", lefl->canonName);
}
else
{
TxError("Cannot find via name %s in table!\n", posstr);
snprintf(viaName, (size_t)24, "_%.10g_%.10g",
((float)w * oscale), ((float)h * oscale));
defCheckForBreak(strlen(lefName) + strlen(viaName) + 2, defdata);
fprintf(f, " %s%s ", lefName, viaName);
}
}
else
{
@ -1347,9 +1444,10 @@ defNetGeometryFunc(tile, plane, defdata)
*/
int
defCountVias(rootDef, MagicToLefTable, oscale)
defCountVias(rootDef, MagicToLefTable, defViaTable, oscale)
CellDef *rootDef;
LefMapping *MagicToLefTable;
HashTable *defViaTable;
float oscale;
{
TileTypeBitMask contactMask, *rmask;
@ -1361,11 +1459,11 @@ defCountVias(rootDef, MagicToLefTable, oscale)
cviadata.scale = oscale;
cviadata.total = 0;
cviadata.MagicToLefTbl = MagicToLefTable;
cviadata.defViaTable = defViaTable;
cviadata.def = rootDef;
for (pNum = PL_SELECTBASE; pNum < DBNumPlanes; pNum++)
{
cviadata.plane = pNum;
/* Only search for contacts that are on their *home* plane */
TTMaskZero(&contactMask);
@ -1396,6 +1494,14 @@ defCountVias(rootDef, MagicToLefTable, oscale)
return cviadata.total;
}
/* Simple callback function used by defCountViaFunc */
int
defCheckFunc(tile)
{
return 1;
}
/* Callback function used by defCountVias */
int
@ -1406,12 +1512,17 @@ defCountViaFunc(tile, cviadata)
TileType ttype = TiGetType(tile), ctype, rtype;
TileTypeBitMask *rmask, *rmask2;
Tile *tp;
char *lname, vname[100], *vp;
Rect r, r2;
int w, h, offx, offy;
char *lname, vname[100], *vp, posstr[24];
Rect r, r2, rorig;
int w, h, offx, offy, sdist, lorient, horient;
int ldist, hdist, sldist, shdist, pNum;
TileType ltype, htype;
float oscale = cviadata->scale;
lefLayer *lefl;
LinkedRect *newlr;
CellDef *def = cviadata->def;
HashEntry *he;
HashTable *defViaTable = cviadata->defViaTable;
LefMapping *MagicToLefTable = cviadata->MagicToLefTbl;
/* Techfiles are allowed not to declare a LEF entry, in which */
@ -1521,6 +1632,7 @@ defCountViaFunc(tile, cviadata)
/* All values for the via rect are in 1/2 lambda to account */
/* for a centerpoint not on the internal grid. */
rorig = r;
r.r_xbot <<= 1;
r.r_xtop <<= 1;
r.r_ybot <<= 1;
@ -1537,7 +1649,67 @@ defCountViaFunc(tile, cviadata)
r.r_xtop = -offx + w;
r.r_ytop = -offy + h;
sprintf(vname, "%s_%.10g_%.10g", lname,
/* If the via type has directional surround rules, then determine */
/* the orientation of the lower and upper metal layers and add a */
/* suffix to the via name. */
rmask = DBResidueMask(ctype);
ldist = hdist = 0;
ltype = htype = TT_SPACE;
for (rtype = TT_TECHDEPBASE; rtype < DBNumUserLayers; rtype++)
if (TTMaskHasType(rmask, rtype))
{
sdist = DRCGetDefaultLayerSurround(ctype, rtype);
if (ltype == TT_SPACE)
sldist = sdist;
else
shdist = sdist;
sdist = DRCGetDirectionalLayerSurround(ctype, rtype);
if (ltype == TT_SPACE)
{
ldist = sdist;
ltype = rtype;
}
else
{
hdist = sdist;
htype = rtype;
break;
}
}
lorient = horient = 0;
if (ldist > 0)
{
r2.r_ybot = rorig.r_ybot - sldist;
r2.r_ytop = rorig.r_ytop + sldist;
r2.r_xbot = rorig.r_xbot - ldist + sldist;
r2.r_xtop = rorig.r_xtop + ldist + sldist;
pNum = DBPlane(ltype);
lorient = DBSrPaintArea((Tile *)NULL, def->cd_planes[pNum], &r2,
&DBNotConnectTbl[ltype], defCheckFunc,
(ClientData)NULL);
}
if (hdist > 0)
{
r2.r_ybot = rorig.r_ybot - shdist;
r2.r_ytop = rorig.r_ytop + shdist;
r2.r_xbot = rorig.r_xbot - hdist + shdist;
r2.r_xtop = rorig.r_xtop + hdist + shdist;
pNum = DBPlane(htype);
horient = DBSrPaintArea((Tile *)NULL, def->cd_planes[pNum], &r2,
&DBNotConnectTbl[htype], defCheckFunc,
(ClientData)NULL);
}
if ((ldist > 0) || (hdist > 0))
{
sprintf(vname, "%s_%.10g_%.10g_%c%c", lname,
((float)offx * oscale), ((float)offy * oscale),
(ldist == 0) ? 'x' : (lorient == 0) ? 'h' : 'v',
(hdist == 0) ? 'x' : (horient == 0) ? 'h' : 'v');
}
else
sprintf(vname, "%s_%.10g_%.10g", lname,
((float)offx * oscale), ((float)offy * oscale));
he = HashFind(&LefInfo, vname);
@ -1555,7 +1727,67 @@ defCountViaFunc(tile, cviadata)
lefl->refCnt = 0; /* These entries will be removed after writing */
HashSetValue(he, lefl);
lefl->canonName = (char *)he->h_key.h_name;
if ((sldist > 0) || (ldist > 0))
{
newlr = (LinkedRect *)mallocMagic(sizeof(LinkedRect));
newlr->r_next = lefl->info.via.lr;
lefl->info.via.lr = newlr;
newlr->r_type = ltype;
r2.r_xbot = r.r_xbot - 2 * sldist;
r2.r_xtop = r.r_xtop + 2 * sldist;
r2.r_ybot = r.r_ybot - 2 * sldist;
r2.r_ytop = r.r_ytop + 2 * sldist;
if (ldist > 0)
{
if (lorient == 0)
{
r2.r_xbot -= 2 * ldist;
r2.r_xtop += 2 * ldist;
}
else
{
r2.r_ybot -= 2 * ldist;
r2.r_ytop += 2 * ldist;
}
}
newlr->r_r = r2;
}
if ((shdist > 0) || (hdist > 0))
{
newlr = (LinkedRect *)mallocMagic(sizeof(LinkedRect));
newlr->r_next = lefl->info.via.lr;
lefl->info.via.lr = newlr;
newlr->r_type = htype;
r2.r_xbot = r.r_xbot - 2 * shdist;
r2.r_xtop = r.r_xtop + 2 * shdist;
r2.r_ybot = r.r_ybot - 2 * shdist;
r2.r_ytop = r.r_ytop + 2 * shdist;
if (hdist > 0)
{
if (horient == 0)
{
r2.r_xbot -= 2 * hdist;
r2.r_xtop += 2 * hdist;
}
else
{
r2.r_ybot -= 2 * hdist;
r2.r_ytop += 2 * hdist;
}
}
newlr->r_r = r2;
}
}
/* Record this tile position in the contact hash table */
sprintf(posstr, "%s_%d_%d", DBPlaneShortName(DBPlane(ctype)),
rorig.r_xbot, rorig.r_ybot);
he = HashFind(defViaTable, posstr);
HashSetValue(he, lefl);
/* XXX WIP XXX */
TxPrintf("Via name \"%s\" hashed as \"%s\"\n", lefl->canonName, posstr);
return 0; /* Keep the search going */
}
@ -1647,6 +1879,8 @@ defWriteVias(f, rootDef, oscale, lefMagicToLefLayer)
lefLayer *lefl;
TileTypeBitMask *rMask;
TileType ttype;
Rect *r;
LinkedRect *lr;
/* Pick up information from the LefInfo hash table */
/* created by fucntion defCountVias() */
@ -1677,12 +1911,24 @@ defWriteVias(f, rootDef, oscale, lefMagicToLefLayer)
rMask = DBResidueMask(lefl->type);
for (ttype = TT_TECHDEPBASE; ttype < DBNumUserLayers; ttype++)
if (TTMaskHasType(rMask, ttype))
{
r = &lefl->info.via.area;
/* If an lr entry was made, then it includes */
/* any required surround distance, so use that */
/* rectangle instead of the via area. */
for (lr =lefl->info.via.lr; lr; lr = lr->r_next)
if (lr->r_type == ttype)
r = &lr->r_r;
fprintf(f, "\n + RECT %s ( %.10g %.10g ) ( %.10g %.10g )",
lefMagicToLefLayer[ttype].lefName,
(float)(lefl->info.via.area.r_xbot) * oscale / 2,
(float)(lefl->info.via.area.r_ybot) * oscale / 2,
(float)(lefl->info.via.area.r_xtop) * oscale / 2,
(float)(lefl->info.via.area.r_ytop) * oscale / 2);
(float)(r->r_xbot) * oscale / 2,
(float)(r->r_ybot) * oscale / 2,
(float)(r->r_xtop) * oscale / 2,
(float)(r->r_ytop) * oscale / 2);
}
/* Handle the contact cuts. */
@ -2409,6 +2655,7 @@ DefWriteCell(def, outName, allSpecial, units)
NetCount nets;
int total;
float scale;
HashTable defViaTable;
LefMapping *lefMagicToLefLayer;
int i;
@ -2438,10 +2685,12 @@ DefWriteCell(def, outName, allSpecial, units)
defWriteHeader(def, f, scale, units);
HashInit(&defViaTable, 256, HT_STRINGKEYS);
lefMagicToLefLayer = defMakeInverseLayerMap(LAYER_MAP_VIAS);
/* Vias---magic contact areas are reported as vias. */
total = defCountVias(def, lefMagicToLefLayer, scale);
total = defCountVias(def, lefMagicToLefLayer, &defViaTable, scale);
fprintf(f, "VIAS %d ;\n", total);
if (total > 0)
defWriteVias(f, def, scale, lefMagicToLefLayer);
@ -2485,8 +2734,8 @@ DefWriteCell(def, outName, allSpecial, units)
if (nets.special > 0)
{
fprintf(f, "SPECIALNETS %d ;\n", nets.special);
defWriteNets(f, def, scale, lefMagicToLefLayer, (allSpecial) ?
ALL_SPECIAL : DO_SPECIAL);
defWriteNets(f, def, scale, lefMagicToLefLayer, &defViaTable,
(allSpecial) ? ALL_SPECIAL : DO_SPECIAL);
fprintf(f, "END SPECIALNETS\n\n");
}
@ -2494,7 +2743,7 @@ DefWriteCell(def, outName, allSpecial, units)
if (nets.regular > 0)
{
fprintf(f, "NETS %d ;\n", nets.regular);
defWriteNets(f, def, scale, lefMagicToLefLayer, DO_REGULAR);
defWriteNets(f, def, scale, lefMagicToLefLayer, &defViaTable, DO_REGULAR);
fprintf(f, "END NETS\n\n");
}
@ -2511,6 +2760,7 @@ DefWriteCell(def, outName, allSpecial, units)
}
freeMagic((char *)lefMagicToLefLayer);
HashKill(&defViaTable);
lefRemoveGeneratedVias();
}

4
scripts/configure vendored
View File

@ -5322,7 +5322,7 @@ fi
if test "x${CSH}" = "x"; then
if test "x${CSH}" = "xno"; then
as_fn_error $? "cannot find /bin/csh---cannot compile!" "$LINENO" 5
fi
@ -5367,7 +5367,7 @@ $as_echo "no" >&6; }
fi
if test "x${PYTHON3}" == "x"; then
if test "x${PYTHON3}" == "xno"; then
usingPython3=

View File

@ -281,14 +281,14 @@ dnl csh not being in /bin, or only tcsh being available.
AC_PATH_PROG(CSH, csh, [no])
if test "x${CSH}" = "x"; then
if test "x${CSH}" = "xno"; then
AC_MSG_ERROR([cannot find /bin/csh---cannot compile!])
fi
dnl Python3 is preferred for running the preprocessor script
dnl but CPP can be used instead.
AC_PATH_PROG([PYTHON3], [python3], [no])
if test "x${PYTHON3}" == "x"; then
if test "x${PYTHON3}" == "xno"; then
dnl check size of pointer for correct behavior on 64-bit systems
dnl If the C preprocessor is GCC, we need to force the flag to