Update the channel routing feature to integrate with the OTC P&R.

* Update: In CRL/node600/phenitec/kite.py, update the routing gauge to
    the new format. So now we can use again SxLib-2M (channel routing
    SxLib for two metal technologies).
* Change: In CRL::BlifParser, if a master cell is not found in the
    AllianceFramework, then try in the Blif supplied libraries.
    This is used to load the zero, one and tie cells.
      Add a Blif::getCell() static function to look into the Blif
    supplied libraries.
* Change: In CRL::LefImport, sometimes there can be discrepencies between
    the LEF ROUTING layers and the Coriolis routing gauge. Now ignore
    routing layers that are *not* presents in the Coriolis gauge.

* Change: In AnabaticEngine, moved routingMode attribute from KatanaEngine,
    as some setup operations needs it.
* Change: In AutoSegment::canReduce(), allow fixed segments to be reduced
    if they are "jumpers" (turn+turn and top+top or bot+bot).
      This case arise on the edge of routing channels for fixed wires
    to connect terminals.
* Change: In AutoSegment::getTopologicalinfos(), compute differently the
    (leftBound,rightBound) interval when in channel mode.
       In over-the-cell mode, this interval is the one of the whole
    GCells under the wire. In channel mode, for fixed wires (that is,
    verticals connecteds to cells) this interval is reduced to half
    the GCell height, on the connected side of said channel.
      This allows Manipulator::_insertToTrack() to issue disantangling
    requests (push left/push right) for fixed segments that are face
    to face in the channel.
* Change: In Anabatic::Configuration CTOR, allow the cellGauge to have a
    different name from the routingGauge. Now if the cell gauge that
    should match the routing gauge is not found, fallback to the
    name set in "anabatic.cellGauge" parameter.
      Case occur when we try to match with CORE sites from LEF files.
* Change: In Etesian::Configuration CTOR, same change as in the
    Anabatic configuration.
* Change: In Anabatic::GCell::updateDensity(), never set the GoStraight
    flag in channel mode. This flag makes sense when there is at least
    4 routing layers (so we have 2 contiguous free of blockages).
* Bug: In Anabatic::Session::_getNearestGridpoint(), sometimes the nearest on
    grid point is outside the constraint box. Now force the point
    to remains inside constraints even if offgrid.

* Change: In Katana::DataNegociate::update(), perpandiculars that are
    either reduced or in non-preferred routing direction should not
    trigger a bug message.
* Change: In KatanaEngine::_check(), do not check for fixed, horizontal
    non-prefs AutoSegments in channel mode (avoid false bug display).
* Bug: In Manipulator::_forceToTrack(), slighty shrink (-1) the interval
    to free. The intersection function of intervals returns true when
    the two intervals *exactly* touches (1.vMax == 2.vMin). But in
    this specific case, they are not *overlapping* and no action
    should be taken...
* Bug: In Manipulator::_insertInTrack(), do not reject the track when
    we are overlapping a fixed vertical segment in channel mode.
    (Hmm, maybe already corrected by the previous one).
* Change: In Katana::NegociateOverlapCost(), in channel mode, do
    not put two overlaping vertical fixed segments into infinite cost.
    This happens when two cell connected verticals are face to face in
    a channel. We want them negociated the track (by shrinking their
    length) instead of excluding it right away.
* Change: In NegociateWindow::createTrackSegment(), in channel mode,
    do not attempt to create a track segment over a fixed and reduced
    AutoSegment.
      Do not attempt to put a non-preferred AutoSegment on a Track
    either.
* Bug: In RoutingEvent::revalidate(), the number of availables tracks
    was badly computed when in the pure constraint case, when there
    was only one it was reporting zero.
* Change: In TrackElements::TrackElements_Perpandicular::Locator,
    do not issue a bug when an non-pref or reduced AutoSegment do not
    have an associated TrackElement.
* Change: In TrackSegmentCost::update(), do not issue a bug when a
    perpandicular is reduded or non-pref and do not have a TrackElement.
This commit is contained in:
Jean-Paul Chaput 2022-10-22 16:39:22 +02:00
parent 9594476ab6
commit a6f61c1044
29 changed files with 264 additions and 119 deletions

View File

