// -*- 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 | // | S O L S T I C E - C o m p a r a t o r | // | | // | Author : Wu Yife | // | E-mail : Wu.Yifei@lip6.fr | // | =============================================================== | // | C++ Header : "./SolsticeEngine.cpp" | // | *************************************************************** | // | U p d a t e s | // | | // x-----------------------------------------------------------------x #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace Solstice { using namespace std; using namespace Hurricane; using Equinox::DefaultStrategy; using Equinox::EquinoxEngine; using Equinox::Equi; using Equinox::CompByXmin; using Equinox::CompByXmax; // ------------------------------------------------------------------- // Class : "Solstice::SolsticeEngine". Name SolsticeEngine::_toolName = "Solstice"; Strategy * SolsticeEngine::_strategy = NULL; void SolsticeEngine::setStrategy (Strategy * s) { if (_strategy) delete _strategy; _strategy = s; }; Strategy* SolsticeEngine::getStrategy () { if (!_strategy) { _strategy = new DefaultStrategy(); } return _strategy; } Cell* SolsticeEngine::getCommonPath(Path path1, Path path2, Path& newpath1, Path& newpath2) { Instance * instance1 = path1.getHeadInstance(); Instance * instance2 = path2.getHeadInstance(); Path commonpath; while(instance1==instance2) { if(!instance1) break; path1 = path1.getTailPath(); path2 = path2.getTailPath(); commonpath = commonpath.isEmpty()?Path(instance1):Path(commonpath, instance1); if(path1.isEmpty()) break; if(path2.isEmpty()) break; instance1 = path1.getHeadInstance(); instance2 = path2.getHeadInstance(); } newpath1 = path1; newpath2 = path2; if (commonpath.isEmpty()) { return NULL; } else { return commonpath.getMasterCell(); } } SolsticeEngine* SolsticeEngine::create (Cell* cell) { SolsticeEngine* solstice = new SolsticeEngine ( cell ); if(!solstice){ throw Error("can't create Solstice : allocation failed"); } solstice->_postCreate (); return solstice; } void SolsticeEngine::_depthCreate(Cell * cell) { forEach(Instance*,instance, cell->getInstances()) { Cell * subcell = (*instance)->getMasterCell(); SolsticeEngine * solstice = get(subcell); if( (!(subcell->isLeaf())) && (!solstice) ) { _depthCreate(subcell); } } SolsticeEngine * solstice = get(cell); if(!solstice) create(cell); } SolsticeEngine* SolsticeEngine::get (const Cell* cell ) { return static_cast(ToolEngine::get(cell,_toolName)); } Record* SolsticeEngine::_getRecord () const { Record* record = ToolEngine::_getRecord (); return ( record ); } SolsticeEngine::~SolsticeEngine () { } SolsticeEngine::SolsticeEngine (Cell* cell): ToolEngine(cell), _isCompared(false), _routingErrors() { _routingErrors = new set; } void SolsticeEngine::_depthDestroy() { if(_cell->isLeaf()) return ; else { forEach(Instance*,instance, _cell->getInstances()) { Cell * cell = (*instance)->getMasterCell(); SolsticeEngine * solstice = get(cell); if(solstice) solstice->_depthDestroy(); } this->destroy(); } } void SolsticeEngine::compare() { // Verify the extractor Equinox // ****************************** EquinoxEngine * equinox = EquinoxEngine::get(_cell); if(!equinox){ throw Error("Can't do comparison, because the extractor haven't been created"); } if(!(equinox->isExtracted())) { throw Error("Can't do comparison, because the extraction haven't been done"); } // Create CEngine Solstice for all models except standards models. // ***************************************************************** _depthCreate(_cell); // If repeat Comparison, flush those olds errors and reset flags to false. // ************************************************************************* if(isCompared()) flushErrors(); // Run comparison and Print Statistique datas. // ********************************************* runComparison(); } void SolsticeEngine::runComparison() { map > map_hypernet2hyperequi; set hypernets; EquinoxEngine * equinox = Equinox::EquinoxEngine::get(_cell); forEach(Equi*,equi, equinox->getRoutingEquis()) { forEach(Occurrence,occurrence, (*equi)->getAllOccurrences()) { // Check Net Power/Ground/Global //******************************* Net * net = dynamic_cast((*occurrence).getEntity()); if(!net) net = dynamic_cast((*occurrence).getEntity())->getNet(); if(net->isGlobal() || net->isGround() || net->isPower()) { continue; } // Add HyperNet //************** Occurrence hypernet = getTopNetOccurrence((*occurrence)); #ifdef ASSERT assert(isHyperNetRootNetOccurrence(hypernet)); #endif hypernets.insert(hypernet); map_hypernet2hyperequi[hypernet].insert((*equi)); } //end of forEach occurrence // ShortCircuits Detection //************************* if(hypernets.size() > 1) { cmess1 << "[BUG] ShortCircuit Detection with " << hypernets.size() << " nets on same Equi" << endl; for (set::iterator i = hypernets.begin() ; i!= hypernets.end();i++) cmess1 << " - Net " << (*i).getEntity()->_getString() << endl; detectShortCircuit((*equi)); } hypernets.clear(); } //end of forEach equi // Disconnects Detection //*********************** for (map >::iterator i = map_hypernet2hyperequi.begin(); i != map_hypernet2hyperequi.end(); i++) { if( (*i).second.size()>1 ) { cmess1 << "[BUG] Disconnection Detection with " << (*i).second.size() << " equi for net " << (*i).first.getEntity()->_getString() << endl; for (set::iterator j = (*i).second.begin(); j != (*i).second.end(); j++) { cmess1 << " - " << (*j) << endl ; forEach(Occurrence,k,(*j)->getAllOccurrences()) { cmess1 << " - " << (*k) << endl ; } } this->_routingErrors->insert(DisconnectError::create(getCell(),Occurrence((*i).first),(*i).second.size())); } } map_hypernet2hyperequi.clear(); setIsComparedTrue(_cell); } Occurrence SolsticeEngine::getTopNetOccurrence(Occurrence occurrence) { Path path = occurrence.getPath(); if( path.isEmpty() ) { Net * net = dynamic_cast(occurrence.getEntity()); if(net) { return occurrence; } else { Component * component = dynamic_cast(occurrence.getEntity()); if(!component) throw Error("Unknow occurrence in EQUINOX::GetUpperNetOccurrence()"); return Occurrence(component->getNet()); } } else { Net * net = dynamic_cast(occurrence.getEntity()); if(net) { if( !(net->isExternal()) ) return occurrence; Instance * tailinstance = path.getTailInstance(); Plug * plug = tailinstance->getPlug(net); if( !(plug->isConnected()) ) return occurrence; Net * uppernet = plug->getNet(); return getTopNetOccurrence(Occurrence(uppernet, path.getHeadPath())); } else { Component* component = dynamic_cast(occurrence.getEntity()); return getTopNetOccurrence(Occurrence(component->getNet(), occurrence.getPath())); } } } void SolsticeEngine::detectShortCircuit(Equi* equi) { // Create Bricks for all component occurrences in this hyper-equi. // *************************************************************** vector* BricksByXmin = new vector ; vector* BricksByXmax = new vector ; forEach(Occurrence,occurrence, equi->getEquiComponentOccurrences()) { Occurrence hypernet = getTopNetOccurrence((*occurrence)); Component* component = dynamic_cast((*occurrence).getEntity()); Box box = (*occurrence).getBoundingBox(); forEach ( BasicLayer*, i, component->getLayer()->getBasicLayers() ) if (Strategy::isExtractableLayer(*i)) { Brick * brick = Brick::create(hypernet, (*occurrence), box, *i); BricksByXmin->push_back(brick); BricksByXmax->push_back(brick); } } // Sort these two tables. // ********************* sort< vector::iterator , CompByXmin > ( BricksByXmin->begin(), BricksByXmin->end(), CompByXmin() ); sort< vector::iterator , CompByXmax > ( (BricksByXmax->begin()), BricksByXmax->end(), CompByXmax() ); BrickSweepLine* sweepLine = BrickSweepLine::create(this,getStrategy()); sweepLine->run(BricksByXmin,BricksByXmax,false,0); } void SolsticeEngine::setIsComparedTrue(Cell * cell) { SolsticeEngine * solstice = get(cell); solstice->setIsCompared(true); forEach(Instance*,instance, cell->getInstances()) { Cell * subcell = (*instance)->getMasterCell(); SolsticeEngine * solstice = get(subcell); if( (!(subcell->isLeaf())) && (!(solstice->isCompared())) ) setIsComparedTrue(subcell); } } void SolsticeEngine::getAllSolstices(Cell* cell, set& solstices) { SolsticeEngine* solstice = get(cell); solstices.insert(solstice); forEach(Instance*,instance, cell->getInstances()) { Cell * subcell = (*instance)->getMasterCell(); if( (!(subcell->isLeaf())) ) getAllSolstices(subcell, solstices); } } void SolsticeEngine::insertInterval ( Brick*brick ,stack * enumResultStack) { while( !(enumResultStack->empty()) ) { Brick* findedbrick = dynamic_cast(enumResultStack->top()); enumResultStack->pop(); if(findedbrick->getHyperNet()!=brick->getHyperNet()) { // Shorts-Circuits Occurrence occurrence1 = brick->getComponentOccurrence(); Occurrence occurrence2 = findedbrick->getComponentOccurrence(); Path newpath1; Path newpath2; Cell * errorcell = getCommonPath(occurrence1.getPath(), occurrence2.getPath(), newpath1, newpath2); SolsticeEngine * solstice = NULL; if(errorcell) { solstice = get(errorcell); if(!solstice) { cout << getString(errorcell) <_routingErrors->insert(error); } } } void SolsticeEngine::removeInterval (Brick* item) { item->destroy(); } void SolsticeEngine::clearErrors() { for(set::iterator e = _routingErrors->begin(); e != _routingErrors->end() ; e++) (*e)->destroy(); _routingErrors->clear(); }; void SolsticeEngine::flushErrors() { forEach(Instance*,instance, _cell->getInstances()) { Cell * cell = (*instance)->getMasterCell(); SolsticeEngine * solstice = get(cell); if( (!(cell->isLeaf())) && (solstice->isCompared()) ) { solstice->flushErrors(); } } clearErrors(); setIsCompared(false); } }// End of namespace Solstice