Fix I/O Pad ring 45 degree corners where off the foundry grid.

* New: In CRL/hepers, new function onFGrid() to ensure a DbU is on the
    foundry grid. Rounding is always done to the inferior integer.
* New: In CRL/GdsDriver, added a set of isOnGrid() functions to check
    that all coordinates of various objects are on the foundry grid.
      Use isOnGrid() in most objects processed in
    GdsStream::operator<<(Cell*).
* Bug: In cumulus/plugins.chip.pads.Corner, correctly round the
    coordinates of the 45 degree segments so they are still on the
    foundry grid.
This commit is contained in:
Jean-Paul Chaput 2020-12-09 00:05:52 +01:00
parent 973cc0f3c3
commit 945b9a24fa
3 changed files with 128 additions and 6 deletions

View File

@ -262,6 +262,13 @@ def u ( value ): return Hurricane.DbU.fromPhysical( value, Hurricane.DbU.UnitPow
def n ( value ): return Hurricane.DbU.fromPhysical( value, Hurricane.DbU.UnitPowerNano ) def n ( value ): return Hurricane.DbU.fromPhysical( value, Hurricane.DbU.UnitPowerNano )
def onFGrid ( u ):
oneGrid = Hurricane.DbU.fromGrid( 1.0 )
if u % oneGrid:
u -= (u % oneGrid)
return u
def initTechno ( argQuiet ): def initTechno ( argQuiet ):
global quiet global quiet
global ndaDir global ndaDir

View File

@ -68,6 +68,115 @@ namespace {
} }
bool isOnGrid ( Instance* instance )
{
bool error = false;
DbU::Unit oneGrid = DbU::fromGrid( 1.0 );
Point position = instance->getTransformation().getTranslation();
if (position.getX() % oneGrid) {
error = true;
cerr << Error( "isOnGrid(): On %s of %s,\n"
" Tx %s is not on grid (%s)"
, getString(instance).c_str()
, getString(instance->getCell()).c_str()
, DbU::getValueString(position.getX()).c_str()
, DbU::getValueString(oneGrid).c_str()
) << endl;
}
if (position.getY() % oneGrid) {
error = true;
cerr << Error( "isOnGrid(): On %s of %s,\n"
" Ty %s is not on grid (%s)"
, getString(instance).c_str()
, getString(instance->getCell()).c_str()
, DbU::getValueString(position.getY()).c_str()
, DbU::getValueString(oneGrid).c_str()
) << endl;
}
return error;
}
bool isOnGrid ( Component* component, const Box& bb )
{
bool error = false;
DbU::Unit oneGrid = DbU::fromGrid( 1.0 );
if (bb.getXMin() % oneGrid) {
error = true;
cerr << Error( "isOnGrid(): On %s of %s,\n"
" X-Min %s is not on grid (%s)"
, getString(component).c_str()
, getString(component->getCell()).c_str()
, DbU::getValueString(bb.getXMin()).c_str()
, DbU::getValueString(oneGrid).c_str()
) << endl;
}
if (bb.getXMax() % oneGrid) {
error = true;
cerr << Error( "isOnGrid(): On %s of %s,\n"
" X-Max %s is not on grid (%s)"
, getString(component).c_str()
, getString(component->getCell()).c_str()
, DbU::getValueString(bb.getXMax()).c_str()
, DbU::getValueString(oneGrid).c_str()
) << endl;
}
if (bb.getYMin() % oneGrid) {
error = true;
cerr << Error( "isOnGrid(): On %s of %s,\n"
" Y-Min %s is not on grid (%s)"
, getString(component).c_str()
, getString(component->getCell()).c_str()
, DbU::getValueString(bb.getYMin()).c_str()
, DbU::getValueString(oneGrid).c_str()
) << endl;
}
if (bb.getYMax() % oneGrid) {
error = true;
cerr << Error( "isOnGrid(): On %s of %s,\n"
" Y-Max %s is not on grid (%s)"
, getString(component).c_str()
, getString(component->getCell()).c_str()
, DbU::getValueString(bb.getYMax()).c_str()
, DbU::getValueString(oneGrid).c_str()
) << endl;
}
return error;
}
bool isOnGrid ( Component* component, const vector<Point>& points )
{
bool error = false;
DbU::Unit oneGrid = DbU::fromGrid( 1.0 );
for ( size_t i=0 ; i<points.size() ; ++i ) {
if (points[i].getX() % oneGrid) {
error = true;
cerr << Error( "isOnGrid(): On %s of %s,\n"
" Point [%d] X %s is not on grid (%s)"
, getString(component).c_str()
, getString(component->getCell()).c_str()
, i
, DbU::getValueString(points[i].getX()).c_str()
, DbU::getValueString(oneGrid).c_str()
) << endl;
}
if (points[i].getY() % oneGrid) {
error = true;
cerr << Error( "isOnGrid(): On %s of %s,\n"
" Point [%d] Y %s is not on grid (%s)"
, getString(component).c_str()
, getString(component->getCell()).c_str()
, i
, DbU::getValueString(points[i].getY()).c_str()
, DbU::getValueString(oneGrid).c_str()
) << endl;
}
}
return error;
}
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Class : "::DepthOrder". // Class : "::DepthOrder".
@ -598,6 +707,7 @@ namespace {
(*this) << SNAME( instance->getMasterCell()->getName() ); (*this) << SNAME( instance->getMasterCell()->getName() );
(*this) << instance->getTransformation(); (*this) << instance->getTransformation();
(*this) << ENDEL; (*this) << ENDEL;
isOnGrid( instance );
} }
for ( Net* net : cell->getNets() ) { for ( Net* net : cell->getNets() ) {
@ -623,6 +733,7 @@ namespace {
(*this) << layer; (*this) << layer;
(*this) << rectilinear->getPoints(); (*this) << rectilinear->getPoints();
(*this) << ENDEL; (*this) << ENDEL;
isOnGrid( component, rectilinear->getPoints() );
} }
} else { } else {
Diagonal* diagonal = dynamic_cast<Diagonal*>(component); Diagonal* diagonal = dynamic_cast<Diagonal*>(component);
@ -638,10 +749,14 @@ namespace {
or dynamic_cast<Contact *>(component) or dynamic_cast<Contact *>(component)
or dynamic_cast<Pad *>(component)) { or dynamic_cast<Pad *>(component)) {
for ( const BasicLayer* layer : component->getLayer()->getBasicLayers() ) { for ( const BasicLayer* layer : component->getLayer()->getBasicLayers() ) {
Box bb = component->getBoundingBox(layer);
if ((bb.getWidth() == 0) or (bb.getHeight() == 0))
continue;
(*this) << BOUNDARY; (*this) << BOUNDARY;
(*this) << layer; (*this) << layer;
(*this) << component->getBoundingBox(layer); (*this) << bb;
(*this) << ENDEL; (*this) << ENDEL;
isOnGrid( component, bb );
} }
} }
} }

