1328 lines
41 KiB
C++
1328 lines
41 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 "hurricane/RoutingPad.h"
|
|
#include "hurricane/NetRoutingProperty.h"
|
|
#include "hurricane/analog/Device.h"
|
|
#include "katana/KatanaEngine.h"
|
|
#include "bora/HVSlicingNode.h"
|
|
#include "bora/HSlicingNode.h"
|
|
#include "bora/VSlicingNode.h"
|
|
#include "bora/DSlicingNode.h"
|
|
#include "bora/RHVSlicingNode.h"
|
|
|
|
|
|
namespace Bora {
|
|
|
|
using namespace std;
|
|
using Hurricane::Error;
|
|
using Hurricane::Warning;
|
|
using Hurricane::Point;
|
|
using Hurricane::Box;
|
|
using Hurricane::RoutingPad;
|
|
using Hurricane::NetRoutingState;
|
|
using Hurricane::NetRoutingExtension;
|
|
using Analog::Device;
|
|
|
|
|
|
// -------------------------------------------------------------------
|
|
// Class : "Bora::HVSlicingNode".
|
|
|
|
|
|
HVSlicingNode::HVSlicingNode ( unsigned int type, unsigned int alignment )
|
|
: Super( type, NodeSets::create(), alignment, NULL )
|
|
, _children ()
|
|
, _toleranceRatioH(0)
|
|
, _toleranceRatioW(0)
|
|
, _toleranceBandH (0)
|
|
, _toleranceBandW (0)
|
|
, _symmetries ()
|
|
, _slicingRouting ()
|
|
, _netSymmetries ()
|
|
{ }
|
|
|
|
|
|
HVSlicingNode::~HVSlicingNode ()
|
|
{ }
|
|
|
|
|
|
DbU::Unit HVSlicingNode::getToleranceRatioH () const
|
|
{ return _toleranceRatioH; }
|
|
|
|
|
|
DbU::Unit HVSlicingNode::getToleranceRatioW () const
|
|
{ return _toleranceRatioW; }
|
|
|
|
|
|
DbU::Unit HVSlicingNode::getToleranceBandH () const
|
|
{ return _toleranceBandH; }
|
|
|
|
|
|
DbU::Unit HVSlicingNode::getToleranceBandW () const
|
|
{ return _toleranceBandW; }
|
|
|
|
|
|
void HVSlicingNode::setToleranceRatioH ( DbU::Unit tolerance )
|
|
{
|
|
_toleranceRatioH = tolerance;
|
|
getRoot()->_resetSlicingTree();
|
|
}
|
|
|
|
|
|
void HVSlicingNode::setToleranceRatioW ( DbU::Unit tolerance )
|
|
{
|
|
_toleranceRatioW = tolerance;
|
|
getRoot()->_resetSlicingTree();
|
|
}
|
|
|
|
|
|
void HVSlicingNode::setToleranceBandH ( DbU::Unit tolerance )
|
|
{
|
|
_toleranceBandH = tolerance;
|
|
resetSlicingTree();
|
|
}
|
|
|
|
|
|
void HVSlicingNode::setToleranceBandW ( DbU::Unit tolerance )
|
|
{
|
|
_toleranceBandW = tolerance;
|
|
resetSlicingTree();
|
|
}
|
|
|
|
|
|
void HVSlicingNode::recursiveSetToleranceRatioH ( DbU::Unit tolerance )
|
|
{
|
|
_recursiveSetToleranceRatioH( tolerance );
|
|
getRoot()->_resetSlicingTree();
|
|
}
|
|
|
|
|
|
void HVSlicingNode::recursiveSetToleranceRatioW ( DbU::Unit tolerance )
|
|
{
|
|
_recursiveSetToleranceRatioW( tolerance );
|
|
getRoot()->_resetSlicingTree();
|
|
}
|
|
|
|
|
|
void HVSlicingNode::recursiveSetToleranceBandH ( DbU::Unit tolerance )
|
|
{
|
|
resetSlicingTree();
|
|
_recursiveSetToleranceBandH( tolerance );
|
|
}
|
|
|
|
|
|
void HVSlicingNode::recursiveSetToleranceBandW ( DbU::Unit tolerance )
|
|
{
|
|
resetSlicingTree();
|
|
_recursiveSetToleranceBandW( tolerance );
|
|
}
|
|
|
|
|
|
void HVSlicingNode::_recursiveSetToleranceRatioH ( DbU::Unit tolerance )
|
|
{
|
|
for ( SlicingNode* node : _children ) {
|
|
if ( (not node->isDevice()) and (not node->isRouting()) )
|
|
node->recursiveSetToleranceRatioH( tolerance );
|
|
}
|
|
_toleranceRatioH = tolerance;
|
|
}
|
|
|
|
|
|
void HVSlicingNode::_recursiveSetToleranceRatioW ( DbU::Unit tolerance )
|
|
{
|
|
for ( SlicingNode* node : _children ) {
|
|
if ( (not node->isDevice()) and (not node->isRouting()) )
|
|
node->recursiveSetToleranceRatioW( tolerance );
|
|
}
|
|
_toleranceRatioW = tolerance;
|
|
}
|
|
|
|
|
|
void HVSlicingNode::_recursiveSetToleranceBandH ( DbU::Unit tolerance )
|
|
{
|
|
for ( SlicingNode* node : _children ) {
|
|
if ( (not node->isDevice()) and (not node->isRouting()) )
|
|
node->recursiveSetToleranceBandH( tolerance );
|
|
}
|
|
_toleranceBandH = tolerance;
|
|
}
|
|
|
|
|
|
void HVSlicingNode::_recursiveSetToleranceBandW ( DbU::Unit tolerance )
|
|
{
|
|
for ( SlicingNode* node : _children ) {
|
|
if ( (not node->isDevice()) and (not node->isRouting()) )
|
|
node->recursiveSetToleranceBandW( tolerance );
|
|
}
|
|
_toleranceBandW = tolerance;
|
|
}
|
|
|
|
|
|
void HVSlicingNode::setTolerances ( DbU::Unit trh, DbU::Unit trw, DbU::Unit tbh, DbU::Unit tbw )
|
|
{
|
|
resetSlicingTree();
|
|
_toleranceRatioH = trh;
|
|
_toleranceRatioW = trw;
|
|
_toleranceBandH = tbh;
|
|
_toleranceBandW = tbw;
|
|
}
|
|
|
|
|
|
void HVSlicingNode::recursiveSetTolerances ( DbU::Unit trh, DbU::Unit trw, DbU::Unit tbh, DbU::Unit tbw )
|
|
{
|
|
resetSlicingTree();
|
|
_recursiveSetTolerances( trh, trw, tbh, tbw );
|
|
}
|
|
|
|
|
|
void HVSlicingNode::_recursiveSetTolerances ( DbU::Unit trh, DbU::Unit trw, DbU::Unit tbh, DbU::Unit tbw )
|
|
{
|
|
_recursiveSetToleranceRatioH(trh);
|
|
_recursiveSetToleranceRatioW(trw);
|
|
_recursiveSetToleranceBandH (tbh);
|
|
_recursiveSetToleranceBandW (tbw);
|
|
}
|
|
|
|
|
|
bool HVSlicingNode::hasEmptyChildrenNodeSets () const
|
|
{
|
|
// WARNING: The original code was nonsensical, have to check it.
|
|
for ( SlicingNode* node : _children ) {
|
|
NodeSets* ns = node->getNodeSets();
|
|
if (ns->empty() and not node->isRouting() )
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
size_t HVSlicingNode::getChildIndex ( SlicingNode* node ) const
|
|
{
|
|
for ( size_t i=0 ; i<_children.size() ; ++i ) {
|
|
if ( (_children[i]->getType() == node->getType() )
|
|
and (_children[i]->getHeight() == node->getHeight())
|
|
and (_children[i]->getWidth () == node->getWidth ())
|
|
and (_children[i]->getX() == node->getX() )
|
|
and (_children[i]->getY() == node->getY() ) )
|
|
return i;
|
|
}
|
|
return NodeSets::NotFound;
|
|
}
|
|
|
|
|
|
SlicingNode* HVSlicingNode::getChild ( size_t index ) const
|
|
{ return _children[index]; }
|
|
|
|
|
|
void HVSlicingNode::createChild ( unsigned int type, unsigned int alignment )
|
|
{
|
|
if (type == HorizontalSNode) {
|
|
HSlicingNode* hsn = HSlicingNode::create( alignment );
|
|
hsn->setTolerances( getToleranceRatioH()
|
|
, getToleranceRatioW()
|
|
, getToleranceBandH ()
|
|
, getToleranceBandW ()
|
|
);
|
|
push_back( hsn );
|
|
resetSlicingTree();
|
|
} else if (type == VerticalSNode) {
|
|
VSlicingNode* vsn = VSlicingNode::create( alignment );
|
|
vsn->setTolerances( getToleranceRatioH()
|
|
, getToleranceRatioW()
|
|
, getToleranceBandH ()
|
|
, getToleranceBandW ()
|
|
);
|
|
push_back( vsn );
|
|
resetSlicingTree();
|
|
}
|
|
else
|
|
cerr << Warning( "HVSlicingNode::createChild(SlicingType, Alignment): Unknown type." ) << endl;
|
|
}
|
|
|
|
|
|
void HVSlicingNode::createChild ( NodeSets* nodeSets
|
|
, unsigned int alignment
|
|
, Instance* instance
|
|
, BoxSet* boxSet
|
|
)
|
|
{
|
|
DSlicingNode* node = DSlicingNode::create( nodeSets, alignment, instance, boxSet );
|
|
node->setParent( this );
|
|
push_back( node );
|
|
resetSlicingTree();
|
|
}
|
|
|
|
|
|
void HVSlicingNode::createChild ( size_t childIndex, size_t copyIndex, unsigned int tr )
|
|
{
|
|
if (childIndex != copyIndex) {
|
|
SlicingNode* node = this->getChild( childIndex )->clone(tr);
|
|
insertNode( node, copyIndex );
|
|
_symmetries.push_back( Symmetry( min(childIndex, copyIndex), max(childIndex, copyIndex) ) );
|
|
resetSlicingTree();
|
|
normalizeSymmetries();
|
|
}
|
|
else
|
|
cerr << Warning( "HVSlicingNode::createChild(size_t,size_t, unsigned int): Indexes cannot be the same." ) << endl;
|
|
}
|
|
|
|
|
|
void HVSlicingNode::insertNode ( SlicingNode* node, size_t index )
|
|
{
|
|
vector<SlicingNode*>::iterator it = _children.begin();
|
|
for ( size_t i=0; i < index; i++ ) { if (it != _children.end()) ++it; }
|
|
_children.insert( it, node );
|
|
node->setParent( this );
|
|
resetSlicingTree();
|
|
}
|
|
|
|
|
|
void HVSlicingNode::push_back ( SlicingNode* node, bool reset )
|
|
{
|
|
node->setParent( this );
|
|
_children.push_back( node );
|
|
if (reset) resetSlicingTree();
|
|
}
|
|
|
|
|
|
void HVSlicingNode::push_front ( SlicingNode* node )
|
|
{
|
|
node->setParent( this );
|
|
_children.insert( _children.begin(), node );
|
|
resetSlicingTree();
|
|
}
|
|
|
|
|
|
void HVSlicingNode::removeNode ( SlicingNode* node )
|
|
{
|
|
size_t index = 0;
|
|
for ( VSlicingNodes::iterator inode = _children.begin()
|
|
; inode != _children.end()
|
|
; ++inode, ++index ) {
|
|
if ((*inode) == node) {
|
|
_children.erase( inode );
|
|
removeSymmetry( index );
|
|
resetSlicingTree();
|
|
node->removeParent();
|
|
node->setX ( 0 );
|
|
node->setY ( 0 );
|
|
node->setPlaced ( false );
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
bool HVSlicingNode::isSymmetry ( size_t index, Symmetry& symmetry )
|
|
{
|
|
if (_symmetries.empty()) return false;
|
|
|
|
for ( LSymmetries::iterator isym=_symmetries.begin() ; isym != _symmetries.end() ; ++isym ) {
|
|
if ((*isym).second == index) {
|
|
symmetry = Symmetry( (*isym) );
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
bool HVSlicingNode::isSymmetry ( size_t index )
|
|
{
|
|
if (_symmetries.empty()) return false;
|
|
|
|
for ( Symmetry& sym : _symmetries ) {
|
|
if (sym.second == index) return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
void HVSlicingNode::addSymmetry ( size_t childIndex, size_t copyIndex, bool reset )
|
|
{
|
|
if (childIndex >= getChildren().size()) {
|
|
cerr << Warning( "HVSlicingNode::addSymmetry(size_t,size_t): Child index out of range %d (> %d), symmetry is ignored."
|
|
, childIndex, getChildren().size() ) << endl;
|
|
return;
|
|
}
|
|
|
|
if (copyIndex >= getChildren().size()) {
|
|
cerr << Warning( "HVSlicingNode::addSymmetry(size_t,size_t): Copy index out of range %d (> %d), symmetry is ignored."
|
|
, copyIndex, getChildren().size() ) << endl;
|
|
return;
|
|
}
|
|
|
|
if (childIndex == copyIndex) {
|
|
cerr << Warning( "HVSlicingNode::addSymmetry(size_t,size_t): Indexes cannot be identical (%d), symmetry is ignored."
|
|
, childIndex ) << endl;
|
|
return;
|
|
}
|
|
|
|
unsigned int symmetryType = 0;
|
|
if (getType() == HorizontalSNode) symmetryType = HSymmetry;
|
|
if (getType() == VerticalSNode ) symmetryType = VSymmetry;
|
|
|
|
if (not getChild(childIndex)->isSymmetric(getChild(copyIndex), symmetryType, ShowDiff)) {
|
|
cerr << Warning( "HVSlicingNode::addSymmetry(int,int)): Children %d and %d are not the same, symmetry is ignored.\n"
|
|
" child %d: %s\n"
|
|
" child %d: %s"
|
|
, childIndex, copyIndex
|
|
, childIndex, getString(getChild(childIndex)).c_str()
|
|
, copyIndex , getString(getChild( copyIndex)).c_str()
|
|
) << endl;
|
|
return;
|
|
}
|
|
|
|
_symmetries.push_back( Symmetry( min(childIndex, copyIndex), max(childIndex, copyIndex) ) );
|
|
if (reset) resetSlicingTree();
|
|
unsigned int flag = 0;
|
|
if (getType() == HorizontalSNode) flag = HSymmetry;
|
|
if (getType() == VerticalSNode ) flag = VSymmetry;
|
|
getChild(copyIndex)->setSymmetryFlag( flag );
|
|
|
|
getChild( copyIndex )->setMaster(getChild( childIndex ));
|
|
normalizeSymmetries();
|
|
}
|
|
|
|
|
|
void HVSlicingNode::removeSymmetry ( size_t index )
|
|
{
|
|
bool first = true;
|
|
bool isReference = true;
|
|
size_t erasedFirst = 0;
|
|
size_t erasedSecond = 0;
|
|
|
|
for ( LSymmetries::iterator it = _symmetries.begin(); it != _symmetries.end(); it++ ) {
|
|
if ( ( ((*it).first == index) or ((*it).second == index)) and first ) {
|
|
LSymmetries::iterator itToerase = it;
|
|
it++;
|
|
resetSlicingTree();
|
|
first = false;
|
|
|
|
if ((*it).first == index){
|
|
erasedFirst = (*itToerase).first;
|
|
erasedSecond = (*itToerase).second;
|
|
} else
|
|
isReference = false;
|
|
|
|
_symmetries.erase(itToerase);
|
|
it--;
|
|
} else {
|
|
if ( not first and isReference ) {
|
|
if ((*it).first == erasedFirst) (*it).first = erasedSecond;
|
|
}
|
|
if ((*it).first > index) (*it).first--;
|
|
if ((*it).second > index) (*it).second--;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void HVSlicingNode::normalizeSymmetries ()
|
|
{
|
|
// Notes :
|
|
// Symmetries must be described in a specific way, in case it is not, this method correct it.
|
|
// Examples:
|
|
// WRONG: Symmetries [< 1, 2 >, < 2, 3 >, < 3, 4 >]; RIGHT: [< 1, 2 >, < 1, 3 >, < 1, 4 >];
|
|
// WRONG: Symmetries [< 3, 4 >, < 5, 6 >, < 1, 2 >]; RIGHT: [< 1, 2 >, < 3, 4 >, < 5, 6 >];
|
|
// WRONG: Symmetries [< 1, 2 >, < 1, 2 >, < 3, 4 >]; RIGHT: [< 1, 2 >, < 3, 4 >];
|
|
|
|
LSymmetries adjustedSymmetries;
|
|
for ( Symmetry& sym : _symmetries ) {
|
|
if (sym.first > sym.second) adjustedSymmetries.push_back( Symmetry( sym.second, sym.first ) );
|
|
else adjustedSymmetries.push_back( Symmetry( sym.first , sym.second ) );
|
|
}
|
|
adjustedSymmetries.sort();
|
|
|
|
for ( LSymmetries::iterator isym = adjustedSymmetries.begin()
|
|
; isym != adjustedSymmetries.end()
|
|
; isym++ ) {
|
|
for ( LSymmetries::iterator idup = isym
|
|
; idup != adjustedSymmetries.end()
|
|
; idup++ ) {
|
|
if (idup == isym) continue;
|
|
|
|
if ((*isym).second == (*idup).first) (*idup).first = (*isym).first;
|
|
if ((*isym).second < (*idup).first) break;
|
|
}
|
|
}
|
|
|
|
_symmetries = adjustedSymmetries;
|
|
}
|
|
|
|
|
|
void HVSlicingNode::_resetSlicingTree ()
|
|
{
|
|
_x = 0;
|
|
_y = 0;
|
|
setPlaced( false );
|
|
|
|
if (not isPreset()) {
|
|
_boxSet = NULL;
|
|
setSet( false );
|
|
|
|
for ( SlicingNode* child : _children ) child->_resetSlicingTree();
|
|
}
|
|
}
|
|
|
|
|
|
void HVSlicingNode::print () const
|
|
{
|
|
SlicingNode::print();
|
|
|
|
if (not _symmetries.empty()) {
|
|
cerr << "Symmetries: " << endl;
|
|
for ( const Symmetry& sym : _symmetries )
|
|
cerr << "Children: " << sym.first << " and " << sym.second << endl;
|
|
cerr << endl;
|
|
} else
|
|
cerr << "Symmetries: None" << endl;
|
|
|
|
if (not _slicingRouting.empty()) {
|
|
cerr<< "Slicing Routing: " << endl;
|
|
|
|
size_t index = 0;
|
|
for ( const RHVSlicingNode* node : _slicingRouting ) {
|
|
cerr << "---------------- " << setprecision(4) << index << " -----------------" << endl;
|
|
cerr << "Print - Slicing Routing: ";
|
|
cerr << "X: " << DbU::getPhysical(node->getX (), DbU::Micro);
|
|
cerr << ", Y: " << DbU::getPhysical(node->getY (), DbU::Micro);
|
|
cerr << ", height: " << DbU::getPhysical(node->getHeight(), DbU::Micro);
|
|
cerr << ", width: " << DbU::getPhysical(node->getWidth (), DbU::Micro) << endl;
|
|
cerr << "GCell: " << node->getGCell() << endl;
|
|
|
|
if(node->getGCell()){
|
|
cerr << "GCell : " << node->getGCell() << endl;
|
|
|
|
cerr << "Edges : " << endl;
|
|
for ( const Anabatic::Edge* edge : node->getGCell()->getNorthEdges() )
|
|
cerr << edge->getOpposite(node->getGCell()) << endl;
|
|
|
|
for ( const Anabatic::Edge* edge : node->getGCell()->getSouthEdges() )
|
|
cerr << edge->getOpposite(node->getGCell()) << endl;
|
|
|
|
for ( const Anabatic::Edge* edge : node->getGCell()->getEastEdges() )
|
|
cerr << edge->getOpposite(node->getGCell()) << endl;
|
|
|
|
for ( const Anabatic::Edge* edge : node->getGCell()->getWestEdges() )
|
|
cerr << edge->getOpposite(node->getGCell()) << endl;
|
|
}
|
|
|
|
cerr << "------------------------------------" << endl;
|
|
++index;
|
|
}
|
|
} else
|
|
cerr << "Slicing Routing: empty" << endl;
|
|
|
|
cerr << endl;
|
|
}
|
|
|
|
|
|
void HVSlicingNode::printChildren () const
|
|
{
|
|
size_t index = 0;
|
|
for ( const SlicingNode* child : _children ) {
|
|
if ( child->isDevice() or child->isRouting() ) {
|
|
cerr << "-- Children: " << index << "/" << _children.size()-1 << " --" << endl;
|
|
child->print();
|
|
} else {
|
|
cerr << "-- Children: " << index << "/" << _children.size()-1 << " --" << endl;
|
|
child->print();
|
|
child->printChildren();
|
|
}
|
|
++index;
|
|
}
|
|
}
|
|
|
|
|
|
void HVSlicingNode::printLine () const
|
|
{
|
|
SlicingNode::printLine();
|
|
|
|
if (not _symmetries.empty()) {
|
|
cerr << "Symmetries: " << endl;
|
|
for ( const Symmetry& sym : _symmetries )
|
|
cerr << "Children: " << sym.first << " and " << sym.second << endl;
|
|
cerr << endl;
|
|
}
|
|
}
|
|
|
|
|
|
void HVSlicingNode::printChildrenLine () const
|
|
{
|
|
size_t index = 0;
|
|
for ( const SlicingNode* child : _children ) {
|
|
if ( child->isDevice() or child->isRouting() ) {
|
|
cerr << "-- Children: " << index << "/" << _children.size()-1 << " --" << endl;
|
|
child->printLine();
|
|
} else {
|
|
cerr << endl;
|
|
cerr << "-- Children: " << index << "/" << _children.size()-1 << " --" << endl;
|
|
child->printLine();
|
|
child->printChildrenLine();
|
|
}
|
|
++index;
|
|
}
|
|
}
|
|
|
|
|
|
bool HVSlicingNode::recursiveCheckPreset () const
|
|
{
|
|
bool preset = isPreset();
|
|
if (preset) {
|
|
for ( const SlicingNode* child : _children ) preset = child->recursiveCheckPreset();
|
|
}
|
|
return preset;
|
|
}
|
|
|
|
|
|
bool HVSlicingNode::recursiveCheckSet () const
|
|
{
|
|
bool rset = isSet();
|
|
if (rset) {
|
|
for ( const SlicingNode* child : _children ) rset = child->recursiveCheckSet();
|
|
}
|
|
return rset;
|
|
}
|
|
|
|
|
|
bool HVSlicingNode::recursiveCheckPlaced () const
|
|
{
|
|
bool placed = isPlaced();
|
|
if (placed) {
|
|
for ( const SlicingNode* child : _children ) placed = child->recursiveCheckPlaced();
|
|
}
|
|
return placed;
|
|
}
|
|
|
|
|
|
int HVSlicingNode::getLeafNumber() const
|
|
{
|
|
int leafs = 0;
|
|
for ( const SlicingNode* child : _children ) leafs += child->getLeafNumber();
|
|
return leafs;
|
|
}
|
|
|
|
|
|
double HVSlicingNode::getDevicesArea () const
|
|
{
|
|
double area = 0.0;
|
|
for ( const SlicingNode* child : _children ) area += child->getDevicesArea();
|
|
return area;
|
|
}
|
|
|
|
|
|
double HVSlicingNode::getOccupationArea () const
|
|
{
|
|
double estimation = 0;
|
|
if (recursiveCheckPlaced())
|
|
estimation = (100 * getDevicesArea()) / (getHeight() * getWidth());
|
|
else
|
|
cerr << Warning( "HVSlicingNode::getSpaceEstimation()): SlicingNodes dimensions need to be set first before being estimated." ) << endl;
|
|
|
|
return estimation;
|
|
}
|
|
|
|
|
|
void HVSlicingNode::setGlobalSize ( DbU::Unit height, DbU::Unit width )
|
|
{
|
|
if (not _nodeSets->empty()) {
|
|
DbU::Unit bestH = 0;
|
|
DbU::Unit bestW = 0;
|
|
DbU::Unit currentH = 0;
|
|
DbU::Unit currentW = 0;
|
|
BoxSet* boxSet = _nodeSets->at( 0 );
|
|
|
|
for ( BoxSet* bs : _nodeSets->getBoxSets() ) {
|
|
currentH = bs->getHeight();
|
|
currentW = bs->getWidth();
|
|
if ( (currentH <= height) and (currentW <= width) ) {
|
|
if ( ((height-currentH) <= _toleranceRatioH) and ((height-bestH) <= _toleranceRatioH) ) {
|
|
if (currentW > bestW) {
|
|
bestH = currentH;
|
|
bestW = currentW;
|
|
boxSet = bs;
|
|
}
|
|
} else if (currentH > bestH) {
|
|
bestH = currentH;
|
|
bestW = currentW;
|
|
boxSet = bs;
|
|
}
|
|
}
|
|
}
|
|
|
|
_setGlobalSize( boxSet );
|
|
} else
|
|
cerr << Warning( "HVSlicingNode::setGlobalSize(DbU::Unit h, DbU::Unit w): NodeSets empty. UpdateGlobalSize needs to be used first or with higher tolerances." ) << endl;
|
|
}
|
|
|
|
|
|
void HVSlicingNode::setGlobalSize ( size_t index )
|
|
{
|
|
if (not _nodeSets->empty()) {
|
|
if (index+1 > _nodeSets->size())
|
|
cerr << Warning( "HVSlicingNode::setGlobalSize(size_t): Out of bound index." ) << endl;
|
|
else
|
|
_setGlobalSize( _nodeSets->at(index) );
|
|
} else
|
|
cerr << Warning( "HVSlicingNode::setGlobalSize(size_t): NodeSets empty. UpdateGlobalSize needs to be used first or with higher tolerances." ) << endl;
|
|
}
|
|
|
|
|
|
void HVSlicingNode::_setGlobalSize ( BoxSet* boxSet )
|
|
{
|
|
if (not isPreset()) {
|
|
if (not getMaster())
|
|
_setBoxSet( boxSet );
|
|
else
|
|
_setBoxSet( _master->getBoxSet() );
|
|
|
|
if ( ((getType() == HorizontalSNode) and (isHSymmetry()))
|
|
or ((getType() == VerticalSNode ) and (isVSymmetry())) ) {
|
|
vector<BoxSet*>::const_iterator ibs = boxSet->getSet().begin();
|
|
for ( VSlicingNodes::reverse_iterator ichild = _children.rbegin()
|
|
; ichild != _children.rend(); ++ichild ) {
|
|
(*ichild)->_setGlobalSize( *ibs );
|
|
ibs++;
|
|
}
|
|
} else {
|
|
vector<BoxSet*>::const_iterator ibs = boxSet->getSet().begin();
|
|
for ( VSlicingNodes::iterator ichild = _children.begin()
|
|
; ichild != _children.end(); ichild++) {
|
|
(*ichild)->_setGlobalSize( *ibs );
|
|
ibs++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void HVSlicingNode::preDestroy ()
|
|
{
|
|
Super::preDestroy();
|
|
for ( SlicingNode* child : _children ) child->removeParent();
|
|
}
|
|
|
|
|
|
void HVSlicingNode::destroy ()
|
|
{
|
|
HVSlicingNode::preDestroy();
|
|
delete this;
|
|
}
|
|
|
|
|
|
void HVSlicingNode::preRecursiveDestroy ()
|
|
{
|
|
Super::preRecursiveDestroy();
|
|
for ( SlicingNode* child : _children ) {
|
|
if ( (child->getType() == HorizontalSNode) or (child->getType() == VerticalSNode) ) {
|
|
child->removeParent();
|
|
child->recursiveDestroy();
|
|
} else {
|
|
child->removeParent();
|
|
child->destroy();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void HVSlicingNode::recursiveDestroy ()
|
|
{
|
|
HVSlicingNode::preRecursiveDestroy();
|
|
delete this;
|
|
}
|
|
|
|
|
|
LSlicingNodes HVSlicingNode::getLeaves ()
|
|
{
|
|
LSlicingNodes leaves;
|
|
for ( SlicingNode* child : _children ) {
|
|
if ( (child->getType() == DeviceSNode) or (child->getType() == RoutingSNode) )
|
|
leaves.push_back( child );
|
|
else
|
|
leaves.splice( leaves.end(), child->getLeaves() );
|
|
}
|
|
return leaves;
|
|
}
|
|
|
|
|
|
bool HVSlicingNode::checkInitialPlacement ( int& cpt ) const
|
|
{
|
|
// Notes::
|
|
// Initial placement criteria is having at least 2 devices placed at (x,y) = (0,0)
|
|
|
|
bool initialPlacement = false;
|
|
if (cpt < 2) {
|
|
initialPlacement = true;
|
|
for ( const SlicingNode* child : _children ) {
|
|
if (cpt < 2) initialPlacement = child->checkInitialPlacement( cpt );
|
|
}
|
|
}
|
|
return initialPlacement;
|
|
}
|
|
|
|
|
|
bool HVSlicingNode::isSame ( SlicingNode* node, unsigned int flags ) const
|
|
{
|
|
if ( (getType() == node->getType() )
|
|
and (getNbChild() == node->getNbChild() )
|
|
and (getToleranceBandH() == node->getToleranceBandH())
|
|
and (getToleranceBandW() == node->getToleranceBandW()) ) {
|
|
bool isSame = true;
|
|
|
|
for ( size_t ichild = 0 ; isSame and (ichild < getNbChild()) ; ++ichild ) {
|
|
isSame = getChild(ichild)->isSame( node->getChild(ichild) );
|
|
}
|
|
|
|
if (not isSame and (flags & ShowDiff))
|
|
cerr << "HVSlicingNode::isSame() " << this << " and " << node << " differs (childs)." << endl;
|
|
|
|
return isSame;
|
|
} else {
|
|
if (flags & ShowDiff)
|
|
cerr << "HVSlicingNode::isSame() " << this << " and " << node << " differs." << endl;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
|
|
bool HVSlicingNode::checkCellInstances ( Cell* cell )
|
|
{
|
|
if (not cell) {
|
|
cerr << Warning( "HVSlicingNode::checkCellInstances(): Cell is NULL." ) << endl;
|
|
return false;
|
|
}
|
|
|
|
for ( SlicingNode* child : _children ) {
|
|
if (not child->checkCellInstances(cell)) return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|
|
SlicingNode* HVSlicingNode::findInstance ( Instance* instance )
|
|
{
|
|
for ( SlicingNode* child : _children ) {
|
|
if ( (child->getType() == HorizontalSNode) or (child->getType() == VerticalSNode) ) {
|
|
SlicingNode* node = child->findInstance( instance );
|
|
if (node) return node;
|
|
} else if (child->getType() == DeviceSNode) {
|
|
if ( child->getInstance() == instance )
|
|
return child;
|
|
}
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
|
|
SlicingNode* HVSlicingNode::findSlicingNode ( Anabatic::GCell* gcell )
|
|
{
|
|
if (getGCell() == gcell) return this;
|
|
|
|
for ( RHVSlicingNode* node : _slicingRouting ) {
|
|
if (node->getGCell() == gcell) return node;
|
|
}
|
|
|
|
for ( SlicingNode* child : _children ) {
|
|
if( (child->getType() == HorizontalSNode) or (child->getType() == VerticalSNode) ) {
|
|
SlicingNode* node = child->findSlicingNode( gcell );
|
|
if (node) return node;
|
|
} else if (child->getType() == DeviceSNode) {
|
|
if (child->getGCell() == gcell)
|
|
return child;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
void HVSlicingNode::resetSlicingRouting ()
|
|
{
|
|
for ( RHVSlicingNode* node : _slicingRouting ) node->resetSize();
|
|
for ( SlicingNode* child : _children ) {
|
|
if ( (child->getType() == HorizontalSNode) or (child->getType() == VerticalSNode) )
|
|
child->resetSlicingRouting();
|
|
}
|
|
setRoutingEstimated(0);
|
|
}
|
|
|
|
|
|
void HVSlicingNode::destroySlicingRouting ()
|
|
{
|
|
for ( RHVSlicingNode* node : _slicingRouting ) node->destroy();
|
|
_slicingRouting.clear();
|
|
|
|
for ( SlicingNode* child : _children ) {
|
|
if ( (child->getType() == HorizontalSNode) or (child->getType() == VerticalSNode) )
|
|
child->destroySlicingRouting();
|
|
}
|
|
|
|
setRoutingEstimated(0);
|
|
}
|
|
|
|
|
|
size_t HVSlicingNode::getRoutingIndex ( SlicingNode* node ) const
|
|
{
|
|
size_t index = 0;
|
|
for ( const RHVSlicingNode* node : _slicingRouting ) {
|
|
if ( (node->getHeight() == node->getHeight())
|
|
and (node->getWidth () == node->getWidth ())
|
|
and (node->getX () == node->getX ())
|
|
and (node->getY () == node->getY ()) )
|
|
return index;
|
|
++index;
|
|
}
|
|
|
|
return NodeSets::NotFound;
|
|
}
|
|
|
|
|
|
SlicingNode* HVSlicingNode::getSlicingRouting ( size_t index ) const
|
|
{ return _slicingRouting.at( index ); }
|
|
|
|
|
|
void HVSlicingNode::restrictDevices ()
|
|
{
|
|
for ( SlicingNode* child : _children ) child->restrictDevices();
|
|
for ( RHVSlicingNode* node : _slicingRouting ) node ->restrictDevices();
|
|
}
|
|
|
|
|
|
void HVSlicingNode::setVertexRestriction ( Net* net, Katana::KatanaEngine* katana )
|
|
{
|
|
cdebug_log(536,1) << "HVSlicingNode::setVertexRestriction(Net*,KatanaEngine*)" << endl;
|
|
|
|
restrictDevices();
|
|
vector<RoutingPad*> rps;
|
|
for ( RoutingPad* rp : net->getRoutingPads() ) rps.push_back( rp );
|
|
for ( RoutingPad* rp : rps ) {
|
|
Box rpBb = rp->getBoundingBox();
|
|
Point center = rpBb.getCenter();
|
|
Anabatic::GCell* gcell = katana->getGCellUnder( center );
|
|
|
|
if (not gcell) {
|
|
cerr << Error( "HVSlicingNode::setVetexRestriction(): %s of %s is not under any GCell.\n"
|
|
" It will be ignored ans the routing will be incomplete."
|
|
, getString(rp ).c_str()
|
|
, getString(net).c_str()
|
|
) << endl;
|
|
continue;
|
|
}
|
|
|
|
Anabatic::Vertex* vertex = gcell->getObserver<Anabatic::Vertex>(Anabatic::GCell::Observable::Vertex);
|
|
// Analog Restrictions
|
|
Plug* plug = dynamic_cast<Plug*>( rp->getPlugOccurrence().getEntity() );
|
|
Cell* cell = plug->getInstance()->getMasterCell();
|
|
Device* device = dynamic_cast<Device*>( cell );
|
|
|
|
if (device) {
|
|
cdebug_log(536,0) << "Underlying device: " << device << endl;
|
|
|
|
unsigned int rule = device->getRestrictions2(plug->getMasterNet());
|
|
vertex->clearRestriction();
|
|
|
|
cdebug_log(536,0) << "Restrictions rule: " << rule << endl;
|
|
if (rule & WestBlocked ) vertex->setWRestricted();
|
|
if (rule & EastBlocked ) vertex->setERestricted();
|
|
if (rule & SouthBlocked) vertex->setSRestricted();
|
|
if (rule & NorthBlocked) vertex->setNRestricted();
|
|
cdebug_log(536,0) << "Applied restrictions: " << vertex << endl;
|
|
} else {
|
|
vertex->clearRestriction();
|
|
}
|
|
}
|
|
|
|
cdebug_tabw(536,-1);
|
|
}
|
|
|
|
|
|
void HVSlicingNode::estimateChannelsSize ()
|
|
{
|
|
for ( RHVSlicingNode* node : _slicingRouting ) node ->estimateChannelsSize();
|
|
for ( SlicingNode* child : _children ) child->estimateChannelsSize();
|
|
}
|
|
|
|
|
|
void HVSlicingNode::expandRoutingChannel ()
|
|
{
|
|
estimateChannelsSize();
|
|
_expandRoutingChannel();
|
|
}
|
|
|
|
|
|
void HVSlicingNode::_expandRoutingChannel ()
|
|
{
|
|
for ( RHVSlicingNode* node : _slicingRouting ) node->_expandRoutingChannel();
|
|
for ( SlicingNode* child : _children ) {
|
|
if (child->getType() != RoutingSNode) child->_expandRoutingChannel();
|
|
}
|
|
setRoutingEstimated(RoutingEstimated);
|
|
if (not _parent) {
|
|
for ( SlicingNode* child : _children ) child->adjustBorderChannels();
|
|
}
|
|
}
|
|
|
|
|
|
void HVSlicingNode::expandRoutingChannel ( DbU::Unit height, DbU::Unit width )
|
|
{
|
|
for ( RHVSlicingNode* node : _slicingRouting ) node->expandRoutingChannel( height, width );
|
|
for ( SlicingNode* child : _children ) {
|
|
if (child->getType() != RoutingSNode) child->expandRoutingChannel( height, width );
|
|
}
|
|
setRoutingEstimated( RoutingEstimated );
|
|
if (_parent == NULL)
|
|
for ( SlicingNode* child : _children ) child->adjustBorderChannels();
|
|
}
|
|
|
|
|
|
bool HVSlicingNode::isRoutingEstimated () const
|
|
{
|
|
bool estimated = true;
|
|
if (_slicingRouting.empty()){
|
|
estimated = false;
|
|
} else {
|
|
for ( RHVSlicingNode* node : _slicingRouting ) estimated &= node->isRoutingEstimated();
|
|
}
|
|
|
|
for ( SlicingNode* child : _children ) {
|
|
if ( (child->getType() == HorizontalSNode ) or (child->getType() == VerticalSNode) )
|
|
estimated &= child->isRoutingEstimated();
|
|
}
|
|
|
|
return estimated;
|
|
}
|
|
|
|
|
|
void HVSlicingNode::updateGCellPosition ()
|
|
{
|
|
cdebug_log(535,1) << "HVSlicingNode::updateGCellPosition()" << endl;
|
|
|
|
for ( SlicingNode* node : _slicingRouting ) node ->updateGCellPosition();
|
|
for ( SlicingNode* child : _children ) child->updateGCellPosition();
|
|
|
|
cdebug_tabw(535,-1);
|
|
}
|
|
|
|
|
|
void HVSlicingNode::updateGContacts ()
|
|
{
|
|
cdebug_log(535,1) << "HVSlicingNode::updateGContacts()" << endl;
|
|
|
|
for ( SlicingNode* node : _slicingRouting ) node ->updateGContacts();
|
|
for ( SlicingNode* child : _children ) child->updateGContacts();
|
|
|
|
cdebug_tabw(535,-1);
|
|
}
|
|
|
|
|
|
void HVSlicingNode::clearGCells ()
|
|
{
|
|
for ( RHVSlicingNode* node : _slicingRouting ) node ->clearGCells();
|
|
for ( SlicingNode* child : _children ) child->clearGCells();
|
|
_gcell = NULL;
|
|
}
|
|
|
|
|
|
int HVSlicingNode::getNbDevices ()
|
|
{
|
|
int count = 0;
|
|
for ( SlicingNode* child : _children ) count += child->getNbDevices();
|
|
return count;
|
|
}
|
|
|
|
|
|
string HVSlicingNode::_getString () const
|
|
{
|
|
string s = Super::_getString();
|
|
s.insert( s.size()-1, " childs:" + getString(_children.size()) );
|
|
return s;
|
|
}
|
|
|
|
|
|
string HVSlicingNode::_getTypeName () const
|
|
{ return "HVSlicingNode"; }
|
|
|
|
|
|
void HVSlicingNode::setSymmetryFlag ( unsigned int flag )
|
|
{
|
|
SlicingNode::setSymmetryFlag( flag );
|
|
for ( RHVSlicingNode* node : _slicingRouting ) node ->setSymmetryFlag( flag );
|
|
for ( SlicingNode* child : _children ) child->setSymmetryFlag( flag );
|
|
}
|
|
|
|
|
|
void HVSlicingNode::setMaster ( SlicingNode* master )
|
|
{
|
|
_master = master;
|
|
|
|
if ( ((getType() == HorizontalSNode) and isHSymmetry())
|
|
or ((getType() == VerticalSNode ) and isVSymmetry()) ) {
|
|
for ( size_t i=0 ; i<_children.size() ; ++i )
|
|
_children[ _children.size()-1 - i ]->setMaster( master->getChild(i) );
|
|
} else {
|
|
for ( size_t i=0 ; i<_children.size() ; ++i )
|
|
_children[ i ]->setMaster( master->getChild(i) );
|
|
}
|
|
}
|
|
|
|
|
|
bool HVSlicingNode::isSymmetric ( SlicingNode* node, unsigned int symmetryType, unsigned int flags ) const
|
|
{
|
|
if ( (getType() == node->getType() )
|
|
and (getNbChild() == node->getNbChild() )
|
|
and (getToleranceBandH() == node->getToleranceBandH())
|
|
and (getToleranceBandW() == node->getToleranceBandW()) ) {
|
|
bool isSame = true;
|
|
|
|
if ( ((getType() == HorizontalSNode) and (symmetryType == HSymmetry))
|
|
or ((getType() == VerticalSNode ) and (symmetryType == VSymmetry)) ) {
|
|
size_t nbChilds = _children.size();
|
|
for ( size_t i=0 ; isSame and (i<nbChilds) ; ++i ) {
|
|
isSame = getChild(i)->isSymmetric( node->getChild(nbChilds-1-i), symmetryType );
|
|
}
|
|
} else {
|
|
size_t nbChilds = _children.size();
|
|
for ( size_t i=0 ; isSame and (i<nbChilds) ; ++i ) {
|
|
isSame = getChild(i)->isSymmetric( node->getChild(i), symmetryType );
|
|
}
|
|
}
|
|
|
|
if (not isSame and (flags & ShowDiff))
|
|
cerr << Warning( "HVSlicingNode::isSame() %s and %s differs (childs)."
|
|
, getString(this).c_str()
|
|
, getString(node).c_str() ) << endl;
|
|
return isSame;
|
|
}
|
|
|
|
if (flags & ShowDiff)
|
|
cerr << Warning( "HVSlicingNode::isSame() %s and %s differs."
|
|
, getString(this).c_str()
|
|
, getString(node).c_str() ) << endl;
|
|
return false;
|
|
}
|
|
|
|
|
|
bool HVSlicingNode::checkSymmetryNet ( unsigned int type, Net* net1, Net* net2 ) const
|
|
{
|
|
for ( const NetSymmetry& netSym : _netSymmetries ) {
|
|
if ( (get<1>(netSym) == net1)
|
|
and (get<2>(netSym) == net2)
|
|
and (get<0>(netSym) == type) )
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
|
|
void HVSlicingNode::addSymmetryNet ( unsigned int type, Net* net1, Net* net2 )
|
|
{
|
|
cerr << "HVSlicingNode::addSymmetryNet(): " << this << endl;
|
|
cerr << "* " << net1 << endl;
|
|
|
|
if (checkSymmetryNet(type,net1,net2)) {
|
|
cerr << Warning( "HVSlicingNode::addSymmetryNet(): Net symmetry already set." ) << endl;
|
|
return;
|
|
}
|
|
|
|
unsigned int ftype = type;
|
|
if (type == 1) ftype = NetRoutingState::Vertical;
|
|
else if (type == 2) ftype = NetRoutingState::Horizontal;
|
|
_netSymmetries.push_back( make_tuple(ftype,net1,net2) );
|
|
}
|
|
|
|
|
|
void HVSlicingNode::updateNetConstraints ()
|
|
{
|
|
if (not _cell) {
|
|
cerr << Warning( "HVSlicingNode::updateNetConstraints(): Cell not set." ) << endl;
|
|
return;
|
|
}
|
|
|
|
for ( NetSymmetry& netSym : _netSymmetries ) {
|
|
if (get<2>(netSym)) {
|
|
Net* masterNet = get<1>(netSym);
|
|
if (not masterNet)
|
|
cerr << Warning( "HVSlicingNode::updateNetConstraints() Reference Net not set." ) << endl;
|
|
else {
|
|
NetRoutingState* masterState = NetRoutingExtension::get( masterNet );
|
|
if (not masterState) masterState = NetRoutingExtension::create( masterNet );
|
|
|
|
masterState->setFlags ( NetRoutingState::AutomaticGlobalRoute
|
|
| NetRoutingState::Symmetric
|
|
| NetRoutingState::SymmetricMaster
|
|
| get<0>(netSym) );
|
|
|
|
Net* slaveNet = get<2>(netSym);
|
|
NetRoutingState* slaveState = NetRoutingExtension::get( slaveNet );
|
|
if (not slaveState) slaveState = NetRoutingExtension::create( slaveNet );
|
|
|
|
slaveState ->setFlags ( NetRoutingState::AutomaticGlobalRoute
|
|
| NetRoutingState::Symmetric
|
|
| get<0>((netSym)) );
|
|
slaveState ->setSymNet( masterNet );
|
|
masterState->setSymNet( slaveNet );
|
|
}
|
|
} else {
|
|
Net* net = get<1>(netSym);
|
|
if (not net)
|
|
cerr << Warning( "HVSlicingNode::updateNetConstraints() Single master Net not set." ) << endl;
|
|
else {
|
|
NetRoutingState* state = NetRoutingExtension::get( net );
|
|
if (not state) state = NetRoutingExtension::create( net );
|
|
|
|
state->setFlags( NetRoutingState::AutomaticGlobalRoute
|
|
| NetRoutingState::Symmetric
|
|
| get<0>(netSym) );
|
|
}
|
|
}
|
|
}
|
|
|
|
for ( SlicingNode* child : _children ) {
|
|
if ( (child->getType() == HorizontalSNode) or (child->getType() == VerticalSNode) )
|
|
child->updateNetConstraints();
|
|
}
|
|
}
|
|
|
|
|
|
void HVSlicingNode::updateSymNetAxis ()
|
|
{
|
|
if (not _cell) {
|
|
cerr << Warning( "HVSlicingNode::updateSymNetAxis(): Cell not set." ) << endl;
|
|
return;
|
|
}
|
|
|
|
for ( const NetSymmetry& symNet : _netSymmetries ) {
|
|
if (_symmetries.empty())
|
|
throw Error( "HVSlicingNode::updateSymNetAxis(): \n"
|
|
" Symmetry request for \"%s\" in non-symmetrical node \"%s\"."
|
|
, getString(get<1>(symNet)->getName()).c_str()
|
|
, getString(this).c_str()
|
|
);
|
|
|
|
SlicingNode* n1 = getChild( _symmetries.front().first );
|
|
SlicingNode* n2 = getChild( _symmetries.front().second );
|
|
DbU::Unit xCenter = (n1->getX() + n2->getX() + n2->getWidth())/2;
|
|
DbU::Unit yCenter = (n1->getY() + n2->getY() + n2->getHeight())/2;
|
|
|
|
if (get<2>(symNet)) {
|
|
Net* masterNet = get<1>( symNet );
|
|
if (not masterNet)
|
|
cerr << Warning( "HVSlicingNode::updateSymNetAxis() Master net not set." ) << endl;
|
|
else {
|
|
NetRoutingState* masterState = NetRoutingExtension::get( masterNet );
|
|
if (not masterState)
|
|
cerr << Warning( "HVSlicingNode::updateSymNetAxis(): UpdateNetConstraint need to be called first." ) << endl;
|
|
else {
|
|
if (get<0>(symNet) == NetRoutingState::Vertical ) masterState->setSymAxis( xCenter );
|
|
else if (get<0>(symNet) == NetRoutingState::Horizontal) masterState->setSymAxis( yCenter );
|
|
else
|
|
cerr << Warning( "HVSlicingNode::updateSymNetAxis(): Unknown NetRoutingState type." ) << endl;
|
|
|
|
Net* slaveNet = get<2>(symNet);
|
|
NetRoutingState* slaveState = NetRoutingExtension::get( slaveNet );
|
|
if (not slaveState)
|
|
cerr << Warning( "HVSlicingNode::updateSymNetAxis(): updateSymNetAxis need to be called first." ) << endl;
|
|
else {
|
|
if (get<0>(symNet) == NetRoutingState::Vertical ) slaveState->setSymAxis( xCenter );
|
|
else if (get<0>(symNet) == NetRoutingState::Horizontal) slaveState->setSymAxis( yCenter );
|
|
else
|
|
cerr << Warning( "HVSlicingNode::updateSymNetAxis(): Unknown NetRoutingState type." ) << endl;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
Net* net = get<1>(symNet);
|
|
if (not net)
|
|
cerr << Warning( "HVSlicingNode::updateSymNetAxis() Signle master net not set." ) << endl;
|
|
else {
|
|
NetRoutingState* state = NetRoutingExtension::get( net );
|
|
if (not state)
|
|
cerr << Warning( "HVSlicingNode::updateSymNetAxis(): UpdateNetConstraint need to be called first." ) << endl;
|
|
else {
|
|
if (get<0>(symNet) == NetRoutingState::Vertical ) state->setSymAxis( xCenter );
|
|
else if (get<0>(symNet) == NetRoutingState::Horizontal) state->setSymAxis( yCenter );
|
|
else
|
|
cerr << Warning( "HVSlicingNode::updateSymNetAxis(): Unknown NetRoutingState type." ) << endl;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for ( SlicingNode* child : _children ) {
|
|
if ( (child->getType() == HorizontalSNode) or (child->getType() == VerticalSNode) )
|
|
child->updateSymNetAxis();
|
|
}
|
|
}
|
|
|
|
|
|
void HVSlicingNode::flattenDigitalNets ()
|
|
{
|
|
if (not _cell) {
|
|
cerr << Warning( "HVSlicingNode::flattenDigitalNets(): Cell not set." ) << endl;
|
|
return;
|
|
}
|
|
|
|
for ( SlicingNode* child : _children ) {
|
|
if ( (child->getType() == HorizontalSNode) or (child->getType() == VerticalSNode) ) {
|
|
child->flattenDigitalNets();
|
|
} else if (child->getType() == DeviceSNode) {
|
|
if ( child->getGCell()
|
|
and child->getInstance()
|
|
and child->getGCell()->isMatrix()) {
|
|
_cell->flattenNets( child->getInstance()
|
|
, Cell::Flags::BuildRings|Cell::Flags::WarnOnUnplacedInstances );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void HVSlicingNode::updateWireOccupation ( Anabatic::Dijkstra* dijkstra )
|
|
{
|
|
cdebug_log(535,1) << "HVSlicingNode::updateWireOccupation() on " << this << endl;
|
|
|
|
if (not _parent) {
|
|
for ( Anabatic::Vertex* vertex : dijkstra->getSources() ) {
|
|
cdebug_log(535,0) << "> " << vertex << endl;
|
|
|
|
Anabatic::GCell* gcell = vertex->getGCell();
|
|
SlicingNode* snode = findSlicingNode( gcell );
|
|
|
|
if (snode) {
|
|
cdebug_log(535,0) << "| isRouting():" << snode->isRouting() << endl;
|
|
|
|
if (snode->isRouting() and vertex->hasAData() )
|
|
snode->addWireOccupation( vertex->getIMin(), vertex->getIMax(), dijkstra->getNet() );
|
|
}
|
|
}
|
|
}
|
|
|
|
cdebug_tabw(535,-1);
|
|
}
|
|
|
|
|
|
void HVSlicingNode::resetWireOccupation ()
|
|
{
|
|
for ( RHVSlicingNode* node : _slicingRouting ) node ->resetWireOccupation();
|
|
for ( SlicingNode* child : _children ) child->resetWireOccupation();
|
|
}
|
|
|
|
|
|
} // Bora namespace.
|