From 6f0bc2ecb0fbcd0cb29142a1d85a3905b5e2600c Mon Sep 17 00:00:00 2001 From: Gabriel Gouvine Date: Sat, 18 Apr 2015 15:50:40 +0200 Subject: [PATCH] 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