373 lines
13 KiB
C++
373 lines
13 KiB
C++
|
|
// -*- C++ -*-
|
|
//
|
|
// This file is part of the Coriolis Software.
|
|
// Copyright (c) UPMC/LIP6 2008-2008, All Rights Reserved
|
|
//
|
|
// ===================================================================
|
|
//
|
|
// $Id$
|
|
//
|
|
// x-----------------------------------------------------------------x
|
|
// | |
|
|
// | C O R I O L I S |
|
|
// | K a t a b a t i c - Routing Toolbox |
|
|
// | |
|
|
// | Author : Jean-Paul CHAPUT |
|
|
// | E-mail : Jean-Paul.Chaput@asim.lip6.fr |
|
|
// | =============================================================== |
|
|
// | C++ Module : "./NetConstraints.cpp" |
|
|
// | *************************************************************** |
|
|
// | U p d a t e s |
|
|
// | |
|
|
// x-----------------------------------------------------------------x
|
|
|
|
|
|
#include <cstdlib>
|
|
#include <sstream>
|
|
|
|
#include "hurricane/DebugSession.h"
|
|
#include "hurricane/BasicLayer.h"
|
|
#include "hurricane/Net.h"
|
|
#include "hurricane/NetExternalComponents.h"
|
|
#include "hurricane/RoutingPad.h"
|
|
#include "hurricane/Pad.h"
|
|
#include "hurricane/Plug.h"
|
|
#include "hurricane/Instance.h"
|
|
#include "hurricane/Vertical.h"
|
|
#include "hurricane/Horizontal.h"
|
|
#include "hurricane/Cell.h"
|
|
|
|
#include "katabatic/AutoContact.h"
|
|
#include "katabatic/AutoSegment.h"
|
|
#include "katabatic/Session.h"
|
|
#include "katabatic/KatabaticEngine.h"
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
//! \addtogroup NetConstraints
|
|
//! \{
|
|
|
|
/*! \function void propagateConstraintFromRp ( RoutingPad* rp )
|
|
* \param rp The \c RoutingPad starting point.
|
|
*
|
|
* Do a full constraint propagation starting from this \c RoutingPad.
|
|
*/
|
|
|
|
/*! \function void propagateConstraint ( AutoContactStack& segmentStack, DbU::Unit constraintMin, DbU::Unit constraintMax, unsigned int direction )
|
|
* \param segmentStack A vector of \c AutoSegment.
|
|
* \param constraintMin The interval lower bound.
|
|
* \param constraintMax The interval upper bound.
|
|
* \param direction The propagation direction.
|
|
*
|
|
* Propagate the constraint in the appropriate direction through the vector
|
|
* of \c AutoSegments and any other linked through collapse.
|
|
*/
|
|
|
|
//! \}
|
|
|
|
|
|
using namespace std;
|
|
using namespace CRL;
|
|
using namespace Hurricane;
|
|
using namespace Katabatic;
|
|
|
|
|
|
// -----------------------------------------------------------------
|
|
// Local Functions.
|
|
|
|
|
|
void propagateConstraint ( AutoContactStack& segmentStack
|
|
, DbU::Unit constraintMin
|
|
, DbU::Unit constraintMax
|
|
, unsigned int direction
|
|
, set<AutoSegment*>& faileds
|
|
)
|
|
{
|
|
ltracein(99);
|
|
|
|
while ( !segmentStack.isEmpty() ) {
|
|
AutoContact* sourceContact = segmentStack.getAutoContact ();
|
|
Segment* sourceSegment = segmentStack.getSegment ();
|
|
AutoSegment* sourceAutoSegment = Session::lookup ( sourceSegment );
|
|
|
|
segmentStack.pop ();
|
|
|
|
if ( sourceContact->isAlignate(direction) ) {
|
|
ltrace(99) << "Apply to (source): " << (void*)sourceContact->base() << ":" << sourceContact << endl;
|
|
if ( not sourceContact->restrictConstraintBox(constraintMin,constraintMax,direction,false) )
|
|
faileds.insert ( sourceAutoSegment );
|
|
}
|
|
|
|
|
|
forEach ( Component*, icomponent, sourceContact->getSlaveComponents() ) {
|
|
if ( *icomponent == sourceSegment ) continue;
|
|
|
|
Segment* targetSegment = dynamic_cast<Segment*>(*icomponent);
|
|
if ( !targetSegment ) continue;
|
|
|
|
AutoSegment* targetAutoSegment = Session::lookup ( targetSegment );
|
|
if ( !targetAutoSegment ) {
|
|
const BasicLayer* basicLayer = dynamic_cast<const BasicLayer*>(targetSegment->getLayer());
|
|
if ( basicLayer && basicLayer->getMaterial() != BasicLayer::Material::metal )
|
|
continue;
|
|
|
|
cerr << Error("Can't lookup <AutoSegment> for ",getString(targetSegment).c_str()) << endl;
|
|
continue;
|
|
}
|
|
|
|
AutoContact* targetContact = Session::lookup
|
|
( dynamic_cast<Contact*>(targetAutoSegment->getOppositeAnchor(sourceContact->base())) );
|
|
|
|
if ( sourceAutoSegment and targetAutoSegment ) {
|
|
unsigned int state = AutoSegment::getPerpandicularState
|
|
( sourceContact
|
|
, sourceAutoSegment
|
|
, targetAutoSegment
|
|
, (direction & Constant::Horizontal)?true:false
|
|
);
|
|
|
|
if ( !( state & (AutoSegment::PerpandicularIndirect
|
|
|AutoSegment::ParallelOrExpanded
|
|
|AutoSegment::ParallelAndLayerChange )) ) {
|
|
segmentStack.push ( targetContact, targetSegment );
|
|
|
|
if ( targetAutoSegment
|
|
&& (targetAutoSegment->getDirection() == direction)
|
|
&& targetContact->isAlignate(direction) ) {
|
|
ltrace(99) << "Apply to (target): " << (void*)targetContact->base() << ":" << targetContact << endl;
|
|
if ( not targetContact->restrictConstraintBox(constraintMin,constraintMax,direction,false) )
|
|
faileds.insert ( targetAutoSegment );
|
|
}
|
|
continue;
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
ltraceout(99);
|
|
ltrace(99) << "Finished propagating." << endl;
|
|
}
|
|
|
|
|
|
void propagateConstraintFromRp ( RoutingPad* rp, set<AutoSegment*>& faileds )
|
|
{
|
|
ltrace(99) << "propagateConstraintFromRp() - " << (void*)rp << " " << rp << endl;
|
|
|
|
forEach ( Component*, icomponent, rp->getSlaveComponents() ) {
|
|
ltrace(99) << "slave: " << *icomponent << endl;
|
|
AutoContact* contact = Session::lookup ( dynamic_cast<Contact*>(*icomponent) );
|
|
if ( contact ) {
|
|
ltrace(99) << "Start slave: " << (void*)contact->getContact() << ":" << contact << endl;
|
|
|
|
set<AutoContact*> collapsedContactsSet;
|
|
AutoContactStack collapsedContactsStack;
|
|
AutoContactStack verticalSegmentsStack;
|
|
AutoContactStack horizontalSegmentsStack;
|
|
|
|
collapsedContactsStack.push ( contact, NULL );
|
|
collapsedContactsSet.insert ( contact );
|
|
|
|
// Find all AutoContacts directly collapeds on the RoutingPad.
|
|
while ( !collapsedContactsStack.isEmpty() ) {
|
|
AutoContact* sourceContact = collapsedContactsStack.getAutoContact ();
|
|
Segment* sourceSegment = collapsedContactsStack.getSegment ();
|
|
Segment* segment;
|
|
|
|
collapsedContactsStack.pop ();
|
|
|
|
forEach ( Component*, icomponent2, sourceContact->getSlaveComponents() ) {
|
|
bool isHorizontal = true;
|
|
segment = dynamic_cast<Horizontal*>(*icomponent2);
|
|
if ( !segment && (segment = dynamic_cast<Vertical*>(*icomponent2)) )
|
|
isHorizontal = false;
|
|
if ( !segment || (segment == sourceSegment) ) continue;
|
|
|
|
AutoSegment* autoSegment = Session::lookup ( segment );
|
|
if ( !autoSegment ) {
|
|
const BasicLayer* basicLayer = dynamic_cast<const BasicLayer*>(segment->getLayer());
|
|
if ( basicLayer && basicLayer->getMaterial() != BasicLayer::Material::metal )
|
|
continue;
|
|
cerr << Error("Can't lookup <AutoSegment> for %s.",getString(segment).c_str()) << endl;
|
|
continue;
|
|
}
|
|
|
|
ltrace(99) << "Examining: " << autoSegment << endl;
|
|
|
|
AutoContact* targetContact = Session::lookup
|
|
( dynamic_cast<Contact*>(autoSegment->getOppositeAnchor(sourceContact->base())) );
|
|
|
|
if ( targetContact ) {
|
|
if ( !autoSegment->isCollapsed() ) {
|
|
if ( isHorizontal ) {
|
|
ltrace(99) << "On horizontal stack " << (void*)segment << ":" << segment << endl;
|
|
horizontalSegmentsStack.push ( targetContact, segment );
|
|
} else {
|
|
ltrace(99) << "On vertical stack " << (void*)segment << ":" << segment << endl;
|
|
verticalSegmentsStack.push ( targetContact, segment );
|
|
}
|
|
} else {
|
|
ltrace(99) << "On collapsed stack " << (void*)segment << ":" << segment << endl;
|
|
collapsedContactsStack.push ( targetContact, segment );
|
|
collapsedContactsSet.insert ( targetContact );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// compute constraint on all AutoContacts collapseds,
|
|
// then sets all the constraint Box to the intersection.
|
|
ltrace(99) << "Computing constraint:" << endl;
|
|
ltracein(99);
|
|
set<AutoContact*>::iterator it = collapsedContactsSet.begin();
|
|
set<AutoContact*>::iterator end = collapsedContactsSet.end();
|
|
ltrace(99) << *it << " " << (*it)->getConstraintBox() << endl;
|
|
Box constraintBox = (*it++)->getConstraintBox ();
|
|
for ( ; it != end ; it++ ) {
|
|
(*it)->intersectConstraintBox ( constraintBox );
|
|
ltrace(99) << *it << " " << constraintBox << endl;
|
|
}
|
|
|
|
if ( constraintBox.isEmpty() ) {
|
|
cerr << "[ERROR] incompatible segment collapse for " << rp << endl;
|
|
ltraceout(99);
|
|
break;
|
|
}
|
|
ltraceout(99);
|
|
|
|
ltrace(99) << "Applying constraint " << constraintBox << " to:" << endl;
|
|
ltracein(99);
|
|
it = collapsedContactsSet.begin();
|
|
for ( ; it != end ; it++ ) {
|
|
ltrace(99) << *it << endl;
|
|
(*it)->setConstraintBox ( constraintBox );
|
|
}
|
|
ltraceout(99);
|
|
|
|
// Propagate constraint through horizontally bound segments.
|
|
ltrace(99) << "Propagate constraint on horizontal segments" << endl;
|
|
propagateConstraint ( horizontalSegmentsStack
|
|
, constraintBox.getYMin()
|
|
, constraintBox.getYMax()
|
|
, Constant::Horizontal
|
|
, faileds );
|
|
|
|
// Propagate constraint through vertically bound segments.
|
|
ltrace(99) << "Propagate constraint on vertical segments" << endl;
|
|
propagateConstraint ( verticalSegmentsStack
|
|
, constraintBox.getXMin()
|
|
, constraintBox.getXMax()
|
|
, Constant::Vertical
|
|
, faileds );
|
|
}
|
|
}
|
|
|
|
ltrace(99) << "propagateConstraintFromRp() - Exit" << endl;
|
|
}
|
|
|
|
|
|
} // End of local namespace.
|
|
|
|
|
|
|
|
|
|
namespace Katabatic {
|
|
|
|
|
|
using Hurricane::Cell;
|
|
|
|
|
|
void KatabaticEngine::_computeNetConstraints ( Net* net, set<AutoSegment*>& faileds )
|
|
{
|
|
DebugSession::open ( net );
|
|
|
|
ltrace(100) << "Katabatic::_computeNetConstraints ( " << net << " )" << endl;
|
|
ltracein(99);
|
|
|
|
//cmess2 << " - " << net << endl;
|
|
|
|
vector<RoutingPad*> routingPads;
|
|
forEach ( Component*, icomponent, net->getComponents() ) {
|
|
Contact* contact = dynamic_cast<Contact*>(*icomponent);
|
|
if ( contact ) {
|
|
AutoContact* autoContact = Session::lookup ( contact );
|
|
if ( autoContact )
|
|
autoContact->restoreNativeConstraintBox ();
|
|
} else {
|
|
RoutingPad* routingPad = dynamic_cast<RoutingPad*>(*icomponent);
|
|
if ( routingPad ) routingPads.push_back ( routingPad );
|
|
}
|
|
}
|
|
|
|
for ( size_t i=0 ; i<routingPads.size() ; i++ )
|
|
propagateConstraintFromRp ( routingPads[i], faileds );
|
|
|
|
set<AutoSegment*> processeds;
|
|
forEach ( Segment*, isegment, net->getSegments() ) {
|
|
AutoSegment* autoSegment = Session::lookup ( *isegment );
|
|
if ( !autoSegment ) continue;
|
|
autoSegment->toConstraintAxis ( &processeds );
|
|
}
|
|
|
|
ltraceout(99);
|
|
|
|
DebugSession::close ();
|
|
}
|
|
|
|
|
|
void KatabaticEngine::_collapseNets ( Nets nets, unsigned int depth )
|
|
{
|
|
forEach ( Net*, inet, nets )
|
|
_collapseNet ( *inet, depth );
|
|
}
|
|
|
|
|
|
void KatabaticEngine::_collapseNet ( const Name& name, unsigned int depth )
|
|
{
|
|
Net* net = getCell()->getNet ( name );
|
|
|
|
if ( !net ) {
|
|
cerr << Error("No net %s in %s"
|
|
,getString(name).c_str()
|
|
,getString(getCell()).c_str()) << endl;
|
|
return;
|
|
}
|
|
|
|
_collapseNet ( net );
|
|
}
|
|
|
|
|
|
void KatabaticEngine::_collapseNet ( Net* net, unsigned int depth )
|
|
{
|
|
ltrace(100) << "Katabatic::_collapseNet ( " << net << " )" << endl;
|
|
ltracein(99);
|
|
|
|
forEach ( Component*, icomponent, net->getComponents() ) {
|
|
RoutingPad* routingPad = dynamic_cast<RoutingPad*>(*icomponent);
|
|
if ( routingPad ) {
|
|
ltrace(99) << "RoutingPad " << routingPad << endl;
|
|
forEach ( Component*, islaveComponent, routingPad->getSlaveComponents() ) {
|
|
ltrace(99) << "SlaveComponent " << *islaveComponent << endl;
|
|
Segment* segment = dynamic_cast<Segment*>(*islaveComponent);
|
|
if ( segment ) {
|
|
AutoSegment* autoSegment = Session::lookup ( segment );
|
|
if ( !autoSegment ) continue;
|
|
|
|
if ( autoSegment->isLocal() ) {
|
|
ltrace(99) << "Collapsing " << autoSegment << endl;
|
|
autoSegment->collapse ();
|
|
}
|
|
}
|
|
} // islaveComponent.
|
|
}
|
|
} // icomponent.
|
|
|
|
ltraceout(99);
|
|
}
|
|
|
|
|
|
} // End of Katabatic namespace.
|