Compare commits

...

3 Commits

Author SHA1 Message Date
Jean-Paul Chaput 92a3e32aaf Add jumpers (antenna protection) on I/O pads and SRAM macro-block.
* New: In cumulus/plugins.chip.pads, add METAL5 jumpers on all wires
    going to/from the I/O pads on the East & West side. This is a
    quick hack as:
      1. We should put it also on North/South, but no violation
         happens here.
      2. We should put it on *ouput* wire only (for only those are
         connected to transistors gates).
* New: In cumulus/plugins.chip.macro, put jumpers on the East side
    connectors for the SRAM block. Also a quick hack, not robust for
    anything else than the SRAM.
2021-06-08 12:20:05 +02:00
Jean-Paul Chaput dd49a185af Compensate diodes between RP clusters & wire clusters.
In Anabatic::AntennaProtect, when we cannot insert enough diodes
under a wire cluster. Which makes it likely very long and over an
area where diodes cannot be inserted (chip border close to I/O pads
or over a macro-block). Request extra diode insertion on it's
connecting RoutingPad clusters.

* New: In Anabatic::DiodeCluster, add a "forced diode" counter for
    extra diodes inertions. Only used in the DiodeRps derived class.
* New: In Anabatic::DiodeCluster, add support for a cluster to know
    it's neighbors. Stored as indexes of the table being built in
    Anabatic::antennaProtect(Net*).
* New: In Anabatic::antennaProtect(Net*), when builing the WireCluster,
    also find it's neigbors. Store the index of the cluster a segment
    belongs to in clusterSegments.
2021-06-08 12:19:40 +02:00
Jean-Paul Chaput 5f60767486 In AutoSegment::expandToMinLength(), ensure that we stay on foundry grid 2021-06-08 12:19:08 +02:00
4 changed files with 262 additions and 77 deletions

View File

@ -123,6 +123,11 @@ namespace {
static const uint32_t IsSegSource;
static const uint32_t InCluster;
static string toStr ( uint32_t );
public:
template<typename DerivedT>
inline const DerivedT* as () const { return dynamic_cast<const DerivedT>( this ); }
template<typename DerivedT>
inline DerivedT* as () { return dynamic_cast<DerivedT>( this ); }
public:
DiodeCluster ( AnabaticEngine*, RoutingPad* );
virtual ~DiodeCluster ();
@ -136,13 +141,17 @@ namespace {
inline AnabaticEngine* _getAnabatic () const;
inline const RoutingPadInfos& getRoutingPads () const;
inline RoutingPadInfos& _getRoutingPads () ;
inline const set<size_t>& getNeighbors () const;
inline const vector<Instance*>& getDiodes () const;
inline vector<Instance*>& _getDiodes ();
inline uint32_t getForcedDiodes () const;
inline DbU::Unit getWL () const;
inline DbU::Unit& _getWL ();
void showArea () const;
virtual bool needsDiode () const = 0;
Box getBoundingBox () const;
inline void addNeighbor ( size_t );
inline void addForcedDiodes ( uint32_t );
void merge ( GCell*, uint32_t distance, GCell* back=NULL );
virtual void merge ( RoutingPad* );
virtual void merge ( Segment* ) = 0;
@ -159,6 +168,8 @@ namespace {
RoutingPadInfos _routingPads;
vector<GCellArea> _areas;
vector<Instance*> _diodes;
set<size_t> _neighbors;
uint32_t _forcedDiodes;
};
@ -187,6 +198,8 @@ namespace {
, _routingPads()
, _areas(1)
, _diodes()
, _neighbors()
, _forcedDiodes(0)
{
merge( rp );
}
@ -205,6 +218,10 @@ namespace {
inline RoutingPadInfos& DiodeCluster::_getRoutingPads () { return _routingPads; }
inline const vector<Instance*>& DiodeCluster::getDiodes () const { return _diodes; }
inline vector<Instance*>& DiodeCluster::_getDiodes () { return _diodes; }
inline const set<size_t>& DiodeCluster::getNeighbors () const { return _neighbors; }
inline void DiodeCluster::addNeighbor ( size_t neighbor ) { _neighbors.insert(neighbor); }
inline uint32_t DiodeCluster::getForcedDiodes () const { return _forcedDiodes; }
inline void DiodeCluster::addForcedDiodes ( uint32_t count ) { _forcedDiodes += count; }
DbU::Unit DiodeCluster::getAntennaGateMaxWL () const
@ -415,6 +432,7 @@ namespace {
cdebug_log(147,1) << "DiodeCluster::createDiodes() count=" << diodeCount
<< ", forcedHalo=" << (_areas.size()-1) << endl;
Instance* diode = NULL;
//for ( size_t i=(_areas.size() == 1)?0:1 ; i<_areas.size() ; ++i ) {
for ( size_t i=0 ; i<_areas.size() ; ++i ) {
if (i) diodeCount = 1;
cdebug_log(147,0) << "Diode for area [" << i << "]" << endl;
@ -502,6 +520,7 @@ namespace {
bool DiodeRps::needsDiode () const
{
if (getForcedDiodes()) return true;
for ( auto& infos : getRoutingPads() ) {
if (std::get<1>(infos) & IsSink) return true;
}
@ -526,8 +545,9 @@ namespace {
cdebug_log(147,0) << "DiodeRps::mergeHalo(): " << segment << endl;
if (not segment) return;
if ( (dynamic_cast<Horizontal*>(segment))
and (getWL() + segment->getLength() > getAntennaGateMaxWL())) {
// if ( (dynamic_cast<Horizontal*>(segment))
// and (getWL() + segment->getLength() > getAntennaGateMaxWL())) {
if (dynamic_cast<Horizontal*>(segment)) {
cdebug_log(147,0) << " Put in forced halo." << segment << endl;
GCellsUnder gcells = _getAnabatic()->getGCellsUnder( segment );
if (not gcells->empty()) {
@ -590,20 +610,26 @@ namespace {
class DiodeWire : public DiodeCluster {
public:
DiodeWire ( AnabaticEngine*, RoutingPad* );
virtual bool needsDiode () const;
virtual void merge ( Segment* );
virtual const vector<Instance*>& createDiodes ( Etesian::Area* );
DiodeWire ( AnabaticEngine*, RoutingPad* );
virtual bool needsDiode () const;
virtual void merge ( Segment* );
virtual const vector<Instance*>& createDiodes ( Etesian::Area* );
inline const set<Segment*,Go::CompareById>& getSegments () const;
private:
set<Box,CompareBySegmentBox> _boxes;
set<Contact*,Go::CompareById> _contacts;
set<Segment*,Go::CompareById> _segments;
};
inline const set<Segment*,Go::CompareById>& DiodeWire::getSegments () const { return _segments; }
DiodeWire::DiodeWire ( AnabaticEngine* anabatic, RoutingPad* rp )
: DiodeCluster(anabatic,rp)
, _boxes()
, _contacts()
, _segments()
{ }
@ -613,9 +639,10 @@ namespace {
void DiodeWire::merge ( Segment* segment )
{
if (_segments.find(segment) != _segments.end()) return;
Box bb = segment->getBoundingBox();
if (_boxes.find(bb) != _boxes.end()) return;
cdebug_log(147,0) << "| merge: " << segment << endl;
_segments.insert( segment );
_boxes.insert( bb );
_getWL() += segment->getLength();
}
@ -623,7 +650,14 @@ namespace {
const vector<Instance*>& DiodeWire::createDiodes ( Etesian::Area* area )
{
cdebug_log(147,1) << "DiodeWire::createDiodes() " << endl;
cdebug_log(147,1) << "DiodeWire::createDiodes() on " << _boxes.size() << " boxes." << endl;
ostringstream m;
m << "Neighbors: [";
for ( size_t neighbor : getNeighbors() ) { m << " " << neighbor; }
m << " ]";
cdebug_log(147,0) << m.str() << endl;
DbU::Unit antennaDiodeMaxWL = getAntennaDiodeMaxWL();
size_t diodeCount = getWL() / antennaDiodeMaxWL;
@ -635,7 +669,7 @@ namespace {
size_t segDiodeCount = bbLength / antennaDiodeMaxWL;
if (not segDiodeCount) ++segDiodeCount;
bool isH = (bb.getWidth() >= bb.getHeight());
cdebug_log(147,0) << "diodes=" << segDiodeCount << " " << bb
cdebug_log(147,0) << "Processing wire diodes=" << segDiodeCount << " " << bb
<< " isH=" << isH
<< " length:" << DbU::getValueString(getBoxLength(bb)) << endl;
//if (bbLength < antennaDiodeMaxWL/4) continue;
@ -647,7 +681,6 @@ namespace {
_createDiode( area, bb, uHint );
uHint += antennaDiodeMaxWL;
}
if (_getDiodes().size() >= diodeCount) break;
} else {
GCellsUnder gcells = _getAnabatic()->getGCellsUnder( Point(bb.getXCenter(),bb.getYMin())
, Point(bb.getXCenter(),bb.getYMax()) );
@ -661,6 +694,11 @@ namespace {
}
}
}
if (_getDiodes().size() >= diodeCount) {
cdebug_log(147,0) << "Added enough diodes " << _getDiodes().size() << endl;
break;
}
}
if (_getDiodes().size() < diodeCount) {
@ -804,9 +842,9 @@ namespace Anabatic {
DbU::Unit antennaGateMaxWL = etesian->getAntennaGateMaxWL();
vector<DiodeCluster*> clusters;
set<RoutingPad*,DBo::CompareById> rpsDone;
set<Segment*,DBo::CompareById> clusterSegments;
vector<DiodeCluster*> clusters;
map<RoutingPad*,size_t,DBo::CompareById> rpsDone;
map<Segment*,size_t,DBo::CompareById> clusterSegments;
for ( RoutingPad* rp : net->getRoutingPads() ) {
set<Segment*,DBo::CompareById> segmentsDone;
@ -815,7 +853,7 @@ namespace Anabatic {
cdebug_log(147,0) << "New Cluster [" << clusters.size() << "] from " << rp << endl;
DiodeCluster* cluster = new DiodeRps ( this, rp );
clusters.push_back( cluster );
rpsDone.insert( rp );
rpsDone.insert( make_pair( rp, clusters.size()-1 ) );
size_t stackTop = 0;
vector< StackItem > hooksStack;
@ -861,7 +899,7 @@ namespace Anabatic {
if (rpsDone.find(toRp) == rpsDone.end()) {
cdebug_log(147,0) << "> Agglomerate " << toRp << endl;
cluster->merge( toRp );
rpsDone.insert( toRp );
rpsDone.insert( make_pair( toRp, clusters.size()-1 ) );
rp = toRp;
}
}
@ -876,7 +914,7 @@ namespace Anabatic {
else branchWL = 0;
cluster->merge( segment );
std::get<3>( hooksStack[backIndex] ) |= DiodeCluster::InCluster;
clusterSegments.insert( segment );
clusterSegments.insert( make_pair( segment, clusters.size()-1 ) );
cdebug_log(147,0) << "| back=" << backIndex
<< " -> " << std::get<2>( hooksStack[backIndex] )
<< " " << DbU::getValueString(segment->getLength())
@ -931,7 +969,9 @@ namespace Anabatic {
}
if (clusters.size() > 1) {
cdebug_log(147,0) << "Cluster wiring" << endl;
size_t rpClustersSize = clusters.size();
cdebug_log(147,0) << "Cluster wiring, rpClustersSize=" << rpClustersSize << endl;
for ( Segment* segment : net->getSegments() ) {
if (clusterSegments.find(segment) != clusterSegments.end()) continue;
@ -940,7 +980,7 @@ namespace Anabatic {
DiodeWire* cluster = new DiodeWire( this, clusters[0]->getRefRp() );
cluster->merge( segment );
clusters.push_back( cluster );
clusterSegments.insert( segment );
clusterSegments.insert( make_pair( segment, clusters.size()-1 ) );
size_t stackTop = 0;
vector< StackItem > hooksStack;
@ -959,8 +999,15 @@ namespace Anabatic {
bool hasRp = false;
for ( Hook* hook : toHook->getHooks() ) {
if (dynamic_cast<RoutingPad*>(hook->getComponent())) {
RoutingPad* rp = dynamic_cast<RoutingPad*>( hook->getComponent() );
if (rp) {
hasRp = true;
auto irp = rpsDone.find( rp );
if (irp != rpsDone.end()) {
size_t neighbor = (*irp).second;
cdebug_log(147,0) << "| " << rp << " belongs to [" << neighbor << "]" << endl;
cluster->addNeighbor( neighbor );
}
break;
}
}
@ -970,8 +1017,15 @@ namespace Anabatic {
Segment* segment = dynamic_cast<Segment*>( hook->getComponent() );
if (segment) {
if (segment == fromSegment) continue;
if (clusterSegments.find(segment) != clusterSegments.end()) continue;
clusterSegments.insert( segment );
auto iclusterSegment = clusterSegments.find( segment );
if (iclusterSegment != clusterSegments.end()) {
size_t neighbor = (*iclusterSegment).second;
cdebug_log(147,0) << "| " << segment << " belongs to [" << neighbor << "]" << endl;
if (neighbor < rpClustersSize)
cluster->addNeighbor( neighbor );
continue;
}
clusterSegments.insert( make_pair( segment, clusters.size()-1 ) );
cluster->merge( segment );
uint32_t flags = (segment->getSourceHook() == hook) ? DiodeCluster::IsSegSource : 0;
if (dynamic_cast<Segment::SourceHook*>(hook)) {
@ -989,7 +1043,8 @@ namespace Anabatic {
total += clusters.size();
cdebug_log(147,1) << "Net \"" << net->getName() << " has " << clusters.size() << " diode clusters." << endl;
for ( size_t i=0 ; i<clusters.size() ; ++i ) {
size_t i = clusters.size()-1;
while ( true ) {
cdebug_log(147,1) << "Cluster [" << i << "] needsDiode=" << clusters[i]->needsDiode()
<< " bb=" << clusters[i]->getBoundingBox() << endl;
cdebug_log(147,0) << " WL=" << DbU::getValueString(clusters[i]->getWL()) << endl;
@ -997,25 +1052,29 @@ namespace Anabatic {
cdebug_log(147,0) << "| flags=" << DiodeCluster::toStr(std::get<1>(item))
<< " " << std::get<0>(item) << endl;
}
if (not clusters[i]->needsDiode()) {
cdebug_tabw(147,-1);
continue;
}
const vector<Instance*>& diodes = clusters[i]->createDiodes( etesian->getArea() );
if (not diodes.empty()) {
clusters[i]->connectDiodes();
} else {
cerr << Error( "EtesianEngine::antennaProtect(): For %s (rps:%u, clusters:%u)\n"
" Cannot find a diode nearby %s."
, getString(net).c_str()
, rpsDone.size()
, clusters.size()
, getString(clusters[i]->getRefRp()).c_str()
) << endl;
failed += 1;
if (clusters[i]->needsDiode()) {
const vector<Instance*>& diodes = clusters[i]->createDiodes( etesian->getArea() );
if (not diodes.empty()) {
clusters[i]->connectDiodes();
} else {
cerr << Error( "EtesianEngine::antennaProtect(): For %s (rps:%u, clusters:%u)\n"
" Cannot find a diode nearby %s."
, getString(net).c_str()
, rpsDone.size()
, clusters.size()
, getString(clusters[i]->getRefRp()).c_str()
) << endl;
failed += 1;
for ( size_t icluster : clusters[i]->getNeighbors() ) {
clusters[icluster]->addForcedDiodes( 1 );
}
}
}
cdebug_tabw(147,-1);
if (i == 0) break;
--i;
}
cdebug_tabw(147,-1);

View File

@ -1697,8 +1697,13 @@ namespace Anabatic {
return false;
}
DbU::Unit oneGrid = DbU::fromGrid( 1 );
DbU::Unit targetExpand = (techMinLength - segMinLength) / 2 + targetCap;
DbU::Unit sourceExpand = - (techMinLength - segMinLength) / 2 - sourceCap;
if (targetExpand % oneGrid)
targetExpand += oneGrid - targetExpand % oneGrid;
if (sourceExpand % oneGrid)
sourceExpand -= oneGrid + sourceExpand % oneGrid;
if (not span.isEmpty()) {
DbU::Unit shiftLeft = span.getVMax() - (getTargetU() + targetExpand);
if (shiftLeft < 0) {

View File

@ -513,6 +513,7 @@ class CoreWire ( object ):
self.offset = 0
self.offsetType = CoreWire.NoOffset
self.side = side
self.addJumper = False
self.preferredDir = preferredDir
self.inCoronaRange = True
self.arraySize = None
@ -520,6 +521,8 @@ class CoreWire ( object ):
self.viaPitch = DbU.fromLambda( 4.0 )
self.gapWidth = 0
self._computeCoreLayers()
if self.conf.routingGauge.getName() == 'FlexLib':
self.addJumper = True
@property
def conf ( self ): return self.corona.conf
@ -627,13 +630,68 @@ class CoreWire ( object ):
if not self.preferredDir:
#xPadMin -= self.bbSegment.getHeight()/2
xPadMin -= 3*vPitch
hReal = Horizontal.create( self.chipNet
, self.padSegment.getLayer()
, self.bbSegment.getCenter().getY()
, self.bbSegment.getHeight()
, xPadMin
, xPadMax
)
if self.addJumper:
rg = self.conf.routingGauge
gaugeM5 = rg.getLayerGauge( 4 )
wwidthM5 = gaugeM5.getWireWidth()
jumperGap = 3*gaugeM5.getPitch()
if self.side == East:
gapCenter = xPadMin + 5*gaugeM5.getPitch()
else:
gapCenter = xPadMax - 5*gaugeM5.getPitch()
xJumpMin = gapCenter - jumperGap/2
xJumpMax = gapCenter + jumperGap/2
hReal1 = Horizontal.create( self.chipNet
, self.padSegment.getLayer()
, self.bbSegment.getCenter().getY()
, self.bbSegment.getHeight()
, xPadMin
, xJumpMin
)
trace( 550, '\thReal1: %s\n' % str(hReal1) )
hReal2 = Horizontal.create( self.chipNet
, self.padSegment.getLayer()
, self.bbSegment.getCenter().getY()
, self.bbSegment.getHeight()
, xJumpMax
, xPadMax
)
trace( 550, '\thReal2: %s\n' % str(hReal2) )
hReal = hReal2 if self.side == West else hReal1
bvia1 = BigVia( self.chipNet
, rg.getLayerDepth( self.padSegment.getLayer() )
, xJumpMin
, self.bbSegment.getCenter().getY()
, wwidthM5
, 2*wwidthM5
, flags=BigVia.AllowAllExpand )
bvia1.mergeDepth( gaugeM5.getDepth() )
trace( 550, '\tbvia1: %s\n' % str(bvia1) )
bvia1.doLayout()
bvia2 = BigVia( self.chipNet
, rg.getLayerDepth( self.padSegment.getLayer() )
, xJumpMax
, self.bbSegment.getCenter().getY()
, wwidthM5
, 2*wwidthM5
, flags=BigVia.AllowAllExpand )
bvia2.mergeDepth( gaugeM5.getDepth() )
bvia2.doLayout()
trace( 550, '\tbvia2: %s\n' % str(bvia2) )
Horizontal.create( bvia1.getPlate( gaugeM5.getLayer() )
, bvia2.getPlate( gaugeM5.getLayer() )
, gaugeM5.getLayer()
, self.bbSegment.getCenter().getY()
, wwidthM5
)
else:
hReal = Horizontal.create( self.chipNet
, self.padSegment.getLayer()
, self.bbSegment.getCenter().getY()
, self.bbSegment.getHeight()
, xPadMin
, xPadMax
)
trace( 550, '\tself.arraySize: %s\n' % str(self.arraySize) )
if self.arraySize:
contacts = self.conf.coronaContactArray( self.chipNet

View File

@ -134,19 +134,33 @@ class Macro ( object ):
gaugeMetal2 = self.rg.getLayerGauge( 1 )
gaugeMetal3 = self.rg.getLayerGauge( 2 )
gaugeMetal4 = self.rg.getLayerGauge( 3 )
gaugeMetal5 = self.rg.getLayerGauge( 4 )
blockageMetal2 = gaugeMetal2.getBlockageLayer()
blockageMetal3 = gaugeMetal3.getBlockageLayer()
blockageMetal4 = gaugeMetal4.getBlockageLayer()
minSpacingMetal2 = gaugeMetal2.getLayer().getMinimalSpacing()
minSpacingMetal3 = gaugeMetal3.getLayer().getMinimalSpacing()
minSpacingMetal4 = gaugeMetal4.getLayer().getMinimalSpacing()
useJumper = False
xMinAdjust = 0
yMinAdjust = 0
xMaxAdjust = 0
yMaxAdjust = 0
if self.cell.getName().lower() == 'spblock_512w64b8w':
print( ' o Ad-hoc patch for "{}".'.format(self.cell.getName()) )
useJumper = True
xMinAdjust = 3*self.rg.getPitch( gaugeMetal5.getLayer() )
pitch = gaugeMetal2.getPitch()
if xMinAdjust % pitch:
xMinAdjust += pitch - (xMinAdjust % pitch)
for net in self.cell.getNets():
for component in net.getComponents():
if isinstance(component,Rectilinear) and component.getLayer() == blockageMetal2:
bb = component.getBoundingBox()
bb.inflate( minSpacingMetal2 )
bb.inflate( minSpacingMetal2 + xMinAdjust
, minSpacingMetal2
, minSpacingMetal2
, minSpacingMetal2 )
Horizontal.create( component.getNet()
, blockageMetal2
, bb.getYCenter()
@ -192,11 +206,9 @@ class Macro ( object ):
elif ab.getXMin() == bb.getXMin(): westPins.append( component )
elif ab.getYMax() == bb.getYMax(): northPins.append( component )
elif ab.getYMin() == bb.getYMin(): southPins.append( component )
xAdjust = 0
yAdjust = 0
if ab.getWidth () % sliceHeight: xAdjust = sliceHeight - ab.getWidth () % sliceHeight
if ab.getHeight() % sliceHeight: yAdjust = sliceHeight - ab.getHeight() % sliceHeight
self.innerAb.inflate( 0, 0, xAdjust, yAdjust )
if ab.getWidth () % sliceHeight: xMaxAdjust = sliceHeight - (ab.getWidth ()+xMinAdjust) % sliceHeight
if ab.getHeight() % sliceHeight: yMaxAdjust = sliceHeight - (ab.getHeight()+yMinAdjust) % sliceHeight
self.innerAb.inflate( xMinAdjust, 0, xMaxAdjust, yMaxAdjust )
self.outerAb = Box( self.innerAb )
self.outerAb.inflate( sliceHeight )
westPins .sort( key=lambda k: k.getBoundingBox().getYCenter() )
@ -225,27 +237,78 @@ class Macro ( object ):
else:
ppYAxis += width/2
ppYOngrid -= wwidth/2
vertical = Vertical.create( component.getNet()
, component.getLayer()
, bb.getXMin()
, width
, ppYAxis
, ppYOngrid
)
horizontal = Horizontal.create( component.getNet()
if useJumper:
jpitch = self.rg.getPitch ( gaugeMetal5.getLayer() )
jwwidth = self.rg.getWireWidth( gaugeMetal5.getLayer() )
xMin -= 4*jpitch
bvia1 = BigVia( component.getNet()
, self.getLayerDepth(component.getLayer())
, xMax
, yOngrid
, wwidth
, 3*wwidth
, flags=BigVia.AllowAllExpand )
bvia1.mergeDepth( gaugeMetal5.getDepth() )
bvia1.doLayout()
bvia2 = BigVia( component.getNet()
, self.getLayerDepth(component.getLayer())
, xMax - 3*jpitch
, yOngrid
, wwidth
, 3*wwidth
, flags=BigVia.AllowAllExpand )
bvia2.mergeDepth( gaugeMetal5.getDepth() )
bvia2.doLayout()
Horizontal.create( bvia1.getPlate( gaugeMetal5.getLayer() )
, bvia2.getPlate( gaugeMetal5.getLayer() )
, gaugeMetal5.getLayer()
, yOngrid
, jwwidth
)
horizontal = Horizontal.create( component.getNet()
, component.getLayer()
, yOngrid
, wwidth
, xMin
, xMax - 3*jpitch
)
horizontal = Horizontal.create( component.getNet()
, component.getLayer()
, yOngrid
, wwidth
, xMin
, xMin + ppitch + ppitch/2
)
blockageNet = self.cell.getNet( '*' )
for gauge in [ gaugeMetal3, gaugeMetal3, gaugeMetal4, gaugeMetal5 ]:
bb = bvia1.getPlate( gauge.getLayer() ).getBoundingBox()
bb.merge( bvia2.getPlate( gauge.getLayer() ).getBoundingBox() )
bb.inflate( gauge.getLayer().getMinimalSpacing() )
Pad.create( blockageNet
, gauge.getLayer().getBlockageLayer()
, bb )
else:
vertical = Vertical.create( component.getNet()
, component.getLayer()
, yOngrid
, wwidth
, xMin
, xMax
)
horizontal = Horizontal.create( component.getNet()
, component.getLayer()
, yOngrid
, wwidth
, xMin
, xMin + ppitch + ppitch/2
, bb.getXMin()
, width
, ppYAxis
, ppYOngrid
)
horizontal = Horizontal.create( component.getNet()
, component.getLayer()
, yOngrid
, wwidth
, xMin
, xMax
)
horizontal = Horizontal.create( component.getNet()
, component.getLayer()
, yOngrid
, wwidth
, xMin
, xMin + ppitch + ppitch/2
)
NetExternalComponents.setExternal( horizontal )
for component in eastPins:
layer = component.getLayer()
@ -259,8 +322,8 @@ class Macro ( object ):
bb = component.getBoundingBox()
yAxis = bb.getYCenter()
yOngrid = self.getNearestTrackAxis( layer, yAxis )
xMin = self.innerAb.getXMax() - xAdjust
xMax = xMin + xAdjust + hMargin*ppitch
xMin = self.innerAb.getXMax() - xMaxAdjust
xMax = xMin + xMaxAdjust + hMargin*ppitch
width = bb.getHeight()
ppYAxis = yAxis
ppYOngrid = yOngrid
@ -289,7 +352,7 @@ class Macro ( object ):
, layer
, yOngrid
, wwidth
, xMin + xAdjust + ppitch
, xMin + xMaxAdjust + ppitch
, xMax
)
NetExternalComponents.setExternal( horizontal )
@ -347,8 +410,8 @@ class Macro ( object ):
bb = component.getBoundingBox()
xAxis = bb.getXCenter()
xOngrid = self.getNearestTrackAxis( layer, xAxis )
yMin = self.innerAb.getYMax() - yAdjust
yMax = yMin + yAdjust + vMargin*ppitch
yMin = self.innerAb.getYMax() - yMaxAdjust
yMax = yMin + yMaxAdjust + vMargin*ppitch
width = bb.getWidth()
ppXAxis = xAxis
ppXOngrid = xOngrid
@ -388,7 +451,7 @@ class Macro ( object ):
, layer
, xOngrid
, wwidth
, yMin + ppitch + yAdjust
, yMin + ppitch + yMaxAdjust
, yMax
)
NetExternalComponents.setExternal( vertical )