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:
parent
3afc462cac
commit
898783467c
135
lef/defWrite.c
135
lef/defWrite.c
|
|
@ -1761,6 +1761,135 @@ defCountCompFunc(cellUse, total)
|
|||
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");
|
||||
|
||||
/* 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 */
|
||||
nets = defCountNets(def, allSpecial);
|
||||
|
|
|
|||
|
|
@ -1602,10 +1602,37 @@ lefWriteMacro(def, f, scale, setback, pinonly, toplayer, domaster)
|
|||
lefWriteGeometry, (ClientData) &lc);
|
||||
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);
|
||||
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)
|
||||
if (lab->lab_flags & PORT_DIR_MASK)
|
||||
|
|
|
|||
Loading…
Reference in New Issue