// -*- C++ -*- // // This file is part of the Coriolis Software. // Copyright (c) UPMC 2008-2018, All Rights Reserved // // +-----------------------------------------------------------------+ // | C O R I O L I S | // | M a u k a - P l a c e r | // | | // | Author : Jean-Paul CHAPUT | // | E-mail : Jean-Paul.Chaput@asim.lip6.fr | // | =============================================================== | // | C++ Module : "./InsertFeeds.cpp" | // +-----------------------------------------------------------------+ #include "hurricane/UpdateSession.h" #include "crlcore/ToolBox.h" #include "mauka/MaukaEngine.h" namespace { using namespace std; using namespace Mauka; using namespace Hurricane; using namespace CRL; // ------------------------------------------------------------------- // Class : "::RowFeed" class SurfaceFeeds; class RowFeed { public: RowFeed ( SurfaceFeeds*, const Box& bb ); inline const Box& getBox () const; inline SurfaceFeeds* getSurfaceFeeds (); inline MaukaEngine* getMauka (); inline void setOrientation ( Transformation::Orientation ); void mergeInstanceSpan ( DbU::Unit source, DbU::Unit target ); void insertTieChunk ( DbU::Unit xmin , DbU::Unit xmax , DbU::Unit y , const Transformation::Orientation& ); void insertFeeds (); private: SurfaceFeeds* _surface; Box _boundingBox; Transformation::Orientation _orientation; list _instanceSpans; }; // ------------------------------------------------------------------- // Class : "::SurfaceFeeds" class SurfaceFeeds { public: SurfaceFeeds ( MaukaEngine* ); ~SurfaceFeeds (); inline MaukaEngine* getMauka (); void addInstanceOccurrence ( Occurrence ); void insertFeeds (); private: void _orientRows ( Transformation::Orientation ); private: MaukaEngine* _mauka; Box _area; vector _rowFeeds; bool _oriented; }; // ------------------------------------------------------------------- // Class Implantation : "::RowFeed" RowFeed::RowFeed ( SurfaceFeeds* surface, const Box& bb ) : _surface (surface) , _boundingBox (bb) , _orientation (Transformation::Orientation::ID) , _instanceSpans() { } inline const Box& RowFeed::getBox () const { return _boundingBox; } inline MaukaEngine* RowFeed::getMauka () { return _surface->getMauka(); } inline void RowFeed::setOrientation ( Transformation::Orientation orientation ) { _orientation = orientation; } void RowFeed::mergeInstanceSpan ( DbU::Unit source, DbU::Unit target ) { Interval spanMerge ( source, target ); list::iterator imerge = _instanceSpans.end(); list::iterator ispan = _instanceSpans.begin(); while ( ispan != _instanceSpans.end() ) { if ( spanMerge.getVMax() < (*ispan).getVMin() ) break; if ( spanMerge.intersect(*ispan) ) { if ( imerge == _instanceSpans.end() ) { imerge = ispan; (*imerge).merge ( spanMerge ); } else { (*imerge).merge ( *ispan ); ispan = _instanceSpans.erase ( ispan ); continue; } } ispan++; } if ( imerge == _instanceSpans.end() ) { _instanceSpans.insert ( ispan, spanMerge ); } } void RowFeed::insertTieChunk ( DbU::Unit xmin , DbU::Unit xmax , DbU::Unit y , const Transformation::Orientation& orientation ) { Cell* feed = getMauka()->getFeedCells().getBiggestFeed(); if ( feed == NULL ) { cerr << Error("No feed has been registered, ignoring.") << endl; } DbU::Unit feedWidth = feed->getAbutmentBox().getWidth(); DbU::Unit xtie = xmin; while ( true ) { if ( xtie >= xmax ) break; if ( xtie+feedWidth > xmax ) { // Feed is too big, try to find a smaller one. int pitch = (int)((xmax-xtie) / getMauka()->getPitch()); for ( ; pitch > 0 ; --pitch ) { feed = getMauka()->getFeedCells().getFeed ( pitch ); feedWidth = feed->getAbutmentBox().getWidth(); if ( feed != NULL ) break; } if ( feed == NULL ) break; } Instance::create ( getMauka()->getCell() , getMauka()->getFeedCells().getNewFeedName().c_str() , feed , getTransformation(feed->getAbutmentBox(),xtie,y,orientation) , Instance::PlacementStatus::PLACED ); xtie += feedWidth; } } void RowFeed::insertFeeds () { list::iterator ispan = _instanceSpans.begin(); DbU::Unit minFeed = _boundingBox.getXMin(); DbU::Unit maxFeed; if ( ispan == _instanceSpans.end() ) { maxFeed = _boundingBox.getXMax(); insertTieChunk ( minFeed, maxFeed, _boundingBox.getYMin(), _orientation ); return; } maxFeed = (*ispan).getVMin(); insertTieChunk ( minFeed, maxFeed, _boundingBox.getYMin(), _orientation ); while ( ispan != _instanceSpans.end() ) { minFeed = (*ispan).getVMax(); if ( ++ispan != _instanceSpans.end() ) maxFeed = (*ispan).getVMin(); else maxFeed = _boundingBox.getXMax(); insertTieChunk ( minFeed, maxFeed, _boundingBox.getYMin(), _orientation ); } } // ------------------------------------------------------------------- // Class Implantation : "::SurfaceFeeds" SurfaceFeeds::SurfaceFeeds ( MaukaEngine* mauka ) : _mauka (mauka) , _area (mauka->getCell()->getAbutmentBox()) , _rowFeeds() , _oriented(false) { DbU::Unit sliceHeight = _mauka->getSliceHeight(); size_t rowsNb = _area.getHeight() / sliceHeight; _rowFeeds.reserve ( rowsNb ); for ( size_t irow=0 ; irow(occurrence.getEntity()); if ( instance == NULL ) { cerr << Error("Entity of occurrence %s is not an instance." ,getString(occurrence).c_str()) << endl; return; } DbU::Unit sliceHeight = _mauka->getSliceHeight(); Box masterABox = instance->getAbutmentBox(); Transformation transformation = occurrence.getPath().getTransformation(); transformation.applyOn(masterABox); Transformation::Orientation orientation = occurrence.getPath().getTransformation().getOrientation(); int rowStart = (masterABox.getYMin() - _area.getYMin()) / sliceHeight; int rowStop = (masterABox.getYMax() - _area.getYMin()) / sliceHeight; if ( (rowStart < 0) or (rowStop > (int)_rowFeeds.size()) ) { cerr << Error("Instance %s (AB:%s) is outside the placement area." ,getString(occurrence).c_str() ,getString(masterABox).c_str() ) << endl; return; } if ( not _oriented ) { size_t instanceRowMY = 0; switch ( orientation ) { case Transformation::Orientation::ID: instanceRowMY = 0; break; default: case Transformation::Orientation::MY: instanceRowMY = 1; break; } Transformation::Orientation rowZeroOrientation = Transformation::Orientation::ID; switch ( (rowStart+instanceRowMY) % 2 ) { case 0: orientation = Transformation::Orientation::ID; break; case 1: orientation = Transformation::Orientation::MY; break; } _orientRows ( rowZeroOrientation ); } for ( size_t irow = rowStart ; (int)irowmergeInstanceSpan ( masterABox.getXMin(), masterABox.getXMax() ); } } void SurfaceFeeds::insertFeeds () { for ( size_t irow=0 ; irow<_rowFeeds.size() ; ++irow ) _rowFeeds[irow]->insertFeeds (); } void SurfaceFeeds::_orientRows ( Transformation::Orientation rowZeroOrientation ) { if ( _oriented ) return; _oriented = true; size_t rowZeroMY = 0; switch ( rowZeroOrientation ) { case Transformation::Orientation::ID: rowZeroMY = 0; break; default: case Transformation::Orientation::MY: rowZeroMY = 1; break; } for ( size_t irow=0 ; irow<_rowFeeds.size() ; ++irow ) { Transformation::Orientation orientation = Transformation::Orientation::ID; switch ( (irow+rowZeroMY) % 2 ) { case 0: orientation = Transformation::Orientation::ID; break; case 1: orientation = Transformation::Orientation::MY; break; } _rowFeeds[irow]->setOrientation(orientation); } } } // End of anonymous namespace. namespace Mauka { using Hurricane::UpdateSession; void MaukaEngine::insertFeeds () { UpdateSession::open (); SurfaceFeeds surfaceFeeds ( this ); forEach ( Occurrence, ioccurrence, getCell()->getTerminalNetlistInstanceOccurrences() ) { surfaceFeeds.addInstanceOccurrence ( *ioccurrence ); } surfaceFeeds.insertFeeds (); UpdateSession::close (); } } // End of Mauka namespace.