diff --git a/bootstrap/build.conf b/bootstrap/build.conf index 61acbdd1..8447c0e8 100644 --- a/bootstrap/build.conf +++ b/bootstrap/build.conf @@ -14,11 +14,11 @@ projects = [ #, "nimbus" #, "metis" #, "mauka" - , "coloquinte" - , "etesian" , "knik" , "katabatic" , "kite" + , "coloquinte" + , "etesian" , "equinox" , "solstice" , "unicorn" 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/coloquinte/src/coloquinte/rough_legalizers.hxx b/coloquinte/src/coloquinte/rough_legalizers.hxx index 67128513..6f86ac6f 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; @@ -128,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 @@ -204,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/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..32fa4753 100644 --- a/etesian/CMakeLists.txt +++ b/etesian/CMakeLists.txt @@ -16,13 +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 67f6df94..6b1dfaef 100644 --- a/etesian/src/CMakeLists.txt +++ b/etesian/src/CMakeLists.txt @@ -30,11 +30,13 @@ 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} ${HURRICANE_LIBRARIES} + ${KITE_LIBRARIES} ${CONFIGURATION_LIBRARY} ${BOOKSHELF_LIBRARY} ${CIF_LIBRARY} 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 8834ae6e..78ce3fdc 100644 --- a/etesian/src/EtesianEngine.cpp +++ b/etesian/src/EtesianEngine.cpp @@ -39,6 +39,9 @@ #include "hurricane/RoutingPad.h" #include "hurricane/UpdateSession.h" #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" @@ -54,9 +57,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 +585,224 @@ 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::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; + using namespace Kite; + /* + * 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; + + KiteEngine* routingEngine = KiteEngine::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; + + 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{ + roughLegalize(minDisruption, options); + 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 ); + + // 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; + + linearDisruption = get_mean_linear_disruption(_circuit, _placementLB, _placementUB); + ++i; + // 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 ); + } + + void EtesianEngine::detailedPlace ( int iterations, int effort, unsigned options ){ using namespace coloquinte::gp; using namespace coloquinte::dp; + int_t sliceHeight = getSliceHeight() / getPitch(); + roughLegalize(sliceHeight, options); + + for ( int i=0; iuniquify(); getConfiguration()->print( getCell() ); @@ -590,204 +814,91 @@ namespace Etesian { Effort placementEffort = getPlaceEffort(); GraphicUpdate placementUpdate = getUpdateConf(); Density densityConf = getSpreadingConf(); + bool routingDriven = getRoutingDriven(); + + startMeasures(); + double sliceHeight = getSliceHeight() / getPitch(); cmess1 << " o Running Coloquinte." << endl; - cmess1 << " o Global placement." << endl; cmess2 << " - Computing initial placement..." << endl; - cmess2 << setfill('0') << right; + cmess2 << 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; irunGlobalRouter(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); } } - _updatePlacement( _placementUB ); cmess2 << " o Adding feed cells." << endl; addFeeds(); @@ -796,9 +907,9 @@ namespace Etesian { stopMeasures(); printMeasures( "total" ); cmess1 << ::Dots::asString - ( " - HPWL", DbU::getValueString( (DbU::Unit)get_HPWL_wirelength(_circuit,_placementUB )*getPitch() ) ) << endl; + ( " - HPWL", DbU::getValueString( (DbU::Unit)coloquinte::gp::get_HPWL_wirelength(_circuit,_placementUB )*getPitch() ) ) << endl; cmess1 << ::Dots::asString - ( " - RMST", DbU::getValueString( (DbU::Unit)get_RSMT_wirelength(_circuit,_placementUB )*getPitch() ) ) << endl; + ( " - RMST", DbU::getValueString( (DbU::Unit)coloquinte::gp::get_RSMT_wirelength(_circuit,_placementUB )*getPitch() ) ) << endl; _placed = true; @@ -806,7 +917,7 @@ namespace Etesian { } - void EtesianEngine::_progressReport1 ( time_t startTime, string label ) const + void EtesianEngine::_progressReport1 ( string label ) const { size_t w = label.size(); string indent ( w, ' ' ); @@ -816,20 +927,20 @@ namespace Etesian { } ostringstream elapsed; - elapsed << " dTime:" << setw(5) << (time(NULL) - startTime) << "s "; + //elapsed << " dTime:" << setw(5) << _timer.getCombTime() << "s "; cmess2 << label << elapsed.str() - << " HPWL:" << coloquinte::gp::get_HPWL_wirelength( _circuit, _placementUB ) - << " RMST:" << coloquinte::gp::get_RSMT_wirelength( _circuit, _placementUB ) + << " HPWL:" << setw(11) << coloquinte::gp::get_HPWL_wirelength( _circuit, _placementUB ) + << " RMST:" << setw(11) << coloquinte::gp::get_RSMT_wirelength( _circuit, _placementUB ) << endl; cparanoid << indent - << " Linear Disrupt.:" << coloquinte::gp::get_mean_linear_disruption ( _circuit, _placementLB, _placementUB ) - << " Quad Disrupt.:" << coloquinte::gp::get_mean_quadratic_disruption( _circuit, _placementLB, _placementUB ) + << " Linear Disrupt.:" << setw(11) << coloquinte::gp::get_mean_linear_disruption ( _circuit, _placementLB, _placementUB ) + << " Quad Disrupt.:" << setw(11) << coloquinte::gp::get_mean_quadratic_disruption( _circuit, _placementLB, _placementUB ) << endl; } - void EtesianEngine::_progressReport2 ( time_t startTime, string label ) const + void EtesianEngine::_progressReport2 ( string label ) const { size_t w = label.size(); string indent ( w, ' ' ); @@ -839,11 +950,11 @@ namespace Etesian { } ostringstream elapsed; - elapsed << " dTime:" << setw(5) << (time(NULL) - startTime) << "s "; + //elapsed << " dTime:" << setw(5) << _timer.getCombTime() << "s "; cmess2 << label << elapsed.str() - << " HPWL:" << coloquinte::gp::get_HPWL_wirelength( _circuit, _placementLB ) - << " RMST:" << coloquinte::gp::get_RSMT_wirelength( _circuit, _placementLB ) + << " HPWL:" << setw(11) << coloquinte::gp::get_HPWL_wirelength( _circuit, _placementLB ) + << " RMST:" << setw(11) << coloquinte::gp::get_RSMT_wirelength( _circuit, _placementLB ) << endl; } 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 cdb1a7ca..a277c570 100644 --- a/etesian/src/etesian/EtesianEngine.h +++ b/etesian/src/etesian/EtesianEngine.h @@ -65,17 +65,28 @@ 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; 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, unsigned options ); + 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 (); @@ -96,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; @@ -113,8 +125,8 @@ namespace Etesian { EtesianEngine& operator= ( const EtesianEngine& ); private: void _updatePlacement ( const coloquinte::placement_t& ); - void _progressReport1 ( time_t startTime, string label ) const; - void _progressReport2 ( time_t startTime, string label ) const; + void _progressReport1 ( string label ) const; + void _progressReport2 ( string label ) const; }; @@ -126,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/katabatic/src/GCell.cpp b/katabatic/src/GCell.cpp index 2be34245..7ca53628 100644 --- a/katabatic/src/GCell.cpp +++ b/katabatic/src/GCell.cpp @@ -545,6 +545,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 { @@ -553,29 +580,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; diff --git a/kite/src/KiteEngine.cpp b/kite/src/KiteEngine.cpp index b31325ff..dd950f5f 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" @@ -176,7 +177,6 @@ namespace Kite { return kite; } - void KiteEngine::_preDestroy () { ltrace(90) << "KiteEngine::_preDestroy()" << endl; @@ -208,6 +208,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; 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)