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:
Tim Edwards 2022-12-21 17:49:43 -05:00
parent be40825e9a
commit 0bbb558b94
7 changed files with 135 additions and 37 deletions

View File

@ -1 +1 @@
8.3.356 8.3.357

View File

@ -323,7 +323,34 @@ calmaElementBoundary()
if (lab == NULL) if (lab == NULL)
{ {
/* There was no label in the area. Create a placeholder label */ /* 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; TileType type;
Rect r; Rect r;
double dval; double dval;
int size, micron, angle, font, pos; int size, micron, angle, font, pos, portnum, idx;
/* Skip CALMA_ELFLAGS, CALMA_PLEX */ /* Skip CALMA_ELFLAGS, CALMA_PLEX */
calmaSkipSet(calmaElementIgnore); calmaSkipSet(calmaElementIgnore);
@ -731,6 +758,7 @@ calmaElementText()
font = -1; font = -1;
angle = 0; angle = 0;
portnum = 0;
/* Use the minimum width of the layer on which the text is placed /* Use the minimum width of the layer on which the text is placed
* as the default text size, or 1um, whichever is smaller. Account * as the default text size, or 1um, whichever is smaller. Account
@ -992,6 +1020,26 @@ calmaElementText()
sl->lab_next = lab->lab_next; sl->lab_next = lab->lab_next;
if (cifReadCellDef->cd_lastLabel == lab) if (cifReadCellDef->cd_lastLabel == lab)
cifReadCellDef->cd_lastLabel = sl; 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); freeMagic((char *)lab);
break; break;
} }
@ -1000,16 +1048,14 @@ calmaElementText()
} }
if (font < 0) if (font < 0)
lab = DBPutLabel(cifReadCellDef, &r, pos, textbody, type, flags, 0); lab = DBPutLabel(cifReadCellDef, &r, pos, textbody, type, flags, portnum);
else else
lab = DBPutFontLabel(cifReadCellDef, &r, font, size, angle, lab = DBPutFontLabel(cifReadCellDef, &r, font, size, angle,
&GeoOrigin, pos, textbody, type, flags, 0); &GeoOrigin, pos, textbody, type, flags, portnum);
if ((lab != NULL) && (cifnum >= 0) && if ((lab != NULL) && (cifnum >= 0) &&
(cifCurReadStyle->crs_labelSticky[cifnum] == LABEL_TYPE_PORT)) (cifCurReadStyle->crs_labelSticky[cifnum] == LABEL_TYPE_PORT))
{ {
int idx;
/* No port information can be encoded in the GDS file, so */ /* No port information can be encoded in the GDS file, so */
/* assume defaults, and assume that the port order is the */ /* assume defaults, and assume that the port order is the */
/* order in which labels arrive in the GDS stream. If */ /* order in which labels arrive in the GDS stream. If */

View File

@ -1341,14 +1341,15 @@ calmaOutFunc(def, f, cliprect)
if (CalmaDoLabels) if (CalmaDoLabels)
{ {
int i, maxport = -1; int i, ltype, maxport = -1;
for (lab = def->cd_labels; lab; lab = lab->lab_next) for (lab = def->cd_labels; lab; lab = lab->lab_next)
{ {
type = CIFCurStyle->cs_labelLayer[lab->lab_type]; if ((lab->lab_flags & PORT_DIR_MASK) == 0)
if ((type >= 0) && (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 else
{ {
@ -1360,11 +1361,12 @@ calmaOutFunc(def, f, cliprect)
for (i = 0; i <= maxport; i++) for (i = 0; i <= maxport; i++)
for (lab = def->cd_labels; lab; lab = lab->lab_next) for (lab = def->cd_labels; lab; lab = lab->lab_next)
{ {
ltype = CIFCurStyle->cs_portText[lab->lab_type];
type = CIFCurStyle->cs_portLayer[lab->lab_type]; type = CIFCurStyle->cs_portLayer[lab->lab_type];
if ((type >= 0) && ((lab->lab_flags & PORT_DIR_MASK) != 0) && if ((type >= 0) && ((lab->lab_flags & PORT_DIR_MASK) != 0) &&
(lab->lab_port == i)) (lab->lab_port == i))
{ {
calmaWriteLabelFunc(lab, type, f); calmaWriteLabelFunc(lab, ltype, type, f);
/* break; */ /* Do not limit to unique labels! */ /* break; */ /* Do not limit to unique labels! */
} }
} }
@ -2823,18 +2825,21 @@ calmaWritePaintFunc(tile, cos)
*/ */
void void
calmaWriteLabelFunc(lab, type, f) calmaWriteLabelFunc(lab, ltype, type, f)
Label *lab; /* Label to output */ 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 */ FILE *f; /* Stream file */
{ {
Point p; Point p;
int calmanum, calmatype; int calmanum, calmatype;
if (type < 0) if (ltype < 0)
return; return;
calmanum = CIFCurStyle->cs_layers[type]->cl_calmanum; calmanum = CIFCurStyle->cs_layers[ltype]->cl_calmanum;
if (!CalmaIsValidLayer(calmanum)) if (!CalmaIsValidLayer(calmanum))
return; return;
@ -2843,7 +2848,7 @@ calmaWriteLabelFunc(lab, type, f)
calmaOutRH(6, CALMA_LAYER, CALMA_I2, f); calmaOutRH(6, CALMA_LAYER, CALMA_I2, f);
calmaOutI2(calmanum, 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); calmaOutRH(6, CALMA_TEXTTYPE, CALMA_I2, f);
calmaOutI2(calmatype, f); calmaOutI2(calmatype, f);
@ -2925,6 +2930,15 @@ calmaWriteLabelFunc(lab, type, f)
/* and the label rectangle is not degenerate, then output the label */ /* and the label rectangle is not degenerate, then output the label */
/* rectangle as a boundary with the label's layer:purpose pair. */ /* 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 */ /* Note that the check for whether the CIF_LABEL_NOPORT flag has */
/* been set is done outside of this routine. */ /* been set is done outside of this routine. */

View File

@ -1249,14 +1249,15 @@ calmaOutFuncZ(def, f, cliprect)
if (CalmaDoLabels) if (CalmaDoLabels)
{ {
int i, maxport = -1; int i, ltype, maxport = -1;
for (lab = def->cd_labels; lab; lab = lab->lab_next) for (lab = def->cd_labels; lab; lab = lab->lab_next)
{ {
type = CIFCurStyle->cs_labelLayer[lab->lab_type]; if ((lab->lab_flags & PORT_DIR_MASK) == 0)
if ((type >= 0) && (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 else
{ {
@ -1268,11 +1269,12 @@ calmaOutFuncZ(def, f, cliprect)
for (i = 0; i <= maxport; i++) for (i = 0; i <= maxport; i++)
for (lab = def->cd_labels; lab; lab = lab->lab_next) for (lab = def->cd_labels; lab; lab = lab->lab_next)
{ {
ltype = CIFCurStyle->cs_portText[lab->lab_type];
type = CIFCurStyle->cs_portLayer[lab->lab_type]; type = CIFCurStyle->cs_portLayer[lab->lab_type];
if ((type >= 0) && ((lab->lab_flags & PORT_DIR_MASK) != 0) && if ((type >= 0) && ((lab->lab_flags & PORT_DIR_MASK) != 0) &&
(lab->lab_port == i)) (lab->lab_port == i))
{ {
calmaWriteLabelFuncZ(lab, type, f); calmaWriteLabelFuncZ(lab, ltype, type, f);
/* break; */ /* Do not limit to unique labels! */ /* break; */ /* Do not limit to unique labels! */
} }
} }
@ -2245,18 +2247,21 @@ calmaWritePaintFuncZ(tile, cos)
*/ */
void void
calmaWriteLabelFuncZ(lab, type, f) calmaWriteLabelFuncZ(lab, ltype, type, f)
Label *lab; /* Label to output */ 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 */ gzFile f; /* Stream file */
{ {
Point p; Point p;
int calmanum, calmatype; int calmanum, calmatype;
if (type < 0) if (ltype < 0)
return; return;
calmanum = CIFCurStyle->cs_layers[type]->cl_calmanum; calmanum = CIFCurStyle->cs_layers[ltype]->cl_calmanum;
if (!CalmaIsValidLayer(calmanum)) if (!CalmaIsValidLayer(calmanum))
return; return;
@ -2265,7 +2270,7 @@ calmaWriteLabelFuncZ(lab, type, f)
calmaOutRHZ(6, CALMA_LAYER, CALMA_I2, f); calmaOutRHZ(6, CALMA_LAYER, CALMA_I2, f);
calmaOutI2Z(calmanum, 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); calmaOutRHZ(6, CALMA_TEXTTYPE, CALMA_I2, f);
calmaOutI2Z(calmatype, f); calmaOutI2Z(calmatype, f);
@ -2347,6 +2352,15 @@ calmaWriteLabelFuncZ(lab, type, f)
/* and the label rectangle is not degenerate, then output the label */ /* and the label rectangle is not degenerate, then output the label */
/* rectangle as a boundary with the label's layer:purpose pair. */ /* 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 */ /* Note that the check for whether the CIF_LABEL_NOPORT flag has */
/* been set is done outside of this routine. */ /* been set is done outside of this routine. */

View File

@ -294,9 +294,12 @@ typedef struct cifstyle
* layer. * layer.
*/ */
int cs_portLayer[TT_MAXTYPES]; int cs_portLayer[TT_MAXTYPES];
/* Similar to cs_labelLayer, to distinguish /* Similar to cs_labelLayer, to use as
* between output types used for "normal" * a type for geometry attached to port labels.
* text and those used specifically for ports. */
int cs_portText[TT_MAXTYPES];
/* Similar to cs_labelLayer, to use as
* a text type for port labels
*/ */
CIFLayer *cs_layers[MAXCIFLAYERS]; CIFLayer *cs_layers[MAXCIFLAYERS];
/* Describes how to generate each layer.*/ /* Describes how to generate each layer.*/

View File

@ -188,6 +188,7 @@ cifTechStyleInit()
{ {
CIFCurStyle->cs_labelLayer[i] = -1; CIFCurStyle->cs_labelLayer[i] = -1;
CIFCurStyle->cs_portLayer[i] = -1; CIFCurStyle->cs_portLayer[i] = -1;
CIFCurStyle->cs_portText[i] = -1;
} }
for (i = 0; i < MAXCIFLAYERS; i++) for (i = 0; i < MAXCIFLAYERS; i++)
CIFCurStyle->cs_layers[i] = NULL; CIFCurStyle->cs_layers[i] = NULL;
@ -871,7 +872,7 @@ CIFTechLine(sectionName, argc, argv)
if (strcmp(argv[0], "labels") == 0) if (strcmp(argv[0], "labels") == 0)
{ {
bool portOnly = FALSE, noPort = FALSE; bool portOnly = FALSE, noPort = FALSE, textOnly = FALSE;
if (cifCurLayer == NULL) if (cifCurLayer == NULL)
{ {
@ -886,6 +887,8 @@ CIFTechLine(sectionName, argc, argv)
portOnly = TRUE; portOnly = TRUE;
else if (!strncmp(argv[2], "noport", 6)) else if (!strncmp(argv[2], "noport", 6))
noPort = TRUE; noPort = TRUE;
else if (!strncmp(argv[2], "text", 6))
textOnly = TRUE;
else else
{ {
TechError("Unknown option %s for labels statement.\n", argv[2]); TechError("Unknown option %s for labels statement.\n", argv[2]);
@ -898,10 +901,28 @@ CIFTechLine(sectionName, argc, argv)
{ {
if (TTMaskHasType(&mask, i)) if (TTMaskHasType(&mask, i))
{ {
if (portOnly != TRUE) if (portOnly == TRUE)
CIFCurStyle->cs_labelLayer[i] = CIFCurStyle->cs_nLayers-1; {
if (noPort != 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; 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; cifGotLabels = TRUE;

View File

@ -65,17 +65,17 @@ Write out all modified cells to disk
</CENTER> </CENTER>
</BLOCKQUOTE> </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 in the hierarchy with no prompting. If one or more cell names
follows <B>write force</B>, the cells listed will be written follows <B>write force</B>, the cells listed will be written
(action "write") and all other cells will be ignored (action (action "write") and all other cells will be ignored (action
"skip"). <P> "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 in the hierarchy which have been modified, ignoring those
cells marked as needing only a bounding box or timestamp update. <P> 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 cells in the hierarchy like it would for <B>write force</B>, but
it does not update timestamps. <P> it does not update timestamps. <P>