// // This file is part of the Coriolis Project. // Copyright (C) Laboratoire LIP6 - Departement ASIM // Universite Pierre et Marie Curie // // Date : 29/01/2004 // Author : Hugo Clément #include #include #include "hurricane/Net.h" #include "hurricane/ContactLayer.h" #include "hurricane/BasicLayer.h" #include "hurricane/Plug.h" #include "hurricane/Pin.h" #include "hurricane/Error.h" #include "nimbus/Splitter.h" #include "nimbus/GCell.h" #include "nimbus/SplitterContact.h" #include "nimbus/RoutTools.h" namespace Nimbus { using namespace Hurricane; // **************************************************************************************************** // SplitterContact_Hooks declaration // **************************************************************************************************** class SplitterContact_Hooks : public Collection { // ******************************************* // Types // ***** public: typedef Collection Inherit; public: class Locator : public Hurricane::Locator { // ***************************************************** public: typedef Hurricane::Locator Inherit; private: const SplitterContact* _splittercontact; private: Hook* _hook; public: Locator(const SplitterContact* splittercontact = NULL); public: Locator(const Locator& locator); public: Locator& operator=(const Locator& locator); public: virtual Hook* getElement() const; public: virtual Hurricane::Locator* getClone() const; public: virtual bool isValid() const; public: virtual void progress(); public: virtual string _getString() const; }; // Attributes // ********** private: const SplitterContact* _splittercontact; // Constructors // ************ public: SplitterContact_Hooks(const SplitterContact* splittercontact = NULL); public: SplitterContact_Hooks(const SplitterContact_Hooks& hooks); // Operators // ********* public: SplitterContact_Hooks& operator=(const SplitterContact_Hooks& hooks); // Accessors // ********* public: virtual Collection* getClone() const; public: virtual Hurricane::Locator* getLocator() const; // Others // ****** public: virtual string _getString() const; }; // **************************************************************************************************** // SplitterContact implementation // **************************************************************************************************** SplitterContact::SplitterContact(Net* net, Layer* layer, const DbU::Unit& x, const DbU::Unit& y, const DbU::Unit& width, const DbU::Unit& height, GCell* gcell) // **************************************************************************************************** : Inherit(net), _anchorHook(this), _layer(layer), _dx(x), _dy(y), _width(width), _height(height), _gcell(gcell), _oppositePlugCount((std::numeric_limits::max)()), _oppositeSplitterCount((std::numeric_limits::max)()), _oppositePinCount((std::numeric_limits::max)()) { if (!_layer) throw Error("Can't create " + _TName("SplitterContact") + " : null layer"); } SplitterContact::SplitterContact(Net* net, Component* anchor, Layer* layer, const DbU::Unit& dx, const DbU::Unit& dy, const DbU::Unit& width, const DbU::Unit& height, GCell* gcell) // **************************************************************************************************** : Inherit(net), _anchorHook(this), _layer(layer), _dx(dx), _dy(dy), _width(width), _height(height), _gcell(gcell), _oppositePlugCount((std::numeric_limits::max)()), _oppositeSplitterCount((std::numeric_limits::max)()), _oppositePinCount((std::numeric_limits::max)()) { if (!anchor) throw Error("Can't create " + _TName("SplitterContact") + " : null anchor"); if (!anchor->getNet()) throw Error("Can't create " + _TName("SplitterContact") + " : unconnected anchor"); if (anchor->getNet() != getNet()) throw Error("Can't create " + _TName("SplitterContact") + " : incompatible anchor"); if (!_layer) throw Error("Can't create " + _TName("SplitterContact") + " : null layer"); _anchorHook.attach(anchor->getBodyHook()); } SplitterContact* SplitterContact::create(Net* net, Layer* layer, const DbU::Unit& x, const DbU::Unit& y, const DbU::Unit& width, const DbU::Unit& height, GCell* gcell) // **************************************************************************************************** { SplitterContact* splittercontact = new SplitterContact(net, layer, x, y, width, height, gcell); splittercontact->_postCreate(); return splittercontact; } SplitterContact* SplitterContact::create(Component* anchor, Layer* layer, const DbU::Unit& dx, const DbU::Unit& dy, const DbU::Unit& width, const DbU::Unit& height, GCell* gcell) // **************************************************************************************************** { if (!anchor) throw Error("Can't create " + _TName("SplitterContact") + " : null anchor"); SplitterContact* splittercontact = new SplitterContact(anchor->getNet(), anchor, layer, dx, dy, width, height, gcell); splittercontact->_postCreate(); return splittercontact; } Splitter* SplitterContact::getSplitter () const // ******************************************** { Component* compo = getAnchor (); if (!compo) { throw Error("Encounter of an unattached SplitterContact"); } if (Splitter* splitter = dynamic_cast(compo)) return splitter; else throw Error("A SplitterContact is parasiting a component other than a Splitter"); } Hook* SplitterContact::getOppositeBodyHook() //const // *********************************************** { Hook* h = getSplitter()->getOppositeBodyHook (getBodyHook()); return h; } SplitterContact* SplitterContact::getOppositeSplitterContact () //const // ******************************************************* { Component* compo = getOppositeBodyHook () -> getComponent (); assert (compo); if (SplitterContact* sc = dynamic_cast(compo)) return sc; else throw Error ("Unexpected component at the opposite side of the Splitter"); } GCells SplitterContact::getSubGCells() // const // *************************************** { GCells subs = getGCell()->getSubGCells(); return subs.getSubSet(getGCellFenceFilter(getSplitter()->getFence())); } unsigned int SplitterContact::getSPType() // ************************************** { Splitter* splitter = getSplitter(); assert ( splitter ); unsigned int spType; if ( splitter->isHorizontal() ) spType = Constant::Horizontal; else spType = Constant::Vertical; if ( splitter->getSplitterContact1() == this ) spType |= SP_1; else spType |= SP_2; return spType; } Hooks SplitterContact::getHooks() const // **************************** { return SplitterContact_Hooks(this); } DbU::Unit SplitterContact::getX() const // *********************** { Component* anchor = getAnchor(); return (!anchor) ? _dx : anchor->getX() + _dx; } DbU::Unit SplitterContact::getY() const // *********************** { Component* anchor = getAnchor(); return (!anchor) ? _dy : anchor->getY() + _dy; } Point SplitterContact::getPosition() const // ******************************* { Component* anchor = getAnchor(); return (!anchor) ? Point(_dx, _dy) : anchor->getPosition().translate(_dx, _dy); } Box SplitterContact::getBoundingBox() const // ******************************** { DbU::Unit size = _getSize(); return Box(getPosition()).inflate(getHalfWidth() + size, getHalfHeight() + size); } Box SplitterContact::getBoundingBox(const BasicLayer* basicLayer) const // ************************************************************* { if (!_layer->contains(basicLayer)) return Box(); DbU::Unit size = _getSize(basicLayer); return Box(getPosition()).inflate(getHalfWidth() + size, getHalfHeight() + size); } Component* SplitterContact::getAnchor() const // ********************************** { Hook* masterHook = _anchorHook.getMasterHook(); return (masterHook) ? masterHook->getComponent() : NULL; } void SplitterContact::translate(const DbU::Unit& dx, const DbU::Unit& dy) // **************************************************** { if ((dx != 0) || (dy != 0)) { invalidate(true); _dx += dx; _dy += dy; } } void SplitterContact::setGCell(GCell* gcell) // ************************************************** { _gcell = gcell; return; } void SplitterContact::setLayer(Layer* layer) // ********************************* { if (!layer) throw Error("Can't set layer : null layer"); if (layer != _layer) { invalidate(false); _layer = layer; } } void SplitterContact::setWidth(const DbU::Unit& width) // ************************************** { if (width != _width) { invalidate(false); _width = width; } } void SplitterContact::setHeight(const DbU::Unit& height) // **************************************** { if (height != _height) { invalidate(false); _height = height; } } void SplitterContact::setSizes(const DbU::Unit& width, const DbU::Unit& height) // ********************************************************** { if ((width != _width) || (height != _height)) { invalidate(false); _width = width; _height = height; } } void SplitterContact::setX(const DbU::Unit& x) // ****************************** { setPosition(x, getY()); } void SplitterContact::setY(const DbU::Unit& y) // ****************************** { setPosition(getX(), y); } void SplitterContact::setPosition(const DbU::Unit& x, const DbU::Unit& y) // **************************************************** { Component* anchor = getAnchor(); if (!anchor) setOffset(x, y); else setOffset(x - anchor->getX(), y - anchor->getY()); } void SplitterContact::setPosition(const Point& position) // ********************************************* { setPosition(position.getX(), position.getY()); } void SplitterContact::setDx(const DbU::Unit& dx) // ******************************** { setOffset(dx, _dy); } void SplitterContact::setDy(const DbU::Unit& dy) // ******************************** { setOffset(_dx, dy); } void SplitterContact::setOffset(const DbU::Unit& dx, const DbU::Unit& dy) // **************************************************** { if ((dx != _dx) || (dy != _dy)) { invalidate(true); _dx = dx; _dy = dy; } } unsigned SplitterContact::getOppositePlugCount() // ********************************************* { if (_oppositePlugCount == (std::numeric_limits::max)()) computeOppositeCounts(); return _oppositePlugCount; } unsigned SplitterContact::getOppositeSplitterCount() // ************************************************* { if (_oppositeSplitterCount == (std::numeric_limits::max)()) computeOppositeCounts(); return _oppositeSplitterCount; } unsigned SplitterContact::getOppositePinCount() // ******************************************** { if (_oppositePinCount == (std::numeric_limits::max)()) computeOppositeCounts(); return _oppositePinCount; } void SplitterContact::computeOppositeCounts() // ****************************************** { unsigned plugCount = 0; unsigned splitterCount = 0; unsigned pinCount = 0; SplitterContact* oppSC = getOppositeSplitterContact(); for_each_hook(hook, oppSC->getBodyHook()->getHooks()) { Component* compo = hook->getComponent(); if (SplitterContact* sc = dynamic_cast (compo)) { if (sc == oppSC) continue; plugCount += sc->getOppositePlugCount(); splitterCount += 1 + sc->getOppositeSplitterCount(); pinCount += sc->getOppositePinCount(); } if (dynamic_cast (compo)) { ++plugCount; } if (dynamic_cast (compo)) { ++pinCount; } end_for; } _oppositePlugCount = plugCount; _oppositeSplitterCount = splitterCount; _oppositePinCount = pinCount; return; } void SplitterContact::invalidateOppositeCounts() // ********************************************* { _oppositePlugCount = (std::numeric_limits::max)(); _oppositeSplitterCount = (std::numeric_limits::max)(); _oppositePinCount = (std::numeric_limits::max)(); return; } void SplitterContact::_preDestroy() // ******************************* { // trace << "entering SplitterContact::PreDelete: " << this << endl; // trace_in(); Inherit::_preDestroy(); Component* anchor = getAnchor (); if (anchor) { _anchorHook.detach(); anchor->destroy (); } // trace << "exiting SplitterContact::PreDelete:" << endl; // trace_out(); } string SplitterContact::_getString() const // ******************************* { string s = Inherit::_getString(); s.insert(s.length() - 1, " " + getString(_layer->getName())); s.insert(s.length() - 1, " [" + DbU::getValueString(getX())); s.insert(s.length() - 1, " " + DbU::getValueString(getY())); s.insert(s.length() - 1, "] " + DbU::getValueString(_width)); s.insert(s.length() - 1, "x" + DbU::getValueString(_height)); return s; } Record* SplitterContact::_getRecord() const // ************************** { Record* record = Inherit::_getRecord(); if (record) { record->add(getSlot("AnchorHook", &_anchorHook)); record->add(getSlot("Anchor", getAnchor())); record->add(getSlot("Layer", _layer)); record->add(getSlot("Dx", &_dx)); record->add(getSlot("Dy", &_dy)); record->add(getSlot("Width", &_width)); record->add(getSlot("Height", &_height)); if (_oppositePlugCount == (std::numeric_limits::max)()) const_cast(this)->computeOppositeCounts(); record->add(getSlot("OppositePlugCount", &_oppositePlugCount)); record->add(getSlot("OppositeSplitterCount", &_oppositeSplitterCount)); record->add(getSlot("OppositePinCount", &_oppositePinCount)); } return record; } DbU::Unit SplitterContact::_getSize() const // *************************** { DbU::Unit size = 0; const Layer* layer = getLayer(); if (const ContactLayer* contactLayer = dynamic_cast(layer)) size = contactLayer->getEnclosure(); return size; } DbU::Unit SplitterContact::_getSize(const BasicLayer* basicLayer) const // ************************************************* { const Layer* layer = getLayer(); if (!layer->contains(basicLayer)) return 0; DbU::Unit size = 0; if (const ContactLayer* contactLayer = dynamic_cast(layer)) size = contactLayer->getEnclosure(basicLayer); return size; } // void SplitterContact::_Draw(View* view, BasicLayer* basicLayer, const Box& updateArea, const Transformation& transformation) // // **************************************************************************************************** // { // if (_width && _height) { // if (1 < view->getScreenSize(max(_width, _height))) // basicLayer->_Fill(view, transformation.getBox(getBoundingBox(basicLayer))); // } // if (basicLayer == _layer->_getSymbolicBasicLayer()) { // if (view->CutPointsAreVisible() && (3 < view->getScale())) { // Point position = getPosition(); // view->DrawPoint(transformation.getPoint(position), 3); // if (_width) { // Box box = transformation.getBox(Box(position).Inflate(getHalfWidth(), 0)); // view->DrawLine(box.getXMin(), box.getYMin(), box.getXMax(), box.getYMax()); // } // if (_height) { // Box box = transformation.getBox(Box(position).Inflate(0, getHalfHeight())); // view->DrawLine(box.getXMin(), box.getYMin(), box.getXMax(), box.getYMax()); // } // } // } // } // void SplitterContact::_Highlight(View* view, const Box& updateArea, const Transformation& transformation) // // ********************************************************************************************** // { // if (_width && _height) { // if (1 < view->getScreenSize(max(_width, _height))) { // for_each_basic_layer(basicLayer, getLayer()->getBasicLayers()) { // basicLayer->_Fill(view, transformation.getBox(getBoundingBox(basicLayer))); // end_for; // } // } // } // if (view->getScale() <= 1) // view->DrawPoint(transformation.getPoint(getPosition()), 1); // else if (view->getScale() <= 3) // view->DrawPoint(transformation.getPoint(getPosition()), 2); // else { // Point position = getPosition(); // view->DrawPoint(transformation.getPoint(position), 3); // if (_width) { // Box box = transformation.getBox(Box(position).Inflate(getHalfWidth(), 0)); // view->DrawLine(box.getXMin(), box.getYMin(), box.getXMax(), box.getYMax()); // } // if (_height) { // Box box = transformation.getBox(Box(position).Inflate(0, getHalfHeight())); // view->DrawLine(box.getXMin(), box.getYMin(), box.getXMax(), box.getYMax()); // } // } // getSplitter()->_Highlight ( view, updateArea, transformation ); // } // void SplitterContact::_SaveHeaderTo(OutputFile& outputFile) // // ************************************************ // { // Inherit::_SaveHeaderTo(outputFile); // outputFile << " " << outputFile.getId(getAnchor()); // outputFile << " " << outputFile.getId(getLayer()); // outputFile << " " << getValueString(getDx()); // outputFile << " " << getValueString(getDy()); // outputFile << " " << getValueString(getWidth()); // outputFile << " " << getValueString(getHeight()); // } // **************************************************************************************************** // SplitterContact::AnchorHook implementation // **************************************************************************************************** static int ANCHOR_HOOK_OFFSET = -1; SplitterContact::AnchorHook::AnchorHook(SplitterContact* splittercontact) // ********************************************** : Inherit() { if (!splittercontact) throw Error("Can't create " + _TName("SplitterContact::AnchorHook") + " : null splittercontact"); if (ANCHOR_HOOK_OFFSET == -1) ANCHOR_HOOK_OFFSET = (unsigned long)this - (unsigned long)splittercontact; } Component* SplitterContact::AnchorHook::getComponent() const // ************************************************* { return (Component*)((unsigned long)this - ANCHOR_HOOK_OFFSET); } string SplitterContact::AnchorHook::_getString() const // ******************************************* { return "<" + _TName("SplitterContact::AnchorHook") + " " + getString(getComponent()) + ">"; } // **************************************************************************************************** // SplitterContact_Hooks implementation // **************************************************************************************************** SplitterContact_Hooks::SplitterContact_Hooks(const SplitterContact* splittercontact) // ************************************************* : Inherit(), _splittercontact(splittercontact) { } SplitterContact_Hooks::SplitterContact_Hooks(const SplitterContact_Hooks& hooks) // ***************************************************** : Inherit(), _splittercontact(hooks._splittercontact) { } SplitterContact_Hooks& SplitterContact_Hooks::operator=(const SplitterContact_Hooks& hooks) // **************************************************************** { _splittercontact = hooks._splittercontact; return *this; } Collection* SplitterContact_Hooks::getClone() const // *********************************************** { return new SplitterContact_Hooks(*this); } Locator* SplitterContact_Hooks::getLocator() const // ********************************************** { return new Locator(_splittercontact); } string SplitterContact_Hooks::_getString() const // ************************************* { string s = "<" + _TName("SplitterContact::Hooks"); if (_splittercontact) s += " " + getString(_splittercontact); s += ">"; return s; } // **************************************************************************************************** // SplitterContact_Hooks::Locator implementation // **************************************************************************************************** SplitterContact_Hooks::Locator::Locator(const SplitterContact* splittercontact) // **************************************************** : Inherit(), _splittercontact(splittercontact), _hook(NULL) { if (_splittercontact) _hook = ((SplitterContact*)_splittercontact)->getBodyHook(); } SplitterContact_Hooks::Locator::Locator(const Locator& locator) // **************************************************** : Inherit(), _splittercontact(locator._splittercontact), _hook(locator._hook) { } SplitterContact_Hooks::Locator& SplitterContact_Hooks::Locator::operator=(const Locator& locator) // ****************************************************************************** { _splittercontact = locator._splittercontact; _hook = locator._hook; return *this; } Hook* SplitterContact_Hooks::Locator::getElement() const // ********************************************* { return _hook; } Locator* SplitterContact_Hooks::Locator::getClone() const // ***************************************************** { return new Locator(*this); } bool SplitterContact_Hooks::Locator::isValid() const // ***************************************** { return (_hook != NULL); } void SplitterContact_Hooks::Locator::progress() // ************************************ { if (_hook) { if (_hook == ((SplitterContact*)_splittercontact)->getBodyHook()) _hook = ((SplitterContact*)_splittercontact)->getAnchorHook(); else _hook = NULL; } } string SplitterContact_Hooks::Locator::_getString() const // ********************************************** { string s = "<" + _TName("SplitterContact::Hooks::Locator"); if (_splittercontact) s += " " + getString(_splittercontact); s += ">"; return s; } // --------------------------------------------------------------- // Function : "getStringDir()". string getStringDir ( unsigned int direction ) { switch ( direction ) { case SplitterContact::SP_1: return "SP_1"; case SplitterContact::SP_2: return "SP_2"; case SplitterContact::SP_LEFT: return "SP_LEFT"; case SplitterContact::SP_RIGHT: return "SP_RIGHT"; case SplitterContact::SP_TOP: return "SP_TOP"; case SplitterContact::SP_BOTTOM: return "SP_BOTTOM"; case Constant::Horizontal: return "Horizontal"; case Constant::Vertical: return "Vertical"; } return "Unknown direction code"; } } // End of Nimbus namespace.