Added support for 2-Metal block routing in Anabatic & Katana.
* New: In AnabaticEngine::invalidateRoutingPads() this method is a temporary workaround for a Hurricane problems. When an instance is moved, the RoutingPads that use it must be moved accordingly, but they are not invalidated so they stay in the wrong QuadTree. New method ::_resizeMatrix() to be called when the associated Cell is resized. * Bug: In AutoHorizontal::getConstraints() and AutoVertical::getConstraints(), the *target* constraints where never merged. * Change: In AutoHorizontal::getCells() and AutoVertical::getGCells(), now return a boolean to tell if it was ok (must not encounter a NULL GCell while progessing from source to target). * New: In Anabatic::Configuration and Anabatic:Session, create new methods: - getDHorizontalLayer() - getDhorizontalDepth() - getDHorizontalWidth() - getDHorizontalPitch() And so on for Vertical and Contact. They supply depth-independant informations about the H/V layers to build the initial detailed routing. The AutoSegment::create() methods have been modificated accordingly. * New: In Anabatic::GCell, add two new types "StdCellRow" and "ChannelRow" for implementing 2-Metal blocks. Rename the GCell::setXY() method in GCell::setSouthWestCorner(), move the contents of GCell::updateContactsPosition() into it and suppress it. WARNING: In case of a GCell shrink this may cause problems. But for now we only expand... New method GCell::getNetCount() to count the number of Net going though the GCell. * Change: In Anabatic::Edge, add specific support for capacity of 2-Metal routing channels. * Change: In Anabatic::Dijsktra various methods, replace the "gcell->isMatrix()" calls by "not gcell->isAnalog()". Add more check so that the methods pertaining to the analog routing (GRData) are not called in digital mode. * New: In Anabatic::Dijkstra::materialize(), add support for 2-Metal specific cases. That is, always break in case of vertical pass-through or U-turn. The global routing must always be broken in H-Channel. * New: In Anabatic::GCell & Anabatic::Edge, make use of the Session mechanism to ensure the revalidation. The "::revalidate()" method is then moved as "::materialize()" (overload of Go) and "::_invalidate()" becomes "::invalidate()" * Change: In LoadGlobalRouting, cosmetic rename of SortHkByX in SortHookByX. * New: In GCellTopology, added support for building 2-Metal topologies. * ForkStack is now an object attribute as many methods do need it. * To push segments/hook on the stack, a new method "push()" is available. Perform NULL and fromHook checking. Can also setup _southWestContact or _northEastContact if it is the "from" edge. * N/S/E/W edges are now vector as in digital channel mode there can be more than one. * Added build topological build methods: - doRp_2m_Access() RoutingPad stem access. - _do_2m_1G_1M1() North or south access. - _do_2m_2G_1M1() North AND south access. - _do_2m_xG() H-Channel routing. * New: In Anabatic::Matrix, new ::resize() function, as Cell can be resizeds. * New: In Anabatic::Vertex, new static method ::getValueString() for a friendly text rendering. * New: In Katana::DigitalDistance, support for channel routing. * Change: In KatanaEngine::digitalSetup() and KatanaEngine::runGlobalrouter(), for channel routing, calls to setupPowerRails() and protectRoutingPads() must be called after the core block has been fully dimensionned. ::runGlobalrouter() contains the code tasked with the grid creation and channel sizing. * New: In KatanaEngine: Added support for core block, for 2-Metal routing. May be expanded for over-the-cell routing in the future. Added methods : - isDigitalMode() - isAnalogMode() - isMixedMode() - isChannelMode() - getBlock() / addBlock() - setupChannelMode() - createChannel() * New: In Katana, new class Block to manage core blocks and perform channel routing. * New: In Katana::Session, new convenience method "isOpen()".
This commit is contained in:
parent
809a91c9c1
commit
eae5d6bf83
|
@ -407,9 +407,7 @@ namespace Anabatic {
|
|||
void AnabaticEngine::updateMatrix()
|
||||
{
|
||||
_matrix.setCell( getCell(), Session::getSliceHeight() );
|
||||
for ( GCell* gcell : _gcells ){
|
||||
gcell->_revalidate();
|
||||
}
|
||||
for ( GCell* gcell : _gcells ) _updateLookup( gcell );
|
||||
}
|
||||
|
||||
size_t AnabaticEngine::getNetsFromEdge ( const Edge* edge, NetSet& nets )
|
||||
|
@ -939,6 +937,18 @@ namespace Anabatic {
|
|||
}
|
||||
|
||||
|
||||
void AnabaticEngine::invalidateRoutingPads ()
|
||||
{
|
||||
// This a flaw in the Hurricane Session update mechanism
|
||||
// and needs to be fixed in the future.
|
||||
for ( Net* net : getCell()->getNets() ) {
|
||||
for ( RoutingPad* rp : net->getRoutingPads() ) {
|
||||
rp->invalidate( false );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AnabaticEngine::updateDensity ()
|
||||
{ for ( GCell* gcell : _gcells ) gcell->updateDensity(); }
|
||||
|
||||
|
|
|
@ -157,6 +157,13 @@ namespace Anabatic {
|
|||
<< DbU::getValueString(getAutoSource()->getCBYMax()) << "]"
|
||||
<< endl;
|
||||
|
||||
constraintMin = std::max ( constraintMin, getAutoTarget()->getCBYMin() );
|
||||
constraintMax = std::min ( constraintMax, getAutoTarget()->getCBYMax() );
|
||||
cdebug_log(144,0) << "Merge with target constraints: ["
|
||||
<< DbU::getValueString(getAutoTarget()->getCBYMin()) << ":"
|
||||
<< DbU::getValueString(getAutoTarget()->getCBYMax()) << "]"
|
||||
<< endl;
|
||||
|
||||
constraintMin = std::max ( constraintMin, getUserConstraints().getVMin() );
|
||||
constraintMax = std::min ( constraintMax, getUserConstraints().getVMax() );
|
||||
cdebug_log(144,0) << "Merge with user constraints: ["
|
||||
|
@ -177,13 +184,14 @@ namespace Anabatic {
|
|||
{ return Flags::Horizontal; }
|
||||
|
||||
|
||||
size_t AutoHorizontal::getGCells ( vector<GCell*>& gcells ) const
|
||||
bool AutoHorizontal::getGCells ( vector<GCell*>& gcells ) const
|
||||
{
|
||||
vector<GCell*>().swap( gcells );
|
||||
|
||||
DbU::Unit yprobe = getY();
|
||||
GCell* gcell = getAutoSource()->getGCell();
|
||||
GCell* end = getAutoTarget()->getGCell();
|
||||
bool success = true;
|
||||
DbU::Unit yprobe = getY();
|
||||
GCell* gcell = getAutoSource()->getGCell();
|
||||
GCell* end = getAutoTarget()->getGCell();
|
||||
|
||||
cdebug_log(144,0) << "yprobe: " << DbU::getValueString(yprobe) << endl;
|
||||
|
||||
|
@ -195,6 +203,7 @@ namespace Anabatic {
|
|||
while ( gcell != end ) {
|
||||
gcell = gcell->getEast( yprobe );
|
||||
if (not gcell) {
|
||||
success = false;
|
||||
cerr << Error( "AutoHorizontal::getGCells() : NULL GCell under %s\n"
|
||||
" begin:%s\n"
|
||||
" end: %s"
|
||||
|
@ -208,7 +217,7 @@ namespace Anabatic {
|
|||
gcells.push_back( gcell );
|
||||
}
|
||||
|
||||
return gcells.size();
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -615,6 +615,7 @@ namespace Anabatic {
|
|||
return getWidth() / 2;
|
||||
}
|
||||
|
||||
|
||||
DbU::Unit AutoSegment::getSlack () const
|
||||
{
|
||||
DbU::Unit constraintMin;
|
||||
|
@ -1862,13 +1863,13 @@ namespace Anabatic {
|
|||
if (getSpanU().contains(interval.getVMax())) rightDogleg++;
|
||||
|
||||
if (not isNotAligned()) {
|
||||
forEach ( AutoSegment*, isegment, getAligneds() ) {
|
||||
if (isegment->getSpanU().contains(interval.getVMin())) {
|
||||
if (isegment->isFixed()) return false;
|
||||
for ( AutoSegment* segment : getAligneds() ) {
|
||||
if (segment->getSpanU().contains(interval.getVMin())) {
|
||||
if (segment->isFixed()) return false;
|
||||
leftDogleg++;
|
||||
}
|
||||
if (isegment->getSpanU().contains(interval.getVMax())) {
|
||||
if (isegment->isFixed()) return 0;
|
||||
if (segment->getSpanU().contains(interval.getVMax())) {
|
||||
if (segment->isFixed()) return 0;
|
||||
rightDogleg++;
|
||||
}
|
||||
}
|
||||
|
@ -1879,7 +1880,7 @@ namespace Anabatic {
|
|||
|
||||
cdebug_log(149,0) << "leftCount:" << leftDogleg << " rightCount:" << rightDogleg << endl;
|
||||
|
||||
return 0;
|
||||
return Flags::NoFlags;
|
||||
}
|
||||
|
||||
|
||||
|
@ -2151,15 +2152,15 @@ namespace Anabatic {
|
|||
, Segment* hurricaneSegment
|
||||
)
|
||||
{
|
||||
const Layer* horizontalLayer = Session::getRoutingLayer( 1 );
|
||||
DbU::Unit horizontalWidth = Session::getWireWidth ( 1 );
|
||||
const Layer* verticalLayer = Session::getRoutingLayer( 2 );
|
||||
DbU::Unit verticalWidth = Session::getWireWidth ( 2 );
|
||||
const Layer* horizontalLayer = Session::getDHorizontalLayer();
|
||||
DbU::Unit horizontalWidth = Session::getDHorizontalWidth();
|
||||
const Layer* verticalLayer = Session::getDVerticalLayer();
|
||||
DbU::Unit verticalWidth = Session::getDVerticalWidth();
|
||||
|
||||
uint32_t wPitch = NetRoutingExtension::getWPitch( source->getNet() );
|
||||
if (wPitch > 1) {
|
||||
horizontalWidth += (wPitch-1) * Session::getPitch(1);
|
||||
verticalWidth += (wPitch-1) * Session::getPitch(2);
|
||||
horizontalWidth += (wPitch-1) * Session::getDHorizontalPitch();
|
||||
verticalWidth += (wPitch-1) * Session::getDVerticalPitch ();
|
||||
}
|
||||
cdebug_log(149,0) << "wPitch:" << wPitch << " hW:" << DbU::getValueString(horizontalWidth) << endl;
|
||||
|
||||
|
@ -2197,6 +2198,8 @@ namespace Anabatic {
|
|||
reference = target;
|
||||
}
|
||||
|
||||
if (target->isTerminal()) reference = target;
|
||||
|
||||
Contact* contact = dynamic_cast<Contact*>( hurricaneSegment->getSource() );
|
||||
AutoContact* autoContact = Session::lookup( contact );
|
||||
if (contact == NULL) {
|
||||
|
@ -2287,10 +2290,10 @@ namespace Anabatic {
|
|||
// depth=1 is horizontal | METAL2
|
||||
// depth=2 is vertical | METAL3
|
||||
// Should be based on gauge informations.
|
||||
const Layer* hLayer = Session::getRoutingLayer( 1 );
|
||||
DbU::Unit hWidth = Session::getWireWidth ( 1 );
|
||||
const Layer* vLayer = Session::getRoutingLayer( 2 );
|
||||
DbU::Unit vWidth = Session::getWireWidth ( 2 );
|
||||
const Layer* hLayer = Session::getDHorizontalLayer();
|
||||
DbU::Unit hWidth = Session::getDHorizontalWidth();
|
||||
const Layer* vLayer = Session::getDVerticalLayer();
|
||||
DbU::Unit vWidth = Session::getDVerticalWidth();
|
||||
|
||||
const Layer* horizontalLayer = hLayer;
|
||||
DbU::Unit horizontalWidth = hWidth;
|
||||
|
@ -2299,8 +2302,8 @@ namespace Anabatic {
|
|||
|
||||
uint32_t wPitch = NetRoutingExtension::getWPitch( source->getNet() );
|
||||
if (wPitch > 1) {
|
||||
horizontalWidth = (wPitch-1) * Session::getPitch(1) + hWidth;
|
||||
verticalWidth = (wPitch-1) * Session::getPitch(2) + vWidth;
|
||||
horizontalWidth = (wPitch-1) * Session::getDHorizontalPitch() + hWidth;
|
||||
verticalWidth = (wPitch-1) * Session::getDVerticalPitch () + vWidth;
|
||||
}
|
||||
|
||||
if (depth != RoutingGauge::nlayerdepth) {
|
||||
|
|
|
@ -152,6 +152,13 @@ namespace Anabatic {
|
|||
<< DbU::getValueString(getAutoSource()->getCBXMax()) << "]"
|
||||
<< endl;
|
||||
|
||||
constraintMin = std::max ( constraintMin, getAutoTarget()->getCBXMin() );
|
||||
constraintMax = std::min ( constraintMax, getAutoTarget()->getCBXMax() );
|
||||
cdebug_log(149,0) << "Merge with target constraints: ["
|
||||
<< DbU::getValueString(getAutoTarget()->getCBXMin()) << ":"
|
||||
<< DbU::getValueString(getAutoTarget()->getCBXMax()) << "]"
|
||||
<< endl;
|
||||
|
||||
constraintMin = max ( constraintMin, getUserConstraints().getVMin() );
|
||||
constraintMax = min ( constraintMax, getUserConstraints().getVMax() );
|
||||
|
||||
|
@ -173,13 +180,14 @@ namespace Anabatic {
|
|||
{ return Flags::Vertical; }
|
||||
|
||||
|
||||
size_t AutoVertical::getGCells ( vector<GCell*>& gcells ) const
|
||||
bool AutoVertical::getGCells ( vector<GCell*>& gcells ) const
|
||||
{
|
||||
vector<GCell*>().swap( gcells );
|
||||
|
||||
DbU::Unit xprobe = getX();
|
||||
GCell* gcell = getAutoSource()->getGCell();
|
||||
GCell* end = getAutoTarget()->getGCell();
|
||||
bool success = true;
|
||||
DbU::Unit xprobe = getX();
|
||||
GCell* gcell = getAutoSource()->getGCell();
|
||||
GCell* end = getAutoTarget()->getGCell();
|
||||
|
||||
cdebug_log(144,0) << "xprobe: " << DbU::getValueString(xprobe) << endl;
|
||||
|
||||
|
@ -192,6 +200,7 @@ namespace Anabatic {
|
|||
gcell = gcell->getNorth( xprobe );
|
||||
|
||||
if (not gcell) {
|
||||
success = false;
|
||||
cerr << Error( "AutoVertical::getGCells() : NULL GCell under %s\n"
|
||||
" begin:%s\n"
|
||||
" end: %s"
|
||||
|
@ -205,7 +214,7 @@ namespace Anabatic {
|
|||
gcells.push_back( gcell );
|
||||
}
|
||||
|
||||
return gcells.size();
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -59,7 +59,12 @@ namespace Anabatic {
|
|||
|
||||
|
||||
Configuration::Configuration ( const CellGauge* cg, const RoutingGauge* rg )
|
||||
: _cg (NULL)
|
||||
: _gdepthv (ndepth)
|
||||
, _gdepthh (ndepth)
|
||||
, _ddepthv (ndepth)
|
||||
, _ddepthh (ndepth)
|
||||
, _ddepthc (ndepth)
|
||||
, _cg (NULL)
|
||||
, _rg (NULL)
|
||||
, _extensionCaps ()
|
||||
, _saturateRatio (Cfg::getParamPercentage("katabatic.saturateRatio",80.0)->asDouble())
|
||||
|
@ -75,14 +80,18 @@ namespace Anabatic {
|
|||
GCell::setDisplayMode( Cfg::getParamEnumerate("anabatic.gcell.displayMode", GCell::Boundary)->asInt() );
|
||||
|
||||
if (cg == NULL) cg = AllianceFramework::get()->getCellGauge();
|
||||
if (rg == NULL) rg = AllianceFramework::get()->getRoutingGauge();
|
||||
if (rg == NULL) {
|
||||
string gaugeName = Cfg::getParamString("anabatic.routingGauge","sxlib")->asString();
|
||||
rg = AllianceFramework::get()->getRoutingGauge( gaugeName );
|
||||
if (rg == NULL)
|
||||
throw Error( "Anabatic::Configuration(): No routing gauge named \"%s\"", gaugeName.c_str() );
|
||||
}
|
||||
_cg = cg->getClone();
|
||||
_rg = rg->getClone();
|
||||
|
||||
if (Cfg::hasParameter("anabatic.topRoutingLayer")) {
|
||||
_setTopRoutingLayer( Cfg::getParamString("anabatic.topRoutingLayer")->asString() );
|
||||
} else
|
||||
_allowedDepth = rg->getDepth()-1;
|
||||
_allowedDepth = rg->getDepth()-1;
|
||||
if (Cfg::hasParameter("katabatic.topRoutingLayer"))
|
||||
_setTopRoutingLayer( Cfg::getParamString("katabatic.topRoutingLayer")->asString() );
|
||||
|
||||
_gmetalh = DataBase::getDB()->getTechnology()->getLayer("gmetalh");
|
||||
_gmetalv = DataBase::getDB()->getTechnology()->getLayer("gmetalv");
|
||||
|
@ -94,8 +103,24 @@ namespace Anabatic {
|
|||
|
||||
//DbU::Unit sliceHeight = _cg->getSliceHeight();
|
||||
|
||||
_ddepthc = (_allowedDepth > 1) ? 1 : 0;
|
||||
|
||||
const vector<RoutingLayerGauge*>& layerGauges = rg->getLayerGauges();
|
||||
for ( size_t depth=0 ; depth < layerGauges.size() ; ++depth ) {
|
||||
if ( (_gdepthh == ndepth)
|
||||
and layerGauges[depth]->isHorizontal()
|
||||
and (layerGauges[depth]->getType() == Constant::LayerGaugeType::Default) ) {
|
||||
_gdepthh = depth;
|
||||
_ddepthh = depth;
|
||||
}
|
||||
|
||||
if ( (_gdepthv == ndepth)
|
||||
and layerGauges[depth]->isVertical()
|
||||
and (layerGauges[depth]->getType() == Constant::LayerGaugeType::Default) ) {
|
||||
_gdepthv = depth;
|
||||
_ddepthv = depth;
|
||||
}
|
||||
|
||||
const RegularLayer* regularLayer = dynamic_cast<const RegularLayer*>( layerGauges[depth]->getLayer() );
|
||||
if (regularLayer)
|
||||
_extensionCaps.push_back( regularLayer->getExtentionCap() );
|
||||
|
@ -115,6 +140,11 @@ namespace Anabatic {
|
|||
: _gmetalh (other._gmetalh)
|
||||
, _gmetalv (other._gmetalv)
|
||||
, _gcontact (other._gcontact)
|
||||
, _gdepthv (other._gdepthv)
|
||||
, _gdepthh (other._gdepthh)
|
||||
, _ddepthv (other._ddepthv)
|
||||
, _ddepthh (other._ddepthh)
|
||||
, _ddepthc (other._ddepthc)
|
||||
, _cg (NULL)
|
||||
, _rg (NULL)
|
||||
, _extensionCaps (other._extensionCaps)
|
||||
|
@ -288,7 +318,7 @@ namespace Anabatic {
|
|||
}
|
||||
}
|
||||
cerr << Error( "In Configuration::Concrete::_setTopRoutingLayer():\n"
|
||||
" The routing gauge <%s> has no layer named <%s>"
|
||||
" The routing gauge <%s> has no layer named <%s>"
|
||||
, getString(_rg->getName()).c_str()
|
||||
, getString(name).c_str() ) << endl;
|
||||
}
|
||||
|
@ -360,6 +390,8 @@ namespace Anabatic {
|
|||
Record* Configuration::_getRecord () const
|
||||
{
|
||||
Record* record = new Record ( _getString() );
|
||||
record->add ( getSlot( "_gdepthh" , _gdepthh ) );
|
||||
record->add ( getSlot( "_gdepthv" , _gdepthv ) );
|
||||
record->add ( getSlot( "_rg" , _rg ) );
|
||||
record->add ( getSlot( "_gmetalh" , _gmetalh ) );
|
||||
record->add ( getSlot( "_gmetalv" , _gmetalv ) );
|
||||
|
|
|
@ -39,6 +39,9 @@ namespace Anabatic {
|
|||
const BaseFlags Flags::MatrixGCell = (1L << 9);
|
||||
const BaseFlags Flags::IoPadGCell = (1L << 10);
|
||||
const BaseFlags Flags::Saturated = (1L << 11);
|
||||
const BaseFlags Flags::StdCellRow = (1L << 12);
|
||||
const BaseFlags Flags::ChannelRow = (1L << 13);
|
||||
const BaseFlags Flags::IllimitedCapacity = (1L << 5);
|
||||
// Flags for Anabatic objects states only.
|
||||
const BaseFlags Flags::DemoMode = (1L << 5);
|
||||
const BaseFlags Flags::WarnOnGCellOverload = (1L << 6);
|
||||
|
@ -56,7 +59,19 @@ namespace Anabatic {
|
|||
const BaseFlags Flags::EndsMask = Source|Target;
|
||||
const BaseFlags Flags::DirectionMask = Horizontal|Vertical;
|
||||
const BaseFlags Flags::DestroyMask = DestroyGCell|DestroyBaseContact|DestroyBaseSegment;
|
||||
const BaseFlags Flags::GCellTypeMask = DeviceGCell|HChannelGCell|VChannelGCell|StrutGCell|MatrixGCell|IoPadGCell;
|
||||
const BaseFlags Flags::GCellTypeMask = DeviceGCell
|
||||
| HChannelGCell
|
||||
| VChannelGCell
|
||||
| StrutGCell
|
||||
| MatrixGCell
|
||||
| IoPadGCell
|
||||
| StdCellRow
|
||||
| ChannelRow;
|
||||
const BaseFlags Flags::RowGCellMask = StdCellRow|ChannelRow;
|
||||
const BaseFlags Flags::AnalogGCellMask = DeviceGCell
|
||||
| HChannelGCell
|
||||
| VChannelGCell
|
||||
| StrutGCell;
|
||||
// Flags for functions arguments only.
|
||||
const BaseFlags Flags::Create = (1L << 5);
|
||||
const BaseFlags Flags::WithPerpands = (1L << 6);
|
||||
|
@ -146,20 +161,22 @@ namespace Anabatic {
|
|||
string Flags::_getString () const
|
||||
{
|
||||
string s = "";
|
||||
s += (_flags & (uint64_t)Horizontal ) ? 'h' : '-';
|
||||
s += (_flags & (uint64_t)Vertical ) ? 'v' : '-';
|
||||
s += (_flags & (uint64_t)Source ) ? 'S' : '-';
|
||||
s += (_flags & (uint64_t)Target ) ? 'T' : '-';
|
||||
s += (_flags & (uint64_t)DeviceGCell ) ? 'd' : '-';
|
||||
s += (_flags & (uint64_t)Horizontal ) ? 'h' : '-';
|
||||
s += (_flags & (uint64_t)Vertical ) ? 'v' : '-';
|
||||
s += (_flags & (uint64_t)Source ) ? 'S' : '-';
|
||||
s += (_flags & (uint64_t)Target ) ? 'T' : '-';
|
||||
s += (_flags & (uint64_t)DeviceGCell ) ? 'd' : '-';
|
||||
s += (_flags & (uint64_t)HChannelGCell) ? 'c' : '-';
|
||||
s += (_flags & (uint64_t)VChannelGCell) ? 'c' : '-';
|
||||
s += (_flags & (uint64_t)StrutGCell ) ? 's' : '-';
|
||||
s += (_flags & (uint64_t)MatrixGCell ) ? 'm' : '-';
|
||||
s += (_flags & (uint64_t)MatrixGCell ) ? 'm' : '-';
|
||||
s += (_flags & (uint64_t)StdCellRow ) ? 'S' : '-';
|
||||
s += (_flags & (uint64_t)ChannelRow ) ? 'C' : '-';
|
||||
s += ",";
|
||||
s += (_flags & (uint64_t)Invalidated ) ? 'i' : '-';
|
||||
s += (_flags & (uint64_t)DestroyGCell ) ? 'D' : '-';
|
||||
s += (_flags & (uint64_t)AboveLayer ) ? 'A' : '-';
|
||||
s += (_flags & (uint64_t)BelowLayer ) ? 'B' : '-';
|
||||
s += (_flags & (uint64_t)Invalidated ) ? 'i' : '-';
|
||||
s += (_flags & (uint64_t)DestroyGCell ) ? 'D' : '-';
|
||||
s += (_flags & (uint64_t)AboveLayer ) ? 'A' : '-';
|
||||
s += (_flags & (uint64_t)BelowLayer ) ? 'B' : '-';
|
||||
|
||||
return s;
|
||||
}
|
||||
|
|
|
@ -276,7 +276,10 @@ namespace Anabatic {
|
|||
) return true;
|
||||
else {
|
||||
if ((v2->getGCell()->isStrut())){
|
||||
if (e->isMaxCapacity(net)) return true;
|
||||
if (e->isMaxCapacity(net)) {
|
||||
cdebug_log(112,0) << "Overcapacity:" << e << endl;
|
||||
return true;
|
||||
}
|
||||
else return false;
|
||||
} else return false;
|
||||
}
|
||||
|
@ -292,7 +295,7 @@ namespace Anabatic {
|
|||
return Point(0,0);
|
||||
}
|
||||
|
||||
if (vnext->getGCell()->isMatrix()) {
|
||||
if (not vnext->getGCell()->isAnalog()) {
|
||||
cdebug_tabw(112,-1);
|
||||
return Point(vnext->getGCell()->getXCenter(), vnext->getGCell()->getYCenter());
|
||||
}
|
||||
|
@ -1283,7 +1286,7 @@ namespace Anabatic {
|
|||
Vertex* seed = gcell->getObserver<Vertex>(GCell::Observable::Vertex);
|
||||
GCell* gseed = seed->getGCell();
|
||||
|
||||
if (!gseed->isMatrix()) _setSourcesGRAData( seed, rp ); // ANALOG
|
||||
if (gseed->isAnalog()) _setSourcesGRAData( seed, rp ); // ANALOG
|
||||
|
||||
if (seed->getConnexId() < 0) {
|
||||
VertexSet connecteds;
|
||||
|
@ -1311,7 +1314,7 @@ namespace Anabatic {
|
|||
}
|
||||
|
||||
_searchArea.inflate( _searchAreaHalo );
|
||||
cdebug_log(112,0) << "Search halo: " << _searchAreaHalo << endl;
|
||||
cdebug_log(112,0) << "Search halo: " << DbU::getValueString(_searchAreaHalo) << endl;
|
||||
cdebug_log(112,0) << "Search area: " << _searchArea << endl;
|
||||
|
||||
setAxisTargets();
|
||||
|
@ -1547,14 +1550,14 @@ namespace Anabatic {
|
|||
continue;
|
||||
}
|
||||
|
||||
if (_checkFrom2(edge, current)) { // ANALOG
|
||||
if ((gcurrent->isAnalog()) and _checkFrom2(edge, current)) {
|
||||
cdebug_log(111,0) << "| Reject: _checkFrom2()" << endl;
|
||||
continue;
|
||||
}
|
||||
|
||||
GCell* gneighbor = edge->getOpposite(current->getGCell());
|
||||
Vertex* vneighbor = gneighbor->getObserver<Vertex>( GCell::Observable::Vertex );
|
||||
if (not gneighbor->isMatrix()) vneighbor->createAData();
|
||||
if (gneighbor->isAnalog()) vneighbor->createAData();
|
||||
|
||||
cdebug_log(111,0) << "+ Neighbor:" << vneighbor << endl;
|
||||
|
||||
|
@ -1573,7 +1576,7 @@ namespace Anabatic {
|
|||
cdebug_log(111,0) << "| From: " << current->getFrom()->getOpposite(gcurrent) << endl;
|
||||
//current->getIntervFrom().print();
|
||||
}
|
||||
if (current->getFrom2()) {
|
||||
if (gcurrent->isAnalog() and current->getFrom2()) {
|
||||
cdebug_log(111,0) << "| From2: " << current->getFrom2()->getOpposite(gcurrent) << endl;
|
||||
current->getIntervFrom2().print();
|
||||
}
|
||||
|
@ -1584,14 +1587,17 @@ namespace Anabatic {
|
|||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
DbU::Unit distance = _distanceCb( current, vneighbor, edge );
|
||||
cdebug_log(111,0) << "distance:" << Vertex::getValueString(distance) << endl;
|
||||
|
||||
bool isDistance2shorter = false;
|
||||
if (gcurrent->isAnalog() and gneighbor->isAnalog())
|
||||
_isDistance2Shorter ( distance, current, vneighbor, edge );
|
||||
|
||||
bool isDistance2shorter = _isDistance2Shorter ( distance, current, vneighbor, edge ); // ANALOG
|
||||
|
||||
if ( (distance == vneighbor->getDistance())
|
||||
and (not gcurrent->isMatrix() )
|
||||
and (not gneighbor->isMatrix())
|
||||
and (vneighbor->getFrom2() == NULL)
|
||||
) {
|
||||
and gcurrent->isAnalog()
|
||||
and gneighbor->isAnalog()
|
||||
and (vneighbor->getFrom2() == NULL) ) {
|
||||
_pushEqualDistance( distance, isDistance2shorter, current, vneighbor, edge ); // ANALOG
|
||||
} else
|
||||
if ( (distance < vneighbor->getDistance()) and (distance != Vertex::unreachable) ) {
|
||||
|
@ -1607,17 +1613,21 @@ namespace Anabatic {
|
|||
}
|
||||
}
|
||||
cdebug_log(111,0) << "Vertex reached through a shorter path" << endl;
|
||||
_updateGRAData( vneighbor, isDistance2shorter, current ); // ANALOG
|
||||
if (gcurrent->isAnalog() and gneighbor->isAnalog())
|
||||
_updateGRAData( vneighbor, isDistance2shorter, current );
|
||||
|
||||
vneighbor->setBranchId( current->getBranchId() );
|
||||
vneighbor->setDistance( distance );
|
||||
cdebug_log(111,0) << "setFrom1: " << vneighbor << endl;
|
||||
vneighbor->setFrom ( edge );
|
||||
vneighbor->setFrom2( NULL );
|
||||
if (gneighbor->isAnalog()) vneighbor->setFrom2( NULL );
|
||||
|
||||
_queue.push( vneighbor );
|
||||
cdebug_log(111,0) << "Push: (size:" << _queue.size() << ") " << vneighbor << endl;
|
||||
} else {
|
||||
cdebug_log(111,0) << "Reject: Vertex reached through a *longer* path" << endl;
|
||||
cdebug_log(111,0) << "Reject: Vertex reached through a *longer* path or unreachable:"
|
||||
<< boolalpha << (distance == Vertex::unreachable)
|
||||
<< endl;
|
||||
}
|
||||
|
||||
cdebug_tabw(111,-1);
|
||||
|
@ -1659,39 +1669,35 @@ namespace Anabatic {
|
|||
|
||||
bool isfirst = true;
|
||||
bool useFrom2 = false;
|
||||
if (!current->getGCell()->isMatrix()){
|
||||
_initiateUpdateIntervals ( current ); // ANALOG
|
||||
if (current->getGCell()->isAnalog()) {
|
||||
_initiateUpdateIntervals( current );
|
||||
} else {
|
||||
current = current->getPredecessor();
|
||||
isfirst = false;
|
||||
|
||||
}
|
||||
cdebug_log(112,0) << "[Start WHILE]" << endl;
|
||||
|
||||
Edge* from = NULL;
|
||||
while ( current ) {
|
||||
cdebug_log(112,0) << endl;
|
||||
cdebug_log(112,0) << "| " << current << " | " << endl;
|
||||
if (current->getFrom()) cdebug_log(112,0) << " | From :" << current->getFrom()->getOpposite(current->getGCell()) << " | " << endl;
|
||||
if (current->getFrom2()) cdebug_log(112,0) << " | From2:" << current->getFrom2()->getOpposite(current->getGCell()) << " | " << endl;
|
||||
cdebug_log(112,0) << "+ " << current << endl;
|
||||
if (current->getFrom()) cdebug_log(112,0) << "| From:" << current->getFrom()->getOpposite(current->getGCell()) << endl;
|
||||
|
||||
if (!current->getGCell()->isMatrix()){
|
||||
//////////////////////////////////////////////////////////////////////////////////////////// ANALOG
|
||||
if (_updateIntervals ( isfirst, current, useFrom2, branchId, from )) break;
|
||||
if (current->getGCell()->isAnalog()) {
|
||||
if (current->getFrom2()) cdebug_log(112,0) << "| From2:" << current->getFrom2()->getOpposite(current->getGCell()) << endl;
|
||||
|
||||
if (_updateIntervals( isfirst, current, useFrom2, branchId, from )) break;
|
||||
Vertex* next = NULL;
|
||||
next = current->getPredecessor();
|
||||
|
||||
if( current->isFromFrom2()) {
|
||||
cdebug_log(112,0) << "ISFROMFROM2: " << current << endl;
|
||||
if (current->isFromFrom2()) {
|
||||
cdebug_log(112,0) << "| isFromFrom2:true (" << current << ")" << endl;
|
||||
useFrom2 = true;
|
||||
current->unsetFlags(Vertex::UseFromFrom2);
|
||||
current->unsetFlags( Vertex::UseFromFrom2 );
|
||||
} else {
|
||||
cdebug_log(112,0) << "ISNOT FROMFROM2" << endl;
|
||||
cdebug_log(112,0) << "| isFromFrom2:false" << endl;
|
||||
useFrom2 = false;
|
||||
}
|
||||
cdebug_log(112,0) << "next: " << next << endl;
|
||||
cdebug_log(112,0) << "| Next: " << next << endl;
|
||||
current = next;
|
||||
////////////////////////////////////////////////////////////////////////////////////////////
|
||||
} else {
|
||||
current->incDegree();
|
||||
if (current->getConnexId() == _connectedsId) break;
|
||||
|
@ -1720,8 +1726,8 @@ namespace Anabatic {
|
|||
NetRoutingState* state = NetRoutingExtension::get( _net );
|
||||
|
||||
for ( Vertex* startVertex : _sources ) {
|
||||
|
||||
if (not startVertex->getFrom()) continue;
|
||||
|
||||
if ( not startVertex->hasGContact(_net)
|
||||
and not startVertex->getRpCount()
|
||||
and (startVertex->getDegree() < 3)
|
||||
|
@ -1729,11 +1735,12 @@ namespace Anabatic {
|
|||
|
||||
Vertex* source = startVertex;
|
||||
while ( source ) {
|
||||
source->resetIntervals(); // ANALOG
|
||||
|
||||
cdebug_log(112,0) << "* " << source << endl;
|
||||
|
||||
Edge* from = source->getFrom();
|
||||
bool isAnalog = source->getGCell()->isAnalog();
|
||||
if (isAnalog) source->resetIntervals();
|
||||
|
||||
Edge* from = source->getFrom();
|
||||
vector<Edge*> aligneds;
|
||||
aligneds.push_back( from );
|
||||
|
||||
|
@ -1751,13 +1758,21 @@ namespace Anabatic {
|
|||
while ( true ) {
|
||||
from = target->getFrom();
|
||||
if ( not from
|
||||
or not (target->getGCell()->isMatrix())
|
||||
or (target->getGCell()->isAnalog())
|
||||
or (target->hasGContact(_net))
|
||||
or (target->getRpCount())
|
||||
or (target->getDegree() > 2)
|
||||
or (aligneds.back()->isHorizontal() xor from->isHorizontal())
|
||||
or not constraint.intersect(from->getSide())) break;
|
||||
|
||||
// U-turn detection. All edges must have the same *spin*.
|
||||
if ( (aligneds[0]->getSource() == source->getGCell())
|
||||
xor (from ->getSource() == target->getGCell()) ) break;
|
||||
|
||||
// Always break vertical in channel (2M routing).
|
||||
if (target->getGCell()->isChannelRow() and aligneds.back()->isVertical())
|
||||
break;
|
||||
|
||||
aligneds.push_back( from );
|
||||
constraint.merge( from->getSide() );
|
||||
|
||||
|
@ -1772,17 +1787,20 @@ namespace Anabatic {
|
|||
Contact* targetContact = target->hasGContact( _net );
|
||||
Segment* segment = NULL;
|
||||
|
||||
|
||||
if (not targetContact) {
|
||||
if (target->getFrom()) targetContact = target->getGContact( _net );
|
||||
else targetContact = target->breakGoThrough( _net );
|
||||
}
|
||||
|
||||
cdebug_log(112,0) << "| aligneds.front():" << aligneds.front()
|
||||
<< " isHorizontal():" << aligneds.front()->isHorizontal() << endl;
|
||||
|
||||
if (aligneds.front()->isHorizontal()) {
|
||||
if (sourceContact->getX() > targetContact->getX())
|
||||
std::swap( sourceContact, targetContact );
|
||||
|
||||
DbU::Unit width = Session::getPitch(Hurricane::DataBase::getDB()->getTechnology()->getLayer("METAL2")); //DbU::fromLambda(2.0);
|
||||
//DbU::Unit width = Session::getPitch(Hurricane::DataBase::getDB()->getTechnology()->getLayer("METAL2")); //DbU::fromLambda(2.0);
|
||||
DbU::Unit width = Session::getGHorizontalPitch(); //DbU::fromLambda(2.0);
|
||||
if (state) width *= state->getWPitch();
|
||||
|
||||
segment = Horizontal::create( sourceContact
|
||||
|
@ -1792,14 +1810,15 @@ namespace Anabatic {
|
|||
, width
|
||||
);
|
||||
for ( Edge* through : aligneds ) through->add( segment );
|
||||
if (state){
|
||||
if (state) {
|
||||
if (state->isSymmetric()) _createSelfSymSeg ( segment );
|
||||
}
|
||||
} else {
|
||||
if (sourceContact->getY() > targetContact->getY())
|
||||
std::swap( sourceContact, targetContact );
|
||||
|
||||
DbU::Unit width = Session::getPitch(Hurricane::DataBase::getDB()->getTechnology()->getLayer("METAL3")); //DbU::fromLambda(2.0);
|
||||
//DbU::Unit width = Session::getPitch(Hurricane::DataBase::getDB()->getTechnology()->getLayer("METAL3")); //DbU::fromLambda(2.0);
|
||||
DbU::Unit width = Session::getGVerticalPitch(); //DbU::fromLambda(2.0);
|
||||
if (state) width *= state->getWPitch();
|
||||
|
||||
segment = Vertical::create( sourceContact
|
||||
|
@ -1809,16 +1828,17 @@ namespace Anabatic {
|
|||
, width
|
||||
);
|
||||
for ( Edge* through : aligneds ) through->add( segment );
|
||||
if (state){
|
||||
if (state) {
|
||||
if (state->isSymmetric()) _createSelfSymSeg ( segment );
|
||||
}
|
||||
}
|
||||
|
||||
cdebug_log(112,0) << "|| " << segment << endl;
|
||||
//cdebug_log(112,0) << "| " << "break (turn, branch or terminal)." << endl;
|
||||
Vertex* stc = source;
|
||||
cdebug_log(112,0) << "| break (U-turn, turn, branch or terminal)." << endl;
|
||||
cdebug_log(112,0) << "| " << segment << endl;
|
||||
|
||||
Vertex* prevSource = source;
|
||||
source = (target->getFrom()) ? target : NULL;
|
||||
stc->clearFrom2();
|
||||
if (isAnalog) prevSource->clearFrom2();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -184,11 +184,13 @@ namespace Anabatic {
|
|||
_realOccupancy = occupancy;
|
||||
}
|
||||
|
||||
|
||||
void Edge::incRealOccupancy2 ( int value )
|
||||
{
|
||||
_realOccupancy += value;
|
||||
}
|
||||
|
||||
|
||||
Segment* Edge::getSegment ( const Net* owner ) const
|
||||
{
|
||||
for ( Segment* segment : _segments ) {
|
||||
|
@ -204,8 +206,8 @@ namespace Anabatic {
|
|||
Horizontal* h = dynamic_cast<Horizontal*>(segment);
|
||||
Vertical* v = dynamic_cast<Vertical*>(segment);
|
||||
DbU::Unit pitch = 0;
|
||||
if (h) pitch = Session::getPitch(Hurricane::DataBase::getDB()->getTechnology()->getLayer("METAL2"));
|
||||
if (v) pitch = Session::getPitch(Hurricane::DataBase::getDB()->getTechnology()->getLayer("METAL3"));
|
||||
if (h) pitch = Session::getGHorizontalPitch();
|
||||
if (v) pitch = Session::getGVerticalPitch();
|
||||
|
||||
incRealOccupancy( segment->getWidth()/pitch ); // Need to take the wire width into account.
|
||||
}
|
||||
|
@ -259,7 +261,7 @@ namespace Anabatic {
|
|||
if (source == _target)
|
||||
throw Error("Edge::_setSource(): Source & target are the same (%s).", getString(source).c_str() );
|
||||
|
||||
_invalidate();
|
||||
invalidate( false );
|
||||
_source=source;
|
||||
}
|
||||
|
||||
|
@ -269,26 +271,40 @@ namespace Anabatic {
|
|||
if (_source == target)
|
||||
throw Error("Edge::_setTarget(): Source & target are the same (%s).", getString(target).c_str() );
|
||||
|
||||
_invalidate();
|
||||
invalidate( false );
|
||||
_target=target;
|
||||
}
|
||||
|
||||
|
||||
void Edge::_invalidate ()
|
||||
void Edge::invalidate ( bool )
|
||||
{
|
||||
cdebug_log(110,1) << "Edge::invalidate() " << this << endl;
|
||||
|
||||
_flags |= Flags::Invalidated;
|
||||
Super::invalidate( false );
|
||||
|
||||
cdebug_tabw(110,-1);
|
||||
}
|
||||
|
||||
|
||||
void Edge::_revalidate ()
|
||||
void Edge::materialize ()
|
||||
{
|
||||
cdebug_log(110,1) << "Edge::materialize() " << this << endl;
|
||||
|
||||
Interval side = getSide();
|
||||
_axis = side.getCenter();
|
||||
_capacity = getAnabatic()->getCapacity( side, _flags );
|
||||
_axis = side.getCenter();
|
||||
|
||||
if (getSource()->isStdCellRow() and getTarget()->isStdCellRow()) _capacity = 0;
|
||||
else if (getSource()->isChannelRow() and getTarget()->isChannelRow()) _capacity = 100;
|
||||
else
|
||||
_capacity = getAnabatic()->getCapacity( side, _flags );
|
||||
|
||||
_flags.reset( Flags::Invalidated );
|
||||
cdebug_log(110,0) << "Edge::_revalidate() " << this << endl;
|
||||
cdebug_log(110,0) << "Edge::materialize() " << this << endl;
|
||||
|
||||
Super::materialize();
|
||||
|
||||
cdebug_tabw(110,-1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -301,28 +317,30 @@ namespace Anabatic {
|
|||
static DbU::Unit halfThickness = getAnabatic()->getConfiguration()->getEdgeWidth () / 2;
|
||||
static DbU::Unit halfLength = getAnabatic()->getConfiguration()->getEdgeLength() / 2;
|
||||
|
||||
if (_flags.isset(Flags::Horizontal))
|
||||
return Box( _target->getXMin() - halfLength, _axis - halfThickness
|
||||
, _target->getXMin() + halfLength, _axis + halfThickness
|
||||
);
|
||||
Box bb;
|
||||
|
||||
return Box( _axis - halfThickness, _target->getYMin() - halfLength
|
||||
if (_flags.isset(Flags::Horizontal))
|
||||
bb = Box( _target->getXMin() - halfLength, _axis - halfThickness
|
||||
, _target->getXMin() + halfLength, _axis + halfThickness
|
||||
);
|
||||
else
|
||||
bb = Box( _axis - halfThickness, _target->getYMin() - halfLength
|
||||
, _axis + halfThickness, _target->getYMin() + halfLength
|
||||
);
|
||||
|
||||
return bb;
|
||||
}
|
||||
|
||||
|
||||
bool Edge::isMaxCapacity ( Net* net ) const
|
||||
{
|
||||
if (net){
|
||||
if (net) {
|
||||
cdebug_log(112,0) << "_capacity:" << _capacity << endl;
|
||||
|
||||
Hurricane::NetRoutingState* state = Hurricane::NetRoutingExtension::get( net );
|
||||
//cerr << "bool Edge::isMaxCapacity ( Net* net ) const: " << net << endl;
|
||||
//cerr << "WPitch: " << state->getWPitch() << endl;
|
||||
|
||||
return ( (_realOccupancy +state->getWPitch()) > _capacity ) ? true : false;
|
||||
} else {
|
||||
return ( _realOccupancy >= _capacity ) ? true : false;
|
||||
return ((_realOccupancy + state->getWPitch()) > _capacity) ? true : false;
|
||||
}
|
||||
return (_realOccupancy >= _capacity) ? true : false;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -63,10 +63,10 @@ namespace Anabatic {
|
|||
{
|
||||
cdebug_log(110,0) << "GCell_Edges::Locator::progress() [from] " << _stateFlags << " iedge:" << _iedge << endl;
|
||||
cdebug_log(110,0) << " _filterFlags:" << _filterFlags << endl;
|
||||
cdebug_log(110,0) << " East:" << _gcell->getEastEdges().size()
|
||||
<< " North:" << _gcell->getNorthEdges().size()
|
||||
<< " West:" << _gcell->getWestEdges().size()
|
||||
<< " South:" << _gcell->getSouthEdges().size() << endl;
|
||||
cdebug_log(110,0) << " East:" << _gcell->getEastEdges ().size()
|
||||
<< " North:" << _gcell->getNorthEdges().size()
|
||||
<< " West:" << _gcell->getWestEdges ().size()
|
||||
<< " South:" << _gcell->getSouthEdges().size() << endl;
|
||||
cdebug_log(110,0) << this << endl;
|
||||
|
||||
++_iedge;
|
||||
|
|
|
@ -331,13 +331,13 @@ namespace Anabatic {
|
|||
if (not anabatic) throw Error( "GCell::create(): NULL anabatic argument." );
|
||||
if (not anabatic->getCell()) throw Error( "GCell::create(): AnabaticEngine has no Cell loaded." );
|
||||
|
||||
anabatic->openSession();
|
||||
bool reUseSession = Session::isOpen();
|
||||
if (not reUseSession) anabatic->openSession();
|
||||
GCell* gcell = new GCell ( anabatic
|
||||
, anabatic->getCell()->getAbutmentBox().getXMin()
|
||||
, anabatic->getCell()->getAbutmentBox().getYMin() );
|
||||
gcell->_postCreate();
|
||||
gcell->_revalidate();
|
||||
Session::close();
|
||||
if (not reUseSession) Session::close();
|
||||
|
||||
return gcell;
|
||||
}
|
||||
|
@ -661,9 +661,6 @@ namespace Anabatic {
|
|||
_moveEdges( chunk, iedge+1, Flags::NorthSide );
|
||||
}
|
||||
|
||||
_revalidate();
|
||||
chunk->_revalidate();
|
||||
|
||||
cdebug_tabw(110,-1);
|
||||
|
||||
return chunk;
|
||||
|
@ -713,9 +710,6 @@ namespace Anabatic {
|
|||
_moveEdges( chunk, iedge+1, Flags::EastSide );
|
||||
}
|
||||
|
||||
_revalidate();
|
||||
chunk->_revalidate();
|
||||
|
||||
cdebug_tabw(110,-1);
|
||||
|
||||
return chunk;
|
||||
|
@ -787,21 +781,33 @@ namespace Anabatic {
|
|||
}
|
||||
|
||||
|
||||
void GCell::_revalidate ()
|
||||
void GCell::invalidate ( bool propagateFlag )
|
||||
{
|
||||
cdebug_log(110,1) << "GCell::revalidate() " << this << endl;
|
||||
cdebug_log(110,1) << "West side." << endl; for ( Edge* edge : _westEdges ) edge->revalidate(); cdebug_tabw(110,-1);
|
||||
cdebug_log(110,1) << "East side." << endl; for ( Edge* edge : _eastEdges ) edge->revalidate(); cdebug_tabw(110,-1);
|
||||
cdebug_log(110,1) << "South side." << endl; for ( Edge* edge : _southEdges ) edge->revalidate(); cdebug_tabw(110,-1);
|
||||
cdebug_log(110,1) << "North side." << endl; for ( Edge* edge : _northEdges ) edge->revalidate(); cdebug_tabw(110,-1);
|
||||
cdebug_log(110,1) << "GCell::invalidate() " << this << endl;
|
||||
Super::invalidate( propagateFlag );
|
||||
|
||||
cdebug_log(110,1) << "West side." << endl; for ( Edge* edge : _westEdges ) edge->invalidate(); cdebug_tabw(110,-1);
|
||||
cdebug_log(110,1) << "East side." << endl; for ( Edge* edge : _eastEdges ) edge->invalidate(); cdebug_tabw(110,-1);
|
||||
cdebug_log(110,1) << "South side." << endl; for ( Edge* edge : _southEdges ) edge->invalidate(); cdebug_tabw(110,-1);
|
||||
cdebug_log(110,1) << "North side." << endl; for ( Edge* edge : _northEdges ) edge->invalidate(); cdebug_tabw(110,-1);
|
||||
|
||||
cdebug_tabw(110,-1);
|
||||
}
|
||||
|
||||
|
||||
void GCell::materialize ()
|
||||
{
|
||||
cdebug_log(110,1) << "GCell::materialize() " << this << endl;
|
||||
|
||||
if (_xmin > getXMax()+1)
|
||||
cerr << Error( "GCell::_revalidate(): %s, X Min is greater than Max.", getString(this).c_str() );
|
||||
cerr << Error( "GCell::materialize(): %s, X Min is greater than Max.", getString(this).c_str() );
|
||||
if (_ymin > getYMax()+1)
|
||||
cerr << Error( "GCell::_revalidate(): %s, Y Min is greater than Max.", getString(this).c_str() );
|
||||
cerr << Error( "GCell::materialize(): %s, Y Min is greater than Max.", getString(this).c_str() );
|
||||
|
||||
_anabatic->_updateLookup( this );
|
||||
//_anabatic->getMatrix()->show();
|
||||
Super::materialize();
|
||||
|
||||
cdebug_tabw(110,-1);
|
||||
}
|
||||
|
||||
|
@ -898,36 +904,31 @@ namespace Anabatic {
|
|||
}
|
||||
|
||||
|
||||
void GCell::setXY ( DbU::Unit x, DbU::Unit y )
|
||||
void GCell::setSouthWestCorner ( DbU::Unit x, DbU::Unit y )
|
||||
{
|
||||
UpdateSession::open();
|
||||
_xmin = x;
|
||||
_ymin = y;
|
||||
UpdateSession::close();
|
||||
}
|
||||
DbU::Unit dx = x - _xmin;
|
||||
DbU::Unit dy = y - _ymin;
|
||||
|
||||
|
||||
void GCell::updateContactsPosition ()
|
||||
{
|
||||
UpdateSession::open();
|
||||
DbU::Unit xc = (getXMax() + getXMin())/2;
|
||||
DbU::Unit yc = (getYMax() + getYMin())/2;
|
||||
for (vector<Contact*>::iterator it = _gcontacts.begin(); it != _gcontacts.end(); it++){
|
||||
for ( Component* c : (*it)->getSlaveComponents() ){
|
||||
Horizontal* h = dynamic_cast<Horizontal*>(c);
|
||||
Vertical* v = dynamic_cast<Vertical*> (c);
|
||||
if (h){
|
||||
//if (h->getY() == (*it)->getY()) h->setY(yc);
|
||||
h->setY(yc);
|
||||
} else if (v) {
|
||||
//if (v->getX() == (*it)->getX()) v->setX(xc);
|
||||
v->setX(xc);
|
||||
for ( Contact* contact : _gcontacts ) {
|
||||
Point position = contact->getPosition().translate( dx, dy );
|
||||
|
||||
for ( Component* component : contact->getSlaveComponents() ) {
|
||||
Horizontal* horizontal = dynamic_cast<Horizontal*>( component );
|
||||
if (horizontal) {
|
||||
horizontal->setY( position.getY() );
|
||||
} else {
|
||||
Vertical* vertical = dynamic_cast<Vertical*>( component );
|
||||
vertical->setX( position.getX() );
|
||||
}
|
||||
}
|
||||
(*it)->setX(xc);
|
||||
(*it)->setY(yc);
|
||||
|
||||
if (not contact->getAnchor()) contact->setPosition( position );
|
||||
}
|
||||
UpdateSession::close();
|
||||
|
||||
_xmin = x;
|
||||
_ymin = y;
|
||||
|
||||
invalidate( false );
|
||||
}
|
||||
|
||||
|
||||
|
@ -1522,6 +1523,19 @@ namespace Anabatic {
|
|||
}
|
||||
|
||||
|
||||
size_t GCell::getNetCount () const
|
||||
{
|
||||
set<Net*> nets;
|
||||
|
||||
for ( Edge* edge : _westEdges ) for ( Segment* segment : edge->getSegments() ) nets.insert( segment->getNet() );
|
||||
for ( Edge* edge : _eastEdges ) for ( Segment* segment : edge->getSegments() ) nets.insert( segment->getNet() );
|
||||
for ( Edge* edge : _northEdges ) for ( Segment* segment : edge->getSegments() ) nets.insert( segment->getNet() );
|
||||
for ( Edge* edge : _southEdges ) for ( Segment* segment : edge->getSegments() ) nets.insert( segment->getNet() );
|
||||
|
||||
return nets.size();
|
||||
}
|
||||
|
||||
|
||||
void GCell::rpDesaturate ( set<Net*>& globalNets )
|
||||
{
|
||||
set<RoutingPad*> rps;
|
||||
|
@ -1702,6 +1716,7 @@ namespace Anabatic {
|
|||
record->add( getSlot("_northEdges" , &_northEdges) );
|
||||
record->add( DbU::getValueSlot("_xmin", &_xmin) );
|
||||
record->add( DbU::getValueSlot("_ymin", &_ymin) );
|
||||
record->add( getSlot ( "_gcontacts", &_gcontacts ) );
|
||||
record->add( getSlot ( "_vsegments", &_vsegments ) );
|
||||
record->add( getSlot ( "_hsegments", &_hsegments ) );
|
||||
record->add( getSlot ( "_contacts" , &_contacts ) );
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -117,7 +117,7 @@ namespace Anabatic {
|
|||
DbU::Unit dy = updateArea.getYMin() - _area.getYMin();
|
||||
|
||||
cdebug_log(110,0) << "raw_i:" << (dx / _side + ((dx%_side) ? 1 : 0))
|
||||
<< " raw_j:" << (dy / _side + ((dy%_side) ? 1 : 0)) << endl;
|
||||
<< " raw_j:" << (dy / _side + ((dy%_side) ? 1 : 0)) << endl;
|
||||
cdebug_log(110,0) << "indexMin:" << indexMin << endl;
|
||||
cdebug_log(110,0) << "indexMax:" << indexMax << endl;
|
||||
cdebug_log(110,0) << "xspan: " << xspan << endl;
|
||||
|
@ -138,6 +138,13 @@ namespace Anabatic {
|
|||
}
|
||||
|
||||
|
||||
void Matrix::resize ( Cell* cell, const vector<GCell*>& gcells )
|
||||
{
|
||||
setCell( cell, _side );
|
||||
for ( GCell* gcell : gcells ) updateLookup( gcell );
|
||||
}
|
||||
|
||||
|
||||
void Matrix::show () const
|
||||
{
|
||||
cdebug_log(111,0) << this << endl;
|
||||
|
|
|
@ -230,6 +230,7 @@ namespace Anabatic {
|
|||
inline Net* getBlockageNet () const;
|
||||
inline const ChipTools& getChipTools () const;
|
||||
inline const vector<NetData*>& getNetOrdering () const;
|
||||
void invalidateRoutingPads ();
|
||||
void updateDensity ();
|
||||
size_t checkGCellDensities ();
|
||||
inline void setGlobalThreshold ( DbU::Unit );
|
||||
|
@ -277,6 +278,7 @@ namespace Anabatic {
|
|||
inline void _add ( GCell* );
|
||||
inline void _remove ( GCell* );
|
||||
inline void _updateLookup ( GCell* );
|
||||
inline void _resizeMatrix ();
|
||||
inline bool _inDestroy () const;
|
||||
// Inspector support.
|
||||
virtual Record* _getRecord () const;
|
||||
|
@ -346,6 +348,7 @@ namespace Anabatic {
|
|||
inline void AnabaticEngine::setGlobalThreshold ( DbU::Unit threshold ) { _configuration->setGlobalThreshold(threshold); }
|
||||
inline const NetDatas& AnabaticEngine::getNetDatas () const { return _netDatas; }
|
||||
inline void AnabaticEngine::_updateLookup ( GCell* gcell ) { _matrix.updateLookup(gcell); }
|
||||
inline void AnabaticEngine::_resizeMatrix () { _matrix.resize( getCell(), getGCells() ); }
|
||||
inline bool AnabaticEngine::_inDestroy () const { return _flags & Flags::DestroyMask; }
|
||||
|
||||
inline void AnabaticEngine::_add ( GCell* gcell )
|
||||
|
|
|
@ -97,7 +97,7 @@ namespace Anabatic {
|
|||
inline void setSizes ( DbU::Unit width, DbU::Unit height );
|
||||
inline void setX ( DbU::Unit );
|
||||
inline void setY ( DbU::Unit );
|
||||
inline void setPosition ( DbU::Unit width, DbU::Unit height );
|
||||
inline void setPosition ( DbU::Unit x, DbU::Unit y );
|
||||
inline void setPosition ( const Point& );
|
||||
inline void setDx ( DbU::Unit );
|
||||
inline void setDy ( DbU::Unit );
|
||||
|
|
|
@ -49,7 +49,7 @@ namespace Anabatic {
|
|||
virtual Interval getSourceConstraints ( Flags flags=0 ) const;
|
||||
virtual Interval getTargetConstraints ( Flags flags=0 ) const;
|
||||
virtual Flags getDirection () const;
|
||||
virtual size_t getGCells ( vector<GCell*>& ) const;
|
||||
virtual bool getGCells ( vector<GCell*>& ) const;
|
||||
// Modifiers.
|
||||
virtual void setDuSource ( DbU::Unit );
|
||||
virtual void setDuTarget ( DbU::Unit );
|
||||
|
|
|
@ -226,7 +226,7 @@ namespace Anabatic {
|
|||
inline uint64_t getFlags () const;
|
||||
virtual Flags getDirection () const = 0;
|
||||
inline GCell* getGCell () const;
|
||||
virtual size_t getGCells ( vector<GCell*>& ) const = 0;
|
||||
virtual bool getGCells ( vector<GCell*>& ) const = 0;
|
||||
inline AutoContact* getAutoSource () const;
|
||||
inline AutoContact* getAutoTarget () const;
|
||||
AutoContact* getOppositeAnchor ( AutoContact* ) const;
|
||||
|
|
|
@ -49,7 +49,7 @@ namespace Anabatic {
|
|||
virtual Interval getSourceConstraints ( Flags flags=0 ) const;
|
||||
virtual Interval getTargetConstraints ( Flags flags=0 ) const;
|
||||
virtual Flags getDirection () const;
|
||||
virtual size_t getGCells ( vector<GCell*>& ) const;
|
||||
virtual bool getGCells ( vector<GCell*>& ) const;
|
||||
// Modifiers.
|
||||
virtual void setDuSource ( DbU::Unit );
|
||||
virtual void setDuTarget ( DbU::Unit );
|
||||
|
|
|
@ -53,6 +53,8 @@ namespace Anabatic {
|
|||
// Class : "Anabatic::Configuration".
|
||||
|
||||
class Configuration {
|
||||
public:
|
||||
static const size_t ndepth = (size_t)-1;
|
||||
public:
|
||||
// Constructor & Destructor.
|
||||
Configuration ( const CellGauge* cg=NULL, const RoutingGauge* rg=NULL );
|
||||
|
@ -65,6 +67,22 @@ namespace Anabatic {
|
|||
const Layer* getGContactLayer () const;
|
||||
const Layer* getGHorizontalLayer () const;
|
||||
const Layer* getGVerticalLayer () const;
|
||||
inline size_t getGVerticalDepth () const;
|
||||
inline DbU::Unit getGVerticalPitch () const;
|
||||
inline size_t getGHorizontalDepth () const;
|
||||
inline DbU::Unit getGHorizontalPitch () const;
|
||||
inline size_t getDVerticalDepth () const;
|
||||
inline const Layer* getDVerticalLayer () const;
|
||||
inline DbU::Unit getDVerticalWidth () const;
|
||||
inline DbU::Unit getDVerticalPitch () const;
|
||||
inline size_t getDHorizontalDepth () const;
|
||||
inline const Layer* getDHorizontalLayer () const;
|
||||
inline DbU::Unit getDHorizontalWidth () const;
|
||||
inline DbU::Unit getDHorizontalPitch () const;
|
||||
inline size_t getDContactDepth () const;
|
||||
inline const Layer* getDContactLayer () const;
|
||||
inline DbU::Unit getDContactWidth () const;
|
||||
inline DbU::Unit getDContactPitch () const;
|
||||
size_t getDepth () const;
|
||||
size_t getAllowedDepth () const;
|
||||
size_t getLayerDepth ( const Layer* ) const;
|
||||
|
@ -106,6 +124,11 @@ namespace Anabatic {
|
|||
const Layer* _gmetalh;
|
||||
const Layer* _gmetalv;
|
||||
const Layer* _gcontact;
|
||||
size_t _gdepthv;
|
||||
size_t _gdepthh;
|
||||
size_t _ddepthv;
|
||||
size_t _ddepthh;
|
||||
size_t _ddepthc;
|
||||
CellGauge* _cg;
|
||||
RoutingGauge* _rg;
|
||||
std::vector<DbU::Unit> _extensionCaps;
|
||||
|
@ -124,6 +147,24 @@ namespace Anabatic {
|
|||
};
|
||||
|
||||
|
||||
inline size_t Configuration::getGHorizontalDepth () const { return _gdepthh; }
|
||||
inline size_t Configuration::getGVerticalDepth () const { return _gdepthv; }
|
||||
inline DbU::Unit Configuration::getGHorizontalPitch () const { return getPitch( getGHorizontalDepth(), Flags::NoFlags ); }
|
||||
inline DbU::Unit Configuration::getGVerticalPitch () const { return getPitch( getGVerticalDepth (), Flags::NoFlags ); }
|
||||
inline size_t Configuration::getDVerticalDepth () const { return _ddepthv; }
|
||||
inline const Layer* Configuration::getDVerticalLayer () const { return getRoutingLayer( getDVerticalDepth() ); }
|
||||
inline DbU::Unit Configuration::getDVerticalWidth () const { return getWireWidth ( getDVerticalDepth() ); }
|
||||
inline DbU::Unit Configuration::getDVerticalPitch () const { return getPitch ( getDVerticalDepth(), Flags::NoFlags ); }
|
||||
inline size_t Configuration::getDHorizontalDepth () const { return _ddepthh; }
|
||||
inline const Layer* Configuration::getDHorizontalLayer () const { return getRoutingLayer( getDHorizontalDepth() ); }
|
||||
inline DbU::Unit Configuration::getDHorizontalWidth () const { return getWireWidth ( getDHorizontalDepth() ); }
|
||||
inline DbU::Unit Configuration::getDHorizontalPitch () const { return getPitch ( getDHorizontalDepth(), Flags::NoFlags ); }
|
||||
inline size_t Configuration::getDContactDepth () const { return _ddepthc; }
|
||||
inline const Layer* Configuration::getDContactLayer () const { return getContactLayer( getDContactDepth() ); }
|
||||
inline DbU::Unit Configuration::getDContactWidth () const { return getWireWidth ( getDContactDepth() ); }
|
||||
inline DbU::Unit Configuration::getDContactPitch () const { return getPitch ( getDContactDepth(), Flags::NoFlags ); }
|
||||
|
||||
|
||||
} // Anabatic namespace.
|
||||
|
||||
|
||||
|
|
|
@ -39,6 +39,10 @@ namespace Anabatic {
|
|||
static const BaseFlags MatrixGCell ; // = (1 << 9);
|
||||
static const BaseFlags IoPadGCell ; // = (1 << 10);
|
||||
static const BaseFlags Saturated ; // = (1 << 11);
|
||||
static const BaseFlags StdCellRow ; // = (1 << 12);
|
||||
static const BaseFlags ChannelRow ; // = (1 << 13);
|
||||
// Flags for Edge objects states only.
|
||||
static const BaseFlags IllimitedCapacity ; // = (1 << 5);
|
||||
// Flags for Anabatic objects states only.
|
||||
static const BaseFlags DemoMode ; // = (1 << 5);
|
||||
static const BaseFlags WarnOnGCellOverload ; // = (1 << 6);
|
||||
|
@ -57,6 +61,8 @@ namespace Anabatic {
|
|||
static const BaseFlags DirectionMask ; // = Horizontal|Vertical;
|
||||
static const BaseFlags DestroyMask ; // = DestroyGCell|DestroyBaseContact|DestroyBaseSegment;
|
||||
static const BaseFlags GCellTypeMask ; // = DeviceGCell|HChannelGCell|VChannelGCell|StrutGCell|MatrixGCell|IoPadGCell;
|
||||
static const BaseFlags RowGCellMask ; // = StdCellRow|ChannelRow;
|
||||
static const BaseFlags AnalogGCellMask ; // = DeviceGCell|HChannelGCell|VChannelGCell|StrutGCell;
|
||||
// Flags for functions arguments only.
|
||||
static const BaseFlags Create ; // = (1 << 5);
|
||||
static const BaseFlags WithPerpands ;
|
||||
|
|
|
@ -164,10 +164,13 @@ namespace Anabatic {
|
|||
inline void GRAData::printInterv () const { _interv.print() ; }
|
||||
inline void GRAData::printIntervfrom () const { _intervfrom.print(); }
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "Anabatic::Vertex".
|
||||
|
||||
class Vertex {
|
||||
public:
|
||||
static inline std::string getValueString ( DbU::Unit );
|
||||
public:
|
||||
class CompareById {
|
||||
public:
|
||||
|
@ -191,6 +194,7 @@ namespace Anabatic {
|
|||
static DbU::Unit unreachable;
|
||||
public:
|
||||
static void notify ( Vertex*, unsigned flags );
|
||||
static inline Vertex* lookup ( GCell* );
|
||||
public:
|
||||
inline Vertex ( GCell* );
|
||||
//inline Vertex ( size_t id );
|
||||
|
@ -328,6 +332,7 @@ namespace Anabatic {
|
|||
}
|
||||
|
||||
|
||||
inline Vertex* Vertex::lookup ( GCell* gcell ) { return gcell->getObserver<Vertex>(GCell::Observable::Vertex); }
|
||||
inline Vertex::~Vertex () { _gcell->setObserver( GCell::Observable::Vertex, NULL ); }
|
||||
inline Contact* Vertex::hasGContact ( Net* net ) const { return _gcell->hasGContact(net); }
|
||||
inline unsigned int Vertex::getId () const { return _id; }
|
||||
|
@ -387,6 +392,14 @@ namespace Anabatic {
|
|||
inline void Vertex::setFlags ( uint32_t mask ) { _flags |= mask ; }
|
||||
inline void Vertex::unsetFlags ( uint32_t mask ) { _flags &= ~mask; }
|
||||
|
||||
inline std::string Vertex::getValueString ( DbU::Unit distance )
|
||||
{
|
||||
if (distance == Vertex::unreachable) return "unreachable";
|
||||
if (distance == Vertex::unreached ) return "unreached";
|
||||
return DbU::getValueString( distance );
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "Anabatic::PriorityQueue".
|
||||
|
||||
|
|
|
@ -86,19 +86,18 @@ namespace Anabatic {
|
|||
inline const Flags& flags () const;
|
||||
inline Flags& flags ();
|
||||
inline void revalidate () const;
|
||||
|
||||
bool isMaxCapacity ( Net* net = NULL ) const;
|
||||
inline Flags& setFlags ( Flags mask );
|
||||
void _setSource ( GCell* );
|
||||
void _setTarget ( GCell* );
|
||||
private:
|
||||
void _invalidate ();
|
||||
void _revalidate ();
|
||||
public:
|
||||
// ExtensionGo support.
|
||||
inline const Name& staticGetName ();
|
||||
virtual const Name& getName () const;
|
||||
virtual void translate ( const DbU::Unit&, const DbU::Unit& );
|
||||
virtual Box getBoundingBox () const;
|
||||
virtual void invalidate ( bool propagateFlag=true );
|
||||
virtual void materialize ();
|
||||
public:
|
||||
// Inspector support.
|
||||
virtual string _getTypeName () const;
|
||||
|
@ -144,7 +143,7 @@ namespace Anabatic {
|
|||
inline void Edge::setHistoricCost ( float hcost ) { _historicCost = hcost; }
|
||||
inline const Flags& Edge::flags () const { return _flags; }
|
||||
inline Flags& Edge::flags () { return _flags; }
|
||||
inline void Edge::revalidate () const { /*if (_flags&Flags::Invalidated)*/ const_cast<Edge*>(this)->_revalidate(); }
|
||||
inline Flags& Edge::setFlags ( Flags mask ) { _flags |= mask; return _flags; }
|
||||
|
||||
} // Anabatic namespace.
|
||||
|
||||
|
|
|
@ -139,8 +139,12 @@ namespace Anabatic {
|
|||
inline bool isHChannel () const;
|
||||
inline bool isVChannel () const;
|
||||
inline bool isStrut () const;
|
||||
inline bool isAnalog () const;
|
||||
inline bool isMatrix () const;
|
||||
inline bool isRow () const;
|
||||
inline bool isIoPad () const;
|
||||
inline bool isStdCellRow () const;
|
||||
inline bool isChannelRow () const;
|
||||
bool isWest ( GCell* ) const;
|
||||
bool isEast ( GCell* ) const;
|
||||
bool isNorth ( GCell* ) const;
|
||||
|
@ -191,14 +195,14 @@ namespace Anabatic {
|
|||
inline const vector<Contact*>& getGContacts () const;
|
||||
Contact* breakGoThrough ( Net* net );
|
||||
bool unrefContact ( Contact* );
|
||||
void setXY ( DbU::Unit x, DbU::Unit y );
|
||||
void updateContactsPosition ();
|
||||
void setSouthWestCorner ( DbU::Unit x, DbU::Unit y );
|
||||
void cleanupGlobal ();
|
||||
inline DbU::Unit getWidth () const;
|
||||
inline DbU::Unit getHeight () const;
|
||||
// Detailed routing functions.
|
||||
bool hasFreeTrack ( size_t depth, float reserve ) const;
|
||||
inline size_t getDepth () const;
|
||||
size_t getNetCount () const;
|
||||
float getHCapacity () const;
|
||||
float getVCapacity () const;
|
||||
float getDensity ( Flags flags=Flags::NoFlags ) const;
|
||||
|
@ -251,7 +255,6 @@ namespace Anabatic {
|
|||
void _add ( Edge* edge, Flags side );
|
||||
void _remove ( Edge* edge, Flags side=Flags::AllSides );
|
||||
void _destroyEdges ();
|
||||
void _revalidate ();
|
||||
private:
|
||||
void _moveEdges ( GCell* dest, size_t ibegin, Flags flags );
|
||||
public:
|
||||
|
@ -265,6 +268,8 @@ namespace Anabatic {
|
|||
virtual const Name& getName () const;
|
||||
virtual void translate ( const DbU::Unit&, const DbU::Unit& );
|
||||
virtual Box getBoundingBox () const;
|
||||
virtual void invalidate ( bool propagateFlag=true );
|
||||
virtual void materialize ();
|
||||
public:
|
||||
// Inspector support.
|
||||
virtual string _getTypeName () const;
|
||||
|
@ -314,8 +319,12 @@ namespace Anabatic {
|
|||
inline bool GCell::isHChannel () const { return _flags & Flags::HChannelGCell; }
|
||||
inline bool GCell::isVChannel () const { return _flags & Flags::VChannelGCell; }
|
||||
inline bool GCell::isStrut () const { return _flags & Flags::StrutGCell; }
|
||||
inline bool GCell::isAnalog () const { return _flags & Flags::AnalogGCellMask; }
|
||||
inline bool GCell::isMatrix () const { return _flags & Flags::MatrixGCell; }
|
||||
inline bool GCell::isRow () const { return _flags & Flags::RowGCellMask; }
|
||||
inline bool GCell::isIoPad () const { return _flags & Flags::IoPadGCell; }
|
||||
inline bool GCell::isStdCellRow () const { return _flags & Flags::StdCellRow; }
|
||||
inline bool GCell::isChannelRow () const { return _flags & Flags::ChannelRow; }
|
||||
inline bool GCell::isSaturated () const { return _flags & Flags::Saturated; }
|
||||
inline bool GCell::isInvalidated () const { return _flags & Flags::Invalidated; }
|
||||
inline Flags GCell::getType () const { return _flags & Flags::GCellTypeMask; }
|
||||
|
|
|
@ -94,7 +94,7 @@ namespace Anabatic {
|
|||
inline GCell* getUnder ( Point ) const;
|
||||
void setCell ( Cell*, DbU::Unit side );
|
||||
void updateLookup ( GCell* );
|
||||
void resize ( Box area, DbU::Unit side );
|
||||
void resize ( Cell*, const vector<GCell*>& );
|
||||
void show () const;
|
||||
// Inspector support.
|
||||
virtual Record* _getRecord () const;
|
||||
|
|
|
@ -71,6 +71,7 @@ namespace Anabatic {
|
|||
class Session {
|
||||
public:
|
||||
// Static Methods.
|
||||
static inline bool isOpen ();
|
||||
static inline bool doDestroyBaseContact ();
|
||||
static inline bool doDestroyBaseSegment ();
|
||||
static inline bool doDestroyTool ();
|
||||
|
@ -87,6 +88,22 @@ namespace Anabatic {
|
|||
static inline CellGauge* getCellGauge ();
|
||||
static inline DbU::Unit getSliceHeight ();
|
||||
static inline DbU::Unit getSliceStep ();
|
||||
static inline size_t getGVerticalDepth ();
|
||||
static inline size_t getGHorizontalDepth ();
|
||||
static inline DbU::Unit getGHorizontalPitch ();
|
||||
static inline DbU::Unit getGVerticalPitch ();
|
||||
static inline size_t getDVerticalDepth ();
|
||||
static inline const Layer* getDVerticalLayer ();
|
||||
static inline DbU::Unit getDVerticalWidth ();
|
||||
static inline DbU::Unit getDVerticalPitch ();
|
||||
static inline size_t getDHorizontalDepth ();
|
||||
static inline const Layer* getDHorizontalLayer ();
|
||||
static inline DbU::Unit getDHorizontalWidth ();
|
||||
static inline DbU::Unit getDHorizontalPitch ();
|
||||
static inline size_t getDContactDepth ();
|
||||
static inline const Layer* getDContactLayer ();
|
||||
static inline DbU::Unit getDContactWidth ();
|
||||
static inline DbU::Unit getDContactPitch ();
|
||||
static inline RoutingGauge* getRoutingGauge ();
|
||||
static inline RoutingLayerGauge* getLayerGauge ( size_t depth );
|
||||
static inline size_t getDepth ();
|
||||
|
@ -178,6 +195,7 @@ namespace Anabatic {
|
|||
|
||||
|
||||
// Inline Functions.
|
||||
inline bool Session::isOpen () { return get() != NULL; }
|
||||
inline Technology* Session::getTechnology () { return get("getTechnology()")->_technology; }
|
||||
inline CellGauge* Session::getCellGauge () { return get("getCellGauge()")->_cellGauge; }
|
||||
inline RoutingGauge* Session::getRoutingGauge () { return get("getRoutingGauge()")->_routingGauge; }
|
||||
|
@ -206,6 +224,22 @@ namespace Anabatic {
|
|||
|
||||
inline DbU::Unit Session::getSliceHeight () { return getCellGauge()->getSliceHeight(); }
|
||||
inline DbU::Unit Session::getSliceStep () { return getCellGauge()->getSliceStep(); }
|
||||
inline size_t Session::getGVerticalDepth () { return getConfiguration()->getGVerticalDepth(); }
|
||||
inline size_t Session::getGHorizontalDepth () { return getConfiguration()->getGHorizontalDepth(); }
|
||||
inline DbU::Unit Session::getGVerticalPitch () { return getConfiguration()->getGVerticalPitch(); }
|
||||
inline DbU::Unit Session::getGHorizontalPitch () { return getConfiguration()->getGHorizontalPitch(); }
|
||||
inline size_t Session::getDVerticalDepth () { return getConfiguration()->getDVerticalDepth(); }
|
||||
inline const Layer* Session::getDVerticalLayer () { return getConfiguration()->getDVerticalLayer(); }
|
||||
inline DbU::Unit Session::getDVerticalWidth () { return getConfiguration()->getDVerticalWidth(); }
|
||||
inline DbU::Unit Session::getDVerticalPitch () { return getConfiguration()->getDVerticalPitch(); }
|
||||
inline size_t Session::getDHorizontalDepth () { return getConfiguration()->getDHorizontalDepth(); }
|
||||
inline const Layer* Session::getDHorizontalLayer () { return getConfiguration()->getDHorizontalLayer(); }
|
||||
inline DbU::Unit Session::getDHorizontalWidth () { return getConfiguration()->getDHorizontalWidth(); }
|
||||
inline DbU::Unit Session::getDHorizontalPitch () { return getConfiguration()->getDHorizontalPitch(); }
|
||||
inline size_t Session::getDContactDepth () { return getConfiguration()->getDContactDepth(); }
|
||||
inline const Layer* Session::getDContactLayer () { return getConfiguration()->getDContactLayer(); }
|
||||
inline DbU::Unit Session::getDContactWidth () { return getConfiguration()->getDContactWidth(); }
|
||||
inline DbU::Unit Session::getDContactPitch () { return getConfiguration()->getDContactPitch(); }
|
||||
inline RoutingLayerGauge* Session::getLayerGauge ( size_t depth ) { return getRoutingGauge()->getLayerGauge(depth); }
|
||||
inline size_t Session::getDepth () { return getRoutingGauge()->getDepth(); }
|
||||
inline size_t Session::getViaDepth ( const Layer* layer ) { return getRoutingGauge()->getViaDepth(layer); }
|
||||
|
|
|
@ -0,0 +1,365 @@
|
|||
// -*- mode: C++ -*-
|
||||
//
|
||||
// This file is part of the Coriolis Software.
|
||||
// Copyright (c) UPMC 2017-2017, All Rights Reserved
|
||||
//
|
||||
// +-----------------------------------------------------------------+
|
||||
// | 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@lip6.fr |
|
||||
// | =============================================================== |
|
||||
// | C++ Module : "./Block.cpp" |
|
||||
// +-----------------------------------------------------------------+
|
||||
|
||||
|
||||
#include "hurricane/Error.h"
|
||||
#include "hurricane/Warning.h"
|
||||
#include "hurricane/Breakpoint.h"
|
||||
#include "hurricane/DebugSession.h"
|
||||
#include "hurricane/RoutingPad.h"
|
||||
#include "hurricane/Cell.h"
|
||||
#include "anabatic/Edge.h"
|
||||
#include "katana/Block.h"
|
||||
#include "katana/KatanaEngine.h"
|
||||
|
||||
|
||||
namespace Katana {
|
||||
|
||||
using std::cerr;
|
||||
using std::endl;
|
||||
using std::make_pair;
|
||||
using std::ostringstream;
|
||||
using std::setw;
|
||||
using Hurricane::Error;
|
||||
using Hurricane::Warning;
|
||||
using Hurricane::Breakpoint;
|
||||
using Hurricane::DebugSession;
|
||||
using Hurricane::SubTypeCollection;
|
||||
using Hurricane::Transformation;
|
||||
using Hurricane::RoutingPad;
|
||||
using Hurricane::Instance;
|
||||
using Hurricane::Path;
|
||||
using Anabatic::Edge;
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "Katana::Row".
|
||||
|
||||
|
||||
void Row::add ( DbU::Unit x, Occurrence occurrence )
|
||||
{
|
||||
auto iocc = _occurrences.find( x );
|
||||
if (iocc != _occurrences.end()) {
|
||||
cerr << Error( "Row::add() In row @%s, two elements at the same X position %s:\n"
|
||||
" %s\n"
|
||||
" %s"
|
||||
, DbU::getValueString(_y).c_str()
|
||||
, DbU::getValueString(x).c_str()
|
||||
, getString((*iocc).second).c_str()
|
||||
, getString(occurrence).c_str()
|
||||
) << endl;
|
||||
return;
|
||||
}
|
||||
_occurrences.insert( make_pair(x,occurrence) );
|
||||
}
|
||||
|
||||
|
||||
void Row::setY ( DbU::Unit y )
|
||||
{
|
||||
for ( auto iocc : _occurrences ) {
|
||||
Instance* instance = dynamic_cast<Instance*>( iocc.second.getEntity() );
|
||||
if (not instance) continue;
|
||||
|
||||
Transformation itransf = instance->getTransformation();
|
||||
Transformation dtransf ( itransf.getTx(), itransf.getTy() - _y + y, itransf.getOrientation() );
|
||||
|
||||
instance->setTransformation( dtransf );
|
||||
}
|
||||
|
||||
_y = y;
|
||||
DbU::Unit sliceHeight = Session::getSliceHeight() + Session::getPitch( (size_t)0 );
|
||||
|
||||
if (getSouthWest()) {
|
||||
GCell* gcellRow = getSouthWest();
|
||||
GCell* gcellChannel = gcellRow->getNorth();
|
||||
|
||||
while ( gcellRow ) {
|
||||
gcellRow->setSouthWestCorner( gcellRow->getXMin(), _y );
|
||||
gcellRow = gcellRow->getEast();
|
||||
|
||||
if (gcellChannel) {
|
||||
gcellChannel->setSouthWestCorner( gcellChannel->getXMin(), _y+sliceHeight );
|
||||
gcellChannel = gcellChannel->getEast();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
GCell* Row::createChannel ( GCell* southWest, DbU::Unit channelHeight )
|
||||
{
|
||||
if (not southWest)
|
||||
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->getYMin() != _y)
|
||||
throw Error( "Row::createChannel(): South-west GCell YMIn and Row Y min differs (%s vs. %s)."
|
||||
, DbU::getValueString(southWest->getYMin()).c_str()
|
||||
, DbU::getValueString(_y).c_str()
|
||||
);
|
||||
|
||||
DbU::Unit ypitch = Session::getPitch( (size_t)0 );
|
||||
DbU::Unit sliceHeight = Session::getSliceHeight() + ypitch;
|
||||
bool northRow = (_y + sliceHeight >= getCell()->getAbutmentBox().getYMax());
|
||||
|
||||
_southWest = southWest;
|
||||
GCell* channel = _southWest->hcut( _southWest->getYMin() + sliceHeight );
|
||||
GCell* nextSW = NULL;
|
||||
if (not northRow) {
|
||||
nextSW = channel->hcut( _southWest->getYMin() + sliceHeight + channelHeight );
|
||||
if (not nextSW) {
|
||||
throw Error( "Row::createChannel(): Cannot h-cut %s @%s."
|
||||
, getString(channel).c_str()
|
||||
, DbU::getValueString(_southWest->getYMin() + sliceHeight + channelHeight).c_str()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
southWest->setType( Anabatic::Flags::StdCellRow );
|
||||
if (channel) channel->setType( Anabatic::Flags::ChannelRow );
|
||||
|
||||
DbU::Unit xmax = getCell()->getAbutmentBox().getXMax() - sliceHeight;
|
||||
DbU::Unit xcut = _southWest->getXMin() + sliceHeight;
|
||||
for ( ; xcut < xmax ; xcut += sliceHeight ) {
|
||||
southWest = southWest->vcut( xcut );
|
||||
southWest->setType( Anabatic::Flags::StdCellRow );
|
||||
if (channel) {
|
||||
channel = channel->vcut( xcut );
|
||||
channel->setType( Anabatic::Flags::ChannelRow );
|
||||
channel->getWestEdge()->setFlags( Flags::IllimitedCapacity );
|
||||
}
|
||||
}
|
||||
|
||||
return nextSW;
|
||||
}
|
||||
|
||||
|
||||
void Row::routingPadsSubBreak ()
|
||||
{
|
||||
if (not _southWest)
|
||||
throw Error( "Row::routingPadsSubBreak(): NULL southWest GCell." );
|
||||
|
||||
set<Net*> nets;
|
||||
map<DbU::Unit, RoutingPad*> rps;
|
||||
GCell* southWest = _southWest;
|
||||
while ( southWest ) {
|
||||
bool gcellSplitted = false;
|
||||
|
||||
for ( RoutingPad* rp : SubTypeCollection<Component*,RoutingPad*>( getCell()->getComponentsUnder(southWest->getBoundingBox() ) ) ) {
|
||||
if ( (rp->getX() >= southWest->getXMax())
|
||||
or (rp->getX() < southWest->getXMin()) ) continue;
|
||||
rps.insert( make_pair(rp->getX(),rp) );
|
||||
}
|
||||
|
||||
for ( auto irp : rps ) {
|
||||
auto inet = nets.find( irp.second->getNet() );
|
||||
if (inet == nets.end()) {
|
||||
nets.insert( irp.second->getNet() );
|
||||
} else {
|
||||
if (southWest->getId() == 2998) DebugSession::close();
|
||||
southWest = southWest->vcut( irp.second->getX() );
|
||||
southWest->setType( Anabatic::Flags::StdCellRow );
|
||||
gcellSplitted = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
rps .clear();
|
||||
nets.clear();
|
||||
if (not gcellSplitted) {
|
||||
if (southWest->getId() == 2998) DebugSession::close();
|
||||
southWest = southWest->getEast();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint32_t Row::computeChannelHeight ()
|
||||
{
|
||||
_channelHeight = 2;
|
||||
|
||||
GCell* gcell = getSouthWest()->getNorth();
|
||||
while ( gcell ) {
|
||||
_channelHeight = std::max( _channelHeight, (uint32_t)gcell->getNetCount() );
|
||||
// Edge* east = gcell->getEastEdge();
|
||||
// if (east)
|
||||
// _channelHeight = std::max( _channelHeight, east->getRealOccupancy() );
|
||||
gcell = gcell->getEast();
|
||||
}
|
||||
|
||||
return _channelHeight;
|
||||
}
|
||||
|
||||
|
||||
string Row::_getString () const
|
||||
{ return "<Row @" + DbU::getValueString(_y) + " instances:" + getString(_occurrences.size()) + ">"; }
|
||||
|
||||
|
||||
Record* Row::_getRecord () const
|
||||
{
|
||||
Record* record = new Record ( _getString() );
|
||||
record->add( DbU::getValueSlot( "_y", &_y ) );
|
||||
record->add( getSlot( "_occurrences", &_occurrences ) );
|
||||
return record;
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "Katana::Block".
|
||||
|
||||
|
||||
Block::Block ( KatanaEngine* katana, Cell* cell )
|
||||
: _katana(katana)
|
||||
, _cell (cell)
|
||||
, _rows ()
|
||||
{
|
||||
for ( Occurrence occurrence : _cell->getLeafInstanceOccurrences() ) {
|
||||
add( occurrence );
|
||||
}
|
||||
_katana->addBlock( this );
|
||||
}
|
||||
|
||||
|
||||
Block::~Block ()
|
||||
{
|
||||
for ( Row* row : _rows ) delete row;
|
||||
}
|
||||
|
||||
|
||||
Row* Block::getAt ( DbU::Unit y ) const
|
||||
{
|
||||
for ( size_t i=0 ; i<_rows.size() ; ++i ) {
|
||||
if (_rows[i]->getY() == y) return _rows[i];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void Block::add ( Occurrence occurrence )
|
||||
{
|
||||
Instance* instance = dynamic_cast<Instance*>(occurrence.getEntity());
|
||||
if (not instance) {
|
||||
cerr << Warning( "Block::add(): Not an Instance occurrence, %s."
|
||||
,getString(occurrence).c_str() ) << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
Transformation transf = occurrence.getPath().getTransformation( instance->getTransformation() );
|
||||
Box bbInstance = transf.getBox( instance->getMasterCell()->getAbutmentBox() );
|
||||
|
||||
Row* row = getAt( bbInstance.getYMin() );
|
||||
if (not row) {
|
||||
row = new Row ( this, bbInstance.getYMin() );
|
||||
auto irow = _rows.begin();
|
||||
for ( ; irow != _rows.end() ; ++irow ) {
|
||||
if ((*irow)->getY() >= row->getY()) break;
|
||||
}
|
||||
_rows.insert( irow, row );
|
||||
}
|
||||
|
||||
row->add( bbInstance.getXMin(), occurrence );
|
||||
}
|
||||
|
||||
|
||||
void Block::createChannels ()
|
||||
{
|
||||
bool sessionReUse = Session::isOpen();
|
||||
if (not sessionReUse) _katana->openSession();
|
||||
|
||||
DbU::Unit ypitch = Session::getPitch( (size_t)0 );
|
||||
DbU::Unit sliceHeight = Session::getSliceHeight() + ypitch;
|
||||
|
||||
for ( size_t i=0 ; i<_rows.size() ; ++i )
|
||||
_rows[i]->setY( i*ypitch + i*sliceHeight );
|
||||
|
||||
Box ab ( _cell->getAbutmentBox() );
|
||||
if (not _rows.empty()) {
|
||||
_cell->setAbutmentBox( ab.inflate( 0, 0, 0, ypitch*(2*_rows.size()-1) ) );
|
||||
_katana->_resizeMatrix();
|
||||
}
|
||||
|
||||
//GCell* southWest = _katana->getGCellUnder( ab.getXMin(), ab.getYMin() );
|
||||
GCell* southWest = _katana->getSouthWestGCell();
|
||||
if (southWest != _katana->getSouthWestGCell())
|
||||
throw Error( "Block::createChannels(): Only block are supported for now..." );
|
||||
|
||||
for ( Row* row : _rows )
|
||||
southWest = row->createChannel( southWest, ypitch );
|
||||
|
||||
_katana->invalidateRoutingPads();
|
||||
|
||||
Session::close();
|
||||
_katana->openSession();
|
||||
|
||||
for ( Row* row : _rows )
|
||||
row->routingPadsSubBreak();
|
||||
|
||||
if (not sessionReUse) Session::close();
|
||||
}
|
||||
|
||||
|
||||
void Block::resizeChannels ()
|
||||
{
|
||||
cmess1 << " o Sizing routing channels." << endl;
|
||||
|
||||
bool sessionReUse = Session::isOpen();
|
||||
if (not sessionReUse) _katana->openSession();
|
||||
|
||||
DbU::Unit ypitch = Session::getPitch( (size_t)0 );
|
||||
DbU::Unit sliceHeight = Session::getSliceHeight() + ypitch;
|
||||
uint32_t channelSum = 0;
|
||||
for ( Row* row : _rows ) channelSum += row->computeChannelHeight();
|
||||
|
||||
Box ab = _cell->getAbutmentBox();
|
||||
_cell->setAbutmentBox( ab.inflate( 0, 0, 0, ypitch*(channelSum - _rows.size() + 1) ) );
|
||||
_katana->_resizeMatrix();
|
||||
|
||||
channelSum = 0;
|
||||
for ( size_t irow=0 ; irow < _rows.size() ; ++irow ) {
|
||||
_rows[irow]->setY( ab.getYMin() + sliceHeight*irow + ypitch*channelSum );
|
||||
channelSum += _rows[irow]->getChannelHeight();
|
||||
|
||||
ostringstream rowName;
|
||||
rowName << " - [" << setw(2) << irow << "]";
|
||||
rowName << " @" << DbU::getValueString(_rows[irow]->getY() + sliceHeight);
|
||||
|
||||
ostringstream rowTracks;
|
||||
rowTracks << _rows[irow]->getChannelHeight() << " tracks.";
|
||||
|
||||
cmess2 << Dots::asString( rowName.str(), rowTracks.str() ) << endl;
|
||||
}
|
||||
|
||||
_katana->invalidateRoutingPads();
|
||||
|
||||
if (not sessionReUse) Session::close();
|
||||
}
|
||||
|
||||
|
||||
string Block::_getString () const
|
||||
{ return "<Block rows:" + getString(_rows.size()) + ">"; }
|
||||
|
||||
|
||||
Record* Block::_getRecord () const
|
||||
{
|
||||
Record* record = new Record ( _getString() );
|
||||
record->add( getSlot( "_katana", _katana ) );
|
||||
record->add( getSlot( "_rows" , &_rows ) );
|
||||
return record;
|
||||
}
|
||||
|
||||
|
||||
} // Katana namespace.
|
|
@ -10,6 +10,7 @@
|
|||
${PYTHON_INCLUDE_PATH}
|
||||
)
|
||||
set( includes katana/Constants.h
|
||||
katana/Block.h
|
||||
katana/TrackCost.h
|
||||
katana/DataNegociate.h
|
||||
katana/DataSymmetric.h
|
||||
|
@ -43,6 +44,7 @@
|
|||
set( mocIncludes katana/GraphicKatanaEngine.h )
|
||||
set( cpps Constants.cpp
|
||||
Configuration.cpp
|
||||
Block.cpp
|
||||
DataNegociate.cpp
|
||||
DataSymmetric.cpp
|
||||
TrackCost.cpp
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
//
|
||||
// +-----------------------------------------------------------------+
|
||||
// | C O R I O L I S |
|
||||
// | A n a b a t i c - Global Routing Toolbox |
|
||||
// | 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@lip6.fr |
|
||||
|
@ -14,8 +14,11 @@
|
|||
// +-----------------------------------------------------------------+
|
||||
|
||||
|
||||
#include "hurricane/Warning.h"
|
||||
#include "hurricane/Breakpoint.h"
|
||||
#include "hurricane/Cell.h"
|
||||
#include "anabatic/Dijkstra.h"
|
||||
#include "katana/Block.h"
|
||||
#include "katana/RoutingPlane.h"
|
||||
#include "katana/KatanaEngine.h"
|
||||
|
||||
|
@ -29,6 +32,7 @@ namespace {
|
|||
using std::left;
|
||||
using std::right;
|
||||
using Hurricane::DbU;
|
||||
using Hurricane::DbU;
|
||||
using Hurricane::Net;
|
||||
using Anabatic::Edge;
|
||||
using Anabatic::Vertex;
|
||||
|
@ -54,10 +58,16 @@ namespace {
|
|||
|
||||
DbU::Unit DigitalDistance::operator() ( const Vertex* source ,const Vertex* target,const Edge* edge ) const
|
||||
{
|
||||
if (edge->getCapacity() <= 0) return Vertex::unreached;
|
||||
if (edge->getCapacity() <= 0) return Vertex::unreachable;
|
||||
|
||||
if (source->getGCell()->isStdCellRow() and target->getGCell()->isStdCellRow())
|
||||
return Vertex::unreachable;
|
||||
|
||||
float congestionCost = 1.0;
|
||||
float congestion = (float)edge->getRealOccupancy() / (float)edge->getCapacity();
|
||||
float congestionCost = 1.0 + _h / (1.0 + std::exp(_k * (congestion - 1.0)));
|
||||
|
||||
if (not source->getGCell()->isChannelRow() or not target->getGCell()->isChannelRow())
|
||||
congestionCost += _h / (1.0 + std::exp(_k * (congestion - 1.0)));
|
||||
|
||||
float viaCost = 0.0;
|
||||
if ( source->getFrom()
|
||||
|
@ -101,12 +111,30 @@ namespace {
|
|||
namespace Katana {
|
||||
|
||||
using Hurricane::Error;
|
||||
using Hurricane::Warning;
|
||||
using Hurricane::Breakpoint;
|
||||
using Hurricane::Timer;
|
||||
using Hurricane::Occurrence;
|
||||
using Hurricane::Transformation;
|
||||
using Hurricane::Instance;
|
||||
using Anabatic::EngineState;
|
||||
using Anabatic::Dijkstra;
|
||||
using Anabatic::NetData;
|
||||
|
||||
|
||||
void KatanaEngine::createChannels ()
|
||||
{
|
||||
Cell* core = getCell();
|
||||
if (isChip())
|
||||
core = getChipTools().getCore()->getMasterCell();
|
||||
|
||||
Block* block = new Block( this, core );
|
||||
block->createChannels();
|
||||
|
||||
_resizeMatrix();
|
||||
}
|
||||
|
||||
|
||||
void KatanaEngine::setupGlobalGraph ( uint32_t mode )
|
||||
{
|
||||
Cell* cell = getCell();
|
||||
|
@ -116,6 +144,8 @@ namespace Katana {
|
|||
|
||||
startMeasures();
|
||||
|
||||
if (isChannelMode()) createChannels();
|
||||
|
||||
if (getGCells().size() == 1) {
|
||||
cmess1 << " o Building regular grid..." << endl;
|
||||
getSouthWestGCell()->doGrid();
|
||||
|
@ -160,6 +190,9 @@ namespace Katana {
|
|||
dijkstra->setDistance( DigitalDistance( getConfiguration()->getEdgeCostH()
|
||||
, getConfiguration()->getEdgeCostK() ));
|
||||
|
||||
if (isChannelMode())
|
||||
dijkstra->setSearchAreaHalo( Session::getSliceHeight()*2 );
|
||||
|
||||
size_t iteration = 0;
|
||||
size_t netCount = 0;
|
||||
do {
|
||||
|
@ -211,8 +244,19 @@ namespace Katana {
|
|||
stopMeasures();
|
||||
printMeasures( "Dijkstra" );
|
||||
|
||||
if (getBlock(0)) {
|
||||
getBlock(0)->resizeChannels();
|
||||
_resizeMatrix();
|
||||
}
|
||||
|
||||
delete dijkstra;
|
||||
|
||||
Session::close();
|
||||
if (isChannelMode()) {
|
||||
setupRoutingPlanes();
|
||||
setupPowerRails();
|
||||
protectRoutingPads();
|
||||
}
|
||||
|
||||
setState( EngineState::EngineGlobalLoaded );
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "hurricane/viewer/Script.h"
|
||||
#include "crlcore/Measures.h"
|
||||
#include "anabatic/AutoContact.h"
|
||||
#include "katana/Block.h"
|
||||
#include "katana/DataNegociate.h"
|
||||
#include "katana/RoutingPlane.h"
|
||||
#include "katana/Session.h"
|
||||
|
@ -175,9 +176,11 @@ namespace Katana {
|
|||
: Super (cell)
|
||||
, _viewer (NULL)
|
||||
, _configuration (new Configuration())
|
||||
, _blocks ()
|
||||
, _routingPlanes ()
|
||||
, _negociateWindow(NULL)
|
||||
, _minimumWL (0.0)
|
||||
, _mode (DigitalMode)
|
||||
, _toolSuccess (false)
|
||||
{ }
|
||||
|
||||
|
@ -213,14 +216,21 @@ namespace Katana {
|
|||
{
|
||||
cdebug_log(155,1) << "KatanaEngine::_initDataBase()" << endl;
|
||||
|
||||
_mode |= DigitalMode;
|
||||
|
||||
Super::chipPrep();
|
||||
|
||||
setupChannelMode();
|
||||
setupGlobalGraph( 0 );
|
||||
setupRoutingPlanes();
|
||||
if (not isChannelMode()) {
|
||||
setupRoutingPlanes();
|
||||
}
|
||||
setupSpecialNets();
|
||||
setupPreRouteds();
|
||||
setupPowerRails();
|
||||
protectRoutingPads();
|
||||
if (not isChannelMode()) {
|
||||
setupPowerRails();
|
||||
protectRoutingPads();
|
||||
}
|
||||
_runKatanaInit();
|
||||
|
||||
cdebug_tabw(155,-1);
|
||||
|
@ -231,6 +241,9 @@ namespace Katana {
|
|||
{
|
||||
cdebug_log(155,1) << "KatanaEngine::_initDataBase()" << endl;
|
||||
|
||||
_mode &= ~DigitalMode;
|
||||
_mode |= AnalogMode;
|
||||
|
||||
Super::chipPrep();
|
||||
|
||||
setupRoutingPlanes();
|
||||
|
@ -240,6 +253,25 @@ namespace Katana {
|
|||
}
|
||||
|
||||
|
||||
void KatanaEngine::setupChannelMode ()
|
||||
{
|
||||
cdebug_log(155,1) << "KatanaEngine::setupChannelMode()" << endl;
|
||||
|
||||
RoutingGauge* rg = getConfiguration()->getRoutingGauge();
|
||||
size_t maxDepth = rg->getDepth();
|
||||
if (maxDepth < 3) {
|
||||
_mode |= ChannelMode;
|
||||
|
||||
if (maxDepth < 2) {
|
||||
throw Error( "KatanaEngine::setupChannelMode(): Layer gauge %s must contains at least two layers (%u)."
|
||||
, getString(rg->getName()).c_str(), maxDepth );
|
||||
}
|
||||
}
|
||||
|
||||
cdebug_tabw(155,-1);
|
||||
}
|
||||
|
||||
|
||||
void KatanaEngine::setupRoutingPlanes ()
|
||||
{
|
||||
cdebug_log(155,1) << "KatanaEngine::setupRoutingPlanes()" << endl;
|
||||
|
@ -254,6 +286,7 @@ namespace Katana {
|
|||
}
|
||||
|
||||
if (not sessionReUse) Session::close();
|
||||
cdebug_tabw(155,-1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -674,6 +707,9 @@ namespace Katana {
|
|||
if (getState() < EngineState::EngineGutted) {
|
||||
openSession();
|
||||
|
||||
for ( Block* block : _blocks ) delete block;
|
||||
_blocks.clear();
|
||||
|
||||
size_t maxDepth = std::min( getConfiguration()->getRoutingGauge()->getDepth(), _routingPlanes.size() );
|
||||
for ( size_t depth=0 ; depth < maxDepth ; depth++ ) {
|
||||
_routingPlanes[depth]->destroy();
|
||||
|
@ -740,6 +776,7 @@ namespace Katana {
|
|||
|
||||
if (record) {
|
||||
record->add( getSlot( "_configuration", _configuration ) );
|
||||
record->add( getSlot( "_blocks" , &_blocks ) );
|
||||
record->add( getSlot( "_routingPlanes", &_routingPlanes ) );
|
||||
record->add( getSlot( "_symmetrics" , &_symmetrics ) );
|
||||
}
|
||||
|
|
|
@ -491,7 +491,11 @@ namespace Katana {
|
|||
cdebug_tabw(159,-1);
|
||||
return false;
|
||||
}
|
||||
_segment->makeDogleg( dogLegGCell, dogleg, segment1 );
|
||||
if (not _segment->makeDogleg( dogLegGCell, dogleg, segment1 )) {
|
||||
cdebug_log(159,0) << "FIRST makeDogleg() call failed (BUG)." << endl;
|
||||
cdebug_tabw(159,-1);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (firstDoglegIsMin) {
|
||||
|
@ -548,7 +552,11 @@ namespace Katana {
|
|||
cdebug_tabw(159,-1);
|
||||
return false;
|
||||
}
|
||||
segment1->makeDogleg( dogLegGCell, dogleg, segment2 );
|
||||
if (not segment1->makeDogleg( dogLegGCell, dogleg, segment2 )) {
|
||||
cdebug_log(159,0) << "SECOND makeDogleg() call failed (BUG)." << endl;
|
||||
cdebug_tabw(159,-1);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (maxExpanded) {
|
||||
|
|
|
@ -316,9 +316,15 @@ namespace Katana {
|
|||
Track* track = plane->getTrackByPosition ( autoSegment->getAxis() );
|
||||
Interval uside = autoSegment->getAutoSource()->getGCell()->getSide( perpandicularTo(autoSegment->getDirection()) );
|
||||
|
||||
cdebug_log(159,0) << "* Nearest " << track << endl;
|
||||
|
||||
if (track->getAxis() > uside.getVMax()) track = track->getPreviousTrack();
|
||||
if (track->getAxis() < uside.getVMin()) track = track->getNextTrack();
|
||||
|
||||
if (not track)
|
||||
throw Error( "NegociateWindow::createTracksegment(): No track near axis of %s."
|
||||
, getString(autoSegment).c_str() );
|
||||
|
||||
cdebug_log(159,0) << "* GCell U-side " << uside << endl;
|
||||
cdebug_log(159,0) << "* " << plane << endl;
|
||||
cdebug_log(159,0) << "* " << track << endl;
|
||||
|
@ -529,51 +535,53 @@ namespace Katana {
|
|||
//_pack( count, true );
|
||||
if (count and cmess2.enabled() and tty::enabled()) cmess1 << endl;
|
||||
|
||||
cdebug_log(9000,0) << "Deter| Repair Stage" << endl;
|
||||
cmess1 << " o Repair Stage." << endl;
|
||||
if (not _katana->isChannelMode() ) {
|
||||
cdebug_log(9000,0) << "Deter| Repair Stage" << endl;
|
||||
cmess1 << " o Repair Stage." << endl;
|
||||
|
||||
cdebug_log(159,0) << "Loadind Repair queue." << endl;
|
||||
RoutingEvent::setStage( RoutingEvent::Repair );
|
||||
for ( size_t i=0 ; (i<_eventHistory.size()) and not isInterrupted() ; i++ ) {
|
||||
RoutingEvent* event = _eventHistory.getNth(i);
|
||||
cdebug_log(159,0) << "Loadind Repair queue." << endl;
|
||||
RoutingEvent::setStage( RoutingEvent::Repair );
|
||||
for ( size_t i=0 ; (i<_eventHistory.size()) and not isInterrupted() ; i++ ) {
|
||||
RoutingEvent* event = _eventHistory.getNth(i);
|
||||
|
||||
if (not event->isCloned() and event->isUnimplemented()) {
|
||||
event->reschedule( _eventQueue, 0 );
|
||||
if (not event->isCloned() and event->isUnimplemented()) {
|
||||
event->reschedule( _eventQueue, 0 );
|
||||
}
|
||||
}
|
||||
}
|
||||
_eventQueue.commit();
|
||||
cmess2 << " <repair.queue:" << right << setw(8) << setfill('0')
|
||||
<< _eventQueue.size() << ">" << endl;
|
||||
_eventQueue.commit();
|
||||
cmess2 << " <repair.queue:" << right << setw(8) << setfill('0')
|
||||
<< _eventQueue.size() << ">" << endl;
|
||||
|
||||
count = 0;
|
||||
//_eventQueue.prepareRepair();
|
||||
while ( not _eventQueue.empty() and not isInterrupted() ) {
|
||||
RoutingEvent* event = _eventQueue.pop();
|
||||
count = 0;
|
||||
//_eventQueue.prepareRepair();
|
||||
while ( not _eventQueue.empty() and not isInterrupted() ) {
|
||||
RoutingEvent* event = _eventQueue.pop();
|
||||
|
||||
if (tty::enabled()) {
|
||||
cmess2 << " <repair.event:" << tty::bold << setw(8) << setfill('0')
|
||||
<< RoutingEvent::getProcesseds() << tty::reset
|
||||
<< " remains:" << right << setw(8) << setfill('0')
|
||||
<< _eventQueue.size() << ">"
|
||||
<< setfill(' ') << tty::reset << tty::cr;
|
||||
cmess2.flush();
|
||||
} else {
|
||||
cmess2 << " <repair.event:" << setw(8) << setfill('0')
|
||||
<< RoutingEvent::getProcesseds() << setfill(' ') << " "
|
||||
<< event->getEventLevel() << ":" << event->getPriority() << "> "
|
||||
<< event->getSegment()
|
||||
<< endl;
|
||||
cmess2.flush();
|
||||
if (tty::enabled()) {
|
||||
cmess2 << " <repair.event:" << tty::bold << setw(8) << setfill('0')
|
||||
<< RoutingEvent::getProcesseds() << tty::reset
|
||||
<< " remains:" << right << setw(8) << setfill('0')
|
||||
<< _eventQueue.size() << ">"
|
||||
<< setfill(' ') << tty::reset << tty::cr;
|
||||
cmess2.flush();
|
||||
} else {
|
||||
cmess2 << " <repair.event:" << setw(8) << setfill('0')
|
||||
<< RoutingEvent::getProcesseds() << setfill(' ') << " "
|
||||
<< event->getEventLevel() << ":" << event->getPriority() << "> "
|
||||
<< event->getSegment()
|
||||
<< endl;
|
||||
cmess2.flush();
|
||||
}
|
||||
|
||||
event->process( _eventQueue, _eventHistory, _eventLoop );
|
||||
|
||||
count++;
|
||||
if (RoutingEvent::getProcesseds() >= limit ) setInterrupt( true );
|
||||
}
|
||||
|
||||
event->process( _eventQueue, _eventHistory, _eventLoop );
|
||||
|
||||
count++;
|
||||
if (RoutingEvent::getProcesseds() >= limit ) setInterrupt( true );
|
||||
if (count and cmess2.enabled() and tty::enabled()) cmess1 << endl;
|
||||
}
|
||||
|
||||
if (count and cmess2.enabled() and tty::enabled()) cmess1 << endl;
|
||||
|
||||
size_t eventsCount = _eventHistory.size();
|
||||
|
||||
_eventHistory.clear();
|
||||
|
|
|
@ -1284,7 +1284,6 @@ namespace Katana {
|
|||
void KatanaEngine::setupPowerRails ()
|
||||
{
|
||||
//DebugSession::open( 150, 160 );
|
||||
|
||||
openSession();
|
||||
|
||||
if (not getBlockageNet()) {
|
||||
|
@ -1321,7 +1320,6 @@ namespace Katana {
|
|||
}
|
||||
|
||||
Session::close();
|
||||
|
||||
//DebugSession::close();
|
||||
}
|
||||
|
||||
|
|
|
@ -711,6 +711,12 @@ namespace Katana {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (doglegGCell->isStdCellRow()) {
|
||||
cdebug_log(159,0) << "false: Cannot dogleg in a Standard Cell row." << endl;
|
||||
cdebug_tabw(159,-1);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (isFixed()) {
|
||||
cdebug_log(159,0) << "false: Cannot dogleg a fixed segment." << endl;
|
||||
cdebug_tabw(159,-1);
|
||||
|
@ -743,7 +749,11 @@ namespace Katana {
|
|||
}
|
||||
|
||||
vector<Anabatic::GCell*> gcells;
|
||||
getGCells( gcells );
|
||||
if (not getGCells(gcells)) {
|
||||
cdebug_log(159,0) << "getGCell() has gone wrong." << endl;
|
||||
cdebug_tabw(159,-1);
|
||||
return false;
|
||||
}
|
||||
|
||||
cdebug_log(159,0) << "Source: " << *gcells.begin () << endl;
|
||||
cdebug_log(159,0) << "Target: " << *gcells.rbegin() << endl;
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
// -*- C++ -*-
|
||||
//
|
||||
// This file is part of the Coriolis Software.
|
||||
// Copyright (c) UPMC 2017-2017, All Rights Reserved
|
||||
//
|
||||
// +-----------------------------------------------------------------+
|
||||
// | 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@lip6.fr |
|
||||
// | =============================================================== |
|
||||
// | C++ Header : "./katana/Block.h" |
|
||||
// +-----------------------------------------------------------------+
|
||||
|
||||
|
||||
#ifndef KATANA_BLOCK_H
|
||||
#define KATANA_BLOCK_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include "hurricane/DbU.h"
|
||||
#include "hurricane/Occurrence.h"
|
||||
|
||||
namespace Anabatic {
|
||||
class GCell;
|
||||
}
|
||||
|
||||
|
||||
namespace Katana {
|
||||
|
||||
using std::string;
|
||||
using std::vector;
|
||||
using std::map;
|
||||
using Hurricane::Name;
|
||||
using Hurricane::DbU;
|
||||
using Hurricane::Record;
|
||||
using Hurricane::Cell;
|
||||
using Hurricane::Occurrence;
|
||||
using Anabatic::GCell;
|
||||
|
||||
class KatanaEngine;
|
||||
class Block;
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "Katana::Row".
|
||||
|
||||
class Row {
|
||||
public:
|
||||
inline Row ( Block*, DbU::Unit );
|
||||
inline Block* getBlock () const;
|
||||
inline Cell* getCell () const;
|
||||
inline DbU::Unit getY () const;
|
||||
inline GCell* getSouthWest () const;
|
||||
inline uint32_t getChannelHeight () const;
|
||||
void setY ( DbU::Unit y );
|
||||
void add ( DbU::Unit x, Occurrence );
|
||||
GCell* createChannel ( GCell* southWest, DbU::Unit channelHeight );
|
||||
uint32_t computeChannelHeight ();
|
||||
void routingPadsSubBreak ();
|
||||
string _getString () const;
|
||||
Record* _getRecord () const;
|
||||
private:
|
||||
Block* _block;
|
||||
DbU::Unit _y;
|
||||
map<DbU::Unit,Occurrence> _occurrences;
|
||||
GCell* _southWest;
|
||||
uint32_t _channelHeight;
|
||||
};
|
||||
|
||||
|
||||
inline Row::Row ( Block* block, DbU::Unit y )
|
||||
: _block(block), _y(y), _occurrences(), _southWest(NULL), _channelHeight(1) { }
|
||||
|
||||
inline DbU::Unit Row::getY () const { return _y; }
|
||||
inline Block* Row::getBlock () const { return _block; }
|
||||
inline GCell* Row::getSouthWest () const { return _southWest; }
|
||||
inline uint32_t Row::getChannelHeight () const { return _channelHeight; }
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// Class : "Katana::Block".
|
||||
|
||||
class Block {
|
||||
public:
|
||||
Block ( KatanaEngine*, Cell* );
|
||||
~Block ();
|
||||
inline Cell* getCell () const;
|
||||
Row* getAt ( DbU::Unit y ) const;
|
||||
void add ( Occurrence );
|
||||
void createChannels ();
|
||||
void resizeChannels ();
|
||||
string _getString () const;
|
||||
Record* _getRecord () const;
|
||||
private:
|
||||
KatanaEngine* _katana;
|
||||
Cell* _cell;
|
||||
vector<Row*> _rows;
|
||||
};
|
||||
|
||||
|
||||
inline Cell* Block::getCell () const { return _cell; }
|
||||
|
||||
|
||||
// Deferred Row functions.
|
||||
inline Cell* Row::getCell () const { return _block->getCell(); }
|
||||
|
||||
|
||||
} // Katana namespace.
|
||||
|
||||
|
||||
INSPECTOR_P_SUPPORT(Katana::Row);
|
||||
INSPECTOR_P_SUPPORT(Katana::Block);
|
||||
|
||||
#endif // KATANA_BLOCK_H
|
|
@ -29,11 +29,6 @@ namespace Hurricane {
|
|||
|
||||
#include "crlcore/RoutingGauge.h"
|
||||
#include "anabatic/AnabaticEngine.h"
|
||||
|
||||
namespace Knik {
|
||||
class KnikEngine;
|
||||
}
|
||||
|
||||
#include "katana/Constants.h"
|
||||
#include "katana/TrackElement.h"
|
||||
#include "katana/Configuration.h"
|
||||
|
@ -50,6 +45,7 @@ namespace Katana {
|
|||
using CRL::RoutingGauge;
|
||||
using Anabatic::AnabaticEngine;
|
||||
|
||||
class Block;
|
||||
class Track;
|
||||
class RoutingPlane;
|
||||
class NegociateWindow;
|
||||
|
@ -59,6 +55,11 @@ namespace Katana {
|
|||
// Class : "Katana::KatanaEngine".
|
||||
|
||||
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);
|
||||
public:
|
||||
typedef AnabaticEngine Super;
|
||||
public:
|
||||
|
@ -66,6 +67,10 @@ 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 useClockTree () const;
|
||||
inline CellViewer* getViewer () const;
|
||||
inline AnabaticEngine* base ();
|
||||
|
@ -90,6 +95,7 @@ namespace Katana {
|
|||
DataSymmetric* getDataSymmetric ( Net* );
|
||||
inline const std::map<Net*,DataSymmetric*>&
|
||||
getSymmetrics () const;
|
||||
inline Block* getBlock ( size_t i ) const;
|
||||
inline void printConfiguration () const;
|
||||
void printCompletion () const;
|
||||
void dumpMeasures ( std::ostream& ) const;
|
||||
|
@ -103,11 +109,14 @@ namespace Katana {
|
|||
inline void setRipupCost ( uint32_t );
|
||||
inline void setHTracksReservedLocal ( uint32_t );
|
||||
inline void setVTracksReservedLocal ( uint32_t );
|
||||
inline void addBlock ( Block* );
|
||||
DataSymmetric* addDataSymmetric ( Net* );
|
||||
void setupChannelMode ();
|
||||
void setupPowerRails ();
|
||||
void protectRoutingPads ();
|
||||
void preProcess ();
|
||||
void setInterrupt ( bool );
|
||||
void createChannels ();
|
||||
void setupRoutingPlanes ();
|
||||
void setupGlobalGraph ( uint32_t mode );
|
||||
void annotateGlobalGraph ();
|
||||
|
@ -135,10 +144,12 @@ namespace Katana {
|
|||
protected:
|
||||
CellViewer* _viewer;
|
||||
Configuration* _configuration;
|
||||
vector<Block*> _blocks;
|
||||
vector<RoutingPlane*> _routingPlanes;
|
||||
NegociateWindow* _negociateWindow;
|
||||
double _minimumWL;
|
||||
std::map<Net*,DataSymmetric*> _symmetrics;
|
||||
uint32_t _mode;
|
||||
mutable bool _toolSuccess;
|
||||
protected:
|
||||
// Constructors & Destructors.
|
||||
|
@ -153,6 +164,10 @@ 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::useClockTree () const { return _configuration->useClockTree(); }
|
||||
inline CellViewer* KatanaEngine::getViewer () const { return _viewer; }
|
||||
inline AnabaticEngine* KatanaEngine::base () { return static_cast<AnabaticEngine*>(this); }
|
||||
|
@ -167,6 +182,7 @@ namespace Katana {
|
|||
inline bool KatanaEngine::profileEventCosts () const { return _configuration->profileEventCosts(); }
|
||||
inline const std::map<Net*,DataSymmetric*>&
|
||||
KatanaEngine::getSymmetrics () const { return _symmetrics; }
|
||||
inline Block* KatanaEngine::getBlock ( size_t i ) const { return (i < _blocks.size()) ? _blocks[i] : NULL; }
|
||||
inline NegociateWindow* KatanaEngine::getNegociateWindow () { return _negociateWindow; }
|
||||
inline size_t KatanaEngine::getRoutingPlanesSize () const { return _routingPlanes.size(); }
|
||||
inline void KatanaEngine::setViewer ( CellViewer* viewer ) { _viewer=viewer; }
|
||||
|
@ -175,6 +191,7 @@ namespace Katana {
|
|||
inline void KatanaEngine::setRipupCost ( uint32_t cost ) { _configuration->setRipupCost(cost); }
|
||||
inline void KatanaEngine::setHTracksReservedLocal ( uint32_t reserved ) { _configuration->setHTracksReservedLocal(reserved); }
|
||||
inline void KatanaEngine::setVTracksReservedLocal ( uint32_t reserved ) { _configuration->setVTracksReservedLocal(reserved); }
|
||||
inline void KatanaEngine::addBlock ( Block* block ) { _blocks.push_back(block); }
|
||||
inline void KatanaEngine::setMinimumWL ( double minimum ) { _minimumWL = minimum; }
|
||||
inline void KatanaEngine::setPostEventCb ( Configuration::PostEventCb_t cb ) { _configuration->setPostEventCb(cb); }
|
||||
inline void KatanaEngine::printConfiguration () const { _configuration->print(getCell()); }
|
||||
|
|
|
@ -66,7 +66,6 @@ namespace Katana {
|
|||
public:
|
||||
static Session* get ( const char* message=NULL );
|
||||
inline static Super* base ();
|
||||
inline static bool isOpen ();
|
||||
inline static bool isEmpty ();
|
||||
inline static KatanaEngine* getKatanaEngine ();
|
||||
static Configuration* getConfiguration ();
|
||||
|
@ -179,9 +178,6 @@ namespace Katana {
|
|||
inline size_t Session::revalidate ()
|
||||
{ return get("revalidate()")->_revalidate(); }
|
||||
|
||||
inline bool Session::isOpen ()
|
||||
{ return get() != NULL; }
|
||||
|
||||
inline bool Session::isEmpty ()
|
||||
{ return get("isEmpty()")->_isEmpty(); }
|
||||
|
||||
|
|
Loading…
Reference in New Issue