coriolis/bora/src/NodeSets.cpp

365 lines
11 KiB
C++
Raw Normal View History

Analog integration part II. Analog place & route (slicing tree). * Change: In Hurricane::CellWidget, set the minimal size to 350 pixels to fit my normal DPI secondary screen... * Change: In Hurricane::Error(), reactivate the backtrace generation by default. Seriously slow down the program each time an Error is to be constructed. * Bug: In Analog::Device::preCreate(), check for NULL Technology before attempting to use it. * Change: In Hurricane/Analog, remove all '*Arguments*' classes and their Python interface. It was an obsoleted way of passing devices parameters to the Python layout generators (located in Oroshi). Now we just get them straight from the Device with the getParamter() method. * Change: In CRL::System CTOR, add Python pathes for Oroshi & Karakaze. * Change: In Oroshi/Python/WIP_*.py layout generator scripts, remove all uses of the "Arguments". Directly access the parameters through the device itself. Make the checkCoherency() with identical arguments as of layout(). * New: Bora tool that performs analog place & route. Based on a slicing tree representation. It is the thesis work of Eric Lao. Code beautyfication and some programming cleanup. * New: Karakaze tool, provide the Python base class AnalogDesign used to build an analog design. Create/configure devices and assemble them in a slicing tree. * Change: In Unicorn/cgt.py, display the stack trace in case of an ImportError exception as well as for other exceptions. Add Bora to the set for included tool engines.
2018-10-18 11:10:01 -05:00
// -*- 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.