329 lines
10 KiB
C++
329 lines
10 KiB
C++
// -*- 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<Interval> _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<RowFeed*> _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<Interval>::iterator imerge = _instanceSpans.end();
|
|
list<Interval>::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<Interval>::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<rowsNb ; ++irow )
|
|
_rowFeeds.push_back ( new RowFeed(this,Box(_area.getXMin()
|
|
, irow * sliceHeight
|
|
,_area.getXMax()
|
|
,(irow+1) * sliceHeight )) );
|
|
}
|
|
|
|
|
|
SurfaceFeeds::~SurfaceFeeds ()
|
|
{
|
|
for ( size_t irow=0 ; irow<_rowFeeds.size() ; ++irow )
|
|
delete _rowFeeds[irow];
|
|
}
|
|
|
|
|
|
inline MaukaEngine* SurfaceFeeds::getMauka () { return _mauka; }
|
|
|
|
|
|
void SurfaceFeeds::addInstanceOccurrence ( Occurrence occurrence )
|
|
{
|
|
Instance* instance = dynamic_cast<Instance*>(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)irow<rowStop ; ++irow ) {
|
|
_rowFeeds[irow]->mergeInstanceSpan ( 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.
|