coriolis/kite/src/PreProcess.cpp

320 lines
12 KiB
C++

// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved
//
// ===================================================================
//
// $Id$
//
// x-----------------------------------------------------------------x
// | |
// | C O R I O L I S |
// | K i t e - D e t a i l e d R o u t e r |
// | |
// | Author : Jean-Paul CHAPUT |
// | E-mail : Jean-Paul.Chaput@asim.lip6.fr |
// | =============================================================== |
// | C++ Module : "./PreProcess.cpp" |
// | *************************************************************** |
// | U p d a t e s |
// | |
// x-----------------------------------------------------------------x
#include <sstream>
#include "hurricane/Bug.h"
#include "hurricane/Warning.h"
#include "hurricane/Net.h"
#include "hurricane/Name.h"
#include "hurricane/RoutingPad.h"
#include "katabatic/AutoContact.h"
#include "kite/GCell.h"
#include "kite/DataNegociate.h"
#include "kite/TrackElement.h"
#include "kite/Track.h"
#include "kite/RoutingPlane.h"
#include "kite/Session.h"
#include "kite/KiteEngine.h"
namespace {
using namespace std;
using namespace Hurricane;
using namespace CRL;
using namespace Kite;
void getPerpandiculars ( TrackElement* segment
, AutoContact* from
, unsigned int direction
, vector<TrackElement*>& perpandiculars
)
{
//AutoContact* to = segment->base()->getAutoSource();
//to = (to != from) ? to : segment->base()->getAutoTarget();
TrackElement* perpandicular;
forEach ( Segment*, isegment, segment->base()->getAutoSource()->getSlaveComponents().getSubSet<Segment*>() ) {
perpandicular = Session::lookup ( *isegment );
ltrace(200) << "S " << perpandicular << endl;
if ( not perpandicular or (perpandicular->getDirection() == direction) ) continue;
perpandiculars.push_back ( perpandicular );
}
forEach ( Segment*, isegment, segment->base()->getAutoTarget()->getSlaveComponents().getSubSet<Segment*>() ) {
perpandicular = Session::lookup ( *isegment );
ltrace(200) << "T " << perpandicular << endl;
if ( not perpandicular or (perpandicular->getDirection() == direction) ) continue;
perpandiculars.push_back ( perpandicular );
}
}
void propagateCagedConstraints ( TrackElement* segment )
{
if ( not segment->isFixed() ) return;
ltrace(200) << "Propagate caging: " << segment << endl;
Track* track = segment->getTrack();
unsigned int direction = Session::getRoutingGauge()->getLayerDirection(segment->getLayer());
AutoContact* source = segment->base()->getAutoSource();
Interval uside = source->getGCell()->getUSide(direction);
DbU::Unit minConstraint = DbU::Min;
DbU::Unit maxConstraint = DbU::Max;
vector<TrackElement*> perpandiculars;
if ( not track ) {
cerr << Bug("%s is not inserted in a <Track>",getString(segment).c_str()) << endl;
return;
}
// Computing constraints from fixed only TrackElements (caging).
TrackElement* parallel;
size_t i = segment->getIndex();
while ( i > 0 ) {
parallel = track->getSegment(--i);
if ( not parallel ) continue;
if ( parallel->getTargetU() < uside.getVMin() ) break;
if ( parallel->getNet() == segment->getNet() ) continue;
if ( not parallel->isFixed() ) continue;
ltrace(200) << "Min Constraint from: " << parallel << endl;
minConstraint = max ( minConstraint, parallel->getTargetU() );
}
i = segment->getIndex();
while ( i < track->getSize()-1 ) {
parallel = track->getSegment(++i);
if ( not parallel ) continue;
if ( parallel->getSourceU() > uside.getVMax() ) break;
if ( parallel->getNet() == segment->getNet() ) continue;
if ( not parallel->isFixed() ) continue;
ltrace(200) << "Max Constraint from: " << parallel << endl;
maxConstraint = min ( maxConstraint, parallel->getSourceU() );
}
if ( minConstraint > maxConstraint ) {
cerr << Bug("%s have too tight caging constraints.",getString(segment).c_str()) << endl;
return;
}
if ( (minConstraint <= uside.getVMin()) and (maxConstraint >= uside.getVMax()) ) {
ltrace(200) << "No constraints [" << DbU::getValueString(minConstraint)
<< ":" << DbU::getValueString(maxConstraint)
<< " vs. " << uside << endl;
return;
}
// Finding perpandiculars, by way of the source & target RoutingPad.
if ( source->getAnchor() ) {
RoutingPad* rp = dynamic_cast<RoutingPad*>(source->getAnchor());
if ( rp ) {
TrackElement* parallel;
forEach ( Segment*, isegment, rp->getSlaveComponents().getSubSet<Segment*>() ) {
parallel = Session::lookup ( *isegment );
ltrace(200) << "* " << parallel << endl;
if ( parallel->isFixed () ) continue;
if ( parallel->isGlobal() ) continue;
getPerpandiculars ( parallel, source, direction, perpandiculars );
getPerpandiculars ( parallel, segment->base()->getAutoTarget(), direction, perpandiculars );
}
} else {
cerr << Bug("%s is not anchored on a <RoutingPad>\n (%s)"
,getString(source).c_str()
,getString(source->getAnchor()).c_str()) << endl;
}
}
// Apply caging constraints to perpandiculars.
ltracein(200);
if ( perpandiculars.size() == 0 ) {
ltrace(200) << "No perpandiculars to " << segment << endl;
}
Interval constraints ( minConstraint, maxConstraint );
for ( size_t iperpand=0 ; iperpand<perpandiculars.size() ; iperpand++ ) {
ltrace(200) << "Caged: " << constraints << " " << perpandiculars[iperpand] << endl;
perpandiculars[iperpand]->base()->mergeUserConstraints ( constraints );
}
ltraceout(200);
}
void freeCagedTerminals ( Track* track )
{
Configuration* configuration = Session::getConfiguration ();
const Layer* metal2 = configuration->getRoutingLayer ( 1 );
const Layer* metal3 = configuration->getRoutingLayer ( 2 );
for ( size_t i=0 ; i<track->getSize() ; i++ ) {
TrackElement* segment = track->getSegment ( i );
if ( segment and segment->isFixed() and segment->isTerminal() ) {
Interval freeInterval = track->getFreeInterval ( segment->getSourceU(), segment->getNet() );
if ( freeInterval.getSize() < DbU::lambda(30.0) ) {
cinfo << "Caged terminal: " << segment << endl;
if ( segment->getLayer() != metal2 ) continue;
if ( segment->getLength() >= DbU::lambda(5.0) ) continue;
AutoContact* support = segment->base()->getAutoSource();
RoutingPad* rp = dynamic_cast<RoutingPad*>(support->getAnchor());
GCell* gcell = Session::lookup ( support->getGCell() );
#if 0
Point point ( segment->base()->getSourceU(), track->getAxis() );
GCell* gcell = Session::lookup ( segment->base()->getAutoSource()->getGCell() );
AutoContact* source = AutoContact::create ( gcell->base(), segment->getNet(), metal3 );
AutoContact* target = AutoContact::create ( gcell->base(), segment->getNet(), metal3 );
source->setPosition ( point );
target->setPosition ( point );
#endif
AutoContact* source = AutoContact::fromRp ( gcell->base()
, rp
, metal3
, rp->getSourcePosition()
, DbU::lambda(1.0), DbU::lambda(1.0)
, true
);
AutoContact* target = AutoContact::fromRp ( gcell->base()
, rp
, metal3
, rp->getSourcePosition()
, DbU::lambda(1.0), DbU::lambda(1.0)
, true
);
AutoSegment* segment = AutoSegment::create ( source
, target
, Constant::Vertical
, AutoSegment::Local
, true
, false
);
segment->setFixed ( true );
GCell::addTrackSegment ( gcell, segment, true );
#if DISABLED
// Force slackening.
bool breakFlag = false;
forEach ( Contact*, icontact, rp->getSlaveComponents().getSubSet<Contact*>() ) {
forEach ( Segment*, isegment, icontact->getSlaveComponents().getSubSet<Segment*>() ) {
TrackElement* trackSegment = Session::lookup(*isegment);
if ( not trackSegment or trackSegment->isFixed() ) continue;
if ( trackSegment->isHorizontal() ) {
ltrace(200) << "M2 to slacken for " << rp << endl;
breakFlag = true;
const vector<AutoSegment*>& dogLegs = Session::getDogLegs();
trackSegment->base()->makeDogLeg ( gcell->base(), true );
GCell::addTrackSegment ( gcell, dogLegs[1], true );
GCell::addTrackSegment ( gcell, dogLegs[2], true );
Session::revalidate ();
}
if ( breakFlag ) break;
}
if ( breakFlag ) break;
}
#endif
}
}
}
}
} // End of local namespace.
namespace Kite {
using Hurricane::Bug;
using Hurricane::Net;
using Hurricane::Name;
void KiteEngine::preProcess ()
{
for ( size_t i=0 ; i<_routingPlanes.size() ; i++ ) {
RoutingPlane* plane = _routingPlanes[i];
Track* track = plane->getTrackByIndex ( 0 );
while ( track ) {
freeCagedTerminals ( track );
track = track->getNext ();
}
}
Session::revalidate ();
}
void KiteEngine::_computeCagedConstraints ()
{
TrackElementLut::iterator isegment = _trackSegmentLut.begin();
for ( ; isegment != _trackSegmentLut.end() ; isegment++ ) {
if ( not isegment->second->isFixed() ) continue;
propagateCagedConstraints ( isegment->second );
}
}
void KiteEngine::_computeCagedConstraints ( Net* net )
{
TrackElement* segment = NULL;
forEach ( Segment*, isegment, net->getComponents().getSubSet<Segment*>() ) {
segment = Session::lookup ( *isegment );
if ( not segment ) continue;
segment->base()->resetUserConstraints();
}
forEach ( Segment*, isegment, net->getComponents().getSubSet<Segment*>() ) {
segment = Session::lookup ( *isegment );
if ( not segment ) continue;
propagateCagedConstraints ( segment );
}
}
} // End of Kite namespace.