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 */
|
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);
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue