Merge the routing-driven version of Etesian (github/RoutingDriven)
This commit is contained in:
commit
731d435a35
|
@ -14,11 +14,11 @@ projects = [
|
||||||
#, "nimbus"
|
#, "nimbus"
|
||||||
#, "metis"
|
#, "metis"
|
||||||
#, "mauka"
|
#, "mauka"
|
||||||
, "coloquinte"
|
|
||||||
, "etesian"
|
|
||||||
, "knik"
|
, "knik"
|
||||||
, "katabatic"
|
, "katabatic"
|
||||||
, "kite"
|
, "kite"
|
||||||
|
, "coloquinte"
|
||||||
|
, "etesian"
|
||||||
, "equinox"
|
, "equinox"
|
||||||
, "solstice"
|
, "solstice"
|
||||||
, "unicorn"
|
, "unicorn"
|
||||||
|
|
|
@ -19,7 +19,11 @@
|
||||||
find_package(Libexecinfo REQUIRED)
|
find_package(Libexecinfo REQUIRED)
|
||||||
|
|
||||||
if(WITH_OPENMP)
|
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()
|
endif()
|
||||||
|
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
|
|
|
@ -18,6 +18,13 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
namespace coloquinte{
|
namespace coloquinte{
|
||||||
|
|
||||||
|
struct density_limit{
|
||||||
|
box<int_t> box_;
|
||||||
|
float_t density_; // from 0.0 for a macro to 1.0 if it does nothing
|
||||||
|
};
|
||||||
|
typedef std::vector<density_limit> density_restrictions;
|
||||||
|
|
||||||
namespace gp{
|
namespace gp{
|
||||||
|
|
||||||
class region_distribution{
|
class region_distribution{
|
||||||
|
@ -38,11 +45,6 @@ class region_distribution{
|
||||||
|
|
||||||
// Specifies a maximum density of movable cells per usable area
|
// Specifies a maximum density of movable cells per usable area
|
||||||
// Representing either a macroblock or a routing congestion
|
// Representing either a macroblock or a routing congestion
|
||||||
struct density_limit{
|
|
||||||
box<int_t> box_;
|
|
||||||
float_t density_; // from 0.0 for a macro to 1.0 if it does nothing
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
struct region;
|
struct region;
|
||||||
|
@ -128,13 +130,16 @@ class region_distribution{
|
||||||
std::vector<region> prepare_regions(index_t x_cnt, index_t y_cnt) const;
|
std::vector<region> prepare_regions(index_t x_cnt, index_t y_cnt) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
inline box<int_t> placement_area() const;
|
||||||
|
inline point<float_t> 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 cell_cnt() const;
|
||||||
inline index_t y_regions_cnt() const;
|
inline index_t fractional_cell_cnt() const;
|
||||||
inline index_t regions_cnt() const;
|
|
||||||
|
|
||||||
inline index_t cell_cnt() const;
|
|
||||||
inline index_t fractional_cell_cnt() const;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Two types of export
|
* 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(){}
|
||||||
inline region_distribution::movable_cell::movable_cell(capacity_t demand, point<float_t> p, index_t ind) : demand_(demand), pos_(p), index_in_placement_(ind){}
|
inline region_distribution::movable_cell::movable_cell(capacity_t demand, point<float_t> p, index_t ind) : demand_(demand), pos_(p), index_in_placement_(ind){}
|
||||||
|
|
||||||
|
inline box<int_t> region_distribution::placement_area() const { return placement_area_; }
|
||||||
|
inline point<float_t> region_distribution::region_dimensions() const {
|
||||||
|
point<int_t> s = static_cast<point<float_t> >(placement_area().dimensions());
|
||||||
|
return point<float_t>(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::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::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; }
|
inline index_t region_distribution::regions_cnt() const { index_t ret = x_regions_cnt() * y_regions_cnt(); assert(placement_regions_.size() == ret); return ret; }
|
||||||
|
|
|
@ -201,6 +201,7 @@ int_t piecewise_linear_function::last_before(int_t pos) const{
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
assert(false); // We should have found it if the bound was correct
|
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{
|
int_t piecewise_linear_function::value_at(int_t pos) const{
|
||||||
|
|
|
@ -117,6 +117,7 @@ std::vector<region_distribution::region> region_distribution::prepare_regions(in
|
||||||
// The regions' capacities
|
// The regions' capacities
|
||||||
std::vector<capacity_t> region_caps(x_cnt * y_cnt, 0);
|
std::vector<capacity_t> region_caps(x_cnt * y_cnt, 0);
|
||||||
|
|
||||||
|
// Find the limits of the regions
|
||||||
std::vector<int_t> x_reg_lims(x_cnt+1), y_reg_lims(y_cnt+1);
|
std::vector<int_t> x_reg_lims(x_cnt+1), y_reg_lims(y_cnt+1);
|
||||||
for(index_t i=0; i<=x_cnt; ++i){
|
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;
|
x_reg_lims[i] = placement_area_.x_min_ + ( ((std::int64_t) (placement_area_.x_max_ - placement_area_.x_min_)) * i ) / x_cnt;
|
||||||
|
|
|
@ -16,13 +16,13 @@
|
||||||
set_lib_link_mode()
|
set_lib_link_mode()
|
||||||
setup_boost(program_options python regex)
|
setup_boost(program_options python regex)
|
||||||
|
|
||||||
find_package(LibXml2 REQUIRED)
|
|
||||||
find_package(PythonLibs REQUIRED)
|
find_package(PythonLibs REQUIRED)
|
||||||
find_package(PythonSitePackages REQUIRED)
|
find_package(PythonSitePackages REQUIRED)
|
||||||
find_package(VLSISAPD REQUIRED)
|
find_package(VLSISAPD REQUIRED)
|
||||||
find_package(LEFDEF REQUIRED)
|
|
||||||
find_package(HURRICANE REQUIRED)
|
find_package(HURRICANE REQUIRED)
|
||||||
|
find_package(KATABATIC REQUIRED)
|
||||||
find_package(CORIOLIS REQUIRED)
|
find_package(CORIOLIS REQUIRED)
|
||||||
|
find_package(KITE REQUIRED)
|
||||||
find_package(COLOQUINTE REQUIRED)
|
find_package(COLOQUINTE REQUIRED)
|
||||||
find_package(Libexecinfo REQUIRED)
|
find_package(Libexecinfo REQUIRED)
|
||||||
|
|
||||||
|
|
|
@ -30,11 +30,13 @@
|
||||||
PyGraphicEtesianEngine.cpp
|
PyGraphicEtesianEngine.cpp
|
||||||
)
|
)
|
||||||
qtX_wrap_cpp( mocCpps ${mocIncludes} )
|
qtX_wrap_cpp( mocCpps ${mocIncludes} )
|
||||||
set( depLibs ${CORIOLIS_PYTHON_LIBRARIES}
|
set( depLibs ${KATABATIC_LIBRARIES}
|
||||||
|
${CORIOLIS_PYTHON_LIBRARIES}
|
||||||
${CORIOLIS_LIBRARIES}
|
${CORIOLIS_LIBRARIES}
|
||||||
${HURRICANE_PYTHON_LIBRARIES}
|
${HURRICANE_PYTHON_LIBRARIES}
|
||||||
${HURRICANE_GRAPHICAL_LIBRARIES}
|
${HURRICANE_GRAPHICAL_LIBRARIES}
|
||||||
${HURRICANE_LIBRARIES}
|
${HURRICANE_LIBRARIES}
|
||||||
|
${KITE_LIBRARIES}
|
||||||
${CONFIGURATION_LIBRARY}
|
${CONFIGURATION_LIBRARY}
|
||||||
${BOOKSHELF_LIBRARY}
|
${BOOKSHELF_LIBRARY}
|
||||||
${CIF_LIBRARY}
|
${CIF_LIBRARY}
|
||||||
|
|
|
@ -56,7 +56,8 @@ namespace Etesian {
|
||||||
: _cg ( NULL )
|
: _cg ( NULL )
|
||||||
, _placeEffort ( static_cast<Effort> (Cfg::getParamEnumerate ("etesian.effort" , Standard )->asInt()) )
|
, _placeEffort ( static_cast<Effort> (Cfg::getParamEnumerate ("etesian.effort" , Standard )->asInt()) )
|
||||||
, _updateConf ( static_cast<GraphicUpdate> (Cfg::getParamEnumerate ("etesian.graphics" , LowerBound )->asInt()) )
|
, _updateConf ( static_cast<GraphicUpdate> (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() )
|
, _spaceMargin ( Cfg::getParamPercentage("etesian.spaceMargin" , 5.0)->asDouble() )
|
||||||
, _aspectRatio ( Cfg::getParamPercentage("etesian.aspectRatio" ,100.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 (" - Place Effort" ,_placeEffort ) << endl;
|
||||||
cout << Dots::asInt (" - Update Conf" ,_updateConf ) << endl;
|
cout << Dots::asInt (" - Update Conf" ,_updateConf ) << endl;
|
||||||
cout << Dots::asInt (" - Spreading Conf",_spreadingConf) << 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(" - Space Margin" ,_spaceMargin ) << endl;
|
||||||
cout << Dots::asPercentage(" - Aspect Ratio" ,_aspectRatio ) << endl;
|
cout << Dots::asPercentage(" - Aspect Ratio" ,_aspectRatio ) << endl;
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,9 @@
|
||||||
#include "hurricane/RoutingPad.h"
|
#include "hurricane/RoutingPad.h"
|
||||||
#include "hurricane/UpdateSession.h"
|
#include "hurricane/UpdateSession.h"
|
||||||
#include "hurricane/viewer/CellWidget.h"
|
#include "hurricane/viewer/CellWidget.h"
|
||||||
|
#include "katabatic/GCellGrid.h"
|
||||||
|
#include "katabatic/KatabaticEngine.h"
|
||||||
|
#include "kite/KiteEngine.h"
|
||||||
#include "crlcore/Utilities.h"
|
#include "crlcore/Utilities.h"
|
||||||
#include "crlcore/Measures.h"
|
#include "crlcore/Measures.h"
|
||||||
#include "crlcore/AllianceFramework.h"
|
#include "crlcore/AllianceFramework.h"
|
||||||
|
@ -54,9 +57,17 @@ namespace {
|
||||||
using coloquinte::float_t;
|
using coloquinte::float_t;
|
||||||
using coloquinte::point;
|
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 )
|
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<int_t>(
|
||||||
|
(*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<float_t>(get_HPWL_wirelength(_circuit, _placementUB)),
|
||||||
|
lowerWL = static_cast<float_t>(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<float_t>(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<float_t>(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::gp;
|
||||||
using namespace coloquinte::dp;
|
using namespace coloquinte::dp;
|
||||||
|
|
||||||
|
int_t sliceHeight = getSliceHeight() / getPitch();
|
||||||
|
roughLegalize(sliceHeight, options);
|
||||||
|
|
||||||
|
for ( int i=0; i<iterations; ++i ){
|
||||||
|
ostringstream label;
|
||||||
|
label.str("");
|
||||||
|
label << " [" << setw(2) << setfill('0') << i << "]";
|
||||||
|
|
||||||
|
optimize_x_orientations( _circuit, _placementUB ); // Don't disrupt VDD/VSS connections in a row
|
||||||
|
_progressReport1(label.str()+" Oriented ......." );
|
||||||
|
if(options & UpdateDetailed)
|
||||||
|
_updatePlacement( _placementUB );
|
||||||
|
|
||||||
|
auto legalizer = legalize( _circuit, _placementUB, _surface, sliceHeight );
|
||||||
|
coloquinte::dp::get_result( _circuit, legalizer, _placementUB );
|
||||||
|
_progressReport1(" Legalized ......" );
|
||||||
|
if(options & UpdateDetailed)
|
||||||
|
_updatePlacement( _placementUB );
|
||||||
|
|
||||||
|
row_compatible_orientation( _circuit, legalizer, true );
|
||||||
|
swaps_global_HPWL( _circuit, legalizer, 3, 4 );
|
||||||
|
coloquinte::dp::get_result( _circuit, legalizer, _placementUB );
|
||||||
|
_progressReport1(" Global Swaps ..." );
|
||||||
|
if(options & UpdateDetailed)
|
||||||
|
_updatePlacement( _placementUB );
|
||||||
|
|
||||||
|
if(options & SteinerModel)
|
||||||
|
OSRP_noncvx_RSMT( _circuit, legalizer );
|
||||||
|
else
|
||||||
|
OSRP_convex_HPWL( _circuit, legalizer );
|
||||||
|
coloquinte::dp::get_result( _circuit, legalizer, _placementUB );
|
||||||
|
_progressReport1(" Row Optimization" );
|
||||||
|
if(options & UpdateDetailed)
|
||||||
|
_updatePlacement( _placementUB );
|
||||||
|
|
||||||
|
if(options & SteinerModel)
|
||||||
|
swaps_row_noncvx_RSMT( _circuit, legalizer, effort+2 );
|
||||||
|
else
|
||||||
|
swaps_row_convex_HPWL( _circuit, legalizer, effort+2 );
|
||||||
|
coloquinte::dp::get_result( _circuit, legalizer, _placementUB );
|
||||||
|
_progressReport1(" Local Swaps ...." );
|
||||||
|
if(options & UpdateDetailed)
|
||||||
|
_updatePlacement( _placementUB );
|
||||||
|
|
||||||
|
if (i == iterations-1) {
|
||||||
|
//swaps_row_convex_RSMT( _circuit, legalizer, 4 );
|
||||||
|
row_compatible_orientation( _circuit, legalizer, true );
|
||||||
|
coloquinte::dp::get_result( _circuit, legalizer, _placementUB );
|
||||||
|
verify_placement_legality( _circuit, _placementUB, _surface );
|
||||||
|
_progressReport1(" Final Legalize ." );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_placementLB = _placementUB; // In case we run other passes
|
||||||
|
_updatePlacement( _placementUB );
|
||||||
|
}
|
||||||
|
|
||||||
|
void EtesianEngine::place ()
|
||||||
|
{
|
||||||
getCell()->uniquify();
|
getCell()->uniquify();
|
||||||
|
|
||||||
getConfiguration()->print( getCell() );
|
getConfiguration()->print( getCell() );
|
||||||
|
@ -590,204 +814,91 @@ namespace Etesian {
|
||||||
Effort placementEffort = getPlaceEffort();
|
Effort placementEffort = getPlaceEffort();
|
||||||
GraphicUpdate placementUpdate = getUpdateConf();
|
GraphicUpdate placementUpdate = getUpdateConf();
|
||||||
Density densityConf = getSpreadingConf();
|
Density densityConf = getSpreadingConf();
|
||||||
|
bool routingDriven = getRoutingDriven();
|
||||||
|
|
||||||
|
startMeasures();
|
||||||
|
double sliceHeight = getSliceHeight() / getPitch();
|
||||||
|
|
||||||
cmess1 << " o Running Coloquinte." << endl;
|
cmess1 << " o Running Coloquinte." << endl;
|
||||||
cmess1 << " o Global placement." << endl;
|
|
||||||
cmess2 << " - Computing initial 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;
|
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){
|
if(placementEffort == Fast){
|
||||||
minPenaltyIncrease = 0.005f;
|
minPenaltyIncrease = 0.005f;
|
||||||
maxPenaltyIncrease = 0.08f;
|
maxPenaltyIncrease = 0.08f;
|
||||||
targetImprovement = 0.05f; // 5/100 per iteration
|
targetImprovement = 0.05f; // 5/100 per iteration
|
||||||
|
detailedIterations = 1;
|
||||||
|
detailedEffort = 0;
|
||||||
}
|
}
|
||||||
else if(placementEffort == Standard){
|
else if(placementEffort == Standard){
|
||||||
minPenaltyIncrease = 0.001f;
|
minPenaltyIncrease = 0.001f;
|
||||||
maxPenaltyIncrease = 0.04f;
|
maxPenaltyIncrease = 0.04f;
|
||||||
targetImprovement = 0.02f; // 2/100 per iteration
|
targetImprovement = 0.02f; // 2/100 per iteration
|
||||||
|
detailedIterations = 2;
|
||||||
|
detailedEffort = 1;
|
||||||
}
|
}
|
||||||
else if(placementEffort == High){
|
else if(placementEffort == High){
|
||||||
minPenaltyIncrease = 0.0005f;
|
minPenaltyIncrease = 0.0005f;
|
||||||
maxPenaltyIncrease = 0.02f;
|
maxPenaltyIncrease = 0.02f;
|
||||||
targetImprovement = 0.01f; // 1/100 per iteration
|
targetImprovement = 0.01f; // 1/100 per iteration
|
||||||
|
detailedIterations = 4;
|
||||||
|
detailedEffort = 2;
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
minPenaltyIncrease = 0.0002f;
|
minPenaltyIncrease = 0.0002f;
|
||||||
maxPenaltyIncrease = 0.01f;
|
maxPenaltyIncrease = 0.01f;
|
||||||
targetImprovement = 0.005f; // 5/1000 per iteration
|
targetImprovement = 0.005f; // 5/1000 per iteration
|
||||||
|
detailedIterations = 7;
|
||||||
|
detailedEffort = 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
float_t pullingForce = minPenaltyIncrease;
|
cmess1 << " o Global placement." << endl;
|
||||||
float_t penaltyIncrease = minPenaltyIncrease;
|
globalPlace(minPenaltyIncrease, sliceHeight, targetImprovement, minPenaltyIncrease, maxPenaltyIncrease, globalOptions);
|
||||||
|
|
||||||
float_t linearDisruption = get_mean_linear_disruption(_circuit, _placementLB, _placementUB);
|
|
||||||
float_t currentDisruption = static_cast<float_t>(get_HPWL_wirelength( _circuit, _placementLB )) / static_cast<float_t>(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<float_t>(get_HPWL_wirelength( _circuit, _placementLB )) / static_cast<float_t>(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 Detailed Placement." << endl;
|
cmess1 << " o Detailed Placement." << endl;
|
||||||
index_t detailedIterations;
|
detailedPlace(detailedIterations, detailedEffort, detailedOptions);
|
||||||
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<detailedIterations; ++i ){
|
|
||||||
ostringstream label;
|
|
||||||
label.str("");
|
|
||||||
label << " [" << setw(2) << setfill('0') << i << "]";
|
|
||||||
|
|
||||||
optimize_x_orientations( _circuit, _placementUB ); // Don't disrupt VDD/VSS connections in a row
|
if(routingDriven){
|
||||||
_progressReport1( startTime, label.str()+" Oriented ......." );
|
bool success = false;
|
||||||
if(placementUpdate <= LowerBound)
|
int routingDrivenIteration = 0;
|
||||||
_updatePlacement( _placementUB );
|
using namespace Kite;
|
||||||
|
while(true){
|
||||||
auto legalizer = legalize( _circuit, _placementUB, _surface, sliceHeight );
|
cmess2 << "Routing-driven placement iteration " << routingDrivenIteration << endl;
|
||||||
coloquinte::dp::get_result( _circuit, legalizer, _placementUB );
|
KiteEngine* kiteE = KiteEngine::create(_cell);
|
||||||
_progressReport1( startTime, " Legalized ......" );
|
kiteE->runGlobalRouter(0);
|
||||||
if(placementUpdate <= LowerBound)
|
kiteE->loadGlobalRouting(Katabatic::EngineLoadGrByNet);
|
||||||
_updatePlacement( _placementUB );
|
kiteE->balanceGlobalDensity();
|
||||||
|
kiteE->layerAssign(Katabatic::EngineNoNetLayerAssign);
|
||||||
row_compatible_orientation( _circuit, legalizer, true );
|
kiteE->runNegociate();
|
||||||
swaps_global_HPWL( _circuit, legalizer, 3, 4 );
|
success = kiteE->getToolSuccess();
|
||||||
coloquinte::dp::get_result( _circuit, legalizer, _placementUB );
|
feedRoutingBack();
|
||||||
_progressReport1( startTime, " Global Swaps ..." );
|
kiteE->destroy();
|
||||||
if(placementUpdate <= LowerBound)
|
KiteEngine::wipeOutRouting(_cell);
|
||||||
_updatePlacement( _placementUB );
|
if(success){
|
||||||
|
cmess2 << "The design is routable; exiting" << endl;
|
||||||
OSRP_convex_HPWL( _circuit, legalizer );
|
break;
|
||||||
//OSRP_noncvx_RSMT( _circuit, legalizer );
|
}
|
||||||
coloquinte::dp::get_result( _circuit, legalizer, _placementUB );
|
detailedPlace(detailedIterations, detailedEffort, detailedOptions);
|
||||||
_progressReport1( startTime, " Row Optimization" );
|
|
||||||
if(placementUpdate == UpdateAll)
|
|
||||||
_updatePlacement( _placementUB );
|
|
||||||
|
|
||||||
swaps_row_convex_HPWL( _circuit, legalizer, 4 );
|
|
||||||
//swaps_row_noncvx_RSMT( _circuit, legalizer, 4 );
|
|
||||||
coloquinte::dp::get_result( _circuit, legalizer, _placementUB );
|
|
||||||
_progressReport1( startTime, " Local Swaps ...." );
|
|
||||||
if(placementUpdate <= LowerBound)
|
|
||||||
_updatePlacement( _placementUB );
|
|
||||||
|
|
||||||
if (i == detailedIterations-1) {
|
|
||||||
swaps_row_convex_RSMT( _circuit, legalizer, 4 );
|
|
||||||
row_compatible_orientation( _circuit, legalizer, true );
|
|
||||||
coloquinte::dp::get_result( _circuit, legalizer, _placementUB );
|
|
||||||
verify_placement_legality( _circuit, _placementUB, _surface );
|
|
||||||
_progressReport1( startTime, " Final Legalize ." );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_updatePlacement( _placementUB );
|
|
||||||
|
|
||||||
cmess2 << " o Adding feed cells." << endl;
|
cmess2 << " o Adding feed cells." << endl;
|
||||||
addFeeds();
|
addFeeds();
|
||||||
|
@ -796,9 +907,9 @@ namespace Etesian {
|
||||||
stopMeasures();
|
stopMeasures();
|
||||||
printMeasures( "total" );
|
printMeasures( "total" );
|
||||||
cmess1 << ::Dots::asString
|
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
|
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;
|
_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();
|
size_t w = label.size();
|
||||||
string indent ( w, ' ' );
|
string indent ( w, ' ' );
|
||||||
|
@ -816,20 +927,20 @@ namespace Etesian {
|
||||||
}
|
}
|
||||||
|
|
||||||
ostringstream elapsed;
|
ostringstream elapsed;
|
||||||
elapsed << " dTime:" << setw(5) << (time(NULL) - startTime) << "s ";
|
//elapsed << " dTime:" << setw(5) << _timer.getCombTime() << "s ";
|
||||||
|
|
||||||
cmess2 << label << elapsed.str()
|
cmess2 << label << elapsed.str()
|
||||||
<< " HPWL:" << coloquinte::gp::get_HPWL_wirelength( _circuit, _placementUB )
|
<< " HPWL:" << setw(11) << coloquinte::gp::get_HPWL_wirelength( _circuit, _placementUB )
|
||||||
<< " RMST:" << coloquinte::gp::get_RSMT_wirelength( _circuit, _placementUB )
|
<< " RMST:" << setw(11) << coloquinte::gp::get_RSMT_wirelength( _circuit, _placementUB )
|
||||||
<< endl;
|
<< endl;
|
||||||
cparanoid << indent
|
cparanoid << indent
|
||||||
<< " Linear Disrupt.:" << coloquinte::gp::get_mean_linear_disruption ( _circuit, _placementLB, _placementUB )
|
<< " Linear Disrupt.:" << setw(11) << coloquinte::gp::get_mean_linear_disruption ( _circuit, _placementLB, _placementUB )
|
||||||
<< " Quad Disrupt.:" << coloquinte::gp::get_mean_quadratic_disruption( _circuit, _placementLB, _placementUB )
|
<< " Quad Disrupt.:" << setw(11) << coloquinte::gp::get_mean_quadratic_disruption( _circuit, _placementLB, _placementUB )
|
||||||
<< endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void EtesianEngine::_progressReport2 ( time_t startTime, string label ) const
|
void EtesianEngine::_progressReport2 ( string label ) const
|
||||||
{
|
{
|
||||||
size_t w = label.size();
|
size_t w = label.size();
|
||||||
string indent ( w, ' ' );
|
string indent ( w, ' ' );
|
||||||
|
@ -839,11 +950,11 @@ namespace Etesian {
|
||||||
}
|
}
|
||||||
|
|
||||||
ostringstream elapsed;
|
ostringstream elapsed;
|
||||||
elapsed << " dTime:" << setw(5) << (time(NULL) - startTime) << "s ";
|
//elapsed << " dTime:" << setw(5) << _timer.getCombTime() << "s ";
|
||||||
|
|
||||||
cmess2 << label << elapsed.str()
|
cmess2 << label << elapsed.str()
|
||||||
<< " HPWL:" << coloquinte::gp::get_HPWL_wirelength( _circuit, _placementLB )
|
<< " HPWL:" << setw(11) << coloquinte::gp::get_HPWL_wirelength( _circuit, _placementLB )
|
||||||
<< " RMST:" << coloquinte::gp::get_RSMT_wirelength( _circuit, _placementLB )
|
<< " RMST:" << setw(11) << coloquinte::gp::get_RSMT_wirelength( _circuit, _placementLB )
|
||||||
<< endl;
|
<< endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -66,6 +66,7 @@ namespace Etesian {
|
||||||
inline Effort getPlaceEffort () const;
|
inline Effort getPlaceEffort () const;
|
||||||
inline GraphicUpdate getUpdateConf () const;
|
inline GraphicUpdate getUpdateConf () const;
|
||||||
inline Density getSpreadingConf () const;
|
inline Density getSpreadingConf () const;
|
||||||
|
inline bool getRoutingDriven () const;
|
||||||
inline double getSpaceMargin () const;
|
inline double getSpaceMargin () const;
|
||||||
inline double getAspectRatio () const;
|
inline double getAspectRatio () const;
|
||||||
void print ( Cell* ) const;
|
void print ( Cell* ) const;
|
||||||
|
@ -78,6 +79,7 @@ namespace Etesian {
|
||||||
Effort _placeEffort;
|
Effort _placeEffort;
|
||||||
GraphicUpdate _updateConf;
|
GraphicUpdate _updateConf;
|
||||||
Density _spreadingConf;
|
Density _spreadingConf;
|
||||||
|
bool _routingDriven;
|
||||||
double _spaceMargin;
|
double _spaceMargin;
|
||||||
double _aspectRatio;
|
double _aspectRatio;
|
||||||
private:
|
private:
|
||||||
|
@ -90,6 +92,7 @@ namespace Etesian {
|
||||||
inline Effort Configuration::getPlaceEffort () const { return _placeEffort; }
|
inline Effort Configuration::getPlaceEffort () const { return _placeEffort; }
|
||||||
inline GraphicUpdate Configuration::getUpdateConf () const { return _updateConf; }
|
inline GraphicUpdate Configuration::getUpdateConf () const { return _updateConf; }
|
||||||
inline Density Configuration::getSpreadingConf () const { return _spreadingConf; }
|
inline Density Configuration::getSpreadingConf () const { return _spreadingConf; }
|
||||||
|
inline bool Configuration::getRoutingDriven () const { return _routingDriven; }
|
||||||
inline double Configuration::getSpaceMargin () const { return _spaceMargin; }
|
inline double Configuration::getSpaceMargin () const { return _spaceMargin; }
|
||||||
inline double Configuration::getAspectRatio () const { return _aspectRatio; }
|
inline double Configuration::getAspectRatio () const { return _aspectRatio; }
|
||||||
|
|
||||||
|
|
|
@ -65,17 +65,28 @@ namespace Etesian {
|
||||||
inline Effort getPlaceEffort () const;
|
inline Effort getPlaceEffort () const;
|
||||||
inline GraphicUpdate getUpdateConf () const;
|
inline GraphicUpdate getUpdateConf () const;
|
||||||
inline Density getSpreadingConf () const;
|
inline Density getSpreadingConf () const;
|
||||||
|
inline bool getRoutingDriven () const;
|
||||||
inline double getSpaceMargin () const;
|
inline double getSpaceMargin () const;
|
||||||
inline double getAspectRatio () const;
|
inline double getAspectRatio () const;
|
||||||
inline const FeedCells& getFeedCells () const;
|
inline const FeedCells& getFeedCells () const;
|
||||||
inline void setCellWidget ( Hurricane::CellWidget* );
|
inline void setCellWidget ( Hurricane::CellWidget* );
|
||||||
|
|
||||||
void startMeasures ();
|
void startMeasures ();
|
||||||
void stopMeasures ();
|
void stopMeasures ();
|
||||||
void printMeasures ( std::string ) const;
|
void printMeasures ( std::string ) const;
|
||||||
|
|
||||||
void setDefaultAb ();
|
void setDefaultAb ();
|
||||||
void resetPlacement ();
|
void resetPlacement ();
|
||||||
void toColoquinte ();
|
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 ();
|
void place ();
|
||||||
|
|
||||||
inline void useFeed ( Cell* );
|
inline void useFeed ( Cell* );
|
||||||
size_t findYSpin ();
|
size_t findYSpin ();
|
||||||
void addFeeds ();
|
void addFeeds ();
|
||||||
|
@ -96,6 +107,7 @@ namespace Etesian {
|
||||||
coloquinte::netlist _circuit;
|
coloquinte::netlist _circuit;
|
||||||
coloquinte::placement_t _placementLB;
|
coloquinte::placement_t _placementLB;
|
||||||
coloquinte::placement_t _placementUB;
|
coloquinte::placement_t _placementUB;
|
||||||
|
coloquinte::density_restrictions _densityLimits;
|
||||||
std::unordered_map<string,unsigned int> _cellsToIds;
|
std::unordered_map<string,unsigned int> _cellsToIds;
|
||||||
std::vector<Instance*> _idsToInsts;
|
std::vector<Instance*> _idsToInsts;
|
||||||
Hurricane::CellWidget* _cellWidget;
|
Hurricane::CellWidget* _cellWidget;
|
||||||
|
@ -113,8 +125,8 @@ namespace Etesian {
|
||||||
EtesianEngine& operator= ( const EtesianEngine& );
|
EtesianEngine& operator= ( const EtesianEngine& );
|
||||||
private:
|
private:
|
||||||
void _updatePlacement ( const coloquinte::placement_t& );
|
void _updatePlacement ( const coloquinte::placement_t& );
|
||||||
void _progressReport1 ( time_t startTime, string label ) const;
|
void _progressReport1 ( string label ) const;
|
||||||
void _progressReport2 ( time_t startTime, string label ) const;
|
void _progressReport2 ( string label ) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -126,6 +138,7 @@ namespace Etesian {
|
||||||
inline Effort EtesianEngine::getPlaceEffort () const { return getConfiguration()->getPlaceEffort(); }
|
inline Effort EtesianEngine::getPlaceEffort () const { return getConfiguration()->getPlaceEffort(); }
|
||||||
inline GraphicUpdate EtesianEngine::getUpdateConf () const { return getConfiguration()->getUpdateConf(); }
|
inline GraphicUpdate EtesianEngine::getUpdateConf () const { return getConfiguration()->getUpdateConf(); }
|
||||||
inline Density EtesianEngine::getSpreadingConf () const { return getConfiguration()->getSpreadingConf(); }
|
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::getSpaceMargin () const { return getConfiguration()->getSpaceMargin(); }
|
||||||
inline double EtesianEngine::getAspectRatio () const { return getConfiguration()->getAspectRatio(); }
|
inline double EtesianEngine::getAspectRatio () const { return getConfiguration()->getAspectRatio(); }
|
||||||
inline void EtesianEngine::useFeed ( Cell* cell ) { _feedCells.useFeed(cell); }
|
inline void EtesianEngine::useFeed ( Cell* cell ) { _feedCells.useFeed(cell); }
|
||||||
|
|
|
@ -545,6 +545,33 @@ namespace Katabatic {
|
||||||
return (float)( _box.getWidth () / Session::getPitch(2) + 1 );
|
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
|
float GCell::getDensity ( unsigned int flags ) const
|
||||||
{
|
{
|
||||||
|
@ -553,29 +580,9 @@ namespace Katabatic {
|
||||||
float density = 0.0;
|
float density = 0.0;
|
||||||
|
|
||||||
if (getGCellGrid()->getDensityMode() == GCellGrid::AverageHVDensity) {
|
if (getGCellGrid()->getDensityMode() == GCellGrid::AverageHVDensity) {
|
||||||
// Average density of all layers mixeds together.
|
density = getAverageHVDensity();
|
||||||
for ( size_t i=0 ; i<_depth ; i++ )
|
|
||||||
density += _densities[i];
|
|
||||||
|
|
||||||
//density = roundfp ( density/((float)(_depth-_pinDepth)) );
|
|
||||||
density = density/((float)(_depth-_pinDepth));
|
|
||||||
} else if (getGCellGrid()->getDensityMode() == GCellGrid::MaxHVDensity) {
|
} else if (getGCellGrid()->getDensityMode() == GCellGrid::MaxHVDensity) {
|
||||||
// Maximum density between all horizontal vs. all vertical layers.
|
density = getMaxHVDensity();
|
||||||
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;
|
|
||||||
} else if (getGCellGrid()->getDensityMode() == GCellGrid::AverageHDensity) {
|
} else if (getGCellGrid()->getDensityMode() == GCellGrid::AverageHDensity) {
|
||||||
// Average density between all horizontal layers.
|
// Average density between all horizontal layers.
|
||||||
size_t hplanes = 0;
|
size_t hplanes = 0;
|
||||||
|
|
|
@ -140,6 +140,8 @@ namespace Katabatic {
|
||||||
float getHCapacity () const;
|
float getHCapacity () const;
|
||||||
float getVCapacity () const;
|
float getVCapacity () const;
|
||||||
float getDensity ( unsigned int flags=0 ) const;
|
float getDensity ( unsigned int flags=0 ) const;
|
||||||
|
float getAverageHVDensity () const;
|
||||||
|
float getMaxHVDensity () const;
|
||||||
inline float getCDensity ( unsigned int flags=0 ) const;
|
inline float getCDensity ( unsigned int flags=0 ) const;
|
||||||
inline float getWDensity ( unsigned int depth, unsigned int flags=0 ) const;
|
inline float getWDensity ( unsigned int depth, unsigned int flags=0 ) const;
|
||||||
inline DbU::Unit getBlockage ( unsigned int depth ) const;
|
inline DbU::Unit getBlockage ( unsigned int depth ) const;
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include "vlsisapd/utilities/Path.h"
|
#include "vlsisapd/utilities/Path.h"
|
||||||
#include "hurricane/DebugSession.h"
|
#include "hurricane/DebugSession.h"
|
||||||
|
#include "hurricane/UpdateSession.h"
|
||||||
#include "hurricane/Bug.h"
|
#include "hurricane/Bug.h"
|
||||||
#include "hurricane/Error.h"
|
#include "hurricane/Error.h"
|
||||||
#include "hurricane/Warning.h"
|
#include "hurricane/Warning.h"
|
||||||
|
@ -176,7 +177,6 @@ namespace Kite {
|
||||||
return kite;
|
return kite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void KiteEngine::_preDestroy ()
|
void KiteEngine::_preDestroy ()
|
||||||
{
|
{
|
||||||
ltrace(90) << "KiteEngine::_preDestroy()" << endl;
|
ltrace(90) << "KiteEngine::_preDestroy()" << endl;
|
||||||
|
@ -208,6 +208,41 @@ namespace Kite {
|
||||||
ltraceout(90);
|
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<Contact*> contactPointers;
|
||||||
|
forEach(Component*, icom, (*inet)->getComponents()){
|
||||||
|
Contact * contact = dynamic_cast<Contact*>(*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<Component*> compPointers;
|
||||||
|
forEach(Component*, icom, (*inet)->getComponents()){
|
||||||
|
Horizontal * h = dynamic_cast<Horizontal*>(*icom);
|
||||||
|
if(h){
|
||||||
|
compPointers.push_back(h);
|
||||||
|
}
|
||||||
|
Vertical * v = dynamic_cast<Vertical*>(*icom);
|
||||||
|
if(v){
|
||||||
|
compPointers.push_back(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(Component* comp : compPointers)
|
||||||
|
comp->destroy();
|
||||||
|
}
|
||||||
|
UpdateSession::close();
|
||||||
|
}
|
||||||
|
|
||||||
KiteEngine::~KiteEngine ()
|
KiteEngine::~KiteEngine ()
|
||||||
{ delete _configuration; }
|
{ delete _configuration; }
|
||||||
|
|
|
@ -63,6 +63,7 @@ namespace Kite {
|
||||||
static const Name& staticGetName ();
|
static const Name& staticGetName ();
|
||||||
static KiteEngine* create ( Cell* );
|
static KiteEngine* create ( Cell* );
|
||||||
static KiteEngine* get ( const Cell* );
|
static KiteEngine* get ( const Cell* );
|
||||||
|
static void wipeOutRouting ( Cell* );
|
||||||
public:
|
public:
|
||||||
inline bool useClockTree () const;
|
inline bool useClockTree () const;
|
||||||
inline CellViewer* getViewer () const;
|
inline CellViewer* getViewer () const;
|
||||||
|
|
|
@ -33,7 +33,15 @@
|
||||||
find_package(KITE REQUIRED)
|
find_package(KITE REQUIRED)
|
||||||
#find_package(EQUINOX REQUIRED)
|
#find_package(EQUINOX REQUIRED)
|
||||||
#find_package(SOLSTICE 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(src)
|
||||||
add_subdirectory(python)
|
add_subdirectory(python)
|
||||||
add_subdirectory(cmake_modules)
|
add_subdirectory(cmake_modules)
|
||||||
|
|
Loading…
Reference in New Issue