Rewrite of the Etesian engine to run the new placer

This commit is contained in:
Gabriel Gouvine 2023-05-19 17:31:26 +02:00
parent a9f55021fd
commit c0b4aad02b
4 changed files with 139 additions and 379 deletions

@ -1 +1 @@
Subproject commit 068689b3eea8d2a5b47ada054fba828209897515
Subproject commit ea12145d338238d3c92c6863a164d3069560c42e

View File

@ -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

View File

@ -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

View File

@ -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;
};