coriolis/bora/src/NodeSets.cpp

365 lines
11 KiB
C++

// -*- C++ -*-
//
// This file is part of the Coriolis Software.
// Copyright (c) UPMC 2015-2018, All Rights Reserved
//
// +-----------------------------------------------------------------+
// | C O R I O L I S |
// | B o r a - A n a l o g S l i c i n g T r e e |
// | |
// | Authors : Eric LAO |
// | E-mail : Jean-Paul.Chaput@lip6.fr |
// | =============================================================== |
// | C++ Module : "./NodeSets.cpp" |
// +-----------------------------------------------------------------+
#include "bora/NodeSets.h"
#include "hurricane/Warning.h"
#include "hurricane/analog/Device.h"
#include "hurricane/analog/TransistorFamily.h"
#include "hurricane/analog/LayoutGenerator.h"
#include "crlcore/RoutingGauge.h"
namespace Bora {
using namespace Hurricane;
using namespace Analog;
NodeSets::NodeSets ( double start, double step, double count )
: _boxSets()
, _start ( start )
, _step ( step )
, _count ( count )
{ }
NodeSets::NodeSets ( const NodeSets* other )
: _boxSets( other->getBoxSets() )
, _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 );
if (not cell) return nodeset;
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 < _boxSets.size()) return _boxSets[i];
return NULL;
}
BoxSet* NodeSets::at ( size_t i )
{
if (i < _boxSets.size()) return _boxSets[i];
return NULL;
}
void NodeSets::clear ()
{
if (not _boxSets.empty()) {
for ( BoxSet* bs : _boxSets ) bs->destroy();
}
_boxSets.clear();
}
BoxSet* NodeSets::getPairH ( DbU::Unit height ) const
{
DbU::Unit w = 0;
DbU::Unit hclosest = 0;
BoxSet* boxSet = (*_boxSets.begin());
for ( BoxSet* bs : _boxSets ) {
if ( (bs->getHeight() > hclosest) and (height >= bs->getHeight()) ) {
hclosest = bs->getHeight();
w = bs->getWidth ();
boxSet = bs;
}
}
if ( (w == 0) and (hclosest == 0) )
cerr << Warning( "NodeSets::getPairH(): No solution for h=%s has been found."
, DbU::getValueString(height).c_str() ) << endl;
return boxSet;
}
BoxSet* NodeSets::getPairHW ( DbU::Unit height, DbU::Unit width ) const
{
vector<BoxSet*>::const_iterator it = _boxSets.begin();
DbU::Unit bestH = (*it)->getHeight();
DbU::Unit bestW = (*it)->getWidth();
DbU::Unit currentH = 0;
DbU::Unit currentW = 0;
BoxSet* boxSet = (*it);
while ( it != _boxSets.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) and (currentW <= width) ) {
bestH = currentH;
bestW = currentW;
boxSet = (*it);
}
else if ( (currentW < bestW) and (bestW > width) ) {
bestH = currentH;
bestW = currentW;
boxSet = (*it);
}
}
++it;
} else {
it = _boxSets.end();
}
}
return boxSet;
}
BoxSet* NodeSets::getPairHW ( unsigned int index ) const
{
if (index < _boxSets.size()) return _boxSets[index];
return NULL;
}
size_t NodeSets::findIndex ( DbU::Unit height, DbU::Unit width ) const
{
for ( size_t i=0 ; i<_boxSets.size() ; ++i ) {
if ( (_boxSets[i]->getHeight() == height)
and (_boxSets[i]->getWidth () == width ) )
return i;
}
return NotFound;
}
BoxSet* NodeSets::find ( DbU::Unit height, DbU::Unit width )
{
size_t i = 0;
for ( ; i<_boxSets.size() ; ++i ) {
if ( (_boxSets[i]->getHeight() == height)
and (_boxSets[i]->getWidth () == width ) )
return _boxSets[i];
}
return NULL;
}
BoxSet* NodeSets::find ( BoxSet* boxSet )
{
return find( boxSet->getHeight(), boxSet->getWidth() );
}
BoxSet* NodeSets::find ( int nfing )
{
size_t i = 0;
for ( ; i<_boxSets.size() ; ++i ) {
if (_boxSets[i]->getNFing() == nfing)
return _boxSets[i];
}
return NULL;
}
void NodeSets::print() const
{
cerr << "Print - NodeSets:" << endl;
int index = 0;
if (not size()) {
cerr << "--- EMPTY ---" << endl;
} else {
for ( size_t i=0 ; _boxSets.size() ; ++i ) {
cerr << "[" << setw(3) << index << "] ";
_boxSets[i]->print();
}
cerr << endl;
}
}
bool NodeSets::compare ( NodeSets nodeSets2, unsigned int flags ) const
{
if (_boxSets.size() != nodeSets2.size()) {
if (flags & ShowDiff)
cerr << "NodeSets::compare() size differs: " << _boxSets.size()
<< " vs. " << nodeSets2.size() << endl;
return false;
}
bool isSame = true;
for ( size_t iset = 0 ; iset<_boxSets.size() ; ++iset ) {
if ( (_boxSets[iset]->getHeight() != nodeSets2[iset]->getHeight())
or (_boxSets[iset]->getWidth () != nodeSets2[iset]->getWidth ()) ) {
isSame = false;
if (flags & ShowDiff)
cerr << "NodeSets::compare() Box [" << iset << "] differs "
<< " (" << DbU::getValueString(_boxSets[iset]->getWidth()) << "," << DbU::getValueString(_boxSets[iset]->getHeight()) << ") vs."
<< " (" << DbU::getValueString(nodeSets2[iset]->getWidth()) << "," << DbU::getValueString(nodeSets2[iset]->getHeight()) << ")"
<< endl;
}
}
return isSame;
}
void NodeSets::push_back ( BoxSet* boxSet )
{
if (find(boxSet) == NULL) _boxSets.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 (find(height,width) == NULL) {
if (type == HorizontalSNode) {
_boxSets.push_back( HBoxSet::create( vect, height, width ) );
} else if (type == VerticalSNode) {
_boxSets.push_back( VBoxSet::create( vect, height, width ) );
}
} else
find( height, width )->incrementCpt();
}
NodeSets* NodeSets::clone()
{
NodeSets* nodesets = new NodeSets( _start, _step, _count );
for ( BoxSet* bs : _boxSets ) _boxSets.push_back( bs->clone() );
return nodesets;
}
} // Bora namespace.