In Anabatic, correctly set the wire width according to the routing gauge.
* New: Anabatic::AutoContact::setLayerAndWidth() to set both layer and VIA width/side according to the RoutingGauge. If the delta in zero, use the metal gauge, and the VIA gauge otherwise. * Bug: In Anabatic::AutoContactTerminal, Anabatic::AutoContactTurn, Anabatic::AutoContactHTee & Anabatic::AutoContactVTee, in the updateTopology() method, set both the layer and the VIA with when there is a change of layer. Note that this default size may be overriden later by updateSeize() in the case of non-default width segments. * New: In Anabatic::AutoSegment, new overload setLayer(size_t) to set both layer and segment with according to the routing gauge. * Bug: In Anabatic::AutoHorizontal and Anabatic::AutoVertical, in method _makeDogleg(), make use of the new setLayer() to correctly set up the wire width. Idem for Anabatic::AutoSegment::changeDepth() and ::makeDogleg(), and in Anabatic::LayerAssign.
This commit is contained in:
parent
2f9a7076cb
commit
ea4fdfd230
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
find_package(PythonLibs 2 REQUIRED)
|
find_package(PythonLibs 2 REQUIRED)
|
||||||
find_package(PythonSitePackages REQUIRED)
|
find_package(PythonSitePackages REQUIRED)
|
||||||
|
find_package(FLUTE REQUIRED)
|
||||||
find_package(VLSISAPD REQUIRED)
|
find_package(VLSISAPD REQUIRED)
|
||||||
find_package(HURRICANE REQUIRED)
|
find_package(HURRICANE REQUIRED)
|
||||||
find_package(CORIOLIS REQUIRED)
|
find_package(CORIOLIS REQUIRED)
|
||||||
|
|
|
@ -552,6 +552,20 @@ namespace Anabatic {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AutoContact::setLayerAndWidth ( size_t delta, size_t depth )
|
||||||
|
{
|
||||||
|
if (delta == 0) {
|
||||||
|
setLayer( Session::getRoutingLayer(depth) );
|
||||||
|
setSizes( Session::getWireWidth (depth)
|
||||||
|
, Session::getWireWidth (depth) );
|
||||||
|
} else {
|
||||||
|
setLayer( Session::getContactLayer(depth) );
|
||||||
|
setSizes( Session::getViaWidth (depth)
|
||||||
|
, Session::getViaWidth (depth) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
AutoContact* AutoContact::createFrom ( Contact* hurricaneContact )
|
AutoContact* AutoContact::createFrom ( Contact* hurricaneContact )
|
||||||
{
|
{
|
||||||
AutoContact* autoContact = NULL;
|
AutoContact* autoContact = NULL;
|
||||||
|
|
|
@ -309,10 +309,10 @@ namespace Anabatic {
|
||||||
if (depthH1 == depthH2) {
|
if (depthH1 == depthH2) {
|
||||||
// Dogleg on the vertical.
|
// Dogleg on the vertical.
|
||||||
switch ( delta ) {
|
switch ( delta ) {
|
||||||
case 0: setLayer( rg->getRoutingLayer(minDepth) ); break;
|
case 0:
|
||||||
case 1: setLayer( rg->getContactLayer(minDepth) ); break;
|
case 1: setLayerAndWidth( delta, minDepth ); break;
|
||||||
default:
|
default:
|
||||||
setLayer( rg->getContactLayer( depthH1 + ((depthH1==minDepth)?0:-1) ) );
|
setLayerAndWidth( delta, depthH1 + ((depthH1==minDepth)?0:-1) );
|
||||||
_vertical1 = static_cast<AutoVertical*>( _vertical1->makeDogleg(this) );
|
_vertical1 = static_cast<AutoVertical*>( _vertical1->makeDogleg(this) );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -322,12 +322,12 @@ namespace Anabatic {
|
||||||
int deltaH2 = (int)depthH2 - (int)depthV1;
|
int deltaH2 = (int)depthH2 - (int)depthV1;
|
||||||
|
|
||||||
if (std::abs(deltaH1) > std::abs(deltaH2)) {
|
if (std::abs(deltaH1) > std::abs(deltaH2)) {
|
||||||
setLayer( rg->getContactLayer( depthH2 + ((depthH2<depthV1)?0:-1) ) );
|
setLayerAndWidth( 2, depthH2 + ((depthH2<depthV1)?0:-1) );
|
||||||
//_horizontal1 = static_cast<AutoHorizontal*>( _horizontal1->makeDogleg(this) );
|
//_horizontal1 = static_cast<AutoHorizontal*>( _horizontal1->makeDogleg(this) );
|
||||||
_horizontal1->makeDogleg(this);
|
_horizontal1->makeDogleg(this);
|
||||||
cdebug_log(145,0) << "New h1:" << _horizontal1 << endl;
|
cdebug_log(145,0) << "New h1:" << _horizontal1 << endl;
|
||||||
} else {
|
} else {
|
||||||
setLayer( rg->getContactLayer( depthH1 + ((depthH1<depthV1)?0:-1) ) );
|
setLayerAndWidth( 2, depthH1 + ((depthH1<depthV1)?0:-1) );
|
||||||
//_horizontal2 = static_cast<AutoHorizontal*>( _horizontal2->makeDogleg(this) );
|
//_horizontal2 = static_cast<AutoHorizontal*>( _horizontal2->makeDogleg(this) );
|
||||||
_horizontal2->makeDogleg(this);
|
_horizontal2->makeDogleg(this);
|
||||||
cdebug_log(145,0) << "New h2:" << _horizontal2 << endl;
|
cdebug_log(145,0) << "New h2:" << _horizontal2 << endl;
|
||||||
|
|
|
@ -550,8 +550,8 @@ namespace Anabatic {
|
||||||
cdebug_log(145,0) << "Update seg: " << _segment << endl;
|
cdebug_log(145,0) << "Update seg: " << _segment << endl;
|
||||||
delta = abssub( anchorDepth, rg->getLayerDepth( _segment->getLayer() ) );
|
delta = abssub( anchorDepth, rg->getLayerDepth( _segment->getLayer() ) );
|
||||||
}
|
}
|
||||||
else if (delta == 0) setLayer( rg->getRoutingLayer(anchorDepth) );
|
else if (delta == 0) setLayerAndWidth( delta, anchorDepth );
|
||||||
else if (delta == 1) setLayer( rg->getContactLayer(std::min(anchorDepth,segmentDepth)) );
|
else if (delta == 1) setLayerAndWidth( delta, std::min(anchorDepth,segmentDepth) );
|
||||||
}
|
}
|
||||||
_segment->invalidate( this );
|
_segment->invalidate( this );
|
||||||
|
|
||||||
|
|
|
@ -263,7 +263,7 @@ namespace Anabatic {
|
||||||
delta = abssub ( depthH1, depthV1 );
|
delta = abssub ( depthH1, depthV1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
setLayer ( (delta == 0) ? rg->getRoutingLayer(depthContact) : rg->getContactLayer(depthContact) );
|
setLayerAndWidth( delta, depthContact );
|
||||||
}
|
}
|
||||||
|
|
||||||
_horizontal1->invalidate( this );
|
_horizontal1->invalidate( this );
|
||||||
|
|
|
@ -278,11 +278,11 @@ namespace Anabatic {
|
||||||
cdebug_log(145,0) << "depthV1 == depthV2 (" << depthV1 << ")" << endl;
|
cdebug_log(145,0) << "depthV1 == depthV2 (" << depthV1 << ")" << endl;
|
||||||
// Dogleg on the horizontal.
|
// Dogleg on the horizontal.
|
||||||
switch ( delta ) {
|
switch ( delta ) {
|
||||||
case 0: setLayer( rg->getRoutingLayer(minDepth) ); break;
|
case 0:
|
||||||
case 1: setLayer( rg->getContactLayer(minDepth) ); break;
|
case 1: setLayerAndWidth( delta, minDepth ); break;
|
||||||
default:
|
default:
|
||||||
cdebug_log(145,0) << "Restore connectivity: dogleg on h1." << endl;
|
cdebug_log(145,0) << "Restore connectivity: dogleg on h1." << endl;
|
||||||
setLayer( rg->getContactLayer( depthV1 + ((depthV1==minDepth)?0:-1) ) );
|
setLayerAndWidth( delta, depthV1 + ((depthV1==minDepth)?0:-1) );
|
||||||
_horizontal1 = static_cast<AutoHorizontal*>( _horizontal1->makeDogleg(this) );
|
_horizontal1 = static_cast<AutoHorizontal*>( _horizontal1->makeDogleg(this) );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -292,11 +292,11 @@ namespace Anabatic {
|
||||||
int deltaV2 = (int)depthV2 - (int)depthH1;
|
int deltaV2 = (int)depthV2 - (int)depthH1;
|
||||||
|
|
||||||
if (std::abs(deltaV1) > std::abs(deltaV2)) {
|
if (std::abs(deltaV1) > std::abs(deltaV2)) {
|
||||||
setLayer( rg->getContactLayer( depthV2 + ((depthV2<depthH1)?0:-1) ) );
|
setLayerAndWidth( 2, depthV2 + ((depthV2<depthH1)?0:-1) );
|
||||||
//_vertical1 = static_cast<AutoVertical*>( _vertical1->makeDogleg(this) );
|
//_vertical1 = static_cast<AutoVertical*>( _vertical1->makeDogleg(this) );
|
||||||
_vertical1->makeDogleg(this);
|
_vertical1->makeDogleg(this);
|
||||||
} else {
|
} else {
|
||||||
setLayer( rg->getContactLayer( depthV1 + ((depthV1<depthH1)?0:-1) ) );
|
setLayerAndWidth( 2, depthV1 + ((depthV1<depthH1)?0:-1) );
|
||||||
//_vertical2 = static_cast<AutoVertical*>( _vertical2->makeDogleg(this) );
|
//_vertical2 = static_cast<AutoVertical*>( _vertical2->makeDogleg(this) );
|
||||||
_vertical2->makeDogleg(this);
|
_vertical2->makeDogleg(this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -804,8 +804,9 @@ namespace Anabatic {
|
||||||
upLayer = (depth+1 <= Session::getConfiguration()->getAllowedDepth());
|
upLayer = (depth+1 <= Session::getConfiguration()->getAllowedDepth());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t doglegDepth = depth + ((upLayer)?1:-1);
|
||||||
Layer* contactLayer = Session::getRoutingGauge()->getContactLayer( depth + ((upLayer)?0:-1) );
|
Layer* contactLayer = Session::getRoutingGauge()->getContactLayer( depth + ((upLayer)?0:-1) );
|
||||||
const Layer* doglegLayer = Session::getRoutingGauge()->getRoutingLayer( depth + ((upLayer)?1:-1) );
|
const Layer* doglegLayer = Session::getRoutingGauge()->getRoutingLayer( doglegDepth );
|
||||||
|
|
||||||
Session::dogleg( this );
|
Session::dogleg( this );
|
||||||
targetDetach();
|
targetDetach();
|
||||||
|
@ -814,7 +815,7 @@ namespace Anabatic {
|
||||||
AutoContact* dlContact1 = AutoContactTurn::create( doglegGCell, _horizontal->getNet(), contactLayer );
|
AutoContact* dlContact1 = AutoContactTurn::create( doglegGCell, _horizontal->getNet(), contactLayer );
|
||||||
AutoContact* dlContact2 = AutoContactTurn::create( doglegGCell, _horizontal->getNet(), contactLayer );
|
AutoContact* dlContact2 = AutoContactTurn::create( doglegGCell, _horizontal->getNet(), contactLayer );
|
||||||
AutoSegment* segment1 = AutoSegment::create( dlContact1 , dlContact2, Flags::Vertical );
|
AutoSegment* segment1 = AutoSegment::create( dlContact1 , dlContact2, Flags::Vertical );
|
||||||
segment1->setLayer( doglegLayer );
|
segment1->setLayer( doglegDepth );
|
||||||
segment1->_setAxis( doglegAxis );
|
segment1->_setAxis( doglegAxis );
|
||||||
segment1->setFlags( SegDogleg|SegSlackened|SegCanonical|SegNotAligned );
|
segment1->setFlags( SegDogleg|SegSlackened|SegCanonical|SegNotAligned );
|
||||||
|
|
||||||
|
@ -825,7 +826,7 @@ namespace Anabatic {
|
||||||
targetAttach( dlContact1 );
|
targetAttach( dlContact1 );
|
||||||
AutoSegment* segment2 = AutoSegment::create( dlContact2 , autoTarget, Flags::Horizontal );
|
AutoSegment* segment2 = AutoSegment::create( dlContact2 , autoTarget, Flags::Horizontal );
|
||||||
autoTarget->cacheAttach( segment2 );
|
autoTarget->cacheAttach( segment2 );
|
||||||
segment2->setLayer( getLayer() );
|
segment2->setLayer( depth );
|
||||||
segment2->_setAxis( getY() );
|
segment2->_setAxis( getY() );
|
||||||
segment2->setFlags( (isSlackened()?SegSlackened:0) );
|
segment2->setFlags( (isSlackened()?SegSlackened:0) );
|
||||||
Session::dogleg( segment2 );
|
Session::dogleg( segment2 );
|
||||||
|
|
|
@ -1632,7 +1632,7 @@ namespace Anabatic {
|
||||||
|
|
||||||
const Layer* newLayer = Session::getRoutingGauge()->getRoutingLayer(depth);
|
const Layer* newLayer = Session::getRoutingGauge()->getRoutingLayer(depth);
|
||||||
if (getLayer() != newLayer) {
|
if (getLayer() != newLayer) {
|
||||||
setLayer( newLayer );
|
setLayer( depth );
|
||||||
getAutoSource()->invalidate( Flags::Topology|Flags::NoCheckLayer );
|
getAutoSource()->invalidate( Flags::Topology|Flags::NoCheckLayer );
|
||||||
getAutoTarget()->invalidate( Flags::Topology|Flags::NoCheckLayer );
|
getAutoTarget()->invalidate( Flags::Topology|Flags::NoCheckLayer );
|
||||||
}
|
}
|
||||||
|
@ -2110,18 +2110,18 @@ namespace Anabatic {
|
||||||
if (getLayer()->above(from->getLayer())) {
|
if (getLayer()->above(from->getLayer())) {
|
||||||
cdebug_log(149,0) << "Go Down from depth " << segmentDepth << endl;
|
cdebug_log(149,0) << "Go Down from depth " << segmentDepth << endl;
|
||||||
|
|
||||||
doglegs[ index + 1 ]->setLayer( rg->getRoutingLayer(segmentDepth-1) );
|
doglegs[ index + 1 ]->setLayer( segmentDepth-1 );
|
||||||
cdebug_log(149,0) << "doglegs[i+1]: " << doglegs[index+1] << endl;
|
cdebug_log(149,0) << "doglegs[i+1]: " << doglegs[index+1] << endl;
|
||||||
|
|
||||||
if (isSource) {
|
if (isSource) {
|
||||||
doglegs[ index + 0 ]->setLayer( rg->getRoutingLayer(segmentDepth-2) );
|
doglegs[ index + 0 ]->setLayer( segmentDepth-2 );
|
||||||
doglegs[ index + 1 ]->getAutoSource()->setLayer( rg->getContactLayer(segmentDepth-2) );
|
doglegs[ index + 1 ]->getAutoSource()->setLayer( rg->getContactLayer(segmentDepth-2) );
|
||||||
doglegs[ index + 1 ]->getAutoTarget()->setLayer( rg->getContactLayer(segmentDepth-1) );
|
doglegs[ index + 1 ]->getAutoTarget()->setLayer( rg->getContactLayer(segmentDepth-1) );
|
||||||
cdebug_log(149,0) << "doglegs[i+0]: " << doglegs[index+0] << endl;
|
cdebug_log(149,0) << "doglegs[i+0]: " << doglegs[index+0] << endl;
|
||||||
cdebug_log(149,0) << "doglegs[i+1]: " << doglegs[index+1]->getAutoSource() << endl;
|
cdebug_log(149,0) << "doglegs[i+1]: " << doglegs[index+1]->getAutoSource() << endl;
|
||||||
cdebug_log(149,0) << "doglegs[i+1]: " << doglegs[index+1]->getAutoTarget() << endl;
|
cdebug_log(149,0) << "doglegs[i+1]: " << doglegs[index+1]->getAutoTarget() << endl;
|
||||||
} else {
|
} else {
|
||||||
doglegs[ index + 2 ]->setLayer( rg->getRoutingLayer(segmentDepth-2) );
|
doglegs[ index + 2 ]->setLayer( segmentDepth-2 );
|
||||||
doglegs[ index + 1 ]->getAutoTarget()->setLayer( rg->getContactLayer(segmentDepth-2) );
|
doglegs[ index + 1 ]->getAutoTarget()->setLayer( rg->getContactLayer(segmentDepth-2) );
|
||||||
doglegs[ index + 1 ]->getAutoSource()->setLayer( rg->getContactLayer(segmentDepth-1) );
|
doglegs[ index + 1 ]->getAutoSource()->setLayer( rg->getContactLayer(segmentDepth-1) );
|
||||||
cdebug_log(149,0) << "doglegs[i+2]: " << doglegs[index+2] << endl;
|
cdebug_log(149,0) << "doglegs[i+2]: " << doglegs[index+2] << endl;
|
||||||
|
@ -2131,18 +2131,18 @@ namespace Anabatic {
|
||||||
} else {
|
} else {
|
||||||
cdebug_log(149,0) << "Go Up from depth " << segmentDepth << endl;
|
cdebug_log(149,0) << "Go Up from depth " << segmentDepth << endl;
|
||||||
|
|
||||||
doglegs[ index + 1 ]->setLayer( rg->getRoutingLayer(segmentDepth+1) );
|
doglegs[ index + 1 ]->setLayer( segmentDepth+1 );
|
||||||
cdebug_log(149,0) << "doglegs[i+1]: " << doglegs[index+1] << endl;
|
cdebug_log(149,0) << "doglegs[i+1]: " << doglegs[index+1] << endl;
|
||||||
|
|
||||||
if (isSource) {
|
if (isSource) {
|
||||||
doglegs[ index + 0 ]->setLayer( rg->getRoutingLayer(segmentDepth+2) );
|
doglegs[ index + 0 ]->setLayer( segmentDepth+2 );
|
||||||
doglegs[ index + 1 ]->getAutoSource()->setLayer( rg->getContactLayer(segmentDepth+1) );
|
doglegs[ index + 1 ]->getAutoSource()->setLayer( rg->getContactLayer(segmentDepth+1) );
|
||||||
doglegs[ index + 1 ]->getAutoTarget()->setLayer( rg->getContactLayer(segmentDepth ) );
|
doglegs[ index + 1 ]->getAutoTarget()->setLayer( rg->getContactLayer(segmentDepth ) );
|
||||||
cdebug_log(149,0) << "doglegs[i+0]: " << doglegs[index+0] << endl;
|
cdebug_log(149,0) << "doglegs[i+0]: " << doglegs[index+0] << endl;
|
||||||
cdebug_log(149,0) << "doglegs[i+1]: " << doglegs[index+1]->getAutoSource() << endl;
|
cdebug_log(149,0) << "doglegs[i+1]: " << doglegs[index+1]->getAutoSource() << endl;
|
||||||
cdebug_log(149,0) << "doglegs[i+1]: " << doglegs[index+1]->getAutoTarget() << endl;
|
cdebug_log(149,0) << "doglegs[i+1]: " << doglegs[index+1]->getAutoTarget() << endl;
|
||||||
} else {
|
} else {
|
||||||
doglegs[ index + 2 ]->setLayer( rg->getRoutingLayer(segmentDepth+2) );
|
doglegs[ index + 2 ]->setLayer( segmentDepth+2 );
|
||||||
doglegs[ index + 1 ]->getAutoTarget()->setLayer( rg->getContactLayer(segmentDepth+1) );
|
doglegs[ index + 1 ]->getAutoTarget()->setLayer( rg->getContactLayer(segmentDepth+1) );
|
||||||
doglegs[ index + 1 ]->getAutoSource()->setLayer( rg->getContactLayer(segmentDepth ) );
|
doglegs[ index + 1 ]->getAutoSource()->setLayer( rg->getContactLayer(segmentDepth ) );
|
||||||
cdebug_log(149,0) << "doglegs[i+2]: " << doglegs[index+2] << endl;
|
cdebug_log(149,0) << "doglegs[i+2]: " << doglegs[index+2] << endl;
|
||||||
|
|
|
@ -712,8 +712,9 @@ namespace Anabatic {
|
||||||
upLayer = (depth+1 <= Session::getConfiguration()->getAllowedDepth());
|
upLayer = (depth+1 <= Session::getConfiguration()->getAllowedDepth());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t doglegDepth = depth + ((upLayer)?1:-1);
|
||||||
Layer* contactLayer = Session::getRoutingGauge()->getContactLayer ( depth + ((upLayer)?0:-1) );
|
Layer* contactLayer = Session::getRoutingGauge()->getContactLayer ( depth + ((upLayer)?0:-1) );
|
||||||
const Layer* doglegLayer = Session::getRoutingGauge()->getRoutingLayer ( depth + ((upLayer)?1:-1) );
|
const Layer* doglegLayer = Session::getRoutingGauge()->getRoutingLayer ( doglegDepth );
|
||||||
|
|
||||||
Session::dogleg( this );
|
Session::dogleg( this );
|
||||||
targetDetach();
|
targetDetach();
|
||||||
|
@ -725,7 +726,7 @@ namespace Anabatic {
|
||||||
cdebug_log(149,0) << dlContact2 << endl;
|
cdebug_log(149,0) << dlContact2 << endl;
|
||||||
AutoSegment* segment1 = AutoSegment::create( dlContact1 , dlContact2, Flags::Horizontal );
|
AutoSegment* segment1 = AutoSegment::create( dlContact1 , dlContact2, Flags::Horizontal );
|
||||||
cdebug_log(149,0) << segment1 << endl;
|
cdebug_log(149,0) << segment1 << endl;
|
||||||
segment1->setLayer( doglegLayer );
|
segment1->setLayer( doglegDepth );
|
||||||
segment1->_setAxis( doglegAxis );
|
segment1->_setAxis( doglegAxis );
|
||||||
segment1->setFlags( SegDogleg|SegSlackened|SegCanonical|SegNotAligned );
|
segment1->setFlags( SegDogleg|SegSlackened|SegCanonical|SegNotAligned );
|
||||||
cdebug_log(149,0) << "New " << dlContact1->base() << "." << endl;
|
cdebug_log(149,0) << "New " << dlContact1->base() << "." << endl;
|
||||||
|
@ -735,7 +736,7 @@ namespace Anabatic {
|
||||||
targetAttach( dlContact1 );
|
targetAttach( dlContact1 );
|
||||||
AutoSegment* segment2 = AutoVertical::create ( dlContact2, autoTarget, Flags::Vertical );
|
AutoSegment* segment2 = AutoVertical::create ( dlContact2, autoTarget, Flags::Vertical );
|
||||||
autoTarget->cacheAttach( segment2 );
|
autoTarget->cacheAttach( segment2 );
|
||||||
segment2->setLayer( getLayer() );
|
segment2->setLayer( depth );
|
||||||
segment2->_setAxis( getX() );
|
segment2->_setAxis( getX() );
|
||||||
segment2->setFlags( (isSlackened()?SegSlackened:0) );
|
segment2->setFlags( (isSlackened()?SegSlackened:0) );
|
||||||
Session::dogleg( segment2 );
|
Session::dogleg( segment2 );
|
||||||
|
|
|
@ -8,6 +8,7 @@ endif ( CHECK_DETERMINISM )
|
||||||
${CORIOLIS_INCLUDE_DIR}
|
${CORIOLIS_INCLUDE_DIR}
|
||||||
${HURRICANE_INCLUDE_DIR}
|
${HURRICANE_INCLUDE_DIR}
|
||||||
${CONFIGURATION_INCLUDE_DIR}
|
${CONFIGURATION_INCLUDE_DIR}
|
||||||
|
${FLUTE_INCLUDE_DIR}
|
||||||
${Boost_INCLUDE_DIRS}
|
${Boost_INCLUDE_DIRS}
|
||||||
${QtX_INCLUDE_DIR}
|
${QtX_INCLUDE_DIR}
|
||||||
${PYTHON_INCLUDE_PATH}
|
${PYTHON_INCLUDE_PATH}
|
||||||
|
@ -76,6 +77,7 @@ endif ( CHECK_DETERMINISM )
|
||||||
${CONFIGURATION_LIBRARY}
|
${CONFIGURATION_LIBRARY}
|
||||||
${CIF_LIBRARY}
|
${CIF_LIBRARY}
|
||||||
${AGDS_LIBRARY}
|
${AGDS_LIBRARY}
|
||||||
|
${FLUTE_LIBRARIES}
|
||||||
${LEFDEF_LIBRARIES}
|
${LEFDEF_LIBRARIES}
|
||||||
${OA_LIBRARIES}
|
${OA_LIBRARIES}
|
||||||
${QtX_LIBRARIES}
|
${QtX_LIBRARIES}
|
||||||
|
|
|
@ -117,8 +117,14 @@ namespace Anabatic {
|
||||||
}
|
}
|
||||||
|
|
||||||
global++;
|
global++;
|
||||||
if ((*isegment)->getLayer() == Session::getRoutingLayer(1)) (*isegment)->setLayer( Session::getRoutingLayer(3) );
|
if ((*isegment)->getLayer() == Session::getRoutingLayer(1)) {
|
||||||
if ((*isegment)->getLayer() == Session::getRoutingLayer(2)) (*isegment)->setLayer( Session::getRoutingLayer(4) );
|
(*isegment)->setLayer( Session::getRoutingLayer(3) );
|
||||||
|
(*isegment)->setWidth( Session::getWireWidth (3) );
|
||||||
|
}
|
||||||
|
if ((*isegment)->getLayer() == Session::getRoutingLayer(2)) {
|
||||||
|
(*isegment)->setLayer( Session::getRoutingLayer(4) );
|
||||||
|
(*isegment)->setWidth( Session::getWireWidth (4) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,8 +178,14 @@ namespace Anabatic {
|
||||||
netGlobal++;
|
netGlobal++;
|
||||||
|
|
||||||
cdebug_log(145,0) << "Migrate to M4/M5: " << autoSegment << endl;
|
cdebug_log(145,0) << "Migrate to M4/M5: " << autoSegment << endl;
|
||||||
if (autoSegment->isHorizontal()) autoSegment->setLayer( Session::getRoutingLayer(3) );
|
if (autoSegment->isHorizontal()) {
|
||||||
if (autoSegment->isVertical ()) autoSegment->setLayer( Session::getRoutingLayer(4) );
|
autoSegment->setLayer( Session::getRoutingLayer(3) );
|
||||||
|
autoSegment->setWidth( Session::getWireWidth (3) );
|
||||||
|
}
|
||||||
|
if (autoSegment->isVertical()) {
|
||||||
|
autoSegment->setLayer( Session::getRoutingLayer(4) );
|
||||||
|
autoSegment->setWidth( Session::getWireWidth (4) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -178,6 +178,7 @@ namespace Anabatic {
|
||||||
, Flags flags=Flags::WarnOnError );
|
, Flags flags=Flags::WarnOnError );
|
||||||
void restoreNativeConstraintBox ();
|
void restoreNativeConstraintBox ();
|
||||||
void migrateConstraintBox ( AutoContact* other );
|
void migrateConstraintBox ( AutoContact* other );
|
||||||
|
void setLayerAndWidth ( size_t delta, size_t depth );
|
||||||
void destroy ();
|
void destroy ();
|
||||||
// Inspector Management.
|
// Inspector Management.
|
||||||
Record* _getRecord () const;
|
Record* _getRecord () const;
|
||||||
|
|
|
@ -178,6 +178,8 @@ namespace Anabatic {
|
||||||
inline DbU::Unit getTargetY () const;
|
inline DbU::Unit getTargetY () const;
|
||||||
inline void invert ();
|
inline void invert ();
|
||||||
inline void setLayer ( const Layer* );
|
inline void setLayer ( const Layer* );
|
||||||
|
inline void setLayer ( size_t depth );
|
||||||
|
inline void setWidth ( DbU::Unit );
|
||||||
// Predicates.
|
// Predicates.
|
||||||
inline bool isHorizontal () const;
|
inline bool isHorizontal () const;
|
||||||
inline bool isVertical () const;
|
inline bool isVertical () const;
|
||||||
|
@ -538,6 +540,7 @@ namespace Anabatic {
|
||||||
inline void AutoSegment::incReduceds () { if (_reduceds<3) ++_reduceds; }
|
inline void AutoSegment::incReduceds () { if (_reduceds<3) ++_reduceds; }
|
||||||
inline void AutoSegment::decReduceds () { if (_reduceds>0) --_reduceds; }
|
inline void AutoSegment::decReduceds () { if (_reduceds>0) --_reduceds; }
|
||||||
inline void AutoSegment::setLayer ( const Layer* layer ) { base()->setLayer(layer); _depth=Session::getLayerDepth(layer); _flags|=SegInvalidatedLayer; }
|
inline void AutoSegment::setLayer ( const Layer* layer ) { base()->setLayer(layer); _depth=Session::getLayerDepth(layer); _flags|=SegInvalidatedLayer; }
|
||||||
|
inline void AutoSegment::setWidth ( DbU::Unit width ) { base()->setWidth(width); }
|
||||||
inline void AutoSegment::setOptimalMin ( DbU::Unit min ) { _optimalMin = (unsigned int)DbU::getLambda(min-getOrigin()); }
|
inline void AutoSegment::setOptimalMin ( DbU::Unit min ) { _optimalMin = (unsigned int)DbU::getLambda(min-getOrigin()); }
|
||||||
inline void AutoSegment::setOptimalMax ( DbU::Unit max ) { _optimalMax = (unsigned int)DbU::getLambda(max-getOrigin()); }
|
inline void AutoSegment::setOptimalMax ( DbU::Unit max ) { _optimalMax = (unsigned int)DbU::getLambda(max-getOrigin()); }
|
||||||
inline void AutoSegment::mergeNativeMin ( DbU::Unit min ) { _nativeConstraints.getVMin() = std::max( min, _nativeConstraints.getVMin() ); }
|
inline void AutoSegment::mergeNativeMin ( DbU::Unit min ) { _nativeConstraints.getVMin() = std::max( min, _nativeConstraints.getVMin() ); }
|
||||||
|
@ -547,6 +550,17 @@ namespace Anabatic {
|
||||||
inline void AutoSegment::resetUserConstraints () { _userConstraints = Interval(false); }
|
inline void AutoSegment::resetUserConstraints () { _userConstraints = Interval(false); }
|
||||||
|
|
||||||
|
|
||||||
|
inline void AutoSegment::setLayer ( size_t depth )
|
||||||
|
{
|
||||||
|
RoutingLayerGauge* layerGauge = Session::getLayerGauge( depth );
|
||||||
|
base()->setLayer( layerGauge->getLayer () );
|
||||||
|
base()->setWidth( layerGauge->getWireWidth() );
|
||||||
|
|
||||||
|
_depth = depth;
|
||||||
|
_flags|=SegInvalidatedLayer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline DbU::Unit AutoSegment::getContactWidth () const
|
inline DbU::Unit AutoSegment::getContactWidth () const
|
||||||
{ return getWidth() + Session::getViaWidth(getLayer()) - Session::getWireWidth(getLayer()); }
|
{ return getWidth() + Session::getViaWidth(getLayer()) - Session::getWireWidth(getLayer()); }
|
||||||
|
|
||||||
|
|
|
@ -1,50 +0,0 @@
|
||||||
READ THIS LICENSE AGREEMENT CAREFULLY BEFORE USING THIS PRODUCT. BY USING
|
|
||||||
THIS PRODUCT YOU INDICATE YOUR ACCEPTANCE OF THE TERMS OF THE FOLLOWING
|
|
||||||
AGREEMENT. THESE TERMS APPLY TO YOU AND ANY SUBSEQUENT LICENSEE OF THIS
|
|
||||||
PRODUCT.
|
|
||||||
|
|
||||||
License Agreement for FLUTE
|
|
||||||
|
|
||||||
Copyright (c) 2004 by Dr. Chris C. N. Chu
|
|
||||||
All rights reserved
|
|
||||||
|
|
||||||
ATTRIBUTION ASSURANCE LICENSE (adapted from the original BSD license)
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the conditions below are
|
|
||||||
met. These conditions require a modest attribution to Dr. Chris C. N. Chu
|
|
||||||
(the "Author").
|
|
||||||
|
|
||||||
1. Redistributions of the source code, with or without modification (the
|
|
||||||
"Code"), must be accompanied by any documentation and, each time
|
|
||||||
the resulting executable program or a program dependent thereon is
|
|
||||||
launched, a prominent display (e.g., splash screen or banner text) of
|
|
||||||
the Author's attribution information, which includes:
|
|
||||||
(a) Dr. Chris C. N. Chu ("AUTHOR"),
|
|
||||||
(b) Iowa State University ("PROFESSIONAL IDENTIFICATION"), and
|
|
||||||
(c) http://home.eng.iastate.edu/~cnchu/ ("URL").
|
|
||||||
|
|
||||||
2. Users who intend to use the Code for commercial purposes will notify
|
|
||||||
Author prior to such commercial use.
|
|
||||||
|
|
||||||
3. Neither the name nor any trademark of the Author may be used to
|
|
||||||
endorse or promote products derived from this software without
|
|
||||||
specific prior written permission.
|
|
||||||
|
|
||||||
4. Users are entirely responsible, to the exclusion of the Author and any
|
|
||||||
other persons, for compliance with (1) regulations set by owners or
|
|
||||||
administrators of employed equipment, (2) licensing terms of any other
|
|
||||||
software, and (3) local, national, and international regulations
|
|
||||||
regarding use, including those regarding import, export, and use of
|
|
||||||
encryption software.
|
|
||||||
|
|
||||||
THIS FREE SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR
|
|
||||||
IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
||||||
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
||||||
IN NO EVENT SHALL THE AUTHOR OR ANY CONTRIBUTOR BE LIABLE FOR ANY DIRECT,
|
|
||||||
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, EFFECTS OF UNAUTHORIZED OR MALICIOUS
|
|
||||||
NETWORK ACCESS; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
||||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
||||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
||||||
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,44 +0,0 @@
|
||||||
#include "knik/global.h"
|
|
||||||
|
|
||||||
/*********************************************************************/
|
|
||||||
/*
|
|
||||||
Return the Manhattan distance between two points
|
|
||||||
*/
|
|
||||||
|
|
||||||
long dist(
|
|
||||||
Point p,
|
|
||||||
Point q
|
|
||||||
)
|
|
||||||
{
|
|
||||||
long dx, dy;
|
|
||||||
|
|
||||||
dx = (p.x) - (q.x);
|
|
||||||
if( dx < 0 ) dx = -dx;
|
|
||||||
dy = (p.y) - (q.y);
|
|
||||||
if( dy < 0 ) dy = -dy;
|
|
||||||
|
|
||||||
return dx + dy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************/
|
|
||||||
/*
|
|
||||||
Return the Manhattan distance between two points
|
|
||||||
*/
|
|
||||||
|
|
||||||
long dist2(
|
|
||||||
Point* p,
|
|
||||||
Point* q
|
|
||||||
)
|
|
||||||
{
|
|
||||||
long dx, dy;
|
|
||||||
|
|
||||||
dx = (p->x) - (q->x);
|
|
||||||
if( dx < 0 ) dx = -dx;
|
|
||||||
dy = (p->y) - (q->y);
|
|
||||||
if( dy < 0 ) dy = -dy;
|
|
||||||
|
|
||||||
return dx + dy;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*********************************************************************/
|
|
||||||
/*********************************************************************/
|
|
|
@ -1,161 +0,0 @@
|
||||||
#include "knik/dl.h"
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
dl_t dl_alloc()
|
|
||||||
{
|
|
||||||
dl_t dl = (dl_t)malloc(sizeof(dl_s));
|
|
||||||
if (!dl) {
|
|
||||||
printf("Out of memory!!\n");
|
|
||||||
} else {
|
|
||||||
dl->first = dl->last = 0; dl->count = 0;
|
|
||||||
}
|
|
||||||
return dl;
|
|
||||||
}
|
|
||||||
|
|
||||||
void dl_delete(dl_t dl, dl_el *el)
|
|
||||||
{
|
|
||||||
if (dl->first == el) {
|
|
||||||
dl->first = el->next;
|
|
||||||
}
|
|
||||||
if (dl->last == el) {
|
|
||||||
dl->last = el->prev;
|
|
||||||
}
|
|
||||||
if (el->next) {
|
|
||||||
el->next->prev = el->prev;
|
|
||||||
}
|
|
||||||
if (el->prev) {
|
|
||||||
el->prev->next = el->next;
|
|
||||||
}
|
|
||||||
free(el); dl->count--;
|
|
||||||
}
|
|
||||||
|
|
||||||
void dl_clear(dl_t dl)
|
|
||||||
{
|
|
||||||
dl_el *el, *next;
|
|
||||||
if (dl->count > 0) {
|
|
||||||
for (el=dl->first; el; el=next) {
|
|
||||||
next = el->next;
|
|
||||||
free(el);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dl->first = dl->last = 0;
|
|
||||||
dl->count = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void dl_concat(dl_t first_list, dl_t second_list)
|
|
||||||
{
|
|
||||||
if (first_list->count <= 0) {
|
|
||||||
*first_list = *second_list;
|
|
||||||
} else if (second_list->count > 0) {
|
|
||||||
first_list->last->next = second_list->first;
|
|
||||||
second_list->first->prev = first_list->last;
|
|
||||||
first_list->last = second_list->last;
|
|
||||||
first_list->count += second_list->count;
|
|
||||||
}
|
|
||||||
|
|
||||||
free(second_list);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void dl_insertion_sort(dl_t dl, size_t el_size,
|
|
||||||
int(*compar)(void *, void *))
|
|
||||||
{
|
|
||||||
char *buf;
|
|
||||||
void *curr_d, *srch_d;
|
|
||||||
dl_el *curr, *srch;
|
|
||||||
|
|
||||||
if (dl_length(dl) <= 1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
buf = (char*)malloc(el_size);
|
|
||||||
|
|
||||||
for (curr=dl->first; curr!=dl->last; curr=curr->next) {
|
|
||||||
curr_d = (void*)(((dl_el*)curr)+1);
|
|
||||||
|
|
||||||
for (srch=dl->last; srch!=curr; srch=srch->prev) {
|
|
||||||
srch_d = (void*)(((dl_el*)srch)+1);
|
|
||||||
if (compar(curr_d, srch_d) > 0) {
|
|
||||||
memcpy((void*)buf, curr_d, el_size);
|
|
||||||
memcpy(curr_d, srch_d, el_size);
|
|
||||||
memcpy(srch_d, (void*)buf, el_size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
free(buf);
|
|
||||||
}
|
|
||||||
|
|
||||||
void dl_sort(dl_t dl, size_t el_size, int(*compar)(void *, void *))
|
|
||||||
{
|
|
||||||
dl_el *el, *first_head, *second_head;
|
|
||||||
dl_s first_list, second_list;
|
|
||||||
void *first_item, *second_item;
|
|
||||||
int i, len;
|
|
||||||
|
|
||||||
if (dl_length(dl) <= 25) {
|
|
||||||
dl_insertion_sort(dl, el_size, compar);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
len = dl_length(dl)/2;
|
|
||||||
for (i=0, el=dl->first; i<len; i++) {
|
|
||||||
el = el->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
first_list.first = dl->first;
|
|
||||||
first_list.last = el->prev;
|
|
||||||
first_list.count = len;
|
|
||||||
first_list.last->next = 0;
|
|
||||||
|
|
||||||
second_list.first = el;
|
|
||||||
second_list.last = dl->last;
|
|
||||||
second_list.count = dl_length(dl)-len;
|
|
||||||
second_list.first->prev = 0;
|
|
||||||
|
|
||||||
dl_sort(&first_list, el_size, compar);
|
|
||||||
dl_sort(&second_list, el_size, compar);
|
|
||||||
|
|
||||||
/* in-place merging */
|
|
||||||
first_head = first_list.first;
|
|
||||||
second_head = second_list.first;
|
|
||||||
|
|
||||||
first_item = (void*)(((dl_el*)first_head)+1);
|
|
||||||
second_item = (void*)(((dl_el*)second_head)+1);
|
|
||||||
if (compar(first_item, second_item) <= 0) {
|
|
||||||
dl->first = el = first_head;
|
|
||||||
first_head = first_head->next;
|
|
||||||
} else {
|
|
||||||
dl->first = el = second_head;
|
|
||||||
second_head = second_head->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (1) {
|
|
||||||
first_item = (void*)(((dl_el*)first_head)+1);
|
|
||||||
second_item = (void*)(((dl_el*)second_head)+1);
|
|
||||||
if (compar(first_item, second_item) <= 0) {
|
|
||||||
el->next = first_head;
|
|
||||||
first_head->prev = el;
|
|
||||||
el = first_head;
|
|
||||||
first_head = first_head->next;
|
|
||||||
if (!first_head) {
|
|
||||||
el->next = second_head;
|
|
||||||
second_head->prev = el;
|
|
||||||
dl->last = second_list.last;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
el->next = second_head;
|
|
||||||
second_head->prev = el;
|
|
||||||
el = second_head;
|
|
||||||
second_head = second_head->next;
|
|
||||||
if (!second_head) {
|
|
||||||
el->next = first_head;
|
|
||||||
first_head->prev = el;
|
|
||||||
dl->last = first_list.last;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,28 +0,0 @@
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*
|
|
||||||
print error message and continue
|
|
||||||
*/
|
|
||||||
|
|
||||||
void err_msg(
|
|
||||||
char* msg
|
|
||||||
)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "%s\n", msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*
|
|
||||||
print error message and exit
|
|
||||||
*/
|
|
||||||
|
|
||||||
void err_exit(
|
|
||||||
char* msg
|
|
||||||
)
|
|
||||||
{
|
|
||||||
fprintf(stderr, "%s\n", msg);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,177 +0,0 @@
|
||||||
/****************************************************************************/
|
|
||||||
/*
|
|
||||||
Binary heap routines for use in Prim's algorithm,
|
|
||||||
with points are numbered from 0 to n-1
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "knik/heap.h"
|
|
||||||
#include "knik/err.h"
|
|
||||||
|
|
||||||
|
|
||||||
Heap* _heap = (Heap*)NULL;
|
|
||||||
long _max_heap_size = 0;
|
|
||||||
long _heap_size = 0;
|
|
||||||
|
|
||||||
/****************************************************************************/
|
|
||||||
/*
|
|
||||||
*/
|
|
||||||
|
|
||||||
void allocate_heap( long n )
|
|
||||||
{
|
|
||||||
if( _max_heap_size < n )
|
|
||||||
{
|
|
||||||
_heap = (Heap*)realloc( (void*)_heap, (size_t)(n+1)*sizeof(Heap) );
|
|
||||||
if( ! _heap )
|
|
||||||
{
|
|
||||||
err_exit( (char*)"Cannot reallocate memory in allocate_heap!" );
|
|
||||||
}
|
|
||||||
_max_heap_size = n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/****************************************************************************/
|
|
||||||
/*
|
|
||||||
*/
|
|
||||||
|
|
||||||
void deallocate_heap()
|
|
||||||
{
|
|
||||||
_max_heap_size = 0;
|
|
||||||
if( _heap )
|
|
||||||
{
|
|
||||||
free( (void*)_heap );
|
|
||||||
_heap = (Heap*)NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************/
|
|
||||||
|
|
||||||
void heap_init( long n )
|
|
||||||
{
|
|
||||||
register long p;
|
|
||||||
|
|
||||||
allocate_heap( n );
|
|
||||||
_heap_size = 0;
|
|
||||||
for( p = 0; p < n; p++ )
|
|
||||||
{
|
|
||||||
heap_idx( p ) = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
} /* END heap_init() */
|
|
||||||
|
|
||||||
/****************************************************************************/
|
|
||||||
|
|
||||||
void heap_insert(
|
|
||||||
long p,
|
|
||||||
long key
|
|
||||||
)
|
|
||||||
{
|
|
||||||
register long k; /* hole in the heap */
|
|
||||||
register long j; /* parent of the hole */
|
|
||||||
register long q; /* heap_elt(j) */
|
|
||||||
|
|
||||||
heap_key( p ) = key;
|
|
||||||
|
|
||||||
if( _heap_size == 0 )
|
|
||||||
{
|
|
||||||
_heap_size = 1;
|
|
||||||
heap_elt( 1 ) = p;
|
|
||||||
heap_idx( p ) = 1;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
k = ++ _heap_size;
|
|
||||||
j = k >> 1; /* k/2 */
|
|
||||||
|
|
||||||
while( (j > 0) && (heap_key(q=heap_elt(j)) > key) ) {
|
|
||||||
|
|
||||||
heap_elt( k ) = q;
|
|
||||||
heap_idx( q ) = k;
|
|
||||||
k = j;
|
|
||||||
j = k>>1; /* k/2 */
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* store p in the position of the hole */
|
|
||||||
heap_elt( k ) = p;
|
|
||||||
heap_idx( p ) = k;
|
|
||||||
|
|
||||||
} /* END heap_insert() */
|
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************/
|
|
||||||
|
|
||||||
void heap_decrease_key
|
|
||||||
(
|
|
||||||
long p,
|
|
||||||
long new_key
|
|
||||||
)
|
|
||||||
{
|
|
||||||
register long k; /* hole in the heap */
|
|
||||||
register long j; /* parent of the hole */
|
|
||||||
register long q; /* heap_elt(j) */
|
|
||||||
|
|
||||||
heap_key( p ) = new_key;
|
|
||||||
k = heap_idx( p );
|
|
||||||
j = k >> 1; /* k/2 */
|
|
||||||
|
|
||||||
if( (j > 0) && (heap_key(q=heap_elt(j)) > new_key) ) { /* change is needed */
|
|
||||||
do {
|
|
||||||
|
|
||||||
heap_elt( k ) = q;
|
|
||||||
heap_idx( q ) = k;
|
|
||||||
k = j;
|
|
||||||
j = k>>1; /* k/2 */
|
|
||||||
|
|
||||||
} while( (j > 0) && (heap_key(q=heap_elt(j)) > new_key) );
|
|
||||||
|
|
||||||
/* store p in the position of the hole */
|
|
||||||
heap_elt( k ) = p;
|
|
||||||
heap_idx( p ) = k;
|
|
||||||
}
|
|
||||||
|
|
||||||
} /* END heap_decrease_key() */
|
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************/
|
|
||||||
|
|
||||||
long heap_delete_min()
|
|
||||||
{
|
|
||||||
long min, last;
|
|
||||||
register long k; /* hole in the heap */
|
|
||||||
register long j; /* child of the hole */
|
|
||||||
register long l_key; /* key of last point */
|
|
||||||
|
|
||||||
if( _heap_size == 0 ) /* heap is empty */
|
|
||||||
return( -1 );
|
|
||||||
|
|
||||||
min = heap_elt( 1 );
|
|
||||||
last = heap_elt( _heap_size -- );
|
|
||||||
l_key = heap_key( last );
|
|
||||||
|
|
||||||
k = 1; j = 2;
|
|
||||||
while( j <= _heap_size ) {
|
|
||||||
|
|
||||||
if( heap_key(heap_elt(j)) > heap_key(heap_elt(j+1)) )
|
|
||||||
j++;
|
|
||||||
|
|
||||||
if( heap_key(heap_elt(j)) >= l_key)
|
|
||||||
break; /* found a position to insert 'last' */
|
|
||||||
|
|
||||||
/* else, sift hole down */
|
|
||||||
heap_elt(k) = heap_elt(j); /* Note that j <= _heap_size */
|
|
||||||
heap_idx( heap_elt(k) ) = k;
|
|
||||||
k = j;
|
|
||||||
j = k << 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
heap_elt( k ) = last;
|
|
||||||
heap_idx( last ) = k;
|
|
||||||
|
|
||||||
heap_idx( min ) = -1; /* mark the point visited */
|
|
||||||
return( min );
|
|
||||||
|
|
||||||
} /* END heap_delete_min() */
|
|
||||||
|
|
||||||
|
|
||||||
/****************************************************************************/
|
|
||||||
|
|
|
@ -1,16 +0,0 @@
|
||||||
#ifndef _DIST_H_
|
|
||||||
#define _DIST_H_
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
|
|
||||||
long dist(
|
|
||||||
Point p,
|
|
||||||
Point q
|
|
||||||
);
|
|
||||||
|
|
||||||
long dist2(
|
|
||||||
Point* p,
|
|
||||||
Point* q
|
|
||||||
);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,180 +0,0 @@
|
||||||
#ifndef DL_H
|
|
||||||
#define DL_H
|
|
||||||
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
typedef struct dl_el_s {
|
|
||||||
struct dl_el_s *prev, *next;
|
|
||||||
} dl_el;
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
dl_el *first, *last;
|
|
||||||
unsigned int count;
|
|
||||||
} dl_s, *dl_t;
|
|
||||||
|
|
||||||
dl_t dl_alloc(void);
|
|
||||||
void dl_delete(dl_t dl, dl_el *el);
|
|
||||||
void dl_clear(dl_t dl);
|
|
||||||
void dl_concat(dl_t list1, dl_t list2);
|
|
||||||
void dl_sort(dl_t dl, size_t el_size, int(*compar)(void *, void *));
|
|
||||||
|
|
||||||
#define dl_length(dl) (dl)->count
|
|
||||||
|
|
||||||
#define dl_empty(dl) ((dl)->count <= 0)
|
|
||||||
|
|
||||||
#define dl_data(type, el) \
|
|
||||||
*(type*)(((dl_el*)(el))+1)
|
|
||||||
|
|
||||||
#define dl_data_p(type, el) \
|
|
||||||
((type*)(((dl_el*)(el))+1))
|
|
||||||
|
|
||||||
#define dl_forall(type, dl, data) \
|
|
||||||
{ \
|
|
||||||
dl_el *_el, *_next; \
|
|
||||||
dl_t _curr_dl = (dl); \
|
|
||||||
for (_el=_curr_dl->first; _el; _el=_next) { \
|
|
||||||
_next = _el->next; \
|
|
||||||
(data) = dl_data(type, _el);
|
|
||||||
|
|
||||||
#define dl_forall_p(type, dl, data_p) \
|
|
||||||
{ \
|
|
||||||
dl_el *_el, *_next; \
|
|
||||||
dl_t _curr_dl = (dl); \
|
|
||||||
for (_el=_curr_dl->first; _el; _el=_next) { \
|
|
||||||
_next = _el->next; \
|
|
||||||
(data_p) = dl_data_p(type, _el);
|
|
||||||
|
|
||||||
#define dl_current() _el
|
|
||||||
#define dl_delete_current() dl_delete(_curr_dl, _el)
|
|
||||||
|
|
||||||
#define dl_endfor \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define dl_forall_reverse(type, dl, data) \
|
|
||||||
{ \
|
|
||||||
dl_el *_el, *_next; \
|
|
||||||
dl_t _curr_dl = (dl); \
|
|
||||||
for (_el=_curr_dl->last; _el; _el=_next) { \
|
|
||||||
_next = _el->prev; \
|
|
||||||
(data) = dl_data(type, _el);
|
|
||||||
|
|
||||||
#define dl_forall_reverse_p(type, dl, data_p) \
|
|
||||||
{ \
|
|
||||||
dl_el *_el, *_next; \
|
|
||||||
dl_t _curr_dl = (dl); \
|
|
||||||
for (_el=_curr_dl->last; _el; _el=_next) { \
|
|
||||||
_next = _el->prev; \
|
|
||||||
(data_p) = dl_data_p(type, _el);
|
|
||||||
|
|
||||||
#define dl_first(type, dl) \
|
|
||||||
dl_data(type, (dl)->first)
|
|
||||||
|
|
||||||
|
|
||||||
#define dl_first_element(dl) (dl)->first
|
|
||||||
|
|
||||||
|
|
||||||
#define dl_last(type, dl) \
|
|
||||||
dl_data(type, (dl)->last)
|
|
||||||
|
|
||||||
#define dl_pop_first(type, dl, data) \
|
|
||||||
{ \
|
|
||||||
(data) = dl_first(type, dl); \
|
|
||||||
dl_delete((dl), (dl)->first); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define dl_pop_last(type, dl, data) \
|
|
||||||
{ (data) = dl_last(type, dl); dl_delete((dl), (dl)->last); }
|
|
||||||
|
|
||||||
#define dl_insert_before(type, dl, element, data) \
|
|
||||||
{ \
|
|
||||||
if ((element) == (dl)->first) { \
|
|
||||||
dl_prepend(type, dl, data); \
|
|
||||||
} else { \
|
|
||||||
dl_el *_el = (dl_el*) malloc(sizeof(dl_el)+sizeof(type)); \
|
|
||||||
if (!_el) { \
|
|
||||||
printf("Out of memory!!\n"); \
|
|
||||||
} else { \
|
|
||||||
memcpy(_el+1, &(data), sizeof(type)); \
|
|
||||||
_el->prev = (element)->prev; _el->next = (element); \
|
|
||||||
(element)->prev->next = _el; (element)->prev = _el; \
|
|
||||||
(dl)->count++; \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define dl_insert_after(type, dl, element, data) \
|
|
||||||
{ \
|
|
||||||
if ((element) == (dl)->last) { \
|
|
||||||
dl_append(type, dl, data); \
|
|
||||||
} else { \
|
|
||||||
dl_el *_el = (dl_el*) malloc(sizeof(dl_el)+sizeof(type)); \
|
|
||||||
if (!_el) { \
|
|
||||||
printf("Out of memory!!\n"); \
|
|
||||||
} else { \
|
|
||||||
memcpy(_el+1, &(data), sizeof(type)); \
|
|
||||||
_el->next = (element)->next; _el->prev = (element); \
|
|
||||||
(element)->next->prev = _el; (element)->next = _el; \
|
|
||||||
(dl)->count++; \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define dl_append(type, dl, data) \
|
|
||||||
{ \
|
|
||||||
dl_el *_el = (dl_el*) malloc(sizeof(dl_el)+sizeof(type)); \
|
|
||||||
if (!_el) { \
|
|
||||||
printf("Out of memory!!\n"); \
|
|
||||||
} else { \
|
|
||||||
memcpy(_el+1, &(data), sizeof(type)); \
|
|
||||||
_el->next = 0; \
|
|
||||||
if ((dl)->count <= 0) { \
|
|
||||||
_el->prev = 0; \
|
|
||||||
(dl)->first = (dl)->last = _el; \
|
|
||||||
(dl)->count = 1; \
|
|
||||||
} else { \
|
|
||||||
_el->prev = (dl)->last; \
|
|
||||||
(dl)->last->next = _el; \
|
|
||||||
(dl)->last = _el; \
|
|
||||||
(dl)->count++; \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define dl_prepend(type, dl, data) \
|
|
||||||
{ \
|
|
||||||
dl_el *_el = (dl_el*) malloc(sizeof(dl_el)+sizeof(type)); \
|
|
||||||
if (!_el) { \
|
|
||||||
printf("Out of memory!!\n"); \
|
|
||||||
} else { \
|
|
||||||
memcpy(_el+1, &(data), sizeof(type)); \
|
|
||||||
_el->prev = 0; \
|
|
||||||
if ((dl)->count <= 0) { \
|
|
||||||
_el->next = 0; \
|
|
||||||
(dl)->first = (dl)->last = _el; \
|
|
||||||
(dl)->count = 1; \
|
|
||||||
} else { \
|
|
||||||
_el->next = (dl)->first; \
|
|
||||||
(dl)->first->prev = _el; \
|
|
||||||
(dl)->first = _el; \
|
|
||||||
(dl)->count++; \
|
|
||||||
} \
|
|
||||||
} \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define dl_free(dl) \
|
|
||||||
{ \
|
|
||||||
dl_clear(dl); free(dl); dl = 0; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#define dl_duplicate(dest, src, type) \
|
|
||||||
{ \
|
|
||||||
dest = dl_alloc(); \
|
|
||||||
type _data_el; \
|
|
||||||
dl_forall(type, src, _data_el) { \
|
|
||||||
dl_append(type, dest, _data_el); \
|
|
||||||
} dl_endfor; \
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,12 +0,0 @@
|
||||||
#ifndef _ERR_H_
|
|
||||||
#define _ERR_H_
|
|
||||||
|
|
||||||
void err_msg(
|
|
||||||
char* msg
|
|
||||||
);
|
|
||||||
|
|
||||||
void err_exit(
|
|
||||||
char* msg
|
|
||||||
);
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,99 +0,0 @@
|
||||||
#ifndef _KNIK_FLUTE_H
|
|
||||||
#define _KNIK_FLUTE_H
|
|
||||||
|
|
||||||
/*****************************/
|
|
||||||
/* User-Defined Parameters */
|
|
||||||
/*****************************/
|
|
||||||
#define MAXD 150 // max. degree that can be handled
|
|
||||||
#define ACCURACY 3 // Default accuracy
|
|
||||||
#define ROUTING 1 // 1 to construct routing, 0 to estimate WL only
|
|
||||||
#define LOCAL_REFINEMENT 0 // Suggestion: Set to 1 if ACCURACY >= 5
|
|
||||||
#define REMOVE_DUPLICATE_PIN 0 // Remove dup. pin for flute_wl() & flute()
|
|
||||||
|
|
||||||
#ifndef DTYPE // Data type for distance
|
|
||||||
#define DTYPE int
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************/
|
|
||||||
/* User-Callable Functions */
|
|
||||||
/*****************************/
|
|
||||||
// void readLUT();
|
|
||||||
// DTYPE flute_wl(int d, DTYPE x[], DTYPE y[], int acc);
|
|
||||||
// DTYPE flutes_wl(int d, DTYPE xs[], DTYPE ys[], int s[], int acc);
|
|
||||||
// FTree flute(int d, DTYPE x[], DTYPE y[], int acc);
|
|
||||||
// FTree flutes(int d, DTYPE xs[], DTYPE ys[], int s[], int acc);
|
|
||||||
// DTYPE wirelength(FTree t);
|
|
||||||
// void printtree(FTree t);
|
|
||||||
// void plottree(FTree t);
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************/
|
|
||||||
/* Internal Parameters and Functions */
|
|
||||||
/*************************************/
|
|
||||||
#define POWVFILE "POWV9.dat" // LUT for POWV (Wirelength Vector)
|
|
||||||
#define POSTFILE "POST9.dat" // LUT for POST (Steiner FTree)
|
|
||||||
#define D 9 // LUT is used for d <= D, D <= 9
|
|
||||||
#define TAU(A) (8+1.3*(A))
|
|
||||||
#define D1(A) (25+120/((A)*(A))) // flute_mr is used for D1 < d <= D2
|
|
||||||
#define D2(A) ((A)<=6 ? 500 : 75+5*(A))
|
|
||||||
|
|
||||||
typedef struct
|
|
||||||
{
|
|
||||||
DTYPE x, y; // starting point of the branch
|
|
||||||
int n; // index of neighbor
|
|
||||||
} Branch;
|
|
||||||
|
|
||||||
struct FTree
|
|
||||||
{
|
|
||||||
int deg; // degree
|
|
||||||
DTYPE length; // total wirelength
|
|
||||||
Branch *branch; // array of tree branches
|
|
||||||
};
|
|
||||||
|
|
||||||
// User-Callable Functions
|
|
||||||
extern void readLUT();
|
|
||||||
extern DTYPE flute_wl(int d, DTYPE x[], DTYPE y[], int acc);
|
|
||||||
//Macro: DTYPE flutes_wl(int d, DTYPE xs[], DTYPE ys[], int s[], int acc);
|
|
||||||
extern FTree flute(int d, DTYPE x[], DTYPE y[], int acc);
|
|
||||||
//Macro: FTree flutes(int d, DTYPE xs[], DTYPE ys[], int s[], int acc);
|
|
||||||
extern DTYPE wirelength(FTree t);
|
|
||||||
extern void printtree(FTree t);
|
|
||||||
extern void plottree(FTree t);
|
|
||||||
|
|
||||||
// Other useful functions
|
|
||||||
extern void init_param();
|
|
||||||
extern DTYPE flutes_wl_LD(int d, DTYPE xs[], DTYPE ys[], int s[]);
|
|
||||||
extern DTYPE flutes_wl_MD(int d, DTYPE xs[], DTYPE ys[], int s[], int acc);
|
|
||||||
extern DTYPE flutes_wl_RDP(int d, DTYPE xs[], DTYPE ys[], int s[], int acc);
|
|
||||||
extern FTree flutes_LD(int d, DTYPE xs[], DTYPE ys[], int s[]);
|
|
||||||
extern FTree flutes_MD(int d, DTYPE xs[], DTYPE ys[], int s[], int acc);
|
|
||||||
extern FTree flutes_HD(int d, DTYPE xs[], DTYPE ys[], int s[], int acc);
|
|
||||||
extern FTree flutes_RDP(int d, DTYPE xs[], DTYPE ys[], int s[], int acc);
|
|
||||||
|
|
||||||
#if REMOVE_DUPLICATE_PIN==1
|
|
||||||
#define flutes_wl(d, xs, ys, s, acc) flutes_wl_RDP(d, xs, ys, s, acc)
|
|
||||||
#define flutes(d, xs, ys, s, acc) flutes_RDP(d, xs, ys, s, acc)
|
|
||||||
#else
|
|
||||||
#define flutes_wl(d, xs, ys, s, acc) flutes_wl_ALLD(d, xs, ys, s, acc)
|
|
||||||
#define flutes(d, xs, ys, s, acc) flutes_ALLD(d, xs, ys, s, acc)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define flutes_wl_ALLD(d, xs, ys, s, acc) flutes_wl_LMD(d, xs, ys, s, acc)
|
|
||||||
#define flutes_ALLD(d, xs, ys, s, acc) \
|
|
||||||
(d<=D ? flutes_LD(d, xs, ys, s) \
|
|
||||||
: (d<=D1(acc) ? flutes_MD(d, xs, ys, s, acc) \
|
|
||||||
: flutes_HD(d, xs, ys, s, acc)))
|
|
||||||
|
|
||||||
#define flutes_wl_LMD(d, xs, ys, s, acc) \
|
|
||||||
(d<=D ? flutes_wl_LD(d, xs, ys, s) : flutes_wl_MD(d, xs, ys, s, acc))
|
|
||||||
#define flutes_LMD(d, xs, ys, s, acc) \
|
|
||||||
(d<=D ? flutes_LD(d, xs, ys, s) : flutes_MD(d, xs, ys, s, acc))
|
|
||||||
|
|
||||||
#define max(x,y) ((x)>(y)?(x):(y))
|
|
||||||
#define min(x,y) ((x)<(y)?(x):(y))
|
|
||||||
#define abs(x) ((x)<0?(-x):(x))
|
|
||||||
#define ADIFF(x,y) ((x)>(y)?(x-y):(y-x)) // Absolute difference
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
#ifndef _GLOBAL_H_
|
|
||||||
#define _GLOBAL_H_
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
|
|
||||||
#define TRUE 1
|
|
||||||
#define FALSE 0
|
|
||||||
#define MAXLONG 0x7fffffffL
|
|
||||||
|
|
||||||
struct point
|
|
||||||
{
|
|
||||||
long x, y;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct point Point;
|
|
||||||
|
|
||||||
typedef long nn_array[8];
|
|
||||||
|
|
||||||
#endif /* _GLOBAL_H_ */
|
|
|
@ -1,31 +0,0 @@
|
||||||
#ifndef _HEAP_H_
|
|
||||||
#define _HEAP_H_
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
|
|
||||||
struct heap_info
|
|
||||||
{
|
|
||||||
long key;
|
|
||||||
long idx;
|
|
||||||
long elt;
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef struct heap_info Heap;
|
|
||||||
|
|
||||||
extern Heap* _heap;
|
|
||||||
|
|
||||||
#define heap_key( p ) ( _heap[p].key )
|
|
||||||
#define heap_idx( p ) ( _heap[p].idx )
|
|
||||||
#define heap_elt( k ) ( _heap[k].elt )
|
|
||||||
|
|
||||||
#define in_heap( p ) ( heap_idx(p) > 0 )
|
|
||||||
#define never_seen( p ) ( heap_idx(p) == 0 )
|
|
||||||
|
|
||||||
void allocate_heap( long n );
|
|
||||||
void deallocate_heap();
|
|
||||||
void heap_init( long n );
|
|
||||||
void heap_insert( long p, long key );
|
|
||||||
void heap_decrease_key( long p, long new_key );
|
|
||||||
long heap_delete_min();
|
|
||||||
|
|
||||||
#endif /* _HEAP_H_ */
|
|
|
@ -1,11 +0,0 @@
|
||||||
#ifndef _MST2_H_
|
|
||||||
#define _MST2_H_
|
|
||||||
|
|
||||||
#include "global.h"
|
|
||||||
|
|
||||||
void mst2_package_init( long n );
|
|
||||||
void mst2_package_done();
|
|
||||||
void mst2( long n, Point* pt, long* parent );
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
@ -1,19 +0,0 @@
|
||||||
#include "global.h"
|
|
||||||
|
|
||||||
void allocate_nn_arrays( long n );
|
|
||||||
void deallocate_nn_arrays();
|
|
||||||
|
|
||||||
void brute_force_nearest_neighbors
|
|
||||||
(
|
|
||||||
long n,
|
|
||||||
Point* pt,
|
|
||||||
nn_array* nn
|
|
||||||
);
|
|
||||||
|
|
||||||
void dq_nearest_neighbors
|
|
||||||
(
|
|
||||||
long n,
|
|
||||||
Point* pt,
|
|
||||||
nn_array* nn
|
|
||||||
);
|
|
||||||
|
|
|
@ -1,92 +0,0 @@
|
||||||
#include <stdlib.h>
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <assert.h>
|
|
||||||
#include "knik/global.h"
|
|
||||||
#include "knik/neighbors.h"
|
|
||||||
#include "knik/dist.h"
|
|
||||||
#include "knik/heap.h"
|
|
||||||
#include "knik/err.h"
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
void mst2_package_init( long n )
|
|
||||||
{
|
|
||||||
allocate_heap( n );
|
|
||||||
allocate_nn_arrays( n );
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************/
|
|
||||||
/*
|
|
||||||
*/
|
|
||||||
|
|
||||||
void mst2_package_done()
|
|
||||||
{
|
|
||||||
deallocate_heap();
|
|
||||||
deallocate_nn_arrays();
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************/
|
|
||||||
/*
|
|
||||||
*/
|
|
||||||
|
|
||||||
void mst2
|
|
||||||
(
|
|
||||||
long n,
|
|
||||||
Point* pt,
|
|
||||||
long* parent
|
|
||||||
)
|
|
||||||
{
|
|
||||||
long i, k, nn1;
|
|
||||||
long d;
|
|
||||||
long oct;
|
|
||||||
long root = 0;
|
|
||||||
extern nn_array* nn;
|
|
||||||
|
|
||||||
// brute_force_nearest_neighbors( n, pt, nn );
|
|
||||||
dq_nearest_neighbors( n, pt, nn );
|
|
||||||
|
|
||||||
/*
|
|
||||||
Binary heap implementation of Prim's algorithm.
|
|
||||||
Runs in O(n*log(n)) time since at most 8n edges are considered
|
|
||||||
*/
|
|
||||||
|
|
||||||
heap_init( n );
|
|
||||||
heap_insert( root, 0 );
|
|
||||||
parent[root] = root;
|
|
||||||
|
|
||||||
for( k = 0; k < n; k++ ) /* n points to be extracted from heap */
|
|
||||||
{
|
|
||||||
i = heap_delete_min();
|
|
||||||
|
|
||||||
if (i<0) break;
|
|
||||||
#ifdef DEBUG
|
|
||||||
assert( i >= 0 );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
pt[i] entered the tree, update heap keys for its neighbors
|
|
||||||
*/
|
|
||||||
for( oct = 0; oct < 8; oct++ )
|
|
||||||
{
|
|
||||||
nn1 = nn[i][oct];
|
|
||||||
if( nn1 >= 0 )
|
|
||||||
{
|
|
||||||
d = dist( pt[i], pt[nn1] );
|
|
||||||
if( in_heap(nn1) && (d < heap_key(nn1)) )
|
|
||||||
{
|
|
||||||
heap_decrease_key( nn1, d );
|
|
||||||
parent[nn1] = i;
|
|
||||||
}
|
|
||||||
else if( never_seen(nn1) )
|
|
||||||
{
|
|
||||||
heap_insert( nn1, d );
|
|
||||||
parent[nn1] = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************************************************************************/
|
|
||||||
/****************************************************************************/
|
|
||||||
|
|
|
@ -1,527 +0,0 @@
|
||||||
#include <assert.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include "knik/global.h"
|
|
||||||
#include "knik/err.h"
|
|
||||||
#include "knik/dist.h"
|
|
||||||
|
|
||||||
long octant
|
|
||||||
(
|
|
||||||
Point from,
|
|
||||||
Point to
|
|
||||||
);
|
|
||||||
|
|
||||||
static Point* _pt;
|
|
||||||
|
|
||||||
/***************************************************************************/
|
|
||||||
/*
|
|
||||||
For efficiency purposes auxiliary arrays are allocated as globals
|
|
||||||
*/
|
|
||||||
|
|
||||||
long max_arrays_size = 0;
|
|
||||||
nn_array* nn = (nn_array*)NULL;
|
|
||||||
Point* sheared = (Point*)NULL;
|
|
||||||
long* sorted = (long*)NULL;
|
|
||||||
long* aux = (long*)NULL;
|
|
||||||
|
|
||||||
/***************************************************************************/
|
|
||||||
/*
|
|
||||||
resize the auxiliary arrays to fit the specified number of points
|
|
||||||
*/
|
|
||||||
|
|
||||||
void allocate_nn_arrays( long n )
|
|
||||||
{
|
|
||||||
if( max_arrays_size < n )
|
|
||||||
{
|
|
||||||
nn = (nn_array*)realloc( (void*)nn, (size_t)n*sizeof(nn_array) );
|
|
||||||
sheared = (Point*)realloc( (void*)sheared, (size_t)n*sizeof(Point) );
|
|
||||||
sorted = (long*)realloc( (void*)sorted, (size_t)n*sizeof(long) );
|
|
||||||
aux = (long*)realloc( (void*)aux, (size_t)n*sizeof(long) );
|
|
||||||
if( !nn || !sheared || !sorted || !aux )
|
|
||||||
{
|
|
||||||
err_exit( (char*)"Cannot allocate memory in allocate_nn_arrays!" );
|
|
||||||
}
|
|
||||||
max_arrays_size = n;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************/
|
|
||||||
/*
|
|
||||||
free memory used by auxiliary arrays
|
|
||||||
*/
|
|
||||||
|
|
||||||
void deallocate_nn_arrays()
|
|
||||||
{
|
|
||||||
max_arrays_size = 0;
|
|
||||||
if( nn )
|
|
||||||
{
|
|
||||||
free( (void*)nn );
|
|
||||||
nn = (nn_array*)NULL;
|
|
||||||
}
|
|
||||||
if( sheared )
|
|
||||||
{
|
|
||||||
free( (void*)sheared );
|
|
||||||
sheared = (Point*)NULL;
|
|
||||||
}
|
|
||||||
if( sorted )
|
|
||||||
{
|
|
||||||
free( (void*)sorted );
|
|
||||||
sorted = (long*)NULL;
|
|
||||||
}
|
|
||||||
if( aux )
|
|
||||||
{
|
|
||||||
free( (void*)aux );
|
|
||||||
aux = (long*)NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************/
|
|
||||||
/*
|
|
||||||
comparison function for use in quicksort
|
|
||||||
*/
|
|
||||||
|
|
||||||
static int compare_x
|
|
||||||
(
|
|
||||||
const void* i,
|
|
||||||
const void* j
|
|
||||||
)
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
points with the same x must appear in increasing order of y
|
|
||||||
*/
|
|
||||||
if( sheared[*((long*)i)].x == sheared[*((long*)j)].x)
|
|
||||||
{
|
|
||||||
return sheared[*((long*)i)].y - sheared[*((long*)j)].y;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return sheared[*((long*)i)].x - sheared[*((long*)j)].x;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************/
|
|
||||||
/*
|
|
||||||
Combine step of the Guibas-Stolfi divide-and-conquer NE nearest neighbor
|
|
||||||
algorithm. For efficiency purposes SW nearest neighbors are computed
|
|
||||||
at the same time.
|
|
||||||
*/
|
|
||||||
|
|
||||||
void ne_sw_combine
|
|
||||||
(
|
|
||||||
long left,
|
|
||||||
long mid,
|
|
||||||
long right,
|
|
||||||
Point* pt,
|
|
||||||
long* sorted,
|
|
||||||
long* aux,
|
|
||||||
long oct,
|
|
||||||
nn_array* nn
|
|
||||||
)
|
|
||||||
{
|
|
||||||
long i, j, k, y2;
|
|
||||||
long i1;
|
|
||||||
long i2;
|
|
||||||
long best_i2; /* index of current best nearest-neighbor */
|
|
||||||
long best_dist; /* distance to best nearest-neighbor */
|
|
||||||
long d;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
assert( right > mid );
|
|
||||||
assert( mid > left );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/*
|
|
||||||
update north-east nearest neighbors accross the mid-line
|
|
||||||
*/
|
|
||||||
|
|
||||||
i1 = left;
|
|
||||||
i2 = mid; y2 = pt[ sorted[i2] ].y;
|
|
||||||
|
|
||||||
while( (i1 < mid) && (pt[ sorted[i1] ].y >= y2) )
|
|
||||||
{
|
|
||||||
i1++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( i1 < mid )
|
|
||||||
{
|
|
||||||
best_i2 = i2;
|
|
||||||
best_dist = dist2( pt + sorted[i1], pt + sorted[best_i2] );
|
|
||||||
i2++;
|
|
||||||
|
|
||||||
while( (i1 < mid) && (i2 < right) )
|
|
||||||
{
|
|
||||||
if( pt[ sorted[i1] ].y < pt[ sorted[i2] ].y )
|
|
||||||
{
|
|
||||||
d = dist2( pt + sorted[i1], pt + sorted[i2] );
|
|
||||||
if( d < best_dist )
|
|
||||||
{
|
|
||||||
best_i2 = i2;
|
|
||||||
best_dist = d;
|
|
||||||
}
|
|
||||||
i2++;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if( (nn[ sorted[i1] ][oct] == -1) ||
|
|
||||||
( best_dist < dist2( pt + sorted[i1], pt + nn[ sorted[i1] ][oct]) )
|
|
||||||
)
|
|
||||||
{
|
|
||||||
nn[ sorted[i1] ][oct] = sorted[best_i2];
|
|
||||||
}
|
|
||||||
i1++;
|
|
||||||
if( i1 < mid )
|
|
||||||
{
|
|
||||||
best_dist = dist2( pt + sorted[i1], pt + sorted[best_i2] );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while( i1 < mid )
|
|
||||||
{
|
|
||||||
if( (nn[ sorted[i1] ][oct] == -1) ||
|
|
||||||
( dist2( pt + sorted[i1], pt + sorted[best_i2] ) <
|
|
||||||
dist2( pt + sorted[i1], pt + nn[ sorted[i1] ][oct]) )
|
|
||||||
)
|
|
||||||
{
|
|
||||||
nn[ sorted[i1] ][oct] = sorted[best_i2];
|
|
||||||
}
|
|
||||||
i1++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
repeat for south-west nearest neighbors
|
|
||||||
*/
|
|
||||||
|
|
||||||
oct = (oct + 4) % 8;
|
|
||||||
|
|
||||||
i1 = right - 1;
|
|
||||||
i2 = mid - 1; y2 = pt[ sorted[i2] ].y;
|
|
||||||
|
|
||||||
while( (i1 >= mid) && (pt[ sorted[i1] ].y <= y2) )
|
|
||||||
{
|
|
||||||
i1--;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( i1 >= mid )
|
|
||||||
{
|
|
||||||
best_i2 = i2;
|
|
||||||
best_dist = dist2( pt + sorted[i1], pt + sorted[best_i2] );
|
|
||||||
i2--;
|
|
||||||
|
|
||||||
while( (i1 >= mid) && (i2 >= left) )
|
|
||||||
{
|
|
||||||
if( pt[ sorted[i1] ].y > pt[ sorted[i2] ].y )
|
|
||||||
{
|
|
||||||
d = dist2( pt + sorted[i1], pt + sorted[i2] );
|
|
||||||
if( d < best_dist )
|
|
||||||
{
|
|
||||||
best_i2 = i2;
|
|
||||||
best_dist = d;
|
|
||||||
}
|
|
||||||
i2--;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if( (nn[ sorted[i1] ][oct] == -1) ||
|
|
||||||
( best_dist < dist2( pt + sorted[i1], pt + nn[ sorted[i1] ][oct]) )
|
|
||||||
)
|
|
||||||
{
|
|
||||||
nn[ sorted[i1] ][oct] = sorted[best_i2];
|
|
||||||
}
|
|
||||||
i1--;
|
|
||||||
if( i1 >= mid )
|
|
||||||
{
|
|
||||||
best_dist = dist2( pt + sorted[i1], pt + sorted[best_i2] );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
while( i1 >= mid )
|
|
||||||
{
|
|
||||||
if( (nn[ sorted[i1] ][oct] == -1) ||
|
|
||||||
( dist2( pt + sorted[i1], pt + sorted[best_i2] ) <
|
|
||||||
dist2( pt + sorted[i1], pt + nn[ sorted[i1] ][oct]) )
|
|
||||||
)
|
|
||||||
{
|
|
||||||
nn[ sorted[i1] ][oct] = sorted[best_i2];
|
|
||||||
}
|
|
||||||
i1--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
merge sorted[left..mid-1] with sorted[mid..right-1] by y-coordinate
|
|
||||||
*/
|
|
||||||
|
|
||||||
i = left; /* first unprocessed element in left list */
|
|
||||||
j = mid; /* first unprocessed element in right list */
|
|
||||||
k = left; /* first free available slot in output list */
|
|
||||||
|
|
||||||
while( (i < mid) && (j < right) )
|
|
||||||
{
|
|
||||||
if( pt[ sorted[i] ].y >= pt[ sorted[j] ].y )
|
|
||||||
{
|
|
||||||
aux[k++] = sorted[i++];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
aux[k++] = sorted[j++];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
copy leftovers
|
|
||||||
*/
|
|
||||||
while( i < mid ) { aux[k++] = sorted[i++]; }
|
|
||||||
while( j < right ) { aux[k++] = sorted[j++]; }
|
|
||||||
|
|
||||||
/*
|
|
||||||
now copy sorted points from 'aux' to 'sorted'
|
|
||||||
*/
|
|
||||||
|
|
||||||
for( i = left; i < right; i++ ) { sorted[i] = aux[i]; }
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
memcpy( (void*)(sorted+left), /* destination */
|
|
||||||
(void*)(aux+left), /* source */
|
|
||||||
(size_t)(right-left)*sizeof(long) /* number of bytes */
|
|
||||||
);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************/
|
|
||||||
/*
|
|
||||||
compute north-east and south-west nearest neighbors for points indexed
|
|
||||||
by {sorted[left],...,sorted[right-1]}
|
|
||||||
*/
|
|
||||||
|
|
||||||
void ne_sw_nearest_neighbors
|
|
||||||
(
|
|
||||||
long left,
|
|
||||||
long right,
|
|
||||||
Point* pt,
|
|
||||||
long* sorted,
|
|
||||||
long* aux,
|
|
||||||
long oct,
|
|
||||||
nn_array* nn
|
|
||||||
)
|
|
||||||
{
|
|
||||||
long mid;
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
assert( right > left );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if( right == left + 1 )
|
|
||||||
{
|
|
||||||
nn[ sorted[left] ][oct] = nn[ sorted[left]][(oct+4) % 8] = -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mid = (left + right) / 2;
|
|
||||||
ne_sw_nearest_neighbors( left, mid, pt, sorted, aux, oct, nn );
|
|
||||||
ne_sw_nearest_neighbors( mid, right, pt, sorted, aux, oct, nn );
|
|
||||||
ne_sw_combine( left, mid, right, pt, sorted, aux, oct, nn );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************/
|
|
||||||
/*
|
|
||||||
Guibas-Stolfi algorithm for computing nearest NE neighbors
|
|
||||||
*/
|
|
||||||
|
|
||||||
void dq_nearest_neighbors
|
|
||||||
(
|
|
||||||
long n,
|
|
||||||
Point* pt,
|
|
||||||
nn_array* nn
|
|
||||||
)
|
|
||||||
{
|
|
||||||
long i, oct;
|
|
||||||
void check_nn( long, Point*, nn_array* );
|
|
||||||
|
|
||||||
long shear[4][4] = {
|
|
||||||
{1, -1, 0, 2},
|
|
||||||
{2, 0, -1, 1},
|
|
||||||
{1, 1, -2, 0},
|
|
||||||
{0, 2, -1, -1}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
_pt = pt;
|
|
||||||
|
|
||||||
for( oct = 0; oct < 4; oct++ )
|
|
||||||
{
|
|
||||||
for( i = 0; i < n; i++ )
|
|
||||||
{
|
|
||||||
sheared[i].x = shear[oct][0]*pt[i].x + shear[oct][1]*pt[i].y;
|
|
||||||
sheared[i].y = shear[oct][2]*pt[i].x + shear[oct][3]*pt[i].y;
|
|
||||||
sorted[i] = i;
|
|
||||||
}
|
|
||||||
|
|
||||||
qsort( sorted, n, sizeof(long), compare_x );
|
|
||||||
ne_sw_nearest_neighbors( 0, n, sheared, sorted, aux, oct, nn );
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef DEBUG
|
|
||||||
check_nn( n, pt, nn );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************/
|
|
||||||
/***************************************************************************/
|
|
||||||
/*
|
|
||||||
Brute-force nearest-neighbor computation for debugging purposes
|
|
||||||
*/
|
|
||||||
|
|
||||||
/***************************************************************************/
|
|
||||||
/*
|
|
||||||
Half-open octants are numbered from 0 to 7 in anti-clockwise order
|
|
||||||
starting from ( dx >= dy > 0 ).
|
|
||||||
*/
|
|
||||||
|
|
||||||
#define sgn(x) ( x>0 ? 1 : (x < 0 ? -1 : 0) )
|
|
||||||
|
|
||||||
long octant
|
|
||||||
(
|
|
||||||
Point from,
|
|
||||||
Point to
|
|
||||||
)
|
|
||||||
{
|
|
||||||
long dx = to.x - from.x;
|
|
||||||
long dy = to.y - from.y;
|
|
||||||
long sgn1 = sgn(dx)*sgn(dy);
|
|
||||||
long sgn2 = sgn(dx+dy)*sgn(dx-dy);
|
|
||||||
long oct = 0x0;
|
|
||||||
|
|
||||||
|
|
||||||
if( (dy < 0) || ((dy==0) && (dx>0)) ) oct += 4;
|
|
||||||
if( (sgn1 < 0) || (dy==0) ) oct += 2;
|
|
||||||
if( (sgn1*sgn2 < 0) || (dy==0) || (dx==0) ) oct += 1;
|
|
||||||
|
|
||||||
return oct;
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************/
|
|
||||||
/*
|
|
||||||
O(n^2) algorithm for computing all nearest neighbors
|
|
||||||
*/
|
|
||||||
|
|
||||||
void brute_force_nearest_neighbors
|
|
||||||
(
|
|
||||||
long n,
|
|
||||||
Point* pt,
|
|
||||||
nn_array* nn
|
|
||||||
)
|
|
||||||
{
|
|
||||||
long i, j, oct;
|
|
||||||
long d;
|
|
||||||
|
|
||||||
/*
|
|
||||||
compute nearest neighbors by inspecting all pairs of points
|
|
||||||
*/
|
|
||||||
for( i = 0; i < n; i++ )
|
|
||||||
{
|
|
||||||
for( oct = 0; oct < 8; oct++ )
|
|
||||||
{
|
|
||||||
nn[i][oct] = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for( i = 0; i < n; i++ )
|
|
||||||
{
|
|
||||||
for( j = i+1; j < n; j++ )
|
|
||||||
{
|
|
||||||
d = dist(pt[i], pt[j]);
|
|
||||||
|
|
||||||
oct = octant( pt[i], pt[j] );
|
|
||||||
if( ( nn[i][oct] == -1 ) ||
|
|
||||||
( d < dist(pt[i], pt[ nn[i][oct] ]) )
|
|
||||||
)
|
|
||||||
{
|
|
||||||
nn[i][oct] = j;
|
|
||||||
}
|
|
||||||
|
|
||||||
oct = (oct + 4) % 8;
|
|
||||||
if( ( nn[j][oct] == -1 ) ||
|
|
||||||
( d < dist(pt[j], pt[ nn[j][oct] ]) )
|
|
||||||
)
|
|
||||||
{
|
|
||||||
nn[j][oct] = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************/
|
|
||||||
/*
|
|
||||||
compare nearest neighbors against those computed by brute force
|
|
||||||
*/
|
|
||||||
|
|
||||||
void check_nn
|
|
||||||
(
|
|
||||||
long n,
|
|
||||||
Point* pt,
|
|
||||||
nn_array* nn
|
|
||||||
)
|
|
||||||
{
|
|
||||||
long i, j, oct;
|
|
||||||
nn_array* nn1;
|
|
||||||
|
|
||||||
nn1 = (nn_array*)calloc( (size_t)n, (size_t)sizeof(nn_array) );
|
|
||||||
brute_force_nearest_neighbors( n, pt, nn1 );
|
|
||||||
|
|
||||||
for( i = 0; i < n; i++ )
|
|
||||||
{
|
|
||||||
for( oct = 0; oct < 8; oct++ )
|
|
||||||
{
|
|
||||||
if( nn[i][oct] == -1 )
|
|
||||||
{
|
|
||||||
assert( nn1[i][oct] == -1 );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
assert( nn1[i][oct] != -1 );
|
|
||||||
|
|
||||||
if( octant(pt[i], pt[ nn[i][oct] ]) != oct )
|
|
||||||
{
|
|
||||||
printf( "WRONG OCTANT!\noct=%ld\n", oct );
|
|
||||||
printf( "i=%ld, x=%ld, y=%ld\n", i, pt[i].x, pt[i].y );
|
|
||||||
j = nn[i][oct];
|
|
||||||
printf( "nn=%ld, x=%ld, y=%ld, dist = %ld\n", j, pt[j].x, pt[j].y,
|
|
||||||
dist(pt[i], pt[j ]) );
|
|
||||||
}
|
|
||||||
// assert( octant(pt[i], pt[ nn[i][oct] ]) == oct );
|
|
||||||
|
|
||||||
assert( octant(pt[i], pt[ nn1[i][oct] ]) == oct );
|
|
||||||
|
|
||||||
if( dist(pt[i], pt[ nn[i][oct] ]) !=
|
|
||||||
dist(pt[i], pt[ nn1[i][oct] ]) )
|
|
||||||
{
|
|
||||||
printf( "NNs DON'T MATCH!\noct=%ld\n", oct );
|
|
||||||
printf( "i=%ld, x=%ld, y=%ld\n", i, pt[i].x, pt[i].y );
|
|
||||||
j = nn[i][oct];
|
|
||||||
printf( "nn=%ld, x=%ld, y=%ld, dist = %ld\n", j, pt[j].x, pt[j].y,
|
|
||||||
dist(pt[i], pt[j ]) );
|
|
||||||
j = nn1[i][oct];
|
|
||||||
printf( "nn1=%ld, x=%ld, y=%ld, dist = %ld\n", j, pt[j].x, pt[j].y,
|
|
||||||
dist(pt[i], pt[ j ]) );
|
|
||||||
}
|
|
||||||
// assert( dist(pt[i], pt[ nn[i][oct] ]) ==
|
|
||||||
// dist(pt[i], pt[ nn1[i][oct] ]) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
free( nn1 );
|
|
||||||
}
|
|
||||||
|
|
||||||
/***************************************************************************/
|
|
||||||
/***************************************************************************/
|
|
||||||
|
|
Loading…
Reference in New Issue