Rewrite of the Etesian engine to run the new placer
This commit is contained in:
parent
a9f55021fd
commit
c0b4aad02b
|
@ -1 +1 @@
|
|||
Subproject commit 068689b3eea8d2a5b47ada054fba828209897515
|
||||
Subproject commit ea12145d338238d3c92c6863a164d3069560c42e
|
|
@ -18,9 +18,6 @@
|
|||
#include <sstream>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include "coloquinte/circuit.hxx"
|
||||
#include "coloquinte/circuit_helper.hxx"
|
||||
#include "coloquinte/legalizer.hxx"
|
||||
#include "hurricane/configuration/Configuration.h"
|
||||
#include "hurricane/utilities/Dots.h"
|
||||
#include "hurricane/DebugSession.h"
|
||||
|
@ -55,10 +52,8 @@ namespace {
|
|||
|
||||
using namespace std;
|
||||
using namespace Hurricane;
|
||||
using coloquinte::int_t;
|
||||
using coloquinte::float_t;
|
||||
using coloquinte::point;
|
||||
using Etesian::EtesianEngine;
|
||||
using coloquinte::CellOrientation;
|
||||
|
||||
// Options for both placers
|
||||
unsigned const SteinerModel = 0x0001;
|
||||
|
@ -156,8 +151,8 @@ namespace {
|
|||
}
|
||||
|
||||
|
||||
Transformation toTransformation ( point<int_t> position
|
||||
, point<bool> orientation
|
||||
Transformation toTransformation ( coloquinte::Point position
|
||||
, coloquinte::CellOrientation orientation
|
||||
, Cell* model
|
||||
, DbU::Unit hpitch
|
||||
, DbU::Unit vpitch
|
||||
|
@ -169,18 +164,44 @@ namespace {
|
|||
Box cellBox = model->getAbutmentBox();
|
||||
Transformation::Orientation orient = Transformation::Orientation::ID;
|
||||
|
||||
if ( not orientation.x and orientation.y) {
|
||||
tx += cellBox.getWidth();
|
||||
orient = Transformation::Orientation::MX;
|
||||
} else if ( orientation.x and not orientation.y) {
|
||||
ty += cellBox.getHeight();
|
||||
orient = Transformation::Orientation::MY;
|
||||
} else if ( not orientation.x and not orientation.y) {
|
||||
tx += cellBox.getWidth();
|
||||
ty += cellBox.getHeight();
|
||||
orient = Transformation::Orientation::R2;
|
||||
switch (orientation) {
|
||||
case CellOrientation::N:
|
||||
orient = Transformation::Orientation::ID;
|
||||
break;
|
||||
case CellOrientation::R180:
|
||||
ty += cellBox.getHeight();
|
||||
tx += cellBox.getWidth();
|
||||
orient = Transformation::Orientation::R2;
|
||||
break;
|
||||
case CellOrientation::MY:
|
||||
orient = Transformation::Orientation::MY;
|
||||
ty += cellBox.getHeight();
|
||||
break;
|
||||
case CellOrientation::MX:
|
||||
orient = Transformation::Orientation::MX;
|
||||
ty += cellBox.getWidth();
|
||||
break;
|
||||
/*
|
||||
case CellOrientation::R90:
|
||||
orient = Transformation::Orientation::R1;
|
||||
// TODO
|
||||
break;
|
||||
case CellOrientation::R270:
|
||||
orient = Transformation::Orientation::R3;
|
||||
// TODO
|
||||
break;
|
||||
case CellOrientation::MX90:
|
||||
orient = Transformation::Orientation::XR;
|
||||
// TODO
|
||||
break;
|
||||
case CellOrientation::MY90:
|
||||
orient = Transformation::Orientation::YR;
|
||||
// TODO
|
||||
break;
|
||||
*/
|
||||
default:
|
||||
throw Error("Unsupported orientation");
|
||||
}
|
||||
|
||||
return Transformation( tx, ty, orient );
|
||||
}
|
||||
|
||||
|
@ -264,18 +285,6 @@ namespace Etesian {
|
|||
using CRL::Measures;
|
||||
using CRL::MeasuresSet;
|
||||
using CRL::CatalogExtension;
|
||||
using coloquinte::index_t;
|
||||
using coloquinte::capacity_t;
|
||||
using coloquinte::int_t;
|
||||
using coloquinte::float_t;
|
||||
using coloquinte::point;
|
||||
using coloquinte::box;
|
||||
using coloquinte::Movability;
|
||||
using coloquinte::temporary_cell;
|
||||
using coloquinte::temporary_net;
|
||||
using coloquinte::temporary_pin;
|
||||
using coloquinte::netlist;
|
||||
using coloquinte::placement_t;
|
||||
|
||||
const char* missingEtesian =
|
||||
"%s :\n\n"
|
||||
|
@ -308,7 +317,7 @@ namespace Etesian {
|
|||
, _circuit (NULL)
|
||||
, _placementLB (NULL)
|
||||
, _placementUB (NULL)
|
||||
, _densityLimits(NULL)
|
||||
//, _densityLimits(NULL)
|
||||
, _netsToIds ()
|
||||
, _instsToIds ()
|
||||
, _idsToInsts ()
|
||||
|
@ -447,7 +456,7 @@ namespace Etesian {
|
|||
delete _circuit;
|
||||
delete _placementLB;
|
||||
delete _placementUB;
|
||||
delete _densityLimits;
|
||||
//delete _densityLimits;
|
||||
|
||||
NetsToIds emptyNetsToIds;
|
||||
_netsToIds.swap( emptyNetsToIds );
|
||||
|
@ -465,7 +474,7 @@ namespace Etesian {
|
|||
_circuit = NULL;
|
||||
_placementLB = NULL;
|
||||
_placementUB = NULL;
|
||||
_densityLimits = NULL;
|
||||
//_densityLimits = NULL;
|
||||
_diodeCount = 0;
|
||||
}
|
||||
|
||||
|
@ -811,10 +820,15 @@ namespace Etesian {
|
|||
|
||||
// Coloquinte circuit description data-structures.
|
||||
// One dummy fixed instance at the end
|
||||
vector<Transformation> idsToTransf ( instancesNb+1 );
|
||||
vector<temporary_cell> instances ( instancesNb+1 );
|
||||
vector< point<int_t> > positions ( instancesNb+1 );
|
||||
vector< point<bool> > orientations( instancesNb+1, point<bool>(true, true) );
|
||||
|
||||
_circuit = new coloquinte::Circuit( instancesNb+1 );
|
||||
vector<int> cellX( instancesNb+1 );
|
||||
vector<int> cellY( instancesNb+1 );
|
||||
vector<coloquinte::CellOrientation> orient( instancesNb+1 );
|
||||
vector<int> cellWidth( instancesNb+1 );
|
||||
vector<int> cellHeight( instancesNb+1 );
|
||||
vector<bool> cellIsFixed( instancesNb+1 );
|
||||
vector<bool> cellIsObstruction( instancesNb+1 );
|
||||
|
||||
cmess1 << ::Dots::asUInt( " - Number of instances ", instancesNb ) << endl;
|
||||
if (instancesNb) {
|
||||
|
@ -837,7 +851,7 @@ namespace Etesian {
|
|||
getCell()->flattenNets( NULL, _excludedNets, Cell::Flags::NoClockFlatten );
|
||||
|
||||
bool tooManyInstances = false;
|
||||
index_t instanceId = 0;
|
||||
int instanceId = 0;
|
||||
if (getBlockInstance()) {
|
||||
for ( Instance* instance : getCell()->getInstances() ) {
|
||||
if (instance == getBlockInstance()) continue;
|
||||
|
@ -845,17 +859,18 @@ namespace Etesian {
|
|||
Box overlapAb = topAb.getIntersection( instance->getAbutmentBox() );
|
||||
if (not overlapAb.isEmpty()) {
|
||||
// Upper rounded
|
||||
int_t xsize = (overlapAb.getWidth () + vpitch - 1) / vpitch;
|
||||
int_t ysize = (overlapAb.getHeight() + hpitch - 1) / hpitch;
|
||||
int xsize = (overlapAb.getWidth () + vpitch - 1) / vpitch;
|
||||
int ysize = (overlapAb.getHeight() + hpitch - 1) / hpitch;
|
||||
// Lower rounded
|
||||
int_t xpos = overlapAb.getXMin() / vpitch;
|
||||
int_t ypos = overlapAb.getYMin() / hpitch;
|
||||
int xpos = overlapAb.getXMin() / vpitch;
|
||||
int ypos = overlapAb.getYMin() / hpitch;
|
||||
|
||||
instances[instanceId].size = point<int_t>( xsize, ysize );
|
||||
instances[instanceId].list_index = instanceId;
|
||||
instances[instanceId].area = static_cast<capacity_t>(xsize) * static_cast<capacity_t>(ysize);
|
||||
positions[instanceId] = point<int_t>( xpos, ypos );
|
||||
instances[instanceId].attributes = 0;
|
||||
cellX[instanceId] = xpos;
|
||||
cellY[instanceId] = ypos;
|
||||
cellWidth[instanceId] = xsize;
|
||||
cellHeight[instanceId] = ysize;
|
||||
cellIsFixed[instanceId] = true;
|
||||
cellIsObstruction[instanceId] = true;
|
||||
|
||||
_instsToIds.insert( make_pair(instance,instanceId) );
|
||||
_idsToInsts.push_back( make_tuple(instance,vector<RoutingPad*>()) );
|
||||
|
@ -904,11 +919,11 @@ namespace Etesian {
|
|||
instanceTransf.applyOn( instanceAb );
|
||||
|
||||
// Upper rounded
|
||||
int_t xsize = (instanceAb.getWidth () + vpitch - 1) / vpitch;
|
||||
int_t ysize = (instanceAb.getHeight() + hpitch - 1) / hpitch;
|
||||
int xsize = (instanceAb.getWidth () + vpitch - 1) / vpitch;
|
||||
int ysize = (instanceAb.getHeight() + hpitch - 1) / hpitch;
|
||||
// Lower rounded
|
||||
int_t xpos = instanceAb.getXMin() / vpitch;
|
||||
int_t ypos = instanceAb.getYMin() / hpitch;
|
||||
int xpos = instanceAb.getXMin() / vpitch;
|
||||
int ypos = instanceAb.getYMin() / hpitch;
|
||||
|
||||
//if (xsize < 6) xsize += 2;
|
||||
|
||||
|
@ -926,18 +941,17 @@ namespace Etesian {
|
|||
if (isFlexLib and not instance->isFixed() and (masterName == "buf_x8"))
|
||||
++xsize;
|
||||
|
||||
instances[instanceId].size = point<int_t>( xsize, ysize );
|
||||
instances[instanceId].list_index = instanceId;
|
||||
instances[instanceId].area = static_cast<capacity_t>(xsize) * static_cast<capacity_t>(ysize);
|
||||
positions[instanceId] = point<int_t>( xpos, ypos );
|
||||
cellX[instanceId] = xpos;
|
||||
cellY[instanceId] = ypos;
|
||||
cellWidth[instanceId] = xsize;
|
||||
cellHeight[instanceId] = ysize;
|
||||
|
||||
if ( not instance->isFixed() and instance->isTerminalNetlist() ) {
|
||||
instances[instanceId].attributes = coloquinte::XMovable
|
||||
|coloquinte::YMovable
|
||||
|coloquinte::XFlippable
|
||||
|coloquinte::YFlippable;
|
||||
cellIsFixed[instanceId] = false;
|
||||
cellIsObstruction[instanceId] = false;
|
||||
} else {
|
||||
instances[instanceId].attributes = 0;
|
||||
cellIsFixed[instanceId] = true;
|
||||
cellIsObstruction[instanceId] = true;
|
||||
// cerr << endl;
|
||||
// cerr << "FIXED " << instance << endl;
|
||||
// cerr << " id=" << instanceId
|
||||
|
@ -965,11 +979,12 @@ namespace Etesian {
|
|||
}
|
||||
|
||||
// Dummy fixed instance at the end
|
||||
instances[instanceId].size = point<int_t>( 0, 0 );
|
||||
instances[instanceId].list_index = instanceId;
|
||||
instances[instanceId].area = 0;
|
||||
positions[instanceId] = point<int_t>( 0, 0 );
|
||||
instances[instanceId].attributes = 0;
|
||||
cellX[instanceId] = 0;
|
||||
cellY[instanceId] = 0;
|
||||
cellWidth[instanceId] = 0;
|
||||
cellHeight[instanceId] = 0;
|
||||
cellIsFixed[instanceId] = true;
|
||||
cellIsObstruction[instanceId] = true;
|
||||
|
||||
dots.finish( Dots::Reset|Dots::FirstDot );
|
||||
|
||||
|
@ -993,8 +1008,6 @@ namespace Etesian {
|
|||
|
||||
cmess1 << " - Converting " << netsNb << " nets" << endl;
|
||||
|
||||
vector<temporary_net> nets ( netsNb );
|
||||
vector<temporary_pin> pins;
|
||||
_idsToNets.resize( netsNb );
|
||||
|
||||
unsigned int netId = 0;
|
||||
|
@ -1012,11 +1025,9 @@ namespace Etesian {
|
|||
|
||||
_netsToIds.insert( make_pair(net,netId) );
|
||||
_idsToNets[netId] = make_tuple( net, _instsToIds.size(), 0 );
|
||||
nets[netId] = temporary_net( netId, 1 );
|
||||
|
||||
//cerr << "+ " << net << endl;
|
||||
|
||||
string topCellInstancePin = getString(getCell()->getName()) + ":C";
|
||||
vector<int> netCells, pinX, pinY;
|
||||
|
||||
for ( RoutingPad* rp : net->getRoutingPads() ) {
|
||||
Path path = rp->getOccurrence().getPath();
|
||||
|
@ -1024,10 +1035,12 @@ namespace Etesian {
|
|||
if (pin) {
|
||||
if (path.isEmpty()) {
|
||||
Point pt = rp->getCenter();
|
||||
int_t xpin = pt.getX() / vpitch;
|
||||
int_t ypin = pt.getY() / hpitch;
|
||||
int xpin = pt.getX() / vpitch;
|
||||
int ypin = pt.getY() / hpitch;
|
||||
// Dummy last instance
|
||||
pins.push_back( temporary_pin( point<int_t>(xpin,ypin), instanceId, netId ) );
|
||||
pinX.push_back(xpin);
|
||||
pinY.push_back(ypin);
|
||||
netCells.push_back(instanceId);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
@ -1054,8 +1067,8 @@ namespace Etesian {
|
|||
string insName = extractInstanceName( rp );
|
||||
Point offset = extractRpOffset ( rp );
|
||||
|
||||
int_t xpin = offset.getX() / vpitch;
|
||||
int_t ypin = offset.getY() / hpitch;
|
||||
int xpin = offset.getX() / vpitch;
|
||||
int ypin = offset.getY() / hpitch;
|
||||
|
||||
auto iid = _instsToIds.find( instance );
|
||||
if (iid == _instsToIds.end()) {
|
||||
|
@ -1063,7 +1076,9 @@ namespace Etesian {
|
|||
cerr << Error( "Unable to lookup instance \"%s\".", insName.c_str() ) << endl;
|
||||
}
|
||||
} else {
|
||||
pins.push_back( temporary_pin( point<int_t>(xpin,ypin), (*iid).second, netId ) );
|
||||
pinX.push_back(xpin);
|
||||
pinY.push_back(ypin);
|
||||
netCells.push_back((*iid).second);
|
||||
Net* rpNet = NULL;
|
||||
Plug* plug = dynamic_cast<Plug*>( rp->getPlugOccurrence().getEntity() );
|
||||
if (plug) {
|
||||
|
@ -1074,6 +1089,7 @@ namespace Etesian {
|
|||
}
|
||||
}
|
||||
}
|
||||
_circuit->addNet(netCells, pinX, pinY);
|
||||
|
||||
netId++;
|
||||
}
|
||||
|
@ -1084,18 +1100,16 @@ namespace Etesian {
|
|||
if (_bloatCells.getSelected()->getName() != "disabled")
|
||||
cmess2 << stdCellSizes.toString(1) << endl;
|
||||
|
||||
_densityLimits = new coloquinte::density_restrictions ();
|
||||
_surface = new box<int_t>( (int_t)(topAb.getXMin() / vpitch)
|
||||
, (int_t)(topAb.getXMax() / vpitch)
|
||||
, (int_t)(topAb.getYMin() / hpitch)
|
||||
, (int_t)(topAb.getYMax() / hpitch)
|
||||
);
|
||||
_circuit = new netlist( instances, nets, pins );
|
||||
_circuit->selfcheck();
|
||||
_placementLB = new coloquinte::placement_t ();
|
||||
_placementLB->positions_ = positions;
|
||||
_placementLB->orientations_ = orientations;
|
||||
_placementUB = new coloquinte::placement_t ( *_placementLB );
|
||||
//_densityLimits = new coloquinte::density_restrictions ();
|
||||
_surface = new coloquinte::Rectangle( (int)(topAb.getXMin() / vpitch)
|
||||
, (int)(topAb.getXMax() / vpitch)
|
||||
, (int)(topAb.getYMin() / hpitch)
|
||||
, (int)(topAb.getYMax() / hpitch)
|
||||
);
|
||||
_circuit->check();
|
||||
// TODO: define the rows
|
||||
_placementLB = new coloquinte::PlacementSolution ();
|
||||
_placementUB = new coloquinte::PlacementSolution ( *_placementLB );
|
||||
|
||||
return instancesNb-fixedNb;
|
||||
}
|
||||
|
@ -1139,216 +1153,38 @@ namespace Etesian {
|
|||
}
|
||||
|
||||
|
||||
void EtesianEngine::preplace ()
|
||||
void EtesianEngine::globalPlace ( unsigned options )
|
||||
{
|
||||
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(" [---]" );
|
||||
_circuit->placeGlobal(getPlaceEffort());
|
||||
// TODO: add callback for placement update + antenna effect
|
||||
*_placementUB = _circuit->solution();
|
||||
_updatePlacement(_placementUB);
|
||||
}
|
||||
|
||||
|
||||
void EtesianEngine::roughLegalize ( float minDisruption, unsigned options )
|
||||
void EtesianEngine::detailedPlace ( 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::globalPlace ( float initPenalty
|
||||
, float minDisruption
|
||||
, float targetImprovement
|
||||
, float minInc
|
||||
, float maxInc
|
||||
, unsigned options )
|
||||
{
|
||||
using namespace coloquinte::gp;
|
||||
|
||||
bool antennaDone = false;
|
||||
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(3) << setfill('0') << i << setfill(' ') << "] "
|
||||
<< setw(7) << fixed << setprecision(1) << linearDisruption << "% 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( _placementUB );
|
||||
|
||||
// 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;
|
||||
|
||||
if ((linearDisruption < getAntennaInsertThreshold()*100.0) and not antennaDone) {
|
||||
//antennaProtect();
|
||||
antennaDone = true;
|
||||
}
|
||||
// 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() / getSliceStep();
|
||||
roughLegalize(sliceHeight, options);
|
||||
// TODO: for uniform density distribution, add some margin to the cell sizes so we don't disrupt it during detailed placement
|
||||
|
||||
for ( int i=0; i<iterations; ++i ){
|
||||
ostringstream label;
|
||||
label.str("");
|
||||
label << " [" << setw(3) << setfill('0') << i << setfill(' ') << "]";
|
||||
|
||||
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 ." );
|
||||
}
|
||||
}
|
||||
_circuit->placeDetailed(getPlaceEffort());
|
||||
*_placementUB = _circuit->solution();
|
||||
// TODO: add callback for placement update + antenna effect
|
||||
*_placementLB = *_placementUB; // In case we run other passes
|
||||
_updatePlacement( _placementUB, FinalStage );
|
||||
_updatePlacement(_placementUB);
|
||||
}
|
||||
|
||||
|
||||
void EtesianEngine::antennaProtect ()
|
||||
{
|
||||
// TODO
|
||||
/*
|
||||
DbU::Unit maxWL = getAntennaGateMaxWL();
|
||||
if (not maxWL) return;
|
||||
|
||||
cmess1 << " o Inserting antenna effect protection." << endl;
|
||||
uint32_t count = 0;
|
||||
int_t diodeWidth = _diodeCell->getAbutmentBox().getWidth() / getSliceStep();
|
||||
int diodeWidth = _diodeCell->getAbutmentBox().getWidth() / getSliceStep();
|
||||
cdebug_log(122,0) << "diodeWidth=" << diodeWidth << "p" << endl;
|
||||
|
||||
for ( coloquinte::index_t inet=0 ; inet < _circuit->net_cnt() ; ++inet ) {
|
||||
for ( coloquinte::int inet=0 ; inet < _circuit->nbNets() ; ++inet ) {
|
||||
DbU::Unit rsmt = toDbU( coloquinte::get_RSMT_length( *_circuit, *_placementUB, inet ) );
|
||||
Net* net = std::get<0>( _idsToNets[inet] );
|
||||
|
||||
|
@ -1371,7 +1207,7 @@ namespace Etesian {
|
|||
if (iinst == _instsToIds.end()) continue;
|
||||
|
||||
std::get<1>( _idsToInsts[ (*iinst).second ] ).push_back( rp );
|
||||
coloquinte::point<int_t> cell_size = _circuit->get_cell_size( (*iinst).second );
|
||||
coloquinte::point<int> cell_size = _circuit->get_cell_size( (*iinst).second );
|
||||
cell_size.x += 2*diodeWidth;
|
||||
_circuit->set_cell_size( (*iinst).second, cell_size );
|
||||
++count;
|
||||
|
@ -1379,6 +1215,7 @@ namespace Etesian {
|
|||
}
|
||||
}
|
||||
cmess1 << ::Dots::asInt( " - Inserted diodes", count ) << endl;
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
@ -1414,20 +1251,11 @@ namespace Etesian {
|
|||
//findYSpin();
|
||||
if (not toColoquinte()) return;
|
||||
|
||||
Effort placementEffort = getPlaceEffort();
|
||||
GraphicUpdate placementUpdate = getUpdateConf();
|
||||
Density densityConf = getSpreadingConf();
|
||||
double sliceHeight = getSliceHeight() / getSliceStep();
|
||||
|
||||
cmess1 << " o Running Coloquinte." << endl;
|
||||
cmess2 << " - Computing initial placement..." << endl;
|
||||
cmess2 << right;
|
||||
startMeasures();
|
||||
|
||||
preplace();
|
||||
|
||||
float_t minPenaltyIncrease, maxPenaltyIncrease, targetImprovement;
|
||||
int detailedIterations, detailedEffort;
|
||||
unsigned globalOptions=0, detailedOptions=0;
|
||||
|
||||
if (placementUpdate == UpdateAll) {
|
||||
|
@ -1441,37 +1269,11 @@ namespace Etesian {
|
|||
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;
|
||||
}
|
||||
|
||||
cmess1 << " o Global placement." << endl;
|
||||
globalPlace(minPenaltyIncrease, sliceHeight, targetImprovement, minPenaltyIncrease, maxPenaltyIncrease, globalOptions);
|
||||
globalPlace(globalOptions);
|
||||
|
||||
cmess1 << " o Detailed Placement." << endl;
|
||||
detailedPlace(detailedIterations, detailedEffort, detailedOptions);
|
||||
detailedPlace(detailedOptions);
|
||||
|
||||
//toHurricane();
|
||||
//addFeeds();
|
||||
|
@ -1479,10 +1281,6 @@ namespace Etesian {
|
|||
cmess1 << " o Placement finished." << endl;
|
||||
stopMeasures();
|
||||
printMeasures();
|
||||
cmess1 << ::Dots::asString
|
||||
( " - HPWL", DbU::getValueString( (DbU::Unit)coloquinte::gp::get_HPWL_wirelength(*_circuit,*_placementUB )*getSliceStep() ) ) << endl;
|
||||
cmess1 << ::Dots::asString
|
||||
( " - RMST", DbU::getValueString( (DbU::Unit)coloquinte::gp::get_RSMT_wirelength(*_circuit,*_placementUB )*getSliceStep() ) ) << endl;
|
||||
addMeasure<double>( "placeT", getTimer().getCombTime() );
|
||||
|
||||
UpdateSession::open();
|
||||
|
@ -1501,44 +1299,7 @@ namespace Etesian {
|
|||
UpdateSession::close();
|
||||
}
|
||||
|
||||
|
||||
void EtesianEngine::_progressReport1 ( string label ) const
|
||||
{
|
||||
size_t w = label.size();
|
||||
string indent ( w, ' ' );
|
||||
if (not w) {
|
||||
label = string( 5, ' ' );
|
||||
indent = label;
|
||||
}
|
||||
|
||||
cmess2 << label
|
||||
<< " HPWL=" << setw(14) << DbU::getValueString(toDbU(coloquinte::gp::get_HPWL_wirelength( *_circuit, *_placementUB )))
|
||||
<< " RMST=" << setw(14) << DbU::getValueString(toDbU(coloquinte::gp::get_RSMT_wirelength( *_circuit, *_placementUB )))
|
||||
<< endl;
|
||||
cparanoid << indent
|
||||
<< " L-Dsrpt=" << setw(8) << coloquinte::gp::get_mean_linear_disruption ( *_circuit, *_placementLB, *_placementUB )
|
||||
<< " Q-Dsrpt=" << setw(8) << coloquinte::gp::get_mean_quadratic_disruption( *_circuit, *_placementLB, *_placementUB )
|
||||
<< endl;
|
||||
}
|
||||
|
||||
|
||||
void EtesianEngine::_progressReport2 ( string label ) const
|
||||
{
|
||||
size_t w = label.size();
|
||||
string indent ( w, ' ' );
|
||||
if (not w) {
|
||||
label = string( 5, ' ' );
|
||||
indent = label;
|
||||
}
|
||||
|
||||
cmess2 << label
|
||||
<< " HPWL=" << setw(14) << DbU::getValueString(toDbU(coloquinte::gp::get_HPWL_wirelength( *_circuit, *_placementLB )))
|
||||
<< " RMST=" << setw(14) << DbU::getValueString(toDbU(coloquinte::gp::get_RSMT_wirelength( *_circuit, *_placementLB )))
|
||||
<< endl;
|
||||
}
|
||||
|
||||
|
||||
void EtesianEngine::_updatePlacement ( const coloquinte::placement_t* placement, uint32_t flags )
|
||||
void EtesianEngine::_updatePlacement ( const coloquinte::PlacementSolution* placement, uint32_t flags )
|
||||
{
|
||||
UpdateSession::open();
|
||||
|
||||
|
@ -1568,9 +1329,9 @@ namespace Etesian {
|
|||
continue;
|
||||
|
||||
//uint32_t outputSide = getOutputSide( instance->getMasterCell() );
|
||||
point<int_t> position = placement->positions_[(*iid).second];
|
||||
Transformation cellTrans = toTransformation( position
|
||||
, placement->orientations_[(*iid).second]
|
||||
auto place = (*placement)[(*iid).second];
|
||||
Transformation cellTrans = toTransformation( place.position
|
||||
, place.orientation
|
||||
, instance->getMasterCell()
|
||||
, hpitch
|
||||
, vpitch
|
||||
|
|
|
@ -40,9 +40,9 @@ namespace Etesian {
|
|||
// Class : "Etesian::Configuration".
|
||||
|
||||
enum Effort { Fast =1
|
||||
, Standard=2
|
||||
, High =3
|
||||
, Extreme =4
|
||||
, Standard=3
|
||||
, High =6
|
||||
, Extreme =9
|
||||
};
|
||||
enum GraphicUpdate { UpdateAll =1
|
||||
, LowerBound=2
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
#include <tuple>
|
||||
#include <iostream>
|
||||
#include <unordered_map>
|
||||
#include "coloquinte/circuit.hxx"
|
||||
#include "coloquinte2/coloquinte.hpp"
|
||||
|
||||
#include "hurricane/Timer.h"
|
||||
#include "hurricane/Name.h"
|
||||
|
@ -131,10 +131,8 @@ namespace Etesian {
|
|||
inline Transformation toBlock ( const Transformation& ) const;
|
||||
void setPlaceArea ( const Box& );
|
||||
size_t 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 globalPlace ( unsigned options=0 );
|
||||
void detailedPlace ( unsigned options=0 );
|
||||
void antennaProtect ();
|
||||
void place ();
|
||||
uint32_t doHFNS ();
|
||||
|
@ -160,11 +158,12 @@ namespace Etesian {
|
|||
bool _flatDesign;
|
||||
Box _placeArea;
|
||||
std::vector<Box> _trackAvoids;
|
||||
coloquinte::box<coloquinte::int_t>* _surface;
|
||||
coloquinte::netlist* _circuit;
|
||||
coloquinte::placement_t* _placementLB;
|
||||
coloquinte::placement_t* _placementUB;
|
||||
coloquinte::density_restrictions* _densityLimits;
|
||||
coloquinte::Rectangle* _surface;
|
||||
coloquinte::Circuit* _circuit;
|
||||
coloquinte::PlacementSolution* _placementLB;
|
||||
coloquinte::PlacementSolution* _placementUB;
|
||||
// TODO
|
||||
// coloquinte::density_restrictions* _densityLimits;
|
||||
NetsToIds _netsToIds;
|
||||
InstancesToIds _instsToIds;
|
||||
std::vector<InstanceInfos> _idsToInsts;
|
||||
|
@ -195,7 +194,7 @@ namespace Etesian {
|
|||
private:
|
||||
inline uint32_t _getNewDiodeId ();
|
||||
Instance* _createDiode ( Cell* );
|
||||
void _updatePlacement ( const coloquinte::placement_t*, uint32_t flags=0 );
|
||||
void _updatePlacement ( const coloquinte::PlacementSolution*, uint32_t flags=0 );
|
||||
void _progressReport1 ( string label ) const;
|
||||
void _progressReport2 ( string label ) const;
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue