From 6f0bc2ecb0fbcd0cb29142a1d85a3905b5e2600c Mon Sep 17 00:00:00 2001 From: Gabriel Gouvine Date: Sat, 18 Apr 2015 15:50:40 +0200 Subject: [PATCH 1/7] Split the placement routine * Separate global and detailed placement * Options provided by the main routine --- etesian/src/EtesianEngine.cpp | 385 +++++++++++++++------------- etesian/src/etesian/EtesianEngine.h | 7 +- 2 files changed, 215 insertions(+), 177 deletions(-) diff --git a/etesian/src/EtesianEngine.cpp b/etesian/src/EtesianEngine.cpp index 002a6d52..12bc0d32 100644 --- a/etesian/src/EtesianEngine.cpp +++ b/etesian/src/EtesianEngine.cpp @@ -54,9 +54,17 @@ namespace { using coloquinte::float_t; using coloquinte::point; + // Options for both placers + unsigned const SteinerModel = 0x0001; + // Options for the global placer + unsigned const ForceUniformDensity = 0x0010; + unsigned const UpdateLB = 0x0020; + unsigned const UpdateUB = 0x0040; - //inline bool isNan( const float_t& f ) { return (f != f); } + // Options for the detailed placer + unsigned const UpdateDetailed = 0x0100; + unsigned const NonConvexOpt = 0x0200; string extractInstanceName ( const RoutingPad* rp ) @@ -574,11 +582,176 @@ namespace Etesian { } - void EtesianEngine::place () - { + void EtesianEngine::preplace (){ + using namespace coloquinte::gp; + // Perform a very quick legalization pass + cmess2 << " o Simple legalization." << endl; + auto first_legalizer = region_distribution::uniform_density_distribution(_surface, _circuit, _placementLB); + first_legalizer.selfcheck(); + get_rough_legalization( _circuit, _placementUB, first_legalizer); + + _placementLB = _placementUB; + + // Early topology-independent solution with a star model + negligible pulling forces to avoid dumb solutions + // Spreads well to help subsequent optimization passes + cmess2 << " o Star (*) Optimization." << endl; + auto solv = get_star_linear_system( _circuit, _placementLB, 1.0, 0, 10) // Limit the number of pins: don't want big awful nets with high weight + + get_pulling_forces( _circuit, _placementUB, 1000000.0); + solve_linear_system( _circuit, _placementLB, solv, 200 ); + _progressReport2(" [--]" ); + } + + + void EtesianEngine::globalPlace ( float initPenalty, float minDisruption, float targetImprovement, float minInc, float maxInc, unsigned options ){ + using namespace coloquinte::gp; + + float_t penaltyIncrease = minInc; + float_t linearDisruption = get_mean_linear_disruption(_circuit, _placementLB, _placementUB); + float_t pullingForce = initPenalty; + float_t upperWL = static_cast(get_HPWL_wirelength(_circuit, _placementUB)), + lowerWL = static_cast(get_HPWL_wirelength(_circuit, _placementLB)); + float_t prevOptRatio = lowerWL / upperWL; + + index_t i=0; + do{ + // Create a legalizer and bipartition it until we have sufficient precision + auto legalizer = (options & ForceUniformDensity) != 0 ? + region_distribution::uniform_density_distribution(_surface, _circuit, _placementLB) + : region_distribution::full_density_distribution(_surface, _circuit, _placementLB); + // Until there is about 10 standard cells per region + for ( int quad_part=0 ; _circuit.cell_cnt() > (index_t)(10 * (1 << (quad_part*2))) ; ++quad_part ) { + legalizer.x_bipartition(); + legalizer.y_bipartition(); + legalizer.redo_line_partitions(); + legalizer.redo_diagonal_bipartitions(); + legalizer.redo_line_partitions(); + legalizer.redo_diagonal_bipartitions(); + legalizer.selfcheck(); + } + // Keep the orientation between LB and UB + _placementUB = _placementLB; + // Update UB + get_rough_legalization( _circuit, _placementUB, legalizer ); + + if(options & UpdateUB) + _updatePlacement( _placementUB ); + + ostringstream label; + label.str(""); + label << " [" << setw(2) << setfill('0') << i << "] Bipart."; + _progressReport1(label.str() ); + + upperWL = static_cast(get_HPWL_wirelength(_circuit, _placementUB)); + float_t legRatio = lowerWL / upperWL; + + // Get the system to optimize (tolerance, maximum and minimum pin counts) + // and the pulling forces (threshold distance) + auto opt_problem = (options & SteinerModel) ? + get_RSMT_linear_system ( _circuit, _placementLB, minDisruption, 2, 100000 ) + : get_HPWLF_linear_system ( _circuit, _placementLB, minDisruption, 2, 100000 ); + auto solv = opt_problem + + get_linear_pulling_forces( _circuit, _placementUB, _placementLB, pullingForce, 2.0f * linearDisruption); + solve_linear_system( _circuit, _placementLB, solv, 200 ); // 200 iterations + _progressReport2(" Linear." ); + + if(options & UpdateLB) + _updatePlacement( _placementLB ); + + // First way to exit the loop: the legalization is close enough to the previous result + linearDisruption = get_mean_linear_disruption(_circuit, _placementLB, _placementUB); + if(linearDisruption <= minDisruption) + break; + + // Optimize orientation sometimes + if (i%5 == 0) { + optimize_exact_orientations( _circuit, _placementLB ); + _progressReport2(" Orient." ); + } + + lowerWL = static_cast(get_HPWL_wirelength(_circuit, _placementLB)); + float_t optRatio = lowerWL / upperWL; + + /* + * Schedule the penalty during global placement to achieve uniform improvement + * + * Currently, the metric considered is the ratio optimized HPWL/legalized HPWL + * Other ones, like the disruption itself, may be considered + */ + penaltyIncrease = std::min(maxInc, std::max(minInc, + penaltyIncrease * std::sqrt( targetImprovement / (optRatio - prevOptRatio) ) + ) ); + cparanoid << " L/U ratio: " << 100*optRatio << "% (previous: " << 100*prevOptRatio << "%)\n" + << " Pulling force: " << pullingForce << " Increase: " << penaltyIncrease << endl; + + pullingForce += penaltyIncrease; + prevOptRatio = optRatio; + + ++i; + // Second way to exit the loop: UB and LB difference is <10% + }while(prevOptRatio <= 0.9); + _updatePlacement( _placementUB ); + } + + void EtesianEngine::detailedPlace ( int iterations, int effort, unsigned options ){ using namespace coloquinte::gp; using namespace coloquinte::dp; + int_t sliceHeight = getSliceHeight() / getPitch(); + + for ( int i=0; iprint( getCell() ); if (getCell()->getAbutmentBox().isEmpty()) setDefaultAb(); @@ -589,203 +762,65 @@ namespace Etesian { GraphicUpdate placementUpdate = getUpdateConf(); Density densityConf = getSpreadingConf(); + startMeasures(); + double sliceHeight = getSliceHeight() / getPitch(); + cmess1 << " o Running Coloquinte." << endl; - cmess1 << " o Global placement." << endl; cmess2 << " - Computing initial placement..." << endl; cmess2 << setfill('0') << right; + preplace(); - double sliceHeight = getSliceHeight() / getPitch(); - time_t startTime = time(NULL); - time_t timeDelta; - ostringstream label; - - cmess2 << " o Initial wirelength " << get_HPWL_wirelength(_circuit, _placementLB) << "." << endl; - startMeasures(); - - cmess2 << " o Simple legalization." << endl; - auto first_legalizer = region_distribution::uniform_density_distribution(_surface, _circuit, _placementLB); - first_legalizer.selfcheck(); - get_rough_legalization( _circuit, _placementUB, first_legalizer); - - timeDelta = time(NULL) - startTime; - cmess2 << " - Elapsed time:" << timeDelta - << " HPWL:" << get_HPWL_wirelength( _circuit, _placementUB ) - << "\n " - << "- Linear Disrupt.:" << get_mean_linear_disruption ( _circuit, _placementLB, _placementUB ) - << " Quad. Disrupt.:" << get_mean_quadratic_disruption( _circuit, _placementLB, _placementUB ) - << endl; - _placementLB = _placementUB; - _placementLB.selfcheck(); - - if(placementUpdate == UpdateAll) - _updatePlacement( _placementUB ); - - // Early topology-independent solution + negligible pulling forces to avoid dumb solutions - cmess2 << " o Star (*) Optimization." << endl; - auto solv = get_star_linear_system( _circuit, _placementLB, 1.0, 0, 10000) - + get_pulling_forces( _circuit, _placementUB, 1000000.0); - solve_linear_system( _circuit, _placementLB, solv, 200 ); - _progressReport2( startTime, " [--]" ); - - if(placementUpdate <= LowerBound) - _updatePlacement( _placementLB ); - - cmess2 << " o Simple legalization." << endl; - auto snd_legalizer = region_distribution::uniform_density_distribution(_surface, _circuit, _placementLB); - get_rough_legalization( _circuit, _placementUB, snd_legalizer); - - if(placementUpdate == UpdateAll) - _updatePlacement( _placementUB ); - - /* - * Schedule the penalty during global placement to achieve uniform improvement - * - * Currently, the metric considered is the ratio legalized HPWL/optimized HPWL - * Other ones, like the disruption itself, may be considered - */ float_t minPenaltyIncrease, maxPenaltyIncrease, targetImprovement; + int detailedIterations, detailedEffort; + unsigned globalOptions=0, detailedOptions=0; + + if(placementUpdate == UpdateAll){ + globalOptions |= (UpdateUB | UpdateLB); + detailedOptions |= UpdateDetailed; + } + else if(placementUpdate == LowerBound){ + globalOptions |= UpdateLB; + } + + if(densityConf == ForceUniform) + globalOptions |= ForceUniformDensity; if(placementEffort == Fast){ minPenaltyIncrease = 0.005f; maxPenaltyIncrease = 0.08f; targetImprovement = 0.05f; // 5/100 per iteration + detailedIterations = 1; + detailedEffort = 0; } else if(placementEffort == Standard){ minPenaltyIncrease = 0.001f; maxPenaltyIncrease = 0.04f; targetImprovement = 0.02f; // 2/100 per iteration + detailedIterations = 2; + detailedEffort = 1; } else if(placementEffort == High){ minPenaltyIncrease = 0.0005f; maxPenaltyIncrease = 0.02f; targetImprovement = 0.01f; // 1/100 per iteration + detailedIterations = 4; + detailedEffort = 2; } else{ minPenaltyIncrease = 0.0002f; maxPenaltyIncrease = 0.01f; targetImprovement = 0.005f; // 5/1000 per iteration + detailedIterations = 7; + detailedEffort = 3; } - float_t pullingForce = minPenaltyIncrease; - float_t penaltyIncrease = minPenaltyIncrease; - - float_t linearDisruption = get_mean_linear_disruption(_circuit, _placementLB, _placementUB); - float_t currentDisruption = static_cast(get_HPWL_wirelength( _circuit, _placementLB )) / static_cast(get_HPWL_wirelength( _circuit, _placementUB )); - - index_t i=0; - do{ - - // Get the system to optimize (tolerance, maximum and minimum pin counts) - // and the pulling forces (threshold distance) - auto solv = get_HPWLF_linear_system ( _circuit, _placementLB, 0.5 * sliceHeight, 2, 100000 ) - + get_linear_pulling_forces( _circuit, _placementUB, _placementLB, pullingForce, 2.0f * linearDisruption); - solve_linear_system( _circuit, _placementLB, solv, 400 ); // number of iterations - _progressReport2( startTime, " Linear." ); - - // Optimize orientation sometimes - if (i%5 == 0) { - optimize_exact_orientations( _circuit, _placementLB ); - _progressReport2( startTime, " Orient." ); - } - if(placementUpdate <= LowerBound) - _updatePlacement( _placementLB ); - - // Create a legalizer and bipartition it until we have sufficient precision - auto legalizer = densityConf == ForceUniform ? - region_distribution::uniform_density_distribution(_surface, _circuit, _placementLB) - : region_distribution::full_density_distribution(_surface, _circuit, _placementLB); - // Until there is about 10 standard cells per region - for ( int quad_part=0 ; _circuit.cell_cnt() > (index_t)(10 * (1 << (quad_part*2))) ; ++quad_part ) { - legalizer.x_bipartition(); - legalizer.y_bipartition(); - legalizer.redo_line_partitions(); - legalizer.redo_diagonal_bipartitions(); - legalizer.redo_line_partitions(); - legalizer.redo_diagonal_bipartitions(); - legalizer.selfcheck(); - } - // Keep the orientation between LB and UB - _placementUB = _placementLB; - - get_rough_legalization( _circuit, _placementUB, legalizer ); - label.str(""); - label << " [" << setw(2) << setfill('0') << i << "] Bipart."; - _progressReport1( startTime, label.str() ); - - if(placementUpdate == UpdateAll) - _updatePlacement( _placementUB ); - - float_t newDisruption = static_cast(get_HPWL_wirelength( _circuit, _placementLB )) / static_cast(get_HPWL_wirelength( _circuit, _placementUB )); - - penaltyIncrease = std::min(maxPenaltyIncrease, std::max(minPenaltyIncrease, - penaltyIncrease * std::sqrt( targetImprovement / (newDisruption - currentDisruption) ) - ) ); - currentDisruption = newDisruption; - linearDisruption = get_mean_linear_disruption(_circuit, _placementLB, _placementUB); - cparanoid << " Pulling force: " << pullingForce << " Increase: " << penaltyIncrease << endl; - - pullingForce += penaltyIncrease; - ++i; - }while(linearDisruption >= 0.5 * sliceHeight and currentDisruption <= 0.9); + cmess1 << " o Global placement." << endl; + globalPlace(minPenaltyIncrease, sliceHeight, targetImprovement, minPenaltyIncrease, maxPenaltyIncrease, globalOptions); cmess1 << " o Detailed Placement." << endl; - index_t detailedIterations; - if(placementEffort == Fast) - detailedIterations = 1; - else if(placementEffort == Standard) - detailedIterations = 3; - else if(placementEffort == High) - detailedIterations = 5; - else - detailedIterations = 8; - for ( index_t i=0; i Date: Sun, 19 Apr 2015 20:11:43 +0200 Subject: [PATCH 2/7] Initial draft for routing-driven placement * Uses density restrictions rather than cell inflation * Will fail brutally if the congestion is too high; does not attempt to balance the densities --- bootstrap/build.conf | 2 +- .../src/coloquinte/rough_legalizers.hxx | 12 +++-- coloquinte/src/rough_legalizers.cxx | 1 + etesian/CMakeLists.txt | 1 + etesian/src/EtesianEngine.cpp | 46 ++++++++++++++++- etesian/src/etesian/EtesianEngine.h | 9 ++++ katabatic/src/GCell.cpp | 51 +++++++++++-------- katabatic/src/katabatic/GCell.h | 2 + 8 files changed, 94 insertions(+), 30 deletions(-) diff --git a/bootstrap/build.conf b/bootstrap/build.conf index 61acbdd1..2b97f90c 100644 --- a/bootstrap/build.conf +++ b/bootstrap/build.conf @@ -14,10 +14,10 @@ projects = [ #, "nimbus" #, "metis" #, "mauka" + , "katabatic" , "coloquinte" , "etesian" , "knik" - , "katabatic" , "kite" , "equinox" , "solstice" diff --git a/coloquinte/src/coloquinte/rough_legalizers.hxx b/coloquinte/src/coloquinte/rough_legalizers.hxx index 67128513..ce524932 100644 --- a/coloquinte/src/coloquinte/rough_legalizers.hxx +++ b/coloquinte/src/coloquinte/rough_legalizers.hxx @@ -18,6 +18,13 @@ */ namespace coloquinte{ + +struct density_limit{ + box box_; + float_t density_; // from 0.0 for a macro to 1.0 if it does nothing +}; +typedef std::vector density_restrictions; + namespace gp{ class region_distribution{ @@ -38,11 +45,6 @@ class region_distribution{ // Specifies a maximum density of movable cells per usable area // Representing either a macroblock or a routing congestion - struct density_limit{ - box box_; - float_t density_; // from 0.0 for a macro to 1.0 if it does nothing - }; - private: struct region; diff --git a/coloquinte/src/rough_legalizers.cxx b/coloquinte/src/rough_legalizers.cxx index bc5f8aa7..ff6e33da 100644 --- a/coloquinte/src/rough_legalizers.cxx +++ b/coloquinte/src/rough_legalizers.cxx @@ -117,6 +117,7 @@ std::vector region_distribution::prepare_regions(in // The regions' capacities std::vector region_caps(x_cnt * y_cnt, 0); + // Find the limits of the regions std::vector x_reg_lims(x_cnt+1), y_reg_lims(y_cnt+1); for(index_t i=0; i<=x_cnt; ++i){ x_reg_lims[i] = placement_area_.x_min_ + ( ((std::int64_t) (placement_area_.x_max_ - placement_area_.x_min_)) * i ) / x_cnt; diff --git a/etesian/CMakeLists.txt b/etesian/CMakeLists.txt index d71cf930..6c2bdff8 100644 --- a/etesian/CMakeLists.txt +++ b/etesian/CMakeLists.txt @@ -22,6 +22,7 @@ find_package(VLSISAPD REQUIRED) find_package(LEFDEF REQUIRED) find_package(HURRICANE REQUIRED) + find_package(KATABATIC REQUIRED) find_package(CORIOLIS REQUIRED) find_package(COLOQUINTE REQUIRED) find_package(Libexecinfo REQUIRED) diff --git a/etesian/src/EtesianEngine.cpp b/etesian/src/EtesianEngine.cpp index 12bc0d32..5a80dedf 100644 --- a/etesian/src/EtesianEngine.cpp +++ b/etesian/src/EtesianEngine.cpp @@ -39,6 +39,8 @@ #include "hurricane/RoutingPad.h" #include "hurricane/UpdateSession.h" #include "hurricane/viewer/CellWidget.h" +#include "katabatic/GCellGrid.h" +#include "katabatic/KatabaticEngine.h" #include "crlcore/Utilities.h" #include "crlcore/Measures.h" #include "crlcore/AllianceFramework.h" @@ -601,6 +603,46 @@ namespace Etesian { _progressReport2(" [--]" ); } + void EtesianEngine::feedRoutingBack(){ + using namespace Katabatic; + /* + * If routing information is present, use it to + * * artificially expand the areas given to coloquinte + * * add placement dentity constraints + */ + DbU::Unit pitch = getPitch(); + const float densityThreshold = 0.9; + + KatabaticEngine* routingEngine = KatabaticEngine::get( getCell() ); + if(routingEngine == NULL) + throw Error("No routing information was found when performing routing-driven placement\n"); + + GCellGrid * grid = routingEngine->getGCellGrid(); + // Get information about the GCells + // Create different densities + + _densityLimits.clear(); + forEach(GCell*, gc, grid->getGCells()){ + float density = (*gc)->getMaxHVDensity(); + if(density >= densityThreshold){ + + coloquinte::density_limit cur; + cur.box_ = coloquinte::box( + (*gc)->getX() / pitch, + (*gc)->getXMax() / pitch, + (*gc)->getY() / pitch, + (*gc)->getYMax() / pitch + ); + cur.density_ = densityThreshold/density; + _densityLimits.push_back(cur); + } + } + + // TODO: Careful to keep the densities high enough + // Will just fail later if the densities are too high + + // Expand areas: TODO + } void EtesianEngine::globalPlace ( float initPenalty, float minDisruption, float targetImprovement, float minInc, float maxInc, unsigned options ){ using namespace coloquinte::gp; @@ -616,8 +658,8 @@ namespace Etesian { do{ // Create a legalizer and bipartition it until we have sufficient precision auto legalizer = (options & ForceUniformDensity) != 0 ? - region_distribution::uniform_density_distribution(_surface, _circuit, _placementLB) - : region_distribution::full_density_distribution(_surface, _circuit, _placementLB); + region_distribution::uniform_density_distribution (_surface, _circuit, _placementLB, _densityLimits) + : region_distribution::full_density_distribution (_surface, _circuit, _placementLB, _densityLimits); // Until there is about 10 standard cells per region for ( int quad_part=0 ; _circuit.cell_cnt() > (index_t)(10 * (1 << (quad_part*2))) ; ++quad_part ) { legalizer.x_bipartition(); diff --git a/etesian/src/etesian/EtesianEngine.h b/etesian/src/etesian/EtesianEngine.h index 26668954..0fdfee53 100644 --- a/etesian/src/etesian/EtesianEngine.h +++ b/etesian/src/etesian/EtesianEngine.h @@ -69,16 +69,24 @@ namespace Etesian { inline double getAspectRatio () const; inline const FeedCells& getFeedCells () const; inline void setCellWidget ( Hurricane::CellWidget* ); + void startMeasures (); void stopMeasures (); void printMeasures ( std::string ) const; + void setDefaultAb (); void resetPlacement (); void toColoquinte (); + void preplace (); + void roughLegalize ( float minDisruption ); + void completeLegalize (); void globalPlace ( float initPenalty, float minDisruption, float targetImprovement, float minInc, float maxInc, unsigned options=0 ); void detailedPlace ( int iterations, int effort, unsigned options=0 ); + void feedRoutingBack (); + void place (); + inline void useFeed ( Cell* ); size_t findYSpin (); void addFeeds (); @@ -99,6 +107,7 @@ namespace Etesian { coloquinte::netlist _circuit; coloquinte::placement_t _placementLB; coloquinte::placement_t _placementUB; + coloquinte::density_restrictions _densityLimits; std::unordered_map _cellsToIds; std::vector _idsToInsts; Hurricane::CellWidget* _cellWidget; diff --git a/katabatic/src/GCell.cpp b/katabatic/src/GCell.cpp index 8b5cd1cc..53d44527 100644 --- a/katabatic/src/GCell.cpp +++ b/katabatic/src/GCell.cpp @@ -543,6 +543,33 @@ namespace Katabatic { return (float)( _box.getWidth () / Session::getPitch(2) + 1 ); } + float GCell::getAverageHVDensity () const + { + // Average density of all layers mixeds together. + float density = 0.0; + for ( size_t i=0 ; i<_depth ; i++ ) + density += _densities[i]; + return density / ((float)(_depth-_pinDepth)); + } + + float GCell::getMaxHVDensity () const + { + // Maximum density between all horizontal vs. all vertical layers. + size_t hplanes = 0; + size_t vplanes = 0; + float hdensity = 0.0; + float vdensity = 0.0; + + for ( size_t i=_pinDepth ; i<_depth ; i++ ) { + if ( i%2 ) { hdensity += _densities[i]; ++hplanes; } + else { vdensity += _densities[i]; ++vplanes; } + } + + if (hplanes) hdensity /= hplanes; + if (vplanes) vdensity /= vplanes; + + return std::max(hdensity, vdensity); + } float GCell::getDensity ( unsigned int flags ) const { @@ -551,29 +578,9 @@ namespace Katabatic { float density = 0.0; if (getGCellGrid()->getDensityMode() == GCellGrid::AverageHVDensity) { - // Average density of all layers mixeds together. - for ( size_t i=0 ; i<_depth ; i++ ) - density += _densities[i]; - - //density = roundfp ( density/((float)(_depth-_pinDepth)) ); - density = density/((float)(_depth-_pinDepth)); + density = getAverageHVDensity(); } else if (getGCellGrid()->getDensityMode() == GCellGrid::MaxHVDensity) { - // Maximum density between all horizontal vs. all vertical layers. - size_t hplanes = 0; - size_t vplanes = 0; - float hdensity = 0.0; - float vdensity = 0.0; - - for ( size_t i=_pinDepth ; i<_depth ; i++ ) { - if ( i%2 ) { hdensity += _densities[i]; ++hplanes; } - else { vdensity += _densities[i]; ++vplanes; } - } - - if (hplanes) hdensity /= hplanes; - if (vplanes) vdensity /= vplanes; - - //density = roundfp ( (hdensity > vdensity) ? hdensity : vdensity ); - density = (hdensity > vdensity) ? hdensity : vdensity; + density = getMaxHVDensity(); } else if (getGCellGrid()->getDensityMode() == GCellGrid::AverageHDensity) { // Average density between all horizontal layers. size_t hplanes = 0; diff --git a/katabatic/src/katabatic/GCell.h b/katabatic/src/katabatic/GCell.h index 9797696c..09b462ae 100644 --- a/katabatic/src/katabatic/GCell.h +++ b/katabatic/src/katabatic/GCell.h @@ -140,6 +140,8 @@ namespace Katabatic { float getHCapacity () const; float getVCapacity () const; float getDensity ( unsigned int flags=0 ) const; + float getAverageHVDensity () const; + float getMaxHVDensity () const; inline float getCDensity ( unsigned int flags=0 ) const; inline float getWDensity ( unsigned int depth, unsigned int flags=0 ) const; inline DbU::Unit getBlockage ( unsigned int depth ) const; From 6a6def8252eda60df48d4a3bdcf7d314a07fb6e8 Mon Sep 17 00:00:00 2001 From: Gabriel Gouvine Date: Mon, 20 Apr 2015 14:49:12 +0200 Subject: [PATCH 3/7] Cleanup to enable routing-driven placement --- bootstrap/build.conf | 4 +- .../src/coloquinte/rough_legalizers.hxx | 21 +++++-- coloquinte/src/piecewise_linear.cxx | 1 + etesian/src/CMakeLists.txt | 3 +- etesian/src/EtesianEngine.cpp | 57 ++++++++++--------- etesian/src/etesian/EtesianEngine.h | 3 +- 6 files changed, 52 insertions(+), 37 deletions(-) diff --git a/bootstrap/build.conf b/bootstrap/build.conf index 2b97f90c..8447c0e8 100644 --- a/bootstrap/build.conf +++ b/bootstrap/build.conf @@ -14,11 +14,11 @@ projects = [ #, "nimbus" #, "metis" #, "mauka" + , "knik" , "katabatic" + , "kite" , "coloquinte" , "etesian" - , "knik" - , "kite" , "equinox" , "solstice" , "unicorn" diff --git a/coloquinte/src/coloquinte/rough_legalizers.hxx b/coloquinte/src/coloquinte/rough_legalizers.hxx index ce524932..6f86ac6f 100644 --- a/coloquinte/src/coloquinte/rough_legalizers.hxx +++ b/coloquinte/src/coloquinte/rough_legalizers.hxx @@ -130,13 +130,16 @@ class region_distribution{ std::vector prepare_regions(index_t x_cnt, index_t y_cnt) const; public: + + inline box placement_area() const; + inline point region_dimensions() const; + + inline index_t x_regions_cnt() const; + inline index_t y_regions_cnt() const; + inline index_t regions_cnt() const; - inline index_t x_regions_cnt() const; - inline index_t y_regions_cnt() const; - inline index_t regions_cnt() const; - - inline index_t cell_cnt() const; - inline index_t fractional_cell_cnt() const; + inline index_t cell_cnt() const; + inline index_t fractional_cell_cnt() const; /* * Two types of export @@ -206,6 +209,12 @@ class region_distribution{ inline region_distribution::movable_cell::movable_cell(){} inline region_distribution::movable_cell::movable_cell(capacity_t demand, point p, index_t ind) : demand_(demand), pos_(p), index_in_placement_(ind){} +inline box region_distribution::placement_area() const { return placement_area_; } +inline point region_distribution::region_dimensions() const { + point s = static_cast >(placement_area().dimensions()); + return point(s.x_/x_regions_cnt(), s.y_/y_regions_cnt()); +} + inline index_t region_distribution::x_regions_cnt() const { return x_regions_cnt_; } inline index_t region_distribution::y_regions_cnt() const { return y_regions_cnt_; } inline index_t region_distribution::regions_cnt() const { index_t ret = x_regions_cnt() * y_regions_cnt(); assert(placement_regions_.size() == ret); return ret; } diff --git a/coloquinte/src/piecewise_linear.cxx b/coloquinte/src/piecewise_linear.cxx index 83b05034..c422354e 100644 --- a/coloquinte/src/piecewise_linear.cxx +++ b/coloquinte/src/piecewise_linear.cxx @@ -201,6 +201,7 @@ int_t piecewise_linear_function::last_before(int_t pos) const{ ++it; } assert(false); // We should have found it if the bound was correct + return -1; } int_t piecewise_linear_function::value_at(int_t pos) const{ diff --git a/etesian/src/CMakeLists.txt b/etesian/src/CMakeLists.txt index 67f6df94..77162099 100644 --- a/etesian/src/CMakeLists.txt +++ b/etesian/src/CMakeLists.txt @@ -30,7 +30,8 @@ PyGraphicEtesianEngine.cpp ) qtX_wrap_cpp( mocCpps ${mocIncludes} ) - set( depLibs ${CORIOLIS_PYTHON_LIBRARIES} + set( depLibs ${KATABATIC_LIBRARIES} + ${CORIOLIS_PYTHON_LIBRARIES} ${CORIOLIS_LIBRARIES} ${HURRICANE_PYTHON_LIBRARIES} ${HURRICANE_GRAPHICAL_LIBRARIES} diff --git a/etesian/src/EtesianEngine.cpp b/etesian/src/EtesianEngine.cpp index 5a80dedf..5b97136d 100644 --- a/etesian/src/EtesianEngine.cpp +++ b/etesian/src/EtesianEngine.cpp @@ -603,6 +603,31 @@ namespace Etesian { _progressReport2(" [--]" ); } + void EtesianEngine::roughLegalize( float minDisruption, unsigned options ){ + using namespace coloquinte::gp; + // Create a legalizer and bipartition it until we have sufficient precision + auto legalizer = (options & ForceUniformDensity) != 0 ? + region_distribution::uniform_density_distribution (_surface, _circuit, _placementLB, _densityLimits) + : region_distribution::full_density_distribution (_surface, _circuit, _placementLB, _densityLimits); + while(legalizer.region_dimensions().x_ > 2*legalizer.region_dimensions().y_) + legalizer.x_bipartition(); + while(2*legalizer.region_dimensions().x_ < legalizer.region_dimensions().y_) + legalizer.y_bipartition(); + while( std::max(legalizer.region_dimensions().x_, legalizer.region_dimensions().y_)*4 > minDisruption ) { + legalizer.x_bipartition(); + legalizer.y_bipartition(); + legalizer.redo_line_partitions(); + legalizer.redo_diagonal_bipartitions(); + legalizer.redo_line_partitions(); + legalizer.redo_diagonal_bipartitions(); + legalizer.selfcheck(); + } + // Keep the orientation between LB and UB + _placementUB = _placementLB; + // Update UB + get_rough_legalization( _circuit, _placementUB, legalizer ); + } + void EtesianEngine::feedRoutingBack(){ using namespace Katabatic; /* @@ -656,25 +681,7 @@ namespace Etesian { index_t i=0; do{ - // Create a legalizer and bipartition it until we have sufficient precision - auto legalizer = (options & ForceUniformDensity) != 0 ? - region_distribution::uniform_density_distribution (_surface, _circuit, _placementLB, _densityLimits) - : region_distribution::full_density_distribution (_surface, _circuit, _placementLB, _densityLimits); - // Until there is about 10 standard cells per region - for ( int quad_part=0 ; _circuit.cell_cnt() > (index_t)(10 * (1 << (quad_part*2))) ; ++quad_part ) { - legalizer.x_bipartition(); - legalizer.y_bipartition(); - legalizer.redo_line_partitions(); - legalizer.redo_diagonal_bipartitions(); - legalizer.redo_line_partitions(); - legalizer.redo_diagonal_bipartitions(); - legalizer.selfcheck(); - } - // Keep the orientation between LB and UB - _placementUB = _placementLB; - // Update UB - get_rough_legalization( _circuit, _placementUB, legalizer ); - + roughLegalize(minDisruption, options); if(options & UpdateUB) _updatePlacement( _placementUB ); @@ -699,11 +706,6 @@ namespace Etesian { if(options & UpdateLB) _updatePlacement( _placementLB ); - // First way to exit the loop: the legalization is close enough to the previous result - linearDisruption = get_mean_linear_disruption(_circuit, _placementLB, _placementUB); - if(linearDisruption <= minDisruption) - break; - // Optimize orientation sometimes if (i%5 == 0) { optimize_exact_orientations( _circuit, _placementLB ); @@ -728,9 +730,11 @@ namespace Etesian { pullingForce += penaltyIncrease; prevOptRatio = optRatio; + linearDisruption = get_mean_linear_disruption(_circuit, _placementLB, _placementUB); ++i; - // Second way to exit the loop: UB and LB difference is <10% - }while(prevOptRatio <= 0.9); + // First way to exit the loop: UB and LB difference is <10% + // Second way to exit the loop: the legalization is close enough to the previous result + }while(linearDisruption > minDisruption and prevOptRatio <= 0.9); _updatePlacement( _placementUB ); } @@ -739,6 +743,7 @@ namespace Etesian { using namespace coloquinte::dp; int_t sliceHeight = getSliceHeight() / getPitch(); + roughLegalize(sliceHeight, options); for ( int i=0; i Date: Mon, 20 Apr 2015 16:50:30 +0200 Subject: [PATCH 4/7] Basic routing-driven placement --- etesian/CMakeLists.txt | 3 +-- etesian/src/CMakeLists.txt | 1 + etesian/src/EtesianEngine.cpp | 32 +++++++++++++++++++++++++++++++- 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/etesian/CMakeLists.txt b/etesian/CMakeLists.txt index 6c2bdff8..32fa4753 100644 --- a/etesian/CMakeLists.txt +++ b/etesian/CMakeLists.txt @@ -16,14 +16,13 @@ set_lib_link_mode() setup_boost(program_options python regex) - find_package(LibXml2 REQUIRED) find_package(PythonLibs REQUIRED) find_package(PythonSitePackages REQUIRED) find_package(VLSISAPD REQUIRED) - find_package(LEFDEF REQUIRED) find_package(HURRICANE REQUIRED) find_package(KATABATIC REQUIRED) find_package(CORIOLIS REQUIRED) + find_package(KITE REQUIRED) find_package(COLOQUINTE REQUIRED) find_package(Libexecinfo REQUIRED) diff --git a/etesian/src/CMakeLists.txt b/etesian/src/CMakeLists.txt index 77162099..6b1dfaef 100644 --- a/etesian/src/CMakeLists.txt +++ b/etesian/src/CMakeLists.txt @@ -36,6 +36,7 @@ ${HURRICANE_PYTHON_LIBRARIES} ${HURRICANE_GRAPHICAL_LIBRARIES} ${HURRICANE_LIBRARIES} + ${KITE_LIBRARIES} ${CONFIGURATION_LIBRARY} ${BOOKSHELF_LIBRARY} ${CIF_LIBRARY} diff --git a/etesian/src/EtesianEngine.cpp b/etesian/src/EtesianEngine.cpp index 5b97136d..dfbd1659 100644 --- a/etesian/src/EtesianEngine.cpp +++ b/etesian/src/EtesianEngine.cpp @@ -41,6 +41,7 @@ #include "hurricane/viewer/CellWidget.h" #include "katabatic/GCellGrid.h" #include "katabatic/KatabaticEngine.h" +#include "kite/KiteEngine.h" #include "crlcore/Utilities.h" #include "crlcore/Measures.h" #include "crlcore/AllianceFramework.h" @@ -630,6 +631,7 @@ namespace Etesian { void EtesianEngine::feedRoutingBack(){ using namespace Katabatic; + using namespace Kite; /* * If routing information is present, use it to * * artificially expand the areas given to coloquinte @@ -638,7 +640,7 @@ namespace Etesian { DbU::Unit pitch = getPitch(); const float densityThreshold = 0.9; - KatabaticEngine* routingEngine = KatabaticEngine::get( getCell() ); + KiteEngine* routingEngine = KiteEngine::get( getCell() ); if(routingEngine == NULL) throw Error("No routing information was found when performing routing-driven placement\n"); @@ -794,6 +796,7 @@ namespace Etesian { _progressReport1(" Final Legalize ." ); } } + _placementLB = _placementUB; // In case we run other passes _updatePlacement( _placementUB ); } @@ -869,6 +872,33 @@ namespace Etesian { cmess1 << " o Detailed Placement." << endl; detailedPlace(detailedIterations, detailedEffort, detailedOptions); + using namespace Kite; + KiteEngine* kiteE = KiteEngine::create(_cell); + kiteE->runGlobalRouter(0); + kiteE->loadGlobalRouting(Katabatic::EngineLoadGrByNet); + kiteE->balanceGlobalDensity(); + kiteE->layerAssign(Katabatic::EngineNoNetLayerAssign); + kiteE->runNegociate(); + feedRoutingBack(); + kiteE->destroy(); + + UpdateSession::open(); + forEach(Net*, inet, _cell->getNets()){ + if(NetRoutingExtension::isManualGlobalRoute(*inet)) + continue; + std::vector pointers; + forEach(Component*, icom, (*inet)->getComponents()){ + Contact * contact = dynamic_cast(*icom); + if(contact){ + pointers.push_back(contact); + } + } + for(Contact* contact : pointers) + contact->destroy(); + } + UpdateSession::close(); + detailedPlace(detailedIterations, detailedEffort, detailedOptions); + cmess2 << " o Adding feed cells." << endl; addFeeds(); From 524b27451e45e6145e06b596bf3196d7116ad93f Mon Sep 17 00:00:00 2001 From: Gabriel Gouvine Date: Thu, 23 Apr 2015 15:16:53 +0200 Subject: [PATCH 5/7] Wiping the routing is possible!! --- etesian/src/EtesianEngine.cpp | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/etesian/src/EtesianEngine.cpp b/etesian/src/EtesianEngine.cpp index dfbd1659..9ce21b34 100644 --- a/etesian/src/EtesianEngine.cpp +++ b/etesian/src/EtesianEngine.cpp @@ -886,15 +886,30 @@ namespace Etesian { forEach(Net*, inet, _cell->getNets()){ if(NetRoutingExtension::isManualGlobalRoute(*inet)) continue; - std::vector pointers; + // First pass: destroy the contacts + std::vector contactPointers; forEach(Component*, icom, (*inet)->getComponents()){ Contact * contact = dynamic_cast(*icom); if(contact){ - pointers.push_back(contact); + contactPointers.push_back(contact); } } - for(Contact* contact : pointers) + for(Contact* contact : contactPointers) contact->destroy(); + // Second pass: destroy unconnected segments added by Knik as blockages + std::vector compPointers; + forEach(Component*, icom, (*inet)->getComponents()){ + Horizontal * h = dynamic_cast(*icom); + if(h){ + compPointers.push_back(h); + } + Vertical * v = dynamic_cast(*icom); + if(v){ + compPointers.push_back(v); + } + } + for(Component* comp : compPointers) + comp->destroy(); } UpdateSession::close(); detailedPlace(detailedIterations, detailedEffort, detailedOptions); From bded70971ee3fd70c6eef8daf3fb162ecc83c1a4 Mon Sep 17 00:00:00 2001 From: Gabriel Gouvine Date: Thu, 23 Apr 2015 16:14:06 +0200 Subject: [PATCH 6/7] Taking into account the configuration flag + wipeout routing function --- etesian/src/Configuration.cpp | 4 +- etesian/src/EtesianEngine.cpp | 61 +++++++++++------------------ etesian/src/etesian/Configuration.h | 3 ++ etesian/src/etesian/EtesianEngine.h | 2 + kite/src/KiteEngine.cpp | 37 ++++++++++++++++- kite/src/kite/KiteEngine.h | 1 + 6 files changed, 67 insertions(+), 41 deletions(-) diff --git a/etesian/src/Configuration.cpp b/etesian/src/Configuration.cpp index 95f0bb2e..bf992b46 100644 --- a/etesian/src/Configuration.cpp +++ b/etesian/src/Configuration.cpp @@ -56,7 +56,8 @@ namespace Etesian { : _cg ( NULL ) , _placeEffort ( static_cast (Cfg::getParamEnumerate ("etesian.effort" , Standard )->asInt()) ) , _updateConf ( static_cast (Cfg::getParamEnumerate ("etesian.graphics" , LowerBound )->asInt()) ) - , _spreadingConf( Cfg::getParamBool ("etesian.uniformDensity", false )->asBool()?ForceUniform:MaxDensity ) + , _spreadingConf( Cfg::getParamBool ("etesian.uniformDensity", false )->asBool()? ForceUniform : MaxDensity ) + , _routingDriven( Cfg::getParamBool ("etesian.routingDriven", false )->asBool()) , _spaceMargin ( Cfg::getParamPercentage("etesian.spaceMargin" , 5.0)->asDouble() ) , _aspectRatio ( Cfg::getParamPercentage("etesian.aspectRatio" ,100.0)->asDouble() ) { @@ -95,6 +96,7 @@ namespace Etesian { cout << Dots::asInt (" - Place Effort" ,_placeEffort ) << endl; cout << Dots::asInt (" - Update Conf" ,_updateConf ) << endl; cout << Dots::asInt (" - Spreading Conf",_spreadingConf) << endl; + cout << Dots::asBool (" - Routing driven",_routingDriven) << endl; cout << Dots::asPercentage(" - Space Margin" ,_spaceMargin ) << endl; cout << Dots::asPercentage(" - Aspect Ratio" ,_aspectRatio ) << endl; } diff --git a/etesian/src/EtesianEngine.cpp b/etesian/src/EtesianEngine.cpp index 9ce21b34..b6d64da6 100644 --- a/etesian/src/EtesianEngine.cpp +++ b/etesian/src/EtesianEngine.cpp @@ -811,6 +811,7 @@ namespace Etesian { Effort placementEffort = getPlaceEffort(); GraphicUpdate placementUpdate = getUpdateConf(); Density densityConf = getSpreadingConf(); + bool routingDriven = getRoutingDriven(); startMeasures(); double sliceHeight = getSliceHeight() / getPitch(); @@ -872,47 +873,29 @@ namespace Etesian { cmess1 << " o Detailed Placement." << endl; detailedPlace(detailedIterations, detailedEffort, detailedOptions); - using namespace Kite; - KiteEngine* kiteE = KiteEngine::create(_cell); - kiteE->runGlobalRouter(0); - kiteE->loadGlobalRouting(Katabatic::EngineLoadGrByNet); - kiteE->balanceGlobalDensity(); - kiteE->layerAssign(Katabatic::EngineNoNetLayerAssign); - kiteE->runNegociate(); - feedRoutingBack(); - kiteE->destroy(); - - UpdateSession::open(); - forEach(Net*, inet, _cell->getNets()){ - if(NetRoutingExtension::isManualGlobalRoute(*inet)) - continue; - // First pass: destroy the contacts - std::vector contactPointers; - forEach(Component*, icom, (*inet)->getComponents()){ - Contact * contact = dynamic_cast(*icom); - if(contact){ - contactPointers.push_back(contact); + if(routingDriven){ + bool success = false; + int routingDrivenIteration = 0; + using namespace Kite; + while(true){ + cmess2 << "Routing-driven placement iteration " << routingDrivenIteration << endl; + KiteEngine* kiteE = KiteEngine::create(_cell); + kiteE->runGlobalRouter(0); + kiteE->loadGlobalRouting(Katabatic::EngineLoadGrByNet); + kiteE->balanceGlobalDensity(); + kiteE->layerAssign(Katabatic::EngineNoNetLayerAssign); + kiteE->runNegociate(); + success = kiteE->getToolSuccess(); + feedRoutingBack(); + kiteE->destroy(); + KiteEngine::wipeOutRouting(_cell); + if(success){ + cmess2 << "The design is routable; exiting" << endl; + break; + } + detailedPlace(detailedIterations, detailedEffort, detailedOptions); } - } - for(Contact* contact : contactPointers) - contact->destroy(); - // Second pass: destroy unconnected segments added by Knik as blockages - std::vector compPointers; - forEach(Component*, icom, (*inet)->getComponents()){ - Horizontal * h = dynamic_cast(*icom); - if(h){ - compPointers.push_back(h); - } - Vertical * v = dynamic_cast(*icom); - if(v){ - compPointers.push_back(v); - } - } - for(Component* comp : compPointers) - comp->destroy(); } - UpdateSession::close(); - detailedPlace(detailedIterations, detailedEffort, detailedOptions); cmess2 << " o Adding feed cells." << endl; addFeeds(); diff --git a/etesian/src/etesian/Configuration.h b/etesian/src/etesian/Configuration.h index 28f4200d..eda4d8d7 100644 --- a/etesian/src/etesian/Configuration.h +++ b/etesian/src/etesian/Configuration.h @@ -66,6 +66,7 @@ namespace Etesian { inline Effort getPlaceEffort () const; inline GraphicUpdate getUpdateConf () const; inline Density getSpreadingConf () const; + inline bool getRoutingDriven () const; inline double getSpaceMargin () const; inline double getAspectRatio () const; void print ( Cell* ) const; @@ -78,6 +79,7 @@ namespace Etesian { Effort _placeEffort; GraphicUpdate _updateConf; Density _spreadingConf; + bool _routingDriven; double _spaceMargin; double _aspectRatio; private: @@ -90,6 +92,7 @@ namespace Etesian { inline Effort Configuration::getPlaceEffort () const { return _placeEffort; } inline GraphicUpdate Configuration::getUpdateConf () const { return _updateConf; } inline Density Configuration::getSpreadingConf () const { return _spreadingConf; } + inline bool Configuration::getRoutingDriven () const { return _routingDriven; } inline double Configuration::getSpaceMargin () const { return _spaceMargin; } inline double Configuration::getAspectRatio () const { return _aspectRatio; } diff --git a/etesian/src/etesian/EtesianEngine.h b/etesian/src/etesian/EtesianEngine.h index 1382f858..a277c570 100644 --- a/etesian/src/etesian/EtesianEngine.h +++ b/etesian/src/etesian/EtesianEngine.h @@ -65,6 +65,7 @@ namespace Etesian { inline Effort getPlaceEffort () const; inline GraphicUpdate getUpdateConf () const; inline Density getSpreadingConf () const; + inline bool getRoutingDriven () const; inline double getSpaceMargin () const; inline double getAspectRatio () const; inline const FeedCells& getFeedCells () const; @@ -137,6 +138,7 @@ namespace Etesian { inline Effort EtesianEngine::getPlaceEffort () const { return getConfiguration()->getPlaceEffort(); } inline GraphicUpdate EtesianEngine::getUpdateConf () const { return getConfiguration()->getUpdateConf(); } inline Density EtesianEngine::getSpreadingConf () const { return getConfiguration()->getSpreadingConf(); } + inline bool EtesianEngine::getRoutingDriven () const { return getConfiguration()->getRoutingDriven(); } inline double EtesianEngine::getSpaceMargin () const { return getConfiguration()->getSpaceMargin(); } inline double EtesianEngine::getAspectRatio () const { return getConfiguration()->getAspectRatio(); } inline void EtesianEngine::useFeed ( Cell* cell ) { _feedCells.useFeed(cell); } diff --git a/kite/src/KiteEngine.cpp b/kite/src/KiteEngine.cpp index 95360368..f898e5d2 100644 --- a/kite/src/KiteEngine.cpp +++ b/kite/src/KiteEngine.cpp @@ -20,6 +20,7 @@ #include #include "vlsisapd/utilities/Path.h" #include "hurricane/DebugSession.h" +#include "hurricane/UpdateSession.h" #include "hurricane/Bug.h" #include "hurricane/Error.h" #include "hurricane/Warning.h" @@ -175,7 +176,6 @@ namespace Kite { return kite; } - void KiteEngine::_preDestroy () { ltrace(90) << "KiteEngine::_preDestroy()" << endl; @@ -207,6 +207,41 @@ namespace Kite { ltraceout(90); } + void KiteEngine::wipeOutRouting( Cell * cell ){ + if(KiteEngine::get(cell) != NULL or KatabaticEngine::get(cell) != NULL) + throw Error("Trying to wipe out a routing with a routing engine\n"); + using namespace Hurricane; + UpdateSession::open(); + forEach(Net*, inet, cell->getNets()){ + if(NetRoutingExtension::isManualGlobalRoute(*inet)) + continue; + // First pass: destroy the contacts + std::vector contactPointers; + forEach(Component*, icom, (*inet)->getComponents()){ + Contact * contact = dynamic_cast(*icom); + if(contact){ + contactPointers.push_back(contact); + } + } + for(Contact* contact : contactPointers) + contact->destroy(); + // Second pass: destroy unconnected segments added by Knik as blockages + std::vector compPointers; + forEach(Component*, icom, (*inet)->getComponents()){ + Horizontal * h = dynamic_cast(*icom); + if(h){ + compPointers.push_back(h); + } + Vertical * v = dynamic_cast(*icom); + if(v){ + compPointers.push_back(v); + } + } + for(Component* comp : compPointers) + comp->destroy(); + } + UpdateSession::close(); + } KiteEngine::~KiteEngine () { delete _configuration; } diff --git a/kite/src/kite/KiteEngine.h b/kite/src/kite/KiteEngine.h index be462bc5..24ab5992 100644 --- a/kite/src/kite/KiteEngine.h +++ b/kite/src/kite/KiteEngine.h @@ -63,6 +63,7 @@ namespace Kite { static const Name& staticGetName (); static KiteEngine* create ( Cell* ); static KiteEngine* get ( const Cell* ); + static void wipeOutRouting ( Cell* ); public: inline bool useClockTree () const; inline CellViewer* getViewer () const; From 4b628baa171d97304058f62e801157be3b460a67 Mon Sep 17 00:00:00 2001 From: Gabriel Gouvine Date: Thu, 23 Apr 2015 18:02:00 +0200 Subject: [PATCH 7/7] Added support for OpenMP in Coloquinte --- coloquinte/CMakeLists.txt | 6 +++++- unicorn/CMakeLists.txt | 10 +++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/coloquinte/CMakeLists.txt b/coloquinte/CMakeLists.txt index a773e8b2..4e435671 100644 --- a/coloquinte/CMakeLists.txt +++ b/coloquinte/CMakeLists.txt @@ -19,7 +19,11 @@ find_package(Libexecinfo REQUIRED) if(WITH_OPENMP) - add_definitions( -fopenmp ) + find_package(OpenMP REQUIRED) + add_definitions(${OpenMP_CXX_FLAGS}) + set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${OpenMP_CXX_FLAGS}") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${OpenMP_CXX_FLAGS}") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_CXX_FLAGS}") endif() add_subdirectory(src) diff --git a/unicorn/CMakeLists.txt b/unicorn/CMakeLists.txt index 9d9623e6..e1d61a7f 100644 --- a/unicorn/CMakeLists.txt +++ b/unicorn/CMakeLists.txt @@ -33,7 +33,15 @@ find_package(KITE REQUIRED) #find_package(EQUINOX REQUIRED) #find_package(SOLSTICE REQUIRED) - + + if(WITH_OPENMP) + find_package(OpenMP REQUIRED) + add_definitions(${OpenMP_CXX_FLAGS}) + set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${OpenMP_CXX_FLAGS}") + set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${OpenMP_CXX_FLAGS}") + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_CXX_FLAGS}") + endif(WITH_OPENMP) + add_subdirectory(src) add_subdirectory(python) add_subdirectory(cmake_modules)