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:
parent
973cc0f3c3
commit
945b9a24fa
|
@ -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
|
||||||
|
|
|
@ -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 );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue