Tuning of Anabatic & Katana for AMS 350nm (c35b4).
* New: In Anabatic::LayerAssign, a new mode "LayerAssignNoGlobalM2V" has been added to manage the 3 routing metal technologies like AMS 350nm. The standard cells have all their connectors punctual and aligned on an horizontal line in the middle of the Cell. This is a design inherited from the channel routing times that makes global routing in metal2 *through* a standard cell almost impossible (except for directly neighboring cells). Thus, the layer assignment must move up all the metal2 that span more than two GCells. * Change: In Katana::Manipulator::ripupPerpandiculars(), when a perpandicular has a fixed axis and it's (sole) underlying track is taken, ripup the other segment to ensure the perpandicular interval will be free. We need to do that, because in DataNegociate::update(), if the perpandicular is taken, the perpandicular interval will always been empty preventing the segment to have a valid track span (so directly failing). * Change: In Katana::SegmentFsm::conflictSolveByPlaceds() the fixed axis segments must also been taken into account as conflicts. Also correct a small bug, the first conflicting segment in the interval was not taken into account correctly.
This commit is contained in:
parent
2077a19bec
commit
e88b2050c2
|
@ -1636,11 +1636,11 @@ namespace Anabatic {
|
||||||
getGCells( gcells );
|
getGCells( gcells );
|
||||||
for ( size_t i=0 ; i<gcells.size() ; ++i ) {
|
for ( size_t i=0 ; i<gcells.size() ; ++i ) {
|
||||||
gcells[i]->flags() |= Flags::Invalidated;
|
gcells[i]->flags() |= Flags::Invalidated;
|
||||||
cdebug_log(159,0) << "changeDepth() " << gcells[i] << this << " " << endl;
|
cdebug_log(149,0) << "changeDepth() " << gcells[i] << this << " " << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (not (flags & Flags::WithNeighbors)) {
|
if (not (flags & Flags::WithNeighbors)) {
|
||||||
cdebug_tabw(159,-1);
|
cdebug_tabw(149,-1);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -199,6 +199,119 @@ namespace Anabatic {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AnabaticEngine::_layerAssignNoGlobalM2V ( Net* net, set<Net*>& globalNets, unsigned long& total, unsigned long& global )
|
||||||
|
{
|
||||||
|
cdebug_log(149,0) << "Anabatic::_layerAssignNoGlobalM2V ( " << net << " )" << endl;
|
||||||
|
cdebug_tabw(145,1);
|
||||||
|
|
||||||
|
bool isGlobalNet = false;
|
||||||
|
unsigned long netGlobal = 0;
|
||||||
|
unsigned long netTotal = 0;
|
||||||
|
set<AutoContact*> globalContacts;
|
||||||
|
|
||||||
|
for ( Segment* baseSegment : net->getSegments() ) {
|
||||||
|
++netTotal;
|
||||||
|
|
||||||
|
AutoSegment* segment = Session::lookup( baseSegment );
|
||||||
|
|
||||||
|
if (not segment or segment->isLocal()) continue;
|
||||||
|
|
||||||
|
isGlobalNet = true;
|
||||||
|
netTotal = 0;
|
||||||
|
globalNets.insert( net );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isGlobalNet) {
|
||||||
|
vector<AutoSegment*> horizontals;
|
||||||
|
|
||||||
|
for ( Segment* baseSegment : net->getSegments() ) {
|
||||||
|
AutoSegment* segment = Session::lookup( baseSegment );
|
||||||
|
if (not segment or not segment->isCanonical()) continue;
|
||||||
|
|
||||||
|
if (segment->isHorizontal()) horizontals.push_back( segment );
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( AutoSegment* horizontal : horizontals ) {
|
||||||
|
vector<AutoSegment*> collapseds;
|
||||||
|
vector<AutoSegment*> perpandiculars;
|
||||||
|
vector<AutoSegment*> northBounds;
|
||||||
|
vector<AutoSegment*> southBounds;
|
||||||
|
DbU::Unit leftBound;
|
||||||
|
DbU::Unit rightBound;
|
||||||
|
bool hasNorth = false;
|
||||||
|
bool hasSouth = false;
|
||||||
|
|
||||||
|
AutoSegment::getTopologicalInfos( horizontal
|
||||||
|
, collapseds
|
||||||
|
, perpandiculars
|
||||||
|
, leftBound
|
||||||
|
, rightBound
|
||||||
|
);
|
||||||
|
|
||||||
|
for ( AutoSegment* perpandicular : perpandiculars ) {
|
||||||
|
if (Session::getLayerDepth(perpandicular->getLayer()) > 2) continue;
|
||||||
|
|
||||||
|
bool hasGlobal = false;
|
||||||
|
for ( AutoSegment* aligned : perpandicular->getAligneds(Flags::NoCheckLayer|Flags::WithSelf) ) {
|
||||||
|
if (aligned->isGlobal()) { hasGlobal = true; break; }
|
||||||
|
}
|
||||||
|
if (not hasGlobal) continue;
|
||||||
|
|
||||||
|
// if (perpandicular->getSourceY() == horizontal->getAxis()) {
|
||||||
|
// hasNorth = true;
|
||||||
|
// if (hasGlobal) northBounds.push_back( perpandicular );
|
||||||
|
// } else {
|
||||||
|
// hasSouth = true;
|
||||||
|
// if (hasGlobal) southBounds.push_back( perpandicular );
|
||||||
|
// }
|
||||||
|
|
||||||
|
if ( perpandicular->getAutoSource()->getGCell()->getNorth()
|
||||||
|
!= perpandicular->getAutoTarget()->getGCell()) {
|
||||||
|
perpandicular->changeDepth( 3, Flags::Propagate );
|
||||||
|
++netGlobal;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (hasSouth and hasNorth) {
|
||||||
|
// if (not northBounds.empty()) {
|
||||||
|
// for ( AutoSegment* perpandicular : northBounds )
|
||||||
|
// perpandicular->changeDepth( 3, Flags::Propagate );
|
||||||
|
// } else {
|
||||||
|
// for ( AutoSegment* perpandicular : southBounds )
|
||||||
|
// perpandicular->changeDepth( 3, Flags::Propagate );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
total += netTotal;
|
||||||
|
global += netGlobal;
|
||||||
|
|
||||||
|
cdebug_tabw(145,-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AnabaticEngine::_layerAssignNoGlobalM2V ( unsigned long& total, unsigned long& global, set<Net*>& globalNets )
|
||||||
|
{
|
||||||
|
cmess1 << " o Assign Layer (no global vertical metal2)." << endl;
|
||||||
|
|
||||||
|
for ( Net* net : getCell()->getNets() ) {
|
||||||
|
DebugSession::open( net, 145, 150 );
|
||||||
|
|
||||||
|
NetRoutingState* state = NetRoutingExtension::get( net );
|
||||||
|
if (not state or state->isAutomaticGlobalRoute()) {
|
||||||
|
_layerAssignNoGlobalM2V( net, globalNets, total, global );
|
||||||
|
} else {
|
||||||
|
cdebug_log(145,0) << net << " is not automatic routed, skipped." << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugSession::close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#if THIS_IS_DISABLED
|
#if THIS_IS_DISABLED
|
||||||
void AnabaticEngine::moveULeft ( AutoSegment* seed, set<Net*>& globalNets, GCell::Set& invalidateds )
|
void AnabaticEngine::moveULeft ( AutoSegment* seed, set<Net*>& globalNets, GCell::Set& invalidateds )
|
||||||
{
|
{
|
||||||
|
@ -488,6 +601,7 @@ namespace Anabatic {
|
||||||
switch ( method ) {
|
switch ( method ) {
|
||||||
case EngineLayerAssignByLength: _layerAssignByLength ( total, global, globalNets ); break;
|
case EngineLayerAssignByLength: _layerAssignByLength ( total, global, globalNets ); break;
|
||||||
case EngineLayerAssignByTrunk: _layerAssignByTrunk ( total, global, globalNets ); break;
|
case EngineLayerAssignByTrunk: _layerAssignByTrunk ( total, global, globalNets ); break;
|
||||||
|
case EngineLayerAssignNoGlobalM2V: _layerAssignNoGlobalM2V ( total, global, globalNets ); break;
|
||||||
case EngineNoNetLayerAssign: break;
|
case EngineNoNetLayerAssign: break;
|
||||||
default:
|
default:
|
||||||
stopMeasures();
|
stopMeasures();
|
||||||
|
|
|
@ -79,7 +79,6 @@ namespace Anabatic {
|
||||||
|
|
||||||
Point sourcePosition;
|
Point sourcePosition;
|
||||||
Point targetPosition;
|
Point targetPosition;
|
||||||
Net* net = rp->getNet();
|
|
||||||
const Layer* rpLayer = rp->getLayer();
|
const Layer* rpLayer = rp->getLayer();
|
||||||
size_t rpDepth = Session::getLayerDepth( rp->getLayer() );
|
size_t rpDepth = Session::getLayerDepth( rp->getLayer() );
|
||||||
Flags direction = Session::getDirection ( rpDepth );
|
Flags direction = Session::getDirection ( rpDepth );
|
||||||
|
|
|
@ -75,6 +75,7 @@ extern "C" {
|
||||||
LoadObjectConstant( dictionnary,EngineLoadGrByGCell ,"EngineLoadGrByGCell" );
|
LoadObjectConstant( dictionnary,EngineLoadGrByGCell ,"EngineLoadGrByGCell" );
|
||||||
LoadObjectConstant( dictionnary,EngineLayerAssignByLength ,"EngineLayerAssignByLength" );
|
LoadObjectConstant( dictionnary,EngineLayerAssignByLength ,"EngineLayerAssignByLength" );
|
||||||
LoadObjectConstant( dictionnary,EngineLayerAssignByTrunk ,"EngineLayerAssignByTrunk" );
|
LoadObjectConstant( dictionnary,EngineLayerAssignByTrunk ,"EngineLayerAssignByTrunk" );
|
||||||
|
LoadObjectConstant( dictionnary,EngineLayerAssignNoGlobalM2V,"EngineLayerAssignNoGlobalM2V" );
|
||||||
LoadObjectConstant( dictionnary,EngineNoNetLayerAssign ,"EngineNoNetLayerAssign" );
|
LoadObjectConstant( dictionnary,EngineNoNetLayerAssign ,"EngineNoNetLayerAssign" );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -267,6 +267,8 @@ namespace Anabatic {
|
||||||
void _layerAssignByLength ( Net*, unsigned long& total, unsigned long& global, set<Net*>& );
|
void _layerAssignByLength ( Net*, unsigned long& total, unsigned long& global, set<Net*>& );
|
||||||
void _layerAssignByTrunk ( unsigned long& total, unsigned long& global, set<Net*>& );
|
void _layerAssignByTrunk ( unsigned long& total, unsigned long& global, set<Net*>& );
|
||||||
void _layerAssignByTrunk ( Net*, set<Net*>&, unsigned long& total, unsigned long& global );
|
void _layerAssignByTrunk ( Net*, set<Net*>&, unsigned long& total, unsigned long& global );
|
||||||
|
void _layerAssignNoGlobalM2V ( unsigned long& total, unsigned long& global, set<Net*>& );
|
||||||
|
void _layerAssignNoGlobalM2V ( Net*, set<Net*>&, unsigned long& total, unsigned long& global );
|
||||||
void _saveNet ( Net* );
|
void _saveNet ( Net* );
|
||||||
void _destroyAutoContacts ();
|
void _destroyAutoContacts ();
|
||||||
void _destroyAutoSegments ();
|
void _destroyAutoSegments ();
|
||||||
|
|
|
@ -126,7 +126,8 @@ namespace Anabatic {
|
||||||
, EngineLoadGrByGCell = (1 << 1)
|
, EngineLoadGrByGCell = (1 << 1)
|
||||||
, EngineLayerAssignByLength = (1 << 2)
|
, EngineLayerAssignByLength = (1 << 2)
|
||||||
, EngineLayerAssignByTrunk = (1 << 3)
|
, EngineLayerAssignByTrunk = (1 << 3)
|
||||||
, EngineNoNetLayerAssign = (1 << 4)
|
, EngineLayerAssignNoGlobalM2V = (1 << 4)
|
||||||
|
, EngineNoNetLayerAssign = (1 << 5)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -188,9 +188,20 @@ namespace Katana {
|
||||||
track = perpandiculars[i]->getTrack();
|
track = perpandiculars[i]->getTrack();
|
||||||
if (not track) {
|
if (not track) {
|
||||||
// The perpandicular is not placed yet.
|
// The perpandicular is not placed yet.
|
||||||
|
if (perpandiculars[i]->isFixedAxis()) {
|
||||||
|
RoutingPlane* plane = Session::getKatanaEngine()->getRoutingPlaneByLayer(perpandiculars[i]->getLayer());
|
||||||
|
Track* track = plane->getTrackByPosition( perpandiculars[i]->getAxis() );
|
||||||
|
if (track) {
|
||||||
|
TrackElement* other = track->getSegment( _segment->getAxis() );
|
||||||
|
if (other and (other->getNet() != _segment->getNet()) ) {
|
||||||
|
_fsm.addAction( other, SegmentAction::OtherRipup );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
if (flags & Manipulator::PerpandicularsFirst) {
|
if (flags & Manipulator::PerpandicularsFirst) {
|
||||||
_fsm.addAction( perpandiculars[i], perpandicularActionFlags );
|
_fsm.addAction( perpandiculars[i], perpandicularActionFlags );
|
||||||
}
|
}
|
||||||
|
}
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -909,6 +909,11 @@ namespace Katana {
|
||||||
|
|
||||||
for ( ; (begin < end) ; ++begin ) {
|
for ( ; (begin < end) ; ++begin ) {
|
||||||
other = track->getSegment( begin );
|
other = track->getSegment( begin );
|
||||||
|
otherIsGlobal = otherIsGlobal
|
||||||
|
or other->isGlobal()
|
||||||
|
or other->isBlockage()
|
||||||
|
or other->isFixed()
|
||||||
|
or other->isFixedAxis();
|
||||||
|
|
||||||
if (other->getNet() == segment->getNet()) {
|
if (other->getNet() == segment->getNet()) {
|
||||||
cdebug_log(159,0) << " | " << begin << " Same net: " << " " << other << endl;
|
cdebug_log(159,0) << " | " << begin << " Same net: " << " " << other << endl;
|
||||||
|
@ -935,7 +940,7 @@ namespace Katana {
|
||||||
otherIsGlobal = other->isGlobal() or other->isBlockage() or other->isFixed();
|
otherIsGlobal = other->isGlobal() or other->isBlockage() or other->isFixed();
|
||||||
} else {
|
} else {
|
||||||
otherOverlap.merge(other->getCanonicalInterval());
|
otherOverlap.merge(other->getCanonicalInterval());
|
||||||
otherIsGlobal = otherIsGlobal or other->isGlobal() or other->isBlockage() or other->isFixed();
|
otherIsGlobal = otherIsGlobal or other->isGlobal() or other->isBlockage() or other->isFixed() or other->isFixedAxis();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (not otherOverlap.isEmpty()) {
|
if (not otherOverlap.isEmpty()) {
|
||||||
|
|
Loading…
Reference in New Issue