Merge branch 'master' into magic-8.2

This commit is contained in:
Tim Edwards 2019-12-09 03:00:06 -05:00
commit 76dc836dca
11 changed files with 4226 additions and 103 deletions

View File

@ -122,55 +122,161 @@ cifPaintFunc(tile, table)
* Always returns 0 to keep the search alive.
*
* Side effects:
* Scales the tile by cifScale, then expands its area by the
* remainder of the distance to meet the minimum dimension, as
* defined by the grid distance (growDistance) in the current
* CIFOp, then paints this area into cifNewPlane using the table
* passed as parameter.
* May paint into cifNewPlane
*
* Algorithm (based on maximum horizontal stripes rule):
* Scan top and bottom boundaries from left to right. For any
* distance (including distance zero) sharing the same type (0 or 1)
* on both the tile top and bottom, find the diagonal length. If
* less than co_distance, then expand this area and paint.
* NOTE: This algorithm does not cover a number of geometry cases
* and needs to be reworked. It should be restricted to cases of
* layers that have "rect_only" DRC rules. Since the rule is usually
* needed for implants on FET gates to maintain the implant width for
* small gates, the "rect_only" requirement is not particularly
* constraining.
*
* ----------------------------------------------------------------------------
*/
int
cifGrowMinFunc(tile, plane)
cifGrowMinFunc(tile, table)
Tile *tile;
Plane *plane;
PaintResultType *table; /* Table to be used for painting. */
{
Rect area, *maxr;
int locDist, width, height;
TileTypeBitMask mask;
TileType type;
Rect area, parea;
int locDist, width, height, h;
TileType type, tptype;
Tile *tp, *tp2;
TiToRect(tile, &area);
type = TiGetType(tile);
TTMaskZero(&mask);
TTMaskSetType(&mask, type);
area.r_xbot *= cifScale;
area.r_xtop *= cifScale;
area.r_ybot *= cifScale;
area.r_ytop *= cifScale;
maxr = FindMaxRectangle2(&area, tile, plane, &mask);
if (maxr == NULL) return 0; /* Should not happen */
parea = area;
maxr->r_xbot *= cifScale;
maxr->r_xtop *= cifScale;
maxr->r_ybot *= cifScale;
maxr->r_ytop *= cifScale;
width = maxr->r_xtop - maxr->r_xbot;
height = maxr->r_ytop - maxr->r_ybot;
locDist = (growDistance - width) / 2;
if (locDist > 0)
/* Check whole tile for minimum width */
width = area.r_xtop - area.r_xbot;
if (width < growDistance)
{
maxr->r_xbot -= locDist;
maxr->r_xtop += locDist;
}
locDist = (growDistance - width) / 2;
area.r_xbot -= locDist;
area.r_xtop += locDist;
locDist = (growDistance - height) / 2;
if (locDist > 0)
/* If there is another tile on top or bottom, and the height is */
/* less than minimum, then extend height in the direction of */
/* the bordering tile. Otherwise, if the height is less than */
/* minimum, then grow halfway in both directions. */
height = area.r_ytop - area.r_ybot;
if (height < growDistance)
{
bool freeTop, freeBot;
freeTop = freeBot = TRUE;
for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp))
if (TiGetTopType(tp) == TiGetBottomType(tile))
{
freeBot = FALSE;
break;
}
for (tp2 = RT(tile); RIGHT(tp2) > LEFT(tile); tp2 = BL(tp2))
if (TiGetBottomType(tp2) == TiGetTopType(tile))
{
freeTop = FALSE;
break;
}
/* In the following, value h ensures that the euclidean */
/* distance between inside corners of the layer */
/* satisfies growDistance. */
if (freeTop == TRUE && freeBot == FALSE)
{
locDist = (growDistance - height) / 2;
h = (int)sqrt((double)(growDistance * growDistance) -
0.25 * (double)((growDistance + width) *
(growDistance + width)) + 0.5);
area.r_ybot -= h;
}
else if (freeTop == FALSE && freeBot == TRUE)
{
h = (int)sqrt((double)(growDistance * growDistance) -
0.25 * (double)((growDistance + width) *
(growDistance + width)) + 0.5);
area.r_ytop += h;
}
else {
locDist = (growDistance - height) / 2;
area.r_ybot -= locDist;
area.r_ytop += locDist;
}
}
}
DBPaintPlane(cifPlane, &area, table, (PaintUndoInfo *) NULL);
area = parea;
/* Scan bottom from left to right */
for (tp = LB(tile); LEFT(tp) < RIGHT(tile); tp = TR(tp))
{
maxr->r_ybot -= locDist;
maxr->r_ytop += locDist;
}
tptype = TiGetTopType(tp);
/* Scan top from right to left across range of tp */
for (tp2 = RT(tile); RIGHT(tp2) > LEFT(tile); tp2 = BL(tp2))
if (TiGetBottomType(tp2) == tptype)
{
/* Set range to length of overlap */
if ((LEFT(tp2) <= RIGHT(tp)) && (LEFT(tp2) >= LEFT(tp)))
{
area.r_xbot = LEFT(tp2) < LEFT(tile) ? LEFT(tile) : LEFT(tp2);
area.r_xtop = RIGHT(tp) > RIGHT(tile) ? RIGHT(tile) : RIGHT(tp);
}
else if ((RIGHT(tp2) >= LEFT(tp)) && (RIGHT(tp2) <= RIGHT(tp)))
{
area.r_xbot = LEFT(tp) < LEFT(tile) ? LEFT(tile) : LEFT(tp);
area.r_xtop = RIGHT(tp2) > RIGHT(tile) ? RIGHT(tile) : RIGHT(tp2);
}
else continue;
DBPaintPlane(cifPlane, maxr, CIFPaintTable, (PaintUndoInfo *) NULL);
area.r_xbot *= cifScale;
area.r_xtop *= cifScale;
/* Does area violate minimum width requirement? */
width = area.r_xtop - area.r_xbot;
height = area.r_ytop - area.r_ybot;
/* Manhattan requirement (to-do: Euclidean) */
if (width < growDistance)
{
locDist = (growDistance - width) / 2;
parea.r_xbot = area.r_xbot - locDist;
parea.r_xtop = area.r_xtop + locDist;
}
else
{
parea.r_xbot = area.r_xbot;
parea.r_xtop = area.r_xtop;
}
if (height < growDistance)
{
locDist = (growDistance - height) / 2;
parea.r_ybot = area.r_ybot - locDist;
parea.r_ytop = area.r_ytop + locDist;
}
else
{
parea.r_ybot = area.r_ybot;
parea.r_ytop = area.r_ytop;
}
if ((width < growDistance) || (height < growDistance))
DBPaintPlane(cifPlane, &parea, table, (PaintUndoInfo *) NULL);
}
}
CIFTileOps += 1;
return 0;
@ -3199,7 +3305,7 @@ CIFGenLayer(op, area, cellDef, temps, clientdata)
cifPlane = nextPlane;
cifScale = 1;
(void) DBSrPaintArea((Tile *) NULL, curPlane, &TiPlaneRect,
&CIFSolidBits, cifGrowMinFunc, (ClientData)curPlane);
&CIFSolidBits, cifGrowMinFunc, (ClientData)CIFPaintTable);
temp = curPlane;
curPlane = nextPlane;
nextPlane = temp;