@ -376,6 +376,7 @@ namespace Anabatic {
, _viewer (NULL)
, _flags (Flags::DestroyBaseContact)
, _stamp (-1)
, _routingMode (DigitalMode)
, _densityMode (MaxDensity)
, _autoSegmentLut ()
, _autoContactLut ()

View File

@ -503,6 +503,9 @@ namespace Anabatic {
AutoContact* opposite = _segment->getOppositeAnchor(this);
AutoSegment* perpandicular = opposite->getPerpandicular( _segment );
if (perpandicular) {
cdebug_log(145,0) << "Draging V interval ["
<< DbU::getValueString(getCBYMin()) << " "
<< DbU::getValueString(getCBYMax()) << "]" << endl;
DbU::Unit y = perpandicular->getAxis();
y = std::min( y, getCBYMax() );
y = std::max( y, getCBYMin() );

View File

@ -466,8 +466,10 @@ namespace Anabatic {
bool isVertical = (depth == 0) or (Session::getLayerGauge(depth)->isVertical());
uint32_t flags = (isVertical) ? Layer::EnclosureV : Layer::EnclosureH ;
//cerr << depth << ":" << Session::getLayerGauge(depth)->getLayer()->getName()
// << " isVertical:" << Session::getLayerGauge(depth)->isVertical() << endl;
// cerr << depth << ":" << Session::getLayerGauge(depth)->getLayer()->getName()
// << " isVertical:" << Session::getLayerGauge(depth)->isVertical() << endl;
// cerr << " minimalSpacing: "
// << DbU::getValueString( Session::getLayerGauge(depth)->getLayer()->getMinimalSpacing() ) << endl;
*viaToSameCap = Session::getPWireWidth(depth)/2;
@ -492,12 +494,12 @@ namespace Anabatic {
*minimalLength += twoGrid - modulo;
}
//cerr << " viaToTop width: " << DbU::getValueString( Session::getViaWidth(depth) ) << endl;
//cerr << " viaToTopCap: " << DbU::getValueString(*viaToTopCap ) << endl;
//if (depth > 0)
// cerr << " viaToBottom width:" << DbU::getValueString( Session::getViaWidth(depth-1)/2 ) << endl;
//cerr << " viaToBottomCap: " << DbU::getValueString(*viaToBottomCap) << endl;
//cerr << " viaToSameCap: " << DbU::getValueString(*viaToSameCap ) << endl;
// cerr << " viaToTop width: " << DbU::getValueString( Session::getViaWidth(depth) ) << endl;
// cerr << " viaToTopCap: " << DbU::getValueString(*viaToTopCap ) << endl;
// if (depth > 0)
// cerr << " viaToBottom width:" << DbU::getValueString( Session::getViaWidth(depth-1)/2 ) << endl;
// cerr << " viaToBottomCap: " << DbU::getValueString(*viaToBottomCap) << endl;
// cerr << " viaToSameCap: " << DbU::getValueString(*viaToSameCap ) << endl;
_extensionCaps.push_back( std::array<DbU::Unit*,4>( {{ viaToTopCap
, viaToBottomCap
@ -1794,14 +1796,21 @@ namespace Anabatic {
DbU::Unit length = getAnchoredLength();
if (isGlobal() and (length > getPPitch())) return false;
if (isDrag() or isFixed()) return false;
if (isDrag()) return false;
if (not isSpinTopOrBottom()) return false;
if ((getDepth() == 1) and isSpinBottom()) return false;
if ((flags & Flags::WithPerpands) and _reduceds) return false;
AutoContact* source = getAutoSource();
AutoContact* target = getAutoTarget();
if (isFixed()) {
if (isSpinTopOrBottom() and source->isTurn() and target->isTurn())
return true;
return false;
}
if ((getDepth() == 1) and isSpinBottom()) return false;
if ((flags & Flags::WithPerpands) and _reduceds) return false;
cdebug_log(159,0) << " source:" << source->isHTee() << "+" << source->isVTee() << endl;
cdebug_log(159,0) << " target:" << target->isHTee() << "+" << target->isVTee() << endl;
@ -3214,6 +3223,9 @@ namespace Anabatic {
{
cdebug_log(145,1) << "getTopologicalInfos() - " << seed << endl;
bool isSourceBoundToChannel = false;
bool isTargetBoundToChannel = false;
leftBound = DbU::Max;
rightBound = DbU::Min;
@ -3271,10 +3283,19 @@ namespace Anabatic {
Flags perpandFlags = (currentSegment->getAutoSource() == sourceContact)
? Flags::Source : Flags::Target;
perpandiculars.push_back( make_tuple( currentSegment, perpandFlags ));
if (Session::getAnabatic()->isChannelMode()) {
if (currentSegment->isNonPref() and currentSegment->isFixed()) {
if (perpandFlags & Flags::Source) isSourceBoundToChannel = true;
else isTargetBoundToChannel = true;
}
}
}
}
}
if (isSourceBoundToChannel) rightBound -= (leftBound + rightBound)/2;
if (isTargetBoundToChannel) leftBound += (leftBound + rightBound)/2;
cdebug_tabw(145,-1);
}

View File

@ -97,17 +97,22 @@ namespace Anabatic {
GCell::setDisplayMode( Cfg::getParamEnumerate("anabatic.gcell.displayMode", GCell::Boundary)->asInt() );
string gaugeName = Cfg::getParamString("anabatic.routingGauge","sxlib")->asString();
if (cg == NULL) {
if (not cg)
cg = AllianceFramework::get()->getCellGauge( gaugeName );
if (cg == NULL)
throw Error( "AnabaticEngine::Configuration(): Unable to find default cell gauge." );
if (not cg) {
string cellGaugeName = Cfg::getParamString("anabatic.cellGauge","sxlib")->asString();
cg = AllianceFramework::get()->getCellGauge( cellGaugeName );
}
if (not cg)
throw Error( "AnabaticEngine::Configuration(): Unable to find cell gauge \"%s\""
, gaugeName.c_str() );
if (rg == NULL) {
if (not rg)
rg = AllianceFramework::get()->getRoutingGauge( gaugeName );
if (rg == NULL)
throw Error( "AnabaticEngine::Configuration(): No routing gauge named \"%s\"", gaugeName.c_str() );
}
if (not rg)
throw Error( "AnabaticEngine::Configuration(): Unable to find routing gauge \"%s\""
, gaugeName.c_str() );
_cg = cg->getClone();
_rg = rg->getClone();

View File

@ -1551,20 +1551,24 @@ namespace Anabatic {
}
// Add the blockages.
int contiguousNonSaturated = 0;
for ( size_t i=0 ; i<_depth ; i++ ) {
uLengths2[i] += _blockages[i];
if (not i) continue;
if (Session::getLayerGauge(i)->getType() & Constant::PowerSupply)
continue;
if ((float)(_blockages[i] * Session::getPitch(i)) > 0.60*(float)(width*height))
contiguousNonSaturated = 0;
else
contiguousNonSaturated++;
}
if (contiguousNonSaturated < 2) {
flags() |= Flags::GoStraight;
//cerr << "| Set GoStraight on " << this << endl;
if (isStdCellRow() or isChannelRow()) {
flags().reset( Flags::GoStraight );
} else {
int contiguousNonSaturated = 0;
for ( size_t i=0 ; i<_depth ; i++ ) {
uLengths2[i] += _blockages[i];
if (not i) continue;
if (Session::getLayerGauge(i)->getType() & Constant::PowerSupply)
continue;
if ((float)(_blockages[i] * Session::getPitch(i)) > 0.60*(float)(width*height))
contiguousNonSaturated = 0;
else
contiguousNonSaturated++;
}
if (contiguousNonSaturated < 2) {
flags() |= Flags::GoStraight;
//cerr << "| Set GoStraight on " << this << endl;
}
}
// Compute the number of non pass-through tracks.

View File

@ -187,7 +187,7 @@ namespace Anabatic {
contact2 ->setFlags( CntFixed );
AutoSegment* fixed = AutoSegment::create( rpContact, contact1, Flags::Vertical );
AutoSegment* dogleg = AutoSegment::create( contact1 , contact2, Flags::Horizontal );
AutoSegment* dogleg = AutoSegment::create( contact1 , contact2, Flags::Horizontal|Flags::UseNonPref );
fixed ->setFlags( AutoSegment::SegFixed );
dogleg->setFlags( AutoSegment::SegFixed );

View File

@ -412,6 +412,9 @@ namespace Anabatic {
if (y < constraint.getYMin()) y += lg->getPitch();
if (y > constraint.getYMax()) y -= lg->getPitch();
y = std::max( y, constraint.getYMin() );
y = std::min( y, constraint.getYMax() );
return Point(x,y);
}
@ -420,6 +423,10 @@ namespace Anabatic {
{ return get("isInDemoMode()")->_anabatic->isInDemoMode(); }
bool Session::isChannelMode ()
{ return get("isChannelMode()")->_anabatic->isChannelMode(); }
float Session::getSaturateRatio ()
{ return get("getSaturateRatio()")->_anabatic->getSaturateRatio(); }

View File

@ -191,20 +191,27 @@ namespace Anabatic {
class AnabaticEngine : public ToolEngine {
public:
enum DensityMode { AverageHVDensity=1 // Average between all densities.
, AverageHDensity =2 // Average between all H densities.
, AverageVDensity =3 // Average between all V densities.
, MaxHVDensity =4 // Maximum between average H and average V.
, MaxVDensity =5 // Maximum of V densities.
, MaxHDensity =6 // Maximum of H densities.
, MaxDensity =7 // Maximum of H & V densities.
};
static const uint32_t DigitalMode = (1 << 0);
static const uint32_t AnalogMode = (1 << 1);
static const uint32_t MixedMode = (1 << 2);
static const uint32_t ChannelMode = (1 << 3);
static const uint32_t AverageHVDensity = 1; // Average between all densities.
static const uint32_t AverageHDensity = 2; // Average between all H densities.
static const uint32_t AverageVDensity = 3; // Average between all V densities.
static const uint32_t MaxHVDensity = 4; // Maximum between average H and average V.
static const uint32_t MaxVDensity = 5; // Maximum of V densities.
static const uint32_t MaxHDensity = 6; // Maximum of H densities.
static const uint32_t MaxDensity = 7; // Maximum of H & V densities.
public:
typedef ToolEngine Super;
public:
static AnabaticEngine* create ( Cell* );
static AnabaticEngine* get ( const Cell* );
inline bool isCanonizeDisabled () const;
inline bool isDigitalMode () const;
inline bool isAnalogMode () const;
inline bool isMixedMode () const;
inline bool isChannelMode () const;
static const Name& staticGetName ();
virtual const Name& getName () const;
virtual Configuration* getConfiguration ();
@ -269,6 +276,8 @@ namespace Anabatic {
void invalidateRoutingPads ();
void updateDensity ();
size_t checkGCellDensities ();
inline void setRoutingMode ( uint32_t );
inline void resetRoutingMode ( uint32_t );
inline void setGlobalThreshold ( DbU::Unit );
inline void setSaturateRatio ( float );
inline void setSaturateRp ( size_t );
@ -350,6 +359,7 @@ namespace Anabatic {
CellViewer* _viewer;
Flags _flags;
int _stamp;
uint32_t _routingMode;
uint64_t _densityMode;
AutoSegmentLut _autoSegmentLut;
AutoContactLut _autoContactLut;
@ -359,6 +369,12 @@ namespace Anabatic {
};
inline bool AnabaticEngine::isDigitalMode () const { return (_routingMode & DigitalMode); };
inline bool AnabaticEngine::isAnalogMode () const { return (_routingMode & AnalogMode); };
inline bool AnabaticEngine::isMixedMode () const { return (_routingMode & MixedMode); };
inline bool AnabaticEngine::isChannelMode () const { return (_routingMode & ChannelMode); };
inline void AnabaticEngine::setRoutingMode ( uint32_t mode ) { _routingMode |= mode; };
inline void AnabaticEngine::resetRoutingMode ( uint32_t mode ) { _routingMode &= ~mode; };
inline EngineState AnabaticEngine::getState () const { return _state; }
inline void AnabaticEngine::setState ( EngineState state ) { _state = state; }
inline CellViewer* AnabaticEngine::getViewer () const { return _viewer; }

View File

@ -76,6 +76,7 @@ namespace Anabatic {
static inline bool doDestroyBaseSegment ();
static inline bool doDestroyTool ();
static bool isInDemoMode ();
static bool isChannelMode ();
static bool doWarnGCellOverload ();
static Session* get ( const char* message=NULL );
static inline Technology* getTechnology ();

View File

@ -85,6 +85,7 @@ rg.addLayerGauge( RoutingLayerGauge.create( tech.getLayer('METAL1') # meta
, l(0) # track offset from AB.
, l(10) # track pitch.
, l(3) # wire width.
, l(3) # perpandicular wire width.
, l(2) # VIA side (that is VIA12).
, l(7) # obstacle dW.
) )
@ -97,6 +98,7 @@ rg.addLayerGauge( RoutingLayerGauge.create( tech.getLayer('METAL2') # meta
, l(0) # track offset from AB.
, l(10) # track pitch.
, l(3) # wire width.
, l(3) # perpandicular wire width.
, l(2) # VIA side (that is VIA23).
, l(8) # obstacle dW.
) )
@ -109,6 +111,7 @@ rg.addLayerGauge( RoutingLayerGauge.create( tech.getLayer('METAL3') # meta
, l(0) # track offset from AB.
, l(10) # track pitch.
, l(3) # wire width.
, l(3) # perpandicular wire width.
, l(2) # VIA side (that is VIA34).
, l(8) # obstacle dW.
) )
@ -121,6 +124,7 @@ rg.addLayerGauge( RoutingLayerGauge.create( tech.getLayer('METAL4') # meta
, l(0) # track offset from AB.
, l(15) # track pitch.
, l(6) # wire width.
, l(6) # perpandicular wire width.
, l(4) # VIA side (that is VIA23).
, l(8) # obstacle dW.
) )
@ -137,6 +141,7 @@ rg.addLayerGauge( RoutingLayerGauge.create( tech.getLayer('METAL1') # meta
, l(0) # track offset from AB.
, l(10) # track pitch.
, l(3) # wire width.
, l(3) # perpandicular wire width.
, l(2) # VIA side (that is VIA12).
, l(7) # obstacle dW.
) )
@ -149,6 +154,7 @@ rg.addLayerGauge( RoutingLayerGauge.create( tech.getLayer('METAL2') # meta
, l(0) # track offset from AB.
, l(10) # track pitch.
, l(3) # wire width.
, l(3) # perpandicular wire width.
, l(2) # VIA side (that is VIA23).
, l(8) # obstacle dW.
) )
@ -161,6 +167,7 @@ rg.addLayerGauge( RoutingLayerGauge.create( tech.getLayer('METAL3') # meta
, l(0) # track offset from AB.
, l(10) # track pitch.
, l(3) # wire width.
, l(3) # perpandicular wire width.
, l(2) # VIA side (that is VIA34).
, l(8) # obstacle dW.
) )
@ -177,6 +184,7 @@ rg.addLayerGauge( RoutingLayerGauge.create( tech.getLayer('METAL1') # meta
, l(0) # track offset from AB.
, l(10) # track pitch.
, l(3) # wire width.
, l(3) # perpandicular wire width.
, l(3) # VIA side (that is VIA12).
, l(7) # obstacle dW.
) )
@ -189,6 +197,7 @@ rg.addLayerGauge( RoutingLayerGauge.create( tech.getLayer('METAL2') # meta
, l(0) # track offset from AB.
, l(10) # track pitch.
, l(3) # wire width.
, l(3) # perpandicular wire width.
, l(3) # VIA side (that is VIA23).
, l(8) # obstacle dW.
) )

View File

@ -24,7 +24,7 @@ from Hurricane import Technology
tech = DataBase.getDB().getTechnology()
if tech:
print( WarningMessage( 'cmos.technology: Technology already exists, "{}"'format(tech.getName()) ))
print( WarningMessage( 'cmos.technology: Technology already exists, "{}"'.format(tech.getName()) ))
else:
tech = Technology.create( DataBase.getDB(), 'phenitec06' )

View File

@ -62,6 +62,7 @@ namespace CRL {
, _technology (DataBase::getDB()->getTechnology())
, _isSymbolic (true)
, _isSuperPitched(true)
, _usableLayers (0)
{ }
@ -72,6 +73,7 @@ namespace CRL {
, _technology (gauge._technology)
, _isSymbolic (gauge._isSymbolic)
, _isSuperPitched(gauge._isSuperPitched)
, _usableLayers (0)
{
// Make a deep copy of the map.
for ( size_t i=0 ; i<gauge._layerGauges.size() ; i++ ) {
@ -312,6 +314,8 @@ namespace CRL {
if (fabsf(roundf(r) - r) > 0.00001f)
_isSuperPitched = false;
}
if (layerGauge->getType() == Constant::LayerGaugeType::Default) ++_usableLayers;
}
@ -354,12 +358,14 @@ namespace CRL {
Record* RoutingGauge::_getRecord ( Record* record ) const
{
if ( record == NULL )
if (not record)
record = new Record ( getString(this) );
record->add ( getSlot("_name" , _name ) );
record->add ( getSlot("_gauges" ,&_layerGauges) );
record->add ( getSlot("_isSymbolic", _isSymbolic ) );
record->add( getSlot("_name" , _name ));
record->add( getSlot("_gauges" ,&_layerGauges ));
record->add( getSlot("_isSymbolic" , _isSymbolic ));
record->add( getSlot("_isSuperPitched", _isSuperPitched ));
record->add( getSlot("_usableLayers" , _usableLayers ));
return ( record );
}

View File

@ -377,10 +377,12 @@ namespace {
static string zeroName = Cfg::getParamString("etesian.cell.zero","zero_x0")->asString();
static string oneName = Cfg::getParamString("etesian.cell.one" , "one_x0")->asString();
_zeroCell = framework->getCell( zeroName, Catalog::State::Views|Catalog::State::Foreign );
_oneCell = framework->getCell( oneName, Catalog::State::Views|Catalog::State::Foreign );
_groundName = Cfg::getParamString("crlcore.groundName","vss")->asString();
_powerName = Cfg::getParamString("crlcore.powerName" ,"vdd")->asString();
_zeroCell = framework->getCell( zeroName, Catalog::State::Views|Catalog::State::Foreign );
_oneCell = framework->getCell( oneName, Catalog::State::Views|Catalog::State::Foreign );
_groundName = Cfg::getParamString("crlcore.groundName","vss")->asString();
_powerName = Cfg::getParamString("crlcore.powerName" ,"vdd")->asString();
if (not _zeroCell) _zeroCell = Blif::getCell( zeroName );
if (not _oneCell) _oneCell = Blif::getCell( oneName );
if (_zeroCell) {
for ( Net* net : _zeroCell->getNets() ) {
@ -818,6 +820,17 @@ namespace CRL {
{ if (library) _libraries.push_back( library ); }
Cell* Blif::getCell ( string name )
{
Cell* cell = nullptr;
for ( Library* library : getLibraries() ) {
cell = library->getCell( name );
if (cell) return cell;
}
return nullptr;
}
Cell* Blif::load ( string cellPath, bool enforceVhdl )
{
using namespace std;

View File

@ -59,6 +59,7 @@ namespace CRL {
static Cell* load ( std::string netlist, bool enforceVhdl=true );
static void add ( Library* );
static inline const std::vector<Library*>& getLibraries ();
static Cell* getCell ( std::string );
private:
static std::vector<Library*> _libraries;
};

View File

@ -64,6 +64,7 @@ namespace CRL {
inline const Name getName () const;
inline Technology* getTechnology () const;
inline size_t getDepth () const;
inline size_t getUsableLayers () const;
inline DbU::Unit getHorizontalPitch () const;
inline DbU::Unit getVerticalPitch () const;
RoutingLayerGauge* getHorizontalGauge () const;
@ -109,6 +110,7 @@ namespace CRL {
Technology* _technology;
bool _isSymbolic;
bool _isSuperPitched;
size_t _usableLayers;
// Internal - Constructors & Destructors.
RoutingGauge ( const char* name );
@ -121,13 +123,14 @@ namespace CRL {
inline bool RoutingGauge::isSymbolic () const { return _isSymbolic; }
inline bool RoutingGauge::isSuperPitched () const { return _isSuperPitched; }
inline bool RoutingGauge::isTwoMetals () const { return (getDepth() < 3); }
inline bool RoutingGauge::isTwoMetals () const { return (_usableLayers < 3); }
inline bool RoutingGauge::isHV () const { return not isTwoMetals() and (getLayerGauge(1)->isHorizontal()); }
inline bool RoutingGauge::isVH () const { return not isTwoMetals() and (getLayerGauge(1)->isVertical()); }
inline bool RoutingGauge::hasPowerSupply () const { return (getPowerSupplyGauge() != NULL); }
inline const Name RoutingGauge::getName () const { return _name; }
inline size_t RoutingGauge::getDepth () const { return _layerGauges.size(); }
inline Technology* RoutingGauge::getTechnology () const { return _technology; }
inline size_t RoutingGauge::getUsableLayers () const { return _usableLayers; }
inline DbU::Unit RoutingGauge::getHorizontalPitch () const { return getHorizontalGauge()->getPitch(); }
inline DbU::Unit RoutingGauge::getVerticalPitch () const { return getVerticalGauge ()->getPitch(); }
inline unsigned int RoutingGauge::getLayerType ( size_t depth ) const { return getLayerGauge(depth)->getType(); }

View File

@ -104,6 +104,8 @@ namespace {
inline void incNthMetal ();
inline int getNthCut () const;
inline void incNthCut ();
inline int getNthRouting () const;
inline void incNthRouting ();
inline RoutingGauge* getRoutingGauge () const;
inline void addPinSegment ( string name, Segment* );
inline void clearPinSegments ();
@ -130,6 +132,7 @@ namespace {
vector<string> _errors;
int _nthMetal;
int _nthCut;
int _nthRouting;
RoutingGauge* _routingGauge;
CellGauge* _cellGauge;
DbU::Unit _minTerminalWidth;
@ -154,6 +157,8 @@ namespace {
inline void LefParser::incNthMetal () { ++_nthMetal; }
inline int LefParser::getNthCut () const { return _nthCut; }
inline void LefParser::incNthCut () { ++_nthCut; }
inline int LefParser::getNthRouting () const { return _nthRouting; }
inline void LefParser::incNthRouting () { ++_nthRouting; }
inline RoutingGauge* LefParser::getRoutingGauge () const { return _routingGauge; }
inline CellGauge* LefParser::getCellGauge () const { return _cellGauge; }
inline void LefParser::setCoreSite ( DbU::Unit x, DbU::Unit y ) { _coreSiteX=x; _coreSiteY=y; }
@ -210,6 +215,7 @@ namespace {
, _errors ()
, _nthMetal (0)
, _nthCut (0)
, _nthRouting (0)
, _routingGauge (NULL)
, _cellGauge (NULL)
, _minTerminalWidth(DbU::fromPhysical(Cfg::getParamDouble("lefImport.minTerminalWidth",0.0)->asDouble(),DbU::UnitPower::Micro))
@ -305,9 +311,9 @@ namespace {
cerr << " - \"" << lefLayer->name() << "\" map to \"" << basicLayer->getName() << "\"" << endl;
RoutingLayerGauge* gauge = parser->getRoutingGauge()->getLayerGauge( parser->getNthMetal() );
RoutingLayerGauge* gauge = parser->getRoutingGauge()->getLayerGauge( parser->getNthRouting() );
if (gauge) {
if (gauge and (layer == gauge->getLayer())) {
if (lefLayer->hasPitch()) {
double lefPitch = lefLayer->pitch();
double crlPitch = DbU::toPhysical(gauge->getPitch(),DbU::Micro);
@ -336,6 +342,7 @@ namespace {
cerr << Warning( "LefParser::_layerCbk(): CRL Routing direction discrepency for \"%s\", LEF is VERTICAL."
, getString( basicLayer->getName() ).c_str() ) << endl;
}
parser->incNthRouting();
} else {
cerr << Warning( "LefParser::_layerCbk(): No CRL routing gauge defined for \"%s\"."
, getString( basicLayer->getName() ).c_str()

View File

@ -73,18 +73,21 @@ namespace Etesian {
, _antennaDiodeMaxWL( Cfg::getParamInt ("etesian.antennaDiodeMaxWL" ,0 )->asInt() )
{
string gaugeName = Cfg::getParamString("anabatic.routingGauge","sxlib")->asString();
if (cg == NULL) {
if (not cg)
cg = AllianceFramework::get()->getCellGauge( gaugeName );
if (cg == NULL)
throw Error( "AnabaticEngine::Configuration(): Unable to find default cell gauge \"%s\"."
, gaugeName.c_str() );
if (not cg) {
string cellGaugeName = Cfg::getParamString("anabatic.cellGauge","sxlib")->asString();
cg = AllianceFramework::get()->getCellGauge( cellGaugeName );
}
if (not cg)
throw Error( "EtesianEngine::Configuration(): Unable to find cell gauge \"%s\""
, gaugeName.c_str() );
if (rg == NULL) {
if (not rg)
rg = AllianceFramework::get()->getRoutingGauge( gaugeName );
if (rg == NULL)
throw Error( "AnabaticEngine::Configuration(): No routing gauge named \"%s\"", gaugeName.c_str() );
}
if (not rg)
throw Error( "EtesianEngine::Configuration(): Unable to find routing gauge \"%s\""
, gaugeName.c_str() );
_rg = rg->getClone();
_cg = cg->getClone();

View File

@ -18,6 +18,7 @@
#include "hurricane/Warning.h"
#include "hurricane/Breakpoint.h"
#include "hurricane/DebugSession.h"
#include "hurricane/UpdateSession.h"
#include "hurricane/RoutingPad.h"
#include "hurricane/Cell.h"
#include "anabatic/Edge.h"
@ -37,6 +38,7 @@ namespace Katana {
using Hurricane::Breakpoint;
using Hurricane::DebugSession;
using Hurricane::SubTypeCollection;
using Hurricane::UpdateSession;
using Hurricane::Transformation;
using Hurricane::RoutingPad;
using Hurricane::Instance;
@ -104,8 +106,14 @@ namespace Katana {
throw Error( "Row::createChannel(): NULL southWest GCell." );
if (_occurrences.empty())
throw Error( "Row::createChannel(): No instances in row." );
if (southWest->getXMin() != (*_occurrences.begin()).first)
throw Error( "Row::createChannel(): South-west GCell XMin and Row X min differs." );
if (southWest->getXMin() != (*_occurrences.begin()).first) {
UpdateSession::close();
throw Error( "Row::createChannel(): South-west GCell XMin and Row X min differs.\n"
" * southWest=%s\n"
" * first=%s\n"
, getString(southWest).c_str()
, DbU::getValueString((*_occurrences.begin()).first).c_str() );
}
if (southWest->getYMin() != _y)
throw Error( "Row::createChannel(): South-west GCell YMIn and Row Y min differs (%s vs. %s)."
, DbU::getValueString(southWest->getYMin()).c_str()
@ -198,6 +206,7 @@ namespace Katana {
// _channelHeight = std::max( _channelHeight, east->getRealOccupancy() );
gcell = gcell->getEast();
}
_channelHeight += 2;
return _channelHeight;
}

View File

@ -95,6 +95,7 @@ namespace Katana {
vector<AutoSegment*> collapseds;
vector< tuple<AutoSegment*,Anabatic::Flags> > perpandiculars;
map<DbU::Unit,int> attractorSpins;
size_t reducedPerpands = 0;
_reduceRanges[0].makeEmpty();
_reduceRanges[1].makeEmpty();
@ -125,12 +126,16 @@ namespace Katana {
perpandicular = Session::lookup( basePerpand->getCanonical(interval)->base() );
}
if (not perpandicular) {
cerr << Bug( "Not a TrackSegment: %s\n (perpandicular: %s)"
//, getString((void*)basePerpand->getCanonical(interval)->base()).c_str()
, getString(basePerpand->getCanonical(interval)).c_str()
//, getString((void*)basePerpand->base()).c_str()
, getString(basePerpand).c_str()
) << endl;
if (not (Session::isChannelMode()
and (basePerpand->isReduced() or basePerpand->isNonPref())))
cerr << Bug( "Not a TrackSegment: %s\n (perpandicular: %s)"
//, getString((void*)basePerpand->getCanonical(interval)->base()).c_str()
, getString(basePerpand->getCanonical(interval)).c_str()
//, getString((void*)basePerpand->base()).c_str()
, getString(basePerpand).c_str()
) << endl;
else
++reducedPerpands;
continue;
}
@ -266,7 +271,7 @@ namespace Katana {
cdebug_tabw(159,-1);
}
if ( not _trackSegment->isTerminal() and (_perpandiculars.size() < 2) )
if ( not _trackSegment->isTerminal() and (_perpandiculars.size()+reducedPerpands < 2) )
cerr << Bug( "Less than two perpandiculars on %s.", getString(_trackSegment).c_str() ) << endl;
map<DbU::Unit,int>::iterator iattractor = attractorSpins.begin();

View File

@ -685,7 +685,8 @@ namespace Katana {
addMeasure<uint32_t>( "H-ovE", hoverflow, 12 );
addMeasure<uint32_t>( "V-ovE", voverflow, 12 );
_buildBloatProfile();
if (not Session::isChannelMode())
_buildBloatProfile();
if (flags & Flags::ShowFailedNets ) selectNets ( this, nets );
if (flags & Flags::ShowFailedGSegments ) selectSegments ( this, segments );

View File

@ -195,7 +195,6 @@ namespace Katana {
, _minimumWL (0.0)
, _shortDoglegs ()
, _symmetrics ()
, _mode (DigitalMode)
, _stage (StageNegociate)
, _successState (0)
{
@ -241,7 +240,7 @@ namespace Katana {
{
cdebug_log(155,1) << "KatanaEngine::_initDataBase()" << endl;
_mode |= DigitalMode;
setRoutingMode( DigitalMode );
Super::chipPrep();
@ -270,8 +269,8 @@ namespace Katana {
{
cdebug_log(155,1) << "KatanaEngine::_initDataBase()" << endl;
_mode &= ~DigitalMode;
_mode |= AnalogMode;
resetRoutingMode( DigitalMode );
setRoutingMode( AnalogMode );
Super::chipPrep();
@ -286,11 +285,11 @@ namespace Katana {
{
cdebug_log(155,1) << "KatanaEngine::setupChannelMode()" << endl;
RoutingGauge* rg = getConfiguration()->getRoutingGauge();
size_t maxDepth = rg->getDepth();
if (maxDepth < 3) {
_mode |= ChannelMode;
RoutingGauge* rg = getConfiguration()->getRoutingGauge();
if (rg->isTwoMetals()) {
setRoutingMode( ChannelMode );
size_t maxDepth = rg->getDepth();
if (maxDepth < 2) {
throw Error( "KatanaEngine::setupChannelMode(): Layer gauge %s must contains at least two layers (%u)."
, getString(rg->getName()).c_str(), maxDepth );
@ -554,10 +553,10 @@ namespace Katana {
}
}
if (Session::getConfiguration()->isTwoMetals()) {
if (Session::isChannelMode()) {
for ( GCell* gcell : getGCells() ) {
if (not gcell->isStdCellRow()) continue;
set<DbU::Unit> terminalsX;
for ( Component* component : getCell()->getComponentsUnder(gcell->getBoundingBox()) ) {
RoutingPad* rp = dynamic_cast<RoutingPad*>( component );
@ -574,7 +573,7 @@ namespace Katana {
edge = gcell->getSouthEdge();
if (edge) {
capacity = edge->getCapacity();
if (terminalsX.size() < capacity) capacity = terminalsX.size();
if (terminalsX.size()/2 < capacity) capacity = terminalsX.size()/2;
edge->reserveCapacity( capacity );
}
}
@ -849,9 +848,15 @@ namespace Katana {
AutoSegment* autoSegment = anbtSession->lookup( segment );
if (not autoSegment) continue;
if (not autoSegment->isCanonical()) continue;
if (autoSegment->isReduced()) continue;
TrackElement* trackSegment = Session::lookup( segment );
if (not trackSegment) {
if ( isChannelMode()
and autoSegment->isFixed()
and autoSegment->isHorizontal()
and autoSegment->isNonPref())
continue;
coherency = false;
cerr << Bug( "%p %s without Track Segment"
, autoSegment

View File

@ -722,8 +722,10 @@ namespace Katana {
cdebug_log(159,0) << "No intersection with: " << segment2->getCanonicalInterval() << endl;
continue;
}
if ( segment2->isBlockage() or segment2->isFixed() ) {
cdebug_log(159,0) << "Ovelap is blockage or fixed." << endl;
if ( segment2->isBlockage()
or (segment2->isFixed()
and not (segment2->isVertical() and Session::getKatanaEngine()->isChannelMode()))) {
cdebug_log(159,0) << "Overlap is blockage or fixed." << endl;
success = false;
continue;
}
@ -890,6 +892,7 @@ namespace Katana {
set<TrackElement*> canonicals;
bool success = true;
toFree.inflate( -1 );
cdebug_log(159,1) << "Manipulator::_forceToTrack(size_t) - " << toFree << endl;
for ( size_t i=begin ; success and (i < end) ; ++i ) {
@ -898,7 +901,15 @@ namespace Katana {
cdebug_log(159,0) << "* Looking // " << segment2 << endl;
if (segment2->getNet() == ownerNet) continue;
if (not toFree.intersect(segment2->getCanonicalInterval())) continue;
Interval segCanon = segment2->getCanonicalInterval();
if (not toFree.intersect(segment2->getCanonicalInterval()))
continue;
cdebug_log(159,0) << "toFree = " << toFree
<< " [" << toFree.getVMin()
<< " " << toFree.getVMax() << "]" << endl;
cdebug_log(159,0) << "segCanon = " << segCanon
<< " [" << segCanon.getVMin()
<< " " << segCanon.getVMax() << "]" << endl;
if (segment2->isFixed()) {
success = false;
continue;

View File

@ -60,7 +60,9 @@ namespace {
if (not intersect.intersect(cost.getInterval())) return;
if (segment->isBlockage() or segment->isFixed()) {
if ( segment->isBlockage()
or (segment->isFixed()
and not (segment->isVertical() and Session::getKatanaEngine()->isChannelMode()))) {
cdebug_log(159,0) << "Infinite cost from: " << segment << endl;
cost.setInfinite ();
cost.setOverlap ();
@ -329,13 +331,25 @@ namespace Katana {
// Special case: fixed AutoSegments must not interfere with blockages.
// Ugly: uses of getExtensionCap().
if (autoSegment->isFixed()) {
if (Session::isChannelMode() and autoSegment->isReduced()) {
cdebug_log(159,0) << "* Fixed segment is reduced, ignore " << autoSegment << endl;
cdebug_tabw(159,-1);
return NULL;
}
size_t begin;
size_t end;
Interval fixedSpan;
Interval blockageSpan;
if (Session::isChannelMode() and autoSegment->isNonPref()) {
cdebug_log(159,0) << "Fixed in non-preferred direction, do not attempt to set on track." << endl;
cdebug_tabw(159,-1);
DebugSession::close();
return NULL;
}
if (not refTrack) {
string message = "NULL refTrack for " + getString(autoSegment);
string message = "NULL refTrack for " + getString(autoSegment) + " brace for crashing!";
Breakpoint::stop( 0, message );
}

View File

@ -99,9 +99,10 @@ namespace {
if (CatalogExtension::isPad(masterNet->getCell())) {
if ( rp->getNet()->isPower()
or (rp->getNet()->getName() == padNetName) )
or (rp->getNet()->getName() == padNetName) ) {
cdebug_tabw(145,-1);
return;
}
}
vector<Segment*> segments;

View File

@ -747,16 +747,22 @@ namespace Katana {
RoutingPlane* plane = Session::getKatanaEngine()->getRoutingPlaneByLayer(_segment->getLayer());
Track* track = plane->getTrackByPosition(_constraints.getVMin());
if ( track && (track->getAxis() < _constraints.getVMin()) ) track = track->getNextTrack();
for ( ; track && (track->getAxis() <= _constraints.getVMax())
; track = track->getNextTrack(), _tracksNb++ );
if ( track and (track->getAxis() < _constraints.getVMin()) ) track = track->getNextTrack();
cdebug_log(159,0) << "| Nearest " << track << endl;
while ( track and (track->getAxis() <= _constraints.getVMax()) ) {
_tracksNb++;
track = track->getNextTrack();
cdebug_log(159,0) << "| Next " << track << endl;
}
}
cdebug_log(159,0) << "| _tracksNb " << _tracksNb << endl;
if (not _tracksNb) {
cdebug_log(159,0) << "| Pure constraints are too tight." << endl;
if (_segment->base())
_overConstrained = _segment->base()->getAutoSource()->isTerminal()
and _segment->base()->getAutoTarget()->isTerminal();
}
cdebug_log(159,0) << "| _tracksNb " << _tracksNb << endl;
_segment->computePriority();

View File

@ -45,8 +45,12 @@ namespace Katana {
Interval bounds;
if ( _locator.isValid() ) {
_element = Session::lookup( _locator.getElement()->getCanonical(bounds)->base() );
if ( !_element ) {
cerr << Bug("Canonical segment without TrackElement.") << endl;
if (not _element) {
AutoSegment* segment = _locator.getElement()->getCanonical(bounds);
if (Session::isChannelMode()
and not ((segment->isReduced() or segment->isNonPref()) and segment->isFixed()))
cerr << Bug( "Canonical segment without TrackElement on %s."
, getString(segment).c_str()) << endl;
progress ();
}
}
@ -67,8 +71,12 @@ namespace Katana {
if ( _locator.isValid() ) {
_element = Session::lookup( _locator.getElement()->getCanonical(bounds)->base() );
if ( !_element ) {
cerr << Bug("Canonical segment without TrackElement.") << endl;
if (not _element ) {
AutoSegment* segment = _locator.getElement()->getCanonical(bounds);
if (Session::isChannelMode()
and not ((segment->isReduced() or segment->isNonPref()) and segment->isFixed()))
cerr << Bug( "Canonical segment without TrackElement on %s."
, getString(segment).c_str() ) << endl;
continue;
}

View File

@ -105,12 +105,14 @@ namespace Katana {
}
if ( not perpandicular ) {
cerr << Bug("Not a TrackSegment: %s:%s\n (perpandicular: %s:%s)"
,getString((void*)basePerpand->getCanonical(interval)->base()).c_str()
,getString(basePerpand->getCanonical(interval)).c_str()
,getString((void*)basePerpand->base()).c_str()
,getString(basePerpand).c_str()
) << endl;
if (Session::isChannelMode()
and not (basePerpand->isReduced() or basePerpand->isNonPref()))
cerr << Bug("Not a TrackSegment: %s:%s\n (perpandicular: %s:%s)"
,getString((void*)basePerpand->getCanonical(interval)->base()).c_str()
,getString(basePerpand->getCanonical(interval)).c_str()
,getString((void*)basePerpand->base()).c_str()
,getString(basePerpand).c_str()
) << endl;
continue;
}
interval.inflate ( DbU::lambda(-1.5) );

View File

@ -14,9 +14,7 @@
// +-----------------------------------------------------------------+
#ifndef KATANA_BLOCK_H
#define KATANA_BLOCK_H
#pragma once
#include <string>
#include <vector>
#include <map>
@ -113,5 +111,3 @@ namespace Katana {
INSPECTOR_P_SUPPORT(Katana::Row);
INSPECTOR_P_SUPPORT(Katana::Block);
#endif // KATANA_BLOCK_H

View File

@ -55,10 +55,6 @@ namespace Katana {
class KatanaEngine : public AnabaticEngine {
public:
static const uint32_t DigitalMode = (1 << 0);
static const uint32_t AnalogMode = (1 << 1);
static const uint32_t MixedMode = (1 << 2);
static const uint32_t ChannelMode = (1 << 3);
static const uint32_t GlobalRoutingSuccess = (1 << 0);
static const uint32_t DetailedRoutingSuccess = (1 << 1);
public:
@ -68,10 +64,6 @@ namespace Katana {
static KatanaEngine* create ( Cell* );
static KatanaEngine* get ( const Cell* );
public:
inline bool isDigitalMode () const;
inline bool isAnalogMode () const;
inline bool isMixedMode () const;
inline bool isChannelMode () const;
inline bool isGlobalRoutingSuccess () const;
inline bool isDetailedRoutingSuccess () const;
inline bool useClockTree () const;
@ -172,7 +164,6 @@ namespace Katana {
double _minimumWL;
TrackElementPairing _shortDoglegs;
DataSymmetricMap _symmetrics;
uint32_t _mode;
uint32_t _stage;
mutable uint32_t _successState;
protected:
@ -188,10 +179,6 @@ namespace Katana {
// Inline Functions.
inline bool KatanaEngine::isDigitalMode () const { return (_mode & DigitalMode); };
inline bool KatanaEngine::isAnalogMode () const { return (_mode & AnalogMode); };
inline bool KatanaEngine::isMixedMode () const { return (_mode & MixedMode); };
inline bool KatanaEngine::isChannelMode () const { return (_mode & ChannelMode); };
inline bool KatanaEngine::isGlobalRoutingSuccess () const { return (_successState & GlobalRoutingSuccess); }
inline bool KatanaEngine::isDetailedRoutingSuccess() const { return (_successState & DetailedRoutingSuccess); }
inline bool KatanaEngine::useClockTree () const { return _configuration->useClockTree(); }