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:
Tim Edwards 2022-11-02 09:40:20 -04:00
parent 5aee1dcb5a
commit 0dac37cb46
12 changed files with 149 additions and 51 deletions

View File

@ -1 +1 @@
8.3.333
8.3.334

View File

@ -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

View File

@ -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,13 +881,19 @@ 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
* not already been output. Numbers are assigned to the subcells

View File

@ -47,6 +47,7 @@ extern int CalmaCompression;
#endif
extern bool CalmaPostOrder;
extern bool CalmaAllowUndefined;
extern bool CalmaAllowAbstract;
/* Externally-visible procedures: */
extern bool CalmaWrite();

View File

@ -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)
{

View File

@ -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

View File

@ -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;

View File

@ -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);

View File

@ -61,7 +61,6 @@ FILE *extFileOpen();
Plane* extCellFile();
void extHeader();
/*
* ----------------------------------------------------------------------------
*

View File

@ -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);

View File

@ -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]);

View File

@ -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);
}