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:
Jean-Paul Chaput 2018-06-11 16:44:26 +02:00
parent 2077a19bec
commit e88b2050c2
8 changed files with 269 additions and 136 deletions

View File

@ -1636,11 +1636,11 @@ namespace Anabatic {
getGCells( gcells );
for ( size_t i=0 ; i<gcells.size() ; ++i ) {
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)) {
cdebug_tabw(159,-1);
cdebug_tabw(149,-1);
return;
}

View File

@ -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
void AnabaticEngine::moveULeft ( AutoSegment* seed, set<Net*>& globalNets, GCell::Set& invalidateds )
{
@ -486,8 +599,9 @@ namespace Anabatic {
if (Session::getAllowedDepth() >= 3) {
switch ( method ) {
case EngineLayerAssignByLength: _layerAssignByLength( total, global, globalNets ); break;
case EngineLayerAssignByLength: _layerAssignByLength ( total, global, globalNets ); break;
case EngineLayerAssignByTrunk: _layerAssignByTrunk ( total, global, globalNets ); break;
case EngineLayerAssignNoGlobalM2V: _layerAssignNoGlobalM2V ( total, global, globalNets ); break;
case EngineNoNetLayerAssign: break;
default:
stopMeasures();

View File

@ -79,7 +79,6 @@ namespace Anabatic {
Point sourcePosition;
Point targetPosition;
Net* net = rp->getNet();
const Layer* rpLayer = rp->getLayer();
size_t rpDepth = Session::getLayerDepth( rp->getLayer() );
Flags direction = Session::getDirection ( rpDepth );

View File

@ -73,8 +73,9 @@ extern "C" {
LoadObjectConstant( dictionnary,EngineLoadGrByNet ,"EngineLoadGrByNet" );
LoadObjectConstant( dictionnary,EngineLoadGrByGCell ,"EngineLoadGrByGCell" );
LoadObjectConstant( dictionnary,EngineLayerAssignByLength,"EngineLayerAssignByLength" );
LoadObjectConstant( dictionnary,EngineLayerAssignByLength ,"EngineLayerAssignByLength" );
LoadObjectConstant( dictionnary,EngineLayerAssignByTrunk ,"EngineLayerAssignByTrunk" );
LoadObjectConstant( dictionnary,EngineLayerAssignNoGlobalM2V,"EngineLayerAssignNoGlobalM2V" );
LoadObjectConstant( dictionnary,EngineNoNetLayerAssign ,"EngineNoNetLayerAssign" );
}

View File

@ -267,6 +267,8 @@ namespace Anabatic {
void _layerAssignByLength ( Net*, 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 _layerAssignNoGlobalM2V ( unsigned long& total, unsigned long& global, set<Net*>& );
void _layerAssignNoGlobalM2V ( Net*, set<Net*>&, unsigned long& total, unsigned long& global );
void _saveNet ( Net* );
void _destroyAutoContacts ();
void _destroyAutoSegments ();

View File

@ -126,7 +126,8 @@ namespace Anabatic {
, EngineLoadGrByGCell = (1 << 1)
, EngineLayerAssignByLength = (1 << 2)
, EngineLayerAssignByTrunk = (1 << 3)
, EngineNoNetLayerAssign = (1 << 4)
, EngineLayerAssignNoGlobalM2V = (1 << 4)
, EngineNoNetLayerAssign = (1 << 5)
};

View File

@ -188,9 +188,20 @@ namespace Katana {
track = perpandiculars[i]->getTrack();
if (not track) {
// 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) {
_fsm.addAction( perpandiculars[i], perpandicularActionFlags );
}
}
continue;
}

View File

@ -909,6 +909,11 @@ namespace Katana {
for ( ; (begin < end) ; ++begin ) {
other = track->getSegment( begin );
otherIsGlobal = otherIsGlobal
or other->isGlobal()
or other->isBlockage()
or other->isFixed()
or other->isFixedAxis();
if (other->getNet() == segment->getNet()) {
cdebug_log(159,0) << " | " << begin << " Same net: " << " " << other << endl;
@ -935,7 +940,7 @@ namespace Katana {
otherIsGlobal = other->isGlobal() or other->isBlockage() or other->isFixed();
} else {
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()) {