457 lines
14 KiB
C++
457 lines
14 KiB
C++
// -*- C++ -*-
|
|
//
|
|
// This file is part of the Coriolis Software.
|
|
// Copyright (c) UPMC 2015-2018, All Rights Reserved
|
|
//
|
|
// +-----------------------------------------------------------------+
|
|
// | C O R I O L I S |
|
|
// | B o r a - A n a l o g S l i c i n g T r e e |
|
|
// | |
|
|
// | Authors : Eric LAO |
|
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
|
// | =============================================================== |
|
|
// | C++ Module : "./HVSlicingNode.cpp" |
|
|
// +-----------------------------------------------------------------+
|
|
|
|
|
|
#include "hurricane/Error.h"
|
|
#include "hurricane/Warning.h"
|
|
#include "crlcore/RoutingGauge.h"
|
|
#include "bora/HVSetState.h"
|
|
#include "bora/HSlicingNode.h"
|
|
#include "bora/RHSlicingNode.h"
|
|
|
|
|
|
namespace Bora {
|
|
|
|
using namespace std;
|
|
using Hurricane::Error;
|
|
using Hurricane::Warning;
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
// Class : "Bora::HSlicingNode".
|
|
|
|
|
|
int HSlicingNode::_count = 0;
|
|
int HSlicingNode::_countAll = 0;
|
|
|
|
|
|
HSlicingNode::HSlicingNode ( unsigned int type, unsigned int alignment )
|
|
: HVSlicingNode(type,alignment)
|
|
{ ++_count; }
|
|
|
|
|
|
HSlicingNode::~HSlicingNode ()
|
|
{ --_count; }
|
|
|
|
|
|
HSlicingNode* HSlicingNode::create ( unsigned int alignment )
|
|
{
|
|
--_countAll;
|
|
return new HSlicingNode( HorizontalSNode, alignment );
|
|
}
|
|
|
|
|
|
void HSlicingNode::createRouting( DbU::Unit space )
|
|
{
|
|
push_back( RHSlicingNode::create( space ) );
|
|
resetSlicingTree();
|
|
}
|
|
|
|
|
|
void HSlicingNode::print () const
|
|
{
|
|
cerr << "- Print from Slicing Node - " << endl;
|
|
cerr << "SlicingType: Horizontal Node" << endl;
|
|
if (isAlignLeft ()) cerr << "Alignment : Left" << endl;
|
|
else if (isAlignCenter()) cerr << "Alignment : Middle" << endl;
|
|
else if (isAlignRight ()) cerr << "Alignment : Right" << endl;
|
|
else cerr << "Alignment : Unknown" << endl;
|
|
cerr << "Tolerances : RatioH: " << DbU::getPhysical(_toleranceRatioH,DbU::Micro)
|
|
<< ", RatioW: " << DbU::getPhysical(_toleranceRatioW,DbU::Micro)
|
|
<< ", BandH: " << DbU::getPhysical(_toleranceBandH ,DbU::Micro)
|
|
<< ", BandW: " << DbU::getPhysical(_toleranceBandW ,DbU::Micro) << endl;
|
|
|
|
HVSlicingNode::print();
|
|
}
|
|
|
|
|
|
HSlicingNode* HSlicingNode::clone ( unsigned int tr )
|
|
{
|
|
HSlicingNode* node = HSlicingNode::create( getAlignment() );
|
|
node->setTolerances( getToleranceRatioH()
|
|
, getToleranceRatioW()
|
|
, getToleranceBandH ()
|
|
, getToleranceBandW ()
|
|
);
|
|
node->setBoxSet ( getBoxSet() );
|
|
node->setNodeSets ( _nodeSets->clone() );
|
|
node->setPreset ( getPreset() );
|
|
node->setSet ( getSet() );
|
|
node->setPlaced ( getPlaced() );
|
|
node->setSymmetries( getSymmetries() );
|
|
|
|
for ( SlicingNode* child : _children ) {
|
|
if (tr == MY) node->push_front( child->clone(tr) );
|
|
else node->push_back ( child->clone(tr) );
|
|
}
|
|
return node;
|
|
}
|
|
|
|
|
|
void HSlicingNode::place ( DbU::Unit x, DbU::Unit y )
|
|
{
|
|
if (recursiveCheckSet()) {
|
|
if (not _slicingRouting.empty()) {
|
|
destroySlicingRouting();
|
|
resetSlicingRouting();
|
|
}
|
|
_place(x,y);
|
|
|
|
if (_slicingRouting.empty())
|
|
createSlicingRouting();
|
|
|
|
updateCellAbutmentBox();
|
|
} else
|
|
cerr << Warning( "HSlicingNode::place(): The SlicingTree is not completely set." ) << endl;
|
|
}
|
|
|
|
|
|
void HSlicingNode::replace ( DbU::Unit x, DbU::Unit y )
|
|
{
|
|
// WARNING: This will change GCell edges.
|
|
|
|
if (recursiveCheckSet()) {
|
|
_place( x, y, true );
|
|
updateCellAbutmentBox();
|
|
updateGCellPosition ();
|
|
updateGContacts ();
|
|
} else {
|
|
cerr << Warning( "HSlicingNode::replace(): The SlicingTree is not completely set." ) << endl;
|
|
}
|
|
}
|
|
|
|
|
|
void HSlicingNode::_place ( DbU::Unit x, DbU::Unit y, bool replace )
|
|
{
|
|
cdebug_log(536,1) << "HSlicingNode::_place(DbU::Unit,DbU::Unit,bool)" << endl;
|
|
|
|
vector<RHVSlicingNode*>::iterator itspace = _slicingRouting.begin();
|
|
DbU::Unit xref = x;
|
|
DbU::Unit yref = y;
|
|
|
|
if (isRoutingEstimated()) {
|
|
(*itspace)->_place( xref, yref, replace );
|
|
yref += (*itspace)->getHeight();
|
|
itspace++;
|
|
}
|
|
|
|
for ( SlicingNode* child : _children ) {
|
|
if ( (child->isHorizontal()) or (child->isVertical()) ) {
|
|
if (child->isAlignLeft()) {
|
|
child->setX( xref );
|
|
child->setY( yref );
|
|
} else if (child->isAlignCenter()) {
|
|
child->setX( xref + (getWidth()/2) - (child->getWidth()/2) );
|
|
child->setY( yref );
|
|
} else if (child->isAlignRight()) {
|
|
child->setX( xref + getWidth() - child->getWidth() );
|
|
child->setY( yref );
|
|
}
|
|
}
|
|
|
|
if (child->isAlignLeft() ) child->_place( xref , yref, replace);
|
|
else if (child->isAlignCenter()) child->_place( xref + (getWidth()/2) - (child->getWidth()/2), yref, replace);
|
|
else if (child->isAlignRight() ) child->_place( xref + getWidth() - child->getWidth() , yref, replace);
|
|
else if (child->isRouting() ) child->_place( xref , yref, replace);
|
|
else {
|
|
cerr << Warning( "HSlicingNode::_place(): Unknown Alignment in SlicingTree." ) << endl;
|
|
child->print();
|
|
}
|
|
|
|
xref = x;
|
|
yref += child->getHeight();
|
|
if (isRoutingEstimated()) {
|
|
(*itspace)->_place( xref, yref, replace );
|
|
yref += (*itspace)->getHeight();
|
|
itspace++;
|
|
}
|
|
}
|
|
|
|
setPlaced( Placed );
|
|
|
|
cdebug_tabw(536,-1);
|
|
}
|
|
|
|
|
|
void HSlicingNode::updateGlobalSize ()
|
|
{
|
|
cdebug_log(535,1) << "HSlicingNode::updateGlobalsize() - " << this << endl;
|
|
|
|
for ( SlicingNode* child : _children ) {
|
|
cdebug_log(535,0) << "child: " << child << endl;
|
|
child->updateGlobalSize();
|
|
}
|
|
|
|
if (not getMaster()) {
|
|
if (getNbChild() == 1) {
|
|
_nodeSets->clear();
|
|
NodeSets* node = _children[0]->getNodeSets();
|
|
|
|
for ( BoxSet* bs : node->getBoxSets() ) {
|
|
vector<BoxSet*> bss;
|
|
|
|
bss.push_back( bs );
|
|
_nodeSets->push_back( bss, bs->getHeight(), bs->getWidth(), HorizontalSNode );
|
|
}
|
|
} else if ( not hasEmptyChildrenNodeSets() and _nodeSets->empty() ) {
|
|
HSetState state = HSetState( this );
|
|
while ( not state.end() ) state.next();
|
|
|
|
_nodeSets = state.getNodeSets();
|
|
}
|
|
if (_nodeSets->empty())
|
|
cerr << Warning( "HSlicingNode::updateGlobalSize(): No solution has been found, try to set larger tolerances." ) << endl;
|
|
} else {
|
|
_nodeSets = _master->getNodeSets();
|
|
}
|
|
|
|
cdebug_log(535,0) << "Found " << _nodeSets->size() << " choices" << endl;
|
|
cdebug_tabw(535,-1);
|
|
}
|
|
|
|
|
|
void HSlicingNode::preDestroy ()
|
|
{
|
|
HVSlicingNode::preDestroy();
|
|
}
|
|
|
|
|
|
void HSlicingNode::destroy ()
|
|
{
|
|
HSlicingNode::preDestroy();
|
|
delete this;
|
|
}
|
|
|
|
|
|
void HSlicingNode::preRecursiveDestroy ()
|
|
{
|
|
HVSlicingNode::preRecursiveDestroy();
|
|
}
|
|
|
|
|
|
void HSlicingNode::recursiveDestroy ()
|
|
{
|
|
HSlicingNode::preRecursiveDestroy();
|
|
delete this;
|
|
}
|
|
|
|
|
|
void HSlicingNode::createSlicingRouting ()
|
|
{
|
|
if (not _boxSet) {
|
|
cerr << Warning( "HSlicingNode::createSlicingRouting(): SlicingTree needs to be placed first." ) << endl;
|
|
return;
|
|
}
|
|
|
|
size_t childrenCount = getNbChild();
|
|
size_t ichild = 0;
|
|
DbU::Unit x = getX();
|
|
DbU::Unit y = getY();
|
|
DbU::Unit heightValue = 0;
|
|
|
|
if (_parent) {
|
|
if (_parent->getType() == VerticalSNode) {
|
|
if ( (getAlignment() == AlignBottom) or (getAlignment() == AlignTop) ) {
|
|
heightValue = _parent->getHeight() - getHeight();
|
|
} else if (getAlignment() == AlignCenter) {
|
|
heightValue = (_parent->getHeight() - getHeight()) / 2;
|
|
}
|
|
}
|
|
}
|
|
|
|
DbU::Unit hpitch = _rg->getHorizontalPitch();
|
|
if (heightValue % hpitch)
|
|
cerr << Warning( "HSlicingNode::createSlicingRouting(): On %s, height is not pitched (%s, pitch:%s)."
|
|
, getString(this).c_str()
|
|
, DbU::getValueString(heightValue).c_str()
|
|
, DbU::getValueString(hpitch).c_str()
|
|
) << endl;
|
|
|
|
for ( size_t inode=0; inode<childrenCount+1; ++inode ) {
|
|
RHSlicingNode* node = NULL;
|
|
if (inode == 0) {
|
|
if ( (getAlignment() == AlignTop )
|
|
or (getAlignment() == AlignCenter) ) node = RHSlicingNode::create( heightValue );
|
|
else node = RHSlicingNode::create();
|
|
} else if (inode == childrenCount) {
|
|
if ( (getAlignment() == AlignBottom)
|
|
or (getAlignment() == AlignCenter) ) node = RHSlicingNode::create( heightValue );
|
|
else node = RHSlicingNode::create();
|
|
} else
|
|
node = RHSlicingNode::create();
|
|
|
|
node->setParent( this );
|
|
|
|
if (inode == 0) {
|
|
if (getAlignment() == AlignBottom) node->place( x, y );
|
|
else if ( (getAlignment() == AlignCenter)
|
|
or (getAlignment() == AlignTop) ) node->place( x, y-heightValue );
|
|
} else
|
|
node->place( x, y );
|
|
|
|
if (_master) node->setMaster( _master->getSlicingRouting(inode) );
|
|
_slicingRouting.push_back( node );
|
|
|
|
if (inode < childrenCount) y += getChild( ichild++ )->getHeight();
|
|
}
|
|
|
|
if (_master) {
|
|
if (isHSymmetry()) {
|
|
for ( size_t i=0; i<_slicingRouting.size(); ++i )
|
|
getSlicingRouting( i )->setMaster( _master->getSlicingRouting( _slicingRouting.size()-1-i ) );
|
|
} else {
|
|
for ( size_t i=0; i<_slicingRouting.size(); ++i )
|
|
getSlicingRouting( i )->setMaster( _master->getSlicingRouting( i ) );
|
|
}
|
|
} else if ( not _symmetries.empty() and isAlignCenter() ) {
|
|
for ( size_t i=0; i<(_slicingRouting.size()/2); ++i ) {
|
|
getSlicingRouting( _slicingRouting.size()-1-i )->setMaster( getSlicingRouting(i) );
|
|
}
|
|
}
|
|
|
|
for ( SlicingNode* child : _children ) {
|
|
if ( child->isHorizontal() or child->isVertical() ) child->createSlicingRouting();
|
|
}
|
|
|
|
setRoutingCreated( RoutingCreated );
|
|
}
|
|
|
|
|
|
DbU::Unit HSlicingNode::getHeight () const
|
|
{
|
|
DbU::Unit hpitch = _rg->getHorizontalPitch();
|
|
DbU::Unit height = 0;
|
|
|
|
if (isRoutingEstimated()){
|
|
for ( SlicingNode* child : _children ) height += child->getHeight();
|
|
for ( RHVSlicingNode* node : _slicingRouting ) height += node ->getHeight();
|
|
} else {
|
|
if (_boxSet != NULL) height = _boxSet->getHeight();
|
|
}
|
|
|
|
if (height % hpitch)
|
|
cerr << Warning( "HSlicingNode::getHeight(): On %s, height is not pitched (%s, pitch:%s)."
|
|
, getString(this).c_str()
|
|
, DbU::getValueString(height).c_str()
|
|
, DbU::getValueString(hpitch).c_str()
|
|
) << endl;
|
|
return height;
|
|
}
|
|
|
|
|
|
DbU::Unit HSlicingNode::getWidth () const
|
|
{
|
|
cdebug_log(536,0) << "HSlicingNode::getWidth()" << endl;
|
|
|
|
DbU::Unit vpitch = _rg->getVerticalPitch();
|
|
DbU::Unit width = 0;
|
|
|
|
if (isRoutingEstimated()) {
|
|
SlicingNode* m = NULL;
|
|
for ( SlicingNode* node : _children ) {
|
|
if ( (node->getType() != RoutingSNode) and (node->getWidth() > width) ) {
|
|
width = node->getWidth();
|
|
m = node;
|
|
}
|
|
}
|
|
if (m->isDevice()) width += vpitch*2;
|
|
} else {
|
|
if (_boxSet) width = _boxSet->getWidth();
|
|
}
|
|
|
|
if (width % vpitch)
|
|
cerr << Warning( "HSlicingNode::getWidth(): On %s, width is not pitched (%s, pitch:%s)."
|
|
, getString(this).c_str()
|
|
, DbU::getValueString(width).c_str()
|
|
, DbU::getValueString(vpitch).c_str()
|
|
) << endl;
|
|
return width;
|
|
}
|
|
|
|
|
|
void HSlicingNode::setGCell ( Anabatic::GCell* gcell )
|
|
{
|
|
cdebug_log(535,1) << "HSlicingNode::setGCell(), start Y: "
|
|
<< _slicingRouting[0]->getY() << ", GCell:" << gcell << endl;
|
|
|
|
Anabatic::GCell* childGCell = gcell;
|
|
Anabatic::GCell* remainGCell = gcell;
|
|
DbU::Unit y = _slicingRouting[0]->getY();
|
|
|
|
for ( size_t ichild=0 ; ichild<_children.size() ; ++ichild ) {
|
|
// Setting up the GCell for the channel *before* the current child.
|
|
cdebug_log(535,0) << "node[" << ichild << "] height:"
|
|
<< DbU::getValueString(_slicingRouting[ ichild ]->getHeight()) << endl;
|
|
|
|
y += _slicingRouting[ ichild ]->getHeight();
|
|
remainGCell = childGCell->hcut( y );
|
|
_slicingRouting[ ichild ]->setGCell( childGCell );
|
|
childGCell = remainGCell;
|
|
|
|
// Setting up the GCell for the current child.
|
|
cdebug_log(535,0) << "children[" << ichild << "] height:"
|
|
<< DbU::getValueString(_children[ ichild ]->getHeight()) << endl;
|
|
|
|
y += _children[ ichild ]->getHeight();
|
|
remainGCell = childGCell->hcut( y );
|
|
_children[ ichild ]->setGCell( childGCell );
|
|
childGCell = remainGCell;
|
|
}
|
|
|
|
// Setting up the GCell for the channel *after* the last child.
|
|
_slicingRouting.back()->setGCell( childGCell );
|
|
|
|
cdebug_tabw(535,-1);
|
|
}
|
|
|
|
|
|
void HSlicingNode::adjustBorderChannels ()
|
|
{
|
|
if (_parent) {
|
|
if (_parent->getHeight() > getHeight()) {
|
|
DbU::Unit space = _parent->getHeight() - getHeight();
|
|
|
|
if (getAlignment() == AlignTop) {
|
|
RHVSlicingNode* channel = _slicingRouting.front();
|
|
channel->setHeight( channel->getHeight() + space );
|
|
} else if (getAlignment() == AlignCenter) {
|
|
RHVSlicingNode* firstChannel = _slicingRouting.front();
|
|
RHVSlicingNode* lastChannel = _slicingRouting.back ();
|
|
firstChannel->setHeight( firstChannel->getHeight() + space/2 );
|
|
lastChannel ->setHeight( lastChannel ->getHeight() + space/2 );
|
|
} else if (getAlignment() == AlignBottom) {
|
|
RHVSlicingNode* channel = _slicingRouting.back();
|
|
channel->setHeight( channel->getHeight() + space );
|
|
}
|
|
}
|
|
}
|
|
|
|
for ( SlicingNode* child : _children ) child->adjustBorderChannels();
|
|
}
|
|
|
|
|
|
string HSlicingNode::_getString () const
|
|
{
|
|
string s = Super::_getString();
|
|
return s;
|
|
}
|
|
|
|
|
|
string HSlicingNode::_getTypeName () const
|
|
{ return "HSlicingNode"; }
|
|
|
|
|
|
} // Bora namespace.
|