3980
cif/CIFgen.c.test Normal file

File diff suppressed because it is too large Load Diff

View File

@ -21,7 +21,7 @@ EFread.o: EFread.c ../tcltk/tclmagic.h ../utils/magic.h ../utils/malloc.h \
../utils/geometry.h ../utils/hash.h ../utils/utils.h ../tiles/tile.h \
../commands/commands.h ../windows/windows.h ../database/database.h \
../extflat/extflat.h ../extflat/EFint.h ../extract/extract.h \
../utils/paths.h
../extract/extractInt.h ../extract/extDebugInt.h ../utils/paths.h
EFsym.o: EFsym.c ../utils/magic.h ../utils/geometry.h ../utils/geofast.h \
../utils/hash.h ../utils/malloc.h ../utils/utils.h ../extflat/extflat.h \
../extflat/EFint.h

View File

@ -63,6 +63,8 @@ void efNodeMerge();
bool efConnBuildName();
bool efConnInitSubs();
extern float locScale;
/*
* ----------------------------------------------------------------------------
@ -177,10 +179,10 @@ efBuildNode(def, isSubsnode, nodeName, nodeCap, x, y, layerName, av, ac)
newnode->efnode_flags = (isSubsnode == TRUE) ? EF_SUBS_NODE : 0;
newnode->efnode_cap = nodeCap;
newnode->efnode_attrs = (EFAttr *) NULL;
newnode->efnode_loc.r_xbot = x;
newnode->efnode_loc.r_ybot = y;
newnode->efnode_loc.r_xtop = x + 1;
newnode->efnode_loc.r_ytop = y + 1;
newnode->efnode_loc.r_xbot = (int)(0.5 + (float)x * locScale);
newnode->efnode_loc.r_ybot = (int)(0.5 + (float)y * locScale);
newnode->efnode_loc.r_xtop = newnode->efnode_loc.r_xbot + 1;
newnode->efnode_loc.r_ytop = newnode->efnode_loc.r_ybot + 1;
newnode->efnode_client = (ClientData) NULL;
if (layerName) newnode->efnode_type =
efBuildAddStr(EFLayerNames, &EFLayerNumNames, MAXTYPES, layerName);
@ -686,7 +688,8 @@ efBuildDevice(def, class, type, r, argc, argv)
{
pn = *(argv[argstart] + 1) - '0';
if (pn == 0)
devtmp.dev_area = atoi(pptr);
devtmp.dev_area = (int)(0.5 + (float)atoi(pptr)
* locScale * locScale);
/* Otherwise, punt */
}
break;
@ -697,15 +700,15 @@ efBuildDevice(def, class, type, r, argc, argv)
{
pn = *(argv[argstart] + 1) - '0';
if (pn == 0)
devtmp.dev_perim = atoi(pptr);
devtmp.dev_perim = (int)(0.5 + (float)atoi(pptr) * locScale);
/* Otherwise, use verbatim */
}
break;
case 'l':
devtmp.dev_length = atoi(pptr);
devtmp.dev_length = (int)(0.5 + (float)atoi(pptr) * locScale);
break;
case 'w':
devtmp.dev_width = atoi(pptr);
devtmp.dev_width = (int)(0.5 + (float)atoi(pptr) * locScale);
break;
case 'c':
devtmp.dev_cap = (float)atof(pptr);
@ -1248,8 +1251,9 @@ efBuildConnect(def, nodeName1, nodeName2, deltaC, av, ac)
conn->conn_next = def->def_conns;
for (n = 0; n < efNumResistClasses && ac > 1; n++, ac -= 2)
{
conn->conn_pa[n].pa_area = atoi(*av++);
conn->conn_pa[n].pa_perim = atoi(*av++);
conn->conn_pa[n].pa_area = (int)(0.5 + (float)atoi(*av++)
* locScale * locScale);
conn->conn_pa[n].pa_perim = (int)(0.5 + (float)atoi(*av++) * locScale);
}
for ( ; n < efNumResistClasses; n++)
conn->conn_pa[n].pa_area = conn->conn_pa[n].pa_perim = 0;

View File

@ -38,6 +38,7 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#include "extflat/extflat.h"
#include "extflat/EFint.h"
#include "extract/extract.h"
#include "extract/extractInt.h"
#include "utils/paths.h"
#ifndef MAGIC_WRAPPER
@ -96,6 +97,7 @@ keyTable[] =
/* Data shared with EFerror.c */
char *efReadFileName; /* Name of file currently being read */
int efReadLineNum; /* Current line number in above file */
float locScale; /* Multiply values in the file by this on read-in */
/* Data local to this file */
static bool efReadDef();
@ -139,6 +141,7 @@ EFReadFile(name, dosubckt, resist, noscale)
if (def == NULL)
def = efDefNew(name);
locScale = 1.0;
rc = efReadDef(def, dosubckt, resist, noscale, TRUE);
if (EFArgTech) EFTech = StrDup((char **) NULL, EFArgTech);
if (EFScale == 0.0) EFScale = 1.0;
@ -265,6 +268,11 @@ readfile:
cscale = 1;
}
lscale = (float)atof(argv[3]);
if (lscale != ExtCurStyle->exts_unitsPerLambda)
{
locScale = lscale / ExtCurStyle->exts_unitsPerLambda;
lscale = ExtCurStyle->exts_unitsPerLambda;
}
if (lscale == 0.0)
{
efReadError("Bad linear scaling = 0; reset to 1.\n");
@ -283,10 +291,10 @@ readfile:
/* attr node xlo ylo xhi yhi type text */
case ATTR:
r.r_xbot = atoi(argv[2]);
r.r_ybot = atoi(argv[3]);
r.r_xtop = atoi(argv[4]);
r.r_ytop = atoi(argv[5]),
r.r_xbot = (int)(0.5 + (float)atoi(argv[2]) * locScale);
r.r_ybot = (int)(0.5 + (float)atoi(argv[3]) * locScale);
r.r_xtop = (int)(0.5 + (float)atoi(argv[4]) * locScale);
r.r_ytop = (int)(0.5 + (float)atoi(argv[5]) * locScale),
efBuildAttr(def, argv[1], &r, argv[6], argv[7]);
break;
@ -351,10 +359,10 @@ readfile:
break; /* we will deal with in efBuildDevice(). */
}
r.r_xbot = atoi(argv[3]);
r.r_ybot = atoi(argv[4]);
r.r_xtop = atoi(argv[5]);
r.r_ytop = atoi(argv[6]);
r.r_xbot = (int)(0.5 + (float)atoi(argv[3]) * locScale);
r.r_ybot = (int)(0.5 + (float)atoi(argv[4]) * locScale);
r.r_xtop = (int)(0.5 + (float)atoi(argv[5]) * locScale);
r.r_ytop = (int)(0.5 + (float)atoi(argv[6]) * locScale);
if (efBuildDevice(def, (char)n, argv[2], &r, argc - 7, &argv[7]) != 0)
{
@ -366,10 +374,10 @@ readfile:
/* for backwards compatibility */
/* fet type xlo ylo xhi yhi area perim substrate GATE T1 T2 ... */
case FET:
r.r_xbot = atoi(argv[2]);
r.r_ybot = atoi(argv[3]);
r.r_xtop = atoi(argv[4]);
r.r_ytop = atoi(argv[5]);
r.r_xbot = (int)(0.5 + (float)atoi(argv[2]) * locScale);
r.r_ybot = (int)(0.5 + (float)atoi(argv[3]) * locScale);
r.r_xtop = (int)(0.5 + (float)atoi(argv[4]) * locScale);
r.r_ytop = (int)(0.5 + (float)atoi(argv[5]) * locScale);
if (efBuildDevice(def, DEV_FET, argv[1], &r, argc - 6, &argv[6]) != 0)
{
efReadError("Incomplete terminal description for fet\n");
@ -563,8 +571,8 @@ resistChanged:
/* distance driver receiver min max */
case DIST:
efBuildDist(def, argv[1], argv[2],
(int)(lscale*atoi(argv[3])),
(int)(lscale*atoi(argv[4])));
(int)(lscale*atoi(argv[3])*locScale),
(int)(lscale*atoi(argv[4])*locScale));
break;
/* killnode nodename */

View File

@ -130,7 +130,6 @@ ResProcessJunction(tile, tp, xj, yj, NodeList)
return;
}
#endif
if (j2->tj_status & RES_TILE_DONE) return;
resptr = (resNode *) mallocMagic((unsigned)(sizeof(resNode)));
resptr->rn_te = (tElement *) NULL;

