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)
{
/* 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 */

View File

@ -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. */

View File

@ -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. */

View File

@ -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.*/

View File

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

View File

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