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 3830a90482
commit 1e71b5fb08
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 <sstream>
#include <fstream> #include <fstream>
#include <iomanip> #include <iomanip>
#include "coloquinte/circuit.hxx"
#include "coloquinte/circuit_helper.hxx"
#include "coloquinte/legalizer.hxx"
#include "hurricane/configuration/Configuration.h" #include "hurricane/configuration/Configuration.h"
#include "hurricane/utilities/Dots.h" #include "hurricane/utilities/Dots.h"
#include "hurricane/DebugSession.h" #include "hurricane/DebugSession.h"
@ -55,10 +52,8 @@ namespace {
using namespace std; using namespace std;
using namespace Hurricane; using namespace Hurricane;
using coloquinte::int_t;
using coloquinte::float_t;
using coloquinte::point;
using Etesian::EtesianEngine; using Etesian::EtesianEngine;
using coloquinte::CellOrientation;
// Options for both placers // Options for both placers
unsigned const SteinerModel = 0x0001; unsigned const SteinerModel = 0x0001;
@ -156,8 +151,8 @@ namespace {
} }
Transformation toTransformation ( point<int_t> position Transformation toTransformation ( coloquinte::Point position
, point<bool> orientation , coloquinte::CellOrientation orientation
, Cell* model , Cell* model
, DbU::Unit hpitch , DbU::Unit hpitch
, DbU::Unit vpitch , DbU::Unit vpitch
@ -169,18 +164,44 @@ namespace {
Box cellBox = model->getAbutmentBox(); Box cellBox = model->getAbutmentBox();
Transformation::Orientation orient = Transformation::Orientation::ID; Transformation::Orientation orient = Transformation::Orientation::ID;
if ( not orientation.x and orientation.y) { switch (orientation) {
tx += cellBox.getWidth(); case CellOrientation::N:
orient = Transformation::Orientation::MX; orient = Transformation::Orientation::ID;
} else if ( orientation.x and not orientation.y) { break;
case CellOrientation::R180:
ty += cellBox.getHeight(); ty += cellBox.getHeight();
orient = Transformation::Orientation::MY;
} else if ( not orientation.x and not orientation.y) {
tx += cellBox.getWidth(); tx += cellBox.getWidth();
ty += cellBox.getHeight();
orient = Transformation::Orientation::R2; 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 ); return Transformation( tx, ty, orient );
} }
@ -264,18 +285,6 @@ namespace Etesian {
using CRL::Measures; using CRL::Measures;
using CRL::MeasuresSet; using CRL::MeasuresSet;
using CRL::CatalogExtension; 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 = const char* missingEtesian =
"%s :\n\n" "%s :\n\n"
@ -308,7 +317,7 @@ namespace Etesian {
, _circuit (NULL) , _circuit (NULL)
, _placementLB (NULL) , _placementLB (NULL)
, _placementUB (NULL) , _placementUB (NULL)
, _densityLimits(NULL) //, _densityLimits(NULL)
, _netsToIds () , _netsToIds ()
, _instsToIds () , _instsToIds ()
, _idsToInsts () , _idsToInsts ()
@ -447,7 +456,7 @@ namespace Etesian {
delete _circuit; delete _circuit;
delete _placementLB; delete _placementLB;
delete _placementUB; delete _placementUB;
delete _densityLimits; //delete _densityLimits;
NetsToIds emptyNetsToIds; NetsToIds emptyNetsToIds;
_netsToIds.swap( emptyNetsToIds ); _netsToIds.swap( emptyNetsToIds );
@ -465,7 +474,7 @@ namespace Etesian {
_circuit = NULL; _circuit = NULL;
_placementLB = NULL; _placementLB = NULL;
_placementUB = NULL; _placementUB = NULL;
_densityLimits = NULL; //_densityLimits = NULL;
_diodeCount = 0; _diodeCount = 0;
} }
@ -811,10 +820,15 @@ namespace Etesian {
// Coloquinte circuit description data-structures. // Coloquinte circuit description data-structures.
// One dummy fixed instance at the end // One dummy fixed instance at the end
vector<Transformation> idsToTransf ( instancesNb+1 );
vector<temporary_cell> instances ( instancesNb+1 ); _circuit = new coloquinte::Circuit( instancesNb+1 );
vector< point<int_t> > positions ( instancesNb+1 ); vector<int> cellX( instancesNb+1 );
vector< point<bool> > orientations( instancesNb+1, point<bool>(true, true) ); 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; cmess1 << ::Dots::asUInt( " - Number of instances ", instancesNb ) << endl;
if (instancesNb) { if (instancesNb) {
@ -837,7 +851,7 @@ namespace Etesian {
getCell()->flattenNets( NULL, _excludedNets, Cell::Flags::NoClockFlatten ); getCell()->flattenNets( NULL, _excludedNets, Cell::Flags::NoClockFlatten );
bool tooManyInstances = false; bool tooManyInstances = false;
index_t instanceId = 0; int instanceId = 0;
if (getBlockInstance()) { if (getBlockInstance()) {
for ( Instance* instance : getCell()->getInstances() ) { for ( Instance* instance : getCell()->getInstances() ) {
if (instance == getBlockInstance()) continue; if (instance == getBlockInstance()) continue;
@ -845,17 +859,18 @@ namespace Etesian {
Box overlapAb = topAb.getIntersection( instance->getAbutmentBox() ); Box overlapAb = topAb.getIntersection( instance->getAbutmentBox() );
if (not overlapAb.isEmpty()) { if (not overlapAb.isEmpty()) {
// Upper rounded // Upper rounded
int_t xsize = (overlapAb.getWidth () + vpitch - 1) / vpitch; int xsize = (overlapAb.getWidth () + vpitch - 1) / vpitch;
int_t ysize = (overlapAb.getHeight() + hpitch - 1) / hpitch; int ysize = (overlapAb.getHeight() + hpitch - 1) / hpitch;
// Lower rounded // Lower rounded
int_t xpos = overlapAb.getXMin() / vpitch; int xpos = overlapAb.getXMin() / vpitch;
int_t ypos = overlapAb.getYMin() / hpitch; int ypos = overlapAb.getYMin() / hpitch;
instances[instanceId].size = point<int_t>( xsize, ysize ); cellX[instanceId] = xpos;
instances[instanceId].list_index = instanceId; cellY[instanceId] = ypos;
instances[instanceId].area = static_cast<capacity_t>(xsize) * static_cast<capacity_t>(ysize); cellWidth[instanceId] = xsize;
positions[instanceId] = point<int_t>( xpos, ypos ); cellHeight[instanceId] = ysize;
instances[instanceId].attributes = 0; cellIsFixed[instanceId] = true;
cellIsObstruction[instanceId] = true;
_instsToIds.insert( make_pair(instance,instanceId) ); _instsToIds.insert( make_pair(instance,instanceId) );
_idsToInsts.push_back( make_tuple(instance,vector<RoutingPad*>()) ); _idsToInsts.push_back( make_tuple(instance,vector<RoutingPad*>()) );
@ -904,11 +919,11 @@ namespace Etesian {
instanceTransf.applyOn( instanceAb ); instanceTransf.applyOn( instanceAb );
// Upper rounded // Upper rounded
int_t xsize = (instanceAb.getWidth () + vpitch - 1) / vpitch; int xsize = (instanceAb.getWidth () + vpitch - 1) / vpitch;
int_t ysize = (instanceAb.getHeight() + hpitch - 1) / hpitch; int ysize = (instanceAb.getHeight() + hpitch - 1) / hpitch;
// Lower rounded // Lower rounded
int_t xpos = instanceAb.getXMin() / vpitch; int xpos = instanceAb.getXMin() / vpitch;
int_t ypos = instanceAb.getYMin() / hpitch; int ypos = instanceAb.getYMin() / hpitch;
//if (xsize < 6) xsize += 2; //if (xsize < 6) xsize += 2;
@ -926,18 +941,17 @@ namespace Etesian {
if (isFlexLib and not instance->isFixed() and (masterName == "buf_x8")) if (isFlexLib and not instance->isFixed() and (masterName == "buf_x8"))
++xsize; ++xsize;
instances[instanceId].size = point<int_t>( xsize, ysize ); cellX[instanceId] = xpos;
instances[instanceId].list_index = instanceId; cellY[instanceId] = ypos;
instances[instanceId].area = static_cast<capacity_t>(xsize) * static_cast<capacity_t>(ysize); cellWidth[instanceId] = xsize;
positions[instanceId] = point<int_t>( xpos, ypos ); cellHeight[instanceId] = ysize;
if ( not instance->isFixed() and instance->isTerminalNetlist() ) { if ( not instance->isFixed() and instance->isTerminalNetlist() ) {
instances[instanceId].attributes = coloquinte::XMovable cellIsFixed[instanceId] = false;
|coloquinte::YMovable cellIsObstruction[instanceId] = false;
|coloquinte::XFlippable
|coloquinte::YFlippable;
} else { } else {
instances[instanceId].attributes = 0; cellIsFixed[instanceId] = true;
cellIsObstruction[instanceId] = true;
// cerr << endl; // cerr << endl;
// cerr << "FIXED " << instance << endl; // cerr << "FIXED " << instance << endl;
// cerr << " id=" << instanceId // cerr << " id=" << instanceId
@ -965,11 +979,12 @@ namespace Etesian {
} }
// Dummy fixed instance at the end // Dummy fixed instance at the end
instances[instanceId].size = point<int_t>( 0, 0 ); cellX[instanceId] = 0;
instances[instanceId].list_index = instanceId; cellY[instanceId] = 0;
instances[instanceId].area = 0; cellWidth[instanceId] = 0;
positions[instanceId] = point<int_t>( 0, 0 ); cellHeight[instanceId] = 0;
instances[instanceId].attributes = 0; cellIsFixed[instanceId] = true;
cellIsObstruction[instanceId] = true;
dots.finish( Dots::Reset|Dots::FirstDot ); dots.finish( Dots::Reset|Dots::FirstDot );
@ -993,8 +1008,6 @@ namespace Etesian {
cmess1 << " - Converting " << netsNb << " nets" << endl; cmess1 << " - Converting " << netsNb << " nets" << endl;
vector<temporary_net> nets ( netsNb );
vector<temporary_pin> pins;
_idsToNets.resize( netsNb ); _idsToNets.resize( netsNb );
unsigned int netId = 0; unsigned int netId = 0;
@ -1012,11 +1025,9 @@ namespace Etesian {
_netsToIds.insert( make_pair(net,netId) ); _netsToIds.insert( make_pair(net,netId) );
_idsToNets[netId] = make_tuple( net, _instsToIds.size(), 0 ); _idsToNets[netId] = make_tuple( net, _instsToIds.size(), 0 );
nets[netId] = temporary_net( netId, 1 );
//cerr << "+ " << net << endl;
string topCellInstancePin = getString(getCell()->getName()) + ":C"; string topCellInstancePin = getString(getCell()->getName()) + ":C";
vector<int> netCells, pinX, pinY;
for ( RoutingPad* rp : net->getRoutingPads() ) { for ( RoutingPad* rp : net->getRoutingPads() ) {
Path path = rp->getOccurrence().getPath(); Path path = rp->getOccurrence().getPath();
@ -1024,10 +1035,12 @@ namespace Etesian {
if (pin) { if (pin) {
if (path.isEmpty()) { if (path.isEmpty()) {
Point pt = rp->getCenter(); Point pt = rp->getCenter();
int_t xpin = pt.getX() / vpitch; int xpin = pt.getX() / vpitch;
int_t ypin = pt.getY() / hpitch; int ypin = pt.getY() / hpitch;
// Dummy last instance // 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; continue;
} }
@ -1054,8 +1067,8 @@ namespace Etesian {
string insName = extractInstanceName( rp ); string insName = extractInstanceName( rp );
Point offset = extractRpOffset ( rp ); Point offset = extractRpOffset ( rp );
int_t xpin = offset.getX() / vpitch; int xpin = offset.getX() / vpitch;
int_t ypin = offset.getY() / hpitch; int ypin = offset.getY() / hpitch;
auto iid = _instsToIds.find( instance ); auto iid = _instsToIds.find( instance );
if (iid == _instsToIds.end()) { if (iid == _instsToIds.end()) {
@ -1063,7 +1076,9 @@ namespace Etesian {
cerr << Error( "Unable to lookup instance \"%s\".", insName.c_str() ) << endl; cerr << Error( "Unable to lookup instance \"%s\".", insName.c_str() ) << endl;
} }
} else { } 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; Net* rpNet = NULL;
Plug* plug = dynamic_cast<Plug*>( rp->getPlugOccurrence().getEntity() ); Plug* plug = dynamic_cast<Plug*>( rp->getPlugOccurrence().getEntity() );
if (plug) { if (plug) {
@ -1074,6 +1089,7 @@ namespace Etesian {
} }
} }
} }
_circuit->addNet(netCells, pinX, pinY);
netId++; netId++;
} }
@ -1084,18 +1100,16 @@ namespace Etesian {
if (_bloatCells.getSelected()->getName() != "disabled") if (_bloatCells.getSelected()->getName() != "disabled")
cmess2 << stdCellSizes.toString(1) << endl; cmess2 << stdCellSizes.toString(1) << endl;
_densityLimits = new coloquinte::density_restrictions (); //_densityLimits = new coloquinte::density_restrictions ();
_surface = new box<int_t>( (int_t)(topAb.getXMin() / vpitch) _surface = new coloquinte::Rectangle( (int)(topAb.getXMin() / vpitch)
, (int_t)(topAb.getXMax() / vpitch) , (int)(topAb.getXMax() / vpitch)
, (int_t)(topAb.getYMin() / hpitch) , (int)(topAb.getYMin() / hpitch)
, (int_t)(topAb.getYMax() / hpitch) , (int)(topAb.getYMax() / hpitch)
); );
_circuit = new netlist( instances, nets, pins ); _circuit->check();
_circuit->selfcheck(); // TODO: define the rows
_placementLB = new coloquinte::placement_t (); _placementLB = new coloquinte::PlacementSolution ();
_placementLB->positions_ = positions; _placementUB = new coloquinte::PlacementSolution ( *_placementLB );
_placementLB->orientations_ = orientations;
_placementUB = new coloquinte::placement_t ( *_placementLB );
return instancesNb-fixedNb; return instancesNb-fixedNb;
} }
@ -1139,216 +1153,38 @@ namespace Etesian {
} }
void EtesianEngine::preplace () void EtesianEngine::globalPlace ( unsigned options )
{ {
using namespace coloquinte::gp; _circuit->placeGlobal(getPlaceEffort());
// TODO: add callback for placement update + antenna effect
// Perform a very quick legalization pass *_placementUB = _circuit->solution();
cmess2 << " o Simple legalization." << endl; _updatePlacement(_placementUB);
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 ) void EtesianEngine::detailedPlace ( unsigned options )
{ {
using namespace coloquinte::gp; _circuit->placeDetailed(getPlaceEffort());
// Create a legalizer and bipartition it until we have sufficient precision *_placementUB = _circuit->solution();
auto legalizer = (options & ForceUniformDensity) != 0 ? // TODO: add callback for placement update + antenna effect
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 ." );
}
}
*_placementLB = *_placementUB; // In case we run other passes *_placementLB = *_placementUB; // In case we run other passes
_updatePlacement( _placementUB, FinalStage ); _updatePlacement(_placementUB);
} }
void EtesianEngine::antennaProtect () void EtesianEngine::antennaProtect ()
{ {
// TODO
/*
DbU::Unit maxWL = getAntennaGateMaxWL(); DbU::Unit maxWL = getAntennaGateMaxWL();
if (not maxWL) return; if (not maxWL) return;
cmess1 << " o Inserting antenna effect protection." << endl; cmess1 << " o Inserting antenna effect protection." << endl;
uint32_t count = 0; 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; 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 ) ); DbU::Unit rsmt = toDbU( coloquinte::get_RSMT_length( *_circuit, *_placementUB, inet ) );
Net* net = std::get<0>( _idsToNets[inet] ); Net* net = std::get<0>( _idsToNets[inet] );
@ -1371,7 +1207,7 @@ namespace Etesian {
if (iinst == _instsToIds.end()) continue; if (iinst == _instsToIds.end()) continue;
std::get<1>( _idsToInsts[ (*iinst).second ] ).push_back( rp ); 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; cell_size.x += 2*diodeWidth;
_circuit->set_cell_size( (*iinst).second, cell_size ); _circuit->set_cell_size( (*iinst).second, cell_size );
++count; ++count;
@ -1379,6 +1215,7 @@ namespace Etesian {
} }
} }
cmess1 << ::Dots::asInt( " - Inserted diodes", count ) << endl; cmess1 << ::Dots::asInt( " - Inserted diodes", count ) << endl;
*/
} }
@ -1414,20 +1251,11 @@ namespace Etesian {
//findYSpin(); //findYSpin();
if (not toColoquinte()) return; if (not toColoquinte()) return;
Effort placementEffort = getPlaceEffort();
GraphicUpdate placementUpdate = getUpdateConf(); GraphicUpdate placementUpdate = getUpdateConf();
Density densityConf = getSpreadingConf(); Density densityConf = getSpreadingConf();
double sliceHeight = getSliceHeight() / getSliceStep();
cmess1 << " o Running Coloquinte." << endl; 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; unsigned globalOptions=0, detailedOptions=0;
if (placementUpdate == UpdateAll) { if (placementUpdate == UpdateAll) {
@ -1441,37 +1269,11 @@ namespace Etesian {
if (densityConf == ForceUniform) if (densityConf == ForceUniform)
globalOptions |= ForceUniformDensity; 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; cmess1 << " o Global placement." << endl;
globalPlace(minPenaltyIncrease, sliceHeight, targetImprovement, minPenaltyIncrease, maxPenaltyIncrease, globalOptions); globalPlace(globalOptions);
cmess1 << " o Detailed Placement." << endl; cmess1 << " o Detailed Placement." << endl;
detailedPlace(detailedIterations, detailedEffort, detailedOptions); detailedPlace(detailedOptions);
//toHurricane(); //toHurricane();
//addFeeds(); //addFeeds();
@ -1479,10 +1281,6 @@ namespace Etesian {
cmess1 << " o Placement finished." << endl; cmess1 << " o Placement finished." << endl;
stopMeasures(); stopMeasures();
printMeasures(); 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() ); addMeasure<double>( "placeT", getTimer().getCombTime() );
UpdateSession::open(); UpdateSession::open();
@ -1501,44 +1299,7 @@ namespace Etesian {
UpdateSession::close(); UpdateSession::close();
} }
void EtesianEngine::_updatePlacement ( const coloquinte::PlacementSolution* placement, uint32_t flags )
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 )
{ {
UpdateSession::open(); UpdateSession::open();
@ -1568,9 +1329,9 @@ namespace Etesian {
continue; continue;
//uint32_t outputSide = getOutputSide( instance->getMasterCell() ); //uint32_t outputSide = getOutputSide( instance->getMasterCell() );
point<int_t> position = placement->positions_[(*iid).second]; auto place = (*placement)[(*iid).second];
Transformation cellTrans = toTransformation( position Transformation cellTrans = toTransformation( place.position
, placement->orientations_[(*iid).second] , place.orientation
, instance->getMasterCell() , instance->getMasterCell()
, hpitch , hpitch
, vpitch , vpitch

View File

@ -40,9 +40,9 @@ namespace Etesian {
// Class : "Etesian::Configuration". // Class : "Etesian::Configuration".
enum Effort { Fast =1 enum Effort { Fast =1
, Standard=2 , Standard=3
, High =3 , High =6
, Extreme =4 , Extreme =9
}; };
enum GraphicUpdate { UpdateAll =1 enum GraphicUpdate { UpdateAll =1
, LowerBound=2 , LowerBound=2

View File

@ -18,7 +18,7 @@
#include <tuple> #include <tuple>
#include <iostream> #include <iostream>
#include <unordered_map> #include <unordered_map>
#include "coloquinte/circuit.hxx" #include "coloquinte2/coloquinte.hpp"
#include "hurricane/Timer.h" #include "hurricane/Timer.h"
#include "hurricane/Name.h" #include "hurricane/Name.h"
@ -131,10 +131,8 @@ namespace Etesian {
inline Transformation toBlock ( const Transformation& ) const; inline Transformation toBlock ( const Transformation& ) const;
void setPlaceArea ( const Box& ); void setPlaceArea ( const Box& );
size_t toColoquinte (); size_t toColoquinte ();
void preplace (); void globalPlace ( unsigned options=0 );
void roughLegalize ( float minDisruption, unsigned options ); void detailedPlace ( unsigned options=0 );
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 antennaProtect (); void antennaProtect ();
void place (); void place ();
uint32_t doHFNS (); uint32_t doHFNS ();
@ -160,11 +158,12 @@ namespace Etesian {
bool _flatDesign; bool _flatDesign;
Box _placeArea; Box _placeArea;
std::vector<Box> _trackAvoids; std::vector<Box> _trackAvoids;
coloquinte::box<coloquinte::int_t>* _surface; coloquinte::Rectangle* _surface;
coloquinte::netlist* _circuit; coloquinte::Circuit* _circuit;
coloquinte::placement_t* _placementLB; coloquinte::PlacementSolution* _placementLB;
coloquinte::placement_t* _placementUB; coloquinte::PlacementSolution* _placementUB;
coloquinte::density_restrictions* _densityLimits; // TODO
// coloquinte::density_restrictions* _densityLimits;
NetsToIds _netsToIds; NetsToIds _netsToIds;
InstancesToIds _instsToIds; InstancesToIds _instsToIds;
std::vector<InstanceInfos> _idsToInsts; std::vector<InstanceInfos> _idsToInsts;
@ -195,7 +194,7 @@ namespace Etesian {
private: private:
inline uint32_t _getNewDiodeId (); inline uint32_t _getNewDiodeId ();
Instance* _createDiode ( Cell* ); 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 _progressReport1 ( string label ) const;
void _progressReport2 ( string label ) const; void _progressReport2 ( string label ) const;
}; };