View File

@ -135,20 +135,40 @@ ResPrintExtDev(outextfile, devices)
if (varsub != NULL) subsName = varsub;
}
#endif
/* Output according to device type and class. */
/* Code largely matches what's in ExtBasic.c extOutputDevices() */
/* Output according to device type */
if (devptr->exts_deviceClass != DEV_FET)
fprintf(outextfile,"device ");
/* fet type xl yl xh yh area perim sub gate t1 t2 */
fprintf(outextfile,"fet %s %d %d %d %d %d %d "
"%s \"%s\" %d %s \"%s\" %d %s \"%s\" %d %s\n",
fprintf(outextfile,"%s %s %d %d %d %d ",
extDevTable[devptr->exts_deviceClass],
devptr->exts_deviceName,
devices->layout->rd_inside.r_ll.p_x,
devices->layout->rd_inside.r_ll.p_y,
devices->layout->rd_inside.r_ll.p_x + 1,
devices->layout->rd_inside.r_ll.p_y + 1,
devices->layout->rd_area,
devices->layout->rd_perim,
subsName,
devices->layout->rd_inside.r_ll.p_y + 1);
switch (devptr->exts_deviceClass)
{
case DEV_FET:
fprintf(outextfile," %d %d",
devices->layout->rd_area,
devices->layout->rd_perim);
break;
case DEV_MOSFET:
case DEV_ASYMMETRIC:
case DEV_BJT:
fprintf(outextfile," %d %d",
devices->layout->rd_length,
devices->layout->rd_width);
break;
}
fprintf(outextfile, " \"%s\"", subsName);
fprintf(outextfile, " \"%s\" %d %s \"%s\" %d %s \"%s\" %d %s\n",
devices->gate->name,
devices->layout->rd_length * 2,
devices->rs_gattr,
@ -190,7 +210,7 @@ ResPrintExtNode(outextfile, nodelist, nodename)
ResSimNode *node,*ResInitializeNode();
bool DoKillNode = TRUE;
resNode *snode = nodelist;
/* If any of the subnode names match the original node name, then */
/* we don't want to rip out that node with a "killnode" statement. */

View File

@ -229,12 +229,12 @@ ResReadNode(nodefile)
char *cp;
float lambda;
/* NOTE: Units from the .sim file or the .nodes file are in centimicrons
* when multiplied by resscale (units from the .sim file 1st line).
* multiply resscale by the extract scale (exts_unitsPerLambda) used to
* generate .ext dimensions originally, to get back to database units.
/* NOTE: Units from the .nodes file are in centimicrons.
* Divide by the extract scale (exts_unitsPerLambda) to get back
* to database units. This assumes that exts_unitsPerLambda doesn't
* change between output and readback.
*/
lambda = resscale * (float)ExtCurStyle->exts_unitsPerLambda;
lambda = (float)ExtCurStyle->exts_unitsPerLambda;
fp = PaOpen(nodefile,"r",".nodes",".", (char *) NULL, (char **) NULL);
if (fp == NULL)
@ -358,11 +358,10 @@ ResSimDevice(line,rpersquare,ttype)
}
device->resistance = MagAtof(line[RDEV_LENGTH]) * rpersquare/MagAtof(line[RDEV_WIDTH]);
}
device->tnumber = ++Maxtnumber;
device->status = FALSE;
device->nextDev = ResRDevList;
lambda = resscale * (float)ExtCurStyle->exts_unitsPerLambda;
lambda = (float)ExtCurStyle->exts_unitsPerLambda / resscale;
device->location.p_x = (int)((float)atof(line[RDEV_DEVX]) / lambda);
device->location.p_y = (int)((float)atof(line[RDEV_DEVY]) / lambda);

View File

@ -35,21 +35,19 @@ static char rcsid[] __attribute__ ((unused)) = "$Header: /usr/cvsroot/magic-8.0/
#define INITFLATSIZE 1024
#define MAXNAME 1000
/* time constants are produced by multiplying attofarads by milliohms, */
/* Time constants are produced by multiplying attofarads by milliohms, */
/* giving zeptoseconds (yes, really. Look it up). This constant */
/* converts zeptoseconts to nanoseconds. */
/* converts zeptoseconds to nanoseconds. */
#define Z_TO_N 1e12
/* ResSimNode is a node read in from a sim file */
HashTable ResNodeTable; /* Hash table of sim file nodes */
RDev *ResRDevList; /* Linked list of Sim devices */
ResGlobalParams gparams; /* Junk passed between */
/* ResCheckSimNodes and */
/* ResExtractNet. */
int Maxtnumber; /*maximum device number */
extern ResSimNode *ResOriginalNodes; /*Linked List of Nodes */
int resNodeNum;
@ -104,7 +102,6 @@ ExtResisForDef(celldef, resisdata)
ResRDevList = NULL;
ResOriginalNodes = NULL;
Maxtnumber = 0;
HashInit(&ResNodeTable, INITFLATSIZE, HT_STRINGKEYS);
/* read in .sim file */
result = (ResReadSim(celldef->cd_name,
@ -870,6 +867,19 @@ ResCheckSimNodes(celldef, resisdata)
return;
}
/*
* Write a scale line at the top of the .res.ext file, as the
* scale may be different from the original .ext file.
*/
if (ResExtFile != NULL)
{
fprintf(ResExtFile, "scale %d %d %g\n",
ExtCurStyle->exts_resistScale,
ExtCurStyle->exts_capScale,
ExtCurStyle->exts_unitsPerLambda);
}
/*
* Write reference plane (substrate) definition and end statement
* to the FastHenry geometry file.

View File

@ -954,26 +954,25 @@ ResDoSimplify(tolerance,rctol,goodies)
{
RCDelayStuff *rc = (RCDelayStuff *) ResNodeList->rn_client;
if (rc != (RCDelayStuff *)NULL)
{
goodies->rg_nodecap = totalcap;
ResCalculateTDi(ResOriginNode,(resResistor *)NULL,
goodies->rg_nodecap = totalcap;
ResCalculateTDi(ResOriginNode,(resResistor *)NULL,
goodies->rg_bigdevres);
goodies->rg_Tdi = rc->rc_Tdi;
slownode = ResNodeList;
for (node = ResNodeList; node != NULL; node = node->rn_more)
{
rc = (RCDelayStuff *)node->rn_client;
if (rc && (goodies->rg_Tdi < rc->rc_Tdi))
{
slownode = node;
goodies->rg_Tdi = rc->rc_Tdi;
}
}
slownode->rn_status |= RN_MAXTDI;
}
if (rc != (RCDelayStuff *)NULL)
goodies->rg_Tdi = rc->rc_Tdi;
else
goodies->rg_Tdi = 0;
goodies->rg_Tdi = 0;
slownode = ResNodeList;
for (node = ResNodeList; node != NULL; node = node->rn_more)
{
rc = (RCDelayStuff *)node->rn_client;
if (rc && (goodies->rg_Tdi < rc->rc_Tdi))
{
slownode = node;
goodies->rg_Tdi = rc->rc_Tdi;
}
}
slownode->rn_status |= RN_MAXTDI;
}
else
{

View File

@ -296,7 +296,6 @@ typedef struct rdev
Point location; /* Location of lower left point of */
/* device. */
float resistance; /* "Resistance" of device. */
int tnumber; /* Device number */
int rs_ttype; /* device type */
char *rs_gattr; /* Gate attributes, if any */
char *rs_sattr;
@ -572,7 +571,6 @@ extern RDev *ResRDevList;
extern REcell *ResBigEventList;
extern int ResOptionsFlags;
extern char *ResCurrentNode;
extern int Maxtnumber;
extern ResSimNode *ResOriginalNodes;
#ifdef ARIEL
extern int ResMinEventTime;