View File

@ -25,7 +25,7 @@ from Hurricane import DbU, Point, Transformation, Interval, Box, \
import CRL import CRL
from CRL import RoutingLayerGauge from CRL import RoutingLayerGauge
import helpers import helpers
from helpers import trace, l, u, n from helpers import trace, l, u, n, onFGrid
from helpers.io import ErrorMessage, WarningMessage from helpers.io import ErrorMessage, WarningMessage
from helpers.overlay import UpdateSession from helpers.overlay import UpdateSession
import plugins.alpha.chip import plugins.alpha.chip
@ -58,28 +58,28 @@ class Corner ( object ):
yCorner = self.conf.chipAb.getYMin() + axis yCorner = self.conf.chipAb.getYMin() + axis
xBb = self.conf.chipAb.getXMin() + self.conf.ioPadHeight xBb = self.conf.chipAb.getXMin() + self.conf.ioPadHeight
yBb = self.conf.chipAb.getYMin() + self.conf.ioPadHeight yBb = self.conf.chipAb.getYMin() + self.conf.ioPadHeight
xExtend = - long( 0.5 * float(self.conf.ioPadHeight - axis) ) xExtend = - onFGrid( long( 0.5 * float(self.conf.ioPadHeight - axis) ) )
yExtend = xExtend yExtend = xExtend
elif self.type == SouthEast: elif self.type == SouthEast:
xCorner = self.conf.chipAb.getXMax() - axis xCorner = self.conf.chipAb.getXMax() - axis
yCorner = self.conf.chipAb.getYMin() + axis yCorner = self.conf.chipAb.getYMin() + axis
xBb = self.conf.chipAb.getXMax() - self.conf.ioPadHeight xBb = self.conf.chipAb.getXMax() - self.conf.ioPadHeight
yBb = self.conf.chipAb.getYMin() + self.conf.ioPadHeight yBb = self.conf.chipAb.getYMin() + self.conf.ioPadHeight
xExtend = long( 0.5 * float(self.conf.ioPadHeight - axis) ) xExtend = onFGrid( long( 0.5 * float(self.conf.ioPadHeight - axis) ) )
yExtend = - xExtend yExtend = - xExtend
elif self.type == NorthEast: elif self.type == NorthEast:
xCorner = self.conf.chipAb.getXMax() - axis xCorner = self.conf.chipAb.getXMax() - axis
yCorner = self.conf.chipAb.getYMax() - axis yCorner = self.conf.chipAb.getYMax() - axis
xBb = self.conf.chipAb.getXMax() - self.conf.ioPadHeight xBb = self.conf.chipAb.getXMax() - self.conf.ioPadHeight
yBb = self.conf.chipAb.getYMax() - self.conf.ioPadHeight yBb = self.conf.chipAb.getYMax() - self.conf.ioPadHeight
xExtend = long( 0.5 * float(self.conf.ioPadHeight - axis) ) xExtend = onFGrid( long( 0.5 * float(self.conf.ioPadHeight - axis) ) )
yExtend = xExtend yExtend = xExtend
elif self.type == NorthWest: elif self.type == NorthWest:
xCorner = self.conf.chipAb.getXMin() + axis xCorner = self.conf.chipAb.getXMin() + axis
yCorner = self.conf.chipAb.getYMax() - axis yCorner = self.conf.chipAb.getYMax() - axis
xBb = self.conf.chipAb.getXMin() + self.conf.ioPadHeight xBb = self.conf.chipAb.getXMin() + self.conf.ioPadHeight
yBb = self.conf.chipAb.getYMax() - self.conf.ioPadHeight yBb = self.conf.chipAb.getYMax() - self.conf.ioPadHeight
xExtend = - long( 0.5 * float(self.conf.ioPadHeight - axis) ) xExtend = - onFGrid( long( 0.5 * float(self.conf.ioPadHeight - axis) ) )
yExtend = - xExtend yExtend = - xExtend
return xCorner, yCorner, xBb, yBb, xExtend, yExtend return xCorner, yCorner, xBb, yBb, xExtend, yExtend