coriolis/bora/src/NodeSets.cpp

368 lines
10 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/MultiCapacitor.h"
#include "hurricane/analog/Resistor.h"
#include "hurricane/analog/LayoutGenerator.h"
#include "crlcore/RoutingGauge.h"
namespace Bora {
using namespace Hurricane;
using namespace Analog;
NodeSets::NodeSets ( ParameterRange* range )
: _boxSets()
, _range (NULL)
{
if (range) {
_range = range->clone();
_range->setNested();
}
}
NodeSets::NodeSets ( const NodeSets* from )
: _boxSets( from->getBoxSets() )
, _range (NULL)
{
if (from->_range) {
_range = from->_range->clone();
_range->setNested();
}
}
NodeSets::~NodeSets ()
{
if (_range) delete _range;
}
NodeSets* NodeSets::create ( Cell* cell
, ParameterRange* range
, CRL::RoutingGauge* rg )
{
NodeSets* nodeset = new NodeSets( range );
if (not cell) return nodeset;
unique_ptr<LayoutGenerator> layoutGenerator ( new LayoutGenerator() );
TransistorFamily* device = dynamic_cast<TransistorFamily *>( cell );
StepParameterRange* stepRange = dynamic_cast<StepParameterRange*>( nodeset->getRange() );
if (device) {
//cdebug_log(536,0) << "createNodeSets for an Analog Device" << endl;
if (not stepRange) {
throw Error( "NodeSets::create(): Device \"%s\" must be associated with a StepParameterRange argument instead of %s."
, getString(device->getName()).c_str()
, getString(stepRange).c_str()
);
}
stepRange->reset();
do {
device->setNfing( stepRange->getValue() );
layoutGenerator->setDevice( device );
layoutGenerator->drawLayout();
nodeset->push_back( DBoxSet::create( device, stepRange->getIndex(), rg ) );
stepRange->progress();
} while ( stepRange->isValid() );
} else {
MultiCapacitor* mcapacitor = dynamic_cast<MultiCapacitor *>( cell );
MatrixParameterRange* matrixRange = dynamic_cast<MatrixParameterRange*>( nodeset->getRange() );
if (mcapacitor) {
if (not matrixRange) {
throw Error( "NodeSets::create(): Device \"%s\" must be associated with a MatrixParameterRange argument instead of %s."
, getString(mcapacitor->getName()).c_str()
, getString(stepRange).c_str()
);
matrixRange->reset();
do {
MatrixParameter* mp = NULL;
if ( (mp = dynamic_cast<MatrixParameter*>(mcapacitor->getParameter("matrix"))) != NULL )
mp->setMatrix( &matrixRange->getValue() );
layoutGenerator->setDevice( mcapacitor );
layoutGenerator->drawLayout();
nodeset->push_back( DBoxSet::create( mcapacitor, matrixRange->getIndex(), rg ) );
matrixRange->progress();
} while ( matrixRange->isValid() );
}
} else {
ResistorFamily* device = dynamic_cast<ResistorFamily *>( cell );
StepParameterRange* stepRange = dynamic_cast<StepParameterRange*>( nodeset->getRange() );
if (device) {
if (not stepRange) {
throw Error( "NodeSets::create(): Device \"%s\" must be associated with a StepParameterRange argument instead of %s."
, getString(device->getName()).c_str()
, getString(stepRange).c_str()
);
}
stepRange->reset();
do {
device->setBends( stepRange->getValue() );
layoutGenerator->setDevice( device );
layoutGenerator->drawLayout();
nodeset->push_back( DBoxSet::create( device, stepRange->getIndex(), rg ) );
stepRange->progress();
} while ( stepRange->isValid() );
} else {
nodeset->push_back( DBoxSet::create( cell, 0, rg ) );
}
}
}
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 ( size_t index )
{
size_t i = 0;
for ( ; i<_boxSets.size() ; ++i ) {
if (_boxSets[i]->getIndex() == index)
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();
cerr << "NodeSets::push_back(): do not add current BoxSet, already exists." << endl;
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( _range );
for ( BoxSet* bs : _boxSets ) _boxSets.push_back( bs->clone() );
return nodesets;
}
} // Bora namespace.