Reworked the "port" and "noport" label type designations in the
tech file to correct the underlying problem with the SkyWater sky130 process in which a different layer/purpose pair is used for TEXTTYPE and DATATYPE for the same layer. Previously, all output from magic writes the same pair for both when writing a port label. The new method preserves existing syntax, although there are some differences based on what order the "port" statement appears relative to other types for the same layer.
This commit is contained in:
parent
be40825e9a
commit
0bbb558b94
|
|
@ -323,7 +323,34 @@ calmaElementBoundary()
|
|||
if (lab == NULL)
|
||||
{
|
||||
/* There was no label in the area. Create a placeholder label */
|
||||
DBPutLabel(cifReadCellDef, &rpc, GEO_CENTER, "", type, 0, 0);
|
||||
lab = DBPutLabel(cifReadCellDef, &rpc, GEO_CENTER, "", type, 0, 0);
|
||||
}
|
||||
if ((cifCurReadStyle->crs_labelSticky[ciftype] == LABEL_TYPE_PORT)
|
||||
&& ((lab->lab_flags & PORT_DIR_MASK) == 0))
|
||||
{
|
||||
/* Label was read previously as a text type, but the pin layer
|
||||
* causes it to be recast as a port, or corresponding label has
|
||||
* not yet been seen.
|
||||
*/
|
||||
int i, idx;
|
||||
Label *sl;
|
||||
|
||||
/* Order ports as encountered. */
|
||||
i = -1;
|
||||
for (sl = cifReadCellDef->cd_labels; sl != NULL; sl = sl->lab_next)
|
||||
{
|
||||
idx = sl->lab_port;
|
||||
if (idx > i) i = idx;
|
||||
if ((idx > 0) && (sl != lab) && !strcmp(sl->lab_text, lab->lab_text))
|
||||
{
|
||||
i = idx - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
lab->lab_port = i;
|
||||
lab->lab_flags |= PORT_DIR_NORTH | PORT_DIR_SOUTH |
|
||||
PORT_DIR_EAST | PORT_DIR_WEST;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -709,7 +736,7 @@ calmaElementText()
|
|||
TileType type;
|
||||
Rect r;
|
||||
double dval;
|
||||
int size, micron, angle, font, pos;
|
||||
int size, micron, angle, font, pos, portnum, idx;
|
||||
|
||||
/* Skip CALMA_ELFLAGS, CALMA_PLEX */
|
||||
calmaSkipSet(calmaElementIgnore);
|
||||
|
|
@ -731,6 +758,7 @@ calmaElementText()
|
|||
|
||||
font = -1;
|
||||
angle = 0;
|
||||
portnum = 0;
|
||||
|
||||
/* Use the minimum width of the layer on which the text is placed
|
||||
* as the default text size, or 1um, whichever is smaller. Account
|
||||
|
|
@ -992,6 +1020,26 @@ calmaElementText()
|
|||
sl->lab_next = lab->lab_next;
|
||||
if (cifReadCellDef->cd_lastLabel == lab)
|
||||
cifReadCellDef->cd_lastLabel = sl;
|
||||
|
||||
/* Port number from the placeholder is ignored; find
|
||||
* a new valid port number for the new label name.
|
||||
*/
|
||||
i = -1;
|
||||
for (sl = cifReadCellDef->cd_labels; sl != NULL; sl = sl->lab_next)
|
||||
{
|
||||
idx = sl->lab_port;
|
||||
if (idx > i) i = idx;
|
||||
if ((idx > 0) && (sl != lab) && !strcmp(sl->lab_text, textbody))
|
||||
{
|
||||
i = idx - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
i++;
|
||||
portnum = i;
|
||||
flags |= PORT_DIR_NORTH | PORT_DIR_SOUTH |
|
||||
PORT_DIR_EAST | PORT_DIR_WEST;
|
||||
|
||||
freeMagic((char *)lab);
|
||||
break;
|
||||
}
|
||||
|
|
@ -1000,16 +1048,14 @@ calmaElementText()
|
|||
}
|
||||
|
||||
if (font < 0)
|
||||
lab = DBPutLabel(cifReadCellDef, &r, pos, textbody, type, flags, 0);
|
||||
lab = DBPutLabel(cifReadCellDef, &r, pos, textbody, type, flags, portnum);
|
||||
else
|
||||
lab = DBPutFontLabel(cifReadCellDef, &r, font, size, angle,
|
||||
&GeoOrigin, pos, textbody, type, flags, 0);
|
||||
&GeoOrigin, pos, textbody, type, flags, portnum);
|
||||
|
||||
if ((lab != NULL) && (cifnum >= 0) &&
|
||||
(cifCurReadStyle->crs_labelSticky[cifnum] == LABEL_TYPE_PORT))
|
||||
{
|
||||
int idx;
|
||||
|
||||
/* No port information can be encoded in the GDS file, so */
|
||||
/* assume defaults, and assume that the port order is the */
|
||||
/* order in which labels arrive in the GDS stream. If */
|
||||
|
|
|
|||
|
|
@ -1341,14 +1341,15 @@ calmaOutFunc(def, f, cliprect)
|
|||
|
||||
if (CalmaDoLabels)
|
||||
{
|
||||
int i, maxport = -1;
|
||||
int i, ltype, maxport = -1;
|
||||
|
||||
for (lab = def->cd_labels; lab; lab = lab->lab_next)
|
||||
{
|
||||
type = CIFCurStyle->cs_labelLayer[lab->lab_type];
|
||||
if ((type >= 0) && (lab->lab_flags & PORT_DIR_MASK) == 0)
|
||||
if ((lab->lab_flags & PORT_DIR_MASK) == 0)
|
||||
{
|
||||
calmaWriteLabelFunc(lab, type, f);
|
||||
ltype = CIFCurStyle->cs_labelLayer[lab->lab_type];
|
||||
type = ltype;
|
||||
calmaWriteLabelFunc(lab, ltype, type, f);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1360,11 +1361,12 @@ calmaOutFunc(def, f, cliprect)
|
|||
for (i = 0; i <= maxport; i++)
|
||||
for (lab = def->cd_labels; lab; lab = lab->lab_next)
|
||||
{
|
||||
ltype = CIFCurStyle->cs_portText[lab->lab_type];
|
||||
type = CIFCurStyle->cs_portLayer[lab->lab_type];
|
||||
if ((type >= 0) && ((lab->lab_flags & PORT_DIR_MASK) != 0) &&
|
||||
(lab->lab_port == i))
|
||||
{
|
||||
calmaWriteLabelFunc(lab, type, f);
|
||||
calmaWriteLabelFunc(lab, ltype, type, f);
|
||||
/* break; */ /* Do not limit to unique labels! */
|
||||
}
|
||||
}
|
||||
|
|
@ -2823,18 +2825,21 @@ calmaWritePaintFunc(tile, cos)
|
|||
*/
|
||||
|
||||
void
|
||||
calmaWriteLabelFunc(lab, type, f)
|
||||
calmaWriteLabelFunc(lab, ltype, type, f)
|
||||
Label *lab; /* Label to output */
|
||||
int type; /* CIF layer number, or -1 if not attached to a layer */
|
||||
int ltype; /* CIF layer number to use for TEXT record */
|
||||
int type; /* CIF layer number to use for BOUNDARY record,
|
||||
* or -1 if not attached to a layer
|
||||
*/
|
||||
FILE *f; /* Stream file */
|
||||
{
|
||||
Point p;
|
||||
int calmanum, calmatype;
|
||||
|
||||
if (type < 0)
|
||||
if (ltype < 0)
|
||||
return;
|
||||
|
||||
calmanum = CIFCurStyle->cs_layers[type]->cl_calmanum;
|
||||
calmanum = CIFCurStyle->cs_layers[ltype]->cl_calmanum;
|
||||
if (!CalmaIsValidLayer(calmanum))
|
||||
return;
|
||||
|
||||
|
|
@ -2843,7 +2848,7 @@ calmaWriteLabelFunc(lab, type, f)
|
|||
calmaOutRH(6, CALMA_LAYER, CALMA_I2, f);
|
||||
calmaOutI2(calmanum, f);
|
||||
|
||||
calmatype = CIFCurStyle->cs_layers[type]->cl_calmatype;
|
||||
calmatype = CIFCurStyle->cs_layers[ltype]->cl_calmatype;
|
||||
calmaOutRH(6, CALMA_TEXTTYPE, CALMA_I2, f);
|
||||
calmaOutI2(calmatype, f);
|
||||
|
||||
|
|
@ -2925,6 +2930,15 @@ calmaWriteLabelFunc(lab, type, f)
|
|||
/* and the label rectangle is not degenerate, then output the label */
|
||||
/* rectangle as a boundary with the label's layer:purpose pair. */
|
||||
|
||||
if (type < 0)
|
||||
return;
|
||||
|
||||
calmanum = CIFCurStyle->cs_layers[type]->cl_calmanum;
|
||||
if (!CalmaIsValidLayer(calmanum))
|
||||
return;
|
||||
|
||||
calmatype = CIFCurStyle->cs_layers[type]->cl_calmatype;
|
||||
|
||||
/* Note that the check for whether the CIF_LABEL_NOPORT flag has */
|
||||
/* been set is done outside of this routine. */
|
||||
|
||||
|
|
|
|||
|
|
@ -1249,14 +1249,15 @@ calmaOutFuncZ(def, f, cliprect)
|
|||
|
||||
if (CalmaDoLabels)
|
||||
{
|
||||
int i, maxport = -1;
|
||||
int i, ltype, maxport = -1;
|
||||
|
||||
for (lab = def->cd_labels; lab; lab = lab->lab_next)
|
||||
{
|
||||
type = CIFCurStyle->cs_labelLayer[lab->lab_type];
|
||||
if ((type >= 0) && (lab->lab_flags & PORT_DIR_MASK) == 0)
|
||||
if ((lab->lab_flags & PORT_DIR_MASK) == 0)
|
||||
{
|
||||
calmaWriteLabelFuncZ(lab, type, f);
|
||||
ltype = CIFCurStyle->cs_labelLayer[lab->lab_type];
|
||||
type = ltype;
|
||||
calmaWriteLabelFuncZ(lab, ltype, type, f);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -1268,11 +1269,12 @@ calmaOutFuncZ(def, f, cliprect)
|
|||
for (i = 0; i <= maxport; i++)
|
||||
for (lab = def->cd_labels; lab; lab = lab->lab_next)
|
||||
{
|
||||
ltype = CIFCurStyle->cs_portText[lab->lab_type];
|
||||
type = CIFCurStyle->cs_portLayer[lab->lab_type];
|
||||
if ((type >= 0) && ((lab->lab_flags & PORT_DIR_MASK) != 0) &&
|
||||
(lab->lab_port == i))
|
||||
{
|
||||
calmaWriteLabelFuncZ(lab, type, f);
|
||||
calmaWriteLabelFuncZ(lab, ltype, type, f);
|
||||
/* break; */ /* Do not limit to unique labels! */
|
||||
}
|
||||
}
|
||||
|
|
@ -2245,18 +2247,21 @@ calmaWritePaintFuncZ(tile, cos)
|
|||
*/
|
||||
|
||||
void
|
||||
calmaWriteLabelFuncZ(lab, type, f)
|
||||
calmaWriteLabelFuncZ(lab, ltype, type, f)
|
||||
Label *lab; /* Label to output */
|
||||
int type; /* CIF layer number, or -1 if not attached to a layer */
|
||||
int ltype; /* CIF layer number to use for TEXT record */
|
||||
int type; /* CIF layer number to use for BOUNDARY record,
|
||||
* or -1 if not attached to a layer
|
||||
*/
|
||||
gzFile f; /* Stream file */
|
||||
{
|
||||
Point p;
|
||||
int calmanum, calmatype;
|
||||
|
||||
if (type < 0)
|
||||
if (ltype < 0)
|
||||
return;
|
||||
|
||||
calmanum = CIFCurStyle->cs_layers[type]->cl_calmanum;
|
||||
calmanum = CIFCurStyle->cs_layers[ltype]->cl_calmanum;
|
||||
if (!CalmaIsValidLayer(calmanum))
|
||||
return;
|
||||
|
||||
|
|
@ -2265,7 +2270,7 @@ calmaWriteLabelFuncZ(lab, type, f)
|
|||
calmaOutRHZ(6, CALMA_LAYER, CALMA_I2, f);
|
||||
calmaOutI2Z(calmanum, f);
|
||||
|
||||
calmatype = CIFCurStyle->cs_layers[type]->cl_calmatype;
|
||||
calmatype = CIFCurStyle->cs_layers[ltype]->cl_calmatype;
|
||||
calmaOutRHZ(6, CALMA_TEXTTYPE, CALMA_I2, f);
|
||||
calmaOutI2Z(calmatype, f);
|
||||
|
||||
|
|
@ -2347,6 +2352,15 @@ calmaWriteLabelFuncZ(lab, type, f)
|
|||
/* and the label rectangle is not degenerate, then output the label */
|
||||
/* rectangle as a boundary with the label's layer:purpose pair. */
|
||||
|
||||
if (type < 0)
|
||||
return;
|
||||
|
||||
calmanum = CIFCurStyle->cs_layers[type]->cl_calmanum;
|
||||
if (!CalmaIsValidLayer(calmanum))
|
||||
return;
|
||||
|
||||
calmatype = CIFCurStyle->cs_layers[type]->cl_calmatype;
|
||||
|
||||
/* Note that the check for whether the CIF_LABEL_NOPORT flag has */
|
||||
/* been set is done outside of this routine. */
|
||||
|
||||
|
|
|
|||
|
|
@ -294,9 +294,12 @@ typedef struct cifstyle
|
|||
* layer.
|
||||
*/
|
||||
int cs_portLayer[TT_MAXTYPES];
|
||||
/* Similar to cs_labelLayer, to distinguish
|
||||
* between output types used for "normal"
|
||||
* text and those used specifically for ports.
|
||||
/* Similar to cs_labelLayer, to use as
|
||||
* a type for geometry attached to port labels.
|
||||
*/
|
||||
int cs_portText[TT_MAXTYPES];
|
||||
/* Similar to cs_labelLayer, to use as
|
||||
* a text type for port labels
|
||||
*/
|
||||
CIFLayer *cs_layers[MAXCIFLAYERS];
|
||||
/* Describes how to generate each layer.*/
|
||||
|
|
|
|||
|
|
@ -188,6 +188,7 @@ cifTechStyleInit()
|
|||
{
|
||||
CIFCurStyle->cs_labelLayer[i] = -1;
|
||||
CIFCurStyle->cs_portLayer[i] = -1;
|
||||
CIFCurStyle->cs_portText[i] = -1;
|
||||
}
|
||||
for (i = 0; i < MAXCIFLAYERS; i++)
|
||||
CIFCurStyle->cs_layers[i] = NULL;
|
||||
|
|
@ -871,7 +872,7 @@ CIFTechLine(sectionName, argc, argv)
|
|||
|
||||
if (strcmp(argv[0], "labels") == 0)
|
||||
{
|
||||
bool portOnly = FALSE, noPort = FALSE;
|
||||
bool portOnly = FALSE, noPort = FALSE, textOnly = FALSE;
|
||||
|
||||
if (cifCurLayer == NULL)
|
||||
{
|
||||
|
|
@ -886,6 +887,8 @@ CIFTechLine(sectionName, argc, argv)
|
|||
portOnly = TRUE;
|
||||
else if (!strncmp(argv[2], "noport", 6))
|
||||
noPort = TRUE;
|
||||
else if (!strncmp(argv[2], "text", 6))
|
||||
textOnly = TRUE;
|
||||
else
|
||||
{
|
||||
TechError("Unknown option %s for labels statement.\n", argv[2]);
|
||||
|
|
@ -898,10 +901,28 @@ CIFTechLine(sectionName, argc, argv)
|
|||
{
|
||||
if (TTMaskHasType(&mask, i))
|
||||
{
|
||||
if (portOnly != TRUE)
|
||||
CIFCurStyle->cs_labelLayer[i] = CIFCurStyle->cs_nLayers-1;
|
||||
if (noPort != TRUE)
|
||||
if (portOnly == TRUE)
|
||||
{
|
||||
/* With "port", use layer for port geometry.
|
||||
* If the port text type has not been set, set it to
|
||||
* this layer.
|
||||
*/
|
||||
CIFCurStyle->cs_portLayer[i] = CIFCurStyle->cs_nLayers-1;
|
||||
if (CIFCurStyle->cs_portText[i] == -1)
|
||||
CIFCurStyle->cs_portText[i] = CIFCurStyle->cs_nLayers-1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* For "noport" or no argument, the label text and data
|
||||
* are set to this layer. If no argument, then set the
|
||||
* port text type to this type. If a later "port" statement
|
||||
* applies to the same layer, then the data type will be
|
||||
* separate from the text type.
|
||||
*/
|
||||
CIFCurStyle->cs_labelLayer[i] = CIFCurStyle->cs_nLayers-1;
|
||||
if (noPort == FALSE)
|
||||
CIFCurStyle->cs_portText[i] = CIFCurStyle->cs_nLayers-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
cifGotLabels = TRUE;
|
||||
|
|
|
|||
|
|
@ -65,17 +65,17 @@ Write out all modified cells to disk
|
|||
</CENTER>
|
||||
</BLOCKQUOTE>
|
||||
|
||||
With the option <B>write force</B>, the command writes all cells
|
||||
With the option <B>writeall force</B>, the command writes all cells
|
||||
in the hierarchy with no prompting. If one or more cell names
|
||||
follows <B>write force</B>, the cells listed will be written
|
||||
(action "write") and all other cells will be ignored (action
|
||||
"skip"). <P>
|
||||
|
||||
With the option <B>write modified</B>, the command writes all
|
||||
With the option <B>writeall modified</B>, the command writes all
|
||||
cells in the hierarchy which have been modified, ignoring those
|
||||
cells marked as needing only a bounding box or timestamp update. <P>
|
||||
|
||||
With the option <B>write noupdate</B>, the command writes all
|
||||
With the option <B>writeall noupdate</B>, the command writes all
|
||||
cells in the hierarchy like it would for <B>write force</B>, but
|
||||
it does not update timestamps. <P>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue