Changed the behavior of GDS writing to halt with an error if an
attempt is made to write an abstract view to GDS. This behavior can be overridded with the new command option "gds abstract [enable|disable]". Also: Corrected extraction to allow split tiles to be set as the reference tile for a node. Previously this was allowed only if the tile was the first to be searched, but that can cause different tiles to be marked as the reference depending on where the search starts, resulting in different names for the same node in .ext files, which is bad. Also: Modified the LEF annotation to avoid bad entries in the LEF that would create layers in the layout where none exist.
This commit is contained in:
parent
5aee1dcb5a
commit
0dac37cb46
|
|
@ -65,6 +65,7 @@ bool CalmaFlattenArrays = FALSE; /* If TRUE, output arrays as individual uses *
|
|||
bool CalmaAddendum = FALSE; /* If TRUE, do not output readonly cell defs */
|
||||
time_t *CalmaDateStamp = NULL; /* If non-NULL, output this for creation date stamp */
|
||||
bool CalmaAllowUndefined = FALSE; /* If TRUE, allow calls to undefined cells */
|
||||
bool CalmaAllowAbstract = FALSE; /* If TRUE, allow abstract views to be written */
|
||||
|
||||
/* Experimental stuff---not thoroughly tested (as of Sept. 2007)! */
|
||||
bool CalmaContactArrays = FALSE; /* If TRUE, output contacts as subcell arrays */
|
||||
|
|
@ -925,12 +926,18 @@ calmaProcessDef(def, outf, do_library)
|
|||
|
||||
if (isReadOnly && hasContent && CalmaAddendum) return (0);
|
||||
|
||||
/* Give a strongly-worded statement about writing abstract views */
|
||||
|
||||
if (isAbstract && !isReadOnly)
|
||||
TxError("Warning: Writing abstract view of \"%s\" to GDS. This is"
|
||||
" probably not what you want to do.\n",
|
||||
{
|
||||
if (CalmaAllowAbstract)
|
||||
TxError("Warning: Writing abstract view of \"%s\" to GDS.\n",
|
||||
def->cd_name);
|
||||
else
|
||||
{
|
||||
TxError("Error: Cell \"%s\" is an abstract view; cannot write GDS.\n",
|
||||
def->cd_name);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Output the definitions for any of our descendants that have
|
||||
|
|
|
|||
|
|
@ -73,6 +73,7 @@ extern HashTable calmaPrefixHash;
|
|||
extern HashTable calmaUndefHash;
|
||||
extern bool CalmaDoLibrary;
|
||||
extern bool CalmaAllowUndefined;
|
||||
extern bool CalmaAllowAbstract;
|
||||
extern bool CalmaContactArrays;
|
||||
extern bool CalmaAddendum;
|
||||
extern bool CalmaMergeTiles;
|
||||
|
|
@ -880,12 +881,18 @@ calmaProcessDefZ(def, outf, do_library)
|
|||
|
||||
if (isReadOnly && hasContent && CalmaAddendum) return (0);
|
||||
|
||||
/* Give a strongly-worded statement about writing abstract views */
|
||||
|
||||
if (isAbstract && !isReadOnly)
|
||||
TxError("Warning: Writing abstract view of \"%s\" to GDS. This is"
|
||||
" probably not what you want to do.\n",
|
||||
{
|
||||
if (CalmaAllowAbstract)
|
||||
TxError("Warning: Writing abstract view of \"%s\" to GDS.\n",
|
||||
def->cd_name);
|
||||
else
|
||||
{
|
||||
TxError("Error: Cell \"%s\" is an abstract view; cannot write GDS.\n",
|
||||
def->cd_name);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Output the definitions for any of our descendants that have
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ extern int CalmaCompression;
|
|||
#endif
|
||||
extern bool CalmaPostOrder;
|
||||
extern bool CalmaAllowUndefined;
|
||||
extern bool CalmaAllowAbstract;
|
||||
|
||||
/* Externally-visible procedures: */
|
||||
extern bool CalmaWrite();
|
||||
|
|
|
|||
|
|
@ -93,31 +93,32 @@ bool cmdDumpParseArgs();
|
|||
*/
|
||||
|
||||
#define CALMA_HELP 0
|
||||
#define CALMA_ADDENDUM 1
|
||||
#define CALMA_ARRAYS 2
|
||||
#define CALMA_COMPRESS 3
|
||||
#define CALMA_CONTACTS 4
|
||||
#define CALMA_DATESTAMP 5
|
||||
#define CALMA_DRCCHECK 6
|
||||
#define CALMA_FLATTEN 7
|
||||
#define CALMA_FLATGLOB 8
|
||||
#define CALMA_ORDERING 9
|
||||
#define CALMA_LABELS 10
|
||||
#define CALMA_LIBRARY 11
|
||||
#define CALMA_LOWER 12
|
||||
#define CALMA_MASKHINTS 13
|
||||
#define CALMA_MERGE 14
|
||||
#define CALMA_NO_STAMP 15
|
||||
#define CALMA_NO_DUP 16
|
||||
#define CALMA_READ 17
|
||||
#define CALMA_READONLY 18
|
||||
#define CALMA_RESCALE 19
|
||||
#define CALMA_WARNING 20
|
||||
#define CALMA_WRITE 21
|
||||
#define CALMA_POLYS 22
|
||||
#define CALMA_PATHS 23
|
||||
#define CALMA_UNDEFINED 24
|
||||
#define CALMA_UNIQUE 25
|
||||
#define CALMA_ABSTRACT 1
|
||||
#define CALMA_ADDENDUM 2
|
||||
#define CALMA_ARRAYS 3
|
||||
#define CALMA_COMPRESS 4
|
||||
#define CALMA_CONTACTS 5
|
||||
#define CALMA_DATESTAMP 6
|
||||
#define CALMA_DRCCHECK 7
|
||||
#define CALMA_FLATTEN 8
|
||||
#define CALMA_FLATGLOB 9
|
||||
#define CALMA_ORDERING 10
|
||||
#define CALMA_LABELS 11
|
||||
#define CALMA_LIBRARY 12
|
||||
#define CALMA_LOWER 13
|
||||
#define CALMA_MASKHINTS 14
|
||||
#define CALMA_MERGE 15
|
||||
#define CALMA_NO_STAMP 16
|
||||
#define CALMA_NO_DUP 17
|
||||
#define CALMA_READ 18
|
||||
#define CALMA_READONLY 19
|
||||
#define CALMA_RESCALE 20
|
||||
#define CALMA_WARNING 21
|
||||
#define CALMA_WRITE 22
|
||||
#define CALMA_POLYS 23
|
||||
#define CALMA_PATHS 24
|
||||
#define CALMA_UNDEFINED 25
|
||||
#define CALMA_UNIQUE 26
|
||||
|
||||
#define CALMA_WARN_HELP CIF_WARN_END /* undefined by CIF module */
|
||||
|
||||
|
|
@ -147,6 +148,8 @@ CmdCalma(w, cmd)
|
|||
static char *cmdCalmaOption[] =
|
||||
{
|
||||
"help print this help information",
|
||||
"abstract [allow|disallow]\n"
|
||||
" [dis]allow writing of GDS with calls to abstract cells",
|
||||
"addendum [yes|no] output only cells that are not type \"readonly\"",
|
||||
"arrays [yes|no] output arrays as individual subuses (like in CIF)",
|
||||
"compress [value] compress output with zlib compression 0 to 6",
|
||||
|
|
@ -320,6 +323,26 @@ CmdCalma(w, cmd)
|
|||
CalmaAllowUndefined = (option < 2) ? FALSE : TRUE;
|
||||
return;
|
||||
|
||||
case CALMA_ABSTRACT:
|
||||
if (cmd->tx_argc == 2)
|
||||
{
|
||||
#ifdef MAGIC_WRAPPER
|
||||
Tcl_SetObjResult(magicinterp, Tcl_NewBooleanObj(CalmaAllowAbstract));
|
||||
#else
|
||||
TxPrintf("Writing of GDS file with abstract cells is %sallowed.\n",
|
||||
(CalmaAllowUndefined) ? "" : "dis");
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
else if (cmd->tx_argc != 3)
|
||||
goto wrongNumArgs;
|
||||
|
||||
option = Lookup(cmd->tx_argv[2], cmdCalmaAllowDisallow);
|
||||
if (option < 0)
|
||||
goto wrongNumArgs;
|
||||
CalmaAllowAbstract = (option < 2) ? FALSE : TRUE;
|
||||
return;
|
||||
|
||||
case CALMA_COMPRESS:
|
||||
if (cmd->tx_argc == 2)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -187,6 +187,13 @@ Read GDSII input or generate GDSII output.
|
|||
Options for <B>gds write</B>:
|
||||
|
||||
<DL>
|
||||
<DT> <B>abstract</B> [<B>allow</B>|<B>disallow</B>]
|
||||
<DD> Define the behavior for abstract cells (e.g., cells derived
|
||||
from LEF views). If allowed, then these cells will be
|
||||
written to GDS even if the abstraction layers (e.g.,
|
||||
metal obstructions) have no defined GDS layers. If
|
||||
disallowed, the GDS file will not be written if abstract
|
||||
cells exist. The default behavior is <B>disallow</B>.
|
||||
<DT> <B>addendum</B> [<B>yes</B>|<B>no</B>]
|
||||
<DD> Do not output vendor (readonly) cell definitions. Only the
|
||||
references will be output. This makes the output file an
|
||||
|
|
|
|||
|
|
@ -926,11 +926,25 @@ efFlatKills(hc)
|
|||
}
|
||||
|
||||
|
||||
/*----
|
||||
* WIP
|
||||
*----
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
* efFlatCapsDeviceless --
|
||||
*
|
||||
* Recursive procedure to flatten all capacitors in the circuit.
|
||||
* Works like efFlatCaps() (see below), but ignores CellDefs that
|
||||
* have no devices.
|
||||
*
|
||||
* Results:
|
||||
* Returns 0 to keep efHierSrUses going.
|
||||
*
|
||||
* Side effects:
|
||||
* See description of efFlatCaps().
|
||||
*
|
||||
* ----------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
int
|
||||
efFlatCapsDeviceless(hc)
|
||||
HierContext *hc;
|
||||
|
|
|
|||
|
|
@ -3553,17 +3553,15 @@ extSetNodeNum(reg, plane, tile)
|
|||
|
||||
if (!SplitSide(tile) && SplitDirection(tile))
|
||||
type = SplitSide(tile) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||
else if (reg->lreg_pnum == DBNumPlanes)
|
||||
else
|
||||
{
|
||||
/* Accept tile provisionally anyway */
|
||||
type = SplitSide(tile) ? SplitRightType(tile) : SplitLeftType(tile);
|
||||
/* (Are these type checks necessary?) */
|
||||
if ((type == TT_SPACE) || !TTMaskHasType(&DBPlaneTypes[plane], type))
|
||||
type = SplitSide(tile) ? SplitLeftType(tile) : SplitRightType(tile);
|
||||
if ((type == TT_SPACE) || !TTMaskHasType(&DBPlaneTypes[plane], type))
|
||||
return;
|
||||
}
|
||||
else
|
||||
return;
|
||||
}
|
||||
else
|
||||
type = TiGetType(tile);
|
||||
|
|
|
|||
|
|
@ -61,7 +61,6 @@ FILE *extFileOpen();
|
|||
Plane* extCellFile();
|
||||
void extHeader();
|
||||
|
||||
|
||||
/*
|
||||
* ----------------------------------------------------------------------------
|
||||
*
|
||||
|
|
|
|||
|
|
@ -96,14 +96,17 @@ extLabEach(tile, pNum, arg)
|
|||
int pNum;
|
||||
FindRegion *arg;
|
||||
{
|
||||
TransRegion *reg = (TransRegion *) arg->fra_region;
|
||||
|
||||
/* Avoid setting the region's tile pointer to a split tile if we can */
|
||||
/*
|
||||
if (IsSplit(reg->treg_tile) && !IsSplit(tile))
|
||||
{
|
||||
reg->treg_tile = tile;
|
||||
reg->treg_area = pNum;
|
||||
}
|
||||
*/
|
||||
|
||||
TransRegion *reg = (TransRegion *) arg->fra_region;
|
||||
|
||||
if (reg->treg_area == DBNumPlanes) reg->treg_area = pNum;
|
||||
extSetNodeNum((LabRegion *)reg, pNum, tile);
|
||||
|
|
|
|||
|
|
@ -1083,6 +1083,25 @@ LefPaintPolygon(lefMacro, pointList, points, curlayer, keep)
|
|||
return rlist;
|
||||
}
|
||||
|
||||
/*
|
||||
*------------------------------------------------------------
|
||||
* lefUnconnectFunc --
|
||||
*
|
||||
* Callback function used by LefReadGeometry when doing LEF
|
||||
* annotation to check if a port is incompatible with the
|
||||
* existing layout.
|
||||
*
|
||||
* Return 1 always.
|
||||
*------------------------------------------------------------
|
||||
*/
|
||||
int
|
||||
lefUnconnectFunc(tile, clientData)
|
||||
Tile *tile;
|
||||
ClientData clientData;
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
*------------------------------------------------------------
|
||||
* LefReadGeometry --
|
||||
|
|
@ -1101,6 +1120,10 @@ LefPaintPolygon(lefMacro, pointList, points, curlayer, keep)
|
|||
* it also determines what layer is returned by
|
||||
* function LefReadLayer().
|
||||
*
|
||||
* If is_imported is TRUE, then this is an annotation,
|
||||
* and no geometry should ever be added over an area
|
||||
* that does not have a compatible type.
|
||||
*
|
||||
* Side Effects:
|
||||
* Reads input from file f;
|
||||
* Paints into the CellDef lefMacro.
|
||||
|
|
@ -1113,11 +1136,12 @@ enum lef_geometry_keys {LEF_LAYER = 0, LEF_WIDTH, LEF_PATH,
|
|||
LEF_GEOMETRY_END};
|
||||
|
||||
LinkedRect *
|
||||
LefReadGeometry(lefMacro, f, oscale, do_list)
|
||||
LefReadGeometry(lefMacro, f, oscale, do_list, is_imported)
|
||||
CellDef *lefMacro;
|
||||
FILE *f;
|
||||
float oscale;
|
||||
bool do_list;
|
||||
bool is_imported;
|
||||
{
|
||||
TileType curlayer = -1, otherlayer = -1;
|
||||
|
||||
|
|
@ -1169,6 +1193,19 @@ LefReadGeometry(lefMacro, f, oscale, do_list)
|
|||
paintrect = (curlayer < 0) ? NULL : LefReadRect(f, curlayer, oscale);
|
||||
if (paintrect)
|
||||
{
|
||||
if (is_imported)
|
||||
{
|
||||
/* Check if layout area is compatible with the port */
|
||||
int pNum = DBPlane(curlayer);
|
||||
if (DBSrPaintArea((Tile *)NULL, lefMacro->cd_planes[pNum],
|
||||
paintrect, &DBConnectTbl[curlayer],
|
||||
lefUnconnectFunc, (ClientData)NULL) == 1)
|
||||
{
|
||||
LefEndStatement(f);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Paint the area, if a CellDef is defined */
|
||||
if (lefMacro)
|
||||
{
|
||||
|
|
@ -1275,18 +1312,20 @@ LefReadGeometry(lefMacro, f, oscale, do_list)
|
|||
*/
|
||||
|
||||
void
|
||||
LefReadPort(lefMacro, f, pinName, pinNum, pinDir, pinUse, pinShape, oscale, lanno)
|
||||
LefReadPort(lefMacro, f, pinName, pinNum, pinDir, pinUse, pinShape, oscale,
|
||||
is_imported, lanno)
|
||||
CellDef *lefMacro;
|
||||
FILE *f;
|
||||
char *pinName;
|
||||
int pinNum, pinDir, pinUse, pinShape;
|
||||
float oscale;
|
||||
bool is_imported;
|
||||
Label *lanno;
|
||||
{
|
||||
Label *newlab;
|
||||
LinkedRect *rectList;
|
||||
|
||||
rectList = LefReadGeometry(lefMacro, f, oscale, TRUE);
|
||||
rectList = LefReadGeometry(lefMacro, f, oscale, TRUE, is_imported);
|
||||
|
||||
while (rectList != NULL)
|
||||
{
|
||||
|
|
@ -1650,7 +1689,7 @@ LefReadPin(lefMacro, f, pinname, pinNum, oscale, is_imported)
|
|||
if ((lab == NULL) && (firstport == TRUE))
|
||||
DBEraseLabelsByContent(lefMacro, NULL, -1, testpin);
|
||||
LefReadPort(lefMacro, f, testpin, pinNum, pinDir, pinUse,
|
||||
pinShape, oscale, lab);
|
||||
pinShape, oscale, TRUE, lab);
|
||||
}
|
||||
else
|
||||
LefSkipSection(f, NULL);
|
||||
|
|
@ -1658,7 +1697,7 @@ LefReadPin(lefMacro, f, pinname, pinNum, oscale, is_imported)
|
|||
}
|
||||
else
|
||||
LefReadPort(lefMacro, f, testpin, pinNum, pinDir, pinUse,
|
||||
pinShape, oscale, NULL);
|
||||
pinShape, oscale, FALSE, NULL);
|
||||
break;
|
||||
case LEF_CAPACITANCE:
|
||||
case LEF_ANTENNADIFF:
|
||||
|
|
@ -2143,7 +2182,7 @@ origin_error:
|
|||
if (is_imported)
|
||||
LefSkipSection(f, NULL);
|
||||
else
|
||||
LefReadGeometry(lefMacro, f, oscale, FALSE);
|
||||
LefReadGeometry(lefMacro, f, oscale, FALSE, is_imported);
|
||||
break;
|
||||
case LEF_TIMING:
|
||||
LefSkipSection(f, macro_keys[LEF_TIMING]);
|
||||
|
|
|
|||
|
|
@ -564,7 +564,7 @@ donesides:
|
|||
pnum = minp;
|
||||
fdir = mindir;
|
||||
|
||||
/* WIP Diagnostic */
|
||||
/* Diagnostic */
|
||||
// TxPrintf("Cost = %d Tile @ %d %d plane %d dir %d\n",
|
||||
// mincost, tile->ti_ll.p_x, tile->ti_ll.p_y, pnum, fdir);
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue