Added handling of coordinates in a FOREIGN statement in a LEF
macro. Based on observation of cells in PDKs where ORIGIN and/or FOREIGN are non-zero, added code that forces a correction of LEF macro coordinates to match the GDS coordinates, with an equivalent negative shift of the LEF macro ORIGIN to compensate. Normally, both ORIGIN and FOREIGN will be zero and the added code will do nothing. Note that this code does not handle the additional optional orientation. A LEF macro with a different coordinate system than its GDS is already weird; a LEF macro with a different rotation than its GDS is hopefully something that nobody ever does in practice. If needed, I'll cross that bridge when I come to it.
This commit is contained in:
parent
6b9efefc02
commit
6e83cbe2d3
|
|
@ -152,7 +152,7 @@ extern CellDef *lefFindCell(const char *name);
|
||||||
extern const char *LefNextToken(FILE *f, bool ignore_eol);
|
extern const char *LefNextToken(FILE *f, bool ignore_eol);
|
||||||
extern char *LefLower(char *token);
|
extern char *LefLower(char *token);
|
||||||
extern TileType LefHelper_DBTechNameType_LefLower(const char *name);
|
extern TileType LefHelper_DBTechNameType_LefLower(const char *name);
|
||||||
extern LinkedRect *LefReadGeometry(CellDef *lefMacro, FILE *f, float oscale, bool do_list, bool is_imported);
|
extern LinkedRect *LefReadGeometry(CellDef *lefMacro, FILE *f, float oscale, Point *, bool do_list, bool is_imported);
|
||||||
extern void LefEstimate(int processed, int total, const char *item_name);
|
extern void LefEstimate(int processed, int total, const char *item_name);
|
||||||
extern lefLayer *LefRedefined(lefLayer *lefl, const char *redefname);
|
extern lefLayer *LefRedefined(lefLayer *lefl, const char *redefname);
|
||||||
extern void LefAddViaGeometry(FILE *f, lefLayer *lefl, TileType curlayer, float oscale);
|
extern void LefAddViaGeometry(FILE *f, lefLayer *lefl, TileType curlayer, float oscale);
|
||||||
|
|
|
||||||
|
|
@ -852,7 +852,9 @@ LefReadLayer(
|
||||||
* return the two coordinates in LEF units (floating-point).
|
* return the two coordinates in LEF units (floating-point).
|
||||||
*
|
*
|
||||||
* Results:
|
* Results:
|
||||||
* Return 0 on success, 1 on error.
|
* Return 0 on success, 1 on error. Return -1 if no
|
||||||
|
* coordinates are found in the input (used where
|
||||||
|
* coordinates may be optional).
|
||||||
*
|
*
|
||||||
* Side Effects:
|
* Side Effects:
|
||||||
* Reads input from file f;
|
* Reads input from file f;
|
||||||
|
|
@ -878,6 +880,7 @@ LefReadLefPoint(
|
||||||
bool needMatch = FALSE;
|
bool needMatch = FALSE;
|
||||||
|
|
||||||
token = LefNextToken(f, TRUE);
|
token = LefNextToken(f, TRUE);
|
||||||
|
if (!token) return -1;
|
||||||
if (*token == '(')
|
if (*token == '(')
|
||||||
{
|
{
|
||||||
token = LefNextToken(f, TRUE);
|
token = LefNextToken(f, TRUE);
|
||||||
|
|
@ -1019,6 +1022,7 @@ LefReadPolygon(
|
||||||
FILE *f,
|
FILE *f,
|
||||||
TileType curlayer,
|
TileType curlayer,
|
||||||
float oscale,
|
float oscale,
|
||||||
|
Point *gdsOffset,
|
||||||
int *ppoints)
|
int *ppoints)
|
||||||
{
|
{
|
||||||
LinkedRect *lr = NULL, *newRect;
|
LinkedRect *lr = NULL, *newRect;
|
||||||
|
|
@ -1056,8 +1060,8 @@ LefReadPolygon(
|
||||||
/* as we read it in. */
|
/* as we read it in. */
|
||||||
|
|
||||||
newRect = (LinkedRect *)mallocMagic(sizeof(LinkedRect));
|
newRect = (LinkedRect *)mallocMagic(sizeof(LinkedRect));
|
||||||
newRect->r_r.r_xbot = (int)roundf(px / oscale);
|
newRect->r_r.r_xbot = (int)roundf(px / oscale) + gdsOffset->p_x;
|
||||||
newRect->r_r.r_ybot = (int)roundf(py / oscale);
|
newRect->r_r.r_ybot = (int)roundf(py / oscale) + gdsOffset->p_y;
|
||||||
newRect->r_next = lr;
|
newRect->r_next = lr;
|
||||||
lr = newRect;
|
lr = newRect;
|
||||||
lpoints++;
|
lpoints++;
|
||||||
|
|
@ -1222,6 +1226,7 @@ LefReadGeometry(
|
||||||
CellDef *lefMacro,
|
CellDef *lefMacro,
|
||||||
FILE *f,
|
FILE *f,
|
||||||
float oscale,
|
float oscale,
|
||||||
|
Point *gdsOffset,
|
||||||
bool do_list,
|
bool do_list,
|
||||||
bool is_imported)
|
bool is_imported)
|
||||||
{
|
{
|
||||||
|
|
@ -1276,6 +1281,11 @@ LefReadGeometry(
|
||||||
paintrect = (curlayer < 0) ? NULL : LefReadRect(f, curlayer, oscale);
|
paintrect = (curlayer < 0) ? NULL : LefReadRect(f, curlayer, oscale);
|
||||||
if (paintrect)
|
if (paintrect)
|
||||||
{
|
{
|
||||||
|
paintrect->r_xbot += gdsOffset->p_x;
|
||||||
|
paintrect->r_ybot += gdsOffset->p_y;
|
||||||
|
paintrect->r_xtop += gdsOffset->p_x;
|
||||||
|
paintrect->r_ytop += gdsOffset->p_y;
|
||||||
|
|
||||||
if (is_imported)
|
if (is_imported)
|
||||||
{
|
{
|
||||||
int pNum = DBPlane(curlayer); /* FIXME unused return value from call to function with no side-effects */
|
int pNum = DBPlane(curlayer); /* FIXME unused return value from call to function with no side-effects */
|
||||||
|
|
@ -1346,7 +1356,7 @@ LefReadGeometry(
|
||||||
LefEndStatement(f);
|
LefEndStatement(f);
|
||||||
break;
|
break;
|
||||||
case LEF_POLYGON:
|
case LEF_POLYGON:
|
||||||
pointList = LefReadPolygon(f, curlayer, oscale, &points);
|
pointList = LefReadPolygon(f, curlayer, oscale, gdsOffset, &points);
|
||||||
if (pointList)
|
if (pointList)
|
||||||
{
|
{
|
||||||
if (lefMacro)
|
if (lefMacro)
|
||||||
|
|
@ -1428,13 +1438,14 @@ LefReadPort(
|
||||||
int pinUse,
|
int pinUse,
|
||||||
int pinShape,
|
int pinShape,
|
||||||
float oscale,
|
float oscale,
|
||||||
|
Point *gdsOffset,
|
||||||
bool is_imported,
|
bool is_imported,
|
||||||
Label *lanno)
|
Label *lanno)
|
||||||
{
|
{
|
||||||
Label *newlab;
|
Label *newlab;
|
||||||
LinkedRect *rectList;
|
LinkedRect *rectList;
|
||||||
|
|
||||||
rectList = LefReadGeometry(lefMacro, f, oscale, TRUE, is_imported);
|
rectList = LefReadGeometry(lefMacro, f, oscale, gdsOffset, TRUE, is_imported);
|
||||||
|
|
||||||
while (rectList != NULL)
|
while (rectList != NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -1549,6 +1560,7 @@ LefReadPin(
|
||||||
char *pinname,
|
char *pinname,
|
||||||
int pinNum,
|
int pinNum,
|
||||||
float oscale,
|
float oscale,
|
||||||
|
Point *gdsOffset,
|
||||||
bool is_imported)
|
bool is_imported)
|
||||||
{
|
{
|
||||||
const char *token;
|
const char *token;
|
||||||
|
|
@ -1815,7 +1827,7 @@ LefReadPin(
|
||||||
DBEraseLabelsByContent(lefMacro, NULL, -1, testpin);
|
DBEraseLabelsByContent(lefMacro, NULL, -1, testpin);
|
||||||
|
|
||||||
LefReadPort(lefMacro, f, testpin, pinNum, pinDir, pinUse,
|
LefReadPort(lefMacro, f, testpin, pinNum, pinDir, pinUse,
|
||||||
pinShape, oscale, TRUE, lab);
|
pinShape, oscale, gdsOffset, TRUE, lab);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LefSkipSection(f, NULL);
|
LefSkipSection(f, NULL);
|
||||||
|
|
@ -1823,7 +1835,7 @@ LefReadPin(
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
LefReadPort(lefMacro, f, testpin, pinNum, pinDir, pinUse,
|
LefReadPort(lefMacro, f, testpin, pinNum, pinDir, pinUse,
|
||||||
pinShape, oscale, FALSE, NULL);
|
pinShape, oscale, gdsOffset, FALSE, NULL);
|
||||||
break;
|
break;
|
||||||
case LEF_CAPACITANCE:
|
case LEF_CAPACITANCE:
|
||||||
case LEF_ANTENNADIFF:
|
case LEF_ANTENNADIFF:
|
||||||
|
|
@ -2124,10 +2136,11 @@ LefReadMacro(
|
||||||
|
|
||||||
const char *token;
|
const char *token;
|
||||||
char tsave[128], *propval;
|
char tsave[128], *propval;
|
||||||
int keyword, pinNum, propsize;
|
int keyword, pinNum, propsize, result;
|
||||||
float x, y;
|
float x, y;
|
||||||
bool has_size, is_imported = FALSE, propfound;
|
bool has_size, is_imported = FALSE, propfound;
|
||||||
Rect lefBBox;
|
Rect lefBBox;
|
||||||
|
Point gdsOffset; /* Difference between GDS and LEF coordinates */
|
||||||
|
|
||||||
static const char * const macro_keys[] = {
|
static const char * const macro_keys[] = {
|
||||||
"CLASS",
|
"CLASS",
|
||||||
|
|
@ -2203,6 +2216,8 @@ LefReadMacro(
|
||||||
has_size = FALSE;
|
has_size = FALSE;
|
||||||
lefBBox.r_xbot = 0;
|
lefBBox.r_xbot = 0;
|
||||||
lefBBox.r_ybot = 0;
|
lefBBox.r_ybot = 0;
|
||||||
|
gdsOffset.p_x = 0;
|
||||||
|
gdsOffset.p_y = 0;
|
||||||
|
|
||||||
while ((token = LefNextToken(f, TRUE)) != NULL)
|
while ((token = LefNextToken(f, TRUE)) != NULL)
|
||||||
{
|
{
|
||||||
|
|
@ -2252,6 +2267,8 @@ size_error:
|
||||||
lefBBox.r_xtop += lefBBox.r_xbot;
|
lefBBox.r_xtop += lefBBox.r_xbot;
|
||||||
lefBBox.r_ytop += lefBBox.r_ybot;
|
lefBBox.r_ytop += lefBBox.r_ybot;
|
||||||
}
|
}
|
||||||
|
gdsOffset.p_x += lefBBox.r_xbot;
|
||||||
|
gdsOffset.p_y += lefBBox.r_ybot;
|
||||||
LefEndStatement(f);
|
LefEndStatement(f);
|
||||||
break;
|
break;
|
||||||
origin_error:
|
origin_error:
|
||||||
|
|
@ -2312,7 +2329,7 @@ origin_error:
|
||||||
TxPrintf(" Macro defines pin %s\n", token);
|
TxPrintf(" Macro defines pin %s\n", token);
|
||||||
*/
|
*/
|
||||||
sprintf(tsave, "%.127s", token);
|
sprintf(tsave, "%.127s", token);
|
||||||
LefReadPin(lefMacro, f, tsave, pinNum++, oscale, is_imported);
|
LefReadPin(lefMacro, f, tsave, pinNum++, oscale, &gdsOffset, is_imported);
|
||||||
break;
|
break;
|
||||||
case LEF_OBS:
|
case LEF_OBS:
|
||||||
/* Diagnostic */
|
/* Diagnostic */
|
||||||
|
|
@ -2322,18 +2339,28 @@ origin_error:
|
||||||
if (is_imported)
|
if (is_imported)
|
||||||
LefSkipSection(f, NULL);
|
LefSkipSection(f, NULL);
|
||||||
else
|
else
|
||||||
LefReadGeometry(lefMacro, f, oscale, FALSE, is_imported);
|
LefReadGeometry(lefMacro, f, oscale, &gdsOffset, FALSE, is_imported);
|
||||||
break;
|
break;
|
||||||
case LEF_TIMING:
|
case LEF_TIMING:
|
||||||
LefSkipSection(f, macro_keys[LEF_TIMING]);
|
LefSkipSection(f, macro_keys[LEF_TIMING]);
|
||||||
break;
|
break;
|
||||||
case LEF_FOREIGN:
|
case LEF_FOREIGN:
|
||||||
|
token = LefNextToken(f, TRUE);
|
||||||
|
sprintf(tsave, "%.127s", token);
|
||||||
|
|
||||||
|
/* Read (optional) FOREIGN coordinate */
|
||||||
|
result = LefReadLefPoint(f, &x, &y);
|
||||||
|
if (result == 1) goto origin_error;
|
||||||
|
else if (result == 0)
|
||||||
|
{
|
||||||
|
gdsOffset.p_x += -(int)roundf(x / oscale);
|
||||||
|
gdsOffset.p_y += -(int)roundf(y / oscale);
|
||||||
|
}
|
||||||
if (importForeign)
|
if (importForeign)
|
||||||
{
|
{
|
||||||
token = LefNextToken(f, TRUE);
|
/* There is no behavioral difference when using
|
||||||
sprintf(tsave, "%.127s", token);
|
* importForiegn.
|
||||||
|
*/
|
||||||
/* To do: Read and apply X and Y offsets */
|
|
||||||
}
|
}
|
||||||
LefEndStatement(f);
|
LefEndStatement(f);
|
||||||
break;
|
break;
|
||||||
|
|
@ -2349,6 +2376,10 @@ origin_error:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Finish up creating the cell */
|
/* Finish up creating the cell */
|
||||||
|
lefBBox.r_xbot -= gdsOffset.p_x;
|
||||||
|
lefBBox.r_ybot -= gdsOffset.p_y;
|
||||||
|
lefBBox.r_xtop -= gdsOffset.p_x;
|
||||||
|
lefBBox.r_ytop -= gdsOffset.p_y;
|
||||||
DBReComputeBbox(lefMacro);
|
DBReComputeBbox(lefMacro);
|
||||||
|
|
||||||
if (is_imported)
|
if (is_imported)
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue