coriolis/equinox/src/EquinoxEngine.cpp

577 lines
16 KiB
C++

// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC/LIP6 2008-2009, All Rights Reserved
//
// ===================================================================
//
// $Id$
//
// x-----------------------------------------------------------------x
// | |
// | C O R I O L I S |
// | E q u i n o x - E x t r a c t o r |
// | |
// | Author : Wu Yife |
// | E-mail : Wu.Yifei@lip6.fr |
// | =============================================================== |
// | C++ Header : "./EquinoxEngine.cpp" |
// | *************************************************************** |
// | U p d a t e s |
// | |
// x-----------------------------------------------------------------x
#include <iostream>
#include <vector>
#include "hurricane/Path.h"
#include "hurricane/Net.h"
#include "hurricane/Name.h"
#include "hurricane/Entity.h"
#include "hurricane/Error.h"
#include "hurricane/Collection.h"
#include "hurricane/DataBase.h"
#include "hurricane/Technology.h"
#include "hurricane/Cell.h"
#include "hurricane/Occurrences.h"
#include "hurricane/Box.h"
#include "hurricane/Instance.h"
#include "hurricane/Components.h"
#include "crlcore/ToolEngine.h"
#include "crlcore/Utilities.h"
#include "equinox/EquinoxFilters.h"
#include "equinox/Equis.h"
#include "equinox/Equi.h"
#include "equinox/Tile.h"
#include "equinox/Tiles.h"
#include "equinox/Strategy.h"
#include "equinox/UnionFind.h"
#include "equinox/EquinoxEngine.h"
#include "equinox/TileSweepLine.h"
namespace Equinox {
using namespace std;
using namespace Hurricane;
// -------------------------------------------------------------------
// Class : "Equinox::EquinoxEngine".
/**/ Name EquinoxEngine::_toolName = "Equinox";
/**/ Strategy * EquinoxEngine::_strategy = NULL;
EquinoxEngine* EquinoxEngine::create (Cell* cell)
{
EquinoxEngine* equinox = new EquinoxEngine ( cell );
if(!equinox){
throw Error("can't create Equinox : allocation failed");
}
equinox->_postCreate ();
return equinox;
}
/**/ void EquinoxEngine::removeEquis ()
{
set<Equi*>::iterator i;
while(!_equis.empty()) {
i = _equis.begin();
(*i)->destroy(); // Delete also addresse of objet Equi from current Equinox
}
_occurrences.clear(); // Clear also map<Occurrence, Equi*>
}
Strategy* EquinoxEngine::getStrategy ()
{
if (!_strategy) {
_strategy = new DefaultStrategy();
}
return _strategy;
}
void EquinoxEngine::withAlimExtract(unsigned int nbwindows)
// **************************************************
{
setStrategy(new WithAlimStrategy());
/*DEBUG*/ cmess1 << " o extract " << endl;
extract(nbwindows);
/*DEBUG*/ cmess1 << " o printEqui " << endl;
printEquis();
/*DEBUG*/ cmess1 << " o Fin " << endl;
}
void EquinoxEngine::withoutAlimExtract(unsigned int nbwindows)
// **************************************************
{
setStrategy(new WithoutAlimStrategy());
/*DEBUG*/ cmess1 << " o extract " << endl;
extract(nbwindows);
/*DEBUG*/ cmess1 << " o printEqui " << endl;
printEquis();
/*DEBUG*/ cmess1 << " o Fin " << endl;
}
void EquinoxEngine::extract(unsigned int nbwindows)
{
// Test for parameter
// ******************
if(!getStrategy())
throw Error("Can't start extraction without mode, the current mode is null");
if( nbwindows >256 || nbwindows < 1 ) {
throw Error("Can't start extraction : the nbwindows " + getString(nbwindows) + " is not valid");
}
// Clean Equis
// ***********
if(isExtracted()) {
flushEquis(_cell);
}
// Start extraction.
// *****************
getStrategy()->run(this, nbwindows);
}
Record* EquinoxEngine::_getRecord () const
{
Record* record = ToolEngine::_getRecord ();
record->add ( getSlot ( "_isExtracted" , _isExtracted ) );
record->add ( getSlot ( "_equis" , _equis ) );
record->add ( getSlot ( "_occurrences" , _occurrences ) );
return ( record );
}
string EquinoxEngine::_getString () const
{
ostringstream os;
os << "<" << "Equinox " << _cell->getName () << ">";
return ( os.str() );
}
string EquinoxEngine::_getTypeName () const { return "Equinox"; }
Equi* EquinoxEngine::getEquiByOccurrence(Occurrence occurrence)
// *********************************************
{
map<Occurrence, Equi*>::iterator i = _occurrences.end();
if( _occurrences.find(occurrence) == i) {
Component * component = dynamic_cast<Component*>(occurrence.getEntity());
if( component && occurrence.getPath().isEmpty() )
{
// If this is a component , maybe it has been factorized, after extraction.
// *************************************************************************
if( _occurrences.find( Occurrence(component->getNet()) ) != i )
return _occurrences[Occurrence(component->getNet())];
}
return NULL;
}
else
return _occurrences[occurrence];
};
Occurrence EquinoxEngine::getEquiOccurrence(Occurrence occurrence)
// ***********************************************
{
map<Occurrence, Equi*>::iterator i = _occurrences.end();
if( _occurrences.find(occurrence) == i ) {
Component* component = dynamic_cast<Component*>(occurrence.getEntity());
if( component && occurrence.getPath().isEmpty() ) { // If this is a component, maybe it has been factorized.
if( _occurrences.find( Occurrence(component->getNet()) ) != i )
return Occurrence(static_cast<Entity*>(_occurrences[Occurrence(component->getNet())]));
}
return Occurrence();
}
else
return Occurrence(static_cast<Entity*>(_occurrences[occurrence]));
};
Occurrence EquinoxEngine::getUpperEquiOccurrence(Occurrence occurrence)
// *****************************************************
{
Path path = occurrence.getPath();
Equi * equi = NULL;
occurrence = Occurrence(occurrence.getEntity());
while(1) {
if(!path.isEmpty())
equi = get(path.getMasterCell())->getEquiByOccurrence(occurrence);
else
equi = this->getEquiByOccurrence(occurrence);
if(!equi) return occurrence;
occurrence = Occurrence(equi, Path(path.getTailInstance()));
path=path.getHeadPath();
}
return Occurrence();
};
void EquinoxEngine::setIsExtracted (const bool flag)
{
_isExtracted= flag;
};
void EquinoxEngine::selectWindowsSize ()
{
Box cellbox = _cell->getBoundingBox();
long cellwidth = cellbox.getWidth();
if ( cellwidth < 50000 ){ _nbWindows = 1; }
else if( cellwidth < 100000 ){ _nbWindows = 2; }
else { _nbWindows = cellwidth / 50000; }
if (_nbWindows > 256) _nbWindows = 256;
_nbWindows=20;
///*DEBUG*/ cmess1 << " o selectWindowsSize : _nbWindows = " << _nbWindows << endl ;
}
void EquinoxEngine::initTiles ()
{
getStrategy()->getTilesFor(this);
}
void EquinoxEngine::postSweepLine ()
{
getStrategy()->operationAfterScanLine(this);
}
void EquinoxEngine::scan (unsigned int nbwindows)
{
/*DEBUG*/ cmess1 << " o EquinoxEngine::scan " << getString(_cell) << endl;
TileSweepLine* sweepLine = TileSweepLine::create(this,getStrategy());
// Step 2 - Select Windows Size
// ****************************
/*DEBUG*/ cmess1 << " - Step 2 - Select Windows Size" << endl;
selectWindowsSize();
// Main algorithme
// ***************
for(_cWindows=0; _cWindows<_nbWindows; _cWindows++) {
// Step 3 - Init tiles vector
// **************************
/*DEBUG*/ cmess1 << " - Step 3 - Init tiles vector " << flush;
initTiles();
// Step 4 - Run Sweep Line
// ***********************
/*DEBUG*/ cmess1 << _tilesByXmin->size() <<" Tiles and SweepLine " << _cWindows << " sur " << _nbWindows << endl;
sweepLine->run(
_tilesByXmin,
_tilesByXmax,
_cWindows < _nbWindows-1,
((_cell->getBoundingBox().getXMin ()+(_cWindows+1)*_cell->getBoundingBox().getWidth()/_nbWindows)) );
} // end for
// Step 5 - Post Sweep Line
// ***********************
/*DEBUG*/ cmess1 << " - Step 4 - PostSweepLine" << endl;
postSweepLine();
// Step 6 - Clean SweepLine
// *************************
sweepLine->destroy();
}
void EquinoxEngine::getOccurrencesOfEquis()
// *******************************************
{
unsigned long count = 0;
forEach (Equi*,equi,getCollection(_equis))
{
// Factoriser occurrences of equi
(*equi)->factorizeComponents();
forEach(Occurrence,occurrence,((*equi)->getOccurrences()))
_occurrences[(*occurrence)] = *equi;
(*equi)->setNumber(++count);
}
}
void EquinoxEngine::cleanUpLeafCell()
// *************************************
{
///*DEBUG*/ cmess1 << " - cleanUpLeafCell() " << endl;
set<Net*> set_nets;
Net * externalnet = NULL;
unsigned long count = 1;
Occurrence o;
forEach(Equi*,equi,getCollection(_equis))
{
externalnet = NULL;
forEach( Occurrence,occurrence, (*equi)->getComponentOccurrences())
{
Net * net = dynamic_cast<Component*>((*occurrence).getEntity())->getNet();
// check for 2 externals nets on the same Equi
if(net->isExternal()) {
if(externalnet && (externalnet != net) )
throw Error("There is two external net in leaf cell : Library Error " + getString(externalnet)
+ " " + getString(net) + " with component "
+ getString((*occurrence)) + " " + getString(o));
if(!externalnet) {
o = (*occurrence);
externalnet = net;
}
}
set_nets.insert(net);
}
// If there is no externalNet, choice the first
if(!externalnet) externalnet = (*set_nets.begin());
forEach(Net*,net, getCollection(set_nets))
{
if( (*net)!= externalnet) {
externalnet->merge(*net);
}
}
_occurrences[Occurrence(externalnet)] = *equi; // Add <Occurrence, Equi*> to map<Occurrence, Equi*> _occurrences.
(*equi)->erase(); // Clean all component occurrences
(*equi)->addOccurrence(Occurrence(externalnet));// Add net occurrence
set_nets.clear();
(*equi)->setNumber(count++);
}
}
EquinoxEngine::EquinoxEngine ( Cell* cell )
: ToolEngine (cell)
, _cWindows(0)
, _nbWindows(0)
, _isExtracted(false)
, _tilesByXmin()
, _tilesByXmax()
{ }
void EquinoxEngine::flushEquis (Cell*cell) {
if(!_isExtracted) // If the top cell hasn't been extracted.
return ;
InstanceLocator instancelocator = cell->getInstances().getLocator();
if(instancelocator.isValid()){ // If the cell isn't a leaf cell.
EquinoxEngine * equinox = NULL;
Cell * mastercell = NULL;
while(instancelocator.isValid()) {
mastercell = instancelocator.getElement()->getMasterCell();
equinox = get(mastercell);
if(equinox && (equinox->isExtracted())) // If the sous-cell has been extracted.
flushEquis(mastercell);
instancelocator.progress();
}
}
EquinoxEngine * equinox = get(cell);
equinox->removeEquis();
equinox->setIsExtracted(false);
}
EquinoxEngine::~EquinoxEngine ()
{
}
void EquinoxEngine::_postCreate ()
{
ToolEngine::_postCreate ();
_tilesByXmin = new TileVector();
_tilesByXmax = new TileVector();
}
void EquinoxEngine::_preDestroy ()
{
ToolEngine::_preDestroy ();
removeEquis();
}
void EquinoxEngine::_destroy ()
{
_preDestroy();
_depthDestroy();
delete this;
}
void EquinoxEngine::_depthDestroy()
// **************************
{
GenericLocator<Instance*> locator = _cell->getInstances().getLocator();
EquinoxEngine * equinox = NULL;
if( !(locator.isValid()) ) {
this->destroy();
}
else {
while(locator.isValid()) {
Cell * cell = locator.getElement()->getMasterCell();
equinox = get(cell);
if(equinox)
equinox->_depthDestroy();
locator.progress();
}
this->destroy();
}
}
void EquinoxEngine::printEquis()
{
cmess1 << "Nombre d'equis"<< _equis.size() <<endl;
/*DEBUG*/// <<endl;
/*DEBUG*/// forEach(Equi*,equi,getCollection(_equis)) {
/*DEBUG*/// cmess1 << " o Equi : " << (*equi)->_getString() << endl;
/*DEBUG*/// forEach(Occurrence,occurrence,((*equi)->getOccurrences()))
/*DEBUG*/// {
/*DEBUG*///
/*DEBUG*/// //NET Occurrence
/*DEBUG*/// if (dynamic_cast<Net*>((*occurrence).getEntity()))
/*DEBUG*/// {
/*DEBUG*/// cmess1 << " - [NET]" << (*occurrence).getEntity() << " \t===>\t " << getHyperNetRootNetOccurrence((*occurrence).getEntity())._getString() << endl;
/*DEBUG*/// }
/*DEBUG*///
/*DEBUG*/// //COMPONENT Occurrence
/*DEBUG*/// if (dynamic_cast<Component*>((*occurrence).getEntity())) {
/*DEBUG*/// Component* composant = dynamic_cast<Component*>((*occurrence).getEntity());
/*DEBUG*/// cmess1 << " - [COM]" << composant << " \t===>\t " << getHyperNetRootNetOccurrence(composant->getNet())._getString() << endl;
/*DEBUG*/// }
/*DEBUG*///
/*DEBUG*/// //EQUI Occurrence
/*DEBUG*/// if (dynamic_cast<Equi*>((*occurrence).getEntity())) {
/*DEBUG*/// Equi* equi = dynamic_cast<Equi*>((*occurrence).getEntity());
/*DEBUG*/// cmess1 << " - [EQU]" << equi << endl;
/*DEBUG*/// }
/*DEBUG*/// }
/*DEBUG*/// }
}
void EquinoxEngine::removeInterval(Tile* item)
{
// on diminue le compteur de reference de l'Equi
item->getEqui()->decrementCount();
// on detruit le tile
item->destroy();
}
void EquinoxEngine::insertInterval(Tile* newtile,stack <Interval*>*enumResultStack)
{
//Application des contacts
Equi * newroot = NULL;
if( !(enumResultStack->empty()) ) { // contact > 0
if( newtile->getEqui() ) enumResultStack->push(newtile);
newroot = UnionFind::getRootEquiWithCompression(dynamic_cast<Tile*>(enumResultStack->top()) );
enumResultStack->pop();
while (!enumResultStack->empty()) {//while contact > 0
Equi * root = UnionFind::getRootEquiWithCompression(dynamic_cast<Tile*>(enumResultStack->top()) );
enumResultStack->pop();
if( root != newroot ) {
root->setNextEqui(newroot);
newroot->merge(root);
newroot->incrementCount();
}
}
if(newtile->getEqui() == NULL){
newtile->setEqui(newroot);
newroot->incrementCount();
newroot->addOccurrence(newtile->getOccurrence());
}
}
else { // contact == 0
if( newtile->getEqui() == NULL) {
newroot = Equi::create(this);
newroot->incrementCount();
newtile->setEqui(newroot);
newroot->addOccurrence(newtile->getOccurrence());
}
}
}
}// End of namespace Equinox