6231 lines
186 KiB
C++
6231 lines
186 KiB
C++
// -*- C++ -*-
|
|
//
|
|
// This file is part of the Chams Software.
|
|
// Copyright (c) UPMC 2012-2016, All Rights Reserved
|
|
//
|
|
// +-----------------------------------------------------------------+
|
|
// | C H A M S |
|
|
// | H o r u s - S l i c i n g T r e e |
|
|
// | |
|
|
// | Authors : Eric LAO |
|
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
|
// | =============================================================== |
|
|
// | C++ Header : "./hurricaneAMS/layout/SlicingNode.cpp" |
|
|
// +-----------------------------------------------------------------+
|
|
|
|
#include "hurricane/Warning.h"
|
|
#include "hurricane/Breakpoint.h"
|
|
#include "hurricane/NetExternalComponents.h"
|
|
#include "hurricaneAMS/analogic/AnalogCellExtension.h"
|
|
#include "hurricaneAMS/layout/SlicingNode.h"
|
|
#include "anabatic/AnabaticEngine.h"
|
|
#include "hurricane/DeepNet.h"
|
|
#include "hurricane/Property.h"
|
|
#include "crlcore/AllianceFramework.h"
|
|
#include "crlcore/RoutingGauge.h"
|
|
#include "crlcore/RoutingLayerGauge.h"
|
|
|
|
using namespace std;
|
|
using Hurricane::Warning;
|
|
using Hurricane::Breakpoint;
|
|
using Hurricane::Error;
|
|
using Hurricane::NetRoutingState;
|
|
using Hurricane::NetRoutingExtension;
|
|
using Hurricane::NetExternalComponents;
|
|
using Hurricane::Net;
|
|
using Hurricane::Cell;
|
|
using Hurricane::DeepNet;
|
|
|
|
|
|
// -----------------------------------------------------------------------------------------------//
|
|
// Class : BoxSet
|
|
// -----------------------------------------------------------------------------------------------//
|
|
|
|
|
|
BoxSet::BoxSet( DbU::Unit height, DbU::Unit width ): _height( height )
|
|
, _width ( width )
|
|
, _cpt ( 1 ){}
|
|
|
|
|
|
BoxSet::BoxSet( BoxSet* boxSet )
|
|
{
|
|
if ( boxSet != NULL ){
|
|
_height = boxSet->getHeight();
|
|
_width = boxSet->getWidth();
|
|
_cpt = boxSet->getCpt();
|
|
} else {
|
|
_height = 0;
|
|
_width = 0;
|
|
_cpt = 1;
|
|
}
|
|
}
|
|
|
|
|
|
BoxSet::~BoxSet(){}
|
|
|
|
|
|
void BoxSet::print() const
|
|
{
|
|
cerr << "area: " << setprecision(4) << this->getOccupationArea() ;
|
|
cerr << "%, \t cpt: " << this->getCpt();
|
|
if ((this->getWidth() == 0) && (this->getHeight() == 0)) cerr << ", \t ratio (W/H):inf";
|
|
else cerr << ", \t ratio (W/H):" << setprecision(2) << this->getWidth()/this->getHeight();
|
|
cerr << ", \t ratio (W*H):" << setprecision(4) << DbU::getPhysical(this->getWidth(),DbU::Micro) * DbU::getPhysical(this->getHeight(),DbU::Micro) << "um²";
|
|
if (this->getType() == DeviceSNode){ cerr << ", \t Nfing: " << this->getNFing(); }
|
|
cerr << ", \t H: " << setprecision(4) << DbU::getPhysical(this->getHeight(),DbU::Micro) << "um" ;
|
|
cerr << ", W: " << DbU::getPhysical(this->getWidth(),DbU::Micro)<< "um";
|
|
cerr << endl;
|
|
}
|
|
|
|
|
|
const vector<BoxSet*>& BoxSet::getSet() const
|
|
{
|
|
cerr << "Error(vector< BoxSet*> getSet () const): DBoxSet and RHVBoxSet do not have vector of BoxSets." << endl;
|
|
static const vector<BoxSet*> boxSet = vector<BoxSet*> ();
|
|
return boxSet;
|
|
}
|
|
|
|
|
|
int BoxSet::getNFing() const
|
|
{
|
|
cerr << "Error(int BoxSet::getNFing() const): Only DBoxSet has fingers." << endl;
|
|
return 0;
|
|
}
|
|
|
|
|
|
void BoxSet::destroy()
|
|
{
|
|
delete(this);
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------------------------//
|
|
// Class : HVBoxSet
|
|
// -----------------------------------------------------------------------------------------------//
|
|
|
|
|
|
HVBoxSet::HVBoxSet( vector<BoxSet*> dimensionSet, DbU::Unit height, DbU::Unit width ): BoxSet ( height, width )
|
|
,_dimensionSet ( dimensionSet ){}
|
|
|
|
|
|
HVBoxSet::HVBoxSet( HVBoxSet* boxSet ): BoxSet ( boxSet )
|
|
, _dimensionSet ( boxSet->getSet() ){}
|
|
|
|
|
|
HVBoxSet::~HVBoxSet(){}
|
|
|
|
|
|
double HVBoxSet::getDevicesArea() const
|
|
{
|
|
double area = 0;
|
|
for (vector<BoxSet*>::const_iterator it = _dimensionSet.begin(); it != _dimensionSet.end(); it++){
|
|
area += (*it)->getDevicesArea();
|
|
}
|
|
return area;
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------------------------//
|
|
// Class : HBoxSet
|
|
// -----------------------------------------------------------------------------------------------//
|
|
|
|
|
|
int HBoxSet::_count = 0;
|
|
int HBoxSet::_countAll = 0;
|
|
|
|
|
|
HBoxSet::HBoxSet( vector< BoxSet*> dimensionSet, DbU::Unit height, DbU::Unit width ): HVBoxSet( dimensionSet, height, width )
|
|
{
|
|
if ( (_height == 0) && (_width == 0) ){
|
|
calculateHeight();
|
|
calculateWidth();
|
|
}
|
|
}
|
|
|
|
|
|
HBoxSet::HBoxSet( HBoxSet* boxSet ): HVBoxSet( boxSet ){}
|
|
|
|
|
|
HBoxSet::~HBoxSet(){}
|
|
|
|
|
|
HBoxSet* HBoxSet::create( vector< BoxSet*> dimensionSet, DbU::Unit height, DbU::Unit width )
|
|
{
|
|
_count++;
|
|
_countAll++;
|
|
return new HBoxSet( dimensionSet, height, width );
|
|
}
|
|
|
|
|
|
HBoxSet* HBoxSet::clone()
|
|
{
|
|
return HBoxSet::create( getSet(), getHeight(), getWidth() );
|
|
}
|
|
|
|
|
|
void HBoxSet::calculateHeight()
|
|
{
|
|
DbU::Unit currentH = 0;
|
|
for (vector<BoxSet*>::const_iterator it = _dimensionSet.begin(); it != _dimensionSet.end(); it++){
|
|
currentH += (*it)->getHeight();
|
|
}
|
|
_height = currentH;
|
|
}
|
|
|
|
|
|
void HBoxSet::calculateWidth()
|
|
{
|
|
DbU::Unit currentW = 0;
|
|
for (vector<BoxSet*>::const_iterator it = _dimensionSet.begin(); it != _dimensionSet.end(); it++){
|
|
if (currentW < (*it)->getWidth()){ currentW = (*it)->getWidth(); }
|
|
}
|
|
_width = currentW;
|
|
}
|
|
|
|
|
|
void HBoxSet::destroy()
|
|
{
|
|
_count--;
|
|
BoxSet::destroy();
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------------------------//
|
|
// Class : VBoxSet
|
|
// -----------------------------------------------------------------------------------------------//
|
|
|
|
|
|
int VBoxSet::_count = 0;
|
|
int VBoxSet::_countAll = 0;
|
|
|
|
|
|
VBoxSet::VBoxSet( vector<BoxSet*> dimensionSet, DbU::Unit height, DbU::Unit width ): HVBoxSet( dimensionSet, height, width )
|
|
{
|
|
if ( (_height == 0) && (_width == 0) ){
|
|
calculateHeight();
|
|
calculateWidth ();
|
|
}
|
|
}
|
|
|
|
|
|
VBoxSet::VBoxSet( VBoxSet* boxSet ): HVBoxSet( boxSet ){}
|
|
|
|
|
|
VBoxSet::~VBoxSet(){}
|
|
|
|
|
|
VBoxSet* VBoxSet::create( vector<BoxSet*> dimensionSet, DbU::Unit height, DbU::Unit width )
|
|
{
|
|
_count++;
|
|
_countAll++;
|
|
return new VBoxSet( dimensionSet, height, width );
|
|
}
|
|
|
|
|
|
VBoxSet* VBoxSet::clone()
|
|
{
|
|
return VBoxSet::create( getSet(), getHeight(), getWidth() );
|
|
}
|
|
|
|
|
|
void VBoxSet::calculateHeight()
|
|
{
|
|
DbU::Unit currentH = 0;
|
|
for (vector<BoxSet*>::const_iterator it = _dimensionSet.begin(); it != _dimensionSet.end(); it++){
|
|
if (currentH < (*it)->getHeight()){ currentH = (*it)->getHeight(); }
|
|
}
|
|
_height = currentH;
|
|
}
|
|
|
|
|
|
void VBoxSet::calculateWidth()
|
|
{
|
|
DbU::Unit currentW = 0;
|
|
for (vector<BoxSet*>::const_iterator it = _dimensionSet.begin(); it != _dimensionSet.end(); it++){
|
|
currentW += (*it)->getWidth();
|
|
}
|
|
_width = currentW;
|
|
}
|
|
|
|
|
|
void VBoxSet::destroy()
|
|
{
|
|
_count--;
|
|
BoxSet::destroy();
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------------------------//
|
|
// Class : DBoxSet
|
|
// -----------------------------------------------------------------------------------------------//
|
|
|
|
|
|
int DBoxSet::_count = 0;
|
|
int DBoxSet::_countAll = 0;
|
|
|
|
|
|
DBoxSet::DBoxSet( DbU::Unit height, DbU::Unit width, int nfing ): BoxSet( height, width ), _nfing(nfing){}
|
|
|
|
|
|
DBoxSet::DBoxSet( DBoxSet* boxSet ): BoxSet( boxSet ), _nfing(boxSet->getNFing()){}
|
|
|
|
|
|
DBoxSet::~DBoxSet(){}
|
|
|
|
|
|
DBoxSet* DBoxSet::create( DbU::Unit height, DbU::Unit width, int nfing )
|
|
{
|
|
_count++;
|
|
_countAll++;
|
|
return new DBoxSet( height, width, nfing );
|
|
}
|
|
|
|
|
|
DBoxSet* DBoxSet::clone()
|
|
{
|
|
return DBoxSet::create( getHeight(), getWidth(), getNFing() );
|
|
}
|
|
|
|
|
|
void DBoxSet::destroy()
|
|
{
|
|
_count--;
|
|
BoxSet::destroy();
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------------------------//
|
|
// Class : RHVBoxSet
|
|
// -----------------------------------------------------------------------------------------------//
|
|
|
|
|
|
int RHVBoxSet::_count = 0;
|
|
int RHVBoxSet::_countAll = 0;
|
|
|
|
|
|
RHVBoxSet::RHVBoxSet( DbU::Unit height, DbU::Unit width ): BoxSet( height, width )
|
|
{
|
|
_width = width;
|
|
_height = height;
|
|
}
|
|
|
|
|
|
RHVBoxSet::RHVBoxSet( RHVBoxSet* boxSet ): BoxSet( boxSet ){}
|
|
|
|
|
|
RHVBoxSet::~RHVBoxSet(){}
|
|
|
|
|
|
void RHVBoxSet::destroy()
|
|
{
|
|
_count--;
|
|
delete(this);
|
|
}
|
|
|
|
|
|
void RHVBoxSet::print() const
|
|
{
|
|
cerr << "area: " << setprecision(4) << this->getOccupationArea() ;
|
|
cerr << "%, \t cpt: " << this->getCpt();
|
|
// if ( (_width == 0)&&(_height == 0) ) cerr << ", \t ratio (W/H):inf";
|
|
// else cerr << ", \t ratio (W/H):" << _width/_height;
|
|
// cerr << ", \t ratio (W*H):" << setprecision(4) << DbU::getPhysical(_width,DbU::Micro) * DbU::getPhysical(_height,DbU::Micro) << "um²";
|
|
|
|
// if (this->getType() == DeviceSNode){ cerr << ", \t Nfing: " << this->getNFing(); }
|
|
cerr << ", \t H: " << setprecision(4) << DbU::getPhysical(_height,DbU::Micro) << "um" ;
|
|
cerr << ", W: " << DbU::getPhysical(_width,DbU::Micro)<< "um";
|
|
cerr << endl;
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------------------------//
|
|
// Class : RHBoxSet
|
|
// -----------------------------------------------------------------------------------------------//
|
|
|
|
|
|
RHBoxSet::RHBoxSet( DbU::Unit height ): RHVBoxSet( height, 0 ){}
|
|
|
|
|
|
RHBoxSet::RHBoxSet( RHBoxSet* boxSet ): RHVBoxSet( boxSet ){}
|
|
|
|
|
|
RHBoxSet::~RHBoxSet(){}
|
|
|
|
|
|
RHBoxSet* RHBoxSet::create( DbU::Unit height )
|
|
{
|
|
_count++;
|
|
_countAll++;
|
|
return new RHBoxSet ( height );
|
|
}
|
|
|
|
|
|
RHBoxSet* RHBoxSet::clone()
|
|
{
|
|
return RHBoxSet::create( getHeight() );
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------------------------//
|
|
// Class : RVBoxSet
|
|
// -----------------------------------------------------------------------------------------------//
|
|
|
|
|
|
RVBoxSet::RVBoxSet( DbU::Unit width ): RHVBoxSet( 0, width ){}
|
|
|
|
|
|
RVBoxSet::RVBoxSet( RVBoxSet* boxSet ): RHVBoxSet( boxSet ){}
|
|
|
|
|
|
RVBoxSet::~RVBoxSet(){}
|
|
|
|
|
|
RVBoxSet* RVBoxSet::create( DbU::Unit width )
|
|
{
|
|
_count++;
|
|
_countAll++;
|
|
return new RVBoxSet( width );
|
|
}
|
|
|
|
|
|
RVBoxSet* RVBoxSet::clone()
|
|
{
|
|
return RVBoxSet::create( getWidth() );
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------------------------//
|
|
// Class : NodeSets
|
|
// -----------------------------------------------------------------------------------------------//
|
|
|
|
|
|
NodeSets::NodeSets( double start, double step, double count )
|
|
{
|
|
_nodeSets = std::vector<BoxSet*>();
|
|
_nodeSets.clear();
|
|
_start = start;
|
|
_step = step;
|
|
_count = count;
|
|
}
|
|
|
|
|
|
NodeSets::NodeSets( const NodeSets* other )
|
|
{
|
|
_nodeSets = other->getNodeSets();
|
|
_start = other->getStartParameter();
|
|
_step = other->getStepParameter();
|
|
_count = other->getCountParameter();
|
|
}
|
|
|
|
|
|
NodeSets::~NodeSets(){}
|
|
|
|
|
|
NodeSets* NodeSets::create( Cell* cell, double start, double step, double count, CRL::RoutingGauge* rg )
|
|
{
|
|
NodeSets* nodeset = new NodeSets(start, step, count);
|
|
|
|
Device* dev = dynamic_cast<Device*>( cell );
|
|
if (dev) {
|
|
//cdebug_log(536,0) << "createNodeSets for an Analog Device" << endl;
|
|
TransistorFamily* tf = dynamic_cast<TransistorFamily*>(dev);
|
|
|
|
for (int i = 0; i < count; i++){
|
|
tf->setNfing( start + i*step );
|
|
|
|
FormFactorParameter* pff = NULL;
|
|
if ( (pff = dynamic_cast<FormFactorParameter*>(tf->getParameter("M"))) != NULL )
|
|
pff->setValue( tf->getNfing() );
|
|
|
|
auto_ptr<LayoutGenerator> layoutGenerator ( new LayoutGenerator() );
|
|
layoutGenerator->setDevice(dev);
|
|
layoutGenerator->drawLayout();
|
|
|
|
if (rg){
|
|
float h2pitch = rg->getHorizontalPitch()*2;
|
|
float v2pitch = rg->getVerticalPitch ()*2;
|
|
|
|
float h = dev->getAbutmentBox().getHeight();
|
|
float w = dev->getAbutmentBox().getWidth();
|
|
|
|
if (fmod(h,h2pitch) > 1e-06) {
|
|
cerr << Warning( "NodeSets::create(): The height of device \"%s\" (%s) is not pitched on 2*%s (adjusted)."
|
|
, getString(dev->getName()).c_str()
|
|
, DbU::getValueString(dev->getAbutmentBox().getWidth()).c_str()
|
|
, DbU::getValueString(rg->getHorizontalPitch()*2).c_str()
|
|
) << endl;
|
|
}
|
|
if (fmod(w,v2pitch) > 1e-06) {
|
|
cerr << Warning( "NodeSets::create(): The width of device \"%s\" (%s) is not pitched on 2*%s (adjusted)."
|
|
, getString(dev->getName()).c_str()
|
|
, DbU::getValueString(dev->getAbutmentBox().getWidth()).c_str()
|
|
, DbU::getValueString(rg->getVerticalPitch()*2).c_str()
|
|
) << endl;
|
|
}
|
|
|
|
nodeset->push_back(DBoxSet::create( ceil(h/h2pitch)*h2pitch
|
|
, ceil(w/v2pitch)*v2pitch
|
|
, start + i*step
|
|
)
|
|
);
|
|
} else {
|
|
nodeset->push_back(DBoxSet::create( dev->getAbutmentBox().getHeight()
|
|
, dev->getAbutmentBox().getWidth()
|
|
, start + i*step
|
|
)
|
|
);
|
|
}
|
|
}
|
|
} else {
|
|
//cdebug_log(536,0) << "createNodeSets for a Digital Device: " << cell << endl;
|
|
if (rg) {
|
|
DbU::Unit h2pitch = rg->getHorizontalPitch()*2;
|
|
DbU::Unit v2pitch = rg->getVerticalPitch ()*2;
|
|
DbU::Unit h = cell->getAbutmentBox().getHeight();
|
|
DbU::Unit w = cell->getAbutmentBox().getWidth();
|
|
|
|
if (h % h2pitch) {
|
|
cerr << Warning( "NodeSets::create(): The height of device \"%s\" (%s) is not pitched on %s*2 (adjusted)."
|
|
, getString(cell->getName()).c_str()
|
|
, DbU::getValueString(cell->getAbutmentBox().getHeight()).c_str()
|
|
, DbU::getValueString(rg->getHorizontalPitch()).c_str()
|
|
) << endl;
|
|
}
|
|
if (w % v2pitch) {
|
|
cerr << Warning( "NodeSets::create(): The width of device \"%s\" (%s) is not pitched on %s*2 (adjusted)."
|
|
, getString(cell->getName()).c_str()
|
|
, DbU::getValueString(cell->getAbutmentBox().getWidth()).c_str()
|
|
, DbU::getValueString(rg->getVerticalPitch()).c_str()
|
|
) << endl;
|
|
}
|
|
|
|
nodeset->push_back(DBoxSet::create( ceil(h/h2pitch)*h2pitch
|
|
, ceil(w/v2pitch)*v2pitch
|
|
)
|
|
);
|
|
} else {
|
|
nodeset->push_back(DBoxSet::create( cell->getAbutmentBox().getHeight()
|
|
, cell->getAbutmentBox().getWidth()
|
|
)
|
|
);
|
|
}
|
|
}
|
|
return nodeset;
|
|
}
|
|
|
|
NodeSets* NodeSets::create()
|
|
{
|
|
return new NodeSets();
|
|
}
|
|
|
|
|
|
BoxSet* NodeSets::operator[] ( size_t i )
|
|
{
|
|
if (i < _nodeSets.size()) return _nodeSets[i];
|
|
return NULL;
|
|
}
|
|
|
|
|
|
BoxSet* NodeSets::at ( size_t i )
|
|
{
|
|
if (i < _nodeSets.size()) return _nodeSets[i];
|
|
return NULL;
|
|
}
|
|
|
|
|
|
void NodeSets::clear()
|
|
{
|
|
if ( _nodeSets.empty() != true ){
|
|
for (vector<BoxSet*>::iterator it = _nodeSets.begin(); it != _nodeSets.end(); it++){
|
|
(*it)->destroy();
|
|
}
|
|
_nodeSets.clear();
|
|
}
|
|
}
|
|
|
|
|
|
BoxSet* NodeSets::getPairH( DbU::Unit height ) const
|
|
{
|
|
DbU::Unit w = 0;
|
|
DbU::Unit hclosest = 0;
|
|
BoxSet* boxSet = (*_nodeSets.begin());
|
|
|
|
for (vector<BoxSet*>::const_iterator itHW = _nodeSets.begin(); itHW != _nodeSets.end(); itHW++){
|
|
|
|
if ( ((*itHW)->getHeight() > hclosest) && (height >= (*itHW)->getHeight()) ){
|
|
hclosest = (*itHW)->getHeight();
|
|
w = (*itHW)->getWidth();
|
|
boxSet = (*itHW);
|
|
}
|
|
}
|
|
|
|
if ( (w == 0) && (hclosest == 0) )
|
|
{ cerr << "Error(pair<DbU::Unit,DbU::Unit> NodeSets::getPairH( DbU::Unit height ) const): No solution for h = " << height << " has been found." << endl; }
|
|
|
|
return boxSet;
|
|
}
|
|
|
|
|
|
BoxSet* NodeSets::getPairHW( DbU::Unit height, DbU::Unit width ) const
|
|
{
|
|
vector<BoxSet*>::const_iterator it = _nodeSets.begin();
|
|
DbU::Unit bestH = (*it)->getHeight();
|
|
DbU::Unit bestW = (*it)->getWidth();
|
|
DbU::Unit currentH = 0;
|
|
DbU::Unit currentW = 0;
|
|
BoxSet* boxSet = (*it);
|
|
|
|
while (it != _nodeSets.end()){
|
|
currentH = (*it)->getHeight();
|
|
currentW = (*it)->getWidth();
|
|
|
|
if (currentH <= height){
|
|
if ( currentH > bestH ){
|
|
bestH = currentH;
|
|
bestW = currentW;
|
|
boxSet = (*it);
|
|
} else if (currentH == bestH){
|
|
if ( (currentW > bestW) && (currentW <= width) ){
|
|
bestH = currentH;
|
|
bestW = currentW;
|
|
boxSet = (*it);
|
|
}
|
|
else if ( (currentW < bestW) && (bestW > width) ){
|
|
bestH = currentH;
|
|
bestW = currentW;
|
|
boxSet = (*it);
|
|
}
|
|
}
|
|
it++;
|
|
} else {
|
|
it = _nodeSets.end();
|
|
}
|
|
}
|
|
|
|
return boxSet;
|
|
}
|
|
|
|
|
|
BoxSet* NodeSets::getPairHW( unsigned int index ) const
|
|
{
|
|
BoxSet* bs = NULL;
|
|
if ( index < _nodeSets.size() ){
|
|
bs = _nodeSets[index];
|
|
}
|
|
return bs;
|
|
}
|
|
|
|
|
|
int NodeSets::findIndex( DbU::Unit height, DbU::Unit width ) const
|
|
{
|
|
bool end = false;
|
|
int indextbd = 0;
|
|
int index = 0;
|
|
vector<BoxSet*>::const_iterator it = _nodeSets.begin();
|
|
|
|
while(end == false){
|
|
if ( ((*it)->getHeight() == height) && ((*it)->getWidth() == width) ){
|
|
indextbd = index;
|
|
end = true;
|
|
}
|
|
index++;
|
|
it++;
|
|
if (it == _nodeSets.end()){ end = true; }
|
|
}
|
|
|
|
return indextbd;
|
|
}
|
|
|
|
|
|
vector<BoxSet* >::iterator NodeSets::find( DbU::Unit height, DbU::Unit width )
|
|
{
|
|
vector<BoxSet* >::iterator it = _nodeSets.begin();
|
|
vector<BoxSet* >::iterator itFind = _nodeSets.end();
|
|
|
|
if (_nodeSets.empty() != true){
|
|
|
|
while(it != _nodeSets.end()){
|
|
if ( ((*it)->getHeight() == height) && ((*it)->getWidth() == width) ){
|
|
itFind = it;
|
|
it = _nodeSets.end();
|
|
}
|
|
else { it++; }
|
|
if ( it == _nodeSets.end() ){ it = _nodeSets.end(); }
|
|
}
|
|
} else { it = _nodeSets.end(); }
|
|
|
|
return itFind;
|
|
}
|
|
|
|
|
|
vector<BoxSet* >::iterator NodeSets::find( BoxSet* boxSet )
|
|
{
|
|
vector<BoxSet* >::iterator it = _nodeSets.begin();
|
|
vector<BoxSet* >::iterator itFind = _nodeSets.end();
|
|
|
|
if ( (_nodeSets.empty() != true) && (boxSet != NULL) ){
|
|
|
|
while(it != _nodeSets.end()){
|
|
if ( ((*it)->getHeight() == boxSet->getHeight()) && ((*it)->getWidth() == boxSet->getWidth()) ){
|
|
itFind = it;
|
|
it = _nodeSets.end();
|
|
}
|
|
else { it++; }
|
|
}
|
|
} else { it = _nodeSets.end(); }
|
|
|
|
return itFind;
|
|
}
|
|
|
|
|
|
vector<BoxSet* >::iterator NodeSets::find( int nfing )
|
|
{
|
|
vector<BoxSet* >::iterator it = _nodeSets.begin();
|
|
vector<BoxSet* >::iterator itFind = _nodeSets.end();
|
|
|
|
if ( (_nodeSets.empty() != true) ){
|
|
|
|
while(it != _nodeSets.end()){
|
|
if ( (*it)->getNFing() == nfing ){
|
|
itFind = it;
|
|
it = _nodeSets.end();
|
|
}
|
|
else { it++; }
|
|
}
|
|
} else { it = _nodeSets.end(); }
|
|
|
|
return itFind;
|
|
}
|
|
|
|
|
|
void NodeSets::print() const
|
|
{
|
|
cerr << "Print - NodeSets:" << endl;
|
|
int index = 0;
|
|
if ( this->size() == 0){ cerr << "--- EMPTY ---" << endl; }
|
|
else {
|
|
for (vector<BoxSet*>::const_iterator itPrint = _nodeSets.begin(); itPrint != _nodeSets.end(); itPrint++)
|
|
{
|
|
cerr << index << ": \t";
|
|
(*itPrint)->print();
|
|
index++;
|
|
}
|
|
cerr << endl;
|
|
}
|
|
}
|
|
|
|
|
|
bool NodeSets::compare ( NodeSets nodeSets2, unsigned int flags ) const
|
|
{
|
|
if (_nodeSets.size() != nodeSets2.size()) {
|
|
if (flags & ShowDiff)
|
|
cerr << "NodeSets::compare() size differs: " << _nodeSets.size()
|
|
<< " vs. " << nodeSets2.size() << endl;
|
|
return false;
|
|
}
|
|
|
|
bool isSame = true;
|
|
for ( size_t iset = 0 ; iset<_nodeSets.size() ; ++iset ) {
|
|
if ( (_nodeSets[iset]->getHeight() != nodeSets2[iset]->getHeight())
|
|
or (_nodeSets[iset]->getWidth () != nodeSets2[iset]->getWidth ()) ) {
|
|
isSame = false;
|
|
if (flags & ShowDiff)
|
|
cerr << "NodeSets::compare() Box [" << iset << "] differs "
|
|
<< " (" << DbU::getValueString(_nodeSets[iset]->getWidth()) << "," << DbU::getValueString(_nodeSets[iset]->getHeight()) << ") vs."
|
|
<< " (" << DbU::getValueString(nodeSets2[iset]->getWidth()) << "," << DbU::getValueString(nodeSets2[iset]->getHeight()) << ")"
|
|
<< endl;
|
|
}
|
|
}
|
|
|
|
return isSame;
|
|
}
|
|
|
|
|
|
void NodeSets::push_back( BoxSet* boxSet )
|
|
{
|
|
if( this->find(boxSet) == _nodeSets.end() ){ _nodeSets.push_back(boxSet); }
|
|
else {
|
|
(*find(boxSet))->incrementCpt();
|
|
boxSet->destroy();
|
|
}
|
|
}
|
|
|
|
|
|
void NodeSets::push_back( vector<BoxSet*> vect, DbU::Unit height, DbU::Unit width, unsigned int type )
|
|
{
|
|
if( this->find(height, width) == _nodeSets.end() ){
|
|
if (type == HorizontalSNode){
|
|
_nodeSets.push_back(HBoxSet::create(vect, height, width));
|
|
}
|
|
else if (type == VerticalSNode){
|
|
_nodeSets.push_back(VBoxSet::create(vect, height, width));
|
|
}
|
|
}
|
|
else {
|
|
(*find(height, width))->incrementCpt();
|
|
}
|
|
}
|
|
|
|
|
|
NodeSets* NodeSets::clone()
|
|
{
|
|
NodeSets* nodesets = new NodeSets( _start, _step, _count );
|
|
for (vector<BoxSet*>::iterator it = _nodeSets.begin(); it != _nodeSets.end(); it++)
|
|
{
|
|
nodesets->push_back((*it)->clone());
|
|
}
|
|
return nodesets;
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------------------------//
|
|
// Class : SlicingNode
|
|
// -----------------------------------------------------------------------------------------------//
|
|
|
|
CRL::RoutingGauge* SlicingNode::_rg = NULL;
|
|
Cell* SlicingNode::_cell = NULL;
|
|
Katana::KatanaEngine* SlicingNode::_katana = NULL;
|
|
vector<Segment*> SlicingNode::_railSegments = vector<Segment*>();
|
|
|
|
SlicingNode::SlicingNode( unsigned int type
|
|
, NodeSets* nodeSets
|
|
, unsigned int alignment
|
|
, BoxSet* boxSet
|
|
):_nodeSets(nodeSets)
|
|
,_x(0), _y(0)
|
|
{
|
|
_flags = 0;
|
|
_parent = NULL;
|
|
_master = NULL;
|
|
_gcell = NULL;
|
|
_nodeSets = nodeSets;
|
|
_x = 0;
|
|
_y = 0;
|
|
this->setType(type);
|
|
this->setAlignment(alignment);
|
|
|
|
if ( boxSet != NULL ){
|
|
this->setBoxSet(boxSet);
|
|
this->setPreset(Preset);
|
|
this->setSet(Set);
|
|
}
|
|
}
|
|
|
|
|
|
SlicingNode::~SlicingNode(){}
|
|
|
|
|
|
bool SlicingNode::isSameSize( BoxSet* boxSet ) const
|
|
{
|
|
bool same = false;
|
|
if ( (_boxSet != NULL)&&(boxSet != NULL) ){
|
|
if ((_boxSet->getHeight() == boxSet->getHeight()) && (_boxSet->getWidth() == boxSet->getWidth())){
|
|
same = true;
|
|
}
|
|
}
|
|
return same;
|
|
}
|
|
|
|
|
|
bool SlicingNode::isSameSize( DbU::Unit height, DbU::Unit width ) const
|
|
{
|
|
bool same = false;
|
|
if ( _boxSet != NULL ){
|
|
if ( (_boxSet->getHeight() == height) && (_boxSet->getWidth() == width) ){
|
|
same = true;
|
|
}
|
|
}
|
|
return same;
|
|
}
|
|
|
|
|
|
bool SlicingNode::isEmpty() const
|
|
{
|
|
return _nodeSets->empty();
|
|
}
|
|
|
|
|
|
DbU::Unit SlicingNode::getHeight () const
|
|
{
|
|
if (_boxSet != NULL){
|
|
return _boxSet->getHeight();
|
|
} else { return 0; }
|
|
}
|
|
|
|
|
|
DbU::Unit SlicingNode::getWidth () const
|
|
{
|
|
if (_boxSet != NULL){
|
|
return _boxSet->getWidth();
|
|
} else { return 0; }
|
|
}
|
|
|
|
|
|
|
|
DbU::Unit SlicingNode::getRootHeight () const
|
|
{
|
|
if (_parent){
|
|
SlicingNode* p = _parent;
|
|
while(p->getParent()){
|
|
p = p->getParent();
|
|
}
|
|
return p->getHeight();
|
|
} else {
|
|
return getHeight();
|
|
}
|
|
}
|
|
|
|
|
|
DbU::Unit SlicingNode::getRootWidth () const
|
|
{
|
|
if (_parent){
|
|
SlicingNode* p = _parent;
|
|
while(p->getParent()){
|
|
p = p->getParent();
|
|
}
|
|
return p->getWidth();
|
|
} else {
|
|
return getWidth();
|
|
}
|
|
}
|
|
|
|
|
|
DbU::Unit SlicingNode::getRootX () const
|
|
{
|
|
if (_parent){
|
|
SlicingNode* p = _parent;
|
|
while(p->getParent()){
|
|
p = p->getParent();
|
|
}
|
|
return p->getX();
|
|
} else {
|
|
return getX();
|
|
}
|
|
}
|
|
|
|
|
|
DbU::Unit SlicingNode::getRootY () const
|
|
{
|
|
if (_parent){
|
|
SlicingNode* p = _parent;
|
|
while(p->getParent()){
|
|
p = p->getParent();
|
|
}
|
|
return p->getY();
|
|
} else {
|
|
return getY();
|
|
}
|
|
}
|
|
|
|
|
|
SlicingNode* SlicingNode::getRoot()
|
|
{
|
|
SlicingNode* parent = this;
|
|
if (_parent != NULL){ parent = _parent->getRoot(); }
|
|
return parent;
|
|
}
|
|
|
|
|
|
int SlicingNode::getCpt()
|
|
{
|
|
if (_boxSet != NULL){ return _boxSet->getCpt(); }
|
|
else { return 0; }
|
|
}
|
|
|
|
|
|
double SlicingNode::getRatio()
|
|
{
|
|
if (_boxSet != NULL){ return _boxSet->getRatio(); }
|
|
else { return 0; }
|
|
}
|
|
|
|
|
|
double SlicingNode::getArea()
|
|
{
|
|
if (_boxSet != NULL){ return _boxSet->getArea(); }
|
|
else { return 0; }
|
|
}
|
|
|
|
|
|
DbU::Unit SlicingNode::getVPitch ()
|
|
{
|
|
if (_rg) return _rg->getVerticalPitch();
|
|
|
|
cerr << Error( "DbU::Unit getVPitch(): RoutingGauge has not been defined." ) << endl;
|
|
return 0;
|
|
}
|
|
|
|
DbU::Unit SlicingNode::getHPitch ()
|
|
{
|
|
if (_rg) return _rg->getHorizontalPitch();
|
|
|
|
cerr << Error( "DbU::Unit getHPitch(): RoutingGauge has not been defined." ) << endl;
|
|
return 0;
|
|
}
|
|
|
|
void SlicingNode::setBoxSet( BoxSet* boxSet )
|
|
{
|
|
if ( (!this->isPreset()) ){
|
|
if (_nodeSets->find(boxSet) != _nodeSets->end()){
|
|
this->setSet(Set);
|
|
_boxSet = boxSet;
|
|
} else {
|
|
cerr << "Error(void SlicingNode::setBoxSet( BoxSet* boxSet )): Boxset not found.";
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void SlicingNode::setBoxSet( DbU::Unit height, DbU::Unit width )
|
|
{
|
|
if (!this->isPreset()){
|
|
if (_nodeSets->find(height, width) != _nodeSets->end()){
|
|
this->setSet(Set);
|
|
_boxSet = (*_nodeSets->find(height, width));
|
|
} else {
|
|
cerr << "Error(void SlicingNode::setBoxSet( BoxSet* boxSet )): Boxset not found.";
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void SlicingNode::setBoxSet( size_t index )
|
|
{
|
|
if (index > (_nodeSets->size()-1)){ cerr << "Error(void SlicingNode::setBoxSet( int index )): Out of bound index." << endl; }
|
|
else {
|
|
this->_setBoxSet((*(_nodeSets->begin() + index)));
|
|
}
|
|
}
|
|
|
|
|
|
void SlicingNode::_setBoxSet( BoxSet* boxSet )
|
|
{
|
|
if (isPreset()) return;
|
|
|
|
setSet( Set );
|
|
_boxSet = boxSet;
|
|
}
|
|
|
|
|
|
void SlicingNode::setX ( DbU::Unit x )
|
|
{
|
|
float pitch = _rg->getVerticalPitch();
|
|
|
|
if (fmod(x,pitch) > 1e-06) {
|
|
cerr << Warning( "SlicingNode::setX(): On %s, X position %s is not pitched on %s (will be adjusted)."
|
|
, getString(this).c_str()
|
|
, DbU::getValueString(x ).c_str()
|
|
, DbU::getValueString(pitch).c_str()
|
|
) << endl;
|
|
}
|
|
|
|
_x = x;
|
|
}
|
|
|
|
|
|
void SlicingNode::setY ( DbU::Unit y )
|
|
{
|
|
float pitch = _rg->getHorizontalPitch();
|
|
|
|
if (fmod(y,pitch) > 1e-06) {
|
|
cerr << Warning( "SlicingNode::setY(): On %s, Y position %s is not pitched on %s (will be adjusted)."
|
|
, getString(this).c_str()
|
|
, DbU::getValueString(y ).c_str()
|
|
, DbU::getValueString(pitch).c_str()
|
|
) << endl;
|
|
}
|
|
|
|
_y = y;
|
|
}
|
|
|
|
|
|
void SlicingNode::clearParentsNodeSets()
|
|
{
|
|
if ( _parent != NULL ){ _parent->clearParentsNodeSets(); }
|
|
if (getMaster() == NULL) _nodeSets->clear();
|
|
}
|
|
|
|
|
|
void SlicingNode::resetSlicingTree()
|
|
{
|
|
// -----------------------------------------------------------------------------------------------//
|
|
// Notes: Reset a slicing tree means:
|
|
// - Empty NodeSets of every parent
|
|
// - Unset every nodes that are not preset
|
|
// - Unplace every nodes
|
|
// -----------------------------------------------------------------------------------------------//
|
|
|
|
clearParentsNodeSets();
|
|
getRoot()->_resetSlicingTree();
|
|
}
|
|
|
|
|
|
void SlicingNode::_resetSlicingTree()
|
|
{
|
|
_x = 0;
|
|
_y = 0;
|
|
setPlaced(false);
|
|
|
|
if (!this->isPreset()){
|
|
_boxSet = NULL;
|
|
setSet(false);
|
|
}
|
|
}
|
|
|
|
|
|
void SlicingNode::print() const
|
|
{
|
|
printParent();
|
|
if ( this->isPreset() ){ cerr << "Preset : True" << endl; }
|
|
else { cerr << "Preset : False " << endl; }
|
|
if ( this->isSet() ) { cerr << "Set : True" << endl; }
|
|
else { cerr << "Set : False " << endl; }
|
|
if ( this->isPlaced() ){ cerr << "Placed : True" << endl; }
|
|
else { cerr << "Placed : False " << endl; }
|
|
if ( this->getMaster()){
|
|
cerr << "Master : ";
|
|
this->getMaster()->printLine();
|
|
}
|
|
unsigned int type = getType();
|
|
if ( type == HorizontalSNode ){ cerr << "Type : HorizontalSNode"<< endl; }
|
|
else if ( type == VerticalSNode ){ cerr << "Type : VerticalSNode" << endl; }
|
|
else if ( type == DeviceSNode ){ cerr << "Type : DeviceSNode" << endl; }
|
|
else if ( type == RoutingSNode ){ cerr << "Type : RoutingSNode" << endl; }
|
|
else { cerr << "Type : UnknownType" << endl; }
|
|
cerr << "Height : " << DbU::getPhysical(getHeight(),DbU::Micro) << endl;
|
|
cerr << "Width : " << DbU::getPhysical(getWidth(),DbU::Micro) << endl;
|
|
cerr << "X : " << DbU::getPhysical(_x,DbU::Micro) << endl;
|
|
cerr << "Y : " << DbU::getPhysical(_y,DbU::Micro) << endl;
|
|
if (isRoutingEstimated()) cerr << "REstimated : True" << endl;
|
|
else cerr << "REstimated : False" << endl;
|
|
|
|
//_nodeSets->print();
|
|
cerr << "GCell : " << _gcell << endl;
|
|
if (!((getType() == HorizontalSNode)||(getType() == VerticalSNode))){
|
|
cerr << "GCell : " << _gcell << endl;
|
|
if(_gcell){
|
|
cerr << "Edges : " << endl;
|
|
vector<Anabatic::Edge*> ne = _gcell->getNorthEdges();
|
|
vector<Anabatic::Edge*> se = _gcell->getSouthEdges();
|
|
vector<Anabatic::Edge*> ee = _gcell->getEastEdges();
|
|
vector<Anabatic::Edge*> we = _gcell->getWestEdges();
|
|
|
|
cerr << "--- North : " << endl;
|
|
for (vector<Anabatic::Edge*>::const_iterator itn = ne.begin(); itn != ne.end(); itn++){
|
|
cerr << (*itn)->getOpposite(_gcell) << endl;
|
|
}
|
|
cerr << "--- South : " << endl;
|
|
for (vector<Anabatic::Edge*>::const_iterator its = se.begin(); its != se.end(); its++){
|
|
cerr << (*its)->getOpposite(_gcell) << endl;
|
|
}
|
|
cerr << "--- East : " << endl;
|
|
for (vector<Anabatic::Edge*>::const_iterator ite = ee.begin(); ite != ee.end(); ite++){
|
|
cerr << (*ite)->getOpposite(_gcell) << endl;
|
|
}
|
|
cerr << "--- West : " << endl;
|
|
for (vector<Anabatic::Edge*>::const_iterator itw = we.begin(); itw != we.end(); itw++){
|
|
cerr << (*itw)->getOpposite(_gcell) << endl;
|
|
}
|
|
}
|
|
}
|
|
cerr << endl;
|
|
|
|
}
|
|
|
|
|
|
void SlicingNode::printLine() const
|
|
{
|
|
unsigned int type = getType();
|
|
if (_master) {
|
|
cerr << " [MASTER]: ";
|
|
_master->printLine();
|
|
}
|
|
if ( type == HorizontalSNode ){ cerr << "Type : HorizontalSNode"; }
|
|
else if ( type == VerticalSNode ){ cerr << "Type : VerticalSNode" ; }
|
|
else if ( type == DeviceSNode ){ cerr << "Type : DeviceSNode" ; }
|
|
else if ( type == RoutingSNode ){ cerr << "Type : RoutingSNode" ; }
|
|
else { cerr << "Type : UnknownType" ; }
|
|
cerr << ", X: " << DbU::getPhysical(getX(),DbU::Micro);
|
|
cerr << ", Y: " << DbU::getPhysical(getY(),DbU::Micro);
|
|
cerr << ", W: " << setprecision(4) << DbU::getPhysical(getWidth() ,DbU::Micro);
|
|
cerr << ", H: " << setprecision(4) << DbU::getPhysical(getHeight(),DbU::Micro) << endl;
|
|
}
|
|
|
|
|
|
void SlicingNode::printParent() const
|
|
{
|
|
if (_parent != NULL){
|
|
unsigned int type = _parent->getType();
|
|
if ( type == HorizontalSNode ){ cerr << "Parent : Type: HorizontalSNode" ; }
|
|
else if ( type == VerticalSNode ){ cerr << "Parent : Type: VerticalSNode" ; }
|
|
else { cerr << "Parent : Type: UnknownType"; }
|
|
cerr << ", H: " << setprecision(4) << DbU::getPhysical(_parent->getHeight(),DbU::Micro);
|
|
cerr << ", W: " << setprecision(4) << DbU::getPhysical(_parent->getWidth(),DbU::Micro);
|
|
cerr << ", X: " << DbU::getPhysical(_parent->getX(),DbU::Micro);
|
|
cerr << ", Y: " << DbU::getPhysical(_parent->getY(),DbU::Micro) << endl;
|
|
} else {
|
|
cerr << "Parent : IsROOT " << endl;
|
|
}
|
|
}
|
|
|
|
|
|
string SlicingNode::_getString () const
|
|
{
|
|
ostringstream os;
|
|
os << "<" << _getTypeName();
|
|
if (getGCell()) os << " id:" << getGCell()->getId();
|
|
os << " " << (void*)this << ">";
|
|
return os.str();
|
|
}
|
|
|
|
|
|
string SlicingNode::_getTypeName () const
|
|
{ return "SlicingNode"; }
|
|
|
|
|
|
void SlicingNode::printBoxSet() const
|
|
{
|
|
if (_boxSet != NULL){
|
|
_boxSet->print();
|
|
}
|
|
}
|
|
|
|
|
|
void SlicingNode::place( DbU::Unit x, DbU::Unit y )
|
|
{
|
|
cdebug_log(536,1) << "SlicingNode::place(DbU::Unit x, DbU::Unit y)" << endl;
|
|
|
|
if (isSet()) {
|
|
_x = x;
|
|
_y = y;
|
|
setPlaced( Placed );
|
|
|
|
DbU::Unit hpitch = _rg->getHorizontalPitch();
|
|
DbU::Unit vpitch = _rg->getVerticalPitch();
|
|
|
|
if (_x % vpitch)
|
|
cerr << Warning( "SlicingNode::place(): On %s, _x is not pitched (%s, pitch:%s)."
|
|
, getString(this).c_str()
|
|
, DbU::getValueString(_x).c_str()
|
|
, DbU::getValueString(vpitch).c_str()
|
|
) << endl;
|
|
|
|
if (_y % hpitch)
|
|
cerr << Warning( "SlicingNode::place(): On %s, _y is not pitched (%s, pitch:%s)."
|
|
, getString(this).c_str()
|
|
, DbU::getValueString(_y).c_str()
|
|
, DbU::getValueString(hpitch).c_str()
|
|
) << endl;
|
|
} else
|
|
cerr << Error( "SlicingNode::place(DbU::Unit x, DbU::Unit y): Device has not been set." ) << endl;
|
|
|
|
cdebug_tabw(536,-1);
|
|
}
|
|
|
|
|
|
void SlicingNode::replace( DbU::Unit x, DbU::Unit y )
|
|
{
|
|
cdebug_log(536,1) << "SlicingNode::replace(DbU::Unit x, DbU::Unit y)" << endl;
|
|
|
|
if (isSet()) {
|
|
_x = x;
|
|
_y = y;
|
|
setPlaced( Placed );
|
|
} else
|
|
cerr << Error( "SlicingNode::replace(DbU::Unit x, DbU::Unit y): Device has not been set." ) << endl;
|
|
|
|
cdebug_tabw(536,-1);
|
|
}
|
|
|
|
|
|
void SlicingNode::_place( DbU::Unit x, DbU::Unit y, bool replace )
|
|
{
|
|
cdebug_log(536,1) << "SlicingNode::place(DbU::Unit x, DbU::Unit y)" << endl;
|
|
SlicingNode::place(x,y);
|
|
cdebug_tabw(536,-1);
|
|
}
|
|
|
|
|
|
void SlicingNode::setGlobalSize( DbU::Unit height, DbU::Unit width )
|
|
{
|
|
cmess2 << " o Selecting box set (" << DbU::getValueString(height)
|
|
<< "," << DbU::getValueString(width) << ")" << endl;
|
|
|
|
this->setBoxSet( height, width );
|
|
}
|
|
|
|
|
|
void SlicingNode::setGlobalSize( size_t index )
|
|
{
|
|
cmess2 << " o Selecting box set at index " << index << endl;
|
|
|
|
this->setBoxSet( index );
|
|
}
|
|
|
|
|
|
void SlicingNode::_setGlobalSize ( BoxSet* boxSet )
|
|
{
|
|
cdebug_log(535,1) << "SlicingNode::_setGlobalSize( BoxSet* boxSet ) " << endl;
|
|
_setBoxSet( boxSet );
|
|
cdebug_log(535,-1);
|
|
}
|
|
|
|
|
|
void SlicingNode::preDestroy()
|
|
{
|
|
if ( _parent != NULL ){
|
|
_parent->removeNode(this);
|
|
}/* else {
|
|
if (_railCell) _railCell->destroy();
|
|
}*/
|
|
if (this->getMaster() == NULL) _nodeSets->clear();
|
|
}
|
|
|
|
|
|
void SlicingNode::destroy()
|
|
{
|
|
SlicingNode::preDestroy();
|
|
delete(this);
|
|
}
|
|
|
|
|
|
void SlicingNode::preRecursiveDestroy()
|
|
{
|
|
SlicingNode::preDestroy();
|
|
}
|
|
|
|
|
|
void SlicingNode::recursiveDestroy()
|
|
{
|
|
SlicingNode::preRecursiveDestroy();
|
|
delete(this);
|
|
}
|
|
|
|
|
|
list<SlicingNode*> SlicingNode::getLeaves() const
|
|
{
|
|
return list<SlicingNode*>();
|
|
}
|
|
|
|
|
|
bool SlicingNode::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; }
|
|
return initialPlacement;
|
|
}
|
|
|
|
void SlicingNode::updateCellAbutmentBox()
|
|
{
|
|
Point pmin = Point(getX(), getY());
|
|
Point pmax = Point(getX()+getWidth(), getY()+getHeight());
|
|
Box box = Box(pmin, pmax);
|
|
_cell->setAbutmentBox(box);
|
|
}
|
|
|
|
|
|
void SlicingNode::setGCell( Anabatic::GCell* gcell )
|
|
{
|
|
_gcell = gcell;
|
|
cdebug_log(535,0) << "SlicingNode::setGCell() " << _gcell << endl;
|
|
}
|
|
|
|
// Error Methods
|
|
DbU::Unit SlicingNode::getToleranceRatioH() const
|
|
{
|
|
cerr << "Error(DbU::Unit SlicingNode::getToleranceH()): Device and Routing do not have tolerance parameters." << endl;
|
|
return 0;
|
|
}
|
|
|
|
|
|
DbU::Unit SlicingNode::getToleranceRatioW() const
|
|
{
|
|
cerr << "Error(DbU::Unit SlicingNode::getToleranceW()): Device and Routing do not have tolerance parameters." << endl;
|
|
return 0;
|
|
}
|
|
|
|
|
|
void SlicingNode::setToleranceRatioH( DbU::Unit tolerance )
|
|
{
|
|
cerr << "Error(void SlicingNode::setToleranceH( DbU::Unit tolerance )): Device and Routing do not have tolerance parameters." << endl;
|
|
}
|
|
|
|
|
|
void SlicingNode::setToleranceRatioW( DbU::Unit tolerance )
|
|
{
|
|
cerr << "Error(void SlicingNode::setToleranceW( DbU::Unit tolerance )): Device and Routing do not have tolerance parameters." << endl;
|
|
}
|
|
|
|
|
|
DbU::Unit SlicingNode::getToleranceBandH() const
|
|
{
|
|
cerr << "Error(DbU::Unit SlicingNode::getToleranceBandH()): Device and Routing do not have tolerance parameters." << endl;
|
|
return 0;
|
|
}
|
|
|
|
|
|
DbU::Unit SlicingNode::getToleranceBandW() const
|
|
{
|
|
cerr << "Error(DbU::Unit SlicingNode::getToleranceBandW()): Device and Routing do not have tolerance parameters." << endl;
|
|
return 0;
|
|
}
|
|
|
|
|
|
void SlicingNode::setToleranceBandH( DbU::Unit tolerance )
|
|
{
|
|
cerr << "Error(void SlicingNode::setToleranceBandH( DbU::Unit tolerance )): Device and Routing do not have tolerance parameters." << endl;
|
|
}
|
|
|
|
|
|
void SlicingNode::setToleranceBandW( DbU::Unit tolerance )
|
|
{
|
|
cerr << "Error(void SlicingNode::setToleranceBandW(DbU::Unit tolerance)): Device and Routing do not have tolerance parameters." << endl;
|
|
}
|
|
|
|
|
|
void SlicingNode::recursiveSetToleranceRatioH( DbU::Unit tolerance )
|
|
{
|
|
cerr << "Error(void SlicingNode::recursiveSetToleranceRatioH( DbU::Unit tolerance )): Device and Routing do not have tolerance parameters." << endl;
|
|
}
|
|
|
|
|
|
void SlicingNode::recursiveSetToleranceRatioW( DbU::Unit tolerance )
|
|
{
|
|
cerr << "Error(void SlicingNode::recursiveSetToleranceRatioW( DbU::Unit tolerance )): Device and Routing do not have tolerance parameters." << endl;
|
|
}
|
|
|
|
|
|
void SlicingNode::recursiveSetToleranceBandH( DbU::Unit tolerance )
|
|
{
|
|
cerr << "Error(void SlicingNode::recursiveSetToleranceBandH( DbU::Unit tolerance )): Device and Routing do not have tolerance parameters." << endl;
|
|
}
|
|
|
|
|
|
void SlicingNode::recursiveSetToleranceBandW( DbU::Unit tolerance )
|
|
{
|
|
cerr << "Error(void SlicingNode::recursiveSetToleranceBandW( DbU::Unit tolerance )): Device and Routing do not have tolerance parameters." << endl;
|
|
}
|
|
|
|
|
|
void SlicingNode::_recursiveSetToleranceRatioH( DbU::Unit tolerance )
|
|
{
|
|
cerr << "Error(void SlicingNode::_recursiveSetToleranceRatioH( DbU::Unit tolerance )): Device and Routing do not have tolerance parameters." << endl;
|
|
}
|
|
|
|
|
|
void SlicingNode::_recursiveSetToleranceRatioW( DbU::Unit tolerance )
|
|
{
|
|
cerr << "Error(void SlicingNode::_recursiveSetToleranceRatioW( DbU::Unit tolerance )): Device and Routing do not have tolerance parameters." << endl;
|
|
}
|
|
|
|
|
|
void SlicingNode::_recursiveSetToleranceBandH( DbU::Unit tolerance )
|
|
{
|
|
cerr << "Error(void SlicingNode::_recursiveSetToleranceBandH( DbU::Unit tolerance )): Device and Routing do not have tolerance parameters." << endl;
|
|
}
|
|
|
|
|
|
void SlicingNode::_recursiveSetToleranceBandW( DbU::Unit tolerance )
|
|
{
|
|
cerr << "Error(void SlicingNode::_recursiveSetToleranceBandW( DbU::Unit tolerance )): Device and Routing do not have tolerance parameters." << endl;
|
|
}
|
|
|
|
|
|
void SlicingNode::setTolerances( DbU::Unit trh, DbU::Unit trw, DbU::Unit tbh, DbU::Unit tbw )
|
|
{
|
|
cerr << "Error(void SlicingNode::setTolerances( DbU::Unit trh, DbU::Unit trw, DbU::Unit tbh, DbU::Unit tbw )): Device and Routing do not have tolerance parameters." << endl;
|
|
}
|
|
|
|
|
|
void SlicingNode::recursiveSetTolerances( DbU::Unit trh, DbU::Unit trw, DbU::Unit tbh, DbU::Unit tbw )
|
|
{
|
|
cerr << "Error(void SlicingNode::recursiveSetTolerances( DbU::Unit trh, DbU::Unit trw, DbU::Unit tbh, DbU::Unit tbw )): Device and Routing do not have tolerance parameters." << endl;
|
|
}
|
|
|
|
|
|
void SlicingNode::_recursiveSetTolerances( DbU::Unit trh, DbU::Unit trw, DbU::Unit tbh, DbU::Unit tbw )
|
|
{
|
|
cerr << "Error(void SlicingNode::_recursiveSetTolerances( DbU::Unit trh, DbU::Unit trw, DbU::Unit tbh, DbU::Unit tbw )): Device and Routing do not have tolerance parameters." << endl;
|
|
}
|
|
|
|
|
|
bool SlicingNode::hasEmptyChildrenNodeSets() const
|
|
{
|
|
cerr << "Error(bool SlicingNode::hasEmptyChildrenNodeSets()): Device and routing do not have child." << endl;
|
|
return true;
|
|
}
|
|
|
|
|
|
const vector<SlicingNode*>& SlicingNode::getChildren() const
|
|
{
|
|
cerr << "Error(vector<SlicingNode*> SlicingNode::getChildren()): Device and Routing do not have child." << endl;
|
|
static vector<SlicingNode*> dummyVectorSlicingNode;
|
|
return dummyVectorSlicingNode;
|
|
}
|
|
|
|
|
|
SlicingNode* SlicingNode::getChild( int index ) const
|
|
{
|
|
cerr << "Error(SlicingNode* SlicingNode::getChild(int index)): Device and Routing do not have child." << endl;
|
|
return NULL;
|
|
}
|
|
|
|
|
|
int SlicingNode::getChildIndex( SlicingNode* node ) const
|
|
{
|
|
cerr << "Error(int SlicingNode::getChildIndex( SlicingNode* node )): Device and Routing do not have child." << endl;
|
|
return 0;
|
|
}
|
|
|
|
|
|
size_t SlicingNode::getNbChild() const
|
|
{
|
|
cerr << "Error(int SlicingNode::getNbChild()): Device and Routing do not have child." << endl;
|
|
return 0;
|
|
}
|
|
|
|
|
|
void SlicingNode::createChild( unsigned int type, unsigned int alignment )
|
|
{
|
|
cerr << "Error(void createChild( SlicingType type, Alignment alignment = UnknownAlignment)): Device and Routing do not have child." << endl;
|
|
}
|
|
|
|
|
|
void SlicingNode::createChild( NodeSets* nodeSets
|
|
, unsigned int alignment
|
|
, Instance* instance
|
|
, BoxSet* boxSet
|
|
)
|
|
{
|
|
cerr << "Error(void createChild( NodeSets* nodeSets, Alignment alignment, Instance* instance, BoxSet* boxset )): Device and Routing do not have child." << endl;
|
|
}
|
|
|
|
|
|
void SlicingNode::createChild( int childIndex, int copyIndex, unsigned int tr )
|
|
{
|
|
std::cerr << "Error(createChild( int childIndex, int copyIndex, unsigned int tr )): Device and Routing do not have child." << endl;
|
|
}
|
|
|
|
|
|
void SlicingNode::createRouting( DbU::Unit space )
|
|
{
|
|
std::cerr << "Error(void createChild( DbU::Unit space )): Device and Routing do not have child." << endl;
|
|
}
|
|
|
|
|
|
void SlicingNode::insertNode( SlicingNode* node, int index )
|
|
{
|
|
cerr << "Error(void SlicingNode::insertNode( SlicingNode* node, int index )): Device and Routing do not have child." << endl;
|
|
}
|
|
|
|
|
|
void SlicingNode::push_back( SlicingNode* node, bool reset )
|
|
{
|
|
cerr << "Error(void SlicingNode::push_back( SlicingNode* node, bool reset )): Device and Routing do not have child." << endl;
|
|
}
|
|
|
|
|
|
void SlicingNode::push_front( SlicingNode* node )
|
|
{
|
|
cerr << "Error(void SlicingNode::push_front( SlicingNode* node )): Device and Routing do not have child." << endl;
|
|
}
|
|
|
|
|
|
void SlicingNode::removeNode( SlicingNode* node )
|
|
{
|
|
cerr << "Error(void SlicingNode::removeNode( SlicingNode* node )): Device and Routing do not have child." << endl;
|
|
}
|
|
|
|
|
|
void SlicingNode::removeAllNodes()
|
|
{
|
|
cerr << "Error(void SlicingNode::removeAllNodes()): Device and Routing do not have child." << endl;
|
|
}
|
|
|
|
|
|
list<pair<int,int> > SlicingNode::getSymmetries() const
|
|
{
|
|
cerr << "Error(list<pair<int,int> > SlicingNode::getSymmetries() const) : Device and Routing do not have symmetries." << endl;
|
|
return list<pair<int,int> >();
|
|
}
|
|
|
|
|
|
void SlicingNode::setSymmetries( list<pair<int,int> > sym )
|
|
{
|
|
cerr << "Error(void SlicingNode::setSymmetries( list<pair<int,int> > sym )) : Device and Routing do not have symmetries." << endl;
|
|
}
|
|
|
|
|
|
bool SlicingNode::isSymmetry( int index, std::pair<int,int>& symmetry )
|
|
{
|
|
cerr << "Error(bool SlicingNode::isSymmetry( int index, std::pair<int,int>& symmetry )) : Device and Routing do not have symmetries." << endl;
|
|
return false;
|
|
}
|
|
|
|
|
|
bool SlicingNode::isSymmetry( int index )
|
|
{
|
|
cerr << "Error(bool SlicingNode::isSymmetry( int index )) : Device and Routing do not have symmetries." << endl;
|
|
return false;
|
|
}
|
|
|
|
|
|
void SlicingNode::addSymmetry( int childIndex, int copyIndex, bool reset )
|
|
{
|
|
cerr << "Error(void SlicingNode::addSymmetry( int childIndex, int copyIndex, bool reset )) : Device and Routing do not have symmetries." << endl;
|
|
}
|
|
|
|
|
|
void SlicingNode::removeSymmetry( int index )
|
|
{
|
|
cerr << "Error(void SlicingNode::removeSymmetry( int index )) : Device and Routing do not have symmetries." << endl;
|
|
}
|
|
|
|
|
|
void SlicingNode::normalizeSymmetries()
|
|
{
|
|
cerr << "Error(void SlicingNode::normalizeSymmetries() const) : Device and Routing do not have symmetries." << endl;
|
|
}
|
|
|
|
|
|
void SlicingNode::printChildren() const
|
|
{
|
|
cerr << "Error(void SlicingNode::printChildren() const): Device and Routing do not have child." << endl;
|
|
}
|
|
|
|
|
|
void SlicingNode::printChildrenLine() const
|
|
{
|
|
cerr << "Error(void SlicingNode::printChildrenLine() const): Device and Routing do not have child." << endl;
|
|
}
|
|
|
|
|
|
double SlicingNode::getOccupationArea() const
|
|
{
|
|
cerr << "Error(double SlicingNode::getOccupationArea() const) : Occupied Area is not relevant for Routing and Devices." << endl;
|
|
return 100;
|
|
}
|
|
|
|
|
|
void SlicingNode::setNFing( int nfing )
|
|
{
|
|
cerr << "Error(void SlicingNode::setNFing( int nfing )): Only DlicingNode have NFing parameter." << endl;
|
|
}
|
|
|
|
|
|
int SlicingNode::getNFing() const
|
|
{
|
|
cerr << "Error(int SlicingNode::getNFing() const): Only DSlicingNode have NFing parameter." << endl;
|
|
return 0;
|
|
}
|
|
|
|
|
|
double SlicingNode::getStartParameter() const
|
|
{
|
|
cerr << "Error(int SlicingNode::getStartParameter() const): Only DSlicingNode have Start parameter." << endl;
|
|
return 0;
|
|
}
|
|
|
|
|
|
double SlicingNode::getStepParameter() const
|
|
{
|
|
cerr << "Error(int SlicingNode::getStepParameter() const): Only DSlicingNode have Step parameter." << endl;
|
|
return 0;
|
|
}
|
|
|
|
|
|
double SlicingNode::getCountParameter() const
|
|
{
|
|
cerr << "Error(int SlicingNode::getCountParameter() const): Only DSlicingNode have Count parameter." << endl;
|
|
return 0;
|
|
}
|
|
|
|
|
|
Instance* SlicingNode::getInstance() const
|
|
{
|
|
cerr << "Error(Instance* getInstance() const): Only DSlicingNode have an Instance." << endl;
|
|
return NULL;
|
|
}
|
|
|
|
|
|
void SlicingNode::setInstance( Instance* instance )
|
|
{
|
|
cerr << "Error(Instance* setInstance( Instance* instance ) const): Only DSlicingNode have an Instance." << endl;
|
|
}
|
|
|
|
|
|
void SlicingNode::setCell( Cell* cell )
|
|
{
|
|
if (_parent == NULL){
|
|
if (checkCellInstances(cell)){
|
|
_cell = cell;
|
|
AnalogCellExtension::setSlicingTree( cell, this );
|
|
}
|
|
} else {
|
|
cerr << "Error(void SlicingNode::setCell( Cell* cell )): SlicingTree's root only can set the Slicing tree's cell." << endl;
|
|
}
|
|
}
|
|
|
|
|
|
void SlicingNode::setKatana( Katana::KatanaEngine* katana )
|
|
{
|
|
_katana = katana;
|
|
}
|
|
|
|
|
|
bool SlicingNode::checkCellInstances( Cell* cell )
|
|
{
|
|
return true;
|
|
}
|
|
|
|
|
|
SlicingNode* SlicingNode::findInstance( Instance* instance )
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
|
|
SlicingNode* SlicingNode::findSlicingNode( Anabatic::GCell* gcell )
|
|
{
|
|
return NULL;
|
|
}
|
|
|
|
|
|
|
|
void SlicingNode::createSlicingRouting()
|
|
{
|
|
cerr << "Error(void SlicingNode::createSlicingRouting()): Used for HVSlicingNode only." << endl;
|
|
}
|
|
|
|
|
|
void SlicingNode::resetSlicingRouting()
|
|
{
|
|
cerr << "Error(void SlicingNode::resetSlicingRouting()): Used for HVSlicingNode only." << endl;
|
|
}
|
|
|
|
|
|
void SlicingNode::destroySlicingRouting()
|
|
{
|
|
cerr << "Error(void SlicingNode::destroySlicingRouting()): Used for HVSlicingNode only." << endl;
|
|
}
|
|
|
|
|
|
int SlicingNode::getRoutingIndex ( SlicingNode* node ) const
|
|
{
|
|
cerr << "Error(int SlicingNode::getRoutingIndex ( SlicingNode* node ) const ): Routing index is used for Horizontal/Vertical nodes." << endl;
|
|
return 0;
|
|
}
|
|
|
|
|
|
SlicingNode* SlicingNode::getSlicingRouting ( int index ) const
|
|
{
|
|
cerr << "Error(SlicingNode* SlicingNode::getSlicingRouting ( int index ) const): Used for Horizontal/Vertical Slicing node only." << endl;
|
|
return NULL;
|
|
}
|
|
|
|
|
|
SlicingNode* SlicingNode::findHorizontalParent () const
|
|
{
|
|
if (_parent) {
|
|
SlicingNode* node = _parent;
|
|
while(node){
|
|
if (node->getType() == HorizontalSNode){ break; }
|
|
else { node = node->getParent(); }
|
|
}
|
|
return node;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
SlicingNode* SlicingNode::findVerticalParent () const
|
|
{
|
|
if (_parent) {
|
|
SlicingNode* node = _parent;
|
|
while(node){
|
|
if (node->getType() == VerticalSNode){ break; }
|
|
else { node = node->getParent(); }
|
|
}
|
|
return node;
|
|
} else {
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
|
|
int SlicingNode::getIndexInHorizontalParent() const
|
|
{
|
|
if (_parent) {
|
|
if (this->getParent()->getType() == HorizontalSNode){
|
|
int i = 0;
|
|
vector<SlicingNode*>::const_iterator it = this->getParent()->getChildren().begin();
|
|
while (it != this->getParent()->getChildren().end()){
|
|
if ( ((*it)->getType() == this->getType() )
|
|
&& ((*it)->getHeight() == this->getHeight())
|
|
&& ((*it)->getWidth () == this->getWidth ())
|
|
&& ((*it)->getX() == this->getX() )
|
|
&& ((*it)->getY() == this->getY() )
|
|
)
|
|
{ it = this->getParent()->getChildren().end(); }
|
|
else {
|
|
i++;
|
|
it++;
|
|
}
|
|
}
|
|
return i;
|
|
} else {
|
|
bool found = false;
|
|
SlicingNode* node = this->getParent();
|
|
|
|
while((node->getParent() != NULL) && (found == false)){
|
|
if (node->getParent()->getType() == HorizontalSNode){
|
|
found = true;
|
|
} else {
|
|
node = node->getParent();
|
|
}
|
|
}
|
|
|
|
if (found){
|
|
return node->getParent()->getChildIndex(node);
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
int SlicingNode::getIndexInVerticalParent() const
|
|
{
|
|
if (_parent) {
|
|
if (this->getParent()->getType() == VerticalSNode){
|
|
int i = 0;
|
|
vector<SlicingNode*>::const_iterator it = this->getParent()->getChildren().begin();
|
|
while (it != this->getParent()->getChildren().end()){
|
|
if ( ((*it)->getType() == this->getType() )
|
|
&& ((*it)->getHeight() == this->getHeight())
|
|
&& ((*it)->getWidth () == this->getWidth ())
|
|
&& ((*it)->getX() == this->getX() )
|
|
&& ((*it)->getY() == this->getY() )
|
|
)
|
|
{ it = this->getParent()->getChildren().end(); }
|
|
else {
|
|
i++;
|
|
it++;
|
|
}
|
|
}
|
|
return i;
|
|
} else {
|
|
bool found = false;
|
|
SlicingNode* node = this->getParent();
|
|
|
|
while((node->getParent() != NULL) && (found == false)){
|
|
if (node->getParent()->getType() == VerticalSNode){
|
|
found = true;
|
|
} else {
|
|
node = node->getParent();
|
|
}
|
|
}
|
|
|
|
if (found){
|
|
return node->getParent()->getChildIndex(node);
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
} else {
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
void SlicingNode::createRoutingPads ()
|
|
{
|
|
cdebug_log(536,1) << "SlicingNode::createRoutingPads()" << endl;
|
|
|
|
if (not _cell) {
|
|
cdebug_tabw(536,-1);
|
|
return;
|
|
}
|
|
|
|
//_cell->flattenNets( Cell::Flags::StayOnPlugs );
|
|
_cell->flattenNets();
|
|
|
|
#if THIS_IS_DISABLED
|
|
for ( Net* net : _cell->getNets() ) {
|
|
cdebug_log(536,0) << "Net: " << net << endl;
|
|
|
|
if ( net->getPlugs().getSize() > 1 ) {
|
|
cdebug_log(530,1) << "Not a rail supply and has " << net->getPlugs().getSize() << " plugs" << endl;
|
|
|
|
vector<Plug*> plugs;
|
|
for ( Plug* plug : net->getPlugs() ) {
|
|
cdebug_log(530,0) << "| " << plug << endl;
|
|
|
|
if (dynamic_cast<Device*>(plug->getMasterNet()->getCell())){
|
|
cdebug_log(530,0) << "| Device: " << plug << endl;
|
|
plugs.push_back( plug );
|
|
} else if (isRailSegments(plug)){
|
|
cdebug_log(530,0) << "| PR: " << plug << endl;
|
|
plugs.push_back( plug );
|
|
} else {
|
|
if (not plug->getNet()->isSupply())
|
|
plugs.push_back( plug );
|
|
}
|
|
}
|
|
|
|
for ( Plug* plug : plugs ) {
|
|
cdebug_log(536,0) << "Building RoutingPad for " << plug << endl;
|
|
|
|
RoutingPad* rp = RoutingPad::create( net, Occurrence(plug) );
|
|
cdebug_log(536,0) << "+ " << rp << ", instance: " << plug->getInstance()->getTransformation() << endl;
|
|
cdebug_log(536,0) << "+ instance ab: " << plug->getInstance()->getMasterCell()->getAbutmentBox() << endl;
|
|
|
|
// Select the Component with the highest layer.
|
|
Net* masterNet = static_cast<Plug*>( rp->getOccurrence().getEntity() )->getMasterNet();
|
|
Horizontal* hbest = NULL;
|
|
Vertical* vbest = NULL;
|
|
|
|
for ( Component* c : masterNet->getComponents() ) {
|
|
//cdebug_log(530,0) << "| " << c << endl;
|
|
|
|
Horizontal* h = dynamic_cast<Horizontal*>(c);
|
|
Vertical* v = dynamic_cast<Vertical*>(c);
|
|
|
|
if (h) {
|
|
if (not hbest) hbest = h;
|
|
else {
|
|
if (h->getLayer()->above(hbest->getLayer())){
|
|
hbest = h;
|
|
} else if (h->getLayer() == hbest->getLayer()){
|
|
if ( hbest->getBoundingBox().getWidth() * hbest->getBoundingBox().getHeight()
|
|
< h->getBoundingBox().getWidth() * h->getBoundingBox().getHeight()
|
|
) {
|
|
hbest = h;
|
|
}
|
|
}
|
|
}
|
|
} else if (v) {
|
|
if (not vbest) vbest = v;
|
|
else {
|
|
if (v->getLayer()->above(vbest->getLayer())){
|
|
vbest = v;
|
|
} else if (v->getLayer() == vbest->getLayer()){
|
|
if ( vbest->getBoundingBox().getWidth() * vbest->getBoundingBox().getHeight()
|
|
< v->getBoundingBox().getWidth() * v->getBoundingBox().getHeight()
|
|
) {
|
|
vbest = v;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (hbest) {
|
|
cdebug_log(536,0) << "* " << hbest << endl;
|
|
rp->setExternalComponent(hbest);
|
|
} else if (vbest) {
|
|
cdebug_log(536,0) << "* " << vbest << endl;
|
|
rp->setExternalComponent(vbest);
|
|
}
|
|
}
|
|
|
|
RoutingPad* previousRp = NULL;
|
|
for ( RoutingPad* rp : net->getRoutingPads() ) {
|
|
if ( previousRp
|
|
and ( not rp ->getBodyHook()->isAttached()
|
|
or not previousRp->getBodyHook()->isAttached()) ) {
|
|
rp->getBodyHook()->attach( previousRp->getBodyHook() );
|
|
}
|
|
previousRp = rp;
|
|
}
|
|
cdebug_tabw(530,-1);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
cdebug_tabw(536,-1);
|
|
}
|
|
|
|
|
|
void SlicingNode::clearRoutingPads()
|
|
{
|
|
vector<DeepNet*> nets;
|
|
|
|
for ( Net* net : _cell->getNets() ) {
|
|
DeepNet* n = dynamic_cast<DeepNet*>(net);
|
|
if (n) nets.push_back(n);
|
|
}
|
|
for ( DeepNet* net : nets ){
|
|
net->destroy();
|
|
}
|
|
for ( Net* net : _cell->getNets() ) {
|
|
vector<RoutingPad*> rps;
|
|
for ( RoutingPad* rp : net->getRoutingPads() ) rps.push_back( rp );
|
|
for ( RoutingPad* rp : rps ) rp->destroy();
|
|
}
|
|
}
|
|
|
|
|
|
void SlicingNode::restrictDevices()
|
|
{
|
|
if (_gcell){
|
|
Anabatic::Vertex* vertex = _gcell->getObserver< Anabatic::Vertex>( Anabatic::GCell::Observable::Vertex);
|
|
vertex->clearRestriction();
|
|
}
|
|
}
|
|
|
|
|
|
void SlicingNode::setVertexRestriction ( Net* net, Katana::KatanaEngine* kanata ){}
|
|
|
|
|
|
void SlicingNode::estimateChannelsSize ()
|
|
{
|
|
setRoutingEstimated (RoutingEstimated);
|
|
}
|
|
|
|
|
|
void SlicingNode::expandRoutingChannel ()
|
|
{
|
|
setRoutingEstimated (RoutingEstimated);
|
|
}
|
|
|
|
|
|
void SlicingNode::_expandRoutingChannel ()
|
|
{
|
|
setRoutingEstimated (RoutingEstimated);
|
|
}
|
|
|
|
|
|
void SlicingNode::expandRoutingChannel ( DbU::Unit height, DbU::Unit width )
|
|
{
|
|
setRoutingEstimated (RoutingEstimated);
|
|
}
|
|
|
|
|
|
void SlicingNode::clearGlobalRouting()
|
|
{
|
|
vector<Component*> c = vector<Component*>();
|
|
c.clear();
|
|
vector<Component*> s = vector<Component*>();
|
|
|
|
int hcpt = 0;
|
|
int vcpt = 0;
|
|
int ccpt = 0;
|
|
|
|
for(Net* net: _cell->getNets()){
|
|
for(Component* component: net->getComponents()){
|
|
if (SlicingNode::isRailSegments(dynamic_cast<Segment*> (component)) == false){
|
|
Hurricane::Horizontal* h = dynamic_cast<Hurricane::Horizontal*>(component);
|
|
Hurricane::Vertical* v = dynamic_cast<Hurricane::Vertical*> (component);
|
|
Hurricane::Contact* cc = dynamic_cast<Hurricane::Contact*> (component);
|
|
|
|
if (h) s.push_back(component);
|
|
if (v) s.push_back(component);
|
|
if (cc) c.push_back(component);
|
|
|
|
if (h) hcpt++;
|
|
if (v) vcpt++;
|
|
if (cc) ccpt++;
|
|
}
|
|
}
|
|
}
|
|
for (vector<Component*>::iterator it = s.begin(); it != s.end(); it++){
|
|
(*it)->destroy();
|
|
}
|
|
for (vector<Component*>::iterator it = c.begin(); it != c.end(); it++){
|
|
(*it)->destroy();
|
|
}
|
|
this->clearGCells();
|
|
}
|
|
|
|
|
|
void SlicingNode::clearGCells()
|
|
{
|
|
_gcell = NULL;
|
|
}
|
|
|
|
|
|
void SlicingNode::updateGCellPosition()
|
|
{
|
|
if (_gcell) {
|
|
_gcell->setSouthWestCorner( getX(), getY() );
|
|
}
|
|
cdebug_log(535,0) << "SlicingNode::updateGCellPosition(): " << _gcell << endl;
|
|
}
|
|
|
|
|
|
void SlicingNode::updateGContacts()
|
|
{
|
|
if (_gcell) {
|
|
_gcell->updateGContacts( Anabatic::Flags::Vertical|Anabatic::Flags::Horizontal );
|
|
}
|
|
cdebug_log(535,0) << "SlicingNode::updateGContacts(): " << _gcell << endl;
|
|
}
|
|
|
|
|
|
/*<<<<<<< HEAD*/
|
|
void SlicingNode::updateMatrixGCellPosition()
|
|
{
|
|
cerr << "Error(void SlicingNode::updateMatrixGCellPosition()): Only used by DSlicingNode" << endl;
|
|
}
|
|
|
|
void SlicingNode::updateMatrixGContacts()
|
|
{
|
|
cerr << "Error(void SlicingNode::updateMatrixGContacts()): Only used by DSlicingNode" << endl;
|
|
}
|
|
|
|
/*void SlicingNode::updateMatrixGContactsPosition()
|
|
{
|
|
cerr << "Error(void SlicingNode::updateMatrixGContactsPosition()): Only used by DSlicingNode" << endl;
|
|
}
|
|
|
|
|
|
void SlicingNode::updateGContactsPosition()
|
|
{
|
|
if (_gcell)_gcell->updateContactsPosition();
|
|
}
|
|
|
|
|
|
=======
|
|
>>>>>>> ad94201dbefd0e6f98b1e28a032a3b2a6d57390d*/
|
|
int SlicingNode::getNbDevices()
|
|
{
|
|
return 1;
|
|
}
|
|
|
|
|
|
bool SlicingNode::containAxis( DbU::Unit axis, unsigned int symmetryType )
|
|
{
|
|
if (symmetryType == HSymmetry){
|
|
return ( (axis > getX()) && (axis < getX()+getWidth()));
|
|
} else if (symmetryType == VSymmetry){
|
|
return ( (axis > getY()) && (axis < getY()+getHeight()));
|
|
} else return false;
|
|
}
|
|
|
|
|
|
bool SlicingNode::checkSymmetryNet ( unsigned int type, Net* net1, Net* net2 ) const
|
|
{
|
|
cerr << "Error(bool checkSymmetryNet ( unsigned int type, Net* net1, Net* net2 ) const): Only used by HVSlicingNode" << endl;
|
|
return false;
|
|
}
|
|
|
|
|
|
void SlicingNode::addSymmetryNet ( unsigned int type, Net* net1, Net* net2 )
|
|
{
|
|
cerr << "Error(void addSymmetryNet ( unsigned int type, Net* net1, Net* net2 )): Only used by HVSlicingNode" << endl;
|
|
}
|
|
|
|
|
|
void SlicingNode::updateNetConstraints ()
|
|
{
|
|
cerr << "Error(void SlicingNode::updateNetConstraints ()): Only used by HVSlicingNode" << endl;
|
|
}
|
|
|
|
|
|
|
|
void SlicingNode::updateSymNetAxis()
|
|
{
|
|
cerr << "Error(void SlicingNode::updateSymNetAxis ()): Only used by HVSlicingNode" << endl;
|
|
}
|
|
|
|
void SlicingNode::setRoutingGauge ( CRL::RoutingGauge* rg )
|
|
{
|
|
_rg = rg;
|
|
}
|
|
|
|
|
|
void SlicingNode::addRailSegments( Hurricane::Segment* s )
|
|
{
|
|
_railSegments.push_back(s);
|
|
}
|
|
|
|
|
|
bool SlicingNode::isRailSegments ( Hurricane::Segment* s )
|
|
{
|
|
bool is = false;
|
|
for (Segment* seg : _railSegments){
|
|
if ( s == seg ) {
|
|
is = true;
|
|
break;
|
|
}
|
|
}
|
|
return is;
|
|
}
|
|
|
|
bool SlicingNode::isRailSegments ( Hurricane::Plug* p )
|
|
{
|
|
Instance* i = p->getInstance();
|
|
Net* net = NULL;
|
|
int t = 0;
|
|
for (Net* n : i->getMasterCell()->getNets()) {
|
|
net = n;
|
|
t++;
|
|
}
|
|
if (t != 1) return false;
|
|
Component* component = NULL;
|
|
t = 0;
|
|
for (Component* c : net->getComponents()){
|
|
component = c;
|
|
t++;
|
|
}
|
|
if (t != 1) return false;
|
|
|
|
Horizontal* h = dynamic_cast<Horizontal*>(component);
|
|
Vertical* v = dynamic_cast<Vertical*> (component);
|
|
if (h) return isRailSegments(h);
|
|
else if (v) return isRailSegments(v);
|
|
else return false;
|
|
}
|
|
|
|
|
|
void SlicingNode::flattenDigitalNets ()
|
|
{
|
|
cerr << "Error(void SlicingNode::flattenDigitalNets ()): Only used by HVSlicingNode" << endl;
|
|
}
|
|
|
|
void SlicingNode::updateWireOccupation ( Anabatic::VertexSet )
|
|
{
|
|
cerr << "Error(void SlicingNode::updateWireOccupation ( Anabatic::VertexSet )): Only used by HVSlicingNode" << endl;
|
|
}
|
|
|
|
void SlicingNode::addWireOccupation ( DbU::Unit min, DbU::Unit max )
|
|
{
|
|
cerr << "Error(void SlicingNode::addWireOccupation ( DbU::Unit min, DbU::Unit max )): Only used by HVSlicingNode and RHVSlicingNode" << endl;
|
|
}
|
|
|
|
void SlicingNode::resetWireOccupation ()
|
|
{
|
|
cerr << "Error(void SlicingNode::resetWireOccupation()): Only used by HVSlicingNode and RHVSlicingNode" << endl;
|
|
}
|
|
|
|
|
|
int SlicingNode::getMaxWireOccupation ()
|
|
{
|
|
cerr << "Error(int SlicingNode::getMaxWireOccupation()): Only used by HVSlicingNode and RHVSlicingNode" << endl;
|
|
return 0;
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------------------------//
|
|
// Class : HVSlicingNode
|
|
// -----------------------------------------------------------------------------------------------//
|
|
|
|
|
|
HVSlicingNode::HVSlicingNode( unsigned int type, unsigned int alignment ): SlicingNode( type, NodeSets::create(), alignment, NULL )
|
|
{
|
|
_toleranceRatioH = 0;
|
|
_toleranceRatioW = 0;
|
|
_toleranceBandH = 0;
|
|
_toleranceBandW = 0;
|
|
_children = vector<SlicingNode*>();
|
|
_symmetries = list<pair <int,int> >();
|
|
_slicingRouting = vector<RHVSlicingNode*>();
|
|
_netsymmetries = vector<tuple<unsigned int, Net*, Net*> >();
|
|
}
|
|
|
|
|
|
HVSlicingNode::~HVSlicingNode(){}
|
|
|
|
|
|
|
|
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 (vector<SlicingNode*>::iterator it = _children.begin(); it != _children.end(); it++){
|
|
|
|
if ( (!(*it)->isDevice()) && (!(*it)->isRouting()) )
|
|
{ (*it)->recursiveSetToleranceRatioH(tolerance); }
|
|
}
|
|
_toleranceRatioH = tolerance;
|
|
}
|
|
|
|
|
|
void HVSlicingNode::_recursiveSetToleranceRatioW( DbU::Unit tolerance )
|
|
{
|
|
for (vector<SlicingNode*>::iterator it = _children.begin(); it != _children.end(); it++){
|
|
|
|
if ( (!(*it)->isDevice()) && (!(*it)->isRouting()) )
|
|
{ (*it)->recursiveSetToleranceRatioW(tolerance); }
|
|
}
|
|
_toleranceRatioW = tolerance;
|
|
}
|
|
|
|
|
|
void HVSlicingNode::_recursiveSetToleranceBandH( DbU::Unit tolerance )
|
|
{
|
|
for (vector<SlicingNode*>::iterator it = _children.begin(); it != _children.end(); it++){
|
|
|
|
if ( (!(*it)->isDevice()) && (!(*it)->isRouting()) )
|
|
{ (*it)->recursiveSetToleranceBandH(tolerance); }
|
|
}
|
|
_toleranceBandH = tolerance;
|
|
}
|
|
|
|
|
|
void HVSlicingNode::_recursiveSetToleranceBandW( DbU::Unit tolerance )
|
|
{
|
|
for (vector<SlicingNode*>::iterator it = _children.begin(); it != _children.end(); it++){
|
|
|
|
if ( (!(*it)->isDevice()) && (!(*it)->isRouting()) )
|
|
{ (*it)->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
|
|
{
|
|
bool flag = false;
|
|
for (vector<SlicingNode*>::const_iterator it = _children.begin(); it != _children.end(); it++){
|
|
NodeSets* node = (*it)->getNodeSets();
|
|
if ( (node->empty() != true) && (!(*it)->isRouting()) )
|
|
{ if (node->empty() == true) {flag = true;} }
|
|
}
|
|
return flag;
|
|
}
|
|
|
|
|
|
int HVSlicingNode::getChildIndex( SlicingNode* node ) const
|
|
{
|
|
int i = 0;
|
|
vector<SlicingNode*>::const_iterator it = _children.begin();
|
|
while (it != _children.end()){
|
|
if ( ((*it)->getType() == node->getType() )
|
|
&& ((*it)->getHeight() == node->getHeight())
|
|
&& ((*it)->getWidth () == node->getWidth ())
|
|
&& ((*it)->getX() == node->getX() )
|
|
&& ((*it)->getY() == node->getY() )
|
|
)
|
|
{ it = _children.end(); }
|
|
else {
|
|
i++;
|
|
it++;
|
|
}
|
|
}
|
|
return i;
|
|
}
|
|
|
|
|
|
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 << " Error(void HVSlicingNode::createChild(SlicingType type, Alignment 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);
|
|
this->push_back(node);
|
|
resetSlicingTree();
|
|
}
|
|
|
|
|
|
void HVSlicingNode::createChild( int childIndex, int copyIndex, unsigned int tr )
|
|
{
|
|
if (childIndex != copyIndex){
|
|
|
|
SlicingNode* node = this->getChild(childIndex)->clone(tr);
|
|
this->insertNode( node, copyIndex );
|
|
_symmetries.push_back( pair<int,int>(min(childIndex, copyIndex), max(childIndex, copyIndex)) );
|
|
resetSlicingTree();
|
|
normalizeSymmetries();
|
|
}
|
|
else { cerr << "Error(void HVSlicingNode::createChild( int childIndex, int copyIndex, unsigned int tr )): Indexes cannot be the same." << endl; }
|
|
}
|
|
|
|
|
|
void HVSlicingNode::insertNode( SlicingNode* node, int index )
|
|
{
|
|
vector<SlicingNode*>::iterator it = _children.begin();
|
|
for (int 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 )
|
|
{
|
|
int index = 0;
|
|
bool found = false;
|
|
vector<SlicingNode*>::iterator it = _children.begin();
|
|
//(*it)->printLine();
|
|
while( it != _children.end() ){
|
|
if ((*it) == node) {
|
|
_children.erase(it);
|
|
found = true;
|
|
it = _children.end();
|
|
}
|
|
else {
|
|
it++;
|
|
index++;
|
|
}
|
|
}
|
|
|
|
if (found == true){
|
|
removeSymmetry(index);
|
|
resetSlicingTree();
|
|
node->removeParent();
|
|
node->setX(0);
|
|
node->setY(0);
|
|
node->setPlaced(false);
|
|
} /*else {
|
|
cerr << "Didn't found" << endl;
|
|
}*/
|
|
}
|
|
|
|
|
|
bool HVSlicingNode::isSymmetry( int index, pair<int,int>& symmetry )
|
|
{
|
|
bool symmetryFound = false;
|
|
|
|
if (_symmetries.empty() != true){
|
|
for (list<pair<int,int> >::const_iterator it2 = _symmetries.begin(); it2 != _symmetries.end(); it2++){
|
|
|
|
if ((*it2).second == index){
|
|
symmetry = pair<int,int>((*it2).first,(*it2).second);
|
|
symmetryFound = true;
|
|
}
|
|
}
|
|
}
|
|
return symmetryFound;
|
|
}
|
|
|
|
|
|
bool HVSlicingNode::isSymmetry( int index )
|
|
{
|
|
bool symmetryFound = false;
|
|
|
|
if (_symmetries.empty() != true){
|
|
for (list<pair<int,int> >::const_iterator it2 = _symmetries.begin(); it2 != _symmetries.end(); it2++){
|
|
|
|
if ((*it2).second == index){
|
|
symmetryFound = true;
|
|
}
|
|
}
|
|
}
|
|
return symmetryFound;
|
|
}
|
|
|
|
|
|
void HVSlicingNode::addSymmetry( int childIndex, int copyIndex, bool reset )
|
|
{
|
|
if (childIndex >= (int)getChildren().size()) {
|
|
cerr << Warning( "HVSlicingNode::addSymmetry(int,int)): Child index out of range:%d (> %d), symmetry is ignored."
|
|
, childIndex, getChildren().size() ) << endl;
|
|
return;
|
|
}
|
|
|
|
if (copyIndex >= (int)getChildren().size()) {
|
|
cerr << Warning( "HVSlicingNode::addSymmetry(int,int)): Copy index out of range:%d (> %d), symmetry is ignored."
|
|
, copyIndex, getChildren().size() ) << endl;
|
|
return;
|
|
}
|
|
|
|
if (childIndex == copyIndex) {
|
|
cerr << Warning( "HVSlicingNode::addSymmetry(int,int)): Indexes cannot be identical (%d), symmetry is ignored."
|
|
, childIndex ) << endl;
|
|
return;
|
|
}
|
|
unsigned int symmetryType = 0;
|
|
if (this->getType() == HorizontalSNode) symmetryType = HSymmetry;
|
|
if (this->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."
|
|
, childIndex, copyIndex ) << endl;
|
|
return;
|
|
}
|
|
|
|
_symmetries.push_back( pair<int,int>(min(childIndex, copyIndex), max(childIndex, copyIndex)) );
|
|
if (reset) resetSlicingTree();
|
|
unsigned int flag = 0;
|
|
if (this->getType() == HorizontalSNode) flag = HSymmetry;
|
|
if (this->getType() == VerticalSNode ) flag = VSymmetry;
|
|
getChild(copyIndex)->setSymmetryFlag(flag);
|
|
|
|
getChild(copyIndex)->setMaster(getChild(childIndex));
|
|
normalizeSymmetries();
|
|
}
|
|
|
|
|
|
void HVSlicingNode::removeSymmetry( int index )
|
|
{
|
|
bool first = true;
|
|
int erasedFirst = 0;
|
|
int erasedSecond = 0;
|
|
bool isReference = true;
|
|
|
|
for ( list<pair<int,int> >::iterator it = _symmetries.begin(); it != _symmetries.end(); it++ ){
|
|
if ((((*it).first == index) || ((*it).second == index) ) && (first == true)){
|
|
list<pair<int,int> >::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 ( (first == false) && (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 >];
|
|
// -----------------------------------------------------------------------------------------------//
|
|
|
|
list<pair<int,int> > adjustedSymmetries = list<pair<int,int> >();
|
|
for (list<pair<int,int> >::const_iterator it = _symmetries.begin(); it != _symmetries.end(); it++){
|
|
|
|
if ((*it).first > (*it).second ){ adjustedSymmetries.push_back(pair<int,int >((*it).second,(*it).first)); }
|
|
else { adjustedSymmetries.push_back(pair<int,int >((*it).first,(*it).second)); }
|
|
}
|
|
adjustedSymmetries.sort();
|
|
|
|
bool next = false;
|
|
list<pair<int,int> >::iterator it2 = adjustedSymmetries.begin();
|
|
it2++;
|
|
|
|
for (list<pair<int,int> >::iterator it = adjustedSymmetries.begin(); it != adjustedSymmetries.end(); it++){
|
|
it2 = it;
|
|
it2++;
|
|
|
|
while(next != true){
|
|
if ( (*it).second == (*it2).first ){ (*it2).first = (*it).first; }
|
|
if ( (*it).second < (*it2).first ){ next = true; }
|
|
it2++;
|
|
if ( it2 == adjustedSymmetries.end() ) { next = true; }
|
|
}
|
|
next = false;
|
|
}
|
|
_symmetries = adjustedSymmetries;
|
|
}
|
|
|
|
|
|
void HVSlicingNode::_resetSlicingTree()
|
|
{
|
|
_x = 0;
|
|
_y = 0;
|
|
setPlaced(false);
|
|
|
|
if (!this->isPreset()){
|
|
_boxSet = NULL;
|
|
setSet(false);
|
|
|
|
for (vector<SlicingNode*>::const_iterator it = _children.begin(); it != _children.end(); it++){
|
|
(*it)->_resetSlicingTree();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void HVSlicingNode::print() const
|
|
{
|
|
SlicingNode::print();
|
|
if (_symmetries.empty() == false){
|
|
cerr << "Symmetries: " << endl;
|
|
for (list<pair<int,int> >::const_iterator it = _symmetries.begin(); it != _symmetries.end(); it++)
|
|
{ cerr << "Children: " << (*it).first << " and " << (*it).second << endl; }
|
|
cerr << endl;
|
|
} else {
|
|
cerr << "Symmetries: None" << endl;
|
|
}
|
|
if (_slicingRouting.empty() == false){
|
|
cerr<< "Slicing Routing: " << endl;
|
|
int index = 0;
|
|
for (vector<RHVSlicingNode*>::const_iterator it = _slicingRouting.begin(); it != _slicingRouting.end(); it++){
|
|
cerr << "---------------- " << setprecision(4) << index << " -----------------" << endl;
|
|
cerr << "Print - Slicing Routing: ";
|
|
cerr << "X: " << DbU::getPhysical((*it)->getX(), DbU::Micro);
|
|
cerr << ", Y: " << DbU::getPhysical((*it)->getY(), DbU::Micro);
|
|
cerr << ", \t height: " << DbU::getPhysical((*it)->getHeight(), DbU::Micro);
|
|
cerr << ", width: " << DbU::getPhysical((*it)->getWidth(), DbU::Micro) << endl;
|
|
cerr << "GCell: " << (*it)->getGCell() << endl;
|
|
if((*it)->getGCell()){
|
|
cerr << "GCell : " << (*it)->getGCell() << endl;
|
|
|
|
cerr << "Edges : " << endl;
|
|
vector<Anabatic::Edge*> ne = (*it)->getGCell()->getNorthEdges();
|
|
vector<Anabatic::Edge*> se = (*it)->getGCell()->getSouthEdges();
|
|
vector<Anabatic::Edge*> ee = (*it)->getGCell()->getEastEdges();
|
|
vector<Anabatic::Edge*> we = (*it)->getGCell()->getWestEdges();
|
|
|
|
cerr << "--- North : " << ne.empty() << endl;
|
|
for (vector<Anabatic::Edge*>::const_iterator itn = ne.begin(); itn != ne.end(); itn++){
|
|
cerr << (*itn)->getOpposite((*it)->getGCell()) << endl;
|
|
}
|
|
cerr << "--- South : " << se.empty()<< endl;
|
|
for (vector<Anabatic::Edge*>::const_iterator its = se.begin(); its != se.end(); its++){
|
|
cerr << (*its)->getOpposite((*it)->getGCell()) << endl;
|
|
}
|
|
cerr << "--- East : " << ee.empty()<< endl;
|
|
for (vector<Anabatic::Edge*>::const_iterator ite = ee.begin(); ite != ee.end(); ite++){
|
|
cerr << (*ite)->getOpposite((*it)->getGCell()) << endl;
|
|
}
|
|
cerr << "--- West : "<< we.empty() << endl;
|
|
for (vector<Anabatic::Edge*>::const_iterator itw = we.begin(); itw != we.end(); itw++){
|
|
cerr << (*itw)->getOpposite((*it)->getGCell()) << endl;
|
|
}
|
|
}
|
|
cerr << "------------------------------------" << endl;
|
|
index++;
|
|
}
|
|
} else {
|
|
cerr<< "Slicing Routing: empty" << endl;
|
|
}
|
|
cerr << endl;
|
|
}
|
|
|
|
|
|
void HVSlicingNode::printChildren() const
|
|
{
|
|
int count = 0;
|
|
for (vector<SlicingNode*>::const_iterator it = _children.begin(); it != _children.end(); it++){
|
|
if ( ((*it)->isDevice()) || ((*it)->isRouting()) ){
|
|
cerr << "-- Children: " << count << "/" << _children.size()-1 << " --" << endl;
|
|
(*it)->print();
|
|
}
|
|
else {
|
|
cerr << "-- Children: " << count << "/" << _children.size()-1 << " --" << endl;
|
|
(*it)->print();
|
|
(*it)->printChildren();
|
|
}
|
|
count++;
|
|
}
|
|
}
|
|
|
|
|
|
void HVSlicingNode::printLine() const
|
|
{
|
|
SlicingNode::printLine();
|
|
|
|
if (_symmetries.empty() == false){
|
|
cerr << "Symmetries: " << endl;
|
|
for (list<pair<int,int> >::const_iterator it = _symmetries.begin(); it != _symmetries.end(); it++)
|
|
{ cerr << "Children: " << (*it).first << " and " << (*it).second << endl; }
|
|
cerr << endl;
|
|
}
|
|
|
|
/*int index = 0;
|
|
cerr << "Print - Slicing Routing: " << endl;
|
|
for (vector<RHVSlicingNode*>::const_iterator it = _slicingRouting.begin(); it != _slicingRouting.end(); it++){
|
|
cerr << "Index: " << index;
|
|
cerr << ", X: " << DbU::getPhysical((*it)->getX(), DbU::Micro);
|
|
cerr << ", Y: " << DbU::getPhysical((*it)->getY(), DbU::Micro);
|
|
cerr << ", \t height: " << DbU::getPhysical((*it)->getHeight(), DbU::Micro);
|
|
cerr << ", width: " << DbU::getPhysical((*it)->getWidth(), DbU::Micro);
|
|
if ((*it)->getMaster()){
|
|
cerr << ", MASTER: ";
|
|
(*it)->getMaster()->printLine();
|
|
} else {
|
|
cerr << endl;
|
|
}
|
|
index++;
|
|
}*/
|
|
}
|
|
|
|
|
|
void HVSlicingNode::printChildrenLine() const
|
|
{
|
|
int count = 0;
|
|
for (vector<SlicingNode*>::const_iterator it = _children.begin(); it != _children.end(); it++){
|
|
if ( ((*it)->isDevice()) || ((*it)->isRouting()) ){
|
|
cerr << "-- Children: " << count << "/" << _children.size()-1 << " --" << endl;
|
|
(*it)->printLine();
|
|
}
|
|
else {
|
|
cerr << endl;
|
|
cerr << "-- Children: " << count << "/" << _children.size()-1 << " --" << endl;
|
|
(*it)->printLine();
|
|
(*it)->printChildrenLine();
|
|
}
|
|
count++;
|
|
}
|
|
}
|
|
|
|
|
|
bool HVSlicingNode::recursiveCheckPreset() const
|
|
{
|
|
bool isPreset = this->isPreset();
|
|
if (isPreset){
|
|
for (vector<SlicingNode*>::const_iterator it = _children.begin(); it != _children.end(); it++){
|
|
isPreset = (*it)->recursiveCheckPreset();
|
|
}
|
|
}
|
|
return isPreset;
|
|
}
|
|
|
|
|
|
bool HVSlicingNode::recursiveCheckSet() const
|
|
{
|
|
bool isSet = this->isSet();
|
|
if (isSet){
|
|
for (vector<SlicingNode*>::const_iterator it = _children.begin(); it != _children.end(); it++){
|
|
isSet = (*it)->recursiveCheckSet();
|
|
}
|
|
}
|
|
return isSet;
|
|
}
|
|
|
|
|
|
bool HVSlicingNode::recursiveCheckPlaced() const
|
|
{
|
|
bool isPlaced = this->isPlaced();
|
|
if (isPlaced){
|
|
for (vector<SlicingNode*>::const_iterator it = _children.begin(); it != _children.end(); it++){
|
|
isPlaced = (*it)->recursiveCheckPlaced();
|
|
}
|
|
}
|
|
return isPlaced;
|
|
}
|
|
|
|
|
|
int HVSlicingNode::getLeafNumber() const
|
|
{
|
|
int cpt = 0;
|
|
for (vector<SlicingNode*>::const_iterator it = _children.begin(); it != _children.end(); it++)
|
|
{ cpt += (*it)->getLeafNumber(); }
|
|
return cpt;
|
|
}
|
|
|
|
|
|
double HVSlicingNode::getDevicesArea() const
|
|
{
|
|
double area = 0;
|
|
for (vector<SlicingNode*>::const_iterator it = _children.begin(); it != _children.end(); it++){
|
|
area += (*it)->getDevicesArea();
|
|
}
|
|
return area;
|
|
}
|
|
|
|
|
|
double HVSlicingNode::getOccupationArea() const
|
|
{
|
|
double estimation = 0;
|
|
if(recursiveCheckPlaced())
|
|
{
|
|
estimation = getDevicesArea()/(getHeight() * getWidth())*100;
|
|
}
|
|
else { cerr << "Error(double 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 ( (_nodeSets->empty() != true) ){
|
|
vector<BoxSet*>::const_iterator it = _nodeSets->begin();
|
|
DbU::Unit bestH = 0;
|
|
DbU::Unit bestW = 0;
|
|
DbU::Unit currentH = 0;
|
|
DbU::Unit currentW = 0;
|
|
BoxSet* boxSet = (*_nodeSets->begin());
|
|
|
|
while (it != _nodeSets->end()){
|
|
currentH = (*it)->getHeight();
|
|
currentW = (*it)->getWidth();
|
|
if ( (currentH <= height) && (currentW <= width) ){
|
|
if ( ((height-currentH) <= _toleranceRatioH) && ((height-bestH) <= _toleranceRatioH) ) {
|
|
if (currentW > bestW){
|
|
bestH = currentH;
|
|
bestW = currentW;
|
|
boxSet = (*it);
|
|
}
|
|
} else if (currentH > bestH) {
|
|
bestH = currentH;
|
|
bestW = currentW;
|
|
boxSet = (*it);
|
|
}
|
|
}
|
|
it++;
|
|
}
|
|
this->_setGlobalSize(boxSet);
|
|
|
|
} else { cerr << "Error(void HVSlicingNode::setGlobalSize( DbU::Unit height, DbU::Unit width )): NodeSets empty. UpdateGlobalSize needs to be used first or with higher tolerances." << endl; }
|
|
}
|
|
|
|
|
|
void HVSlicingNode::setGlobalSize( size_t index )
|
|
{
|
|
if ( _nodeSets->empty() != true ){
|
|
if (index > (_nodeSets->size()-1)){ cerr << "Error(void HVSlicingNode::setGlobalSize( size_t index )): Out of bound index." << endl; }
|
|
else {
|
|
this->_setGlobalSize((*(_nodeSets->begin() + index)));
|
|
}
|
|
} else { cerr << "Error(void HVSlicingNode::setGlobalSize( int index )): NodeSets empty. UpdateGlobalSize needs to be used first or with higher tolerances." << endl; }
|
|
}
|
|
|
|
|
|
void HVSlicingNode::_setGlobalSize ( BoxSet* boxSet )
|
|
{
|
|
//cerr << "void HVSlicingNode::_setGlobalSize ( BoxSet* boxSet ) " << endl;
|
|
if ( (!this->isPreset()) ){
|
|
if (this->getMaster() == NULL) {
|
|
this->_setBoxSet(boxSet);
|
|
} else {
|
|
this->_setBoxSet(_master->getBoxSet());
|
|
}
|
|
if ( ((getType() == HorizontalSNode) && (isHSymmetry()))
|
|
|| ((getType() == VerticalSNode ) && (isVSymmetry()))
|
|
){
|
|
vector<BoxSet*>::const_iterator itBoxSet = boxSet->getSet().begin();
|
|
for (vector<SlicingNode*>::reverse_iterator it = _children.rbegin(); it != _children.rend(); ++it){
|
|
(*it)->_setGlobalSize((*itBoxSet));
|
|
itBoxSet++;
|
|
}
|
|
} else {
|
|
vector<BoxSet*>::const_iterator itBoxSet = boxSet->getSet().begin();
|
|
for (vector<SlicingNode*>::iterator it = _children.begin(); it != _children.end(); it++){
|
|
(*it)->_setGlobalSize((*itBoxSet));
|
|
itBoxSet++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void HVSlicingNode::preDestroy()
|
|
{
|
|
SlicingNode::preDestroy();
|
|
for (vector<SlicingNode*>::iterator it = _children.begin(); it != _children.end(); it++){
|
|
(*it)->removeParent();
|
|
}
|
|
}
|
|
|
|
|
|
void HVSlicingNode::destroy()
|
|
{
|
|
HVSlicingNode::preDestroy();
|
|
delete(this);
|
|
}
|
|
|
|
|
|
void HVSlicingNode::preRecursiveDestroy()
|
|
{
|
|
SlicingNode::preRecursiveDestroy();
|
|
for (vector<SlicingNode*>::iterator it = _children.begin(); it != _children.end(); it++){
|
|
if ( ((*it)->getType() == HorizontalSNode) || ((*it)->getType() == VerticalSNode) ){
|
|
(*it)->removeParent();
|
|
(*it)->recursiveDestroy();
|
|
} else {
|
|
(*it)->removeParent();
|
|
(*it)->destroy();
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void HVSlicingNode::recursiveDestroy()
|
|
{
|
|
HVSlicingNode::preRecursiveDestroy();
|
|
delete(this);
|
|
}
|
|
|
|
void printList( list<SlicingNode*> liste )
|
|
{
|
|
for ( list<SlicingNode*>::const_iterator it = liste.begin(); it != liste.end(); it++ ){
|
|
(*it)->print();
|
|
}
|
|
}
|
|
|
|
list<SlicingNode*> HVSlicingNode::getLeaves () const
|
|
{
|
|
list<SlicingNode*> leaves = list<SlicingNode*>();
|
|
for (vector<SlicingNode*>::const_iterator it = _children.begin(); it != _children.end(); it++){
|
|
if ( ((*it)->getType() == DeviceSNode) || ((*it)->getType() == RoutingSNode) ){
|
|
leaves.push_back((*it));
|
|
} else {
|
|
leaves.splice(leaves.end(), (*it)->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 (vector<SlicingNode*>::const_iterator it = _children.begin(); it != _children.end(); it++){
|
|
if (cpt < 2){ initialPlacement = (*it)->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 (cell) {
|
|
bool found = true;
|
|
for ( Instance* instance : cell->getInstances() ) {
|
|
if (not findInstance(instance)) {
|
|
found = false;
|
|
cerr << Warning( "HVSlicingNode::checkCellInstances() Instance \"%s\" is missing from the SlicingTree. "
|
|
, getString(instance->getName()).c_str()
|
|
) << endl;
|
|
}
|
|
}
|
|
return found;
|
|
}
|
|
|
|
return false;
|
|
}*/
|
|
bool HVSlicingNode::checkCellInstances ( Cell* cell )
|
|
{
|
|
if (cell) {
|
|
bool found = true;
|
|
for (vector<SlicingNode*>::const_iterator it = _children.begin(); it != _children.end(); it++){
|
|
if (not (*it)->checkCellInstances(cell)) found = false;
|
|
}
|
|
return found;
|
|
} else {
|
|
cerr << "HVSlicingNode::checkCellInstances() Cell is NULL. " << endl;
|
|
return false;
|
|
}
|
|
}
|
|
|
|
SlicingNode* HVSlicingNode::findInstance( Instance* instance )
|
|
{
|
|
SlicingNode* node = NULL;
|
|
for (vector<SlicingNode*>::const_iterator it = _children.begin(); it != _children.end(); it++){
|
|
if( ((*it)->getType() == HorizontalSNode) || ((*it)->getType() == VerticalSNode) ){
|
|
SlicingNode* inode = (*it)->findInstance(instance);
|
|
if (inode != NULL){ node = inode; }
|
|
} else if ((*it)->getType() == DeviceSNode){
|
|
if ( (*it)->getInstance() == instance ){
|
|
node = (*it);
|
|
}
|
|
}
|
|
}
|
|
return node;
|
|
}
|
|
|
|
|
|
|
|
SlicingNode* HVSlicingNode::findSlicingNode( Anabatic::GCell* gcell )
|
|
{
|
|
SlicingNode* node = NULL;
|
|
for (vector<RHVSlicingNode*>::iterator it = _slicingRouting.begin(); it != _slicingRouting.end(); ++it){
|
|
if ( (*it)->getGCell() == gcell ){
|
|
node = (*it);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (node == NULL){
|
|
for (vector<SlicingNode*>::const_iterator it = _children.begin(); it != _children.end(); ++it){
|
|
if( ((*it)->getType() == HorizontalSNode) || ((*it)->getType() == VerticalSNode) ){
|
|
SlicingNode* inode = (*it)->findSlicingNode(gcell);
|
|
if (inode != NULL){ node = inode; }
|
|
} else if ((*it)->getType() == DeviceSNode){
|
|
if ( (*it)->getGCell() == gcell ){
|
|
node = (*it);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return node;
|
|
}
|
|
|
|
|
|
void HVSlicingNode::resetSlicingRouting()
|
|
{
|
|
for (vector<RHVSlicingNode*>::iterator it = _slicingRouting.begin(); it != _slicingRouting.end(); it++){
|
|
(*it)->resetSize();
|
|
}
|
|
for (vector<SlicingNode*>::const_iterator it = _children.begin(); it != _children.end(); it++){
|
|
if ( ((*it)->getType() == HorizontalSNode)||((*it)->getType() == VerticalSNode) ){
|
|
(*it)->resetSlicingRouting();
|
|
}
|
|
}
|
|
this->setRoutingEstimated(0);
|
|
}
|
|
|
|
|
|
void HVSlicingNode::destroySlicingRouting()
|
|
{
|
|
for (vector<RHVSlicingNode*>::iterator it = _slicingRouting.begin(); it != _slicingRouting.end(); it++){
|
|
(*it)->destroy();
|
|
}
|
|
_slicingRouting.clear();
|
|
for (vector<SlicingNode*>::const_iterator it = _children.begin(); it != _children.end(); it++){
|
|
if ( ((*it)->getType() == HorizontalSNode)||((*it)->getType() == VerticalSNode) ){
|
|
(*it)->destroySlicingRouting();
|
|
}
|
|
}
|
|
this->setRoutingEstimated(0);
|
|
}
|
|
|
|
|
|
int HVSlicingNode::getRoutingIndex( SlicingNode* node ) const
|
|
{
|
|
int i = 0;
|
|
vector<RHVSlicingNode*>::const_iterator it = _slicingRouting.begin();
|
|
while (it != _slicingRouting.end()){
|
|
if ( ((*it)->getHeight() == node->getHeight())
|
|
&& ((*it)->getWidth () == node->getWidth ())
|
|
&& ((*it)->getX() == node->getX() )
|
|
&& ((*it)->getY() == node->getY() )
|
|
)
|
|
{ it = _slicingRouting.end(); }
|
|
else {
|
|
i++;
|
|
it++;
|
|
}
|
|
}
|
|
return i;
|
|
}
|
|
|
|
|
|
SlicingNode* HVSlicingNode::getSlicingRouting( int index ) const
|
|
{
|
|
return (*(_slicingRouting.begin()+index));
|
|
}
|
|
|
|
|
|
void HVSlicingNode::restrictDevices()
|
|
{
|
|
for (vector<SlicingNode*>::const_iterator it = _children.begin(); it != _children.end(); it++){
|
|
(*it)->restrictDevices();
|
|
}
|
|
for (std::vector<RHVSlicingNode*>::iterator it = _slicingRouting.begin(); it != _slicingRouting.end(); it++){
|
|
(*it)->restrictDevices();
|
|
}
|
|
}
|
|
|
|
|
|
void HVSlicingNode::setVertexRestriction( Net* net, Katana::KatanaEngine* katana )
|
|
{
|
|
cdebug_log(536,1) << "HVSlicingNode::setVertexRestriction(Net*,KatanaEngine*)" << endl;
|
|
|
|
this->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( "Dijkstra::load(): %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 (std::vector<RHVSlicingNode*>::iterator it = _slicingRouting.begin(); it != _slicingRouting.end(); it++){
|
|
(*it)->estimateChannelsSize();
|
|
}
|
|
for (vector<SlicingNode*>::iterator it = _children.begin(); it != _children.end(); it++){
|
|
(*it)->estimateChannelsSize();
|
|
}
|
|
}
|
|
|
|
|
|
void HVSlicingNode::expandRoutingChannel()
|
|
{
|
|
estimateChannelsSize();
|
|
_expandRoutingChannel();
|
|
}
|
|
|
|
|
|
void HVSlicingNode::_expandRoutingChannel()
|
|
{
|
|
for ( RHVSlicingNode* node : _slicingRouting ) node->_expandRoutingChannel();
|
|
for ( SlicingNode* node : _children ) {
|
|
if (node->getType() != RoutingSNode) node->_expandRoutingChannel();
|
|
}
|
|
setRoutingEstimated(RoutingEstimated);
|
|
if (_parent == NULL) {
|
|
for ( SlicingNode* node : _children ) node->adjustBorderChannels();
|
|
}
|
|
}
|
|
|
|
|
|
void HVSlicingNode::expandRoutingChannel( DbU::Unit height, DbU::Unit width )
|
|
{
|
|
for ( RHVSlicingNode* node : _slicingRouting ) node->expandRoutingChannel( height, width );
|
|
for ( SlicingNode* node : _children ) {
|
|
if (node->getType() != RoutingSNode) node->expandRoutingChannel( height, width );
|
|
}
|
|
setRoutingEstimated( RoutingEstimated );
|
|
if (_parent == NULL)
|
|
for ( SlicingNode* node : _children ) node->adjustBorderChannels();
|
|
}
|
|
|
|
|
|
bool HVSlicingNode::isRoutingEstimated() const
|
|
{
|
|
//cerr << "bool HVSlicingNode::isRoutingEstimated() const" << endl;
|
|
bool estimated = true;
|
|
if (_slicingRouting.empty()){
|
|
estimated = false;
|
|
} else {
|
|
for (std::vector<RHVSlicingNode*>::const_iterator it = _slicingRouting.begin(); it != _slicingRouting.end(); it++){
|
|
estimated &= (*it)->isRoutingEstimated();
|
|
}
|
|
}
|
|
|
|
for (vector<SlicingNode*>::const_iterator it = _children.begin(); it != _children.end(); it++){
|
|
if ( ((*it)->getType() == HorizontalSNode ) || ((*it)->getType() == VerticalSNode) ){
|
|
estimated &= (*it)->isRoutingEstimated();
|
|
}
|
|
}
|
|
return estimated;
|
|
}
|
|
|
|
|
|
void HVSlicingNode::updateGCellPosition()
|
|
{
|
|
cdebug_log(535,1) << "HVSlicingNode::updateGCellPosition()" << endl;
|
|
|
|
for ( SlicingNode* node : _slicingRouting ) node->updateGCellPosition();
|
|
for ( SlicingNode* node : _children ) node->updateGCellPosition();
|
|
|
|
cdebug_tabw(535,-1);
|
|
}
|
|
|
|
|
|
void HVSlicingNode::updateGContacts()
|
|
{
|
|
cdebug_log(535,1) << "HVSlicingNode::updateGContacts()" << endl;
|
|
|
|
for ( SlicingNode* node : _slicingRouting ) node->updateGContacts();
|
|
for ( SlicingNode* node : _children ) node->updateGContacts();
|
|
|
|
cdebug_tabw(535,-1);
|
|
}
|
|
|
|
|
|
void HVSlicingNode::clearGCells()
|
|
{
|
|
for (std::vector<RHVSlicingNode*>::const_iterator it = _slicingRouting.begin(); it != _slicingRouting.end(); it++){
|
|
(*it)->clearGCells();
|
|
}
|
|
for (vector<SlicingNode*>::const_iterator it = _children.begin(); it != _children.end(); it++){
|
|
(*it)->clearGCells();
|
|
}
|
|
_gcell = NULL;
|
|
}
|
|
|
|
|
|
int HVSlicingNode::getNbDevices ()
|
|
{
|
|
int nb = 0;
|
|
for ( SlicingNode* node : _children ){
|
|
nb += node->getNbDevices();
|
|
}
|
|
return nb;
|
|
}
|
|
|
|
|
|
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 (std::vector<RHVSlicingNode*>::const_iterator it = _slicingRouting.begin(); it != _slicingRouting.end(); it++){
|
|
(*it)->setSymmetryFlag(flag);
|
|
}
|
|
for (vector<SlicingNode*>::const_iterator it = _children.begin(); it != _children.end(); it++){
|
|
(*it)->setSymmetryFlag(flag);
|
|
}
|
|
}
|
|
|
|
|
|
void HVSlicingNode::setMaster ( SlicingNode* master )
|
|
{
|
|
_master = master;
|
|
int index = 0;
|
|
|
|
if ( ((getType() == HorizontalSNode) && (isHSymmetry()))
|
|
|| ((getType() == VerticalSNode ) && (isVSymmetry()))
|
|
){
|
|
for (vector<SlicingNode*>::reverse_iterator it = _children.rbegin(); it != _children.rend(); it++) {
|
|
(*it)->setMaster(master->getChild(index));
|
|
index++;
|
|
}
|
|
} else {
|
|
for (vector<SlicingNode*>::iterator it = _children.begin(); it != _children.end(); it++) {
|
|
(*it)->setMaster(master->getChild(index));
|
|
index++;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
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) && (symmetryType == HSymmetry))
|
|
|| ((getType() == VerticalSNode ) && (symmetryType == VSymmetry))
|
|
){
|
|
int i = 0;
|
|
for ( int ichild = (int) getNbChild()-1 ; isSame and (ichild > -1) ; --ichild ) {
|
|
isSame = getChild(i)->isSymmetric( node->getChild(ichild), symmetryType );
|
|
i++;
|
|
}
|
|
} else {
|
|
for ( int ichild = 0 ; isSame and (ichild < (int) getNbChild()) ; ++ichild ) {
|
|
isSame = getChild(ichild)->isSymmetric( node->getChild(ichild), symmetryType );
|
|
}
|
|
}
|
|
|
|
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::checkSymmetryNet( unsigned int type, Net* net1, Net* net2 ) const
|
|
{
|
|
//cerr << "bool HVSlicingNode::checkSymmetryNet( unsigned int type, Net* net1, Net* net2 ) const" << endl;
|
|
bool b = false;
|
|
for ( vector<tuple<unsigned int, Net*, Net*> >::const_iterator it = _netsymmetries.begin(); it != _netsymmetries.end(); ++it) {
|
|
if (get<1>((*it)) == net1){
|
|
if (get<2>((*it)) == net2){
|
|
if (get<0>((*it)) == type) {
|
|
b = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return b;
|
|
}
|
|
|
|
|
|
void HVSlicingNode::addSymmetryNet( unsigned int type, Net* net1, Net* net2 )
|
|
{
|
|
//cerr << "void HVSlicingNode::addSymmetryNet( unsigned int type, Net* net1, Net* net2 )" << endl;
|
|
if (!checkSymmetryNet(type, net1, net2)){
|
|
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));
|
|
} else {
|
|
cerr << "Warning(void HVSlicingNode::addSymmetryNet( unsigned int type, Net* net1, Net* net2 )): Net symmetry already set." << endl;
|
|
}
|
|
}
|
|
|
|
|
|
void HVSlicingNode::updateNetConstraints()
|
|
{
|
|
//cerr << "void void HVSlicingNode::updateNetConstraints()" << endl;
|
|
if (_cell != NULL){
|
|
for ( vector<tuple<unsigned int, Net*, Net*> >::const_iterator it = _netsymmetries.begin(); it != _netsymmetries.end(); ++it) {
|
|
if (get<2>((*it))){
|
|
Net* masterNet = get<1>((*it));
|
|
if (not masterNet) cerr << "void HVSlicingNode::updateNetConstraints() Net \"%s\" not found." << endl;
|
|
|
|
NetRoutingState* masterState = NetRoutingExtension::get( masterNet );
|
|
if (not masterState) masterState = NetRoutingExtension::create( masterNet );
|
|
//cerr << "type: " << get<0>((*it)) << endl;
|
|
//cerr << "net1: " << get<1>((*it)) << endl;
|
|
//cerr << "net2: " << get<2>((*it)) << endl;
|
|
|
|
masterState->setFlags ( NetRoutingState::AutomaticGlobalRoute
|
|
| NetRoutingState::Symmetric
|
|
| NetRoutingState::SymmetricMaster
|
|
| get<0>((*it)) );
|
|
/*if (get<0>((*it)) == NetRoutingState::Vertical ) masterState->setSymAxis( getX() + getWidth ()/2 );
|
|
else if (get<0>((*it)) == NetRoutingState::Horizontal) masterState->setSymAxis( getY() + getHeight()/2 );
|
|
else cerr << "void HVSlicingNode::updateNetConstraints(): Wrong axis for Net \"%s\"." << endl;*/
|
|
|
|
Net* slaveNet = get<2>((*it));
|
|
if (not slaveNet) cerr << "void HVSlicingNode::updateNetConstraints() Net \"%s\" not found." << endl;
|
|
|
|
NetRoutingState* slaveState = NetRoutingExtension::get( slaveNet );
|
|
if (not slaveState) slaveState = NetRoutingExtension::create( slaveNet );
|
|
|
|
slaveState ->setFlags ( NetRoutingState::AutomaticGlobalRoute
|
|
| NetRoutingState::Symmetric
|
|
| get<0>((*it)) );
|
|
/*if (get<0>((*it)) == NetRoutingState::Vertical ) slaveState->setSymAxis( getX() + getWidth ()/2 );
|
|
else if (get<0>((*it)) == NetRoutingState::Horizontal) slaveState->setSymAxis( getY() + getHeight()/2 );
|
|
else cerr << "void HVSlicingNode::updateNetConstraints(): Wrong axis for Net \"%s\"." << endl;*/
|
|
slaveState ->setSymNet ( masterNet );
|
|
masterState->setSymNet ( slaveNet );
|
|
|
|
//cerr << "masterState: " << masterState << endl;
|
|
//cerr << "slaveState : " << slaveState << endl;
|
|
} else {
|
|
Net* net = get<1>((*it));
|
|
if (not net) cerr << "void HVSlicingNode::updateNetConstraints() Net \"%s\" not found." << endl;
|
|
|
|
NetRoutingState* state = NetRoutingExtension::get( net );
|
|
if (not state) state = NetRoutingExtension::create( net );
|
|
|
|
state->setFlags ( NetRoutingState::AutomaticGlobalRoute
|
|
| NetRoutingState::Symmetric
|
|
| get<0>((*it)) );
|
|
//cerr << "state: " << state << endl;
|
|
/*if (get<0>((*it)) == NetRoutingState::Vertical ) state->setSymAxis( getX() + getWidth ()/2 );
|
|
else if (get<0>((*it)) == NetRoutingState::Horizontal) state->setSymAxis( getY() + getHeight()/2 );
|
|
else cerr << "void HVSlicingNode::updateNetConstraints(): Wrong axis for Net \"%s\"." << endl;*/
|
|
}
|
|
}
|
|
for (vector<SlicingNode*>::iterator it = _children.begin(); it != _children.end(); ++it){
|
|
if (((*it)->getType() == HorizontalSNode)||((*it)->getType() == VerticalSNode)) (*it)->updateNetConstraints();
|
|
}
|
|
} else {
|
|
cerr << "Error(void HVSlicingNode::updateNetConstraints()): Cell undefined." << endl;
|
|
}
|
|
}
|
|
|
|
|
|
void HVSlicingNode::updateSymNetAxis()
|
|
{
|
|
//cerr << "void HVSlicingNode::updateSymNetAxis()" << endl;
|
|
if (_cell != NULL){
|
|
for ( const tuple<unsigned int, Net*, Net*> triplet : _netsymmetries ) {
|
|
|
|
|
|
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>(triplet)){
|
|
Net* masterNet = get<1>(triplet);
|
|
if (not masterNet) cerr << "void HVSlicingNode::updateSymNetAxis() Net \"%s\" not found." << endl;
|
|
|
|
NetRoutingState* masterState = NetRoutingExtension::get( masterNet );
|
|
if (not masterState) cerr << "void HVSlicingNode::updateSymNetAxis(): UpdateNetConstraint need to be used first." << endl;
|
|
|
|
if (get<0>(triplet) == NetRoutingState::Vertical ) masterState->setSymAxis( xCenter );//getXCenter() );
|
|
else if (get<0>(triplet) == NetRoutingState::Horizontal) masterState->setSymAxis( yCenter );//getYCenter() );
|
|
else cerr << "void HVSlicingNode::updateSymNetAxis(): Unknown NetRoutingState type." << endl;
|
|
|
|
Net* slaveNet = get<2>(triplet);
|
|
if (not slaveNet) cerr << "void HVSlicingNode::updateSymNetAxis() Net \"%s\" not found." << endl;
|
|
|
|
NetRoutingState* slaveState = NetRoutingExtension::get( slaveNet );
|
|
if (not slaveState) cerr << "void HVSlicingNode::updateSymNetAxis(): updateSymNetAxis need to be used first." << endl;
|
|
|
|
if (get<0>(triplet) == NetRoutingState::Vertical ) slaveState->setSymAxis( xCenter );//getXCenter() );
|
|
else if (get<0>(triplet) == NetRoutingState::Horizontal) slaveState->setSymAxis( yCenter );//getYCenter() );
|
|
else cerr << "void HVSlicingNode::updateSymNetAxis(): Unknown NetRoutingState type." << endl;
|
|
|
|
//cerr << "Master net: " << masterNet << ", state: " << masterState << ", axis: " << DbU::getValueString(masterState->getSymAxis())<< endl;
|
|
//cerr << "Slave net: " << slaveNet << ", state: " << slaveState << ", axis: " << DbU::getValueString(slaveState->getSymAxis())<< endl;
|
|
} else {
|
|
|
|
|
|
/*
|
|
if ( getType() == HorizontalSNode ) {
|
|
if ( !checkSelfSymH (get<1>(triplet)) ) {
|
|
cerr << Error( "SlicingNode::HVSlicingNode::updateSymNetAxis(): Net %s is not self symmetric.", getString(get<1>(triplet)).c_str() ) << endl;
|
|
}
|
|
} else if ( getType() == VerticalSNode ) {
|
|
if ( !checkSelfSymV (get<1>(triplet)) ) {
|
|
cerr << Error( "SlicingNode::HVSlicingNode::updateSymNetAxis(): Net %s is not self symmetric.", getString(get<1>(triplet)).c_str() ) << endl;
|
|
}
|
|
} */
|
|
|
|
Net* net = get<1>(triplet);
|
|
if (not net) cerr << "void HVSlicingNode::updateSymNetAxis() Net not found." << endl;
|
|
|
|
NetRoutingState* state = NetRoutingExtension::get( net );
|
|
if (not state) cerr << "void HVSlicingNode::updateSymNetAxis(): UpdateNetConstraint need to be used first." << endl;
|
|
|
|
if (get<0>(triplet) == NetRoutingState::Vertical ){
|
|
//cerr << "case Vertical" << endl ;
|
|
state->setSymAxis( xCenter );//getXCenter() );
|
|
}
|
|
else if (get<0>(triplet) == NetRoutingState::Horizontal) {
|
|
//cerr << "case Horizontal" << endl ;
|
|
state->setSymAxis( yCenter );//getYCenter() );
|
|
}
|
|
|
|
|
|
|
|
|
|
else cerr << "void HVSlicingNode::updateSymNetAxis(): Unknown NetRoutingState type." << endl;
|
|
//cerr << "Master Only net: " << net << ", state: " << state << ", axis: " << DbU::getValueString(state->getSymAxis())<< endl;
|
|
}
|
|
}
|
|
for ( SlicingNode* child : _children ) {
|
|
if ( (child->getType() == HorizontalSNode) or (child->getType() == VerticalSNode) )
|
|
child->updateSymNetAxis();
|
|
}
|
|
} else {
|
|
cerr << "Error(void HVSlicingNode::updateSymNetAxis()): Cell undefined." << endl;
|
|
}
|
|
}
|
|
|
|
|
|
void HVSlicingNode::flattenDigitalNets ()
|
|
{
|
|
if (_cell != NULL){
|
|
for (vector<SlicingNode*>::iterator it = _children.begin(); it != _children.end(); ++it){
|
|
if (((*it)->getType() == HorizontalSNode)||((*it)->getType() == VerticalSNode)){
|
|
(*it)->flattenDigitalNets();
|
|
} else if ((*it)->getType() == DeviceSNode){
|
|
if ( ((*it)->getGCell() != NULL) && ((*it)->getInstance() != NULL) ){
|
|
if ( (*it)->getGCell()->isMatrix() ) {
|
|
//cerr << "FLATTEN NETS: " << (*it)->getInstance() << endl;
|
|
_cell->flattenNets( (*it)->getInstance(), Cell::Flags::BuildRings|Cell::Flags::WarnOnUnplacedInstances );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
cerr << "Error(void HVSlicingNode::flattenDigitalNets()): Cell not found." << endl;
|
|
}
|
|
}
|
|
|
|
|
|
void HVSlicingNode::updateWireOccupation ( Anabatic::VertexSet sources )
|
|
{
|
|
//cerr << "void HVSlicingNode::updateWireOccupation ( Anabatic::VertexSet sources )" << endl;
|
|
if (_parent == NULL){
|
|
//Anabatic::Vertex* ivertex = NULL;
|
|
for ( Anabatic::Vertex* ivertex : sources ) {
|
|
Anabatic::GCell* igcell = ivertex->getGCell();
|
|
SlicingNode* snode = findSlicingNode(igcell);
|
|
if (snode){
|
|
if((snode->getType() == RoutingSNode)&& ivertex->hasAData()){
|
|
//cerr << "ivertex:" << ivertex << ", min:" << DbU::getPhysical(ivertex->getIMin(), DbU::Micro) << ", max:" << DbU::getPhysical(ivertex->getIMax(), DbU::Micro) << endl;
|
|
snode->addWireOccupation( ivertex->getIMin()
|
|
, ivertex->getIMax()
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//cerr << "" << endl;
|
|
}
|
|
|
|
void HVSlicingNode::resetWireOccupation ()
|
|
{
|
|
for (std::vector<RHVSlicingNode*>::const_iterator it = _slicingRouting.begin(); it != _slicingRouting.end(); ++it){
|
|
(*it)->resetWireOccupation();
|
|
}
|
|
|
|
for (vector<SlicingNode*>::iterator it = _children.begin(); it != _children.end(); ++it){
|
|
if ((*it)->getType() != DeviceSNode) (*it)->resetWireOccupation();
|
|
}
|
|
}
|
|
// -----------------------------------------------------------------------------------------------//
|
|
// Class : HSlicingNode
|
|
// -----------------------------------------------------------------------------------------------//
|
|
|
|
|
|
int HSlicingNode::_count = 0;
|
|
int HSlicingNode::_countAll = 0;
|
|
|
|
|
|
HSlicingNode::HSlicingNode( unsigned int type, unsigned int alignment ): HVSlicingNode( type, alignment ){}
|
|
|
|
|
|
HSlicingNode::~HSlicingNode(){}
|
|
|
|
|
|
HSlicingNode* HSlicingNode::create( unsigned int alignment )
|
|
{
|
|
_count++;
|
|
_countAll++;
|
|
return new HSlicingNode( HorizontalSNode, alignment );
|
|
}
|
|
|
|
|
|
void HSlicingNode::createRouting( DbU::Unit space )
|
|
{
|
|
this->push_back(RHSlicingNode::create( space ));
|
|
resetSlicingTree();
|
|
}
|
|
|
|
|
|
void HSlicingNode::print() const
|
|
{
|
|
cerr << "- Print from Slicing Node - " << endl;
|
|
cerr << "SlicingType: Horizontal Node" << endl;
|
|
if (this->isAlignLeft ()){ cerr << "Alignment : Left" << endl; }
|
|
else if (this->isAlignCenter()){ cerr << "Alignment : Middle" << endl; }
|
|
else if (this->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( this->getAlignment() );
|
|
node->setTolerances( getToleranceRatioH()
|
|
, getToleranceRatioW()
|
|
, getToleranceBandH()
|
|
, getToleranceBandW()
|
|
);
|
|
node->setBoxSet ( getBoxSet() );
|
|
node->setNodeSets ( _nodeSets->clone() );
|
|
node->setPreset ( this->getPreset() );
|
|
node->setSet ( this->getSet() );
|
|
node->setPlaced ( this->getPlaced() );
|
|
node->setSymmetries( this->getSymmetries() );
|
|
|
|
for (vector<SlicingNode*>::iterator it = _children.begin(); it != _children.end(); it++){
|
|
if (tr == MY){ node->push_front((*it)->clone(tr)); }
|
|
else { node->push_back ((*it)->clone(tr)); }
|
|
}
|
|
return node;
|
|
}
|
|
|
|
|
|
void HSlicingNode::place( DbU::Unit x, DbU::Unit y )
|
|
{
|
|
if( recursiveCheckSet() ){
|
|
if (!_slicingRouting.empty()) {
|
|
this->destroySlicingRouting();
|
|
this->resetSlicingRouting();
|
|
}
|
|
this->_place(x,y);
|
|
if (_slicingRouting.empty()) {
|
|
this->createSlicingRouting();
|
|
}
|
|
this->updateCellAbutmentBox();
|
|
} else { cerr << "Error(void HSlicingNode::place( DbU::Unit x, DbU::Unit y )): 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 << Error( "void HSlicingNode::replace(DbU::Unit,DbU::Unit)): The SlicingTree is not completely set." ) << endl;
|
|
}
|
|
}
|
|
|
|
|
|
void HSlicingNode::_place( DbU::Unit x, DbU::Unit y, bool replace )
|
|
{
|
|
cdebug_log(536,1) << "void HSlicingNode::_place( DbU::Unit x, DbU::Unit y, bool replace )" << 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 (vector<SlicingNode*>::iterator it = _children.begin(); it != _children.end(); it++){
|
|
if ( ((*it)->isHorizontal()) || ((*it)->isVertical()) ){
|
|
if ( (*it)->isAlignLeft() ){
|
|
(*it)->setX(xref);
|
|
(*it)->setY(yref);
|
|
}
|
|
else if ( (*it)->isAlignCenter() ){
|
|
(*it)->setX(xref + (this->getWidth()/2) - ((*it)->getWidth()/2));
|
|
(*it)->setY(yref);
|
|
}
|
|
else if ( (*it)->isAlignRight() ){
|
|
(*it)->setX(xref + this->getWidth() - (*it)->getWidth());
|
|
(*it)->setY(yref);
|
|
}
|
|
}
|
|
|
|
if ( (*it)->isAlignLeft() ) { (*it)->_place(xref , yref, replace); }
|
|
else if ( (*it)->isAlignCenter() ) { (*it)->_place(xref + (this->getWidth()/2) - ((*it)->getWidth()/2), yref, replace); }
|
|
else if ( (*it)->isAlignRight() ) { (*it)->_place(xref + this->getWidth() - (*it)->getWidth() , yref, replace); }
|
|
else if ( (*it)->isRouting() ) { (*it)->_place(xref , yref, replace); }
|
|
else {
|
|
cerr << "Error(_place( DbU::Unit x, DbU::Unit y )): Unknown Alignment in SlicingTree." << endl ;
|
|
(*it)->print();
|
|
}
|
|
|
|
xref = x;
|
|
yref += (*it)->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()" << endl;
|
|
|
|
for (vector<SlicingNode*>::iterator it = _children.begin(); it != _children.end(); it++) {
|
|
(*it)->updateGlobalSize();
|
|
}
|
|
|
|
if (this->getMaster() == NULL) {
|
|
if (this->getNbChild() == 1){
|
|
_nodeSets->clear();
|
|
NodeSets* node = _children[0]->getNodeSets();
|
|
for(vector<BoxSet*>::const_iterator it2 = node->begin(); it2 != node->end(); it2++){
|
|
vector<BoxSet*> vect = vector<BoxSet*>();
|
|
vect.push_back((*it2));
|
|
DbU::Unit height = (*it2)->getHeight();
|
|
DbU::Unit width = (*it2)->getWidth();
|
|
_nodeSets->push_back(vect, height, width, HorizontalSNode);
|
|
}
|
|
}
|
|
else if ( (this->hasEmptyChildrenNodeSets() != true) && (_nodeSets->empty() == true) ){
|
|
|
|
HSetState state = HSetState(this);
|
|
while( !state.end() ){ state.next(); }
|
|
|
|
_nodeSets = state.getNodeSets();
|
|
}
|
|
if (_nodeSets->empty()){ cerr << "Error(void HSlicingNode::updateGlobalSize()): No solution has been found. Try to set larger tolerances." << endl; }
|
|
} else {
|
|
_nodeSets = _master->getNodeSets();
|
|
}
|
|
|
|
cdebug_tabw(535,-1);
|
|
}
|
|
|
|
|
|
void HSlicingNode::preDestroy()
|
|
{
|
|
_count--;
|
|
HVSlicingNode::preDestroy();
|
|
}
|
|
|
|
|
|
void HSlicingNode::destroy()
|
|
{
|
|
HSlicingNode::preDestroy();
|
|
delete(this);
|
|
}
|
|
|
|
|
|
void HSlicingNode::preRecursiveDestroy()
|
|
{
|
|
_count--;
|
|
HVSlicingNode::preRecursiveDestroy();
|
|
}
|
|
|
|
|
|
void HSlicingNode::recursiveDestroy()
|
|
{
|
|
HSlicingNode::preRecursiveDestroy();
|
|
delete(this);
|
|
}
|
|
|
|
|
|
OpenChams::SlicingNode* HSlicingNode::toOpenChams()
|
|
{
|
|
OpenChams::SlicingNode* hnode = OpenChams::HSlicingNode::create();
|
|
if ( isAlignLeft() ){ hnode->setAlignment( "AlignLeft" ); }
|
|
else if ( isAlignRight() ){ hnode->setAlignment( "AlignRight" ); }
|
|
else if ( isAlignCenter() ){ hnode->setAlignment( "AlignCenter" ); }
|
|
else if ( isAlignTop() ){ hnode->setAlignment( "AlignTop" ); }
|
|
else if ( isAlignBottom() ){ hnode->setAlignment( "AlignBottom" ); }
|
|
else { hnode->setAlignment( "UnknownAlignment"); }
|
|
|
|
hnode->setToleranceRatioH(_toleranceRatioH);
|
|
hnode->setToleranceRatioW(_toleranceRatioW);
|
|
hnode->setToleranceBandH(_toleranceBandH);
|
|
hnode->setToleranceBandW(_toleranceBandW);
|
|
|
|
if (!_symmetries.empty()){
|
|
for (list<pair <int,int> >::const_iterator it = _symmetries.begin(); it != _symmetries.end(); it++){
|
|
hnode->addSymmetry((*it).first, (*it).second);
|
|
}
|
|
}
|
|
|
|
for (vector<SlicingNode*>::iterator it2 = _children.begin(); it2 != _children.end(); it2++){
|
|
hnode->push_back( (*it2)->toOpenChams() );
|
|
}
|
|
|
|
return hnode;
|
|
}
|
|
|
|
|
|
void HSlicingNode::createSlicingRouting() // Needs to be change in case of not alternative H/V
|
|
{
|
|
if (_boxSet){
|
|
int numberChildren = getNbChild();
|
|
vector<SlicingNode*>::iterator it1 = _children.begin();
|
|
DbU::Unit x = this->getX();
|
|
DbU::Unit y = this->getY();
|
|
|
|
DbU::Unit heightValue = 0;
|
|
if ( _parent ){
|
|
if ( _parent->getType() == VerticalSNode ){
|
|
if ( (this->getAlignment() == AlignBottom) || (this->getAlignment() == AlignTop) ){
|
|
heightValue = _parent->getHeight() - this->getHeight();
|
|
} else if ( this->getAlignment() == AlignCenter ){
|
|
heightValue = (_parent->getHeight() - this->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 (int i = 0; i < numberChildren+1; ++i){
|
|
RHSlicingNode* rnode = NULL;
|
|
if ( i == 0 ){
|
|
if ( (this->getAlignment() == AlignTop) || (this->getAlignment() == AlignCenter) ){
|
|
rnode = RHSlicingNode::create( heightValue );
|
|
} else {
|
|
rnode = RHSlicingNode::create();
|
|
}
|
|
} else if ( i == numberChildren ){
|
|
if ( (this->getAlignment() == AlignBottom) || (this->getAlignment() == AlignCenter) ){
|
|
rnode = RHSlicingNode::create( heightValue );
|
|
} else {
|
|
rnode = RHSlicingNode::create();
|
|
}
|
|
} else {
|
|
rnode = RHSlicingNode::create();
|
|
}
|
|
rnode->setParent(this);
|
|
|
|
if (i == 0){
|
|
if ( this->getAlignment() == AlignBottom ){
|
|
rnode->place(x, y);
|
|
} else if ( (this->getAlignment() == AlignCenter) || (this->getAlignment() == AlignTop)) {
|
|
rnode->place(x, y-heightValue);
|
|
}
|
|
} else {
|
|
rnode->place(x, y);
|
|
}
|
|
|
|
if (_master){
|
|
rnode->setMaster(_master->getSlicingRouting(i));
|
|
}
|
|
_slicingRouting.push_back(rnode);
|
|
|
|
if (i < numberChildren){
|
|
y += (*it1)->getHeight();
|
|
it1++;
|
|
}
|
|
}
|
|
|
|
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 ((_symmetries.empty() == false)&&(isAlignCenter())){
|
|
for (size_t i = 0; i < (_slicingRouting.size()/2); i++){
|
|
getSlicingRouting(_slicingRouting.size()-1-i)->setMaster(getSlicingRouting(i));
|
|
}
|
|
}
|
|
|
|
for (vector<SlicingNode*>::iterator it = _children.begin(); it != _children.end(); it++){
|
|
if ( ((*it)->isHorizontal()) || ((*it)->isVertical()) ){
|
|
(*it)->createSlicingRouting();
|
|
}
|
|
}
|
|
|
|
this->setRoutingCreated(RoutingCreated);
|
|
} else {
|
|
cerr << "Error(void HSlicingNode::createSlicingRouting()): SlicingTree needs to be placed first." << endl;
|
|
}
|
|
}
|
|
|
|
|
|
DbU::Unit HSlicingNode::getHeight () const
|
|
{
|
|
DbU::Unit hpitch = _rg->getHorizontalPitch();
|
|
DbU::Unit height = 0;
|
|
|
|
if (isRoutingEstimated()){
|
|
for ( SlicingNode* node : _children ) height += node->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) << "DbU::Unit HSlicingNode::getWidth () const " << 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 {
|
|
//cdebug_log(536,0) << "case is routing not estimated" << endl;
|
|
if (_boxSet != NULL) 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 )
|
|
{
|
|
Anabatic::GCell* prevGCell = gcell;
|
|
Anabatic::GCell* nextGCell = NULL;
|
|
vector<SlicingNode* >::const_iterator itc = _children.begin();
|
|
vector<RHVSlicingNode*>::const_iterator its = _slicingRouting.begin();
|
|
cdebug_log(535,1) << "HSlicingNode::setGCell(Anabatic::GCell*), start Y: "<< (*its)->getY() << ", GCell:" << gcell << endl;
|
|
int index = 0;
|
|
DbU::Unit y = (*its)->getY();
|
|
|
|
while ( not ((itc == _children.end()) and (its+1 == _slicingRouting.end())) ) {
|
|
if (index%2 == 0) {
|
|
y += (*its)->getHeight();
|
|
nextGCell = prevGCell->hcut( y );
|
|
(*its)->setGCell( prevGCell );
|
|
its++;
|
|
} else {
|
|
y += (*itc)->getHeight();
|
|
nextGCell = prevGCell->hcut( y );
|
|
(*itc)->setGCell( prevGCell );
|
|
itc++;
|
|
}
|
|
prevGCell = nextGCell;
|
|
index++;
|
|
}
|
|
(*its)->setGCell( prevGCell );
|
|
|
|
cdebug_tabw(535,-1);
|
|
}
|
|
|
|
|
|
void HSlicingNode::adjustBorderChannels ()
|
|
{
|
|
if (_parent){
|
|
if (_parent->getHeight() > getHeight()){
|
|
DbU::Unit space = _parent->getHeight() - getHeight();
|
|
|
|
if ( this->getAlignment() == AlignTop ){
|
|
RHVSlicingNode* ch = (*_slicingRouting.begin());
|
|
ch->setHeight(ch->getHeight()+space);
|
|
|
|
|
|
} else if ( this->getAlignment() == AlignCenter ){
|
|
RHVSlicingNode* chf = (*_slicingRouting.begin());
|
|
RHVSlicingNode* chl = (*(_slicingRouting.end()-1));
|
|
chf->setHeight(chf->getHeight()+space/2);
|
|
chl->setHeight(chl->getHeight()+space/2);
|
|
|
|
} else if ( this->getAlignment() == AlignBottom ){
|
|
RHVSlicingNode* ch = (*(_slicingRouting.end()-1));
|
|
ch->setHeight(ch->getHeight()+space);
|
|
|
|
}
|
|
}
|
|
}
|
|
for (vector<SlicingNode*>::iterator it = _children.begin(); it != _children.end(); it++){
|
|
(*it)->adjustBorderChannels();
|
|
}
|
|
}
|
|
|
|
|
|
string HSlicingNode::_getString () const
|
|
{
|
|
string s = Super::_getString();
|
|
return s;
|
|
}
|
|
|
|
|
|
string HSlicingNode::_getTypeName () const
|
|
{ return "HSlicingNode"; }
|
|
|
|
|
|
// -----------------------------------------------------------------------------------------------//
|
|
// Class : VSlicingNode
|
|
// -----------------------------------------------------------------------------------------------//
|
|
|
|
|
|
int VSlicingNode::_count = 0;
|
|
int VSlicingNode::_countAll = 0;
|
|
|
|
|
|
VSlicingNode::VSlicingNode( unsigned int type, unsigned int alignment ): HVSlicingNode( type, alignment ){}
|
|
|
|
|
|
VSlicingNode::~VSlicingNode(){}
|
|
|
|
|
|
VSlicingNode* VSlicingNode::create( unsigned int alignment )
|
|
{
|
|
_count++;
|
|
_countAll++;
|
|
return new VSlicingNode( VerticalSNode, alignment );
|
|
}
|
|
|
|
|
|
void VSlicingNode::createRouting( DbU::Unit space )
|
|
{
|
|
this->push_back(RVSlicingNode::create( space ));
|
|
resetSlicingTree();
|
|
}
|
|
|
|
|
|
void VSlicingNode::print() const
|
|
{
|
|
cerr << "- Print from Slicing Node - " << endl;
|
|
cerr << "SlicingType: Vertical Node" << endl;
|
|
if (this->isAlignBottom()){ cerr << "Alignment : Bottom" << endl; }
|
|
else if (this->isAlignCenter()){ cerr << "Alignment : Middle" << endl; }
|
|
else if (this->isAlignTop ()){ cerr << "Alignment : Top" << 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();
|
|
}
|
|
|
|
|
|
VSlicingNode* VSlicingNode::clone( unsigned int tr )
|
|
{
|
|
VSlicingNode* node = VSlicingNode::create( this->getAlignment() );
|
|
node->setTolerances( getToleranceRatioH()
|
|
, getToleranceRatioW()
|
|
, getToleranceBandH()
|
|
, getToleranceBandW()
|
|
);
|
|
node->setBoxSet ( getBoxSet() );
|
|
node->setNodeSets ( _nodeSets->clone() );
|
|
node->setPreset ( this->getPreset() );
|
|
node->setSet ( this->getSet() );
|
|
node->setPlaced ( this->getPlaced() );
|
|
node->setSymmetries( this->getSymmetries() );
|
|
|
|
for (vector<SlicingNode*>::iterator it = _children.begin(); it != _children.end(); it++){
|
|
if (tr == MX){ node->push_front((*it)->clone(tr)); }
|
|
else { node->push_back ((*it)->clone(tr)); }
|
|
}
|
|
return node;
|
|
}
|
|
|
|
|
|
void VSlicingNode::place( DbU::Unit x, DbU::Unit y )
|
|
{
|
|
if (recursiveCheckSet()){
|
|
if (!_slicingRouting.empty()) {
|
|
this->destroySlicingRouting();
|
|
this->resetSlicingRouting();
|
|
}
|
|
this->_place(x,y);
|
|
if (_slicingRouting.empty()) {
|
|
this->createSlicingRouting();
|
|
}
|
|
this->updateCellAbutmentBox();
|
|
} else { cerr << "Error(void VSlicingNode::place( DbU::Unit x, DbU::Unit y )): The SlicingTree is not completely set." << endl; }
|
|
}
|
|
|
|
|
|
void VSlicingNode::replace( DbU::Unit x, DbU::Unit y )
|
|
{
|
|
// WARNING: This will change GCell edges.
|
|
if (recursiveCheckSet()) {
|
|
_place( x, y, true );
|
|
updateCellAbutmentBox();
|
|
updateGCellPosition();
|
|
updateGContacts();
|
|
} else {
|
|
cerr << Error( "HVlicingNode::place(DbU::Unit,DbU::Unit)): The SlicingTree is not completely set." ) << endl;
|
|
}
|
|
}
|
|
|
|
|
|
void VSlicingNode::_place( DbU::Unit x, DbU::Unit y, bool replace )
|
|
{
|
|
cdebug_log(536,1) << "void VSlicingNode::_place( DbU::Unit x, DbU::Unit y, bool replace )" << endl;
|
|
//printLine();
|
|
vector<RHVSlicingNode*>::iterator itspace = _slicingRouting.begin();
|
|
DbU::Unit xref = x;
|
|
DbU::Unit yref = y;
|
|
|
|
if (isRoutingEstimated()){
|
|
(*itspace)->_place(xref, yref, replace);
|
|
xref += (*itspace)->getWidth();
|
|
itspace++;
|
|
}
|
|
|
|
for (vector<SlicingNode*>::iterator it = _children.begin(); it != _children.end(); it++){
|
|
if ( ( (*it)->isHorizontal()) || ((*it)->isVertical()) ){
|
|
if ( (*it)->isAlignBottom() ){
|
|
(*it)->setX(xref);
|
|
(*it)->setY(yref);
|
|
}
|
|
else if ( (*it)->isAlignCenter() ){
|
|
(*it)->setX(xref);
|
|
(*it)->setY(yref + (this->getHeight()/2) - ((*it)->getHeight()/2));
|
|
}
|
|
else if ( (*it)->isAlignTop() ){
|
|
(*it)->setX(xref);
|
|
(*it)->setY(yref + this->getHeight() - (*it)->getHeight());
|
|
}
|
|
}
|
|
|
|
if ( (*it)->isAlignBottom() ) { (*it)->_place(xref, yref , replace); }
|
|
else if ( (*it)->isAlignCenter() ) { (*it)->_place(xref, yref + (this->getHeight()/2) - ((*it)->getHeight()/2), replace); }
|
|
else if ( (*it)->isAlignTop() ) { (*it)->_place(xref, yref + this->getHeight() - (*it)->getHeight() , replace); }
|
|
else if ( (*it)->isRouting() ) { (*it)->_place(xref, yref , replace); }
|
|
else {
|
|
cerr << " Error(void place( DbU::Unit x, DbU::Unit y )): Unknown Alignment in SlicingTree." << endl ;
|
|
(*it)->print();
|
|
}
|
|
|
|
xref += (*it)->getWidth();
|
|
yref = y;
|
|
if (isRoutingEstimated()){
|
|
(*itspace)->_place(xref, yref, replace);
|
|
xref += (*itspace)->getWidth();
|
|
itspace++;
|
|
}
|
|
}
|
|
setPlaced(Placed);
|
|
cdebug_tabw(536,-1);
|
|
}
|
|
|
|
|
|
void VSlicingNode::updateGlobalSize()
|
|
{
|
|
cdebug_log(535,1) << "HSlicingNode::updateGlobalsize()" << endl;
|
|
|
|
for (vector<SlicingNode*>::iterator it = _children.begin(); it != _children.end(); it++) {
|
|
(*it)->updateGlobalSize();
|
|
}
|
|
|
|
if (this->getMaster() == NULL) {
|
|
if (this->getNbChild() == 1){
|
|
_nodeSets->clear();
|
|
NodeSets* node = _children[0]->getNodeSets();
|
|
for(vector<BoxSet*>::const_iterator it2 = node->begin(); it2 != node->end(); it2++){
|
|
vector<BoxSet*> vect = vector<BoxSet*>();
|
|
vect.push_back((*it2));
|
|
DbU::Unit height = (*it2)->getHeight();
|
|
DbU::Unit width = (*it2)->getWidth();
|
|
_nodeSets->push_back(vect, height, width, VerticalSNode);
|
|
}
|
|
}
|
|
else if ( (this->hasEmptyChildrenNodeSets() != true) && (_nodeSets->empty() == true) ){
|
|
|
|
VSetState state = VSetState(this);
|
|
while( !state.end() ){ state.next(); }
|
|
|
|
_nodeSets = state.getNodeSets();
|
|
}
|
|
if (_nodeSets->empty()) { cerr << "Error(void VSlicingNode::updateGlobalSize()): No solution has been found. Try to set larger tolerances." << endl; }
|
|
} else {
|
|
_nodeSets = _master->getNodeSets();
|
|
}
|
|
|
|
cdebug_tabw(535,-1);
|
|
}
|
|
|
|
|
|
void VSlicingNode::preDestroy()
|
|
{
|
|
_count--;
|
|
HVSlicingNode::preDestroy();
|
|
}
|
|
|
|
|
|
void VSlicingNode::destroy()
|
|
{
|
|
VSlicingNode::preDestroy();
|
|
delete(this);
|
|
}
|
|
|
|
|
|
void VSlicingNode::preRecursiveDestroy()
|
|
{
|
|
_count--;
|
|
HVSlicingNode::preRecursiveDestroy();
|
|
}
|
|
|
|
|
|
void VSlicingNode::recursiveDestroy()
|
|
{
|
|
VSlicingNode::preRecursiveDestroy();
|
|
delete(this);
|
|
}
|
|
|
|
|
|
OpenChams::SlicingNode* VSlicingNode::toOpenChams()
|
|
{
|
|
OpenChams::SlicingNode* vnode = OpenChams::VSlicingNode::create();
|
|
if ( isAlignLeft() ){ vnode->setAlignment( "AlignLeft" ); }
|
|
else if ( isAlignRight() ){ vnode->setAlignment( "AlignRight" ); }
|
|
else if ( isAlignCenter() ){ vnode->setAlignment( "AlignCenter" ); }
|
|
else if ( isAlignTop() ){ vnode->setAlignment( "AlignTop" ); }
|
|
else if ( isAlignBottom() ){ vnode->setAlignment( "AlignBottom" ); }
|
|
else { vnode->setAlignment( "UnknownAlignment"); }
|
|
|
|
vnode->setToleranceRatioH(_toleranceRatioH);
|
|
vnode->setToleranceRatioW(_toleranceRatioW);
|
|
vnode->setToleranceBandH(_toleranceBandH);
|
|
vnode->setToleranceBandW(_toleranceBandW);
|
|
|
|
if (!_symmetries.empty()){
|
|
for (list<pair <int,int> >::const_iterator it = _symmetries.begin(); it != _symmetries.end(); it++){
|
|
vnode->addSymmetry((*it).first, (*it).second);
|
|
}
|
|
}
|
|
|
|
for (vector<SlicingNode*>::iterator it2 = _children.begin(); it2 != _children.end(); it2++){
|
|
vnode->push_back( (*it2)->toOpenChams() );
|
|
}
|
|
|
|
return vnode;
|
|
}
|
|
|
|
|
|
void VSlicingNode::createSlicingRouting() // Needs to be change in case of not alternative H/V
|
|
{
|
|
if ( isPlaced() ){
|
|
int numberChildren = getNbChild();
|
|
vector<SlicingNode*>::iterator it1 = _children.begin();
|
|
DbU::Unit x = this->getX();
|
|
DbU::Unit y = this->getY();
|
|
|
|
|
|
DbU::Unit widthValue = 0;
|
|
if (_parent){
|
|
if ( _parent->getType() == HorizontalSNode ){
|
|
if ( (this->getAlignment() == AlignLeft) || (this->getAlignment() == AlignRight) ){
|
|
widthValue = _parent->getWidth() - this->getWidth();
|
|
} else if ( this->getAlignment() == AlignCenter ){
|
|
widthValue = (_parent->getWidth() - this->getWidth())/2;
|
|
}
|
|
}
|
|
}
|
|
|
|
DbU::Unit vpitch = _rg->getVerticalPitch();
|
|
if (widthValue % vpitch)
|
|
cerr << Warning( "VSlicingNode::createSlicingRouting(): On %s, width is not pitched (%s, pitch:%s)."
|
|
, getString(this).c_str()
|
|
, DbU::getValueString(widthValue).c_str()
|
|
, DbU::getValueString(vpitch).c_str()
|
|
) << endl;
|
|
|
|
for (int i = 0; i < numberChildren+1; ++i){
|
|
RVSlicingNode* rnode = NULL;
|
|
if ( i == 0 ){
|
|
if ( (this->getAlignment() == AlignRight) || (this->getAlignment() == AlignCenter) ){
|
|
rnode = RVSlicingNode::create( widthValue );
|
|
} else {
|
|
rnode = RVSlicingNode::create();
|
|
}
|
|
} else if ( i == numberChildren ){
|
|
if ( (this->getAlignment() == AlignLeft) || (this->getAlignment() == AlignCenter) ){
|
|
rnode = RVSlicingNode::create( widthValue );
|
|
} else {
|
|
rnode = RVSlicingNode::create();
|
|
}
|
|
} else {
|
|
rnode = RVSlicingNode::create();
|
|
}
|
|
rnode->setParent(this);
|
|
|
|
if (i == 0){
|
|
if ( this->getAlignment() == AlignLeft ){
|
|
rnode->place(x, y);
|
|
} else if ( (this->getAlignment() == AlignCenter) || (this->getAlignment() == AlignRight)) {
|
|
rnode->place(x-widthValue, y);
|
|
}
|
|
} else {
|
|
rnode->place(x, y);
|
|
}
|
|
_slicingRouting.push_back(rnode);
|
|
|
|
if (i < numberChildren){
|
|
x += (*it1)->getWidth();
|
|
it1++;
|
|
}
|
|
}
|
|
|
|
if (_master){
|
|
if (isVSymmetry()){
|
|
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 ((_symmetries.empty() == false)&&(isAlignCenter())){
|
|
for (size_t i = 0; i < (_slicingRouting.size()/2); i++){
|
|
getSlicingRouting(_slicingRouting.size()-1-i)->setMaster(getSlicingRouting(i));
|
|
}
|
|
}
|
|
|
|
for (vector<SlicingNode*>::iterator it = _children.begin(); it != _children.end(); it++){
|
|
if ( ((*it)->isHorizontal()) || ((*it)->isVertical()) ){
|
|
(*it)->createSlicingRouting();
|
|
}
|
|
}
|
|
this->setRoutingCreated(RoutingCreated);
|
|
}
|
|
}
|
|
|
|
|
|
DbU::Unit VSlicingNode::getWidth () const
|
|
{
|
|
DbU::Unit vpitch = _rg->getVerticalPitch();
|
|
DbU::Unit width = 0;
|
|
|
|
if (isRoutingEstimated()){
|
|
for ( SlicingNode* node : _children ) width += node->getWidth();
|
|
for ( RHVSlicingNode* node : _slicingRouting ) width += node->getWidth();
|
|
} else {
|
|
if (_boxSet != NULL) width = _boxSet->getWidth();
|
|
}
|
|
|
|
if (width % vpitch)
|
|
cerr << Warning( "VSlicingNode::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;
|
|
}
|
|
|
|
|
|
DbU::Unit VSlicingNode::getHeight () const
|
|
{
|
|
DbU::Unit hpitch = _rg->getHorizontalPitch();
|
|
DbU::Unit height = 0;
|
|
|
|
if (isRoutingEstimated()) {
|
|
SlicingNode* m = NULL;
|
|
for ( SlicingNode* node : _children ) {
|
|
if (node->getType() != RoutingSNode) {
|
|
if (node->getHeight() > height) {
|
|
height = node->getHeight();
|
|
m = node;
|
|
}
|
|
}
|
|
}
|
|
if (m->isDevice()) height += hpitch*2;
|
|
} else {
|
|
if (_boxSet != NULL) height = _boxSet->getHeight();
|
|
}
|
|
|
|
if (height % hpitch)
|
|
cerr << Warning( "VSlicingNode::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;
|
|
}
|
|
|
|
|
|
void VSlicingNode::setGCell ( Anabatic::GCell* gcell )
|
|
{
|
|
cdebug_log(535,1) << "VSlicingNode::setGCell(Anabatic::GCell*) " << gcell << endl;
|
|
|
|
Anabatic::GCell* prevGCell = gcell;
|
|
Anabatic::GCell* nextGCell = NULL;
|
|
vector<SlicingNode* >::const_iterator itc = _children.begin();
|
|
vector<RHVSlicingNode*>::const_iterator its = _slicingRouting.begin();
|
|
int index = 0;
|
|
DbU::Unit x = (*its)->getX();
|
|
|
|
while ( not ((itc == _children.end()) and (its+1 == _slicingRouting.end())) ) {
|
|
if (index%2 == 0) {
|
|
x += (*its)->getWidth();
|
|
nextGCell = prevGCell->vcut( x );
|
|
(*its)->setGCell( prevGCell );
|
|
its++;
|
|
} else {
|
|
x += (*itc)->getWidth();
|
|
nextGCell = prevGCell->vcut( x );
|
|
(*itc)->setGCell( prevGCell );
|
|
itc++;
|
|
}
|
|
prevGCell = nextGCell;
|
|
index++;
|
|
}
|
|
(*its)->setGCell( prevGCell );
|
|
|
|
cdebug_tabw(535,-1);
|
|
}
|
|
|
|
|
|
|
|
void VSlicingNode::adjustBorderChannels ()
|
|
{
|
|
if (_parent){
|
|
DbU::Unit space = _parent->getWidth() - getWidth();
|
|
|
|
if ( this->getAlignment() == AlignRight ){
|
|
RHVSlicingNode* ch = (*_slicingRouting.begin());
|
|
ch->setWidth(ch->getWidth()+space);
|
|
|
|
|
|
} else if ( this->getAlignment() == AlignCenter ){
|
|
RHVSlicingNode* chf = (*_slicingRouting.begin());
|
|
RHVSlicingNode* chl = (*(_slicingRouting.end()-1));
|
|
chf->setWidth(chf->getWidth()+space/2);
|
|
chl->setWidth(chl->getWidth()+space/2);
|
|
|
|
} else if ( this->getAlignment() == AlignLeft ){
|
|
RHVSlicingNode* ch = (*(_slicingRouting.end()-1));
|
|
ch->setWidth(ch->getWidth()+space);
|
|
|
|
}
|
|
}
|
|
for (vector<SlicingNode*>::iterator it = _children.begin(); it != _children.end(); it++){
|
|
(*it)->adjustBorderChannels();
|
|
}
|
|
}
|
|
|
|
|
|
string VSlicingNode::_getString () const
|
|
{
|
|
string s = Super::_getString();
|
|
return s;
|
|
}
|
|
|
|
|
|
string VSlicingNode::_getTypeName () const
|
|
{ return "VSlicingNode"; }
|
|
|
|
// -----------------------------------------------------------------------------------------------//
|
|
// Class : DSlicingNode
|
|
// -----------------------------------------------------------------------------------------------//
|
|
|
|
int DSlicingNode::_count = 0;
|
|
int DSlicingNode::_countAll = 0;
|
|
|
|
|
|
DSlicingNode::DSlicingNode( unsigned int type
|
|
, NodeSets* nodeSets
|
|
, unsigned int alignment
|
|
, Instance* instance
|
|
, BoxSet* boxSet
|
|
): SlicingNode( type, nodeSets, alignment, boxSet )
|
|
, _instance(instance)
|
|
{}
|
|
|
|
|
|
DSlicingNode::~DSlicingNode(){}
|
|
|
|
|
|
DSlicingNode* DSlicingNode::create( NodeSets* nodeSets
|
|
, unsigned int alignment
|
|
, Instance* instance
|
|
, BoxSet* boxSet
|
|
)
|
|
{
|
|
_count++;
|
|
_countAll++;
|
|
return new DSlicingNode( DeviceSNode, nodeSets, alignment, instance, boxSet );
|
|
}
|
|
|
|
|
|
void DSlicingNode::print() const
|
|
{
|
|
cerr << "- Print from Slicing Node - " << endl;
|
|
cerr << "SlicingType: Device Node" << endl;
|
|
if (this->isAlignLeft ()){ cerr << "Alignment : Left" << endl; }
|
|
else if (this->isAlignCenter()){ cerr << "Alignment : Middle" << endl; }
|
|
else if (this->isAlignRight ()){ cerr << "Alignment : Right" << endl; }
|
|
else if (this->isAlignTop ()){ cerr << "Alignment : Top" << endl; }
|
|
else if (this->isAlignBottom()){ cerr << "Alignment : Bottom" << endl; }
|
|
else { cerr << "Alignment : Unknown" << endl; }
|
|
cerr << "NFingers : " << getNFing() << endl;
|
|
if (_instance != NULL){
|
|
cerr << "Instance : " << _instance << endl;
|
|
} else {
|
|
cerr << "Instance : None" << endl;
|
|
}
|
|
SlicingNode::print();
|
|
}
|
|
|
|
|
|
DSlicingNode* DSlicingNode::clone( unsigned int tr )
|
|
{
|
|
DSlicingNode* node = DSlicingNode::create( _nodeSets->clone()
|
|
, this->getAlignment()
|
|
, this->getInstance()
|
|
, this->getBoxSet()
|
|
);
|
|
node->setPreset(this->getPreset());
|
|
node->setSet (this->getSet() );
|
|
node->setPlaced(this->getPlaced());
|
|
return node;
|
|
}
|
|
|
|
|
|
void DSlicingNode::setNFing( int nfing )
|
|
{
|
|
if (_nodeSets->find(nfing) != _nodeSets->end()){
|
|
_boxSet = (*_nodeSets->find(nfing));
|
|
} else {
|
|
_boxSet = (*_nodeSets->begin());
|
|
}
|
|
}
|
|
|
|
|
|
int DSlicingNode::getNFing() const
|
|
{
|
|
if (_boxSet != NULL) { return _boxSet->getNFing(); }
|
|
else { return 1; }
|
|
}
|
|
|
|
|
|
double DSlicingNode::getStartParameter() const
|
|
{
|
|
return _nodeSets->getStartParameter();
|
|
}
|
|
|
|
|
|
double DSlicingNode::getStepParameter() const
|
|
{
|
|
return _nodeSets->getStepParameter();
|
|
}
|
|
|
|
|
|
double DSlicingNode::getCountParameter() const
|
|
{
|
|
return _nodeSets->getCountParameter();
|
|
}
|
|
|
|
|
|
void DSlicingNode::_place( DbU::Unit x, DbU::Unit y, bool replace )
|
|
{
|
|
cdebug_log(536,1) << "void DSlicingNode::_place( DbU::Unit x, DbU::Unit y, bool replace )" << endl;
|
|
if (replace){
|
|
SlicingNode::place(x,y);
|
|
if (_instance != NULL){
|
|
Cell* model = _instance->getMasterCell();
|
|
_instance->setTransformation(Transformation( _x - model->getAbutmentBox().getXMin(), _y - model->getAbutmentBox().getYMin()));
|
|
_instance->setPlacementStatus(Instance::PlacementStatus::PLACED);
|
|
}
|
|
} else {
|
|
if (isSet()){
|
|
SlicingNode::place(x,y);
|
|
|
|
if (_instance != NULL){
|
|
Cell* model = _instance->getMasterCell();
|
|
Device* dev = dynamic_cast<Device*>(model);
|
|
|
|
if (dev) {
|
|
TransistorFamily* tf = dynamic_cast<TransistorFamily*>(dev);
|
|
if (tf) {
|
|
tf->setNfing( this->getNFing() );
|
|
FormFactorParameter* pff = NULL;
|
|
if ( (pff = dynamic_cast<FormFactorParameter*>(tf->getParameter("M"))) != NULL ) {
|
|
pff->setValue( tf->getNfing() );
|
|
}
|
|
shared_ptr<LayoutGenerator> layoutGenerator ( new LayoutGenerator() );
|
|
layoutGenerator->setDevice(dev);
|
|
layoutGenerator->drawLayout();
|
|
}
|
|
}
|
|
_instance->setTransformation(Transformation( _x - model->getAbutmentBox().getXMin(), _y - model->getAbutmentBox().getYMin()));
|
|
_instance->setPlacementStatus(Instance::PlacementStatus::PLACED);
|
|
|
|
}
|
|
}
|
|
}
|
|
cdebug_tabw(536,-1);
|
|
}
|
|
|
|
|
|
void DSlicingNode::place( DbU::Unit x, DbU::Unit y )
|
|
{
|
|
DSlicingNode::_place(x, y);
|
|
}
|
|
|
|
|
|
void DSlicingNode::preDestroy()
|
|
{
|
|
_count--;
|
|
SlicingNode::preDestroy();
|
|
}
|
|
|
|
|
|
void DSlicingNode::destroy()
|
|
{
|
|
DSlicingNode::preDestroy();
|
|
delete(this);
|
|
}
|
|
|
|
|
|
void DSlicingNode::preRecursiveDestroy()
|
|
{
|
|
_count--;
|
|
SlicingNode::preRecursiveDestroy();
|
|
}
|
|
|
|
|
|
void DSlicingNode::recursiveDestroy()
|
|
{
|
|
DSlicingNode::preRecursiveDestroy();
|
|
delete(this);
|
|
}
|
|
|
|
|
|
OpenChams::SlicingNode* DSlicingNode::toOpenChams()
|
|
{
|
|
OpenChams::SlicingNode* dnode = OpenChams::DSlicingNode::create(_instance->getName()._getString());
|
|
if ( isAlignLeft() ){ dnode->setAlignment("AlignLeft" ); }
|
|
else if ( isAlignRight() ){ dnode->setAlignment("AlignRight" ); }
|
|
else if ( isAlignCenter() ){ dnode->setAlignment("AlignCenter" ); }
|
|
else if ( isAlignTop() ){ dnode->setAlignment("AlignTop" ); }
|
|
else if ( isAlignBottom() ){ dnode->setAlignment("AlignBottom" ); }
|
|
else { dnode->setAlignment("UnknownAlignment"); }
|
|
|
|
string strue = "true";
|
|
string sfalse = "false";
|
|
if( isPreset() ){ dnode->setPreset( strue ); }
|
|
else { dnode->setPreset( sfalse ); }
|
|
dnode->setX ( _x );
|
|
dnode->setY ( _y );
|
|
dnode->setNFing ( getNFing() );
|
|
dnode->setStart ( getStartParameter() );
|
|
dnode->setStep ( getStepParameter() );
|
|
dnode->setCount ( getCountParameter() );
|
|
|
|
return dnode;
|
|
}
|
|
|
|
|
|
bool DSlicingNode::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 ){
|
|
if ( (_x == 0) && (_y == 0) ){
|
|
cpt++;
|
|
if ( cpt < 2 ) { initialPlacement = true; }
|
|
}
|
|
else { initialPlacement = true; }
|
|
}
|
|
return initialPlacement;
|
|
}
|
|
|
|
|
|
void DSlicingNode::setGCell( Anabatic::GCell* gcell )
|
|
{
|
|
cdebug_log(535,0) << "DSlicingNode::setGCell(Anabatic::GCell*) " << gcell << endl;
|
|
|
|
if (getParent() != NULL) {
|
|
if (getParent()->getType() == HorizontalSNode) {
|
|
if (getAlignment() == AlignLeft) {
|
|
Anabatic::GCell* rightc = gcell->vcut( getX() + getWidth() );
|
|
_gcell = gcell;
|
|
rightc->setType( Anabatic::Flags::StrutGCell );
|
|
} else if (getAlignment() == AlignCenter) {
|
|
_gcell = gcell->vcut( getX() );
|
|
Anabatic::GCell* rightc = _gcell->vcut( this->getX() + this->getWidth() );
|
|
gcell->setType ( Anabatic::Flags::StrutGCell );
|
|
rightc->setType( Anabatic::Flags::StrutGCell );
|
|
} else if (getAlignment() == AlignRight ){
|
|
_gcell = gcell->vcut( getX() );
|
|
gcell->setType( Anabatic::Flags::StrutGCell );
|
|
}
|
|
} else if (getParent()->getType() == VerticalSNode) {
|
|
if (getAlignment() == AlignBottom){
|
|
Anabatic::GCell* topc = gcell->hcut(this->getY()+this->getHeight());
|
|
_gcell = gcell;
|
|
topc->setType( Anabatic::Flags::StrutGCell );
|
|
} else if (getAlignment() == AlignCenter) {
|
|
_gcell = gcell->hcut( getY() );
|
|
Anabatic::GCell* topc = _gcell->hcut( getY() + getHeight() );
|
|
gcell->setType( Anabatic::Flags::StrutGCell );
|
|
topc->setType ( Anabatic::Flags::StrutGCell );
|
|
} else if (getAlignment() == AlignTop) {
|
|
_gcell = gcell->hcut( this->getY() );
|
|
gcell->setType( Anabatic::Flags::StrutGCell );
|
|
}
|
|
} else {
|
|
_gcell = gcell;
|
|
}
|
|
} else {
|
|
_gcell = gcell;
|
|
}
|
|
if (_gcell) {
|
|
if (dynamic_cast<Device*>(_instance->getMasterCell())){
|
|
_gcell->setType( Anabatic::Flags::DeviceGCell );
|
|
} else {
|
|
_gcell->setType( Anabatic::Flags::MatrixGCell );
|
|
if( (_gcell->getWidth() > Anabatic::Session::getSliceHeight())
|
|
and(_gcell->getHeight() > Anabatic::Session::getSliceHeight()) ) {
|
|
_gcell->doGrid();
|
|
}
|
|
}
|
|
}
|
|
|
|
cdebug_log(535,0) << "> Device:" << _instance << endl;
|
|
cdebug_log(535,0) << "> GCell: " << _gcell << endl;
|
|
}
|
|
|
|
|
|
bool DSlicingNode::isSame ( SlicingNode* node, unsigned int flags ) const
|
|
{
|
|
bool isSame = _nodeSets->compare( node->getNodeSets(), flags );
|
|
if (not isSame and (flags & ShowDiff))
|
|
cerr << "DSlicingNode::isSame() Check " << this << " vs. " << node << endl;
|
|
return isSame;
|
|
}
|
|
|
|
|
|
bool DSlicingNode::isSymmetric( SlicingNode* node, unsigned int symmetryType, unsigned int flags ) const
|
|
{
|
|
bool isSame = _nodeSets->compare( node->getNodeSets(), flags );
|
|
if (not isSame and (flags & ShowDiff))
|
|
cerr << "[WARNING] DSlicingNode::isSymmetric(): Different nodesets Check " << this << " vs. " << node << endl;
|
|
if (_instance != NULL){
|
|
Cell* model1 = _instance->getMasterCell();
|
|
Cell* model2 = node->getInstance()->getMasterCell();
|
|
|
|
Device* dev1 = dynamic_cast<Device*>(model1);
|
|
Device* dev2 = dynamic_cast<Device*>(model2);
|
|
if ((dev1 != NULL) && (dev2 !=NULL)){
|
|
CommonSourcePair* csp1 = dynamic_cast<CommonSourcePair*>(model1);
|
|
DifferentialPair* dp1 = dynamic_cast<DifferentialPair*>(model1);
|
|
Transistor* ts1 = dynamic_cast<Transistor*>(model1);
|
|
|
|
CommonSourcePair* csp2 = dynamic_cast<CommonSourcePair*>(model2);
|
|
DifferentialPair* dp2 = dynamic_cast<DifferentialPair*>(model2);
|
|
Transistor* ts2 = dynamic_cast<Transistor*>(model2);
|
|
|
|
if ((csp1 != NULL) && (csp2 != NULL)) isSame = csp1->isSame(csp2);
|
|
else if ((dp1 != NULL) && (dp2 != NULL)) isSame = dp1->isSame(dp2);
|
|
else if ((ts1 != NULL) && (ts2 != NULL)) isSame = ts1->isSame(ts2);
|
|
else isSame = false;
|
|
}
|
|
if (not(isSame)) cerr << "[WARNING] DSlicingNode::isSymmetric(): Different devices. Check " << this << " vs. " << node << endl;
|
|
}
|
|
return isSame;
|
|
}
|
|
|
|
|
|
void DSlicingNode::updateMatrixGCellPosition()
|
|
{
|
|
DbU::Unit tx = getX()-_gcell->getXMin();
|
|
DbU::Unit ty = getY()-_gcell->getYMin();
|
|
Anabatic::GCell* ygcell = _gcell;
|
|
Anabatic::GCell* xgcell = ygcell;
|
|
while (ygcell){
|
|
while(xgcell){
|
|
xgcell->setSouthWestCorner( xgcell->getXMin()+tx, xgcell->getYMin()+ty );
|
|
if (xgcell->getEast()->isMatrix()) xgcell = xgcell->getEast();
|
|
else xgcell = NULL;
|
|
}
|
|
if (ygcell->getNorth()->isMatrix()) ygcell = ygcell->getNorth();
|
|
else ygcell = NULL;
|
|
xgcell = ygcell;
|
|
}
|
|
}
|
|
|
|
|
|
void DSlicingNode::updateMatrixGContacts()
|
|
{
|
|
Anabatic::GCell* ygcell = _gcell;
|
|
Anabatic::GCell* xgcell = ygcell;
|
|
while (ygcell){
|
|
while(xgcell){
|
|
xgcell->updateGContacts( Anabatic::Flags::Vertical|Anabatic::Flags::Horizontal );
|
|
if (xgcell->getEast()->isMatrix()) xgcell = xgcell->getEast();
|
|
else xgcell = NULL;
|
|
}
|
|
if (ygcell->getNorth()->isMatrix()) ygcell = ygcell->getNorth();
|
|
else ygcell = NULL;
|
|
xgcell = ygcell;
|
|
}
|
|
}
|
|
|
|
|
|
void DSlicingNode::updateGCellPosition()
|
|
{
|
|
cdebug_log(535,0) << "DSlicingNode::updateGCellPosition() " << _gcell << endl;
|
|
|
|
if (_gcell) {
|
|
if (_parent) {
|
|
if (_parent->getType() == HorizontalSNode) {
|
|
DbU::Unit hpitch = _rg->getHorizontalPitch();
|
|
|
|
if (getAlignment() == AlignLeft) {
|
|
_gcell->getEastNMatrix()->setSouthWestCorner( getX()+getWidth(), getY() );
|
|
_gcell->getEastNMatrix()->forceEdgesCapacities( floor((_parent->getWidth()-getWidth())/hpitch)
|
|
, floor(getHeight()/hpitch)
|
|
);
|
|
} else if (getAlignment() == AlignCenter) {
|
|
_gcell->getWest()->setSouthWestCorner( _parent->getX(), getY() );
|
|
_gcell->getWest()->forceEdgesCapacities( floor((_parent->getWidth()-getWidth())/(2*hpitch))
|
|
, floor(getHeight()/(2*hpitch))
|
|
);
|
|
|
|
_gcell->getEastNMatrix()->setSouthWestCorner( getX()+getWidth(), getY() );
|
|
_gcell->getEastNMatrix()->forceEdgesCapacities( floor((_parent->getWidth()-getWidth())/(2*hpitch))
|
|
, floor(getHeight()/(2*hpitch))
|
|
);
|
|
} else if (getAlignment() == AlignRight) {
|
|
_gcell->getWest()->setSouthWestCorner( _parent->getX(), getY() );
|
|
_gcell->getWest()->forceEdgesCapacities( floor((_parent->getWidth()-getWidth())/hpitch)
|
|
, floor(getHeight()/hpitch)
|
|
);
|
|
|
|
}
|
|
} else if (_parent->getType() == VerticalSNode) {
|
|
DbU::Unit vpitch = _rg->getVerticalPitch();
|
|
|
|
if (getAlignment() == AlignBottom) {
|
|
_gcell->getNorthNMatrix()->setSouthWestCorner( getX(), getY()+getHeight() );
|
|
_gcell->getNorthNMatrix()->forceEdgesCapacities( floor((_parent->getHeight()-getHeight())/vpitch)
|
|
, floor(getWidth()/vpitch)
|
|
);
|
|
} else if (getAlignment() == AlignCenter) {
|
|
_gcell->getSouth()->setSouthWestCorner( getX(), _parent->getY() );
|
|
_gcell->getSouth()->forceEdgesCapacities( floor((_parent->getHeight()-getHeight())/(2*vpitch))
|
|
, floor(getWidth()/(2*vpitch))
|
|
);
|
|
|
|
_gcell->getNorthNMatrix()->setSouthWestCorner( getX(), getY()+getHeight() );
|
|
_gcell->getNorthNMatrix()->forceEdgesCapacities( floor((_parent->getHeight()-getHeight())/(2*vpitch))
|
|
, floor(getWidth()/(2*vpitch))
|
|
);
|
|
} else if (getAlignment() == AlignTop) {
|
|
_gcell->getSouth()->setSouthWestCorner( getX(), _parent->getY() );
|
|
_gcell->getSouth()->forceEdgesCapacities( floor((_parent->getHeight()-getHeight())/vpitch)
|
|
, floor(getWidth()/vpitch)
|
|
);
|
|
}
|
|
}
|
|
}
|
|
if (_gcell->isMatrix()) this->updateMatrixGCellPosition();
|
|
else _gcell->setSouthWestCorner( getX(), getY() );
|
|
cdebug_log(535,0) << "| Updated:" << _gcell << endl;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void DSlicingNode::updateGContacts()
|
|
{
|
|
cdebug_log(535,0) << "DSlicingNode::updateGContacts() " << _gcell << endl;
|
|
|
|
if (_gcell) {
|
|
if (_parent) {
|
|
if (_parent->getType() == HorizontalSNode) {
|
|
|
|
if (getAlignment() == AlignLeft) {
|
|
_gcell->getEastNMatrix()->updateGContacts( Anabatic::Flags::Vertical|Anabatic::Flags::Horizontal );
|
|
|
|
} else if (getAlignment() == AlignCenter) {
|
|
_gcell->getWest()->updateGContacts( Anabatic::Flags::Vertical|Anabatic::Flags::Horizontal );
|
|
_gcell->getEastNMatrix()->updateGContacts( Anabatic::Flags::Vertical|Anabatic::Flags::Horizontal );
|
|
|
|
} else if (getAlignment() == AlignRight) {
|
|
_gcell->getWest()->updateGContacts( Anabatic::Flags::Vertical|Anabatic::Flags::Horizontal );
|
|
|
|
}
|
|
} else if (_parent->getType() == VerticalSNode) {
|
|
|
|
if (getAlignment() == AlignBottom) {
|
|
_gcell->getNorthNMatrix()->updateGContacts( Anabatic::Flags::Vertical|Anabatic::Flags::Horizontal );
|
|
} else if (getAlignment() == AlignCenter) {
|
|
_gcell->getSouth()->updateGContacts( Anabatic::Flags::Vertical|Anabatic::Flags::Horizontal );
|
|
_gcell->getNorthNMatrix()->updateGContacts( Anabatic::Flags::Vertical|Anabatic::Flags::Horizontal );
|
|
|
|
} else if (getAlignment() == AlignTop) {
|
|
_gcell->getSouth()->updateGContacts( Anabatic::Flags::Vertical|Anabatic::Flags::Horizontal );
|
|
}
|
|
}
|
|
}
|
|
if (_gcell->isMatrix()) this->updateMatrixGContacts();
|
|
else _gcell->updateGContacts( Anabatic::Flags::Vertical|Anabatic::Flags::Horizontal );
|
|
cdebug_log(535,0) << "| Updated:" << _gcell << endl;
|
|
}
|
|
}
|
|
|
|
|
|
void DSlicingNode::restrictDevices()
|
|
{
|
|
if (_gcell){
|
|
Anabatic::Vertex* vertex = _gcell->getObserver< Anabatic::Vertex>( Anabatic::GCell::Observable::Vertex);
|
|
vertex->setRestricted();
|
|
|
|
if (!vertex->hasValidStamp()){
|
|
if ((_gcell->getWidth() > _gcell->getHeight())||(_gcell->getWidth() == _gcell->getHeight())) {
|
|
vertex->unsetFlags(Anabatic::Vertex::iVertical);
|
|
vertex->setFlags(Anabatic::Vertex::iHorizontal);
|
|
} else {
|
|
vertex->unsetFlags(Anabatic::Vertex::iHorizontal);
|
|
vertex->setFlags(Anabatic::Vertex::iVertical );
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
void DSlicingNode::printLine() const
|
|
{
|
|
cerr << "Instance: " << _instance << ", " ;
|
|
SlicingNode::printLine();
|
|
}
|
|
|
|
|
|
string DSlicingNode::_getString () const
|
|
{
|
|
string s = Super::_getString();
|
|
s.insert( s.size()-1, " "+getString(_instance->getName()));
|
|
return s;
|
|
}
|
|
|
|
|
|
string DSlicingNode::_getTypeName () const
|
|
{ return "DSlicingNode"; }
|
|
|
|
|
|
bool DSlicingNode::isAnalog () const
|
|
{
|
|
if (_instance){
|
|
Cell* model = _instance->getMasterCell();
|
|
Device* dev = dynamic_cast<Device*>(model);
|
|
if (dev) return true;
|
|
else return false;
|
|
} else return false;
|
|
}
|
|
|
|
|
|
bool DSlicingNode::isDigital () const
|
|
{
|
|
return (not (isAnalog()));
|
|
}
|
|
|
|
|
|
bool DSlicingNode::checkCellInstances ( Cell* cell ){
|
|
if (_instance){
|
|
if (cell->getInstance(_instance->getName())) return true;
|
|
else return false;
|
|
} else return false;
|
|
}
|
|
// -----------------------------------------------------------------------------------------------//
|
|
// Class : RHVSlicingNode
|
|
// -----------------------------------------------------------------------------------------------//
|
|
|
|
int RHVSlicingNode::_count = 0;
|
|
int RHVSlicingNode::_countAll = 0;
|
|
|
|
|
|
RHVSlicingNode::RHVSlicingNode(): SlicingNode( RoutingSNode, NodeSets::create(), UnknownAlignment, NULL )
|
|
, _railInstance(NULL)
|
|
{
|
|
this->setPreset(Preset);
|
|
this->setSet (Set );
|
|
this->setOverCell(OverCell);
|
|
_wireOccupation = ChannelRouting::create();
|
|
}
|
|
|
|
|
|
RHVSlicingNode::~RHVSlicingNode(){}
|
|
|
|
|
|
void RHVSlicingNode::print() const
|
|
{
|
|
cerr << "- Print from Slicing Node - " << endl;
|
|
if (_railInstance) cerr << "RailInstace: " << _railInstance << endl;
|
|
SlicingNode::print();
|
|
}
|
|
|
|
|
|
void RHVSlicingNode::_setGlobalSize ( DbU::Unit height, DbU::Unit width ){}
|
|
|
|
|
|
void RHVSlicingNode::preDestroy()
|
|
{
|
|
_count--;
|
|
SlicingNode::preDestroy();
|
|
if(_wireOccupation) _wireOccupation->destroy();
|
|
}
|
|
|
|
|
|
void RHVSlicingNode::destroy()
|
|
{
|
|
RHVSlicingNode::preDestroy();
|
|
delete(this);
|
|
}
|
|
|
|
|
|
void RHVSlicingNode::preRecursiveDestroy()
|
|
{
|
|
_count--;
|
|
SlicingNode::preRecursiveDestroy();
|
|
}
|
|
|
|
|
|
void RHVSlicingNode::recursiveDestroy()
|
|
{
|
|
RHVSlicingNode::preRecursiveDestroy();
|
|
delete(this);
|
|
}
|
|
|
|
|
|
void RHVSlicingNode::resetSize()
|
|
{
|
|
_boxSet->setHeight( _minHeight );
|
|
_boxSet->setWidth ( _minWidth );
|
|
}
|
|
|
|
|
|
bool RHVSlicingNode::isSame( SlicingNode* node, unsigned int flags ) const
|
|
{
|
|
return ( (this->getHeight() == node->getHeight())&& (this->getWidth() == node->getWidth()) );
|
|
}
|
|
|
|
|
|
bool RHVSlicingNode::isSymmetric( SlicingNode* node, unsigned int symmetryType, unsigned int flags ) const
|
|
{
|
|
return ( (this->getHeight() == node->getHeight())&& (this->getWidth() == node->getWidth()) );
|
|
}
|
|
|
|
|
|
void RHVSlicingNode::setRailInstance(Hurricane::Instance* i)
|
|
{
|
|
_railInstance = i;
|
|
}
|
|
|
|
|
|
void RHVSlicingNode::_place( DbU::Unit x, DbU::Unit y, bool replace )
|
|
{
|
|
SlicingNode::_place(x,y,replace);
|
|
if (_railInstance){
|
|
Net* net = NULL;
|
|
int t = 0;
|
|
for (Net* n : _railInstance->getMasterCell()->getNets()) {
|
|
net = n;
|
|
t++;
|
|
}
|
|
if (t != 1) cerr << "Error(void RHVSlicingNode::_place( DbU::Unit x, DbU::Unit y, bool replace )): Several Nets in Rail Instance Cell." << endl;
|
|
Component* component = NULL;
|
|
t = 0;
|
|
for (Component* c : net->getComponents()){
|
|
component = c;
|
|
t++;
|
|
}
|
|
if (t != 1) cerr << "Error(void RHVSlicingNode::_place( DbU::Unit x, DbU::Unit y, bool replace )): Several Components in Rail Instance Cell." << endl;
|
|
|
|
Horizontal* h = dynamic_cast<Horizontal*>(component);
|
|
Vertical* v = dynamic_cast<Vertical*> (component);
|
|
UpdateSession::open();
|
|
if (h){
|
|
h->setDxSource(0);
|
|
h->setDxTarget(getRootWidth());
|
|
_railInstance->getMasterCell()->setAbutmentBox(Box( 0, 0, getRootWidth(), getHeight() ));
|
|
_railInstance->setTransformation(Transformation( _cell->getAbutmentBox().getXMin(), getY() ) );
|
|
} else if (v){
|
|
v->setDySource(0);
|
|
v->setDyTarget(getRootHeight());
|
|
_railInstance->getMasterCell()->setAbutmentBox(Box( 0, 0, getWidth(), getRootHeight() ));
|
|
_railInstance->setTransformation(Transformation( getX(), _cell->getAbutmentBox().getYMin() ) );
|
|
} else {
|
|
cerr << "Error(void RHVSlicingNode::_place( DbU::Unit x = 0, DbU::Unit y = 0, bool replace = false )): Unknown segment type." << endl;
|
|
}
|
|
_railInstance->setPlacementStatus(Instance::PlacementStatus::PLACED);
|
|
UpdateSession::close();
|
|
}
|
|
}
|
|
|
|
|
|
void RHVSlicingNode::addWireOccupation( DbU::Unit min, DbU::Unit max )
|
|
{
|
|
//cerr << "addWireOccupation min:" << DbU::getPhysical(min, DbU::Micro) << ", max:" << DbU::getPhysical(max, DbU::Micro) << ", MaxCount: " << _wireOccupation->getMaxCount() << endl;
|
|
if (_wireOccupation) {
|
|
if (min == max){/*
|
|
RHSlicingNode* h = dynamic_cast<RHSlicingNode*>(this);
|
|
RVSlicingNode* v = dynamic_cast<RVSlicingNode*>(this);
|
|
if (h) {
|
|
_wireOccupation->insertChannel(getX(), getX()+getWidth());
|
|
} else if (v) {
|
|
_wireOccupation->insertChannel(getY(), getY()+getHeight());
|
|
}*/
|
|
} else {
|
|
_wireOccupation->insertChannel(min, max);
|
|
}
|
|
}
|
|
//cerr << "NewMaxCount:" << _wireOccupation->getMaxCount() << endl;
|
|
//_wireOccupation->print();
|
|
//printLine();
|
|
}
|
|
|
|
|
|
void RHVSlicingNode::resetWireOccupation()
|
|
{
|
|
if (_wireOccupation) _wireOccupation->reset();
|
|
}
|
|
|
|
|
|
int RHVSlicingNode::getMaxWireOccupation()
|
|
{
|
|
if (_wireOccupation) return _wireOccupation->getMaxCount()+1;
|
|
else return 0;
|
|
}
|
|
|
|
|
|
// Error Message Methods
|
|
unsigned int RHVSlicingNode::getAlignment() const
|
|
{
|
|
cerr << " Error(unsigned int getAlignment () const): Routing does not have centering type." << endl;
|
|
return UnknownAlignment;
|
|
}
|
|
|
|
|
|
NodeSets* RHVSlicingNode::getNodeSets() const
|
|
{
|
|
cerr << " Error(NodeSets* getNodeSets() const): Routing does not have different dimensions." << endl;
|
|
return NULL;
|
|
}
|
|
|
|
|
|
BoxSet* RHVSlicingNode::getPairH( DbU::Unit height ) const
|
|
{
|
|
cerr << " Error(BoxSet* getPairH ( DbU::Unit height ) const): Routing does not have different dimensions." << endl;
|
|
return _boxSet;
|
|
}
|
|
|
|
|
|
BoxSet* RHVSlicingNode::getPairHW( DbU::Unit height, DbU::Unit width ) const
|
|
{
|
|
cerr << " Error(BoxSet* RHVSlicingNode::getPairHW( DbU::Unit height, DbU::Unit width ) const): Routing does not have different dimensions." << endl;
|
|
return _boxSet;
|
|
}
|
|
|
|
|
|
void RHVSlicingNode::setPairH( DbU::Unit height )
|
|
{
|
|
cerr << " Error(void setPairH ( DbU::Unit height )): Routing does not have different dimensions." << endl;
|
|
}
|
|
|
|
|
|
void RHVSlicingNode::setPairHW( DbU::Unit height, DbU::Unit width )
|
|
{
|
|
cerr << " Error(void setPairHW ( DbU::Unit height, DbU::Unit width )): Routing does not have different dimensions." << endl;
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------------------------//
|
|
// Class : RHSlicingNode
|
|
// -----------------------------------------------------------------------------------------------//
|
|
|
|
|
|
RHSlicingNode::RHSlicingNode( DbU::Unit height ): RHVSlicingNode()
|
|
{
|
|
RHBoxSet* node = RHBoxSet::create(height);
|
|
_nodeSets->push_back(node);
|
|
_boxSet = node;
|
|
_minHeight = height;
|
|
if (_parent != NULL){
|
|
_minWidth = _parent->getWidth();
|
|
} else {
|
|
_minWidth = 0;
|
|
}
|
|
|
|
DbU::Unit hpitch = _rg->getHorizontalPitch();
|
|
if (height % hpitch)
|
|
cerr << Warning( "RHSlicingNode::RHSlicingNode(): On %s, height is not pitched (%s, pitch:%s)."
|
|
, getString(this).c_str()
|
|
, DbU::getValueString(height).c_str()
|
|
, DbU::getValueString(hpitch).c_str()
|
|
) << endl;
|
|
}
|
|
|
|
|
|
RHSlicingNode::RHSlicingNode( Hurricane::Instance* i ): RHVSlicingNode()
|
|
{
|
|
RHBoxSet* node = RHBoxSet::create(i->getMasterCell()->getAbutmentBox().getHeight());
|
|
_nodeSets->push_back(node);
|
|
_boxSet = node;
|
|
_minHeight = i->getMasterCell()->getAbutmentBox().getHeight();
|
|
setRailInstance(i);
|
|
if (_parent != NULL){
|
|
_minWidth = _parent->getWidth();
|
|
} else {
|
|
_minWidth = 0;
|
|
}
|
|
}
|
|
|
|
|
|
RHSlicingNode::~RHSlicingNode(){};
|
|
|
|
|
|
RHSlicingNode* RHSlicingNode::create( DbU::Unit height )
|
|
{
|
|
_count++;
|
|
_countAll++;
|
|
|
|
return new RHSlicingNode(height);
|
|
}
|
|
|
|
|
|
RHSlicingNode* RHSlicingNode::create( Hurricane::Net* net,Hurricane::Layer* layer, int npitch, string cname, string iname )
|
|
{
|
|
//cerr << "RHSlicingNode::Create (Layer and co)" << endl;
|
|
Cell* cell = Hurricane::Cell::create(Hurricane::DataBase::getDB()->getRootLibrary(), cname);
|
|
Net* subnet = Hurricane::Net::create(cell, net->getName());
|
|
DbU::Unit height = CRL::AllianceFramework::get()->getRoutingGauge()->getHorizontalPitch()* npitch;
|
|
subnet->setExternal(true);
|
|
Hurricane::Horizontal* h = Hurricane::Horizontal::create( subnet, layer, height/2, height );
|
|
NetExternalComponents::setExternal( h );
|
|
Hurricane::Instance* instance = Hurricane::Instance::create(_cell, iname, cell);
|
|
instance->getPlug(subnet)->setNet(net);
|
|
cell->setAbutmentBox(Box(0, 0, 0, height));
|
|
SlicingNode::addRailSegments(h);
|
|
return new RHSlicingNode(instance);
|
|
}
|
|
|
|
|
|
RHSlicingNode* RHSlicingNode::clone( unsigned int tr )
|
|
{
|
|
RHSlicingNode* node = RHSlicingNode::create(this->getHeight());
|
|
return node;
|
|
}
|
|
|
|
|
|
DbU::Unit RHSlicingNode::getWidth () const
|
|
{
|
|
//cerr << "DbU::Unit RHSlicingNode::getWidth () const" << endl;
|
|
if ( (_parent) ){
|
|
return _parent->getWidth();
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
void RHSlicingNode::setHeight( DbU::Unit height )
|
|
{
|
|
_boxSet->setHeight( height );
|
|
|
|
DbU::Unit hpitch = _rg->getHorizontalPitch();
|
|
if (height % hpitch)
|
|
cerr << Warning( "RHSlicingNode::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;
|
|
}
|
|
|
|
|
|
OpenChams::SlicingNode* RHSlicingNode::toOpenChams()
|
|
{
|
|
OpenChams::SlicingNode* rnode = OpenChams::RSlicingNode::create(this->getHeight());
|
|
return rnode;
|
|
}
|
|
|
|
|
|
void RHSlicingNode:: estimateChannelsSize()
|
|
{
|
|
if (getRailInstance() == NULL){
|
|
if (_gcell){
|
|
/*ChannelRouting* c = ChannelRouting::create();
|
|
for ( Contact* contact : _gcell->getGContacts() ) {
|
|
DbU::Unit xmin = contact->getX();
|
|
DbU::Unit xmax = contact->getX();
|
|
NetRoutingState* state = NetRoutingExtension::get( contact->getNet() );
|
|
DbU::Unit wpitch = 1;
|
|
if (state) wpitch = state->getWPitch();
|
|
for ( Component* comp: contact->getSlaveComponents() ){
|
|
Vertical* v = dynamic_cast<Vertical*>(comp);
|
|
Horizontal* h = dynamic_cast<Horizontal*>(comp);
|
|
if (v){
|
|
if (xmin > v->getX()) xmin = v->getX();
|
|
if (xmax < v->getX()) xmax = v->getX();
|
|
|
|
if (xmin < getX()) xmin = getX();
|
|
if (xmax > getX()+getWidth()) xmax = getX()+getWidth();
|
|
|
|
} else if (h){
|
|
xmin = getX();
|
|
xmax = getX()+getWidth();
|
|
}
|
|
}
|
|
c->insertChannel(xmin, xmax, wpitch);
|
|
}*/
|
|
|
|
/*if (_rg){
|
|
DbU::Unit hpitch = _rg->getHorizontalPitch();
|
|
|
|
if ( c->getMaxCount() > 0 ){
|
|
int occupancyH = c->getMaxCount()+1; //+1 for having enough space
|
|
if (occupancyH%2 != 0) occupancyH++;
|
|
this->updateMasterSize( occupancyH*hpitch );
|
|
} else this->updateMasterSize( 2*hpitch );
|
|
this->setRoutingEstimated(RoutingEstimated);
|
|
} else {
|
|
cerr << "Error(void RHSlicingNode::estimateChannelsSize()): Technology missing." << endl;
|
|
}*/
|
|
if (_rg){
|
|
DbU::Unit hpitch = _rg->getHorizontalPitch();
|
|
if ( getMaxWireOccupation()> 0 ){
|
|
int occupancyH = getMaxWireOccupation (); //+1 for having enough space
|
|
if (occupancyH%2 != 0) occupancyH++;
|
|
this->updateMasterSize( occupancyH*hpitch );
|
|
} else this->updateMasterSize( 2*hpitch );
|
|
this->setRoutingEstimated(RoutingEstimated);
|
|
} else {
|
|
cerr << "Error(void RHSlicingNode::estimateChannelsSize()): Technology missing." << endl;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void RHSlicingNode::_expandRoutingChannel ()
|
|
{
|
|
SlicingNode* master = this;
|
|
while ( master->getMaster() != NULL ) master = master->getMaster();
|
|
|
|
// cerr << "RHSlicingNode::_expandRoutingChannel() " << this
|
|
// << " to " << DbU::getValueString( master->getHeight() ) << endl;
|
|
|
|
setHeight( master->getHeight() );
|
|
setRoutingEstimated( RoutingEstimated );
|
|
}
|
|
|
|
|
|
void RHSlicingNode::expandRoutingChannel ( DbU::Unit height, DbU::Unit width )
|
|
{
|
|
// cerr << "RHSlicingNode::expandRoutingChannel(DbU::Unit h, DbU::Unit w) " << this
|
|
// << " to " << DbU::getValueString( height ) << endl;
|
|
|
|
setHeight( height );
|
|
setRoutingEstimated( RoutingEstimated );
|
|
}
|
|
|
|
|
|
void RHSlicingNode::updateMasterSize( DbU::Unit size )
|
|
{
|
|
SlicingNode* master = this;
|
|
while(master->getMaster() != NULL) master = master->getMaster();
|
|
if (master->getHeight() < size) master->setHeight(size);
|
|
}
|
|
|
|
|
|
void RHSlicingNode::setGCell( Anabatic::GCell* gcell )
|
|
{
|
|
_gcell = gcell;
|
|
if (_gcell) {
|
|
if (_railInstance) _gcell->setType( Anabatic::Flags::HRailGCell );
|
|
else _gcell->setType( Anabatic::Flags::HChannelGCell );
|
|
}
|
|
|
|
cdebug_log(535,0) << "RHSlicingNode::setGCell() " << _gcell << endl;
|
|
}
|
|
|
|
// Error Methods
|
|
void RHSlicingNode::setWidth( DbU::Unit width )
|
|
{
|
|
cerr << "Error(void RHSlicingNode::setWidth( DbU::Unit width )): Routing does not have width." << endl;
|
|
}
|
|
|
|
|
|
string RHSlicingNode::_getTypeName () const
|
|
{ return "RHSlicingNode"; }
|
|
|
|
|
|
// -----------------------------------------------------------------------------------------------//
|
|
// Class : RVSlicingNode
|
|
// -----------------------------------------------------------------------------------------------//
|
|
|
|
|
|
RVSlicingNode::RVSlicingNode( DbU::Unit width ): RHVSlicingNode()
|
|
{
|
|
RVBoxSet* node = RVBoxSet::create(width);
|
|
_nodeSets->push_back(node);
|
|
_boxSet = node;
|
|
_minWidth = width;
|
|
if (_parent != NULL){
|
|
_minHeight = _parent->getHeight();
|
|
} else {
|
|
_minHeight = 0;
|
|
}
|
|
|
|
DbU::Unit vpitch = _rg->getVerticalPitch();
|
|
if (width % vpitch)
|
|
cerr << Warning( "RVSlicingNode::RVSlicingNode(): On %s, width is not pitched (%s, pitch:%s)."
|
|
, getString(this).c_str()
|
|
, DbU::getValueString(width).c_str()
|
|
, DbU::getValueString(vpitch).c_str()
|
|
) << endl;
|
|
}
|
|
|
|
|
|
RVSlicingNode::RVSlicingNode( Hurricane::Instance* i ): RHVSlicingNode()
|
|
{
|
|
RVBoxSet* node = RVBoxSet::create(i->getMasterCell()->getAbutmentBox().getWidth());
|
|
_nodeSets->push_back(node);
|
|
_boxSet = node;
|
|
_minHeight = i->getMasterCell()->getAbutmentBox().getWidth();
|
|
setRailInstance(i);
|
|
if (_parent != NULL){
|
|
_minWidth = _parent->getWidth();
|
|
} else {
|
|
_minWidth = 0;
|
|
}
|
|
}
|
|
|
|
|
|
RVSlicingNode::~RVSlicingNode(){};
|
|
|
|
|
|
RVSlicingNode* RVSlicingNode::create( DbU::Unit width )
|
|
{
|
|
_count++;
|
|
_countAll++;
|
|
return new RVSlicingNode(width);
|
|
}
|
|
|
|
|
|
RVSlicingNode* RVSlicingNode::create( Hurricane::Net* net, Hurricane::Layer* layer, int npitch, string cname, string iname )
|
|
{
|
|
//cerr << "RVSlicingNode::Create (Layer and co)" << endl;
|
|
Cell* cell = Hurricane::Cell::create(Hurricane::DataBase::getDB()->getRootLibrary(), cname);
|
|
Net* subnet = Hurricane::Net::create(cell, net->getName());
|
|
|
|
DbU::Unit width = CRL::AllianceFramework::get()->getRoutingGauge()->getVerticalPitch()* npitch;
|
|
subnet->setExternal(true);
|
|
Hurricane::Vertical* v = Hurricane::Vertical::create( subnet, layer, width/2, width );
|
|
NetExternalComponents::setExternal( v );
|
|
Hurricane::Instance* instance = Hurricane::Instance::create(_cell, iname, cell);
|
|
instance->getPlug(subnet)->setNet(net);
|
|
cell->setAbutmentBox(Box(0, 0, width, 0));
|
|
SlicingNode::addRailSegments(v);
|
|
return new RVSlicingNode(instance);
|
|
}
|
|
|
|
|
|
RVSlicingNode* RVSlicingNode::clone( unsigned int tr )
|
|
{
|
|
RVSlicingNode* node = RVSlicingNode::create(this->getWidth());
|
|
return node;
|
|
}
|
|
|
|
|
|
DbU::Unit RVSlicingNode::getHeight () const
|
|
{
|
|
//cerr << "DbU::Unit RVSlicingNode::getHeight () const" << endl;
|
|
if ( (_parent) ){
|
|
return _parent->getHeight();
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
|
|
void RVSlicingNode::setWidth( DbU::Unit width )
|
|
{
|
|
_boxSet->setWidth( width );
|
|
}
|
|
|
|
|
|
OpenChams::SlicingNode* RVSlicingNode::toOpenChams()
|
|
{
|
|
OpenChams::SlicingNode* rnode = OpenChams::RSlicingNode::create(this->getWidth());
|
|
return rnode;
|
|
}
|
|
|
|
void RVSlicingNode::estimateChannelsSize()
|
|
{
|
|
if (getRailInstance() == NULL){
|
|
if (_gcell){
|
|
/*ChannelRouting* c = ChannelRouting::create();
|
|
for ( Contact* contact : _gcell->getGContacts() ) {
|
|
DbU::Unit ymin = contact->getY();
|
|
DbU::Unit ymax = contact->getY();
|
|
NetRoutingState* state = NetRoutingExtension::get( contact->getNet() );
|
|
DbU::Unit wpitch = 1;
|
|
if (state) wpitch = state->getWPitch();
|
|
for ( Component* comp: contact->getSlaveComponents() ){
|
|
Vertical* v = dynamic_cast<Vertical*>(comp);
|
|
Horizontal* h = dynamic_cast<Horizontal*>(comp);
|
|
if (h){
|
|
if (ymin > h->getY()) ymin = h->getY();
|
|
if (ymax < h->getY()) ymax = h->getY();
|
|
|
|
if (ymin < getY()) ymin = getY();
|
|
if (ymax > getY()+getHeight()) ymax = getY()+getHeight();
|
|
|
|
} else if (v){
|
|
ymin = getY();
|
|
ymax = getY()+getHeight();
|
|
}
|
|
}
|
|
c->insertChannel(ymin, ymax, wpitch);
|
|
}
|
|
|
|
if (_rg){
|
|
DbU::Unit vpitch = _rg->getVerticalPitch();
|
|
|
|
if ( c->getMaxCount() > 0 ){
|
|
int occupancyV = c->getMaxCount()+1; //+1 for having enough space
|
|
if (occupancyV%2 != 0) occupancyV++;
|
|
this->updateMasterSize(occupancyV*vpitch);
|
|
//this->setWidth(occupancyV*vpitch);
|
|
} else this->updateMasterSize(2*vpitch);
|
|
this->setRoutingEstimated(RoutingEstimated);
|
|
} else {
|
|
cerr << "Error(void RHSlicingNode::estimateChannelsSize ()): Technology missing." << endl;
|
|
}*/
|
|
|
|
|
|
if (_rg){
|
|
DbU::Unit vpitch = _rg->getVerticalPitch();
|
|
|
|
if ( getMaxWireOccupation() > 0 ){
|
|
int occupancyV = getMaxWireOccupation(); //+1 for having enough space
|
|
if (occupancyV%2 != 0) occupancyV++;
|
|
this->updateMasterSize(occupancyV*vpitch);
|
|
//this->setWidth(occupancyV*vpitch);
|
|
} else this->updateMasterSize(2*vpitch);
|
|
this->setRoutingEstimated(RoutingEstimated);
|
|
} else {
|
|
cerr << "Error(void RHSlicingNode::estimateChannelsSize ()): Technology missing." << endl;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void RVSlicingNode::_expandRoutingChannel ()
|
|
{
|
|
SlicingNode* master = this;
|
|
while(master->getMaster() != NULL) master = master->getMaster();
|
|
this->setWidth(master->getWidth());
|
|
this->setRoutingEstimated(RoutingEstimated);
|
|
}
|
|
|
|
|
|
void RVSlicingNode::expandRoutingChannel( DbU::Unit height, DbU::Unit width )
|
|
{
|
|
this->setWidth(width);
|
|
this->setRoutingEstimated(RoutingEstimated);
|
|
}
|
|
|
|
|
|
void RVSlicingNode::setGCell( Anabatic::GCell* gcell )
|
|
{
|
|
_gcell = gcell;
|
|
if (_gcell) {
|
|
if (_railInstance) _gcell->setType( Anabatic::Flags::VRailGCell );
|
|
else _gcell->setType( Anabatic::Flags::VChannelGCell );
|
|
}
|
|
|
|
cdebug_log(535,0) << "RVSlicingNode::setGCell() " << _gcell << endl;
|
|
}
|
|
|
|
|
|
void RVSlicingNode::updateMasterSize( DbU::Unit size )
|
|
{
|
|
SlicingNode* master = this;
|
|
while(master->getMaster() != NULL) master = master->getMaster();
|
|
if (master->getWidth() < size) master->setWidth(size);
|
|
}
|
|
|
|
|
|
// Error Methods
|
|
void RVSlicingNode::setHeight( DbU::Unit height )
|
|
{
|
|
cerr << "Error(void RVSlicingNode::setHeight( DbU::Unit height )): Routing does not have height." << endl;
|
|
}
|
|
|
|
|
|
string RVSlicingNode::_getTypeName () const
|
|
{ return "RVSlicingNode"; }
|
|
|
|
|
|
// -----------------------------------------------------------------------------------------------//
|
|
// Class : HVSetState
|
|
// -----------------------------------------------------------------------------------------------//
|
|
|
|
|
|
HVSetState::HVSetState( HVSlicingNode* node ): _HVSnode( node )
|
|
{
|
|
_currentSet = vector<size_t> ();
|
|
_nextSet = vector<size_t> ();
|
|
_nodeSets = NodeSets::create();
|
|
_counter = 1;
|
|
initSet();
|
|
initModulos();
|
|
}
|
|
|
|
|
|
HVSetState::~HVSetState(){}
|
|
|
|
|
|
NodeSets* HVSetState::getNodeSets()
|
|
{
|
|
_nodeSets->sort();
|
|
return _nodeSets;
|
|
}
|
|
|
|
|
|
void HVSetState::print()
|
|
{
|
|
int index = 0;
|
|
cerr << "currentSet:" << endl;
|
|
vector<size_t>::iterator it2 = _currentSet.begin();
|
|
for (vector<SlicingNode*>::const_iterator it = _HVSnode->getChildren().begin(); it != _HVSnode->getChildren().end(); it++){
|
|
NodeSets* node = (*it)->getNodeSets();
|
|
cerr << index << ": H = " << node->at((*it2))->getHeight() << ", W = " << node->at((*it2))->getWidth() << endl;
|
|
it2++;
|
|
index++;
|
|
}
|
|
cerr << "counter = " << _counter << endl;
|
|
cerr << "end counter = " << _modulos.back()<< endl;
|
|
cerr << "modulos:" << endl;
|
|
index = 0;
|
|
for (vector<int>::iterator it = _modulos.begin(); it != _modulos.end(); it++)
|
|
{
|
|
cerr << index << ": modulo = " << (*it) << endl;
|
|
index++;
|
|
}
|
|
_nodeSets->print();
|
|
}
|
|
|
|
|
|
void HVSetState::initSet()
|
|
{
|
|
_nextSet.clear();
|
|
for (vector<SlicingNode*>::const_iterator it = _HVSnode->getChildren().begin(); it != _HVSnode->getChildren().end(); it++){
|
|
if ( (*it)->isPreset() )
|
|
{ _nextSet.push_back((*it)->getNodeSets()->findIndex((*it)->getHeight(), (*it)->getWidth())); }
|
|
else
|
|
{ _nextSet.push_back(0); }
|
|
}
|
|
_currentSet = _nextSet;
|
|
}
|
|
|
|
|
|
void HVSetState::initModulos()
|
|
{
|
|
// -----------------------------------------------------------------------------------------------//
|
|
// Notes: Considering a horizontal/vertical node with X children and each children has N possibilities:
|
|
// child 0: N0 possibilities,
|
|
// child 1: N1 possibilities,
|
|
// .
|
|
// .
|
|
// .
|
|
// child X: NX possibilities.
|
|
// If a child is preset then, it only has 1 possibility and N = 1. So we have:
|
|
// number of possibilities to be studied = N0 * N1 * ... * NX.
|
|
// Children are seen like a <vector> and modulos are used to know when a child needs to choose its next possibility.
|
|
// It starts like this:
|
|
// - child 0 goes through its N0 possibilities
|
|
// - when child 0 was at its last possibility, it goes back to its first one and child 1 pick its second possibility.
|
|
// - and we keep going . . .
|
|
// -----------------------------------------------------------------------------------------------//
|
|
|
|
int modulo = 1;
|
|
int index = 0;
|
|
|
|
_modulos.clear();
|
|
_modulos.push_back(1);
|
|
for (vector<SlicingNode*>::const_iterator it = _HVSnode->getChildren().begin(); it != _HVSnode->getChildren().end(); it++){
|
|
|
|
if ( it != _HVSnode->getChildren().begin() ) { _modulos.push_back(modulo); }
|
|
if ( (!isSymmetry(index)) && (!(*it)->isPreset()) ){ modulo *= (*it)->getNodeSets()->size(); }
|
|
index++;
|
|
}
|
|
_modulos.push_back(modulo);
|
|
}
|
|
|
|
|
|
void HVSetState::next()
|
|
{
|
|
// -----------------------------------------------------------------------------------------------//
|
|
// Notes: Set the next combination. See notes above.
|
|
// -----------------------------------------------------------------------------------------------//
|
|
|
|
int index = 0;
|
|
pair<int,int> symmetry = pair<int,int>();
|
|
vector<size_t>::iterator itpair = _nextSet.begin();
|
|
|
|
for (vector<SlicingNode*>::const_iterator it = _HVSnode->getChildren().begin(); it != _HVSnode->getChildren().end(); it++){
|
|
|
|
if ( this->isSymmetry(index, symmetry) )
|
|
{ (*itpair) = _nextSet[symmetry.first]; }
|
|
else {
|
|
if ( (((_counter-1)%_modulos[index]) == _modulos[index]-1) && (!(*it)->isPreset()) ) {
|
|
if ( (*itpair)+1 != (*it)->getNodeSets()->size() ) { (*itpair)++ ; }
|
|
else { (*itpair) = 0; }
|
|
}
|
|
}
|
|
index++;
|
|
itpair++;
|
|
}
|
|
_counter += 1;
|
|
_currentSet = _nextSet;
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------------------------//
|
|
// Class : HSetState
|
|
// -----------------------------------------------------------------------------------------------//
|
|
|
|
|
|
HSetState::HSetState( HSlicingNode* node ):HVSetState(node) {}
|
|
|
|
|
|
HSetState::~HSetState(){}
|
|
|
|
|
|
pair<DbU::Unit,DbU::Unit> HSetState::getCurrentWs()
|
|
{
|
|
// -----------------------------------------------------------------------------------------------//
|
|
// Notes: Calculate the min and max width of the current combination
|
|
// Routing nodes need to be taken into account to not calculate a wrong width.
|
|
// -----------------------------------------------------------------------------------------------//
|
|
|
|
DbU::Unit wmin = 0;
|
|
DbU::Unit wmax = 0;
|
|
if (!_currentSet.empty()) {
|
|
vector< size_t >::const_iterator it2 = _currentSet.begin();
|
|
vector<SlicingNode*>::const_iterator it = _HVSnode->getChildren().begin();
|
|
|
|
while( (wmin == 0) && (it != _HVSnode->getChildren().end()) ){
|
|
NodeSets* node = (*it)->getNodeSets();
|
|
if ( node->at((*it2))->getWidth() != 0 )
|
|
{ wmin = node->at((*it2))->getWidth(); }
|
|
it++;
|
|
it2++;
|
|
}
|
|
|
|
it2 = _currentSet.begin();
|
|
for (vector<SlicingNode*>::const_iterator it = _HVSnode->getChildren().begin(); it != _HVSnode->getChildren().end(); it++){
|
|
NodeSets* node = (*it)->getNodeSets();
|
|
if ( (node->at((*it2))->getWidth() < wmin)&&(node->at((*it2))->getWidth() != 0) )
|
|
{ wmin = node->at((*it2))->getWidth(); }
|
|
if (node->at((*it2))->getWidth() > wmax)
|
|
{ wmax = node->at((*it2))->getWidth(); }
|
|
it2++;
|
|
}
|
|
}
|
|
return pair<DbU::Unit,DbU::Unit> (wmin, wmax);
|
|
}
|
|
|
|
|
|
DbU::Unit HSetState::getCurrentH()
|
|
{
|
|
// -----------------------------------------------------------------------------------------------//
|
|
// Notes: Calculate the height of the current combination
|
|
// Routing nodes need to be taken into account to not calculate a wrong height.
|
|
// -----------------------------------------------------------------------------------------------//
|
|
|
|
DbU::Unit currentH = 0;
|
|
vector< size_t >::const_iterator it2 = _currentSet.begin();
|
|
for (vector<SlicingNode*>::const_iterator it = _HVSnode->getChildren().begin(); it != _HVSnode->getChildren().end(); it++){
|
|
NodeSets* node = (*it)->getNodeSets();
|
|
currentH += node->at((*it2))->getHeight();
|
|
it2++;
|
|
}
|
|
return currentH;
|
|
}
|
|
|
|
|
|
DbU::Unit HSetState::getCurrentW()
|
|
{
|
|
// -----------------------------------------------------------------------------------------------//
|
|
// Notes: Calculate the width of the current combination
|
|
// Routing nodes need to be taken into account to not calculate a wrong width.
|
|
// -----------------------------------------------------------------------------------------------//
|
|
|
|
DbU::Unit currentW = 0;
|
|
vector< size_t >::const_iterator it2 = _currentSet.begin();
|
|
for (vector<SlicingNode*>::const_iterator it = _HVSnode->getChildren().begin(); it != _HVSnode->getChildren().end(); it++){
|
|
NodeSets* node = (*it)->getNodeSets();
|
|
if (node->at((*it2))->getWidth() > currentW)
|
|
{ currentW = node->at((*it2))->getWidth(); }
|
|
it2++;
|
|
}
|
|
return currentW;
|
|
}
|
|
|
|
|
|
void HSetState::print()
|
|
{
|
|
HVSetState::print();
|
|
cerr << "currentH = " << getCurrentH() << endl;
|
|
cerr << "currentW = " << getCurrentW() << endl;
|
|
cerr << endl;
|
|
}
|
|
|
|
|
|
void HSetState::next()
|
|
{
|
|
push_back();
|
|
HVSetState::next();
|
|
}
|
|
|
|
|
|
void HSetState::push_back()
|
|
{
|
|
// -----------------------------------------------------------------------------------------------//
|
|
// Notes: Check if conditions on tolerance are filled.
|
|
// If yes, add the current set to the NodeSets
|
|
// -----------------------------------------------------------------------------------------------//
|
|
|
|
pair<DbU::Unit,DbU::Unit> paireWidths = getCurrentWs();
|
|
DbU::Unit width = paireWidths.second;
|
|
DbU::Unit wmin = paireWidths.first;
|
|
DbU::Unit height = 0;
|
|
if ( width - wmin <= _HVSnode->getToleranceBandW() ){
|
|
vector<BoxSet*> vect = vector<BoxSet*>();
|
|
vector<size_t>::iterator it2 = _currentSet.begin();
|
|
|
|
for (vector<SlicingNode*>::const_iterator it = _HVSnode->getChildren().begin(); it != _HVSnode->getChildren().end(); it++){
|
|
NodeSets* node = (*it)->getNodeSets();
|
|
vect.push_back(node->at((*it2)));
|
|
height += node->at((*it2))->getHeight();
|
|
it2++;
|
|
}
|
|
|
|
_nodeSets->push_back(vect, height, width, HorizontalSNode); // create the BoxSet of the current accepted set
|
|
}
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------------------------//
|
|
// Class : VSetState
|
|
// -----------------------------------------------------------------------------------------------//
|
|
|
|
|
|
VSetState::VSetState( VSlicingNode* node ):HVSetState(node) {}
|
|
|
|
|
|
VSetState::~VSetState(){}
|
|
|
|
|
|
pair<DbU::Unit,DbU::Unit> VSetState::getCurrentHs ()
|
|
{
|
|
// -----------------------------------------------------------------------------------------------//
|
|
// Notes: Same as HSetState but for Vertical Node. See notes above.
|
|
// -----------------------------------------------------------------------------------------------//
|
|
|
|
DbU::Unit hmin = 0;
|
|
DbU::Unit hmax = 0;
|
|
if (!_currentSet.empty()) {
|
|
vector<size_t>::const_iterator it2 = _currentSet.begin();
|
|
vector<SlicingNode*>::const_iterator it = _HVSnode->getChildren().begin();
|
|
|
|
while( (hmin == 0) && (it != _HVSnode->getChildren().end()) ){
|
|
NodeSets* node = (*it)->getNodeSets();
|
|
if ( node->at((*it2))->getHeight() != 0 )
|
|
{ hmin = node->at((*it2))->getHeight(); }
|
|
it++;
|
|
it2++;
|
|
}
|
|
|
|
it2 = _currentSet.begin();
|
|
for (vector<SlicingNode*>::const_iterator it = _HVSnode->getChildren().begin(); it != _HVSnode->getChildren().end(); it++){
|
|
NodeSets* node = (*it)->getNodeSets();
|
|
if ( (node->at((*it2))->getHeight() < hmin)&&(node->at((*it2))->getHeight() != 0) )
|
|
{ hmin = node->at((*it2))->getHeight(); }
|
|
|
|
if (node->at((*it2))->getHeight() > hmax)
|
|
{ hmax = node->at((*it2))->getHeight(); }
|
|
it2++;
|
|
}
|
|
}
|
|
return pair<DbU::Unit,DbU::Unit> (hmin, hmax);
|
|
}
|
|
|
|
|
|
DbU::Unit VSetState::getCurrentH()
|
|
{
|
|
// -----------------------------------------------------------------------------------------------//
|
|
// Notes: Same as HSetState but for Vertical Node. See notes above.
|
|
// -----------------------------------------------------------------------------------------------//
|
|
DbU::Unit currentH = 0;
|
|
vector< size_t >::const_iterator it2 = _currentSet.begin();
|
|
for (vector<SlicingNode*>::const_iterator it = _HVSnode->getChildren().begin(); it != _HVSnode->getChildren().end(); it++){
|
|
NodeSets* node = (*it)->getNodeSets();
|
|
if (node->at((*it2))->getHeight() > currentH)
|
|
{ currentH = node->at((*it2))->getHeight(); }
|
|
it2++;
|
|
}
|
|
|
|
return currentH;
|
|
}
|
|
|
|
|
|
DbU::Unit VSetState::getCurrentW()
|
|
{
|
|
// -----------------------------------------------------------------------------------------------//
|
|
// Notes: Same as HSetState but for Vertical Node. See notes above.
|
|
// -----------------------------------------------------------------------------------------------//
|
|
DbU::Unit currentW = 0;
|
|
vector< size_t >::const_iterator it2 = _currentSet.begin();
|
|
for (vector<SlicingNode*>::const_iterator it = _HVSnode->getChildren().begin(); it != _HVSnode->getChildren().end(); it++){
|
|
NodeSets* node = (*it)->getNodeSets();
|
|
currentW += node->at((*it2))->getWidth();
|
|
it2++;
|
|
}
|
|
return currentW;
|
|
}
|
|
|
|
|
|
void VSetState::print()
|
|
{
|
|
HVSetState::print();
|
|
cerr << "currentH = " << getCurrentH() << endl;
|
|
cerr << "currentW = " << getCurrentW() << endl;
|
|
cerr << endl;
|
|
}
|
|
|
|
|
|
void VSetState::next()
|
|
{
|
|
push_back();
|
|
HVSetState::next();
|
|
}
|
|
|
|
|
|
void VSetState::push_back()
|
|
{
|
|
// -----------------------------------------------------------------------------------------------//
|
|
// Notes: Same as HSetState but for Vertical Node. See notes above.
|
|
// -----------------------------------------------------------------------------------------------//
|
|
|
|
pair<DbU::Unit,DbU::Unit> paireHeights = getCurrentHs();
|
|
DbU::Unit height = paireHeights.second;
|
|
DbU::Unit hmin = paireHeights.first;
|
|
DbU::Unit width = 0;
|
|
|
|
if (height - hmin <= _HVSnode->getToleranceBandH()){
|
|
vector<BoxSet*> vect = vector<BoxSet*>();
|
|
vector<size_t>::iterator it2 = _currentSet.begin();
|
|
|
|
for (vector<SlicingNode*>::const_iterator it = _HVSnode->getChildren().begin(); it != _HVSnode->getChildren().end(); it++){
|
|
NodeSets* node = (*it)->getNodeSets();
|
|
vect.push_back(node->at((*it2)));
|
|
width += node->at((*it2))->getWidth();
|
|
it2++;
|
|
}
|
|
_nodeSets->push_back(vect, height, width, VerticalSNode);
|
|
}
|
|
}
|
|
|
|
|
|
// -----------------------------------------------------------------------------------------------//
|
|
// Class : ChannelRouting
|
|
// -----------------------------------------------------------------------------------------------//
|
|
|
|
ChannelRouting::ChannelRouting(){}
|
|
|
|
|
|
ChannelRouting::~ChannelRouting(){}
|
|
|
|
|
|
ChannelRouting* ChannelRouting::create()
|
|
{
|
|
return new ChannelRouting();
|
|
}
|
|
|
|
|
|
void ChannelRouting::destroy()
|
|
{
|
|
delete this;
|
|
}
|
|
|
|
|
|
void ChannelRouting::reset()
|
|
{
|
|
_limits.clear();
|
|
_counts.clear();
|
|
}
|
|
|
|
|
|
int ChannelRouting::getMaxCount() const
|
|
{
|
|
int count = 0;
|
|
for (vector<int>::const_iterator it = _counts.begin(); it != _counts.end(); it++){
|
|
count = max( (*it), count );
|
|
}
|
|
return count;
|
|
}
|
|
|
|
|
|
void pvectF(vector<DbU::Unit> vec)
|
|
{
|
|
for (vector<DbU::Unit>::const_iterator it = vec.begin(); it != vec.end(); it++){
|
|
cerr << (*it) << " - ";
|
|
}
|
|
cerr << endl;
|
|
}
|
|
|
|
|
|
void pvectI(vector<int> vec)
|
|
{
|
|
for (vector<int>::const_iterator it = vec.begin(); it != vec.end(); it++){
|
|
cerr << (*it) << " - ";
|
|
}
|
|
cerr << endl;
|
|
}
|
|
|
|
|
|
void ChannelRouting::insertChannel( DbU::Unit xy1, DbU::Unit xy2, unsigned int w )
|
|
{
|
|
for (unsigned int i = 0; i < w; ++i){
|
|
insertChannel(xy1, xy2);
|
|
}
|
|
}
|
|
|
|
|
|
void ChannelRouting::insertChannel( DbU::Unit xy1, DbU::Unit xy2 )
|
|
{
|
|
DbU::Unit min = xy1;
|
|
DbU::Unit max = xy2;
|
|
;
|
|
if (_limits.empty()){
|
|
_limits.push_back(min);
|
|
_limits.push_back(max);
|
|
_counts.push_back(1);
|
|
} else {
|
|
if (max < _limits.front()){
|
|
_limits.insert(_limits.begin(), max);
|
|
_limits.insert(_limits.begin(), min);
|
|
_counts.insert(_counts.begin(), 0);
|
|
_counts.insert(_counts.begin(), 1);
|
|
} else if (min > _limits.back ()){
|
|
_limits.push_back(min);
|
|
_limits.push_back(max);
|
|
_counts.push_back(0);
|
|
_counts.push_back(1);
|
|
} else {
|
|
int index = 0;
|
|
vector<DbU::Unit>::iterator itL = _limits.begin();
|
|
vector<int>::iterator itC = _counts.begin();
|
|
|
|
if (min < (*itL)){
|
|
_limits.insert(itL, min);
|
|
_counts.insert(itC, 1 );
|
|
} else {
|
|
while( ((*itL) < min) && (itL != _limits.end()) ){
|
|
itL++;
|
|
index++;
|
|
if (itC != _counts.end()) itC++;
|
|
}
|
|
|
|
if ((*itL) != min){
|
|
_limits.insert(itL, min);
|
|
_counts.insert(itC, *(itC-1) );
|
|
itL = _limits.begin()+index;
|
|
itC = _counts.begin()+index;
|
|
}
|
|
itL = _limits.begin()+index;
|
|
itC = _counts.begin()+index;
|
|
|
|
|
|
while( ((*itL) < max) && (itL != _limits.end()) ){
|
|
itL++;
|
|
index++;
|
|
if (itC != _counts.end()) {
|
|
(*itC) += 1;
|
|
itC++;
|
|
}
|
|
}
|
|
if ( itL != _limits.end() ){
|
|
if ((*(itL)) > max){
|
|
_limits.insert(itL, max);
|
|
_counts.insert(itC, *(itC-1)-1 );
|
|
}
|
|
} else {
|
|
if ((*(itL-1)) != max){
|
|
_limits.push_back(max);
|
|
_counts.push_back(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void ChannelRouting::print() const
|
|
{
|
|
cerr << "limits: ";
|
|
for (vector<DbU::Unit>::const_iterator it = _limits.begin(); it != _limits.end(); it++){
|
|
cerr << DbU::getPhysical((*it), DbU::Micro) << " - ";
|
|
}
|
|
cerr << endl;
|
|
cerr << "count: ";
|
|
for (vector<int>::const_iterator it = _counts.begin(); it != _counts.end(); it++){
|
|
cerr << (*it) << " - ";
|
|
}
|
|
cerr << endl;
|
|
}
|