// -*- 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 | // | | // | Updater : Bodin bruno | // | E-mail : Jean-Paul.Chaput@lip6.fr | // | =============================================================== | // | C++ Header : "./Strategy.cpp" | // | *************************************************************** | // | U p d a t e s | // | | // x-----------------------------------------------------------------x #include #include #include #include "hurricane/Bug.h" #include "hurricane/Net.h" #include "hurricane/Name.h" #include "hurricane/Error.h" #include "hurricane/Warning.h" #include "hurricane/BasicLayer.h" #include "hurricane/Technology.h" #include "hurricane/Collection.h" #include "hurricane/Cell.h" #include "hurricane/Box.h" #include "hurricane/Locator.h" #include "hurricane/Instance.h" #include "hurricane/Occurrence.h" #include "hurricane/Component.h" #include "hurricane/DataBase.h" #include "hurricane/DebugSession.h" #include "crlcore/Utilities.h" #include #include "equinox/Strategy.h" #include "equinox/Equi.h" #include "equinox/Tile.h" #include "equinox/Tiles.h" #include "equinox/EquinoxFilters.h" #include "equinox/EquinoxEngine.h" namespace { } namespace Equinox { using namespace std; using namespace Hurricane; Strategy::Strategy() {} bool const Strategy::isExtractableLayer(BasicLayer * basicLayer) { static Layer * _gmetalh = DataBase::getDB()->getTechnology()->getLayer("gmetalh"); static Layer * _gmetalv = DataBase::getDB()->getTechnology()->getLayer("gmetalv"); static Layer * _gcontact = DataBase::getDB()->getTechnology()->getLayer("gcontact"); if ( DataBase::getDB()->getTechnology()->isMetal(dynamic_cast ( basicLayer )) ) if (( ( (basicLayer) != _gmetalh ) && ( (basicLayer) != _gmetalv ) && ( (basicLayer) != _gcontact ) )) return true; return false; } WithAlimStrategy::WithAlimStrategy() {} WithAlimStrategy::~WithAlimStrategy() {} void WithAlimStrategy::run(EquinoxEngine* equinox, unsigned nbwindows) { forEach(Instance*,instance, equinox->_cell->getInstances()) { Cell * cell = instance->getMasterCell(); EquinoxEngine* subequinox = EquinoxEngine::get(cell); if(!subequinox) subequinox = EquinoxEngine::create(cell); if( !(subequinox->isExtracted()) ) run(subequinox, nbwindows); } equinox->scan(nbwindows); equinox->setIsExtracted(true); } void WithAlimStrategy::getTilesFor(EquinoxEngine* equinox) { // Init //****** ///*DEBUG*/ cmess1 << " o getTilesFor : " << endl ; Box cellbox = equinox->_cell->getBoundingBox(); long cellwidth = cellbox.getWidth(); long ymax = cellbox.getYMax(); long ymin = cellbox.getYMin(); long xmin = cellbox.getXMin(); long xmax = cellbox.getXMax(); long interval = cellwidth/equinox->_nbWindows; // Cas de la premiere fenetre //**************************** if( equinox->_cWindows == 0 ) if ((equinox->_tilesByXmin->size()) + (equinox->_tilesByXmax->size())) throw "Listes non vides avant constitution des Tiles"; // calcul de la UnderBox //****************** long underbox_xmax = 0; if( equinox->_cWindows == equinox->_nbWindows-1 ) underbox_xmax = xmax; else underbox_xmax = xmin + (equinox->_cWindows+1)*interval; Box underbox(xmin+equinox->_cWindows*interval, ymin, underbox_xmax, ymax); //Component Occurrence with a basiclayer on Metal at least Occurrences componentoccurrences = equinox->_cell->getComponentOccurrencesUnder(underbox, DataBase::getDB()->getTechnology()->_getMetalMask()).getSubSet((WithAlimStrategyFilter())); Component * component = NULL; Box box; Tile * tile = NULL; Equi * equi = NULL; bool equicreated = false; Occurrence o = NULL; forEach(Occurrence,occurrence,componentoccurrences) { component = dynamic_cast((*occurrence).getEntity()); box = (*occurrence).getBoundingBox(); tile = NULL; equi = NULL; equicreated = false; // ignorer les occurrences inutiles // ***************************** if( box.getXMin() < xmin || box.getXMin() >= xmax ) continue; if((*occurrence)._getSharedPath()) { o = (equinox->getUpperEquiOccurrence((*occurrence))); if(!(o.isValid())) throw Error("Can't use Equinox::GetTilesFor() : GetUpperEquiOccurrence Return Invalid Occurrence"); } else { o = (*occurrence); } if (dynamic_cast(component->getLayer())) { // BasicLayer //************ tile = Tile::create((o), box, const_cast(dynamic_cast(component->getLayer())), NULL); equinox->_tilesByXmin->push_back(tile); equinox->_tilesByXmax->push_back(tile); } else { // Not BasicLayer //**************** forEach ( BasicLayer*, i, component->getLayer()->getBasicLayers() ) { if (isExtractableLayer(*i)) { if(!equicreated && tile){ equi = Equi::create(equinox); tile->setEqui(equi); equi->incrementCount(); equi->addOccurrence((o)); equicreated = true; } tile = Tile::create((o), box, (*i), equi); equinox->_tilesByXmin->push_back(tile); equinox->_tilesByXmax->push_back(tile); if(equi) equi->incrementCount(); } } } } // Sort these two vectors // *********************** sort::iterator, CompByXmin >( equinox->_tilesByXmin->begin(), equinox->_tilesByXmin->end(), CompByXmin() ); sort::iterator, CompByXmax >( equinox->_tilesByXmax->begin(), equinox->_tilesByXmax->end(), CompByXmax() ); } void WithAlimStrategy::operationAfterScanLine(EquinoxEngine* equinox) { Cell * cell = equinox->_cell; if( cell->isLeaf()) // If this is a leaf cell equinox->cleanUpLeafCell(); else equinox->getOccurrencesOfEquis(); } WithoutAlimStrategy::WithoutAlimStrategy() {} WithoutAlimStrategy::~WithoutAlimStrategy() {} void WithoutAlimStrategy::run(EquinoxEngine* equinox, unsigned nbwindows) { forEach(Instance*,instance, equinox->_cell->getInstances()) { Cell * cell = instance->getMasterCell(); EquinoxEngine* subequinox = EquinoxEngine::get(cell); if(!subequinox) subequinox = EquinoxEngine::create(cell); if( !(subequinox->isExtracted()) ) run(subequinox, nbwindows); } equinox->scan(nbwindows); equinox->setIsExtracted(true); } void WithoutAlimStrategy::getTilesFor(EquinoxEngine* equinox) { // Init //****** ///*DEBUG*/ cmess1 << " o getTilesFor : " << endl ; Box cellbox = equinox->_cell->getBoundingBox(); long cellwidth = cellbox.getWidth(); long ymax = cellbox.getYMax(); long ymin = cellbox.getYMin(); long xmin = cellbox.getXMin(); long xmax = cellbox.getXMax(); long interval = cellwidth/equinox->_nbWindows; // Cas de la premiere fenetre //**************************** if( equinox->_cWindows == 0 ) { ///*DEBUG*/ cmess1 << " - vidage de tilesByXmin (" << equinox->_tilesByXmin->size() << ") et tilesByXmax (" << equinox->_tilesByXmax->size() << ")" << endl; equinox->_tilesByXmin->clear(); equinox->_tilesByXmax->clear(); } // calcul de la box //****************** long underbox_xmax = 0; if( equinox->_cWindows==equinox->_nbWindows-1 ) underbox_xmax = xmax; else underbox_xmax = xmin + (equinox->_cWindows+1)*interval; Box underbox(xmin+equinox->_cWindows*interval, ymin, underbox_xmax, ymax); ///*DEBUG*/ cmess1 << " - underbox = "<< underbox << endl ; Occurrences componentoccurrences ; if(equinox->_cell->isLeaf()) componentoccurrences = equinox->_cell->getComponentOccurrencesUnder(underbox, DataBase::getDB()->getTechnology()->_getMetalMask()).getSubSet((WithAlimStrategyFilter())); else componentoccurrences = equinox->_cell->getComponentOccurrencesUnder(underbox, DataBase::getDB()->getTechnology()->_getMetalMask()).getSubSet((WithoutAlimStrategyFilter())); Component * component = NULL; Box box; Tile * tile = NULL; Equi * equi = NULL; bool equicreated = false; Occurrence o = NULL; forEach(Occurrence,occurrence,componentoccurrences) { component = dynamic_cast((*occurrence).getEntity()); box = (*occurrence).getBoundingBox(); tile = NULL; equi = NULL; equicreated = false; // ignorer les occurrences inutiles // ***************************** if( box.getXMin() < xmin || box.getXMin() >= xmax ) continue; if((*occurrence)._getSharedPath()){ o = (equinox->getUpperEquiOccurrence((*occurrence))); if(!(o.isValid())) throw Error("Can't use Equinox::GetTilesFor() : GetUpperEquiOccurrence Return Invalid Occurrence"); } else { o = (*occurrence); } //o = (*occurrence); if (dynamic_cast(component->getLayer())) { // BasicLayer //************ tile = Tile::create((o), box, const_cast(dynamic_cast(component->getLayer())), NULL); equinox->_tilesByXmin->push_back(tile); equinox->_tilesByXmax->push_back(tile); /////*DEBUG*/ bt++; } else { // Not BasicLayer //**************** forEach ( BasicLayer*, i, component->getLayer()->getBasicLayers() ) { if ( isExtractableLayer(*i)) { if(!equicreated && tile){ equi = Equi::create(equinox); tile->setEqui(equi); equi->incrementCount(); equi->addOccurrence((o)); equicreated = true; } tile = Tile::create((o), box, (*i), equi); equinox->_tilesByXmin->push_back(tile); equinox->_tilesByXmax->push_back(tile); if(equi) equi->incrementCount(); } } } } // Sort these two vectors // *********************** sort::iterator, CompByXmin >( equinox->_tilesByXmin->begin(), equinox->_tilesByXmin->end(), CompByXmin() ); sort::iterator, CompByXmax >( equinox->_tilesByXmax->begin(), equinox->_tilesByXmax->end(), CompByXmax() ); } void WithoutAlimStrategy::operationAfterScanLine(EquinoxEngine* equinox) { Cell * cell = equinox->_cell; if( cell->isLeaf()) // If this is a leaf cell equinox->cleanUpLeafCell(); else equinox->getOccurrencesOfEquis(); } // ------------------------------------------------------------------- // Class : "Equinox::WithAlimStrategyFilter". /**/ WithAlimStrategyFilter::WithAlimStrategyFilter () {}; /**/ WithAlimStrategyFilter::WithAlimStrategyFilter (const WithAlimStrategyFilter&) {}; WithAlimStrategyFilter& WithAlimStrategyFilter::operator= (const WithAlimStrategyFilter&) {return *this; }; Filter* WithAlimStrategyFilter::getClone () const {return new WithAlimStrategyFilter(*this); }; string WithAlimStrategyFilter::_getString () const {return ""; }; bool WithAlimStrategyFilter::accept (Occurrence item) const { Component* component = dynamic_cast(item.getEntity()); Box box = component->getBoundingBox(); // If box is not valid , this component occurrence is unuseful. // ************************************************************ if( (box.getYMin() == box.getYMax()) || (box.getXMin() == box.getXMax()) ) return false; forEach ( BasicLayer*, i, component->getLayer()->getBasicLayers() ) { if (WithAlimStrategy::isExtractableLayer(*i)) return true; } return false; }; // ------------------------------------------------------------------- // Class : "Equinox::WithoutAlimStrategyFilter". /**/ WithoutAlimStrategyFilter::WithoutAlimStrategyFilter () {}; /**/ WithoutAlimStrategyFilter::WithoutAlimStrategyFilter (const WithoutAlimStrategyFilter&) {}; WithoutAlimStrategyFilter& WithoutAlimStrategyFilter::operator= (const WithoutAlimStrategyFilter&) {return *this; }; Filter* WithoutAlimStrategyFilter::getClone () const {return new WithoutAlimStrategyFilter(*this); }; string WithoutAlimStrategyFilter::_getString () const {return ""; }; bool WithoutAlimStrategyFilter::accept (Occurrence item) const { Component* component = dynamic_cast(item.getEntity()); Box box = component->getBoundingBox(); Net * net = component->getNet(); if(net->isGlobal() || net->isGround() || net->isPower()) { return false; } // If box is not valid , this component occurrence is unuseful. // ************************************************************ if( (box.getYMin() == box.getYMax()) || (box.getXMin() == box.getXMax()) ) return false; forEach ( BasicLayer*, i, component->getLayer()->getBasicLayers() ) { if (Strategy::isExtractableLayer(*i)) return true; } return false; }; }// End of namespace Equinox