Corrected the "lef write" routine to more correctly handle port

statements, with all "hard" connections being enumerated in the
same PORT entry, and "soft" connections (same label on unconnected
areas;  e.g., through substrate or resistor device) being
enumerated as separate PORT entries, per the LEF spec.  Also
corrected behavior with respect to the "lef write -toplayer"
option, which was treating each port label independently, and so
generating entries for lower layers of a port if there were ports
on those layers, in contravention to the "-toplayer" option.
Also:  Added the PINS section to the "def write" output;  this had
been left as a "to be completed" item but was never done in spite
of being easy to add.
This commit is contained in:
Tim Edwards 2021-11-12 11:34:16 -05:00
parent 3afc462cac
commit 898783467c
3 changed files with 163 additions and 3 deletions

View File

@ -1 +1 @@
8.3.226 8.3.227

View File

@ -1761,6 +1761,135 @@ defCountCompFunc(cellUse, total)
return 0; /* Keep the search going */ return 0; /* Keep the search going */
} }
/*
*------------------------------------------------------------
*
* defCountPins --
*
* First-pass function to count the number of pins
* to be written to the DEF output file.
*
* Results:
* The total number of pins to be written.
*
* Side Effects:
* None.
*
*------------------------------------------------------------
*/
int
defCountPins(rootDef)
CellDef *rootDef;
{
int total;
Label *lab;
TxPrintf("Diagnostic: Finding all pins of cell %s\n", rootDef->cd_name);
total = 0;
for (lab = rootDef->cd_labels; lab; lab = lab->lab_next)
if (lab->lab_flags & PORT_DIR_MASK)
total++;
return total;
}
/*
*------------------------------------------------------------
*
* defWritePins --
*
* Output the PINS section of the DEF file. This
* is a listing of all ports, their placement, and
* name.
*
* Results:
* None.
*
* Side Effects:
* Output to the DEF file.
*
*------------------------------------------------------------
*/
void
defWritePins(f, rootDef, oscale)
FILE *f; /* File to write to */
CellDef *rootDef; /* Cell definition to use */
float oscale; /* Output scale factor */
{
Label *lab;
int lwidth, lheight;
int dcenterx, dcentery;
for (lab = rootDef->cd_labels; lab; lab = lab->lab_next)
{
if (lab->lab_flags & PORT_DIR_MASK)
{
fprintf(f, " - %s + NET %s\n", lab->lab_text, lab->lab_text);
if (lab->lab_flags & PORT_CLASS_MASK)
{
fprintf(f, " + DIRECTION ");
switch (lab->lab_flags & PORT_CLASS_MASK)
{
case PORT_CLASS_INPUT:
fprintf(f, "INPUT");
break;
case PORT_CLASS_OUTPUT:
fprintf(f, "OUTPUT");
break;
case PORT_CLASS_TRISTATE:
case PORT_CLASS_BIDIRECTIONAL:
fprintf(f, "INOUT");
break;
case PORT_CLASS_FEEDTHROUGH:
fprintf(f, "FEEDTHRU");
break;
}
fprintf(f, "\n");
}
if (lab->lab_flags & PORT_USE_MASK)
{
fprintf(f, " + USE ");
switch (lab->lab_flags & PORT_USE_MASK)
{
case PORT_USE_SIGNAL:
fprintf(f, "SIGNAL");
break;
case PORT_USE_ANALOG:
fprintf(f, "ANALOG");
break;
case PORT_USE_POWER:
fprintf(f, "POWER");
break;
case PORT_USE_GROUND:
fprintf(f, "GROUND");
break;
case PORT_USE_CLOCK:
fprintf(f, "CLOCK");
break;
}
fprintf(f, "\n");
}
lwidth = lab->lab_rect.r_xtop - lab->lab_rect.r_xbot;
lheight = lab->lab_rect.r_ytop - lab->lab_rect.r_ybot;
dcenterx = lab->lab_rect.r_xtop + lab->lab_rect.r_xbot;
dcentery = lab->lab_rect.r_ytop + lab->lab_rect.r_ybot;
fprintf(f, " + PORT\n");
fprintf(f, " + LAYER %s ( %.10g %.10g ) ( %.10g %.10g )",
DBTypeLongNameTbl[lab->lab_type],
oscale * (float)(-lwidth) / 2.0, oscale * (float)(-lheight) / 2.0,
oscale * (float)lwidth / 2.0, oscale * (float)lheight / 2.0);
fprintf(f, " + PLACED ( %.10g %.10g ) N ;\n",
oscale * (float)dcenterx / 2.0, oscale * (float)dcentery / 2.0);
}
}
}
/* /*
*------------------------------------------------------------ *------------------------------------------------------------
* *
@ -1996,7 +2125,11 @@ DefWriteCell(def, outName, allSpecial, units)
fprintf(f, "END COMPONENTS\n\n"); fprintf(f, "END COMPONENTS\n\n");
/* Pins---assume no pins (for now) */ /* Pins---assume no pins (for now) */
fprintf(f, "PINS 0 ;\nEND PINS\n\n"); total = defCountPins(def);
fprintf(f, "PINS %d ;\n", total);
if (total > 0)
defWritePins(f, def, scale);
fprintf(f, "END PINS\n\n");
/* Count the number of nets and "special" nets */ /* Count the number of nets and "special" nets */
nets = defCountNets(def, allSpecial); nets = defCountNets(def, allSpecial);

View File

@ -1602,10 +1602,37 @@ lefWriteMacro(def, f, scale, setback, pinonly, toplayer, domaster)
lefWriteGeometry, (ClientData) &lc); lefWriteGeometry, (ClientData) &lc);
lc.lefMode = LEF_MODE_PORT; lc.lefMode = LEF_MODE_PORT;
} }
/* Check if any other ports are already contained in this selection. */
/* If so, mark them as visited. Use lefFindTopmost(), which is just a */
/* routine that stops the search by returning 1 when something is found */
for (tlab = lab->lab_next; tlab != (Label *)NULL; tlab = tlab->lab_next)
if (tlab->lab_flags & PORT_DIR_MASK)
if (!(tlab->lab_flags & PORT_VISITED))
if ((tlab->lab_flags & PORT_NUM_MASK) == idx)
{
TileTypeBitMask lmask;
TTMaskSetOnlyType(&lmask, tlab->lab_type);
pNum = DBPlane(tlab->lab_type);
if (DBSrPaintArea((Tile *)NULL, lc.lefYank->cd_planes[pNum],
&tlab->lab_rect, &lmask,
lefFindTopmost, (ClientData)NULL))
tlab->lab_flags |= PORT_VISITED;
/* For the "toplayer" option, ports on lower layers will not be */
/* in the yank buffer but will still be in the selection. */
else if (toplayer)
if (DBSrPaintArea((Tile *)NULL, SelectDef->cd_planes[pNum],
&tlab->lab_rect, &lmask,
lefFindTopmost, (ClientData)NULL))
tlab->lab_flags |= PORT_VISITED;
}
DBCellClearDef(lc.lefYank); DBCellClearDef(lc.lefYank);
lab->lab_flags |= PORT_VISITED; lab->lab_flags |= PORT_VISITED;
/* Check if any other ports belong to this pin */ /* Check if any other unvisited ports belong to this pin */
for (; lab != NULL; lab = lab->lab_next) for (; lab != NULL; lab = lab->lab_next)
if (lab->lab_flags & PORT_DIR_MASK) if (lab->lab_flags & PORT_DIR_MASK)