365 lines
11 KiB
C++
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.
|