First merge of coloquinte2 & tramontana branches.
Needed to merge thoses two branches as I needed to to uses features from each other to implement GF180MCU.
This commit is contained in:
commit
014ec72652
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
srcDir=${HOME}${nightly}/coriolis-2.x/src/alliance/alliance/src
|
srcDir=${HOME}${nightly}/coriolis-2.x/src/alliance/alliance/src
|
||||||
commonRoot=${HOME}${nightly}/coriolis-2.x/${arch}/Release.Shared
|
commonRoot=${HOME}${nightly}/coriolis-2.x/${arch}/Release.Shared
|
||||||
|
#commonRoot=${HOME}${nightly}/coriolis-2.x/${arch}/Debug.Shared
|
||||||
buildDir=${commonRoot}/build
|
buildDir=${commonRoot}/build
|
||||||
installDir=${commonRoot}/install
|
installDir=${commonRoot}/install
|
||||||
|
|
||||||
|
|
|
@ -24,8 +24,9 @@ projects = [
|
||||||
#, "knik"
|
#, "knik"
|
||||||
#, "katabatic"
|
#, "katabatic"
|
||||||
#, "kite"
|
#, "kite"
|
||||||
, "equinox"
|
#, "equinox"
|
||||||
, "solstice"
|
#, "solstice"
|
||||||
|
, "tramontana"
|
||||||
, "oroshi"
|
, "oroshi"
|
||||||
, "bora"
|
, "bora"
|
||||||
, "karakaze"
|
, "karakaze"
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
FindQwt.cmake
|
FindQwt.cmake
|
||||||
FindSphinx.cmake
|
FindSphinx.cmake
|
||||||
FindPelican.cmake
|
FindPelican.cmake
|
||||||
|
FindCOLOQUINTE.cmake
|
||||||
GetGitRevisionDescription.cmake
|
GetGitRevisionDescription.cmake
|
||||||
GetGitRevisionDescription.cmake.in
|
GetGitRevisionDescription.cmake.in
|
||||||
)
|
)
|
||||||
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
# - Find the Coloquinte includes and libraries.
|
||||||
|
# The following variables are set if Coriolis is found. If COLOQUINTE is not
|
||||||
|
# found, COLOQUINTE_FOUND is set to false.
|
||||||
|
# COLOQUINTE_FOUND - True when the Coriolis include directory is found.
|
||||||
|
# COLOQUINTE_INCLUDE_DIR - the path to where the Coriolis include files are.
|
||||||
|
# COLOQUINTE_LIBRARIES - The path to where the Coriolis library files are.
|
||||||
|
|
||||||
|
|
||||||
|
SET(COLOQUINTE_INCLUDE_PATH_DESCRIPTION "directory containing the Coloquinte include files. E.g /usr/local/include/coriolis2 or /asim/coriolis/include/coriolis2")
|
||||||
|
|
||||||
|
SET(COLOQUINTE_DIR_MESSAGE "Set the COLOQUINTE_INCLUDE_DIR cmake cache entry to the ${COLOQUINTE_INCLUDE_PATH_DESCRIPTION}")
|
||||||
|
|
||||||
|
# don't even bother under WIN32
|
||||||
|
IF(UNIX)
|
||||||
|
#
|
||||||
|
# Look for an installation.
|
||||||
|
#
|
||||||
|
FIND_PATH(COLOQUINTE_INCLUDE_PATH NAMES coloquinte/coloquinte.hpp PATHS
|
||||||
|
# Look in other places.
|
||||||
|
${CORIOLIS_DIR_SEARCH}
|
||||||
|
PATH_SUFFIXES include/coriolis2
|
||||||
|
# Help the user find it if we cannot.
|
||||||
|
DOC "The ${COLOQUINTE_INCLUDE_PATH_DESCRIPTION}"
|
||||||
|
)
|
||||||
|
MESSAGE( "COL ${COLOQUINTE_INCLUDE_PATH}" )
|
||||||
|
|
||||||
|
FIND_LIBRARY(COLOQUINTE_LIBRARY_PATH
|
||||||
|
NAMES coloquinte
|
||||||
|
PATHS ${CORIOLIS_DIR_SEARCH}
|
||||||
|
PATH_SUFFIXES lib64 lib
|
||||||
|
# Help the user find it if we cannot.
|
||||||
|
DOC "The ${COLOQUINTE_INCLUDE_PATH_DESCRIPTION}"
|
||||||
|
)
|
||||||
|
|
||||||
|
SET_LIBRARIES_PATH(COLOQUINTE COLOQUINTE)
|
||||||
|
HURRICANE_CHECK_LIBRARIES(COLOQUINTE)
|
||||||
|
|
||||||
|
ENDIF(UNIX)
|
|
@ -191,8 +191,9 @@ namespace CRL {
|
||||||
bool ToolEngine::_inDestroyAll = false;
|
bool ToolEngine::_inDestroyAll = false;
|
||||||
|
|
||||||
|
|
||||||
ToolEngine::ToolEngine ( Cell* cell )
|
ToolEngine::ToolEngine ( Cell* cell, bool verbose )
|
||||||
: Super()
|
: Super()
|
||||||
|
, _verbose (verbose)
|
||||||
, _cell (cell)
|
, _cell (cell)
|
||||||
, _placementModificationFlag(0)
|
, _placementModificationFlag(0)
|
||||||
, _routingModificationFlag (0)
|
, _routingModificationFlag (0)
|
||||||
|
@ -219,11 +220,13 @@ namespace CRL {
|
||||||
|
|
||||||
put( enginesRelation );
|
put( enginesRelation );
|
||||||
|
|
||||||
cmess1 << " o Creating ToolEngine<" << getName() << "> for Cell <"
|
if (_verbose) {
|
||||||
<< _cell->getName() << ">" << endl;
|
cmess1 << " o Creating ToolEngine<" << getName() << "> for Cell <"
|
||||||
|
<< _cell->getName() << ">" << endl;
|
||||||
cmess1 << Dots::asString( " - Initial memory"
|
|
||||||
, Timer::getStringMemory(Timer::getMemorySize()) ) << endl;
|
cmess1 << Dots::asString( " - Initial memory"
|
||||||
|
, Timer::getStringMemory(Timer::getMemorySize()) ) << endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -81,13 +81,14 @@ namespace CRL {
|
||||||
protected:
|
protected:
|
||||||
Cell* _cell;
|
Cell* _cell;
|
||||||
private:
|
private:
|
||||||
|
bool _verbose;
|
||||||
unsigned int _placementModificationFlag;
|
unsigned int _placementModificationFlag;
|
||||||
unsigned int _routingModificationFlag;
|
unsigned int _routingModificationFlag;
|
||||||
bool _inRelationDestroy;
|
bool _inRelationDestroy;
|
||||||
Timer _timer;
|
Timer _timer;
|
||||||
uint32_t _passNumber;
|
uint32_t _passNumber;
|
||||||
protected:
|
protected:
|
||||||
ToolEngine ( Cell* cell );
|
ToolEngine ( Cell* cell, bool verbose=true );
|
||||||
virtual void _postCreate ();
|
virtual void _postCreate ();
|
||||||
virtual void _preDestroy ();
|
virtual void _preDestroy ();
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -64,7 +64,7 @@ class PnR ( FlowTask ):
|
||||||
else:
|
else:
|
||||||
print( 'PnR.doTask() run in interactive CGT mode.' )
|
print( 'PnR.doTask() run in interactive CGT mode.' )
|
||||||
PnR.textMode = False
|
PnR.textMode = False
|
||||||
from .. import Etesian, Anabatic, Katana, Bora, Tutorial, Viewer, Unicorn
|
from .. import Etesian, Anabatic, Katana, Bora, Tramontana, Tutorial, Viewer, Unicorn
|
||||||
|
|
||||||
ShellEnv().export()
|
ShellEnv().export()
|
||||||
if self.script and not callable(self.script):
|
if self.script and not callable(self.script):
|
||||||
|
@ -80,8 +80,8 @@ class PnR ( FlowTask ):
|
||||||
unicorn = Unicorn.UnicornGui.create()
|
unicorn = Unicorn.UnicornGui.create()
|
||||||
unicorn.setApplicationName ( 'cgt')
|
unicorn.setApplicationName ( 'cgt')
|
||||||
unicorn.registerTool ( Etesian.GraphicEtesianEngine.grab() )
|
unicorn.registerTool ( Etesian.GraphicEtesianEngine.grab() )
|
||||||
#unicorn.registerTool ( Kite.GraphicKiteEngine.grab() )
|
|
||||||
unicorn.registerTool ( Katana.GraphicKatanaEngine.grab() )
|
unicorn.registerTool ( Katana.GraphicKatanaEngine.grab() )
|
||||||
|
unicorn.registerTool ( Tramontana.GraphicTramontanaEngine.grab() )
|
||||||
unicorn.registerTool ( Bora.GraphicBoraEngine.grab() )
|
unicorn.registerTool ( Bora.GraphicBoraEngine.grab() )
|
||||||
unicorn.registerTool ( Tutorial.GraphicTutorialEngine.grab() )
|
unicorn.registerTool ( Tutorial.GraphicTutorialEngine.grab() )
|
||||||
#unicorn.setAnonNetSelectable(False)
|
#unicorn.setAnonNetSelectable(False)
|
||||||
|
|
|
@ -190,6 +190,7 @@ def setupSky130_c4m ( checkToolkit=None, pdkMasterTop=None ):
|
||||||
cfg.misc.logMode = True
|
cfg.misc.logMode = True
|
||||||
cfg.misc.verboseLevel1 = False
|
cfg.misc.verboseLevel1 = False
|
||||||
cfg.misc.verboseLevel2 = False
|
cfg.misc.verboseLevel2 = False
|
||||||
|
cfg.viewer.pixelThreshold = 5
|
||||||
cfg.etesian.graphics = 2
|
cfg.etesian.graphics = 2
|
||||||
cfg.anabatic.topRoutingLayer = 'm4'
|
cfg.anabatic.topRoutingLayer = 'm4'
|
||||||
cfg.katana.eventsLimit = 4000000
|
cfg.katana.eventsLimit = 4000000
|
||||||
|
|
|
@ -1204,8 +1204,8 @@ namespace Etesian {
|
||||||
Instance* instance = static_cast<Instance*>(occurrence.getEntity());
|
Instance* instance = static_cast<Instance*>(occurrence.getEntity());
|
||||||
string instanceName = occurrence.getCompactString();
|
string instanceName = occurrence.getCompactString();
|
||||||
// Remove the enclosing brackets...
|
// Remove the enclosing brackets...
|
||||||
instanceName.erase( 0, 1 );
|
//instanceName.erase( 0, 1 );
|
||||||
instanceName.erase( instanceName.size()-1 );
|
//instanceName.erase( instanceName.size()-1 );
|
||||||
|
|
||||||
auto iid = _instsToIds.find( instance );
|
auto iid = _instsToIds.find( instance );
|
||||||
if (iid == _instsToIds.end() ) {
|
if (iid == _instsToIds.end() ) {
|
||||||
|
|
|
@ -36,7 +36,7 @@ namespace Hurricane {
|
||||||
#ifdef HAVE_CXA_DEMANGLE
|
#ifdef HAVE_CXA_DEMANGLE
|
||||||
|
|
||||||
string demangle ( const char* symbol )
|
string demangle ( const char* symbol )
|
||||||
{
|
{
|
||||||
int status;
|
int status;
|
||||||
size_t length = 4096;
|
size_t length = 4096;
|
||||||
char demangled[length];
|
char demangled[length];
|
||||||
|
@ -49,13 +49,25 @@ string demangle ( const char* symbol )
|
||||||
#else
|
#else
|
||||||
|
|
||||||
string demangle ( const char* symbol )
|
string demangle ( const char* symbol )
|
||||||
{
|
{ return symbol; }
|
||||||
return symbol;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
string& split ( string& s )
|
||||||
|
{
|
||||||
|
size_t i = s.find( "<" );
|
||||||
|
while ( i != string::npos ) {
|
||||||
|
if (i+3 > s.size()) break;
|
||||||
|
//if (s[i+2] != '>') {
|
||||||
|
s.insert( i, "\\n" );
|
||||||
|
//}
|
||||||
|
i = s.find( "<", i+3 );
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // End of Hurricane namespace.
|
} // End of Hurricane namespace.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -111,21 +111,21 @@ bool Interval::intersect(const Interval& interval, bool strict) const
|
||||||
if (isEmpty() or interval.isEmpty()) return false;
|
if (isEmpty() or interval.isEmpty()) return false;
|
||||||
if ( (_vMax < interval._vMin) or (interval._vMax < _vMin) ) return false;
|
if ( (_vMax < interval._vMin) or (interval._vMax < _vMin) ) return false;
|
||||||
|
|
||||||
return not strict or ( (_vMax != interval._vMin) and (interval._vMax != _vMin) );
|
return not strict or ( (_vMax > interval._vMin) or (interval._vMax > _vMin) );
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Interval::inferior(const Interval& interval, bool strict) const
|
bool Interval::inferior(const Interval& interval, bool strict) const
|
||||||
// *****************************************************************
|
// *****************************************************************
|
||||||
{
|
{
|
||||||
if (_vMax < interval._vMin) return true;
|
if (_vMax == interval._vMin) return not strict;
|
||||||
return not strict and (_vMax == interval._vMin);
|
return (_vMax < interval._vMin);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Interval::superior(const Interval& interval, bool strict) const
|
bool Interval::superior(const Interval& interval, bool strict) const
|
||||||
// *****************************************************************
|
// *****************************************************************
|
||||||
{
|
{
|
||||||
if (_vMin > interval._vMax) return true;
|
if (_vMin > interval._vMax) return true;
|
||||||
return !strict && (_vMin == interval._vMax);
|
return not (strict or (_vMin != interval._vMax));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Interval::isConstrainedBy(const Interval& interval) const
|
bool Interval::isConstrainedBy(const Interval& interval) const
|
||||||
|
|
|
@ -772,15 +772,23 @@ void Net::_preDestroy()
|
||||||
cdebug_tabw(18,-1);
|
cdebug_tabw(18,-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string Net::_getFlagsAsString() const
|
||||||
|
// **********************************
|
||||||
|
{
|
||||||
|
string ds;
|
||||||
|
ds += ((isDeepNet() ) ? "d" : "-");
|
||||||
|
ds += ((_isExternal ) ? "e" : "-");
|
||||||
|
ds += ((_isGlobal ) ? "g" : "-");
|
||||||
|
ds += ((_isAutomatic) ? "a" : "-");
|
||||||
|
return ds;
|
||||||
|
}
|
||||||
|
|
||||||
string Net::_getString() const
|
string Net::_getString() const
|
||||||
// ***************************
|
// ***************************
|
||||||
{
|
{
|
||||||
string bs = Inherit::_getString();
|
string bs = Inherit::_getString();
|
||||||
string ds = "\"" + getString(_name) + "\" ";
|
string ds = "\"" + getString(_name) + "\" ";
|
||||||
ds += ((isDeepNet() ) ? "d" : "-");
|
ds += _getFlagsAsString();
|
||||||
ds += ((_isExternal ) ? "e" : "-");
|
|
||||||
ds += ((_isGlobal ) ? "g" : "-");
|
|
||||||
ds += ((_isAutomatic) ? "a" : "-");
|
|
||||||
ds += " ";
|
ds += " ";
|
||||||
ds += getString(_type ) + " ";
|
ds += getString(_type ) + " ";
|
||||||
ds += getString(_direction);
|
ds += getString(_direction);
|
||||||
|
|
|
@ -96,16 +96,27 @@ bool Occurrence::operator!=(const Occurrence& occurrence) const
|
||||||
bool Occurrence::operator<(const Occurrence& occurrence) const
|
bool Occurrence::operator<(const Occurrence& occurrence) const
|
||||||
// ********************************************************
|
// ********************************************************
|
||||||
{
|
{
|
||||||
if (not _entity and not occurrence._entity) return false;
|
cdebug_log(0,0) << "Occurrence::operator<()" << endl;
|
||||||
if (not _entity) return true;
|
cdebug_log(0,0) << "| lhs=" << *this << endl;
|
||||||
if (not occurrence._entity) return false;
|
cdebug_log(0,0) << "| rhs=" << occurrence << endl;
|
||||||
|
if ((not _sharedPath) xor (not occurrence._sharedPath)) return not _sharedPath;
|
||||||
|
if ((not _entity ) xor (not occurrence._entity )) return not _entity;
|
||||||
|
if (_entity and (_entity->getId() != occurrence._entity->getId()))
|
||||||
|
return _entity->getId() < occurrence._entity->getId();
|
||||||
|
if (not _sharedPath) return false;
|
||||||
|
|
||||||
if (_entity->getId() < occurrence._entity->getId()) return true;
|
// if (not _sharedPath) return true;
|
||||||
if (_entity->getId() > occurrence._entity->getId()) return false;
|
// if (not occurrence._sharedPath) return false;
|
||||||
|
// if (not _sharedPath and not occurrence._sharedPath) return false;
|
||||||
|
// if (not _sharedPath) return true;
|
||||||
|
// if (not occurrence._sharedPath) return false;
|
||||||
|
|
||||||
if (not _sharedPath and not occurrence._sharedPath) return false;
|
// if (not _entity and not occurrence._entity) return false;
|
||||||
if (not _sharedPath) return true;
|
// if (not _entity) return true;
|
||||||
if (not occurrence._sharedPath) return false;
|
// if (not occurrence._entity) return false;
|
||||||
|
|
||||||
|
// if (_entity->getId() < occurrence._entity->getId()) return true;
|
||||||
|
// if (_entity->getId() > occurrence._entity->getId()) return false;
|
||||||
|
|
||||||
return _sharedPath->getHash() < occurrence._sharedPath->getHash();
|
return _sharedPath->getHash() < occurrence._sharedPath->getHash();
|
||||||
|
|
||||||
|
@ -274,11 +285,12 @@ string Occurrence::_getString() const
|
||||||
string Occurrence::getCompactString() const
|
string Occurrence::getCompactString() const
|
||||||
// ****************************************
|
// ****************************************
|
||||||
{
|
{
|
||||||
string s = "<";
|
string s;
|
||||||
if (_entity) {
|
if (_entity) {
|
||||||
s += getString(getOwnerCell()->getName());
|
s += getString(getOwnerCell()->getName());
|
||||||
s += ":";
|
s += ":";
|
||||||
if (_sharedPath) s += getString(_sharedPath->getName()) + ":";
|
if (_sharedPath) s += getString(_sharedPath->getName());
|
||||||
|
s += ":";
|
||||||
Instance* instance = dynamic_cast<Instance*>(_entity);
|
Instance* instance = dynamic_cast<Instance*>(_entity);
|
||||||
if (instance) {
|
if (instance) {
|
||||||
s += "I."+getString(instance->getName());
|
s += "I."+getString(instance->getName());
|
||||||
|
@ -291,7 +303,6 @@ string Occurrence::getCompactString() const
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s += ">";
|
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,284 @@
|
||||||
#include "hurricane/Warning.h"
|
#include "hurricane/Warning.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using Hurricane::DbU;
|
||||||
|
using Hurricane::Point;
|
||||||
|
using Hurricane::Box;
|
||||||
|
using Hurricane::Interval;
|
||||||
|
using Hurricane::Rectilinear;
|
||||||
|
|
||||||
|
|
||||||
|
class SweepInterval : public Interval {
|
||||||
|
public:
|
||||||
|
inline SweepInterval ( DbU::Unit vmin , DbU::Unit vmax, DbU::Unit xmin );
|
||||||
|
inline SweepInterval ( Interval&, DbU::Unit xmin );
|
||||||
|
inline SweepInterval& inflate ( DbU::Unit dvMin, DbU::Unit dvMax );
|
||||||
|
inline SweepInterval& merge ( DbU::Unit v );
|
||||||
|
inline DbU::Unit getXMin () const;
|
||||||
|
inline void setXMin ( DbU::Unit );
|
||||||
|
inline string _getString () const;
|
||||||
|
private:
|
||||||
|
DbU::Unit _xMin;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
inline SweepInterval::SweepInterval ( DbU::Unit vmin , DbU::Unit vmax, DbU::Unit xmin )
|
||||||
|
: Interval(vmin,vmax)
|
||||||
|
, _xMin (xmin)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
inline SweepInterval::SweepInterval ( Interval& base, DbU::Unit xmin )
|
||||||
|
: Interval(base)
|
||||||
|
, _xMin (xmin)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
inline SweepInterval& SweepInterval::inflate ( DbU::Unit dvMin, DbU::Unit dvMax ) { Interval::inflate(dvMin,dvMax); return *this; }
|
||||||
|
inline SweepInterval& SweepInterval::merge ( DbU::Unit v ) { Interval::merge(v); return *this; }
|
||||||
|
inline DbU::Unit SweepInterval::getXMin () const { return _xMin; }
|
||||||
|
inline void SweepInterval::setXMin ( DbU::Unit xmin ) { _xMin=xmin; }
|
||||||
|
|
||||||
|
inline string SweepInterval::_getString () const
|
||||||
|
{
|
||||||
|
string s;
|
||||||
|
s += "@" + DbU::getValueString(_xMin);
|
||||||
|
s += " [" + DbU::getValueString(getVMin());
|
||||||
|
s += " " + DbU::getValueString(getVMax()) + "]";
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // Anonymous namespace.
|
||||||
|
|
||||||
|
|
||||||
|
GETSTRING_VALUE_SUPPORT(::SweepInterval);
|
||||||
|
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
|
||||||
|
class SweepLine {
|
||||||
|
public:
|
||||||
|
SweepLine ( const Rectilinear*, vector<Box>& );
|
||||||
|
~SweepLine ();
|
||||||
|
void addVEdge ( DbU::Unit ymin, DbU::Unit ymax, DbU::Unit x );
|
||||||
|
void loadVEdges ();
|
||||||
|
void process ( Interval );
|
||||||
|
void process ( const pair< DbU::Unit, list<Interval> >& );
|
||||||
|
void toBox ( SweepInterval& );
|
||||||
|
void asRectangles ();
|
||||||
|
private:
|
||||||
|
const Rectilinear* _rectilinear;
|
||||||
|
vector<Box>& _boxes;
|
||||||
|
list< pair< DbU::Unit, list<Interval> > > _vedges;
|
||||||
|
list< SweepInterval > _sweepLine;
|
||||||
|
DbU::Unit _prevX;
|
||||||
|
DbU::Unit _currX;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
SweepLine::SweepLine ( const Rectilinear* r, vector<Box>& boxes )
|
||||||
|
: _rectilinear(r)
|
||||||
|
, _boxes (boxes)
|
||||||
|
, _vedges ()
|
||||||
|
, _sweepLine ()
|
||||||
|
, _prevX (0)
|
||||||
|
, _currX (0)
|
||||||
|
{
|
||||||
|
cdebug_log(17,1) << "SweepLine::SweepLine()" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SweepLine::~SweepLine ()
|
||||||
|
{
|
||||||
|
cdebug_tabw(17,-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SweepLine::addVEdge ( DbU::Unit ymin, DbU::Unit ymax, DbU::Unit x )
|
||||||
|
{
|
||||||
|
if (ymin > ymax) std::swap( ymin, ymax );
|
||||||
|
|
||||||
|
cdebug_log(17,1) << "SweepLine::addVEdge() @"<< DbU::getValueString(x)
|
||||||
|
<< " [" << DbU::getValueString(ymin)
|
||||||
|
<< " " << DbU::getValueString(ymax) << "]" << endl;
|
||||||
|
|
||||||
|
bool inserted = false;
|
||||||
|
for ( auto ix = _vedges.begin() ; ix != _vedges.end() ; ++ix ) {
|
||||||
|
cdebug_log(17,0) << "| Looking @" << DbU::getValueString(ix->first)
|
||||||
|
<< " size=" << ix->second.size() << endl;
|
||||||
|
|
||||||
|
if (ix->first > x) {
|
||||||
|
_vedges.insert( ix, make_pair( x, list<Interval>() ));
|
||||||
|
cdebug_log(17,0) << "+ add new @" << DbU::getValueString(x) << endl;
|
||||||
|
--ix;
|
||||||
|
}
|
||||||
|
if (ix->first == x) {
|
||||||
|
for ( auto iintv = ix->second.begin() ; iintv != ix->second.end() ; ++iintv ) {
|
||||||
|
if (iintv->getVMin() >= ymax) {
|
||||||
|
ix->second.insert( iintv, Interval(ymin,ymax) );
|
||||||
|
inserted = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (not inserted) {
|
||||||
|
ix->second.push_back( Interval(ymin,ymax) );
|
||||||
|
inserted = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (not inserted) {
|
||||||
|
cdebug_log(17,0) << "+ add new (back) @" << DbU::getValueString(x) << endl;
|
||||||
|
_vedges.push_back( make_pair( x, list<Interval>() ));
|
||||||
|
_vedges.back().second.push_back( Interval(ymin,ymax) );
|
||||||
|
}
|
||||||
|
|
||||||
|
cdebug_tabw(17,-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SweepLine::loadVEdges ()
|
||||||
|
{
|
||||||
|
const vector<Point>& points = _rectilinear->getPoints();
|
||||||
|
for ( size_t i=0 ; i<points.size()-1 ; ++i ) {
|
||||||
|
const Point& source = points[ i ];
|
||||||
|
const Point& target = points[ (i+1) % points.size() ];
|
||||||
|
DbU::Unit dx = target.getX() - source.getX();
|
||||||
|
//DbU::Unit dy = target.getY() - source.getY();
|
||||||
|
if (dx == 0) {
|
||||||
|
addVEdge( source.getY(), target.getY(), source.getX() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SweepLine::toBox ( SweepInterval& intv )
|
||||||
|
{
|
||||||
|
if (intv.getXMin() == _currX) return;
|
||||||
|
_boxes.push_back( Box( intv.getXMin(), intv.getVMin()
|
||||||
|
, _currX , intv.getVMax() ));
|
||||||
|
intv.setXMin( _currX );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SweepLine::process ( Interval v )
|
||||||
|
{
|
||||||
|
cdebug_log(17,1) << "SweepLine::process(Interval&) "
|
||||||
|
<< " [" << DbU::getValueString(v.getVMin())
|
||||||
|
<< " " << DbU::getValueString(v.getVMax()) << "]" << endl;
|
||||||
|
bool done = false;
|
||||||
|
for ( auto iintv = _sweepLine.begin() ; iintv != _sweepLine.end() ; ++iintv ) {
|
||||||
|
// Extractor p. 9 (a).
|
||||||
|
if (v.getVMax() < iintv->getVMin()) {
|
||||||
|
_sweepLine.insert( iintv, SweepInterval(v,_currX) );
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Extractor p. 9 (f).
|
||||||
|
if ( (v.getVMin() == iintv->getVMin())
|
||||||
|
and (v.getVMax() == iintv->getVMax()) ) {
|
||||||
|
toBox( *iintv );
|
||||||
|
_sweepLine.erase( iintv );
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Extractor p. 9 (b).
|
||||||
|
if (v.getVMax() == iintv->getVMin()) {
|
||||||
|
toBox( *iintv );
|
||||||
|
iintv->merge( v.getVMin() );
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Extractor p. 9 (g).
|
||||||
|
if (v.getVMax() == iintv->getVMax()) {
|
||||||
|
toBox( *iintv );
|
||||||
|
cdebug_log(17,0) << "case (g): carve" << endl;
|
||||||
|
iintv->inflate( 0, v.getVMin() - iintv->getVMax() );
|
||||||
|
cdebug_log(17,0) << "| " << (*iintv) << endl;
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Extractor p. 9 (h).
|
||||||
|
if (v.getVMin() == iintv->getVMin()) {
|
||||||
|
toBox( *iintv );
|
||||||
|
iintv->inflate(iintv->getVMin() - v.getVMax(), 0 );
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Extractor p. 9 (c).
|
||||||
|
if ( (v.getVMin() > iintv->getVMin())
|
||||||
|
and (v.getVMax() < iintv->getVMax()) ) {
|
||||||
|
toBox( *iintv );
|
||||||
|
cdebug_log(17,0) << "case (c): carve" << endl;
|
||||||
|
DbU::Unit wholeVMin = iintv->getVMin();
|
||||||
|
iintv->inflate( iintv->getVMin() - v.getVMax(), 0 );
|
||||||
|
cdebug_log(17,0) << "| " << (*iintv) << endl;
|
||||||
|
_sweepLine.insert( iintv, SweepInterval( wholeVMin, v.getVMin(), _currX ) );
|
||||||
|
cdebug_log(17,0) << "| " << (*(--iintv)) << endl;
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Extractor p. 9 (d,e).
|
||||||
|
if (v.getVMin() == iintv->getVMax()) {
|
||||||
|
auto iintvNext = iintv;
|
||||||
|
++iintvNext;
|
||||||
|
// Extractor p. 9 (d).
|
||||||
|
if (iintvNext == _sweepLine.end()) {
|
||||||
|
toBox( *iintv );
|
||||||
|
iintv->merge( v.getVMax() );
|
||||||
|
} else {
|
||||||
|
// Extractor p. 9 (d).
|
||||||
|
if (v.getVMax() < iintvNext->getVMin()) {
|
||||||
|
toBox( *iintv );
|
||||||
|
iintv->merge( v.getVMax() );
|
||||||
|
} else {
|
||||||
|
// Extractor p. 9 (e).
|
||||||
|
toBox( *iintv );
|
||||||
|
toBox( *iintvNext );
|
||||||
|
iintv->merge( iintvNext->getVMax() );
|
||||||
|
_sweepLine.erase( iintvNext );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (not done) {
|
||||||
|
_sweepLine.push_back( SweepInterval(v,_currX) );
|
||||||
|
}
|
||||||
|
|
||||||
|
cdebug_tabw(17,-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SweepLine::process ( const pair< DbU::Unit, list<Interval> >& intervals )
|
||||||
|
{
|
||||||
|
cdebug_log(17,1) << "SweepLine::process() @"<< DbU::getValueString(intervals.first)
|
||||||
|
<< " size=" << intervals.second.size() << endl;
|
||||||
|
_currX = intervals.first;
|
||||||
|
for ( const Interval& v : intervals.second ) process( v );
|
||||||
|
cdebug_tabw(17,-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SweepLine::asRectangles ()
|
||||||
|
{
|
||||||
|
loadVEdges();
|
||||||
|
for ( auto intervals : _vedges ) {
|
||||||
|
process( intervals );
|
||||||
|
}
|
||||||
|
cdebug_log(17,0) << "SweepLine::asRectangles() size=" << _boxes.size() << endl;
|
||||||
|
for ( const Box& b : _boxes )
|
||||||
|
cdebug_log(17,0) << "| " << b << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // Anonymous namespace.
|
||||||
|
|
||||||
|
|
||||||
namespace Hurricane {
|
namespace Hurricane {
|
||||||
|
|
||||||
|
|
||||||
|
@ -50,6 +328,7 @@ namespace Hurricane {
|
||||||
: Super (net)
|
: Super (net)
|
||||||
, _layer (layer)
|
, _layer (layer)
|
||||||
, _points(points)
|
, _points(points)
|
||||||
|
, _flags (IsRectilinear)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
@ -58,9 +337,21 @@ namespace Hurricane {
|
||||||
if (not layer)
|
if (not layer)
|
||||||
throw Error( "Rectilinear::create(): Can't create, NULL layer" );
|
throw Error( "Rectilinear::create(): Can't create, NULL layer" );
|
||||||
|
|
||||||
if (points.size() > 1000)
|
if (points.size() < 4)
|
||||||
throw Error( "Rectilinear::create(): Rectlinear polygons must not exceed 1000 vertexes." );
|
throw Error( "Rectilinear::create(): Rectilinear polygons must at least contains 3 vertexes." );
|
||||||
|
|
||||||
|
if (points.size() > 1000)
|
||||||
|
throw Error( "Rectilinear::create(): Rectilinear polygons must not exceed 1000 vertexes." );
|
||||||
|
|
||||||
|
if (points[0] != points[points.size()-1])
|
||||||
|
throw Error( "Rectilinear::create(): First and last point must be the same.\n"
|
||||||
|
"0:%s %d:%s"
|
||||||
|
, getString(points[0]).c_str()
|
||||||
|
, points.size()-1
|
||||||
|
, getString(points[points.size()-1]).c_str()
|
||||||
|
);
|
||||||
|
|
||||||
|
bool isRect = true;
|
||||||
DbU::Unit oneGrid = DbU::fromGrid( 1.0 );
|
DbU::Unit oneGrid = DbU::fromGrid( 1.0 );
|
||||||
for ( size_t i=0 ; i<points.size() ; ++i ) {
|
for ( size_t i=0 ; i<points.size() ; ++i ) {
|
||||||
size_t j = (i+1) % points.size();
|
size_t j = (i+1) % points.size();
|
||||||
|
@ -68,9 +359,12 @@ namespace Hurricane {
|
||||||
DbU::Unit dx = std::abs( points[i].getX() - points[j].getX() );
|
DbU::Unit dx = std::abs( points[i].getX() - points[j].getX() );
|
||||||
DbU::Unit dy = std::abs( points[i].getY() - points[j].getY() );
|
DbU::Unit dy = std::abs( points[i].getY() - points[j].getY() );
|
||||||
|
|
||||||
if ( (dx != 0) and (dy != 0) and (dx != dy) )
|
if ((dx != 0) and (dy != 0)) {
|
||||||
throw Error( "Rectilinear::create(): Can't create, non H/V edge (points %d:%s - %d:%s)."
|
isRect = false;
|
||||||
, i, getString(points[i]).c_str(), j, getString(points[j]).c_str() );
|
if (dx != dy)
|
||||||
|
throw Error( "Rectilinear::create(): Can't create, non H/V edge (points %d:%s - %d:%s)."
|
||||||
|
, i, getString(points[i]).c_str(), j, getString(points[j]).c_str() );
|
||||||
|
}
|
||||||
|
|
||||||
if (points[i].getX() % oneGrid)
|
if (points[i].getX() % oneGrid)
|
||||||
cerr << Warning( "Rectilinear::create(): In Cell \"%s\", Net \"%s\",\n"
|
cerr << Warning( "Rectilinear::create(): In Cell \"%s\", Net \"%s\",\n"
|
||||||
|
@ -91,7 +385,7 @@ namespace Hurricane {
|
||||||
}
|
}
|
||||||
|
|
||||||
Rectilinear* rectilinear = new Rectilinear ( net, layer, points );
|
Rectilinear* rectilinear = new Rectilinear ( net, layer, points );
|
||||||
|
if (not isRect) rectilinear->_flags &= ~IsRectilinear;
|
||||||
rectilinear->_postCreate();
|
rectilinear->_postCreate();
|
||||||
|
|
||||||
return rectilinear;
|
return rectilinear;
|
||||||
|
@ -176,6 +470,15 @@ namespace Hurricane {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Rectilinear::getAsRectangles ( std::vector<Box>& rectangles ) const
|
||||||
|
{
|
||||||
|
rectangles.clear();
|
||||||
|
if (not isRectilinear()) return false;
|
||||||
|
SweepLine( this, rectangles ).asRectangles();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Rectilinear::_toJson ( JsonWriter* writer ) const
|
void Rectilinear::_toJson ( JsonWriter* writer ) const
|
||||||
{
|
{
|
||||||
Inherit::_toJson( writer );
|
Inherit::_toJson( writer );
|
||||||
|
|
|
@ -146,6 +146,9 @@ namespace Hurricane {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string& split ( std::string& );
|
||||||
|
|
||||||
|
|
||||||
} // End of Hurricane namespace.
|
} // End of Hurricane namespace.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
#ifndef HURRICANE_COMPONENT_H
|
#ifndef HURRICANE_COMPONENT_H
|
||||||
#define HURRICANE_COMPONENT_H
|
#define HURRICANE_COMPONENT_H
|
||||||
|
|
||||||
|
#include <set>
|
||||||
#include "hurricane/Points.h"
|
#include "hurricane/Points.h"
|
||||||
#include "hurricane/Go.h"
|
#include "hurricane/Go.h"
|
||||||
#include "hurricane/Components.h"
|
#include "hurricane/Components.h"
|
||||||
|
@ -170,6 +171,9 @@ namespace Hurricane {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef std::set<Component*,DBo::CompareById> ComponentSet;
|
||||||
|
|
||||||
|
|
||||||
} // Hurricane namespace.
|
} // Hurricane namespace.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// -*- C++ -*-
|
// -*- C++ -*-
|
||||||
//
|
//
|
||||||
// Copyright (c) BULL S.A. 2000-2018, All Rights Reserved
|
// Copyright (c) BULL S.A. 2000-2023, All Rights Reserved
|
||||||
//
|
//
|
||||||
// This file is part of Hurricane.
|
// This file is part of Hurricane.
|
||||||
//
|
//
|
||||||
|
@ -29,9 +29,7 @@
|
||||||
// +-----------------------------------------------------------------+
|
// +-----------------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
#ifndef HURRICANE_INTERVAL_H
|
#pragma once
|
||||||
#define HURRICANE_INTERVAL_H
|
|
||||||
|
|
||||||
#include "hurricane/DbU.h"
|
#include "hurricane/DbU.h"
|
||||||
|
|
||||||
namespace Hurricane {
|
namespace Hurricane {
|
||||||
|
@ -48,6 +46,11 @@ namespace Hurricane {
|
||||||
inline bool operator() ( const Interval& rhs, const Interval& lhs ) const;
|
inline bool operator() ( const Interval& rhs, const Interval& lhs ) const;
|
||||||
inline bool operator() ( const Interval* rhs, const Interval* lhs ) const;
|
inline bool operator() ( const Interval* rhs, const Interval* lhs ) const;
|
||||||
};
|
};
|
||||||
|
class CompareByMinMax {
|
||||||
|
public:
|
||||||
|
inline bool operator() ( const Interval& rhs, const Interval& lhs ) const;
|
||||||
|
inline bool operator() ( const Interval* rhs, const Interval* lhs ) const;
|
||||||
|
};
|
||||||
public:
|
public:
|
||||||
Interval ( bool makeEmpty=true );
|
Interval ( bool makeEmpty=true );
|
||||||
Interval ( const DbU::Unit& );
|
Interval ( const DbU::Unit& );
|
||||||
|
@ -124,6 +127,20 @@ namespace Hurricane {
|
||||||
{ return lhs->getVMin() < rhs->getVMin(); }
|
{ return lhs->getVMin() < rhs->getVMin(); }
|
||||||
|
|
||||||
|
|
||||||
|
inline bool Interval::CompareByMinMax::operator() ( const Interval& lhs, const Interval& rhs ) const
|
||||||
|
{
|
||||||
|
if (lhs.getVMin() != rhs.getVMin()) return lhs.getVMin() < rhs.getVMin();
|
||||||
|
return lhs.getVMax() < rhs.getVMax();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool Interval::CompareByMinMax::operator() ( const Interval* lhs, const Interval* rhs ) const
|
||||||
|
{
|
||||||
|
if (lhs->getVMin() != rhs->getVMin()) return lhs->getVMin() < rhs->getVMin();
|
||||||
|
return lhs->getVMax() < rhs->getVMax();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // Hurricane namespace.
|
} // Hurricane namespace.
|
||||||
|
|
||||||
|
|
||||||
|
@ -136,7 +153,5 @@ inline void jsonWrite ( JsonWriter* w, const std::string& key, const Hurricane:
|
||||||
w->endArray();
|
w->endArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
INSPECTOR_PR_SUPPORT(Hurricane::Interval);
|
INSPECTOR_PR_SUPPORT(Hurricane::Interval);
|
||||||
|
|
||||||
|
|
||||||
#endif // HURRICANE_INTERVAL_H
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// -*- C++ -*-
|
// -*- C++ -*-
|
||||||
//
|
//
|
||||||
// Copyright (c) BULL S.A. 2018-2018, All Rights Reserved
|
// Copyright (c) BULL S.A. 2018-2023, All Rights Reserved
|
||||||
//
|
//
|
||||||
// This file is part of Hurricane.
|
// This file is part of Hurricane.
|
||||||
//
|
//
|
||||||
|
@ -34,9 +34,7 @@
|
||||||
// Third edition, MIT press, 2011, p. 348.
|
// Third edition, MIT press, 2011, p. 348.
|
||||||
|
|
||||||
|
|
||||||
#ifndef HURRICANE_INTERVAL_TREE_H
|
#pragma once
|
||||||
#define HURRICANE_INTERVAL_TREE_H
|
|
||||||
|
|
||||||
#include "hurricane/Interval.h"
|
#include "hurricane/Interval.h"
|
||||||
#include "hurricane/RbTree.h"
|
#include "hurricane/RbTree.h"
|
||||||
|
|
||||||
|
@ -57,6 +55,7 @@ namespace Hurricane {
|
||||||
inline Data& getData () const;
|
inline Data& getData () const;
|
||||||
inline DbU::Unit getChildsVMax () const;
|
inline DbU::Unit getChildsVMax () const;
|
||||||
inline DbU::Unit updateChildsVMax ( DbU::Unit lvmax, DbU::Unit rvmax );
|
inline DbU::Unit updateChildsVMax ( DbU::Unit lvmax, DbU::Unit rvmax );
|
||||||
|
inline bool operator== ( const IntervalData& ) const;
|
||||||
string _getString () const;
|
string _getString () const;
|
||||||
Record* _getRecord () const;
|
Record* _getRecord () const;
|
||||||
private:
|
private:
|
||||||
|
@ -64,7 +63,7 @@ namespace Hurricane {
|
||||||
Data data_;
|
Data data_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template< typename Data >
|
template< typename Data >
|
||||||
inline IntervalData<Data>::IntervalData ()
|
inline IntervalData<Data>::IntervalData ()
|
||||||
: Interval(1,-1)
|
: Interval(1,-1)
|
||||||
|
@ -93,7 +92,17 @@ namespace Hurricane {
|
||||||
|
|
||||||
template< typename Data >
|
template< typename Data >
|
||||||
inline DbU::Unit IntervalData<Data>::updateChildsVMax ( DbU::Unit lvmax, DbU::Unit rvmax )
|
inline DbU::Unit IntervalData<Data>::updateChildsVMax ( DbU::Unit lvmax, DbU::Unit rvmax )
|
||||||
{ childsVMax_ = std::max( getVMax(), std::max( lvmax, rvmax ) ); return childsVMax_; }
|
{
|
||||||
|
cdebug_log(0,0) << "IntervalData::updateChildsVMax() " << DbU::getValueString(lvmax)
|
||||||
|
<< " " << DbU::getValueString(lvmax)
|
||||||
|
<< " " << this << endl;
|
||||||
|
childsVMax_ = std::max( getVMax(), std::max( lvmax, rvmax ) ); return childsVMax_;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template< typename Data >
|
||||||
|
inline bool IntervalData<Data>::operator== ( const IntervalData<Data>& other ) const
|
||||||
|
{ return Interval::operator==(*this) and (data_ == other.data_); }
|
||||||
|
|
||||||
|
|
||||||
template< typename Data >
|
template< typename Data >
|
||||||
|
@ -117,14 +126,35 @@ namespace Hurricane {
|
||||||
return record;
|
return record;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : "Hurricane::IntervalDataCompare".
|
||||||
|
|
||||||
|
template< typename Data, typename DataCompare=std::less<Data> >
|
||||||
|
class IntervalDataCompare {
|
||||||
|
public:
|
||||||
|
inline bool operator() ( const IntervalData<Data>& lhs, const IntervalData<Data>& rhs ) const
|
||||||
|
{
|
||||||
|
static Interval::CompareByMinMax compare;
|
||||||
|
static DataCompare dataCompare;
|
||||||
|
if ( (lhs.getVMin() == rhs.getVMin())
|
||||||
|
and (lhs.getVMax() == rhs.getVMax())) {
|
||||||
|
cdebug_log(0,0) << "IntervalDataCompare::operator<() - Data fallback." << endl;
|
||||||
|
cdebug_log(0,0) << "| " << lhs.getData() << endl;
|
||||||
|
return dataCompare( lhs.getData(), rhs.getData() );
|
||||||
|
}
|
||||||
|
return compare( lhs, rhs );
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
// Class : "Hurricane::IntervalTree".
|
// Class : "Hurricane::IntervalTree".
|
||||||
|
|
||||||
|
template< typename Data, typename DataCompare=std::less<Data> >
|
||||||
template< typename Data >
|
class IntervalTree : public RbTree< IntervalData<Data>, IntervalDataCompare<Data,DataCompare> > {
|
||||||
class IntervalTree : public RbTree< IntervalData<Data>, Interval::CompareByMin > {
|
|
||||||
public:
|
public:
|
||||||
typedef RbTree< IntervalData<Data>, Interval::CompareByMin > Super;
|
typedef RbTree< IntervalData<Data>, IntervalDataCompare<Data,DataCompare> > Super;
|
||||||
public:
|
public:
|
||||||
class overlap_iterator : public Super::iterator {
|
class overlap_iterator : public Super::iterator {
|
||||||
public:
|
public:
|
||||||
|
@ -171,31 +201,39 @@ namespace Hurricane {
|
||||||
size_t getThickness () const;
|
size_t getThickness () const;
|
||||||
overlap_iterator beginOverlaps ( const Interval& ) const;
|
overlap_iterator beginOverlaps ( const Interval& ) const;
|
||||||
inline OverlapElements getOverlaps ( const Interval& ) const;
|
inline OverlapElements getOverlaps ( const Interval& ) const;
|
||||||
|
void checkVMax () const;
|
||||||
|
void checkVMax ( typename Super::Node* node ) const;
|
||||||
private:
|
private:
|
||||||
inline void updateChildsVMax ( typename Super::Node* );
|
inline void updateChildsVMax ( typename Super::Node* );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template< typename Data >
|
template< typename Data, typename DataCompare >
|
||||||
IntervalTree<Data>::overlap_iterator::overlap_iterator ( const typename Super::Node* node, const Interval& overlap )
|
IntervalTree<Data,DataCompare>::overlap_iterator::overlap_iterator ( const typename Super::Node* node, const Interval& overlap )
|
||||||
: Super::iterator(node)
|
: Super::iterator(node)
|
||||||
, overlap_(overlap)
|
, overlap_(overlap)
|
||||||
{ }
|
|
||||||
|
|
||||||
|
|
||||||
template< typename Data >
|
|
||||||
typename IntervalTree<Data>::overlap_iterator& IntervalTree<Data>::overlap_iterator::operator++ ()
|
|
||||||
{
|
{
|
||||||
while (this->isValid()) {
|
cdebug_log(0,0) << "IntervalTree::overlap_iterator CTOR "
|
||||||
|
<< (node ? ::getString(node->getValue()) : "node=NULL")
|
||||||
|
<< " " << overlap << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template< typename Data, typename DataCompare >
|
||||||
|
typename IntervalTree<Data,DataCompare>::overlap_iterator&
|
||||||
|
IntervalTree<Data,DataCompare>::overlap_iterator::operator++ ()
|
||||||
|
{
|
||||||
|
cdebug_log(0,0) << "IntervalTree::overlap_iterator::operator++()" << endl;
|
||||||
|
while ( true ) {
|
||||||
Super::iterator::operator++();
|
Super::iterator::operator++();
|
||||||
|
if (not this->isValid()) break;
|
||||||
|
|
||||||
cdebug_log(0,0) << "IntervalTree::overlap_iterator::operator++() "
|
cdebug_log(0,0) << " ==> " << ::getString(this->getNode()->getValue()) << std::endl;
|
||||||
<< ::getString(this->getNode()) << std::endl;
|
|
||||||
|
|
||||||
if (this->getNode()->getValue().intersect(overlap_,true)) break;
|
if (this->getNode()->getValue().intersect(overlap_,false)) break;
|
||||||
cdebug_log(0,0) << "NO intersections" << endl;
|
cdebug_log(0,0) << " NO intersections" << endl;
|
||||||
if (overlap_.inferior(this->getNode()->getValue(),true)) {
|
if (overlap_.inferior(this->getNode()->getValue(),false)) {
|
||||||
cdebug_log(0,0) << "Node is inferior, stop here." << endl;
|
cdebug_log(0,0) << " Node is inferior, stop here." << endl;
|
||||||
this->setNode( NULL );
|
this->setNode( NULL );
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -208,44 +246,45 @@ namespace Hurricane {
|
||||||
// Class : "Hurricane::IntervalTree::OverlapOverlapElements" (implementation)
|
// Class : "Hurricane::IntervalTree::OverlapOverlapElements" (implementation)
|
||||||
|
|
||||||
|
|
||||||
template< typename Data >
|
template< typename Data, typename DataCompare >
|
||||||
inline IntervalTree<Data>::OverlapElements::Locator::Locator ( const Locator &locator )
|
inline IntervalTree<Data,DataCompare>::OverlapElements::Locator::Locator ( const Locator &locator )
|
||||||
: Hurricane::Locator< IntervalData<Data> >()
|
: Hurricane::Locator< IntervalData<Data> >()
|
||||||
, iterator_(locator.iterator_)
|
, iterator_(locator.iterator_)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
||||||
template< typename Data >
|
template< typename Data, typename DataCompare >
|
||||||
IntervalTree<Data>::OverlapElements::Locator::Locator ( const IntervalTree<Data>& tree, const Interval& span )
|
IntervalTree<Data,DataCompare>::OverlapElements::Locator::Locator ( const IntervalTree<Data,DataCompare>& tree, const Interval& span )
|
||||||
: Hurricane::Locator< IntervalData<Data> >()
|
: Hurricane::Locator< IntervalData<Data> >()
|
||||||
, iterator_(tree.beginOverlaps(span))
|
, iterator_(tree.beginOverlaps(span))
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
||||||
template< typename Data >
|
template< typename Data, typename DataCompare >
|
||||||
typename IntervalTree<Data>::OverlapElements::Locator* IntervalTree<Data>::OverlapElements::Locator::getClone () const
|
typename IntervalTree<Data,DataCompare>::OverlapElements::Locator*
|
||||||
|
IntervalTree<Data,DataCompare>::OverlapElements::Locator::getClone () const
|
||||||
{ return new Locator(*this); }
|
{ return new Locator(*this); }
|
||||||
|
|
||||||
|
|
||||||
template< typename Data >
|
template< typename Data, typename DataCompare >
|
||||||
IntervalData<Data> IntervalTree<Data>::OverlapElements::Locator::getElement () const
|
IntervalData<Data> IntervalTree<Data,DataCompare>::OverlapElements::Locator::getElement () const
|
||||||
{ return (*iterator_); }
|
{ return (*iterator_); }
|
||||||
|
|
||||||
|
|
||||||
template< typename Data >
|
template< typename Data, typename DataCompare >
|
||||||
bool IntervalTree<Data>::OverlapElements::Locator::isValid () const
|
bool IntervalTree<Data,DataCompare>::OverlapElements::Locator::isValid () const
|
||||||
{ return iterator_.isValid(); }
|
{ return iterator_.isValid(); }
|
||||||
|
|
||||||
|
|
||||||
template< typename Data >
|
template< typename Data, typename DataCompare >
|
||||||
void IntervalTree<Data>::OverlapElements::Locator::progress ()
|
void IntervalTree<Data,DataCompare>::OverlapElements::Locator::progress ()
|
||||||
{
|
{
|
||||||
if (isValid()) ++iterator_;
|
if (isValid()) ++iterator_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template< typename Data >
|
template< typename Data, typename DataCompare >
|
||||||
std::string IntervalTree<Data>::OverlapElements::Locator::_getString () const
|
std::string IntervalTree<Data,DataCompare>::OverlapElements::Locator::_getString () const
|
||||||
{
|
{
|
||||||
std::string s = "<" + _TName("OverlapElements::Locator")
|
std::string s = "<" + _TName("OverlapElements::Locator")
|
||||||
+ ">";
|
+ ">";
|
||||||
|
@ -253,34 +292,34 @@ namespace Hurricane {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template< typename Data >
|
template< typename Data, typename DataCompare >
|
||||||
inline IntervalTree<Data>::OverlapElements::OverlapElements ( const IntervalTree& tree, const Interval& span )
|
inline IntervalTree<Data,DataCompare>::OverlapElements::OverlapElements ( const IntervalTree& tree, const Interval& span )
|
||||||
: Collection< IntervalData<Data> >()
|
: Collection< IntervalData<Data> >()
|
||||||
, tree_(tree)
|
, tree_(tree)
|
||||||
, span_(span)
|
, span_(span)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
||||||
template< typename Data >
|
template< typename Data, typename DataCompare >
|
||||||
inline IntervalTree<Data>::OverlapElements::OverlapElements ( const OverlapElements& elements )
|
inline IntervalTree<Data,DataCompare>::OverlapElements::OverlapElements ( const OverlapElements& elements )
|
||||||
: Collection< IntervalData<Data> >()
|
: Collection< IntervalData<Data> >()
|
||||||
, tree_(elements.tree_)
|
, tree_(elements.tree_)
|
||||||
, span_(elements.span_)
|
, span_(elements.span_)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
|
|
||||||
template< typename Data >
|
template< typename Data, typename DataCompare >
|
||||||
Collection< IntervalData<Data> >* IntervalTree<Data>::OverlapElements::getClone () const
|
Collection< IntervalData<Data> >* IntervalTree<Data,DataCompare>::OverlapElements::getClone () const
|
||||||
{ return new OverlapElements(*this); }
|
{ return new OverlapElements(*this); }
|
||||||
|
|
||||||
|
|
||||||
template< typename Data >
|
template< typename Data, typename DataCompare >
|
||||||
typename IntervalTree<Data>::OverlapElements::Locator* IntervalTree<Data>::OverlapElements::getLocator () const
|
typename IntervalTree<Data,DataCompare>::OverlapElements::Locator* IntervalTree<Data,DataCompare>::OverlapElements::getLocator () const
|
||||||
{ return new Locator( tree_, span_ ); }
|
{ return new Locator( tree_, span_ ); }
|
||||||
|
|
||||||
|
|
||||||
template< typename Data >
|
template< typename Data, typename DataCompare >
|
||||||
std::string IntervalTree<Data>::OverlapElements::_getString () const
|
std::string IntervalTree<Data,DataCompare>::OverlapElements::_getString () const
|
||||||
{
|
{
|
||||||
std::string s = "<" + _TName("OverlapElements") + " "
|
std::string s = "<" + _TName("OverlapElements") + " "
|
||||||
+ getString(tree_)
|
+ getString(tree_)
|
||||||
|
@ -293,39 +332,45 @@ namespace Hurricane {
|
||||||
// Class : "Hurricane::IntervalTree" (implementation).
|
// Class : "Hurricane::IntervalTree" (implementation).
|
||||||
|
|
||||||
|
|
||||||
template< typename Data >
|
template< typename Data, typename DataCompare >
|
||||||
inline void IntervalTree<Data>::updateChildsVMax ( typename Super::Node* node )
|
inline void IntervalTree<Data,DataCompare>::updateChildsVMax ( typename Super::Node* node )
|
||||||
{
|
{
|
||||||
|
cdebug_log(0,1) << "IntervalTree::updateChildsVMax() " << node->getValue() << endl;
|
||||||
DbU::Unit lchildVMax = (node->getLeft ()) ? node->getLeft ()->getValue().getChildsVMax() : node->getValue().getVMax();
|
DbU::Unit lchildVMax = (node->getLeft ()) ? node->getLeft ()->getValue().getChildsVMax() : node->getValue().getVMax();
|
||||||
DbU::Unit rchildVMax = (node->getRight()) ? node->getRight()->getValue().getChildsVMax() : node->getValue().getVMax();
|
DbU::Unit rchildVMax = (node->getRight()) ? node->getRight()->getValue().getChildsVMax() : node->getValue().getVMax();
|
||||||
|
|
||||||
const_cast< IntervalData<Data>& >( node->getValue() ).updateChildsVMax( lchildVMax, rchildVMax );
|
const_cast< IntervalData<Data>& >( node->getValue() ).updateChildsVMax( lchildVMax, rchildVMax );
|
||||||
|
cdebug_tabw(0,-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template< typename Data >
|
template< typename Data, typename DataCompare >
|
||||||
void IntervalTree<Data>::postRotateLeft ( typename Super::Node* node )
|
void IntervalTree<Data,DataCompare>::postRotateLeft ( typename Super::Node* node )
|
||||||
{
|
{
|
||||||
|
cdebug_log(0,1) << "IntervalTree::postRotateLeft() " << node->getValue() << endl;
|
||||||
|
updateChildsVMax( node );
|
||||||
|
if (node->getParent()) updateChildsVMax( node->getParent() );
|
||||||
|
cdebug_tabw(0,-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template< typename Data, typename DataCompare >
|
||||||
|
void IntervalTree<Data,DataCompare>::postRotateRight ( typename Super::Node* node )
|
||||||
|
{
|
||||||
|
cdebug_log(0,0) << "IntervalTree::postRotateRight() " << node->getValue() << endl;
|
||||||
updateChildsVMax( node );
|
updateChildsVMax( node );
|
||||||
if (node->getParent()) updateChildsVMax( node->getParent() );
|
if (node->getParent()) updateChildsVMax( node->getParent() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template< typename Data >
|
template< typename Data, typename DataCompare >
|
||||||
void IntervalTree<Data>::postRotateRight ( typename Super::Node* node )
|
void IntervalTree<Data,DataCompare>::postInsert ( typename Super::Node* node )
|
||||||
{
|
{
|
||||||
updateChildsVMax( node );
|
cdebug_log(0,1) << "IntervalTree::postInsert() "
|
||||||
if (node->getParent()) updateChildsVMax( node->getParent() );
|
<< ((node) ? ::getString(node->getValue()) : "node=NULL") << std::endl;
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template< typename Data >
|
|
||||||
void IntervalTree<Data>::postInsert ( typename Super::Node* node )
|
|
||||||
{
|
|
||||||
cdebug_log(0,1) << "IntervalTree::postInsert() " << node << std::endl;
|
|
||||||
|
|
||||||
while ( node ) {
|
while ( node ) {
|
||||||
cdebug_log(0,0) << "| " << node << std::endl;
|
cdebug_log(0,0) << "| " << node->getValue() << std::endl;
|
||||||
|
|
||||||
updateChildsVMax( node );
|
updateChildsVMax( node );
|
||||||
node = node->getParent();
|
node = node->getParent();
|
||||||
|
@ -335,26 +380,38 @@ namespace Hurricane {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template< typename Data >
|
template< typename Data, typename DataCompare >
|
||||||
void IntervalTree<Data>::postRemove ( typename Super::Node* node )
|
void IntervalTree<Data,DataCompare>::postRemove ( typename Super::Node* node )
|
||||||
{
|
{
|
||||||
|
cdebug_log(0,1) << "IntervalTree::postRemove() "
|
||||||
|
<< ((node) ? ::getString(node->getValue()) : "node=NULL") << std::endl;
|
||||||
|
|
||||||
|
if (not node) {
|
||||||
|
cdebug_tabw(0,-1);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
typename Super::Node* parent = node->getParent();
|
typename Super::Node* parent = node->getParent();
|
||||||
if (parent) {
|
if (parent) {
|
||||||
typename Super::Node* child = NULL;
|
DbU::Unit childsVMax = parent->getValue().getVMax();
|
||||||
|
typename Super::Node* child1 = parent->getLeft ();
|
||||||
|
typename Super::Node* child2 = parent->getRight();
|
||||||
|
if (child1 == node) std::swap( child1, child2 );
|
||||||
|
if (child1) childsVMax = std::max( childsVMax, child1->getValue().getChildsVMax() );
|
||||||
|
if (child2->getLeft ()) childsVMax = std::max( childsVMax, child2->getLeft ()->getValue().getChildsVMax() );
|
||||||
|
if (child2->getRight()) childsVMax = std::max( childsVMax, child2->getRight()->getValue().getChildsVMax() );
|
||||||
|
|
||||||
if (parent->hasLeftChild(node)) child = parent->getRight();
|
const_cast< IntervalData<Data>& >( parent->getValue() ).updateChildsVMax( childsVMax, childsVMax );
|
||||||
else child = parent->getLeft ();
|
|
||||||
|
|
||||||
DbU::Unit childVMax = (child) ? child->getValue().getChildsVMax() : parent->getValue().getVMax();
|
|
||||||
const_cast< IntervalData<Data>& >( parent->getValue() ).updateChildsVMax( childVMax, childVMax );
|
|
||||||
|
|
||||||
postInsert( parent->getParent() );
|
postInsert( parent->getParent() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cdebug_tabw(0,-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template< typename Data >
|
template< typename Data, typename DataCompare >
|
||||||
size_t IntervalTree<Data>::getThickness () const
|
size_t IntervalTree<Data,DataCompare>::getThickness () const
|
||||||
{
|
{
|
||||||
cdebug_log(0,0) << "IntervalTree::getThickness() " << std::endl;
|
cdebug_log(0,0) << "IntervalTree::getThickness() " << std::endl;
|
||||||
|
|
||||||
|
@ -382,36 +439,70 @@ namespace Hurricane {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template< typename Data >
|
template< typename Data, typename DataCompare >
|
||||||
typename IntervalTree<Data>::overlap_iterator IntervalTree<Data>::beginOverlaps ( const Interval& overlap ) const
|
typename IntervalTree<Data,DataCompare>::overlap_iterator
|
||||||
|
IntervalTree<Data,DataCompare>::beginOverlaps ( const Interval& overlap ) const
|
||||||
{
|
{
|
||||||
cdebug_log(0,0) << "IntervalTree::beginOverlaps() " << overlap << std::endl;
|
cdebug_log(0,0) << "IntervalTree::beginOverlaps() " << overlap << std::endl;
|
||||||
|
|
||||||
const typename Super::Node* current = this->getRoot();
|
const typename Super::Node* current = this->getRoot();
|
||||||
const typename Super::Node* leftMost = NULL;
|
const typename Super::Node* leftMost = nullptr;
|
||||||
while ( current ) {
|
while ( current ) {
|
||||||
cdebug_log(0,0) << "| " << ::getString(current) << endl;
|
cdebug_log(0,0) << "| " << ::getString(current->getValue()) << endl;
|
||||||
|
|
||||||
if (current->getValue().intersect(overlap)) leftMost = current;
|
if (current->getValue().intersect(overlap,false)) {
|
||||||
|
cdebug_log(0,0) << "* Leftmost candidate." << endl;
|
||||||
|
leftMost = current;
|
||||||
|
}
|
||||||
if ( current->getLeft()
|
if ( current->getLeft()
|
||||||
and (overlap.getVMin() < current->getLeft()->getValue().getChildsVMax()) )
|
and (overlap.getVMin() < current->getLeft()->getValue().getChildsVMax()) ) {
|
||||||
current = current->getLeft();
|
current = current->getLeft();
|
||||||
else
|
leftMost = nullptr;
|
||||||
current = current->getRight();
|
} else {
|
||||||
|
if (not leftMost)
|
||||||
|
current = current->getRight();
|
||||||
|
else
|
||||||
|
current = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return overlap_iterator( leftMost, overlap );
|
return overlap_iterator( leftMost, overlap );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template< typename Data >
|
template< typename Data, typename DataCompare >
|
||||||
typename IntervalTree<Data>::OverlapElements IntervalTree<Data>::getOverlaps ( const Interval& overlap ) const
|
typename IntervalTree<Data,DataCompare>::OverlapElements
|
||||||
|
IntervalTree<Data,DataCompare>::getOverlaps ( const Interval& overlap ) const
|
||||||
{
|
{
|
||||||
cdebug_log(0,0) << "IntervalTree::getOverlaps() " << overlap << std::endl;
|
cdebug_log(0,0) << "IntervalTree::getOverlaps() " << overlap << std::endl;
|
||||||
return OverlapElements( *this, overlap );
|
return OverlapElements( *this, overlap );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template< typename Data, typename DataCompare >
|
||||||
|
void IntervalTree<Data,DataCompare>::checkVMax () const
|
||||||
|
{
|
||||||
|
checkVMax( this->getRoot() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template< typename Data, typename DataCompare >
|
||||||
|
void IntervalTree<Data,DataCompare>::checkVMax ( typename Super::Node* node ) const
|
||||||
|
{
|
||||||
|
if (not node) return;
|
||||||
|
|
||||||
|
DbU::Unit lchildVMax = (node->getLeft ()) ? node->getLeft ()->getValue().getChildsVMax() : node->getValue().getVMax();
|
||||||
|
DbU::Unit rchildVMax = (node->getRight()) ? node->getRight()->getValue().getChildsVMax() : node->getValue().getVMax();
|
||||||
|
DbU::Unit childsVMax = std::max( lchildVMax, rchildVMax );
|
||||||
|
childsVMax = std::max( childsVMax, node->getValue().getVMax() );
|
||||||
|
|
||||||
|
if (node->getValue().getChildsVMax() != childsVMax) {
|
||||||
|
cerr << "ChildVMax discrepency on vmax=" << DbU::getValueString(childsVMax)
|
||||||
|
<< " " << ::getString(node->getValue()) << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
checkVMax( node->getLeft() );
|
||||||
|
checkVMax( node->getRight() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
} // HUrricane namespace.
|
} // HUrricane namespace.
|
||||||
|
|
||||||
#endif // HURRICANE_INTERVAL_TREE_H
|
|
||||||
|
|
|
@ -17,9 +17,7 @@
|
||||||
// not, see <http://www.gnu.org/licenses/>.
|
// not, see <http://www.gnu.org/licenses/>.
|
||||||
// ****************************************************************************************************
|
// ****************************************************************************************************
|
||||||
|
|
||||||
#ifndef HURRICANE_NET
|
#pragma once
|
||||||
#define HURRICANE_NET
|
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include "hurricane/Entity.h"
|
#include "hurricane/Entity.h"
|
||||||
#include "hurricane/Nets.h"
|
#include "hurricane/Nets.h"
|
||||||
|
@ -253,6 +251,7 @@ class Net : public Entity {
|
||||||
public: virtual void _toJsonSignature(JsonWriter*) const;
|
public: virtual void _toJsonSignature(JsonWriter*) const;
|
||||||
public: virtual void _toJsonCollections(JsonWriter*) const;
|
public: virtual void _toJsonCollections(JsonWriter*) const;
|
||||||
public: virtual string _getTypeName() const {return _TName("Net");};
|
public: virtual string _getTypeName() const {return _TName("Net");};
|
||||||
|
public: string _getFlagsAsString() const;
|
||||||
public: virtual string _getString() const;
|
public: virtual string _getString() const;
|
||||||
public: virtual Record* _getRecord() const;
|
public: virtual Record* _getRecord() const;
|
||||||
public: NetMainName& _getMainName() { return _mainName; }
|
public: NetMainName& _getMainName() { return _mainName; }
|
||||||
|
@ -445,9 +444,10 @@ namespace Hurricane {
|
||||||
// Because sometimes it didn't happens (?).
|
// Because sometimes it didn't happens (?).
|
||||||
const SlotTemplate<Net*> dummyNetSlot ( string("dummyNetSlot"), NULL );
|
const SlotTemplate<Net*> dummyNetSlot ( string("dummyNetSlot"), NULL );
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // HURRICANE_NET
|
typedef std::set<Net*,DBo::CompareById> NetSet;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ****************************************************************************************************
|
// ****************************************************************************************************
|
||||||
|
|
|
@ -121,6 +121,10 @@ class JsonOccurrence : public JsonObject {
|
||||||
public: virtual void toData(JsonStack&);
|
public: virtual void toData(JsonStack&);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
typedef std::set<Occurrence> OccurrenceSet;
|
||||||
|
|
||||||
|
|
||||||
} // End of Hurricane namespace.
|
} // End of Hurricane namespace.
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -34,9 +34,7 @@
|
||||||
// Third edition, MIT press, 2011, p. 308.
|
// Third edition, MIT press, 2011, p. 308.
|
||||||
|
|
||||||
|
|
||||||
#ifndef HURRICANE_RBTREE_H
|
#pragma once
|
||||||
#define HURRICANE_RBTREE_H
|
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
@ -90,7 +88,7 @@ namespace Hurricane {
|
||||||
inline void copyColor ( Node* );
|
inline void copyColor ( Node* );
|
||||||
void updateEdge ( Node* oldChild, Node* newChild );
|
void updateEdge ( Node* oldChild, Node* newChild );
|
||||||
void clear ();
|
void clear ();
|
||||||
inline void copy ( const Node* );
|
inline void swap ( Node* );
|
||||||
virtual std::string _getString () const;
|
virtual std::string _getString () const;
|
||||||
virtual Record* _getRecord () const;
|
virtual Record* _getRecord () const;
|
||||||
private:
|
private:
|
||||||
|
@ -284,8 +282,15 @@ namespace Hurricane {
|
||||||
|
|
||||||
|
|
||||||
template< typename Data, typename Compare >
|
template< typename Data, typename Compare >
|
||||||
inline void RbTree<Data,Compare>::Node::copy ( const Node* other )
|
inline void RbTree<Data,Compare>::Node::swap ( Node* other )
|
||||||
{ value_ = other->value_; }
|
{
|
||||||
|
cdebug_log(0,0) << "Node::swap()" << endl;
|
||||||
|
cdebug_log(0,0) << "| " << value_ << endl;
|
||||||
|
cdebug_log(0,0) << "| " << other->value_ << endl;
|
||||||
|
Data tmp = value_; value_ = other->value_; other->value_ = tmp;
|
||||||
|
cdebug_log(0,0) << "| " << value_ << endl;
|
||||||
|
cdebug_log(0,0) << "| " << other->value_ << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template< typename Data, typename Compare >
|
template< typename Data, typename Compare >
|
||||||
|
@ -515,7 +520,7 @@ namespace Hurricane {
|
||||||
template< typename Data, typename Compare >
|
template< typename Data, typename Compare >
|
||||||
void RbTree<Data,Compare>::rotateLeft ( typename RbTree<Data,Compare>::Node* node )
|
void RbTree<Data,Compare>::rotateLeft ( typename RbTree<Data,Compare>::Node* node )
|
||||||
{
|
{
|
||||||
cdebug_log(0,0) << "RbTree::rotateLeft() " << node << std::endl;
|
cdebug_log(0,0) << "RbTree::rotateLeft() " << node->getValue() << std::endl;
|
||||||
|
|
||||||
Node* rchild = node->getRight();
|
Node* rchild = node->getRight();
|
||||||
|
|
||||||
|
@ -534,7 +539,7 @@ namespace Hurricane {
|
||||||
template< typename Data, typename Compare >
|
template< typename Data, typename Compare >
|
||||||
void RbTree<Data,Compare>::rotateRight ( typename RbTree<Data,Compare>::Node* node )
|
void RbTree<Data,Compare>::rotateRight ( typename RbTree<Data,Compare>::Node* node )
|
||||||
{
|
{
|
||||||
cdebug_log(0,0) << "RbTree::rotateRight() " << node << std::endl;
|
cdebug_log(0,0) << "RbTree::rotateRight() " << node->getValue() << std::endl;
|
||||||
|
|
||||||
Node* lchild = node->getLeft();
|
Node* lchild = node->getLeft();
|
||||||
|
|
||||||
|
@ -557,15 +562,21 @@ namespace Hurricane {
|
||||||
|
|
||||||
Node* current = root_;
|
Node* current = root_;
|
||||||
while ( current ) {
|
while ( current ) {
|
||||||
cdebug_log(0,0) << "| " << current << std::endl;
|
cdebug_log(0,0) << "| " << current->getValue() << std::endl;
|
||||||
|
|
||||||
if (current->getValue() == value) {
|
if (current->getValue() == value) {
|
||||||
cdebug_log(0,-1) << "> Value found: " << current <<std::endl;
|
cdebug_log(0,-1) << "> Value found: " << current->getValue() << std::endl;
|
||||||
return iterator(current);
|
return iterator(current);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (compare_(value,current->getValue())) current = current->getLeft ();
|
if (compare_(value,current->getValue())) {
|
||||||
else current = current->getRight();
|
current = current->getLeft ();
|
||||||
|
cdebug_log(0,0) << "| Go left " << ((current) ? ::getString(current->getValue()) : "NULL") << std::endl;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
current = current->getRight();
|
||||||
|
cdebug_log(0,0) << "| Go right " << ((current) ? ::getString(current->getValue()) : "NULL") << std::endl;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cdebug_log(0,-1) << "Value not found." << std::endl;
|
cdebug_log(0,-1) << "Value not found." << std::endl;
|
||||||
|
@ -630,21 +641,22 @@ namespace Hurricane {
|
||||||
|
|
||||||
Node* rmNode = const_cast<Node*>( find( value ).getNode() );
|
Node* rmNode = const_cast<Node*>( find( value ).getNode() );
|
||||||
if (not rmNode) {
|
if (not rmNode) {
|
||||||
cdebug_log(0,1) << "No node of value=" << value << std::endl;
|
cdebug_log(0,-1) << "No node of value=" << value << std::endl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Node* rmLeaf = nullptr;
|
||||||
if (rmNode->getLeft() and rmNode->getRight()) {
|
if (rmNode->getLeft() and rmNode->getRight()) {
|
||||||
Node* rmLeaf = rmNode->getLeft();
|
rmLeaf = rmNode->getLeft();
|
||||||
Node* rmMax = rmLeaf->getMax();
|
Node* rmMax = rmLeaf->getMax();
|
||||||
if (rmMax) rmLeaf = rmMax;
|
if (rmMax) rmLeaf = rmMax;
|
||||||
|
|
||||||
rmNode->copy( rmLeaf );
|
rmNode->swap( rmLeaf );
|
||||||
rmNode = rmLeaf;
|
std::swap( rmNode, rmLeaf );
|
||||||
}
|
}
|
||||||
|
|
||||||
postRemove ( rmNode );
|
|
||||||
removeRepair( rmNode, 0 );
|
removeRepair( rmNode, 0 );
|
||||||
|
postRemove ( rmNode );
|
||||||
|
|
||||||
Node* parent = rmNode->getParent();
|
Node* parent = rmNode->getParent();
|
||||||
Node* child = (rmNode->getLeft()) ? rmNode->getLeft() : rmNode->getRight();
|
Node* child = (rmNode->getLeft()) ? rmNode->getLeft() : rmNode->getRight();
|
||||||
|
@ -660,8 +672,9 @@ namespace Hurricane {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cdebug_log(0,0) << "delete " << rmNode << std::endl;
|
cdebug_log(0,0) << "delete " << rmNode->getValue() << std::endl;
|
||||||
delete rmNode;
|
delete rmNode;
|
||||||
|
|
||||||
--count_;
|
--count_;
|
||||||
|
|
||||||
cdebug_tabw(0,-1);
|
cdebug_tabw(0,-1);
|
||||||
|
@ -671,8 +684,13 @@ namespace Hurricane {
|
||||||
template< typename Data, typename Compare >
|
template< typename Data, typename Compare >
|
||||||
void RbTree<Data,Compare>::removeRepair ( typename RbTree<Data,Compare>::Node* rmNode, size_t depth )
|
void RbTree<Data,Compare>::removeRepair ( typename RbTree<Data,Compare>::Node* rmNode, size_t depth )
|
||||||
{
|
{
|
||||||
cdebug_log(0,1) << "RbTree::removeRepair() rmNode:" << rmNode
|
cdebug_log(0,1) << "RbTree::removeRepair() rmNode:" << rmNode->getValue()
|
||||||
<< " depth:" << depth << std::endl;
|
<< " depth:" << depth << std::endl;
|
||||||
|
|
||||||
|
if (not rmNode) {
|
||||||
|
cdebug_tabw(0,-1);
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
if (rmNode->isBlack()) {
|
if (rmNode->isBlack()) {
|
||||||
Node* parent = rmNode->getParent();
|
Node* parent = rmNode->getParent();
|
||||||
|
@ -979,6 +997,7 @@ namespace Hurricane {
|
||||||
void RbTreeToDot<Data,Compare,RbTree>::write ( std::ostream& o ) const
|
void RbTreeToDot<Data,Compare,RbTree>::write ( std::ostream& o ) const
|
||||||
{
|
{
|
||||||
o << "digraph RbTree {\n";
|
o << "digraph RbTree {\n";
|
||||||
|
o << " ratio=\"1.0\";\n";
|
||||||
toDot( o, tree_->getRoot() );
|
toDot( o, tree_->getRoot() );
|
||||||
o << "}";
|
o << "}";
|
||||||
}
|
}
|
||||||
|
@ -989,8 +1008,9 @@ namespace Hurricane {
|
||||||
{
|
{
|
||||||
if (not node) return;
|
if (not node) return;
|
||||||
|
|
||||||
|
string svalue = ::getString( node->getValue() );
|
||||||
o << " id_" << getId(node) << " "
|
o << " id_" << getId(node) << " "
|
||||||
<< "[label=\"id:" << getId(node) << "\\n" << ::getString(node->getValue())
|
<< "[label=\"id:" << getId(node) << "\\n" << split( svalue )
|
||||||
<< "\""
|
<< "\""
|
||||||
<< ",color=" << (node->isRed() ? "red" : "black")
|
<< ",color=" << (node->isRed() ? "red" : "black")
|
||||||
<< ",fontcolor=" << (node->isRed() ? "red" : "black")
|
<< ",fontcolor=" << (node->isRed() ? "red" : "black")
|
||||||
|
@ -1031,6 +1051,3 @@ namespace Hurricane {
|
||||||
|
|
||||||
|
|
||||||
} // Hurricane namespace.
|
} // Hurricane namespace.
|
||||||
|
|
||||||
|
|
||||||
#endif // HURRICANE_RBTREE_H
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// -*- C++ -*-
|
// -*- C++ -*-
|
||||||
//
|
//
|
||||||
// Copyright (c) BULL S.A. 2018-2018, All Rights Reserved
|
// Copyright (c) BULL S.A. 2018-2023, All Rights Reserved
|
||||||
//
|
//
|
||||||
// This file is part of Hurricane.
|
// This file is part of Hurricane.
|
||||||
//
|
//
|
||||||
|
@ -28,10 +28,7 @@
|
||||||
// | C++ Header : "./hurricane/Rectilinear.h" |
|
// | C++ Header : "./hurricane/Rectilinear.h" |
|
||||||
// +-----------------------------------------------------------------+
|
// +-----------------------------------------------------------------+
|
||||||
|
|
||||||
|
#pragma once
|
||||||
#ifndef HURRICANE_RECTILINEAR_H
|
|
||||||
#define HURRICANE_RECTILINEAR_H
|
|
||||||
|
|
||||||
#include "hurricane/Component.h"
|
#include "hurricane/Component.h"
|
||||||
|
|
||||||
|
|
||||||
|
@ -46,11 +43,13 @@ namespace Hurricane {
|
||||||
class Rectilinear : public Component {
|
class Rectilinear : public Component {
|
||||||
public:
|
public:
|
||||||
typedef Component Super;
|
typedef Component Super;
|
||||||
|
static const uint32_t IsRectilinear = (1<<0);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static Rectilinear* create ( Net*, const Layer*, const vector<Point>& );
|
static Rectilinear* create ( Net*, const Layer*, const vector<Point>& );
|
||||||
// Accessors.
|
// Accessors.
|
||||||
virtual bool isNonRectangle () const;
|
virtual bool isNonRectangle () const;
|
||||||
|
inline bool isRectilinear () const;
|
||||||
virtual DbU::Unit getX () const;
|
virtual DbU::Unit getX () const;
|
||||||
virtual DbU::Unit getY () const;
|
virtual DbU::Unit getY () const;
|
||||||
virtual Box getBoundingBox () const;
|
virtual Box getBoundingBox () const;
|
||||||
|
@ -59,6 +58,7 @@ namespace Hurricane {
|
||||||
virtual Point getPoint ( size_t i ) const;
|
virtual Point getPoint ( size_t i ) const;
|
||||||
virtual const Layer* getLayer () const;
|
virtual const Layer* getLayer () const;
|
||||||
inline Points getContour () const;
|
inline Points getContour () const;
|
||||||
|
bool getAsRectangles ( std::vector<Box>& ) const;
|
||||||
inline const vector<Point>& getPoints () const;
|
inline const vector<Point>& getPoints () const;
|
||||||
// Mutators.
|
// Mutators.
|
||||||
void setLayer ( const Layer* );
|
void setLayer ( const Layer* );
|
||||||
|
@ -75,11 +75,13 @@ namespace Hurricane {
|
||||||
private:
|
private:
|
||||||
const Layer* _layer;
|
const Layer* _layer;
|
||||||
vector<Point> _points;
|
vector<Point> _points;
|
||||||
|
uint32_t _flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
inline Points Rectilinear::getContour () const { return new VectorCollection<Point>(_points); }
|
inline bool Rectilinear::isRectilinear () const { return _flags & IsRectilinear; }
|
||||||
inline const vector<Point>& Rectilinear::getPoints () const { return _points; }
|
inline Points Rectilinear::getContour () const { return new VectorCollection<Point>(_points); }
|
||||||
|
inline const vector<Point>& Rectilinear::getPoints () const { return _points; }
|
||||||
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
|
@ -99,5 +101,3 @@ namespace Hurricane {
|
||||||
|
|
||||||
|
|
||||||
INSPECTOR_P_SUPPORT(Hurricane::Rectilinear);
|
INSPECTOR_P_SUPPORT(Hurricane::Rectilinear);
|
||||||
|
|
||||||
#endif // HURRICANE_RECTILINEAR_H
|
|
||||||
|
|
|
@ -45,6 +45,24 @@ namespace Isobar {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PyObject* VectorToList ( const std::vector<Box>& v )
|
||||||
|
{
|
||||||
|
PyObject* pyList = PyList_New( v.size() );
|
||||||
|
|
||||||
|
for ( size_t i=0 ; i<v.size() ; ++i ) {
|
||||||
|
PyBox* pyBox = PyObject_NEW( PyBox, &PyTypeBox );
|
||||||
|
if (not pyBox) { return NULL; }
|
||||||
|
|
||||||
|
HTRY
|
||||||
|
pyBox->_object = new Box ( v[i] );
|
||||||
|
HCATCH
|
||||||
|
PyList_SetItem( pyList, i, (PyObject*)pyBox );
|
||||||
|
}
|
||||||
|
|
||||||
|
return pyList;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
|
|
||||||
|
@ -168,20 +186,54 @@ extern "C" {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PyObject* PyRectilinear_getAsRectangles ( PyRectilinear *self, PyObject* args )
|
||||||
|
{
|
||||||
|
cdebug_log(20,0) << "Rectilinear.getAsRectangles()" << endl;
|
||||||
|
|
||||||
|
HTRY
|
||||||
|
METHOD_HEAD( "Rectilinear.getAsRectangles()" )
|
||||||
|
|
||||||
|
PyObject* pyList = NULL;
|
||||||
|
if (not PyArg_ParseTuple( args, "O:Rectilinear.getAsRectangles", &pyList )) {
|
||||||
|
PyErr_SetString( ConstructorError, "Rectilinear.getAsRectangles(): Must have exactly one parameter." );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (not PyList_Check(pyList)) {
|
||||||
|
PyErr_SetString( ConstructorError, "Rectilinear.getAsRectangles(): Argument must be a list." );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
PyList_SetSlice( pyList, 0, PyList_Size(pyList), NULL );
|
||||||
|
vector<Box> boxes;
|
||||||
|
rectilinear->getAsRectangles( boxes );
|
||||||
|
for ( size_t i=0 ; i<boxes.size() ; ++i ) {
|
||||||
|
PyBox* pyBox = PyObject_NEW( PyBox, &PyTypeBox );
|
||||||
|
if (not pyBox) { return NULL; }
|
||||||
|
|
||||||
|
pyBox->_object = new Box ( boxes[i] );
|
||||||
|
PyList_Append( pyList, (PyObject*)pyBox );
|
||||||
|
}
|
||||||
|
HCATCH
|
||||||
|
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// ---------------------------------------------------------------
|
// ---------------------------------------------------------------
|
||||||
// PyRectilinear Attribute Method table.
|
// PyRectilinear Attribute Method table.
|
||||||
|
|
||||||
PyMethodDef PyRectilinear_Methods[] =
|
PyMethodDef PyRectilinear_Methods[] =
|
||||||
{ { "create" , (PyCFunction)PyRectilinear_create , METH_VARARGS|METH_STATIC
|
{ { "create" , (PyCFunction)PyRectilinear_create , METH_VARARGS|METH_STATIC
|
||||||
, "Create a new Rectilinear polygon." }
|
, "Create a new Rectilinear polygon." }
|
||||||
, { "isNonRectangle", (PyCFunction)PyRectilinear_isNonRectangle, METH_NOARGS , "Tells if the shape is not a rectangle." }
|
, { "isNonRectangle" , (PyCFunction)PyRectilinear_isNonRectangle , METH_NOARGS , "Tells if the shape is not a rectangle." }
|
||||||
, { "getX" , (PyCFunction)PyRectilinear_getX , METH_NOARGS , "Return the Rectilinear X value." }
|
, { "getX" , (PyCFunction)PyRectilinear_getX , METH_NOARGS , "Return the Rectilinear X value." }
|
||||||
, { "getY" , (PyCFunction)PyRectilinear_getY , METH_NOARGS , "Return the Rectilinear Y value." }
|
, { "getY" , (PyCFunction)PyRectilinear_getY , METH_NOARGS , "Return the Rectilinear Y value." }
|
||||||
, { "getBoundingBox", (PyCFunction)PyRectilinear_getBoundingBox, METH_NOARGS , "Return the Rectilinear Bounding Box." }
|
, { "getBoundingBox" , (PyCFunction)PyRectilinear_getBoundingBox , METH_NOARGS , "Return the Rectilinear Bounding Box." }
|
||||||
, { "setPoints" , (PyCFunction)PyRectilinear_setPoints , METH_VARARGS, "Sets the Rectilinear Bounding Box." }
|
, { "setPoints" , (PyCFunction)PyRectilinear_setPoints , METH_VARARGS, "Sets the Rectilinear Bounding Box." }
|
||||||
, { "translate" , (PyCFunction)PyRectilinear_translate , METH_VARARGS, "Translates the Rectilinear of dx and dy." }
|
, { "translate" , (PyCFunction)PyRectilinear_translate , METH_VARARGS, "Translates the Rectilinear of dx and dy." }
|
||||||
, { "destroy" , (PyCFunction)PyRectilinear_destroy , METH_NOARGS
|
, { "getAsRectangles", (PyCFunction)PyRectilinear_getAsRectangles, METH_VARARGS, "Return the rectangle coverage." }
|
||||||
, "Destroy associated hurricane object, the python object remains." }
|
, { "destroy" , (PyCFunction)PyRectilinear_destroy , METH_NOARGS
|
||||||
|
, "Destroy associated hurricane object, the python object remains." }
|
||||||
, {NULL, NULL, 0, NULL} /* sentinel */
|
, {NULL, NULL, 0, NULL} /* sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1625,31 +1625,31 @@ extern "C" {
|
||||||
catch ( const Warning& w ) { \
|
catch ( const Warning& w ) { \
|
||||||
std::string message = getString(w); \
|
std::string message = getString(w); \
|
||||||
PyErr_Warn ( HurricaneWarning, const_cast<char*>(message.c_str()) ); \
|
PyErr_Warn ( HurricaneWarning, const_cast<char*>(message.c_str()) ); \
|
||||||
std::cerr << message << std::endl; \
|
std::cerr << message << std::endl; \
|
||||||
} \
|
} \
|
||||||
catch ( const Error& e ) { \
|
catch ( const Error& e ) { \
|
||||||
std::string message = getString(e); \
|
std::string message = getString(e); \
|
||||||
if (not e.where().empty()) message += "\n" + e.where(); \
|
if (not e.where().empty()) message += "\n" + e.where(); \
|
||||||
PyErr_SetString ( HurricaneError, message.c_str() ); \
|
PyErr_SetString ( HurricaneError, message.c_str() ); \
|
||||||
std::cerr << message << std::endl; \
|
std::cerr << message << std::endl; \
|
||||||
return NULL; \
|
return NULL; \
|
||||||
} \
|
} \
|
||||||
catch ( const Bug& e ) { \
|
catch ( const Bug& e ) { \
|
||||||
std::string message = getString(e); \
|
std::string message = getString(e); \
|
||||||
PyErr_SetString ( HurricaneError, message.c_str() ); \
|
PyErr_SetString ( HurricaneError, message.c_str() ); \
|
||||||
std::cerr << message << std::endl; \
|
std::cerr << message << std::endl; \
|
||||||
return NULL; \
|
return NULL; \
|
||||||
} \
|
} \
|
||||||
catch ( const Exception& e ) { \
|
catch ( const Exception& e ) { \
|
||||||
std::string message = "Unknown Hurricane::Exception"; \
|
std::string message = "Unknown Hurricane::Exception"; \
|
||||||
PyErr_SetString ( HurricaneError, message.c_str() ); \
|
PyErr_SetString ( HurricaneError, message.c_str() ); \
|
||||||
std::cerr << message << std::endl; \
|
std::cerr << message << std::endl; \
|
||||||
return NULL; \
|
return NULL; \
|
||||||
} \
|
} \
|
||||||
catch ( const std::exception& e ) { \
|
catch ( const std::exception& e ) { \
|
||||||
std::string message = std::string(e.what()); \
|
std::string message = std::string(e.what()); \
|
||||||
PyErr_SetString ( HurricaneError, message.c_str() ); \
|
PyErr_SetString ( HurricaneError, message.c_str() ); \
|
||||||
std::cerr << message << std::endl; \
|
std::cerr << message << std::endl; \
|
||||||
return NULL; \
|
return NULL; \
|
||||||
} \
|
} \
|
||||||
catch ( ... ) { \
|
catch ( ... ) { \
|
||||||
|
@ -1657,7 +1657,7 @@ extern "C" {
|
||||||
"Unmanaged exception, neither a Hurricane::Error nor" \
|
"Unmanaged exception, neither a Hurricane::Error nor" \
|
||||||
" a std::exception."; \
|
" a std::exception."; \
|
||||||
PyErr_SetString ( HurricaneError, message.c_str() ); \
|
PyErr_SetString ( HurricaneError, message.c_str() ); \
|
||||||
std::cerr << message << std::endl; \
|
std::cerr << message << std::endl; \
|
||||||
return NULL; \
|
return NULL; \
|
||||||
} \
|
} \
|
||||||
|
|
||||||
|
|
|
@ -157,8 +157,9 @@ namespace Hurricane {
|
||||||
|
|
||||||
//int scale = 80 * Cfg::getParamEnumerate("viewer.printer.mode")->asInt();
|
//int scale = 80 * Cfg::getParamEnumerate("viewer.printer.mode")->asInt();
|
||||||
int scale = (Graphics::isHighDpi()) ? 4 : 2;
|
int scale = (Graphics::isHighDpi()) ? 4 : 2;
|
||||||
_drawingWidth = _cellWidget->width () * scale;
|
_drawingWidth = _screenCellWidget->geometry().width () * scale;
|
||||||
_drawingHeight = _cellWidget->height() * scale;
|
_drawingHeight = _screenCellWidget->geometry().height() * scale;
|
||||||
|
_cellWidget->resize( _drawingWidth, _drawingHeight );
|
||||||
|
|
||||||
_image = new QImage( _drawingWidth
|
_image = new QImage( _drawingWidth
|
||||||
, _drawingHeight + ((_flags&ShowScale) ? 60 : 0)
|
, _drawingHeight + ((_flags&ShowScale) ? 60 : 0)
|
||||||
|
@ -188,7 +189,7 @@ namespace Hurricane {
|
||||||
setFitOnAbutmentBox( true );
|
setFitOnAbutmentBox( true );
|
||||||
_cellWidget->fitToContents();
|
_cellWidget->fitToContents();
|
||||||
} else {
|
} else {
|
||||||
//_cellWidget->reframe( _screenCellWidget->getVisibleArea() );
|
_cellWidget->reframe( _screenCellWidget->getVisibleArea() );
|
||||||
}
|
}
|
||||||
|
|
||||||
cerr << " After resize CellWidget: " << _cellWidget->geometry().width() << "x" << _cellWidget->geometry().height() << endl;
|
cerr << " After resize CellWidget: " << _cellWidget->geometry().width() << "x" << _cellWidget->geometry().height() << endl;
|
||||||
|
|
|
@ -584,7 +584,7 @@ namespace Hurricane {
|
||||||
|
|
||||||
void CellViewer::refreshTitle ()
|
void CellViewer::refreshTitle ()
|
||||||
{
|
{
|
||||||
QString cellName = "None";
|
QString cellName = "empty";
|
||||||
if ( getCell() )
|
if ( getCell() )
|
||||||
cellName = getString(getCell()->getName()).c_str();
|
cellName = getString(getCell()->getName()).c_str();
|
||||||
|
|
||||||
|
|
|
@ -2683,7 +2683,86 @@ namespace Hurricane {
|
||||||
} else
|
} else
|
||||||
selected = false;
|
selected = false;
|
||||||
|
|
||||||
if ( (--_delaySelectionChanged == 0) and selected ) emit selectionChanged( _selectors );
|
if ( (--_delaySelectionChanged == 0) and selected )
|
||||||
|
emit selectionChanged( _selectors );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CellWidget::selectSet ( const ComponentSet& components )
|
||||||
|
{
|
||||||
|
if ( (++_delaySelectionChanged == 1) and not _state->cumulativeSelection() ) {
|
||||||
|
openRefreshSession();
|
||||||
|
unselectAll();
|
||||||
|
closeRefreshSession();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool selected = true;
|
||||||
|
// SelectorCriterion* criterion = _state->getSelection().add ( selectArea );
|
||||||
|
// if ( criterion and (not criterion->isEnabled()) ) {
|
||||||
|
// criterion->enable();
|
||||||
|
|
||||||
|
for ( Component* component : components ) {
|
||||||
|
if (component->getCell() == getCell()) {
|
||||||
|
select( Occurrence( component ));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// } else
|
||||||
|
// selected = false;
|
||||||
|
|
||||||
|
if ( (--_delaySelectionChanged == 0) and selected )
|
||||||
|
emit selectionChanged( _selectors );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CellWidget::selectSet ( const OccurrenceSet& occurrences )
|
||||||
|
{
|
||||||
|
if ( (++_delaySelectionChanged == 1) and not _state->cumulativeSelection() ) {
|
||||||
|
openRefreshSession();
|
||||||
|
unselectAll();
|
||||||
|
closeRefreshSession();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool selected = true;
|
||||||
|
// SelectorCriterion* criterion = _state->getSelection().add ( selectArea );
|
||||||
|
// if ( criterion and (not criterion->isEnabled()) ) {
|
||||||
|
// criterion->enable();
|
||||||
|
|
||||||
|
for ( const Occurrence& occurrence : occurrences ) {
|
||||||
|
if (occurrence.getOwnerCell() == getCell()) {
|
||||||
|
select( occurrence );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// } else
|
||||||
|
// selected = false;
|
||||||
|
|
||||||
|
if ( (--_delaySelectionChanged == 0) and selected )
|
||||||
|
emit selectionChanged( _selectors );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CellWidget::select ( Occurrences occurrences )
|
||||||
|
{
|
||||||
|
if ( (++_delaySelectionChanged == 1) and not _state->cumulativeSelection() ) {
|
||||||
|
openRefreshSession();
|
||||||
|
unselectAll();
|
||||||
|
closeRefreshSession();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool selected = true;
|
||||||
|
// SelectorCriterion* criterion = _state->getSelection().add ( selectArea );
|
||||||
|
// if ( criterion and (not criterion->isEnabled()) ) {
|
||||||
|
// criterion->enable();
|
||||||
|
|
||||||
|
for ( const Occurrence& occurrence : occurrences ) {
|
||||||
|
if (occurrence.getOwnerCell() == getCell()) {
|
||||||
|
select( occurrence );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// } else
|
||||||
|
// selected = false;
|
||||||
|
|
||||||
|
if ( (--_delaySelectionChanged == 0) and selected )
|
||||||
|
emit selectionChanged( _selectors );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2744,7 +2823,7 @@ namespace Hurricane {
|
||||||
|
|
||||||
if ( (--_delaySelectionChanged == 0) and selected ) {
|
if ( (--_delaySelectionChanged == 0) and selected ) {
|
||||||
if ( _state->showSelection() ) _redrawManager.refresh ();
|
if ( _state->showSelection() ) _redrawManager.refresh ();
|
||||||
emit selectionChanged(_selectors);
|
emit selectionChanged(_selectors);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2782,7 +2861,47 @@ namespace Hurricane {
|
||||||
}
|
}
|
||||||
|
|
||||||
_selectionHasChanged = true;
|
_selectionHasChanged = true;
|
||||||
if ( (_delaySelectionChanged == 0) and unselected ) emit selectionChanged( _selectors );
|
if ( (_delaySelectionChanged == 0) and unselected )
|
||||||
|
emit selectionChanged( _selectors );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CellWidget::unselectSet ( const ComponentSet& components )
|
||||||
|
{
|
||||||
|
++_delaySelectionChanged;
|
||||||
|
for ( Component* component : components ) {
|
||||||
|
if (component->getCell() == getCell()) {
|
||||||
|
unselect( Occurrence( component ));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( --_delaySelectionChanged == 0 )
|
||||||
|
emit selectionChanged( _selectors );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CellWidget::unselectSet ( const OccurrenceSet& occurrences )
|
||||||
|
{
|
||||||
|
++_delaySelectionChanged;
|
||||||
|
for ( const Occurrence& occurrence : occurrences ) {
|
||||||
|
if (occurrence.getOwnerCell() == getCell()) {
|
||||||
|
unselect( occurrence );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( --_delaySelectionChanged == 0 )
|
||||||
|
emit selectionChanged( _selectors );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void CellWidget::unselect ( Occurrences occurrences )
|
||||||
|
{
|
||||||
|
++_delaySelectionChanged;
|
||||||
|
for ( const Occurrence& occurrence : occurrences ) {
|
||||||
|
if (occurrence.getOwnerCell() == getCell()) {
|
||||||
|
unselect( occurrence );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( --_delaySelectionChanged == 0 )
|
||||||
|
emit selectionChanged( _selectors );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -2793,7 +2912,8 @@ namespace Hurricane {
|
||||||
_state->getSelection().clear ();
|
_state->getSelection().clear ();
|
||||||
_unselectAll ();
|
_unselectAll ();
|
||||||
|
|
||||||
if ( --_delaySelectionChanged == 0 ) emit selectionChanged(_selectors);
|
if ( --_delaySelectionChanged == 0 )
|
||||||
|
emit selectionChanged(_selectors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -658,6 +658,19 @@ namespace Hurricane {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ControllerWidget::insertTabAfter ( const QString& ref, QWidget* tab, const QString& label )
|
||||||
|
{
|
||||||
|
for ( int itab=0 ; true; ++itab ) {
|
||||||
|
QWidget* refTab = widget( itab );
|
||||||
|
if (not refTab) break;
|
||||||
|
if (refTab->objectName() != ref) continue;
|
||||||
|
insertTab( itab, tab, label );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
addTab( tab, label );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
// Class : "ControllerWidget::GraphicsObserver".
|
// Class : "ControllerWidget::GraphicsObserver".
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ namespace Hurricane {
|
||||||
|
|
||||||
|
|
||||||
int SimpleNetInformations::getColumnCount ()
|
int SimpleNetInformations::getColumnCount ()
|
||||||
{ return 3; }
|
{ return 6; }
|
||||||
|
|
||||||
|
|
||||||
QVariant SimpleNetInformations::getColumnName ( int column )
|
QVariant SimpleNetInformations::getColumnName ( int column )
|
||||||
|
@ -71,7 +71,10 @@ namespace Hurricane {
|
||||||
switch ( column ) {
|
switch ( column ) {
|
||||||
case 0: return QVariant(QObject::tr("Net"));
|
case 0: return QVariant(QObject::tr("Net"));
|
||||||
case 1: return QVariant(QObject::tr("Plugs"));
|
case 1: return QVariant(QObject::tr("Plugs"));
|
||||||
case 2: return QVariant(QObject::tr("RoutingPads"));
|
case 2: return QVariant(QObject::tr("RPs"));
|
||||||
|
case 3: return QVariant(QObject::tr("Flags"));
|
||||||
|
case 4: return QVariant(QObject::tr("Type"));
|
||||||
|
case 5: return QVariant(QObject::tr("Direction"));
|
||||||
}
|
}
|
||||||
return QVariant(QObject::tr("Column Out of Bound"));
|
return QVariant(QObject::tr("Column Out of Bound"));
|
||||||
}
|
}
|
||||||
|
@ -84,11 +87,15 @@ namespace Hurricane {
|
||||||
case 1: return (unsigned int)_plugsCount;
|
case 1: return (unsigned int)_plugsCount;
|
||||||
case 2:
|
case 2:
|
||||||
if (_net->isGlobal()) {
|
if (_net->isGlobal()) {
|
||||||
if (not _rpsCount) return "N/A (global)";
|
if (not _rpsCount) return "N/A";
|
||||||
string s = getString(_rpsCount) + " (global)";
|
string s = getString(_rpsCount);
|
||||||
return s.c_str();
|
return s.c_str();
|
||||||
}
|
}
|
||||||
return (unsigned int)_rpsCount;
|
return (unsigned int)_rpsCount;
|
||||||
|
case 3: return QString::fromStdString( getString( _net->_getFlagsAsString() ));
|
||||||
|
case 4: return QString::fromStdString( getString( _net->getType() ));
|
||||||
|
case 5: return QString::fromStdString( getString( _net->getDirection() ));
|
||||||
|
|
||||||
}
|
}
|
||||||
return QVariant(QObject::tr("Column Out of Bound"));
|
return QVariant(QObject::tr("Column Out of Bound"));
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,7 +70,7 @@ namespace Hurricane {
|
||||||
|
|
||||||
QHeaderView* horizontalHeader = _view->horizontalHeader();
|
QHeaderView* horizontalHeader = _view->horizontalHeader();
|
||||||
horizontalHeader->setDefaultAlignment ( Qt::AlignHCenter );
|
horizontalHeader->setDefaultAlignment ( Qt::AlignHCenter );
|
||||||
horizontalHeader->setMinimumSectionSize( (Graphics::isHighDpi()) ? 300 : 150 );
|
horizontalHeader->setMinimumSectionSize( (Graphics::isHighDpi()) ? 150 : 75 );
|
||||||
horizontalHeader->setStretchLastSection( true );
|
horizontalHeader->setStretchLastSection( true );
|
||||||
|
|
||||||
QHeaderView* verticalHeader = _view->verticalHeader();
|
QHeaderView* verticalHeader = _view->verticalHeader();
|
||||||
|
@ -151,24 +151,18 @@ namespace Hurricane {
|
||||||
_forceReselect = false;
|
_forceReselect = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SelectedNetSet::iterator remove;
|
SelectedNetSet::iterator isel = _selecteds.begin ();
|
||||||
SelectedNetSet::iterator isel = _selecteds.begin ();
|
|
||||||
while ( isel != _selecteds.end() ) {
|
while ( isel != _selecteds.end() ) {
|
||||||
switch ( isel->getAccesses() ) {
|
SelectedNetSet::iterator remove = isel++;
|
||||||
case 1: break;
|
if ( remove->getAccesses() == 0 ) {
|
||||||
case 64:
|
emit netUnselected ( Occurrence(remove->getNet()) );
|
||||||
emit netSelected ( Occurrence(isel->getNet()) );
|
_selecteds.erase ( remove );
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
emit netUnselected ( Occurrence(isel->getNet()) );
|
|
||||||
remove = isel;
|
|
||||||
++isel;
|
|
||||||
_selecteds.erase ( remove );
|
|
||||||
continue;
|
|
||||||
default:
|
|
||||||
cerr << Bug("NetlistWidget::updateSelecteds(): invalid code %d"
|
|
||||||
,isel->getAccesses()) << endl;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
isel = _selecteds.begin ();
|
||||||
|
while ( isel != _selecteds.end() ) {
|
||||||
|
if ( isel->getAccesses() == 64 )
|
||||||
|
emit netSelected ( Occurrence(isel->getNet()) );
|
||||||
++isel;
|
++isel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -219,6 +219,7 @@ extern "C" {
|
||||||
}
|
}
|
||||||
|
|
||||||
cw->setApplicationName ( name );
|
cw->setApplicationName ( name );
|
||||||
|
cw->refreshTitle ();
|
||||||
HCATCH
|
HCATCH
|
||||||
|
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
|
|
|
@ -91,8 +91,8 @@ namespace Hurricane {
|
||||||
{
|
{
|
||||||
if (not _cellWidget) return;
|
if (not _cellWidget) return;
|
||||||
|
|
||||||
|
if (not isCumulative()) clear ();
|
||||||
beginResetModel();
|
beginResetModel();
|
||||||
if (not isCumulative()) _selection.clear ();
|
|
||||||
|
|
||||||
for ( Selector* selector : selection ) {
|
for ( Selector* selector : selection ) {
|
||||||
if (not selector->isInModel(_cellWidget)) {
|
if (not selector->isInModel(_cellWidget)) {
|
||||||
|
|
|
@ -87,6 +87,7 @@ namespace Hurricane {
|
||||||
CellViewer ( QWidget* parent=NULL );
|
CellViewer ( QWidget* parent=NULL );
|
||||||
virtual ~CellViewer ();
|
virtual ~CellViewer ();
|
||||||
inline bool isToolInterrupted () const;
|
inline bool isToolInterrupted () const;
|
||||||
|
void refreshTitle ();
|
||||||
QMenu* createDebugMenu ();
|
QMenu* createDebugMenu ();
|
||||||
bool hasMenu ( const QString& path ) const;
|
bool hasMenu ( const QString& path ) const;
|
||||||
bool hasMenuAction ( const QString& path ) const;
|
bool hasMenuAction ( const QString& path ) const;
|
||||||
|
@ -166,7 +167,6 @@ namespace Hurricane {
|
||||||
void cellPostModificated ();
|
void cellPostModificated ();
|
||||||
protected:
|
protected:
|
||||||
void createMenus ();
|
void createMenus ();
|
||||||
void refreshTitle ();
|
|
||||||
void refreshHistory ();
|
void refreshHistory ();
|
||||||
void rebuildHistory ();
|
void rebuildHistory ();
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -265,10 +265,16 @@ namespace Hurricane {
|
||||||
inline DrawingPlanes& getDrawingPlanes ();
|
inline DrawingPlanes& getDrawingPlanes ();
|
||||||
// void select ( const Net* );
|
// void select ( const Net* );
|
||||||
void select ( Occurrence );
|
void select ( Occurrence );
|
||||||
|
void select ( Occurrences );
|
||||||
|
void selectSet ( const OccurrenceSet& );
|
||||||
|
void selectSet ( const ComponentSet& );
|
||||||
bool isSelected ( Occurrence );
|
bool isSelected ( Occurrence );
|
||||||
void selectOccurrencesUnder ( Box selectArea );
|
void selectOccurrencesUnder ( Box selectArea );
|
||||||
// void unselect ( const Net* );
|
// void unselect ( const Net* );
|
||||||
void unselect ( Occurrence );
|
void unselect ( Occurrence );
|
||||||
|
void unselect ( Occurrences );
|
||||||
|
void unselectSet ( const ComponentSet& );
|
||||||
|
void unselectSet ( const OccurrenceSet& );
|
||||||
void unselectAll ();
|
void unselectAll ();
|
||||||
void toggleSelection ( Occurrence );
|
void toggleSelection ( Occurrence );
|
||||||
void setShowSelection ( bool state );
|
void setShowSelection ( bool state );
|
||||||
|
|
|
@ -312,6 +312,7 @@ namespace Hurricane {
|
||||||
inline TabSettings* getSettings ();
|
inline TabSettings* getSettings ();
|
||||||
void setCellWidget ( CellWidget* );
|
void setCellWidget ( CellWidget* );
|
||||||
//inline int addSetting ( QWidget* page, const QString& label );
|
//inline int addSetting ( QWidget* page, const QString& label );
|
||||||
|
void insertTabAfter ( const QString& ref, QWidget*, const QString& label );
|
||||||
public slots:
|
public slots:
|
||||||
void graphicsUpdated ();
|
void graphicsUpdated ();
|
||||||
void cellPreModificate ();
|
void cellPreModificate ();
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
# -*- explicit-buffer-name: "CMakeLists.txt<tramontana>" -*-
|
||||||
|
|
||||||
|
set(CMAKE_LEGACY_CYGWIN_WIN32 0)
|
||||||
|
project(TRAMONTANA)
|
||||||
|
|
||||||
|
set(ignoreVariables "${BUILD_DOC} ${CMAKE_INSTALL_DIR}")
|
||||||
|
|
||||||
|
option(BUILD_DOC "Build the documentation (doxygen)" OFF)
|
||||||
|
option(USE_LIBBFD "Link with BFD libraries to print stack traces" OFF)
|
||||||
|
|
||||||
|
cmake_minimum_required(VERSION 3.16)
|
||||||
|
|
||||||
|
list(INSERT CMAKE_MODULE_PATH 0 "${DESTDIR}$ENV{CORIOLIS_TOP}/share/cmake/Modules/")
|
||||||
|
find_package(Bootstrap REQUIRED)
|
||||||
|
setup_project_paths(CORIOLIS)
|
||||||
|
|
||||||
|
set_cmake_policies()
|
||||||
|
setup_boost()
|
||||||
|
setup_qt()
|
||||||
|
|
||||||
|
find_package(Python 3 REQUIRED COMPONENTS Interpreter Development)
|
||||||
|
find_package(PythonSitePackages REQUIRED)
|
||||||
|
find_package(HURRICANE REQUIRED)
|
||||||
|
find_package(CORIOLIS REQUIRED)
|
||||||
|
find_package(Doxygen)
|
||||||
|
|
||||||
|
add_subdirectory(src)
|
||||||
|
#add_subdirectory(cmake_modules)
|
||||||
|
#add_subdirectory(doc)
|
|
@ -0,0 +1,78 @@
|
||||||
|
# -*- explicit-buffer-name: "CMakeLists.txt<tramontana/src>" -*-
|
||||||
|
|
||||||
|
# include( ${QT_USE_FILE} )
|
||||||
|
include_directories( ${TRAMONTANA_SOURCE_DIR}/src
|
||||||
|
${CORIOLIS_INCLUDE_DIR}
|
||||||
|
${HURRICANE_INCLUDE_DIR}
|
||||||
|
${CONFIGURATION_INCLUDE_DIR}
|
||||||
|
${QtX_INCLUDE_DIRS}
|
||||||
|
${Boost_INCLUDE_DIRS}
|
||||||
|
${Python_INCLUDE_DIRS}
|
||||||
|
)
|
||||||
|
set( includes tramontana/Tile.h
|
||||||
|
tramontana/QueryTiles.h
|
||||||
|
tramontana/SweepLine.h
|
||||||
|
tramontana/Equipotential.h
|
||||||
|
tramontana/EquipotentialRelation.h
|
||||||
|
tramontana/EquipotentialComponents.h
|
||||||
|
tramontana/TramontanaEngine.h
|
||||||
|
tramontana/GraphicTramontanaEngine.h
|
||||||
|
)
|
||||||
|
set( pyIncludes tramontana/PyTramontanaEngine.h
|
||||||
|
tramontana/PyGraphicTramontanaEngine.h
|
||||||
|
)
|
||||||
|
set( mocIncludes tramontana/GraphicTramontanaEngine.h
|
||||||
|
tramontana/EquipotentialsModel.h
|
||||||
|
tramontana/EquipotentialsWidget.h
|
||||||
|
tramontana/TabEquipotentials.h
|
||||||
|
)
|
||||||
|
set( cpps Tile.cpp
|
||||||
|
QueryTiles.cpp
|
||||||
|
SweepLine.cpp
|
||||||
|
Equipotential.cpp
|
||||||
|
EquipotentialRelation.cpp
|
||||||
|
EquipotentialComponents.cpp
|
||||||
|
TramontanaEngine.cpp
|
||||||
|
GraphicTramontanaEngine.cpp
|
||||||
|
EquipotentialsModel.cpp
|
||||||
|
EquipotentialsWidget.cpp
|
||||||
|
TabEquipotentials.cpp
|
||||||
|
)
|
||||||
|
set( pyCpps PyTramontana.cpp
|
||||||
|
PyTramontanaEngine.cpp
|
||||||
|
PyGraphicTramontanaEngine.cpp
|
||||||
|
)
|
||||||
|
qtX_wrap_cpp( mocCpps ${mocIncludes} )
|
||||||
|
|
||||||
|
set( depLibs ${CORIOLIS_PYTHON_LIBRARIES}
|
||||||
|
${CORIOLIS_LIBRARIES}
|
||||||
|
${HURRICANE_PYTHON_LIBRARIES}
|
||||||
|
${HURRICANE_GRAPHICAL_LIBRARIES}
|
||||||
|
${HURRICANE_LIBRARIES}
|
||||||
|
${CONFIGURATION_LIBRARY}
|
||||||
|
${UTILITIES_LIBRARY}
|
||||||
|
${LEFDEF_LIBRARIES}
|
||||||
|
${QtX_LIBRARIES}
|
||||||
|
${Boost_LIBRARIES}
|
||||||
|
${Python3_LIBRARIES}
|
||||||
|
-lutil
|
||||||
|
${LIBEXECINFO_LIBRARIES}
|
||||||
|
)
|
||||||
|
|
||||||
|
add_library( tramontana ${cpps} ${mocCpps} ${pyCpps} )
|
||||||
|
set_target_properties( tramontana PROPERTIES VERSION 1.0 SOVERSION 1 )
|
||||||
|
target_link_libraries( tramontana ${depLibs} )
|
||||||
|
|
||||||
|
add_python_module( "${pyCpps}"
|
||||||
|
"${pyIncludes}"
|
||||||
|
"Do_not_generate_C_library"
|
||||||
|
Tramontana
|
||||||
|
"tramontana;${depLibs}"
|
||||||
|
include/coriolis2/tramontana
|
||||||
|
)
|
||||||
|
|
||||||
|
install( TARGETS tramontana DESTINATION lib${LIB_SUFFIX} )
|
||||||
|
install( FILES ${includes}
|
||||||
|
${mocIncludes} DESTINATION include/coriolis2/tramontana )
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,533 @@
|
||||||
|
// -*- C++ -*-
|
||||||
|
//
|
||||||
|
// This file is part of the Coriolis Software.
|
||||||
|
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||||
|
//
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
// | C O R I O L I S |
|
||||||
|
// | T r a m o n t a n a - Extractor & LVX |
|
||||||
|
// | |
|
||||||
|
// | Algorithm : Christian MASSON |
|
||||||
|
// | First impl. : Yifei WU |
|
||||||
|
// | Second impl. : Jean-Paul CHAPUT |
|
||||||
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||||
|
// | =============================================================== |
|
||||||
|
// | C++ Module : "./Equipotential.cpp" |
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
#include <iomanip>
|
||||||
|
#include <set>
|
||||||
|
#include <map>
|
||||||
|
#include "hurricane/utilities/Path.h"
|
||||||
|
#include "hurricane/DebugSession.h"
|
||||||
|
#include "hurricane/UpdateSession.h"
|
||||||
|
#include "hurricane/Bug.h"
|
||||||
|
#include "hurricane/Error.h"
|
||||||
|
#include "hurricane/Warning.h"
|
||||||
|
#include "hurricane/Breakpoint.h"
|
||||||
|
#include "hurricane/Timer.h"
|
||||||
|
#include "hurricane/Layer.h"
|
||||||
|
#include "hurricane/Net.h"
|
||||||
|
#include "hurricane/Pad.h"
|
||||||
|
#include "hurricane/Contact.h"
|
||||||
|
#include "hurricane/Plug.h"
|
||||||
|
#include "hurricane/Cell.h"
|
||||||
|
#include "hurricane/Instance.h"
|
||||||
|
#include "hurricane/Vertical.h"
|
||||||
|
#include "hurricane/Horizontal.h"
|
||||||
|
#include "hurricane/RoutingPad.h"
|
||||||
|
#include "crlcore/Utilities.h"
|
||||||
|
#include "tramontana/Equipotential.h"
|
||||||
|
#include "tramontana/EquipotentialRelation.h"
|
||||||
|
#include "tramontana/EquipotentialComponents.h"
|
||||||
|
#include "tramontana/TramontanaEngine.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Tramontana {
|
||||||
|
|
||||||
|
using std::cout;
|
||||||
|
using std::cerr;
|
||||||
|
using std::endl;
|
||||||
|
using std::dec;
|
||||||
|
using std::setw;
|
||||||
|
using std::setfill;
|
||||||
|
using std::left;
|
||||||
|
using std::string;
|
||||||
|
using std::ostream;
|
||||||
|
using std::ofstream;
|
||||||
|
using std::ostringstream;
|
||||||
|
using std::setprecision;
|
||||||
|
using std::vector;
|
||||||
|
using std::set;
|
||||||
|
using std::make_pair;
|
||||||
|
using Hurricane::dbo_ptr;
|
||||||
|
using Hurricane::UpdateSession;
|
||||||
|
using Hurricane::DebugSession;
|
||||||
|
using Hurricane::tab;
|
||||||
|
using Hurricane::Bug;
|
||||||
|
using Hurricane::Error;
|
||||||
|
using Hurricane::Warning;
|
||||||
|
using Hurricane::Breakpoint;
|
||||||
|
using Hurricane::Box;
|
||||||
|
using Hurricane::Layer;
|
||||||
|
using Hurricane::Entity;
|
||||||
|
using Hurricane::Net;
|
||||||
|
using Hurricane::Plug;
|
||||||
|
using Hurricane::Contact;
|
||||||
|
using Hurricane::Horizontal;
|
||||||
|
using Hurricane::Vertical;
|
||||||
|
using Hurricane::RoutingPad;
|
||||||
|
using Hurricane::Cell;
|
||||||
|
using Hurricane::Instance;
|
||||||
|
using Hurricane::Path;
|
||||||
|
|
||||||
|
|
||||||
|
bool NetCompareByName::operator() ( const Net* lhs, const Net* rhs ) const
|
||||||
|
{
|
||||||
|
if (lhs->isFused () != rhs->isFused ()) return rhs->isFused();
|
||||||
|
if (lhs->isAutomatic() != rhs->isAutomatic()) return rhs->isAutomatic();
|
||||||
|
if (lhs->isGlobal () != rhs->isGlobal ()) return rhs->isGlobal();
|
||||||
|
|
||||||
|
if (lhs->getName().size() != rhs->getName().size())
|
||||||
|
return lhs->getName().size() < rhs->getName().size();
|
||||||
|
return lhs->getName() < rhs->getName();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool OccNetCompareByName::operator() ( const Occurrence& lhs, const Occurrence& rhs ) const
|
||||||
|
{
|
||||||
|
static NetCompareByName compareByName;
|
||||||
|
|
||||||
|
size_t lhsLength = lhs.getPath().getInstances().getSize();
|
||||||
|
size_t rhsLength = rhs.getPath().getInstances().getSize();
|
||||||
|
|
||||||
|
if (lhsLength != rhsLength) return lhsLength < rhsLength;
|
||||||
|
return compareByName( static_cast<Net*>(lhs.getEntity()), static_cast<Net*>(rhs.getEntity()) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : "Tramontana::Equipotential".
|
||||||
|
|
||||||
|
|
||||||
|
Equipotential* Equipotential::get ( Component* component )
|
||||||
|
{
|
||||||
|
EquipotentialRelation* relation = dynamic_cast<EquipotentialRelation*>(
|
||||||
|
component->getNet()->getProperty( EquipotentialRelation::staticGetName() ));
|
||||||
|
if (not relation) {
|
||||||
|
relation = dynamic_cast<EquipotentialRelation*>(
|
||||||
|
component->getProperty( EquipotentialRelation::staticGetName() ));
|
||||||
|
}
|
||||||
|
if (not relation) return nullptr;
|
||||||
|
return dynamic_cast<Equipotential*>( relation->getMasterOwner() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Equipotential* Equipotential::get ( Occurrence occurrence )
|
||||||
|
{
|
||||||
|
EquipotentialRelation* relation = dynamic_cast<EquipotentialRelation*>(
|
||||||
|
occurrence.getProperty( EquipotentialRelation::staticGetName() ));
|
||||||
|
if (not relation) return nullptr;
|
||||||
|
return dynamic_cast<Equipotential*>( relation->getMasterOwner() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Occurrence Equipotential::getChildEqui ( Occurrence flatOccurrence )
|
||||||
|
{
|
||||||
|
Component* component = dynamic_cast<Component*>( flatOccurrence.getEntity() );
|
||||||
|
if (not component) {
|
||||||
|
cerr << Error( "Equipotential::getChildEqui(): Occurrence must be over a Component.\n"
|
||||||
|
" (on:%s)"
|
||||||
|
, getString(flatOccurrence).c_str()
|
||||||
|
) << endl;
|
||||||
|
return Occurrence();
|
||||||
|
}
|
||||||
|
|
||||||
|
Equipotential* equi = Equipotential::get( component );
|
||||||
|
if (not equi) {
|
||||||
|
cerr << Error( "Equipotential::getChildEqui(): Component not associated to an Equipotential.\n"
|
||||||
|
" (on:%s)"
|
||||||
|
, getString(flatOccurrence).c_str()
|
||||||
|
) << endl;
|
||||||
|
return Occurrence();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flatOccurrence.getPath().isEmpty()) return flatOccurrence;
|
||||||
|
|
||||||
|
// cerr << "childEqui:" << flatOccurrence << endl;
|
||||||
|
// cerr << " " << equi << endl;
|
||||||
|
Instance* tailInst = flatOccurrence.getPath().getTailInstance();
|
||||||
|
Path headPath = flatOccurrence.getPath().getHeadPath();
|
||||||
|
Occurrence tailOccurrence;
|
||||||
|
while ( tailInst ) {
|
||||||
|
tailOccurrence = Occurrence( equi, tailInst );
|
||||||
|
equi = Equipotential::get( tailOccurrence );
|
||||||
|
tailInst = headPath.getTailInstance();
|
||||||
|
headPath = headPath.getHeadPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
// cerr << " ==> " << tailOccurrence << endl;
|
||||||
|
// cerr << " " << equi << endl;
|
||||||
|
return tailOccurrence;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Equipotential::Equipotential ( Cell* owner )
|
||||||
|
: _owner (owner)
|
||||||
|
, _boundingBox ()
|
||||||
|
, _components ()
|
||||||
|
, _childs ()
|
||||||
|
, _name ()
|
||||||
|
, _type (Net::Type::UNDEFINED)
|
||||||
|
, _direction (Net::Direction::DirUndefined)
|
||||||
|
, _netCount (0)
|
||||||
|
, _isBuried (false)
|
||||||
|
, _isExternal (false)
|
||||||
|
, _isGlobal (false)
|
||||||
|
, _isAutomatic (false)
|
||||||
|
, _hasFused (false)
|
||||||
|
, _shortCircuits()
|
||||||
|
{
|
||||||
|
_name = "Unnamed_" + getString( getId() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Equipotential::_postCreate ()
|
||||||
|
{
|
||||||
|
Super::_postCreate();
|
||||||
|
TramontanaEngine* tramontana = TramontanaEngine::get( _owner );
|
||||||
|
tramontana->add( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Equipotential* Equipotential::create ( Cell* owner )
|
||||||
|
{
|
||||||
|
Equipotential* equi = new Equipotential ( owner );
|
||||||
|
equi->_postCreate();
|
||||||
|
return equi;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Equipotential::_preDestroy ()
|
||||||
|
{
|
||||||
|
Super::_preDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Equipotential::~Equipotential ()
|
||||||
|
{
|
||||||
|
for ( ShortCircuit* shortCircuit : _shortCircuits ) delete shortCircuit;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Cell* Equipotential::getCell () const
|
||||||
|
{ return _owner; }
|
||||||
|
|
||||||
|
|
||||||
|
Box Equipotential::getBoundingBox () const
|
||||||
|
{ return _boundingBox; }
|
||||||
|
|
||||||
|
|
||||||
|
Occurrences Equipotential::getFlatComponents () const
|
||||||
|
{ return EquipotentialComponents( this ); }
|
||||||
|
|
||||||
|
|
||||||
|
void Equipotential::add ( Occurrence occ, const Box& boundingBox )
|
||||||
|
{
|
||||||
|
if(occ.getPath().isEmpty()) {
|
||||||
|
Contact* contact = dynamic_cast<Contact*>( occ.getEntity() );
|
||||||
|
if ((_components.find(occ) != _components.end())) {
|
||||||
|
if (not contact)
|
||||||
|
cdebug_log(160,0) << "Equipotential::add(): Duplicated " << occ.getCompactString() << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Component* comp = dynamic_cast<Component*>( occ.getEntity() );
|
||||||
|
if (not comp) {
|
||||||
|
cerr << Error( "Equipotential::add(): Occurrences with null Path must be Components.\n"
|
||||||
|
" (on:%s)"
|
||||||
|
, getString(occ).c_str()
|
||||||
|
) << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cdebug_log(160,0) << "Equipotential::add(): " << occ << endl;
|
||||||
|
_components.insert( occ );
|
||||||
|
NetMap::iterator inet = _nets.find( comp->getNet() );
|
||||||
|
if (inet != _nets.end()) {
|
||||||
|
inet->second.first++;
|
||||||
|
if (inet->second.first > inet->second.second) {
|
||||||
|
cerr << Error( "Equipotential::add(): Doubly counted component of %s.\n"
|
||||||
|
" (on:%s)"
|
||||||
|
, getString(inet->first).c_str()
|
||||||
|
, getString(occ).c_str()
|
||||||
|
) << endl;
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
uint32_t compCount = 0;
|
||||||
|
for ( Component* component : comp->getNet()->getComponents() ) {
|
||||||
|
if (dynamic_cast<Plug*>(component)) continue;
|
||||||
|
++compCount;
|
||||||
|
}
|
||||||
|
_nets.insert( make_pair( comp->getNet(), make_pair(1,compCount) ));
|
||||||
|
if (comp->getNet()->isFused()) {
|
||||||
|
_hasFused = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (_nets.size() <= 1 + ((_hasFused) ? 1 : 0))
|
||||||
|
return;
|
||||||
|
Net* netA = nullptr;
|
||||||
|
for ( auto item : _nets ) {
|
||||||
|
if (not item.first->isFused() and (item.first != comp->getNet())) {
|
||||||
|
netA = item.first;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_shortCircuits.push_back( new ShortCircuit( netA, comp->getNet(), comp ));
|
||||||
|
} else {
|
||||||
|
Equipotential* equi = dynamic_cast<Equipotential*>( occ.getEntity() );
|
||||||
|
if (not equi) {
|
||||||
|
cerr << Error( "Equipotential::add(): Occurrence is not an Equipotential.\n"
|
||||||
|
" (on:%s)"
|
||||||
|
, getString(occ).c_str()
|
||||||
|
) << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (not occ.getPath().getTailPath().isEmpty()) {
|
||||||
|
cerr << Error( "Equipotential::add(): Occurrence is more than one instances deep.\n"
|
||||||
|
" (on:%s)"
|
||||||
|
, getString(occ).c_str()
|
||||||
|
) << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
_childs.insert( occ );
|
||||||
|
}
|
||||||
|
_boundingBox.merge( boundingBox );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Equipotential::merge ( Equipotential* other )
|
||||||
|
{
|
||||||
|
if (this == other) {
|
||||||
|
cerr << Warning( "Equipotential::merge(): Attempt to merge itself (ignored).\n"
|
||||||
|
" (on: %s)"
|
||||||
|
, getString(this).c_str()
|
||||||
|
) << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( auto otherNetData : other->_nets ) {
|
||||||
|
NetMap::iterator inet = _nets.find( otherNetData.first );
|
||||||
|
if (inet != _nets.end()) {
|
||||||
|
//inet->second.first += otherNetData.second.first;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (otherNetData.first->isFused()) _hasFused = true;
|
||||||
|
_nets.insert( make_pair( otherNetData.first, make_pair(0,otherNetData.second.second) ));
|
||||||
|
|
||||||
|
if (_nets.size() > 1 + ((_hasFused) ? 1 : 0)) {
|
||||||
|
cdebug_log(169,0) << "Short by merging equis." << _nets.size() << endl;
|
||||||
|
for ( auto inet : _nets ) {
|
||||||
|
cdebug_log(169,0) << "this | " << inet.first << endl;
|
||||||
|
}
|
||||||
|
for ( auto inet : other->_nets ) {
|
||||||
|
cdebug_log(169,0) << "other | " << inet.first << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//cerr << "Equipotential::merge() " << this << endl;
|
||||||
|
//cerr << " " << other << endl;
|
||||||
|
for ( const Occurrence& component : other->getComponents () ) add( component );
|
||||||
|
for ( const Occurrence& child : other->getChilds () ) add( child );
|
||||||
|
for ( ShortCircuit* shortCircuit : other->getShortCircuits () ) add( shortCircuit );
|
||||||
|
_boundingBox.merge( other->_boundingBox );
|
||||||
|
//cerr << "Equipotential::merge() done" << endl;
|
||||||
|
other->clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Equipotential::consolidate ()
|
||||||
|
{
|
||||||
|
EquipotentialRelation* relation = EquipotentialRelation::create( this );
|
||||||
|
|
||||||
|
|
||||||
|
for ( const Occurrence& occurrence : getComponents() ) {
|
||||||
|
Component* component = dynamic_cast<Component*>( occurrence.getEntity() );
|
||||||
|
if (not component) continue;
|
||||||
|
if (not occurrence.getPath().isEmpty()) {
|
||||||
|
//cerr << "Occurrence from a DeepNet " << occurrence << endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
component->put( relation );
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not _nets.empty()) {
|
||||||
|
_name = getString( (*_nets.begin()).first->getName() );
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( auto netData : _nets ) {
|
||||||
|
Net* net = netData.first;
|
||||||
|
if (net->isFused()) continue;
|
||||||
|
if (net->isExternal ()) _isExternal = true;
|
||||||
|
if (net->isGlobal ()) _isGlobal = true;
|
||||||
|
if (net->isAutomatic()) _isAutomatic = true;
|
||||||
|
_type = net->getType();
|
||||||
|
_direction |= net->getDirection();
|
||||||
|
|
||||||
|
if (netData.second.first >= netData.second.second) {
|
||||||
|
for ( Component* component : net->getComponents() ) {
|
||||||
|
if (dynamic_cast<Plug*>(component)) continue;
|
||||||
|
component->remove( relation );
|
||||||
|
}
|
||||||
|
net->put( relation );
|
||||||
|
}
|
||||||
|
cdebug_log(169,0) << netData.first << " [" << netData.second.first
|
||||||
|
<< " / " << netData.second.second << "]" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
for ( Occurrence childEqui : _childs ) {
|
||||||
|
childEqui.put( relation );
|
||||||
|
}
|
||||||
|
if (_components.empty() and _nets.empty()) _isBuried = true;
|
||||||
|
|
||||||
|
#if FIRST_IMPLEMENTATION
|
||||||
|
EquipotentialRelation* relation = EquipotentialRelation::create( this );
|
||||||
|
map<Net*,uint32_t,NetCompareByName> nets;
|
||||||
|
set<Occurrence,OccNetCompareByName> deepNets;
|
||||||
|
for ( const Occurrence& occurrence : getComponents() ) {
|
||||||
|
Component* component = dynamic_cast<Component*>( occurrence.getEntity() );
|
||||||
|
if (not component) continue;
|
||||||
|
if (not occurrence.getPath().isEmpty()) {
|
||||||
|
deepNets.insert( Occurrence( component->getNet(), occurrence.getPath() ));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
component->put( relation );
|
||||||
|
Net* net = component->getNet();
|
||||||
|
if (net->isFused()) _hasFused = true;
|
||||||
|
else {
|
||||||
|
if (net->isExternal ()) _isExternal = true;
|
||||||
|
if (net->isGlobal ()) _isGlobal = true;
|
||||||
|
if (net->isAutomatic()) _isAutomatic = true;
|
||||||
|
_type = net->getType();
|
||||||
|
_direction |= net->getDirection();
|
||||||
|
}
|
||||||
|
uint32_t accounted = (dynamic_cast<Plug*>(component)) ? 0 : 1;
|
||||||
|
auto inet = nets.find( component->getNet() );
|
||||||
|
if (inet != nets.end())
|
||||||
|
inet->second += accounted;
|
||||||
|
else
|
||||||
|
nets.insert( make_pair( component->getNet(), accounted ) );
|
||||||
|
}
|
||||||
|
if (not nets.empty()) {
|
||||||
|
_name = getString( (*nets.begin()).first->getName() );
|
||||||
|
} else {
|
||||||
|
if (not deepNets.empty()) {
|
||||||
|
_name = (*deepNets.begin()).getCompactString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_netCount = nets.size();
|
||||||
|
|
||||||
|
for ( auto item : nets ) {
|
||||||
|
Net* net = item.first;
|
||||||
|
uint32_t count = 0;
|
||||||
|
for ( Component* component : net->getComponents() ) {
|
||||||
|
count += (dynamic_cast<Plug*>(component)) ? 0 : 1;
|
||||||
|
}
|
||||||
|
if (count > item.second) continue;
|
||||||
|
if (count < item.second) {
|
||||||
|
cerr << Error( "Equipotential::consolidate(): On %s, found more components of %s than existing (%d > %d)."
|
||||||
|
, getString(this).c_str()
|
||||||
|
, getString(net).c_str()
|
||||||
|
, item.second
|
||||||
|
, count ) << endl;
|
||||||
|
}
|
||||||
|
for ( Component* component : net->getComponents() ) {
|
||||||
|
if (dynamic_cast<Plug*>(component)) continue;
|
||||||
|
component->remove( relation );
|
||||||
|
}
|
||||||
|
net->put( relation );
|
||||||
|
//_nets.insert( net );
|
||||||
|
}
|
||||||
|
for ( Occurrence childEqui : _childs ) {
|
||||||
|
childEqui.put( relation );
|
||||||
|
}
|
||||||
|
if (_components.empty() and _nets.empty()) _isBuried = true;
|
||||||
|
|
||||||
|
// if (_name == "abc_11873_auto_rtlil_cc_2560_muxgate_11612")
|
||||||
|
// show();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Equipotential::clear ()
|
||||||
|
{
|
||||||
|
_components .clear();
|
||||||
|
_childs .clear();
|
||||||
|
_nets .clear();
|
||||||
|
_shortCircuits.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Equipotential::show () const
|
||||||
|
{
|
||||||
|
cerr << this << endl;
|
||||||
|
cerr << "+ Components:" << endl;
|
||||||
|
for ( const Occurrence& component : _components ) {
|
||||||
|
cerr << "| " << component << endl;
|
||||||
|
}
|
||||||
|
cerr << "+ Occurrences:" << endl;
|
||||||
|
for ( Occurrence occ : _childs ) {
|
||||||
|
cerr << "| " << occ << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string Equipotential::getFlagsAsString () const
|
||||||
|
{
|
||||||
|
string sflags;
|
||||||
|
sflags += ((_isExternal ) ? "e" : "-");
|
||||||
|
sflags += ((_isGlobal ) ? "g" : "-");
|
||||||
|
sflags += ((_isAutomatic) ? "a" : "-");
|
||||||
|
sflags += ((_isBuried ) ? "B" : "-");
|
||||||
|
sflags += " [N:" + getString( _nets.size() - ((_hasFused) ? 1 : 0) );
|
||||||
|
sflags += "+E:" + getString( _childs.size() );
|
||||||
|
if (_hasFused)
|
||||||
|
sflags += "+fused";
|
||||||
|
sflags += "] ";
|
||||||
|
return sflags;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string Equipotential::_getTypeName () const
|
||||||
|
{ return "Tramontana::Equipotential"; }
|
||||||
|
|
||||||
|
|
||||||
|
string Equipotential::_getString () const
|
||||||
|
{
|
||||||
|
ostringstream os;
|
||||||
|
os << "<Equipotential id:" << getId() << " "
|
||||||
|
<< getFlagsAsString()
|
||||||
|
<< " " << getName()
|
||||||
|
<< " " << getType()
|
||||||
|
<< " " << getDirection()
|
||||||
|
<< ">";
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Record* Equipotential::_getRecord () const
|
||||||
|
{
|
||||||
|
Record* record = Super::_getRecord();
|
||||||
|
if (record) {
|
||||||
|
record->add( getSlot( "_name" , &_name ) );
|
||||||
|
record->add( getSlot( "_boundingBox", &_boundingBox ) );
|
||||||
|
//record->add( getSlot( "_nets" , &_nets ) );
|
||||||
|
record->add( getSlot( "_components" , &_components ) );
|
||||||
|
record->add( getSlot( "_childs" , &_childs ) );
|
||||||
|
}
|
||||||
|
return record;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // Tramontana namespace.
|
|
@ -0,0 +1,245 @@
|
||||||
|
// -*- C++ -*-
|
||||||
|
//
|
||||||
|
// This file is part of the Coriolis Software.
|
||||||
|
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||||
|
//
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
// | C O R I O L I S |
|
||||||
|
// | T r a m o n t a n a - Extractor & LVX |
|
||||||
|
// | |
|
||||||
|
// | Algorithm : Christian MASSON |
|
||||||
|
// | First impl. : Yifei WU |
|
||||||
|
// | Second impl. : Jean-Paul CHAPUT |
|
||||||
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||||
|
// | =============================================================== |
|
||||||
|
// | C++ Module : "./EquipotentialComponents.cpp" |
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
#include "hurricane/Error.h"
|
||||||
|
#include "tramontana/EquipotentialComponents.h"
|
||||||
|
#include "tramontana/Equipotential.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Tramontana {
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using Hurricane::tab;
|
||||||
|
using Hurricane::Error;
|
||||||
|
using Hurricane::Path;
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : "Tramontana::EquipotentialComponents".
|
||||||
|
|
||||||
|
EquipotentialComponents::EquipotentialComponents ()
|
||||||
|
: Super()
|
||||||
|
, _equipotential(nullptr)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
EquipotentialComponents::EquipotentialComponents ( const Equipotential* equi )
|
||||||
|
: Super()
|
||||||
|
, _equipotential(equi)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
EquipotentialComponents::EquipotentialComponents ( const EquipotentialComponents& other )
|
||||||
|
: Super()
|
||||||
|
, _equipotential(other._equipotential)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
EquipotentialComponents& EquipotentialComponents::operator= ( const EquipotentialComponents& other )
|
||||||
|
{
|
||||||
|
_equipotential = other._equipotential;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Collection<Occurrence>* EquipotentialComponents::getClone () const
|
||||||
|
{ return new EquipotentialComponents( *this ); }
|
||||||
|
|
||||||
|
|
||||||
|
Locator<Occurrence>* EquipotentialComponents::getLocator () const
|
||||||
|
{ return new Locator ( _equipotential ); }
|
||||||
|
|
||||||
|
|
||||||
|
string EquipotentialComponents::_getString () const
|
||||||
|
{
|
||||||
|
string s = "<EquipotentialComponents ";
|
||||||
|
if (_equipotential) {
|
||||||
|
s += " " + getString( _equipotential );
|
||||||
|
} else {
|
||||||
|
s += " NULL";
|
||||||
|
}
|
||||||
|
s += ">";
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : "Tramontana::EquipotentialComponents::Locator".
|
||||||
|
|
||||||
|
|
||||||
|
EquipotentialComponents::Locator::Locator ()
|
||||||
|
: Super()
|
||||||
|
, _equipotential (nullptr)
|
||||||
|
, _state (Constructed)
|
||||||
|
, _componentsIterator()
|
||||||
|
, _netsIterator ()
|
||||||
|
, _childsIterator ()
|
||||||
|
, _childCompsLocator (nullptr)
|
||||||
|
, _componentsLocator (nullptr)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
EquipotentialComponents::Locator::Locator ( const Equipotential* equi )
|
||||||
|
: Super()
|
||||||
|
, _equipotential (equi)
|
||||||
|
, _state (Constructed)
|
||||||
|
, _componentsIterator(equi->getComponents().end())
|
||||||
|
, _netsIterator (equi->getNets().end())
|
||||||
|
, _childsIterator (equi->getChilds().end())
|
||||||
|
, _childCompsLocator (nullptr)
|
||||||
|
, _componentsLocator (nullptr)
|
||||||
|
{
|
||||||
|
progress();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EquipotentialComponents::Locator::Locator ( const Locator& other )
|
||||||
|
: Super()
|
||||||
|
, _equipotential (other._equipotential)
|
||||||
|
, _state (other._state)
|
||||||
|
, _componentsIterator(other._componentsIterator)
|
||||||
|
, _netsIterator (other._netsIterator)
|
||||||
|
, _childsIterator (other._childsIterator)
|
||||||
|
, _childCompsLocator (nullptr)
|
||||||
|
, _componentsLocator (nullptr)
|
||||||
|
{
|
||||||
|
if (other._childCompsLocator) _childCompsLocator = other._childCompsLocator->getClone();
|
||||||
|
if (other._componentsLocator) _componentsLocator = other._componentsLocator->getClone();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EquipotentialComponents::Locator& EquipotentialComponents::Locator::operator= ( const Locator& other )
|
||||||
|
{
|
||||||
|
_equipotential = other._equipotential;
|
||||||
|
_state = other._state;
|
||||||
|
_componentsIterator= other._componentsIterator;
|
||||||
|
_netsIterator = other._netsIterator;
|
||||||
|
_childsIterator = other._childsIterator;
|
||||||
|
_componentsLocator = (other._componentsLocator) ? other._componentsLocator->getClone() : nullptr;
|
||||||
|
_childCompsLocator = (other._childCompsLocator) ? other._childCompsLocator->getClone() : nullptr;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Occurrence EquipotentialComponents::Locator::getElement () const
|
||||||
|
{
|
||||||
|
if (not _equipotential or (_state >= Finished)) return Occurrence();
|
||||||
|
switch ( _state ) {
|
||||||
|
case InComponents: return (*_componentsIterator);
|
||||||
|
case InNets: return Occurrence( _componentsLocator->getElement() );
|
||||||
|
case InChildEquis: {
|
||||||
|
Path compPath = (*_childsIterator).getPath();
|
||||||
|
Path tailPath = _childCompsLocator->getElement().getPath();
|
||||||
|
while ( not tailPath.isEmpty() ) {
|
||||||
|
compPath = Path( compPath, tailPath.getHeadInstance() );
|
||||||
|
tailPath = tailPath.getTailPath();
|
||||||
|
}
|
||||||
|
return Occurrence( _childCompsLocator->getElement().getEntity(), compPath );
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return Occurrence();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Locator<Occurrence>* EquipotentialComponents::Locator::getClone () const
|
||||||
|
{ return new Locator( *this ); }
|
||||||
|
|
||||||
|
|
||||||
|
bool EquipotentialComponents::Locator::isValid () const
|
||||||
|
{ return (_equipotential) and (_state < Finished); }
|
||||||
|
|
||||||
|
|
||||||
|
void EquipotentialComponents::Locator::progress ()
|
||||||
|
{
|
||||||
|
while ( isValid() ) {
|
||||||
|
switch ( _state ) {
|
||||||
|
case Constructed: {
|
||||||
|
_state = InComponents;
|
||||||
|
_componentsIterator = _equipotential->getComponents().begin();
|
||||||
|
if (_componentsIterator != _equipotential->getComponents().end()) return;
|
||||||
|
}
|
||||||
|
case InComponents: {
|
||||||
|
if (_componentsIterator != _equipotential->getComponents().end()) {
|
||||||
|
++_componentsIterator;
|
||||||
|
if (_componentsIterator != _equipotential->getComponents().end()) return;
|
||||||
|
}
|
||||||
|
_state = InNets;
|
||||||
|
_netsIterator = _equipotential->getNets().begin();
|
||||||
|
}
|
||||||
|
case InNets: {
|
||||||
|
if (_netsIterator != _equipotential->getNets().end()) {
|
||||||
|
if ( not _netsIterator->first->isFused()
|
||||||
|
and _netsIterator->first->getProperty(EquipotentialRelation::staticGetName())) {
|
||||||
|
if (not _componentsLocator) {
|
||||||
|
_componentsLocator = _netsIterator->first->getComponents().getLocator()->getClone();
|
||||||
|
if (_componentsLocator->isValid()) return;
|
||||||
|
} else {
|
||||||
|
_componentsLocator->progress();
|
||||||
|
if (_componentsLocator->isValid()) return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_componentsLocator = nullptr;
|
||||||
|
++_netsIterator;
|
||||||
|
if (_netsIterator != _equipotential->getNets().end())
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
_state = InChildEquis;
|
||||||
|
_childsIterator = _equipotential->getChilds().begin();
|
||||||
|
}
|
||||||
|
case InChildEquis: {
|
||||||
|
if (_childsIterator != _equipotential->getChilds().end()) {
|
||||||
|
if (not _childCompsLocator) {
|
||||||
|
Equipotential* child = dynamic_cast<Equipotential*>( (*_childsIterator).getEntity() );
|
||||||
|
_childCompsLocator = child->getFlatComponents().getLocator()->getClone();
|
||||||
|
if (_childCompsLocator->isValid()) return;
|
||||||
|
} else {
|
||||||
|
_childCompsLocator->progress();
|
||||||
|
if (_childCompsLocator->isValid()) return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_childCompsLocator = nullptr;
|
||||||
|
++_childsIterator;
|
||||||
|
if (_childsIterator != _equipotential->getChilds().end())
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
_state = Finished;
|
||||||
|
}
|
||||||
|
case Finished:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string EquipotentialComponents::Locator::_getString () const
|
||||||
|
{
|
||||||
|
string s = "<EquipotentialComponents::Locator";
|
||||||
|
if (_equipotential) {
|
||||||
|
s += " " + getString(_equipotential);
|
||||||
|
} else {
|
||||||
|
s += " NULL";
|
||||||
|
}
|
||||||
|
s += ">";
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // Tramontana namespace.
|
|
@ -0,0 +1,86 @@
|
||||||
|
// -*- C++ -*-
|
||||||
|
//
|
||||||
|
// This file is part of the Coriolis Software.
|
||||||
|
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||||
|
//
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
// | C O R I O L I S |
|
||||||
|
// | T r a m o n t a n a - Extractor & LVX |
|
||||||
|
// | |
|
||||||
|
// | Algorithm : Christian MASSON |
|
||||||
|
// | First impl. : Yifei WU |
|
||||||
|
// | Second impl. : Jean-Paul CHAPUT |
|
||||||
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||||
|
// | =============================================================== |
|
||||||
|
// | C++ Module : "./EquipotentialRelation.cpp" |
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
#include "tramontana/EquipotentialRelation.h"
|
||||||
|
#include "tramontana/TramontanaEngine.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Tramontana {
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using Hurricane::Property;
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : "Tramontana::EquipotentialRelation".
|
||||||
|
|
||||||
|
const Name EquipotentialRelationName = "EquipotentialRelation";
|
||||||
|
|
||||||
|
|
||||||
|
EquipotentialRelation::EquipotentialRelation ( Equipotential* owner )
|
||||||
|
: Super(owner)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
EquipotentialRelation* EquipotentialRelation::create ( Equipotential* owner )
|
||||||
|
{
|
||||||
|
EquipotentialRelation* relation = new EquipotentialRelation ( owner );
|
||||||
|
relation->_postCreate();
|
||||||
|
return relation;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EquipotentialRelation::_preDestroy ()
|
||||||
|
{ Super::_preDestroy(); }
|
||||||
|
|
||||||
|
|
||||||
|
Name EquipotentialRelation::staticGetName ()
|
||||||
|
{ return EquipotentialRelationName; }
|
||||||
|
|
||||||
|
|
||||||
|
Name EquipotentialRelation::getName () const
|
||||||
|
{ return EquipotentialRelationName; }
|
||||||
|
|
||||||
|
|
||||||
|
string EquipotentialRelation::_getTypeName () const
|
||||||
|
{ return "EquipotentialRelation"; }
|
||||||
|
|
||||||
|
|
||||||
|
Record* EquipotentialRelation::_getRecord () const
|
||||||
|
{
|
||||||
|
Record* record = Super::_getRecord();
|
||||||
|
return record;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
EquipotentialRelation* EquipotentialRelation::get ( const Component* component )
|
||||||
|
{
|
||||||
|
if (not component) return nullptr;
|
||||||
|
|
||||||
|
Property* property = component->getProperty( EquipotentialRelationName );
|
||||||
|
if (not property) return nullptr;
|
||||||
|
|
||||||
|
EquipotentialRelation* relation = dynamic_cast<EquipotentialRelation*>( property );
|
||||||
|
if (not relation) return nullptr;
|
||||||
|
return relation;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} // Tramontana namespace.
|
||||||
|
|
|
@ -0,0 +1,122 @@
|
||||||
|
// -*- C++ -*-
|
||||||
|
//
|
||||||
|
// This file is part of the Coriolis Software.
|
||||||
|
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||||
|
//
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
// | C O R I O L I S |
|
||||||
|
// | T r a m o n t a n a - Extractor & LVX |
|
||||||
|
// | |
|
||||||
|
// | Algorithm : Christian MASSON |
|
||||||
|
// | First impl. : Yifei WU |
|
||||||
|
// | Second impl. : Jean-Paul CHAPUT |
|
||||||
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||||
|
// | =============================================================== |
|
||||||
|
// | C++ Module : "./EquipotentialsModel.cpp" |
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
#include <QFont>
|
||||||
|
#include <QApplication>
|
||||||
|
#include "hurricane/Name.h"
|
||||||
|
#include "hurricane/Net.h"
|
||||||
|
#include "hurricane/Cell.h"
|
||||||
|
#include "hurricane/viewer/Graphics.h"
|
||||||
|
#include "tramontana/EquipotentialsModel.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Tramontana {
|
||||||
|
|
||||||
|
using Hurricane::Graphics;
|
||||||
|
|
||||||
|
|
||||||
|
EquipotentialsModel::EquipotentialsModel ( QObject* parent )
|
||||||
|
: QAbstractTableModel(parent)
|
||||||
|
, _cell (nullptr)
|
||||||
|
, _equipotentials ()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
QVariant EquipotentialsModel::data ( const QModelIndex& index, int role ) const
|
||||||
|
{
|
||||||
|
static QFont nameFont = Graphics::getFixedFont ( QFont::Bold );
|
||||||
|
static QFont valueFont = Graphics::getFixedFont ( QFont::Normal, true );
|
||||||
|
|
||||||
|
if (role == Qt::FontRole) {
|
||||||
|
switch (index.column()) {
|
||||||
|
case 0: return nameFont;
|
||||||
|
default: return valueFont;
|
||||||
|
}
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (not index.isValid()) return QVariant ();
|
||||||
|
|
||||||
|
if (role == Qt::DisplayRole) {
|
||||||
|
Equipotential* equi = _equipotentials[ index.row() ];
|
||||||
|
switch ( index.column() ) {
|
||||||
|
case 0: return QString::fromStdString( equi->getName() );
|
||||||
|
case 1: return QString::fromStdString( equi->getFlagsAsString() );
|
||||||
|
case 2: return QString::fromStdString( getString( equi->getType() ));
|
||||||
|
case 3: return QString::fromStdString( getString( equi->getDirection() ));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QVariant EquipotentialsModel::headerData ( int section
|
||||||
|
, Qt::Orientation orientation
|
||||||
|
, int role ) const
|
||||||
|
{
|
||||||
|
if (orientation == Qt::Vertical) return QVariant();
|
||||||
|
|
||||||
|
static QFont headerFont = Graphics::getFixedFont( QFont::Bold, false, false, +0 );
|
||||||
|
|
||||||
|
if (role == Qt::FontRole ) return headerFont;
|
||||||
|
if (role != Qt::DisplayRole) return QVariant();
|
||||||
|
if (section == 0) return QVariant( "Name" );
|
||||||
|
if (section == 1) return QVariant( "Flags" );
|
||||||
|
if (section == 2) return QVariant( "Type" );
|
||||||
|
if (section == 3) return QVariant( "Direction" );
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int EquipotentialsModel::rowCount ( const QModelIndex& parent ) const
|
||||||
|
{ return _equipotentials.size(); }
|
||||||
|
|
||||||
|
|
||||||
|
int EquipotentialsModel::columnCount ( const QModelIndex& parent ) const
|
||||||
|
{ return 4; }
|
||||||
|
|
||||||
|
|
||||||
|
const Equipotential* EquipotentialsModel::getEqui ( int row )
|
||||||
|
{
|
||||||
|
if (row >= (int)_equipotentials.size()) return nullptr;
|
||||||
|
return _equipotentials[ row ];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EquipotentialsModel::setCell ( Cell* cell )
|
||||||
|
{
|
||||||
|
if (_cell != cell) {
|
||||||
|
emit layoutAboutToBeChanged ();
|
||||||
|
|
||||||
|
if (_cell) _equipotentials.clear();
|
||||||
|
_cell = cell;
|
||||||
|
|
||||||
|
if (_cell) {
|
||||||
|
TramontanaEngine* tramontana = TramontanaEngine::get( _cell );
|
||||||
|
if (tramontana) {
|
||||||
|
for ( Equipotential* equi : tramontana->getEquipotentials() )
|
||||||
|
_equipotentials.push_back( equi );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
emit layoutChanged ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // Tramontana namespace.
|
|
@ -0,0 +1,269 @@
|
||||||
|
// -*- C++ -*-
|
||||||
|
//
|
||||||
|
// This file is part of the Coriolis Software.
|
||||||
|
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||||
|
//
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
// | C O R I O L I S |
|
||||||
|
// | T r a m o n t a n a - Extractor & LVX |
|
||||||
|
// | |
|
||||||
|
// | Algorithm : Christian MASSON |
|
||||||
|
// | First impl. : Yifei WU |
|
||||||
|
// | Second impl. : Jean-Paul CHAPUT |
|
||||||
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||||
|
// | =============================================================== |
|
||||||
|
// | C++ Header : "./EquipotentialsWidget.cpp" |
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
#include <QFontMetrics>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QLineEdit>
|
||||||
|
#include <QHeaderView>
|
||||||
|
#include <QKeyEvent>
|
||||||
|
#include <QGroupBox>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QAction>
|
||||||
|
#include <QModelIndex>
|
||||||
|
#include "hurricane/Commons.h"
|
||||||
|
#include "hurricane/viewer/Graphics.h"
|
||||||
|
#include "tramontana/EquipotentialsModel.h"
|
||||||
|
#include "tramontana/EquipotentialsWidget.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Tramontana {
|
||||||
|
|
||||||
|
using std::cerr;
|
||||||
|
using std::endl;
|
||||||
|
using Hurricane::Bug;
|
||||||
|
using Hurricane::Graphics;
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : "BuriedFilterProxymodel".
|
||||||
|
|
||||||
|
|
||||||
|
EquiFilterProxyModel::EquiFilterProxyModel ( QObject* parent )
|
||||||
|
: Super (parent)
|
||||||
|
, _filter(NoFilter)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
void EquiFilterProxyModel::setFilter ( uint32_t filter )
|
||||||
|
{ _filter = filter; invalidateFilter(); }
|
||||||
|
|
||||||
|
|
||||||
|
bool EquiFilterProxyModel::filterAcceptsRow ( int row, const QModelIndex& index ) const
|
||||||
|
{
|
||||||
|
EquipotentialsModel* model = dynamic_cast<EquipotentialsModel*>( sourceModel() );
|
||||||
|
if (not model) return true;
|
||||||
|
|
||||||
|
const Equipotential* equi = model->getEqui( row );
|
||||||
|
if (not (_filter & ShowBuried) and equi->isBuried()) return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : "EquipotentialsWidget".
|
||||||
|
|
||||||
|
|
||||||
|
EquipotentialsWidget::EquipotentialsWidget ( QWidget* parent )
|
||||||
|
: QWidget (parent)
|
||||||
|
, _cellWidget (NULL)
|
||||||
|
, _cell (NULL)
|
||||||
|
, _baseModel (new EquipotentialsModel(this))
|
||||||
|
, _sortModel (new QSortFilterProxyModel(this))
|
||||||
|
, _filterModel (new EquiFilterProxyModel(this))
|
||||||
|
, _view (new QTableView(this))
|
||||||
|
, _rowHeight (20)
|
||||||
|
, _selecteds ()
|
||||||
|
, _forceReselect(false)
|
||||||
|
{
|
||||||
|
setAttribute( Qt::WA_DeleteOnClose );
|
||||||
|
setAttribute( Qt::WA_QuitOnClose, false );
|
||||||
|
setContextMenuPolicy( Qt::ActionsContextMenu );
|
||||||
|
|
||||||
|
_rowHeight = QFontMetrics( Graphics::getFixedFont() ).height() + 4;
|
||||||
|
|
||||||
|
_filterModel->setSourceModel ( _baseModel );
|
||||||
|
//_filterModel->setFilter ( EquiFilterProxyModel::ShowBuried );
|
||||||
|
_sortModel->setSourceModel ( _filterModel );
|
||||||
|
_sortModel->setDynamicSortFilter( true );
|
||||||
|
_sortModel->setFilterKeyColumn ( 0 );
|
||||||
|
|
||||||
|
_view->setShowGrid ( false );
|
||||||
|
_view->setAlternatingRowColors( true );
|
||||||
|
_view->setSelectionBehavior ( QAbstractItemView::SelectRows );
|
||||||
|
_view->setSortingEnabled ( true );
|
||||||
|
_view->setModel ( _sortModel );
|
||||||
|
|
||||||
|
QHeaderView* horizontalHeader = _view->horizontalHeader();
|
||||||
|
horizontalHeader->setDefaultAlignment ( Qt::AlignHCenter );
|
||||||
|
horizontalHeader->setMinimumSectionSize( (Graphics::isHighDpi()) ? 150 : 75 );
|
||||||
|
horizontalHeader->setStretchLastSection( true );
|
||||||
|
|
||||||
|
QHeaderView* verticalHeader = _view->verticalHeader();
|
||||||
|
verticalHeader->setVisible( false );
|
||||||
|
verticalHeader->setDefaultSectionSize( _rowHeight );
|
||||||
|
|
||||||
|
// verticalHeader->setStyleSheet( "QHeaderView::section {"
|
||||||
|
// "padding-bottom: 0px;"
|
||||||
|
// "padding-top: 0px;"
|
||||||
|
// "padding-left: 0px;"
|
||||||
|
// "padding-right: 1px;"
|
||||||
|
// "margin: 0px;"
|
||||||
|
// "}"
|
||||||
|
// );
|
||||||
|
|
||||||
|
_filterPatternLineEdit = new QLineEdit( this );
|
||||||
|
QLabel* filterPatternLabel = new QLabel( tr("&Filter pattern:"), this );
|
||||||
|
filterPatternLabel->setBuddy( _filterPatternLineEdit );
|
||||||
|
|
||||||
|
QGridLayout* gLayout = new QGridLayout();
|
||||||
|
gLayout->addWidget( _view , 1, 0, 1, 2 );
|
||||||
|
gLayout->addWidget( filterPatternLabel , 2, 0 );
|
||||||
|
gLayout->addWidget( _filterPatternLineEdit, 2, 1 );
|
||||||
|
|
||||||
|
setLayout( gLayout );
|
||||||
|
|
||||||
|
QAction* fitAction = new QAction( tr("&Fit to Equi"), this );
|
||||||
|
fitAction->setShortcut ( QKeySequence(tr("CTRL+F")) );
|
||||||
|
fitAction->setStatusTip( tr("Fit the view to the Equipotentials's bounding box") );
|
||||||
|
addAction( fitAction );
|
||||||
|
|
||||||
|
connect( _filterPatternLineEdit , SIGNAL(textChanged(const QString &))
|
||||||
|
, this , SLOT (textFilterChanged()) );
|
||||||
|
connect( _view->selectionModel(), SIGNAL(selectionChanged(const QItemSelection&,const QItemSelection&))
|
||||||
|
, this , SLOT (updateSelecteds (const QItemSelection&,const QItemSelection&)) );
|
||||||
|
connect( fitAction, SIGNAL(triggered()), this, SLOT(fitToEqui()) );
|
||||||
|
|
||||||
|
resize( 300, 300 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
QModelIndex EquipotentialsWidget::mapToSource ( QModelIndex viewIndex ) const
|
||||||
|
{ return _filterModel->mapToSource( _sortModel->mapToSource( viewIndex )); }
|
||||||
|
|
||||||
|
|
||||||
|
void EquipotentialsWidget::setShowBuried ( bool state )
|
||||||
|
{
|
||||||
|
_filterModel->setFilter( (state) ? EquiFilterProxyModel::ShowBuried
|
||||||
|
: EquiFilterProxyModel::NoFilter );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EquipotentialsWidget::goTo ( int delta )
|
||||||
|
{
|
||||||
|
if ( delta == 0 ) return;
|
||||||
|
|
||||||
|
QModelIndex newIndex = _sortModel->index( _view->currentIndex().row()+delta, 0, QModelIndex() );
|
||||||
|
if (newIndex.isValid())
|
||||||
|
_view->selectRow( newIndex.row() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EquipotentialsWidget::updateSelecteds ()
|
||||||
|
{
|
||||||
|
_forceReselect = true;
|
||||||
|
|
||||||
|
QItemSelection dummy;
|
||||||
|
updateSelecteds( dummy, dummy );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EquipotentialsWidget::updateSelecteds ( const QItemSelection& , const QItemSelection& )
|
||||||
|
{
|
||||||
|
if (_cellWidget) _cellWidget->openRefreshSession ();
|
||||||
|
|
||||||
|
_selecteds.resetAccesses ();
|
||||||
|
|
||||||
|
const Equipotential* equi = nullptr;
|
||||||
|
QModelIndexList iList = _view->selectionModel()->selectedRows();
|
||||||
|
for ( int i=0 ; i<iList.size() ; i++ ) {
|
||||||
|
equi = _baseModel->getEqui( mapToSource(iList[i]).row() );
|
||||||
|
if ( equi )
|
||||||
|
_selecteds.insert( equi );
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_forceReselect) {
|
||||||
|
_selecteds.forceInserteds();
|
||||||
|
_forceReselect = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SelectedEquiSet::iterator isel = _selecteds.begin ();
|
||||||
|
while ( isel != _selecteds.end() ) {
|
||||||
|
SelectedEquiSet::iterator remove = isel++;
|
||||||
|
if (remove->getAccesses() == 0) {
|
||||||
|
emit equipotentialUnselect ( remove->getEqui()->getFlatComponents() );
|
||||||
|
_selecteds.erase( remove );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
isel = _selecteds.begin ();
|
||||||
|
while ( isel != _selecteds.end() ) {
|
||||||
|
if (isel->getAccesses() == 64) {
|
||||||
|
emit equipotentialSelect ( isel->getEqui()->getFlatComponents() );
|
||||||
|
}
|
||||||
|
++isel;
|
||||||
|
}
|
||||||
|
isel = _selecteds.begin ();
|
||||||
|
|
||||||
|
if (_cellWidget) _cellWidget->closeRefreshSession ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EquipotentialsWidget::textFilterChanged ()
|
||||||
|
{
|
||||||
|
_sortModel->setFilterRegExp( _filterPatternLineEdit->text() );
|
||||||
|
//updateSelecteds ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EquipotentialsWidget::fitToEqui ()
|
||||||
|
{
|
||||||
|
const Equipotential* equi = _baseModel->getEqui( mapToSource(_view->currentIndex()).row() );
|
||||||
|
if (equi) emit reframe ( equi->getBoundingBox() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EquipotentialsWidget::setCellWidget ( CellWidget* cw )
|
||||||
|
{
|
||||||
|
if (_cellWidget) {
|
||||||
|
disconnect( this, 0, _cellWidget, 0 );
|
||||||
|
}
|
||||||
|
|
||||||
|
_cellWidget = cw;
|
||||||
|
if (_cellWidget) {
|
||||||
|
setCell( _cellWidget->getCell() );
|
||||||
|
connect( this, SIGNAL( reframe(const Box&) ), _cellWidget, SLOT( reframe(const Box&) ));
|
||||||
|
} else
|
||||||
|
setCell( nullptr );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void EquipotentialsWidget::setCell ( Cell* cell )
|
||||||
|
{
|
||||||
|
_cell = cell;
|
||||||
|
_view->setVisible( false );
|
||||||
|
_view->selectionModel()->clear();
|
||||||
|
_baseModel->setCell( cell );
|
||||||
|
|
||||||
|
string windowTitle = "Equis" + getString(cell);
|
||||||
|
setWindowTitle( tr(windowTitle.c_str()) );
|
||||||
|
|
||||||
|
QHeaderView* header = _view->horizontalHeader();
|
||||||
|
|
||||||
|
_view->selectRow( 0 );
|
||||||
|
for ( int i=0 ; i<_baseModel->columnCount() ; ++i ) {
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(5,0,0)
|
||||||
|
header->setSectionResizeMode( i, QHeaderView::Interactive );
|
||||||
|
#else
|
||||||
|
header->setResizeMode( i, QHeaderView::Interactive );
|
||||||
|
#endif
|
||||||
|
_view->resizeColumnToContents( i );
|
||||||
|
}
|
||||||
|
_view->setVisible( true );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,258 @@
|
||||||
|
// -*- C++ -*-
|
||||||
|
//
|
||||||
|
// This file is part of the Coriolis Software.
|
||||||
|
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||||
|
//
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
// | C O R I O L I S |
|
||||||
|
// | T r a m o n t a n a - Extractor & LVX |
|
||||||
|
// | |
|
||||||
|
// | Algorithm : Christian MASSON |
|
||||||
|
// | First impl. : Yifei WU |
|
||||||
|
// | Second impl. : Jean-Paul CHAPUT |
|
||||||
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||||
|
// | =============================================================== |
|
||||||
|
// | C++ Module : "./GraphicTramontanaEngine.cpp" |
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
#include <boost/bind.hpp>
|
||||||
|
#include <QAction>
|
||||||
|
#include <QMenu>
|
||||||
|
#include <QMenuBar>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <hurricane/Warning.h>
|
||||||
|
#include <hurricane/Error.h>
|
||||||
|
#include <hurricane/Breakpoint.h>
|
||||||
|
#include <hurricane/DebugSession.h>
|
||||||
|
#include <hurricane/Go.h>
|
||||||
|
#include <hurricane/Net.h>
|
||||||
|
#include <hurricane/Cell.h>
|
||||||
|
#include <hurricane/viewer/Graphics.h>
|
||||||
|
#include <hurricane/viewer/CellWidget.h>
|
||||||
|
#include <hurricane/viewer/CellViewer.h>
|
||||||
|
#include <hurricane/viewer/ControllerWidget.h>
|
||||||
|
#include <hurricane/viewer/ExceptionWidget.h>
|
||||||
|
#include <crlcore/Utilities.h>
|
||||||
|
#include <crlcore/AllianceFramework.h>
|
||||||
|
#include <anabatic/GCell.h>
|
||||||
|
#include <tramontana/TabEquipotentials.h>
|
||||||
|
#include <tramontana/GraphicTramontanaEngine.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace Tramontana {
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using Hurricane::Error;
|
||||||
|
using Hurricane::Warning;
|
||||||
|
using Hurricane::Exception;
|
||||||
|
using Hurricane::Breakpoint;
|
||||||
|
using Hurricane::DebugSession;
|
||||||
|
using Hurricane::Point;
|
||||||
|
using Hurricane::Entity;
|
||||||
|
using Hurricane::Net;
|
||||||
|
using Hurricane::Graphics;
|
||||||
|
using Hurricane::ColorScale;
|
||||||
|
using Hurricane::DisplayStyle;
|
||||||
|
using Hurricane::ControllerWidget;
|
||||||
|
using Hurricane::ExceptionWidget;
|
||||||
|
using CRL::Catalog;
|
||||||
|
using CRL::AllianceFramework;
|
||||||
|
|
||||||
|
|
||||||
|
size_t GraphicTramontanaEngine::_references = 0;
|
||||||
|
GraphicTramontanaEngine* GraphicTramontanaEngine::_singleton = NULL;
|
||||||
|
|
||||||
|
|
||||||
|
#if THIS_IS_DISABLED
|
||||||
|
void GraphicTramontanaEngine::initGCell ( CellWidget* widget )
|
||||||
|
{
|
||||||
|
widget->getDrawingPlanes().setPen( Qt::NoPen );
|
||||||
|
TramontanaEngine* tramontana = TramontanaEngine::get( widget->getCell() );
|
||||||
|
if (tramontana) tramontana->setDensityMode( GCell::MaxDensity );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GraphicTramontanaEngine::drawGCell ( CellWidget* widget
|
||||||
|
, const Go* go
|
||||||
|
, const BasicLayer* basicLayer
|
||||||
|
, const Box& box
|
||||||
|
, const Transformation& transformation
|
||||||
|
)
|
||||||
|
{
|
||||||
|
const GCell* gcell = static_cast<const GCell*>(go);
|
||||||
|
|
||||||
|
QPainter& painter = widget->getPainter();
|
||||||
|
QPen pen = Graphics::getPen ("Anabatic::GCell",widget->getDarkening());
|
||||||
|
Box bb = gcell->getBoundingBox();
|
||||||
|
QRect pixelBb = widget->dbuToScreenRect(bb);
|
||||||
|
|
||||||
|
if (GCell::getDisplayMode() == GCell::Density) {
|
||||||
|
uint32_t density = (unsigned int)( 255.0 * gcell->getDensity() );
|
||||||
|
if (density > 255) density = 255;
|
||||||
|
|
||||||
|
painter.setBrush( Graphics::getColorScale( ColorScale::Fire ).getBrush( density, widget->getDarkening() ) );
|
||||||
|
painter.drawRect( pixelBb );
|
||||||
|
} else {
|
||||||
|
int fontScale = 0;
|
||||||
|
int halfHeight = 20;
|
||||||
|
int halfWidth = 80;
|
||||||
|
if (widget->isPrinter()) {
|
||||||
|
fontScale = -5;
|
||||||
|
halfHeight = 9;
|
||||||
|
halfWidth = 39;
|
||||||
|
}
|
||||||
|
|
||||||
|
painter.setPen ( pen );
|
||||||
|
painter.setBrush( Graphics::getBrush("Anabatic::GCell",widget->getDarkening()) );
|
||||||
|
painter.drawRect( pixelBb );
|
||||||
|
|
||||||
|
if ( (pixelBb.width() > 2*halfWidth) and (pixelBb.height() > 2*halfHeight) ) {
|
||||||
|
QString text = QString("%1").arg(gcell->getId());
|
||||||
|
QFont font = Graphics::getFixedFont( QFont::Normal, false, false, fontScale );
|
||||||
|
painter.setFont(font);
|
||||||
|
|
||||||
|
pen.setWidth( 1 );
|
||||||
|
painter.setPen( pen );
|
||||||
|
|
||||||
|
painter.save ();
|
||||||
|
painter.translate( widget->dbuToScreenPoint(bb.getCenter().getX(), bb.getCenter().getY()) );
|
||||||
|
painter.drawRect ( QRect( -halfWidth, -halfHeight, 2*halfWidth, 2*halfHeight ) );
|
||||||
|
painter.drawText ( QRect( -halfWidth, -halfHeight, 2*halfWidth, 2*halfHeight )
|
||||||
|
, text
|
||||||
|
, QTextOption(Qt::AlignCenter)
|
||||||
|
);
|
||||||
|
painter.restore ();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
TramontanaEngine* GraphicTramontanaEngine::createEngine ()
|
||||||
|
{
|
||||||
|
Cell* cell = getCell ();
|
||||||
|
|
||||||
|
TramontanaEngine* tramontana = TramontanaEngine::get( cell );
|
||||||
|
if (not tramontana) {
|
||||||
|
tramontana = TramontanaEngine::create( cell );
|
||||||
|
tramontana->setViewer( _viewer );
|
||||||
|
} else
|
||||||
|
cerr << Warning( "%s already has a Tramontana engine.", getString(cell).c_str() ) << endl;
|
||||||
|
|
||||||
|
return tramontana;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TramontanaEngine* GraphicTramontanaEngine::getForFramework ( uint32_t flags )
|
||||||
|
{
|
||||||
|
// Currently, only one framework is avalaible: Alliance.
|
||||||
|
|
||||||
|
TramontanaEngine* tramontana = TramontanaEngine::get( getCell() );
|
||||||
|
if (tramontana) return tramontana;
|
||||||
|
|
||||||
|
if (flags & CreateEngine) {
|
||||||
|
tramontana = createEngine();
|
||||||
|
if (not tramontana)
|
||||||
|
throw Error( "Failed to create Tramontana engine on %s.", getString(getCell()).c_str() );
|
||||||
|
} else {
|
||||||
|
throw Error( "TramontanaEngine not created yet, run the global router first." );
|
||||||
|
}
|
||||||
|
|
||||||
|
return tramontana;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GraphicTramontanaEngine::_extract ()
|
||||||
|
{
|
||||||
|
TramontanaEngine* tramontana = getForFramework( CreateEngine );
|
||||||
|
tramontana->extract();
|
||||||
|
|
||||||
|
//Breakpoint::stop( 0, "GraphicTramontanaEngine::_extract() done." );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GraphicTramontanaEngine::addToMenu ( CellViewer* viewer )
|
||||||
|
{
|
||||||
|
assert(_viewer == NULL);
|
||||||
|
|
||||||
|
_viewer = viewer;
|
||||||
|
|
||||||
|
if (_viewer->hasMenuAction("tools.extract")) {
|
||||||
|
cerr << Warning( "GraphicTramontanaEngine::addToMenu() - Tramontana extractor already hooked in." ) << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_viewer->addToMenu( "tools.extract"
|
||||||
|
, "E&xtract . . . . . [Tramontana]"
|
||||||
|
, "Run the extractor"
|
||||||
|
, std::bind(&GraphicTramontanaEngine::_extract,this)
|
||||||
|
);
|
||||||
|
|
||||||
|
ControllerWidget* controller = viewer->getControllerWidget();
|
||||||
|
if (controller) {
|
||||||
|
TabEquipotentials* tabEqui = new TabEquipotentials ();
|
||||||
|
tabEqui->setObjectName( "controller.tabEquipotentials" );
|
||||||
|
tabEqui->setCellWidget( viewer->getCellWidget() );
|
||||||
|
controller->insertTabAfter( "controller.tabNetlist", tabEqui, "Equipotentials" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const Name& GraphicTramontanaEngine::getName () const
|
||||||
|
{ return TramontanaEngine::staticGetName(); }
|
||||||
|
|
||||||
|
|
||||||
|
Cell* GraphicTramontanaEngine::getCell ()
|
||||||
|
{
|
||||||
|
if (not _viewer) {
|
||||||
|
throw Error( "<b>Tramontana:</b> GraphicTramontanaEngine not bound to any Viewer." );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (not _viewer->getCell()) {
|
||||||
|
throw Error( "<b>Tramontana:</b> No Cell is loaded into the Viewer." );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _viewer->getCell();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GraphicTramontanaEngine* GraphicTramontanaEngine::grab ()
|
||||||
|
{
|
||||||
|
if (not _references) {
|
||||||
|
_singleton = new GraphicTramontanaEngine ();
|
||||||
|
}
|
||||||
|
_references++;
|
||||||
|
|
||||||
|
return _singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t GraphicTramontanaEngine::release ()
|
||||||
|
{
|
||||||
|
--_references;
|
||||||
|
if (not _references) {
|
||||||
|
delete _singleton;
|
||||||
|
_singleton = NULL;
|
||||||
|
}
|
||||||
|
return _references;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GraphicTramontanaEngine::GraphicTramontanaEngine ()
|
||||||
|
: GraphicTool()
|
||||||
|
, _viewer (NULL)
|
||||||
|
{
|
||||||
|
#if THIS_IS_DISABLED
|
||||||
|
addDrawGo( "Anabatic::GCell", initGCell, drawGCell );
|
||||||
|
addDrawGo( "Anabatic::Edge" , initEdge , drawEdge );
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GraphicTramontanaEngine::~GraphicTramontanaEngine ()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
} // Tramontana namespace.
|
|
@ -0,0 +1,113 @@
|
||||||
|
// -*- C++ -*-
|
||||||
|
//
|
||||||
|
// This file is part of the Coriolis Software.
|
||||||
|
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||||
|
//
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
// | C O R I O L I S |
|
||||||
|
// | T r a m o n t a n a - Extractor & LVX |
|
||||||
|
// | |
|
||||||
|
// | Algorithm : Christian MASSON |
|
||||||
|
// | First impl. : Yifei WU |
|
||||||
|
// | Second impl. : Jean-Paul CHAPUT |
|
||||||
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||||
|
// | =============================================================== |
|
||||||
|
// | C++ Module : "./PyGraphicTramontanaEngine.cpp" |
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
#include "tramontana/PyGraphicTramontanaEngine.h"
|
||||||
|
#include "hurricane/isobar/PyCell.h"
|
||||||
|
#include "hurricane/Cell.h"
|
||||||
|
|
||||||
|
|
||||||
|
#undef ACCESS_OBJECT
|
||||||
|
#undef ACCESS_CLASS
|
||||||
|
#define ACCESS_OBJECT _baseObject._object
|
||||||
|
#define ACCESS_CLASS(_pyObject) &(_pyObject->_baseObject)
|
||||||
|
#define METHOD_HEAD(function) GENERIC_METHOD_HEAD(GraphicTramontanaEngine,gtool,function)
|
||||||
|
|
||||||
|
|
||||||
|
namespace Tramontana {
|
||||||
|
|
||||||
|
using namespace Hurricane;
|
||||||
|
using namespace Isobar;
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
|
||||||
|
// +=================================================================+
|
||||||
|
// | "PyGraphicTramontanaEngine" Python Module Code Part |
|
||||||
|
// +=================================================================+
|
||||||
|
|
||||||
|
#if defined(__PYTHON_MODULE__)
|
||||||
|
|
||||||
|
|
||||||
|
static PyObject* PyGraphicTramontanaEngine_grab ( PyObject* )
|
||||||
|
{
|
||||||
|
cdebug_log(40,0) << "PyGraphicTramontanaEngine_grab()" << endl;
|
||||||
|
PyGraphicTramontanaEngine* pyGraphicTramontanaEngine = NULL;
|
||||||
|
HTRY
|
||||||
|
pyGraphicTramontanaEngine = PyObject_NEW ( PyGraphicTramontanaEngine, &PyTypeGraphicTramontanaEngine );
|
||||||
|
if ( pyGraphicTramontanaEngine == NULL ) return NULL;
|
||||||
|
pyGraphicTramontanaEngine->ACCESS_OBJECT = GraphicTramontanaEngine::grab();
|
||||||
|
HCATCH
|
||||||
|
return (PyObject*)pyGraphicTramontanaEngine;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PyObject* PyGraphicTramontanaEngine_getCell ( PyGraphicTramontanaEngine* self )
|
||||||
|
{
|
||||||
|
cdebug_log(40,0) << "PyGraphicTramontanaEngine_getCell ()" << endl;
|
||||||
|
Cell* cell = NULL;
|
||||||
|
HTRY
|
||||||
|
METHOD_HEAD("GraphicTramontanaEngine.getCell()")
|
||||||
|
cell = gtool->getCell ();
|
||||||
|
HCATCH
|
||||||
|
if (cell == NULL) Py_RETURN_NONE;
|
||||||
|
return PyCell_Link(cell);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
GetNameMethod(GraphicTramontanaEngine, gtool)
|
||||||
|
|
||||||
|
// Standart destroy (Attribute).
|
||||||
|
|
||||||
|
|
||||||
|
PyMethodDef PyGraphicTramontanaEngine_Methods[] =
|
||||||
|
{ { "grab" , (PyCFunction)PyGraphicTramontanaEngine_grab , METH_NOARGS|METH_STATIC
|
||||||
|
, "Returns the GraphicTramontanaEngine singleton." }
|
||||||
|
, { "getName" , (PyCFunction)PyGraphicTramontanaEngine_getName , METH_NOARGS
|
||||||
|
, "Returns the name of the GraphicTramontanaEngine (class attribute)." }
|
||||||
|
, { "getCell" , (PyCFunction)PyGraphicTramontanaEngine_getCell , METH_NOARGS
|
||||||
|
, "Returns the Cell on which this GraphicTramontanaEngine is attached." }
|
||||||
|
, {NULL, NULL, 0, NULL} /* sentinel */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------
|
||||||
|
// PyGraphicTramontanaEngine Type Methods.
|
||||||
|
|
||||||
|
|
||||||
|
PythonOnlyDeleteMethod(GraphicTramontanaEngine)
|
||||||
|
PyTypeObjectLinkPyType(GraphicTramontanaEngine)
|
||||||
|
|
||||||
|
|
||||||
|
#else // End of Python Module Code Part.
|
||||||
|
|
||||||
|
|
||||||
|
// +=================================================================+
|
||||||
|
// | "PyGraphicTramontanaEngine" Shared Library Code Part |
|
||||||
|
// +=================================================================+
|
||||||
|
|
||||||
|
// Link/Creation Method.
|
||||||
|
LinkCreateMethod(GraphicTramontanaEngine)
|
||||||
|
|
||||||
|
PyTypeInheritedObjectDefinitions(GraphicTramontanaEngine,GraphicTool)
|
||||||
|
|
||||||
|
|
||||||
|
#endif // End of Shared Library Code Part.
|
||||||
|
|
||||||
|
} // extern "C".
|
||||||
|
|
||||||
|
} // CRL namespace.
|
|
@ -0,0 +1,107 @@
|
||||||
|
// -*- C++ -*-
|
||||||
|
//
|
||||||
|
// This file is part of the Coriolis Software.
|
||||||
|
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||||
|
//
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
// | C O R I O L I S |
|
||||||
|
// | T r a m o n t a n a - Extractor & LVX |
|
||||||
|
// | |
|
||||||
|
// | Algorithm : Christian MASSON |
|
||||||
|
// | First impl. : Yifei WU |
|
||||||
|
// | Second impl. : Jean-Paul CHAPUT |
|
||||||
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||||
|
// | =============================================================== |
|
||||||
|
// | C++ Module : "./PyTramontana.cpp" |
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
#include "hurricane/isobar/PyHurricane.h"
|
||||||
|
#include "hurricane/isobar/PyCell.h"
|
||||||
|
#include "tramontana/PyTramontanaEngine.h"
|
||||||
|
#include "tramontana/PyGraphicTramontanaEngine.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Tramontana {
|
||||||
|
|
||||||
|
using std::cerr;
|
||||||
|
using std::endl;
|
||||||
|
using Hurricane::tab;
|
||||||
|
using Isobar::getPyHash;
|
||||||
|
using Isobar::__cs;
|
||||||
|
using CRL::PyTypeToolEngine;
|
||||||
|
using CRL::PyTypeGraphicTool;
|
||||||
|
|
||||||
|
|
||||||
|
#if !defined(__PYTHON_MODULE__)
|
||||||
|
|
||||||
|
// +=================================================================+
|
||||||
|
// | "PyTramontana" Shared Library Code Part |
|
||||||
|
// +=================================================================+
|
||||||
|
|
||||||
|
|
||||||
|
# else // End of PyHurricane Shared Library Code Part.
|
||||||
|
|
||||||
|
|
||||||
|
// +=================================================================+
|
||||||
|
// | "PyTramontana" Python Module Code Part |
|
||||||
|
// +=================================================================+
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
|
||||||
|
static PyMethodDef PyTramontana_Methods[] =
|
||||||
|
{ {NULL, NULL, 0, NULL} /* sentinel */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static PyModuleDef PyTramontana_ModuleDef =
|
||||||
|
{ PyModuleDef_HEAD_INIT
|
||||||
|
, .m_name = "Tramontana"
|
||||||
|
, .m_doc = "Layout extractor & LVX."
|
||||||
|
, .m_size = -1
|
||||||
|
, .m_methods = PyTramontana_Methods
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------
|
||||||
|
// Module Initialization : "PyInit_Tramontana ()"
|
||||||
|
|
||||||
|
PyMODINIT_FUNC PyInit_Tramontana ( void )
|
||||||
|
{
|
||||||
|
cdebug_log(40,0) << "PyInit_Tramontana()" << endl;
|
||||||
|
|
||||||
|
PyTramontanaEngine_LinkPyType();
|
||||||
|
PyGraphicTramontanaEngine_LinkPyType();
|
||||||
|
|
||||||
|
PYTYPE_READY_SUB( TramontanaEngine , ToolEngine );
|
||||||
|
PYTYPE_READY_SUB( GraphicTramontanaEngine, GraphicTool );
|
||||||
|
|
||||||
|
|
||||||
|
PyObject* module = PyModule_Create( &PyTramontana_ModuleDef );
|
||||||
|
if (module == NULL) {
|
||||||
|
cerr << "[ERROR]\n"
|
||||||
|
<< " Failed to initialize Tramontana module." << endl;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Py_INCREF( &PyTypeTramontanaEngine );
|
||||||
|
PyModule_AddObject( module, "TramontanaEngine", (PyObject*)&PyTypeTramontanaEngine );
|
||||||
|
Py_INCREF( &PyTypeGraphicTramontanaEngine );
|
||||||
|
PyModule_AddObject( module, "GraphicTramontanaEngine", (PyObject*)&PyTypeGraphicTramontanaEngine );
|
||||||
|
|
||||||
|
//PyTramontanaEngine_postModuleInit();
|
||||||
|
return module;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // End of extern "C".
|
||||||
|
|
||||||
|
|
||||||
|
#endif // End of Python Module Code Part.
|
||||||
|
|
||||||
|
|
||||||
|
} // End of Tramontana namespace.
|
|
@ -0,0 +1,216 @@
|
||||||
|
// -*- C++ -*-
|
||||||
|
//
|
||||||
|
// This file is part of the Coriolis Software.
|
||||||
|
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||||
|
//
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
// | C O R I O L I S |
|
||||||
|
// | T r a m o n t a n a - Extractor & LVX |
|
||||||
|
// | |
|
||||||
|
// | Algorithm : Christian MASSON |
|
||||||
|
// | First impl. : Yifei WU |
|
||||||
|
// | Second impl. : Jean-Paul CHAPUT |
|
||||||
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||||
|
// | =============================================================== |
|
||||||
|
// | C++ Module : "./PyTramontanaEngine.cpp" |
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
#include "hurricane/isobar/PyNet.h"
|
||||||
|
#include "hurricane/isobar/PyCell.h"
|
||||||
|
#include "hurricane/viewer/PyCellViewer.h"
|
||||||
|
#include "hurricane/viewer/ExceptionWidget.h"
|
||||||
|
#include "hurricane/Cell.h"
|
||||||
|
#include "crlcore/Utilities.h"
|
||||||
|
#include "tramontana/PyTramontanaEngine.h"
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
|
# undef ACCESS_OBJECT
|
||||||
|
# undef ACCESS_CLASS
|
||||||
|
# define ACCESS_OBJECT _baseObject._object
|
||||||
|
# define ACCESS_CLASS(_pyObject) &(_pyObject->_baseObject)
|
||||||
|
#define METHOD_HEAD(function) GENERIC_METHOD_HEAD(TramontanaEngine,tramontana,function)
|
||||||
|
|
||||||
|
|
||||||
|
namespace Tramontana {
|
||||||
|
|
||||||
|
using std::cerr;
|
||||||
|
using std::endl;
|
||||||
|
using std::hex;
|
||||||
|
using std::ostringstream;
|
||||||
|
using Hurricane::tab;
|
||||||
|
using Hurricane::Exception;
|
||||||
|
using Hurricane::Bug;
|
||||||
|
using Hurricane::Error;
|
||||||
|
using Hurricane::Warning;
|
||||||
|
using Hurricane::ExceptionWidget;
|
||||||
|
using Isobar::__cs;
|
||||||
|
using Isobar::Converter;
|
||||||
|
using Isobar::ProxyProperty;
|
||||||
|
using Isobar::ProxyError;
|
||||||
|
using Isobar::ConstructorError;
|
||||||
|
using Isobar::HurricaneError;
|
||||||
|
using Isobar::HurricaneWarning;
|
||||||
|
using Isobar::getPyHash;
|
||||||
|
using Isobar::ParseOneArg;
|
||||||
|
using Isobar::ParseTwoArg;
|
||||||
|
using Isobar::PyNet;
|
||||||
|
using Isobar::PyCell;
|
||||||
|
using Isobar::PyCell_Link;
|
||||||
|
using Isobar::PyCellViewer;
|
||||||
|
using Isobar::PyTypeCellViewer;
|
||||||
|
using CRL::PyToolEngine;
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
#if defined(__PYTHON_MODULE__)
|
||||||
|
|
||||||
|
|
||||||
|
#define DirectVoidToolMethod(SELF_TYPE, SELF_OBJECT, FUNC_NAME) \
|
||||||
|
static PyObject* Py##SELF_TYPE##_##FUNC_NAME(Py##SELF_TYPE* self) \
|
||||||
|
{ \
|
||||||
|
cdebug_log(40,0) << "Py" #SELF_TYPE "_" #FUNC_NAME "()" << endl; \
|
||||||
|
HTRY \
|
||||||
|
METHOD_HEAD(#SELF_TYPE "." #FUNC_NAME "()") \
|
||||||
|
if (SELF_OBJECT->getViewer()) { \
|
||||||
|
if (ExceptionWidget::catchAllWrapper( std::bind(&TramontanaEngine::FUNC_NAME,SELF_OBJECT) )) { \
|
||||||
|
PyErr_SetString( HurricaneError, #FUNC_NAME "() has thrown an exception (C++)." ); \
|
||||||
|
return NULL; \
|
||||||
|
} \
|
||||||
|
} else { \
|
||||||
|
SELF_OBJECT->FUNC_NAME(); \
|
||||||
|
} \
|
||||||
|
HCATCH \
|
||||||
|
Py_RETURN_NONE; \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// +=================================================================+
|
||||||
|
// | "PyTramontanaEngine" Python Module Code Part |
|
||||||
|
// +=================================================================+
|
||||||
|
|
||||||
|
|
||||||
|
static PyObject* PyTramontanaEngine_get ( PyObject*, PyObject* args )
|
||||||
|
{
|
||||||
|
cdebug_log(40,0) << "PyTramontanaEngine_get()" << endl;
|
||||||
|
TramontanaEngine* tramontana = NULL;
|
||||||
|
HTRY
|
||||||
|
PyObject* arg0;
|
||||||
|
if (not ParseOneArg("Tramontana.get", args, CELL_ARG, &arg0)) return NULL;
|
||||||
|
tramontana = TramontanaEngine::get(PYCELL_O(arg0));
|
||||||
|
HCATCH
|
||||||
|
return PyTramontanaEngine_Link(tramontana);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PyObject* PyTramontanaEngine_create ( PyObject*, PyObject* args )
|
||||||
|
{
|
||||||
|
cdebug_log(40,0) << "PyTramontanaEngine_create()" << endl;
|
||||||
|
TramontanaEngine* tramontana = NULL;
|
||||||
|
HTRY
|
||||||
|
PyObject* arg0;
|
||||||
|
if (not ParseOneArg("Tramontana.get", args, CELL_ARG, &arg0)) return NULL;
|
||||||
|
Cell* cell = PYCELL_O(arg0);
|
||||||
|
tramontana = TramontanaEngine::get(cell);
|
||||||
|
if (tramontana == NULL) {
|
||||||
|
tramontana = TramontanaEngine::create(cell);
|
||||||
|
} else
|
||||||
|
cerr << Warning("%s already has a Tramontana engine.",getString(cell).c_str()) << endl;
|
||||||
|
HCATCH
|
||||||
|
return PyTramontanaEngine_Link(tramontana);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PyObject* PyTramontanaEngine_setViewer ( PyTramontanaEngine* self, PyObject* args )
|
||||||
|
{
|
||||||
|
cdebug_log(40,0) << "PyTramontanaEngine_setViewer ()" << endl;
|
||||||
|
HTRY
|
||||||
|
METHOD_HEAD( "TramontanaEngine.setViewer()" )
|
||||||
|
PyObject* pyViewer = NULL;
|
||||||
|
if (not PyArg_ParseTuple(args,"O:TramontanaEngine.setViewer()",&pyViewer)) {
|
||||||
|
PyErr_SetString( ConstructorError, "Bad parameters given to TramontanaEngine.setViewer()." );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
if (IsPyCellViewer(pyViewer)) {
|
||||||
|
tramontana->setViewer( PYCELLVIEWER_O(pyViewer) );
|
||||||
|
}
|
||||||
|
HCATCH
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PyObject* PyTramontanaEngine_extract ( PyTramontanaEngine* self )
|
||||||
|
{
|
||||||
|
cdebug_log(40,0) << "PyTramontanaEngine_extract()" << endl;
|
||||||
|
HTRY
|
||||||
|
METHOD_HEAD("TramontanaEngine.extract()")
|
||||||
|
if (tramontana->getViewer()) {
|
||||||
|
if (ExceptionWidget::catchAllWrapper( std::bind(&TramontanaEngine::extract,tramontana) )) {
|
||||||
|
PyErr_SetString( HurricaneError, "TramontanaEngine::extract() has thrown an exception (C++)." );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
tramontana->extract();
|
||||||
|
}
|
||||||
|
HCATCH
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Standart Accessors (Attributes).
|
||||||
|
|
||||||
|
// Standart Destroy (Attribute).
|
||||||
|
DBoDestroyAttribute(PyTramontanaEngine_destroy,PyTramontanaEngine)
|
||||||
|
|
||||||
|
|
||||||
|
PyMethodDef PyTramontanaEngine_Methods[] =
|
||||||
|
{ { "get" , (PyCFunction)PyTramontanaEngine_get , METH_VARARGS|METH_STATIC
|
||||||
|
, "Returns the Tramontana engine attached to the Cell, None if there isnt't." }
|
||||||
|
, { "create" , (PyCFunction)PyTramontanaEngine_create , METH_VARARGS|METH_STATIC
|
||||||
|
, "Create a Tramontana engine on this cell." }
|
||||||
|
, { "destroy" , (PyCFunction)PyTramontanaEngine_destroy , METH_NOARGS
|
||||||
|
, "Destroy a Tramontana engine." }
|
||||||
|
, { "setViewer" , (PyCFunction)PyTramontanaEngine_setViewer , METH_VARARGS
|
||||||
|
, "Associate a Viewer to this TramontanaEngine." }
|
||||||
|
, { "extract" , (PyCFunction)PyTramontanaEngine_extract , METH_NOARGS
|
||||||
|
, "Perform the layout extraction." }
|
||||||
|
, {NULL, NULL, 0, NULL} /* sentinel */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
DBoDeleteMethod(TramontanaEngine)
|
||||||
|
PyTypeObjectLinkPyType(TramontanaEngine)
|
||||||
|
|
||||||
|
|
||||||
|
#else // End of Python Module Code Part.
|
||||||
|
|
||||||
|
|
||||||
|
// +=================================================================+
|
||||||
|
// | "PyTramontanaEngine" Shared Library Code Part |
|
||||||
|
// +=================================================================+
|
||||||
|
|
||||||
|
|
||||||
|
// Link/Creation Method.
|
||||||
|
PyTypeInheritedObjectDefinitions(TramontanaEngine,PyToolEngine)
|
||||||
|
DBoLinkCreateMethod(TramontanaEngine)
|
||||||
|
|
||||||
|
|
||||||
|
// extern void PyTramontanaEngine_postModuleInit ()
|
||||||
|
// {
|
||||||
|
// PyTramontanaFlags_postModuleInit();
|
||||||
|
|
||||||
|
// PyDict_SetItemString( PyTypeTramontanaEngine.tp_dict, "Flags", (PyObject*)&PyTypeTramontanaFlags );
|
||||||
|
|
||||||
|
// PyObject* constant = NULL;
|
||||||
|
// LoadObjectConstant( PyTypeTramontanaEngine.tp_dict, TramontanaEngine::GlobalRoutingSuccess , "GlobalRoutingSuccess" )
|
||||||
|
// LoadObjectConstant( PyTypeTramontanaEngine.tp_dict, TramontanaEngine::DetailedRoutingSuccess, "DetailedRoutingSuccess" )
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
|
#endif // Shared Library Code Part.
|
||||||
|
|
||||||
|
} // extern "C".
|
||||||
|
|
||||||
|
} // Tramontana namespace.
|
||||||
|
|
|
@ -0,0 +1,105 @@
|
||||||
|
// -*- C++ -*-
|
||||||
|
//
|
||||||
|
// This file is part of the Coriolis Software.
|
||||||
|
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||||
|
//
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
// | C O R I O L I S |
|
||||||
|
// | T r a m o n t a n a - Extractor & LVX |
|
||||||
|
// | |
|
||||||
|
// | Algorithm : Christian MASSON |
|
||||||
|
// | First impl. : Yifei WU |
|
||||||
|
// | Second impl. : Jean-Paul CHAPUT |
|
||||||
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||||
|
// | =============================================================== |
|
||||||
|
// | C++ Module : "./QueryTiles.cpp" |
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include "tramontana/QueryTiles.h"
|
||||||
|
#include "tramontana/SweepLine.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Tramontana {
|
||||||
|
|
||||||
|
using std::cerr;
|
||||||
|
using std::endl;
|
||||||
|
using std::vector;
|
||||||
|
|
||||||
|
|
||||||
|
QueryTiles::QueryTiles ( SweepLine* sweepLine )
|
||||||
|
: Query ()
|
||||||
|
, _sweepLine (sweepLine)
|
||||||
|
, _goMatchCount (0)
|
||||||
|
, _processedLayers(0)
|
||||||
|
{
|
||||||
|
setCell ( sweepLine->getCell() );
|
||||||
|
setArea ( sweepLine->getCell()->getBoundingBox() );
|
||||||
|
setFilter( Query::DoComponents|Query::DoTerminalCells );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void QueryTiles::setBasicLayer ( const BasicLayer* basicLayer )
|
||||||
|
{
|
||||||
|
_processedLayers |= basicLayer->getMask();
|
||||||
|
Query::setBasicLayer ( basicLayer );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool QueryTiles::isProcessed ( Component* component ) const
|
||||||
|
{
|
||||||
|
Layer::Mask fullyProcesseds = _processedLayers & ~getBasicLayer()->getMask();
|
||||||
|
return component->getLayer()->getMask().intersect( fullyProcesseds );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void QueryTiles::masterCellCallback ()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
void QueryTiles::rubberCallback ( Rubber* )
|
||||||
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
void QueryTiles::extensionGoCallback ( Go* )
|
||||||
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
bool QueryTiles::hasGoCallback () const
|
||||||
|
{ return true; }
|
||||||
|
|
||||||
|
|
||||||
|
void QueryTiles::goCallback ( Go* go )
|
||||||
|
{
|
||||||
|
Tile* rootTile = nullptr;
|
||||||
|
Component* component = dynamic_cast<Component*>( go );
|
||||||
|
if (not component) return;
|
||||||
|
if (isProcessed(component)) return;
|
||||||
|
Occurrence occurrence = Occurrence( go, getPath() );
|
||||||
|
for ( const BasicLayer* layer : _sweepLine->getExtracteds() ) {
|
||||||
|
if (not component->getLayer()->getMask().intersect(layer->getMask())) continue;
|
||||||
|
Tile* tile = Tile::create( occurrence
|
||||||
|
, layer
|
||||||
|
, rootTile
|
||||||
|
, _sweepLine );
|
||||||
|
if (not rootTile) rootTile = tile;
|
||||||
|
}
|
||||||
|
|
||||||
|
BasicLayer* cutLayer = component->getLayer()->getBasicLayers().getFirst();
|
||||||
|
if (cutLayer->getMaterial() == BasicLayer::Material::cut) {
|
||||||
|
const SweepLine::LayerSet& connexSet = _sweepLine->getCutConnexLayers( cutLayer );
|
||||||
|
for ( const BasicLayer* connexLayer : connexSet ) {
|
||||||
|
Tile::create( occurrence
|
||||||
|
, connexLayer
|
||||||
|
, rootTile
|
||||||
|
, _sweepLine
|
||||||
|
, Tile::ForceLayer );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_goMatchCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // Tramontana namespace.
|
|
@ -0,0 +1,370 @@
|
||||||
|
// -*- C++ -*-
|
||||||
|
//
|
||||||
|
// This file is part of the Coriolis Software.
|
||||||
|
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||||
|
//
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
// | C O R I O L I S |
|
||||||
|
// | T r a m o n t a n a - Extractor & LVX |
|
||||||
|
// | |
|
||||||
|
// | Algorithm : Christian MASSON |
|
||||||
|
// | First impl. : Yifei WU |
|
||||||
|
// | Second impl. : Jean-Paul CHAPUT |
|
||||||
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||||
|
// | =============================================================== |
|
||||||
|
// | C++ Module : "./SweepLine.cpp" |
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
#include <iomanip>
|
||||||
|
#include "hurricane/utilities/Path.h"
|
||||||
|
#include "hurricane/DebugSession.h"
|
||||||
|
#include "hurricane/UpdateSession.h"
|
||||||
|
#include "hurricane/Bug.h"
|
||||||
|
#include "hurricane/Error.h"
|
||||||
|
#include "hurricane/Warning.h"
|
||||||
|
#include "hurricane/Breakpoint.h"
|
||||||
|
#include "hurricane/Timer.h"
|
||||||
|
#include "hurricane/DataBase.h"
|
||||||
|
#include "hurricane/Technology.h"
|
||||||
|
#include "hurricane/Layer.h"
|
||||||
|
#include "hurricane/ViaLayer.h"
|
||||||
|
#include "hurricane/Net.h"
|
||||||
|
#include "hurricane/Pad.h"
|
||||||
|
#include "hurricane/Plug.h"
|
||||||
|
#include "hurricane/Cell.h"
|
||||||
|
#include "hurricane/Instance.h"
|
||||||
|
#include "hurricane/Vertical.h"
|
||||||
|
#include "hurricane/Horizontal.h"
|
||||||
|
#include "hurricane/RoutingPad.h"
|
||||||
|
#include "crlcore/Utilities.h"
|
||||||
|
#include "tramontana/SweepLine.h"
|
||||||
|
#include "tramontana/QueryTiles.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Tramontana {
|
||||||
|
|
||||||
|
using std::cout;
|
||||||
|
using std::cerr;
|
||||||
|
using std::endl;
|
||||||
|
using std::dec;
|
||||||
|
using std::setw;
|
||||||
|
using std::setfill;
|
||||||
|
using std::left;
|
||||||
|
using std::right;
|
||||||
|
using std::string;
|
||||||
|
using std::ostream;
|
||||||
|
using std::ofstream;
|
||||||
|
using std::ostringstream;
|
||||||
|
using std::setprecision;
|
||||||
|
using std::vector;
|
||||||
|
using std::make_pair;
|
||||||
|
using Hurricane::dbo_ptr;
|
||||||
|
using Hurricane::UpdateSession;
|
||||||
|
using Hurricane::DebugSession;
|
||||||
|
using Hurricane::tab;
|
||||||
|
using Hurricane::Bug;
|
||||||
|
using Hurricane::Error;
|
||||||
|
using Hurricane::Warning;
|
||||||
|
using Hurricane::Breakpoint;
|
||||||
|
using Hurricane::Interval;
|
||||||
|
using Hurricane::Box;
|
||||||
|
using Hurricane::DataBase;
|
||||||
|
using Hurricane::Technology;
|
||||||
|
using Hurricane::Layer;
|
||||||
|
using Hurricane::ViaLayer;
|
||||||
|
using Hurricane::Entity;
|
||||||
|
using Hurricane::Horizontal;
|
||||||
|
using Hurricane::Vertical;
|
||||||
|
using Hurricane::RoutingPad;
|
||||||
|
using Hurricane::Cell;
|
||||||
|
using Hurricane::Instance;
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : "Tramontana::SweepLine".
|
||||||
|
|
||||||
|
|
||||||
|
SweepLine::SweepLine ( TramontanaEngine* tramontana )
|
||||||
|
: _tramontana (tramontana)
|
||||||
|
, _extracteds ()
|
||||||
|
, _extractedsMask()
|
||||||
|
, _connexityMap ()
|
||||||
|
, _tiles ()
|
||||||
|
, _intervalTrees ()
|
||||||
|
{
|
||||||
|
for ( const BasicLayer* bl : DataBase::getDB()->getTechnology()->getBasicLayers() ) {
|
||||||
|
// HARDCODED. Should read the gauge.
|
||||||
|
if (getString(bl->getName()).substr(0,6) == "gmetal") continue;
|
||||||
|
if ( (bl->getMaterial() == BasicLayer::Material::metal)
|
||||||
|
or (bl->getMaterial() == BasicLayer::Material::poly)
|
||||||
|
or (bl->getMaterial() == BasicLayer::Material::cut)) {
|
||||||
|
_extracteds.push_back( bl );
|
||||||
|
_extractedsMask |= bl->getMask();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_buildCutConnexMap();
|
||||||
|
|
||||||
|
// _extracteds.push_back( DataBase::getDB()->getTechnology()->getBasicLayer( "metal5" ));
|
||||||
|
// _extracteds.push_back( DataBase::getDB()->getTechnology()->getBasicLayer( "metal4" ));
|
||||||
|
// _extracteds.push_back( DataBase::getDB()->getTechnology()->getBasicLayer( "metal3" ));
|
||||||
|
// _extracteds.push_back( DataBase::getDB()->getTechnology()->getBasicLayer( "metal2" ));
|
||||||
|
// _extracteds.push_back( DataBase::getDB()->getTechnology()->getBasicLayer( "metal1" ));
|
||||||
|
// _extracteds.push_back( DataBase::getDB()->getTechnology()->getBasicLayer( "poly" ));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SweepLine::~SweepLine ()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
void SweepLine::_buildCutConnexMap ()
|
||||||
|
{
|
||||||
|
for ( const ViaLayer* viaLayer : DataBase::getDB()->getTechnology()->getViaLayers() ) {
|
||||||
|
const BasicLayer* cutLayer = nullptr;
|
||||||
|
for ( const BasicLayer* layer : viaLayer->getBasicLayers() ) {
|
||||||
|
if (layer->getMaterial() == BasicLayer::Material::cut) {
|
||||||
|
cutLayer = layer;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (not cutLayer) {
|
||||||
|
cerr << Error( "SweepLine::_buildConnexityMap(): ViaLayer \"%s\" does not contains any *cut* (ignored)."
|
||||||
|
, getString(viaLayer->getName()).c_str()
|
||||||
|
) << endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
auto iCutMap = _connexityMap.find( cutLayer );
|
||||||
|
if (iCutMap == _connexityMap.end()) {
|
||||||
|
_connexityMap.insert( make_pair( cutLayer, LayerSet() ));
|
||||||
|
iCutMap = _connexityMap.find( cutLayer );
|
||||||
|
}
|
||||||
|
for ( const BasicLayer* layer : viaLayer->getBasicLayers() ) {
|
||||||
|
if ( (layer->getMaterial() != BasicLayer::Material::cut)
|
||||||
|
and (_extractedsMask.intersect(layer->getMask())) ) {
|
||||||
|
iCutMap->second.insert( layer );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// for ( auto item : _connexityMap ) {
|
||||||
|
// cerr << "BasicLayers connex to cut: " << item.first << endl;
|
||||||
|
// for ( const BasicLayer* bl : item.second ) {
|
||||||
|
// cerr << "| " << bl << endl;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const SweepLine::LayerSet& SweepLine::getCutConnexLayers ( const BasicLayer* cutLayer ) const
|
||||||
|
{
|
||||||
|
static LayerSet emptySet;
|
||||||
|
auto iCutMap = _connexityMap.find( cutLayer );
|
||||||
|
if (iCutMap == _connexityMap.end())
|
||||||
|
return emptySet;
|
||||||
|
return iCutMap->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SweepLine::run ()
|
||||||
|
{
|
||||||
|
//DebugSession::open( 160, 169 );
|
||||||
|
cdebug_log(160,1) << "SweepLine::run()" << endl;
|
||||||
|
loadTiles();
|
||||||
|
//bool debugOn = false;
|
||||||
|
//bool written = false;
|
||||||
|
for ( Element& element : _tiles ) {
|
||||||
|
Tile* tile = element.getTile();
|
||||||
|
TileIntv tileIntv ( tile, tile->getYMin(), tile->getYMax() );
|
||||||
|
// if (tile->getOccurrence().getEntity()->getId() == 3348) {
|
||||||
|
// DebugSession::open( 160, 169 );
|
||||||
|
// }
|
||||||
|
// if (getString(tile->getNet()->getName()) == "a(13)") {
|
||||||
|
// cerr << tile << endl;
|
||||||
|
// }
|
||||||
|
// if (not debugOn and (element.getX() == DbU::fromLambda(1724.0))) {
|
||||||
|
// debugOn = true;
|
||||||
|
// DebugSession::open( 0, 169 );
|
||||||
|
// }
|
||||||
|
// if (debugOn and (element.getX() > DbU::fromLambda(1726.0))) {
|
||||||
|
// debugOn = false;
|
||||||
|
// DebugSession::close();
|
||||||
|
// }
|
||||||
|
cdebug_log(160,1) << "X@ + " << DbU::getValueString(element.getX()) << " " << tile << endl;
|
||||||
|
auto intvTree = _intervalTrees.find( element.getMask() );
|
||||||
|
if (intvTree == _intervalTrees.end()) {
|
||||||
|
cerr << Error( "SweepLine::run(): Missing interval tree for layer(mask) %s."
|
||||||
|
" (for tile: %s)"
|
||||||
|
, getString(element.getMask()).c_str()
|
||||||
|
, getString(element.getTile()).c_str()
|
||||||
|
) << endl;
|
||||||
|
cdebug_tabw(160,-1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (element.isLeftEdge()) {
|
||||||
|
// if (tile->getOccurrence().getEntity()->getId() == 3348) {
|
||||||
|
// //if (not written) intvTree->second.write( "tree-before.gv" );
|
||||||
|
// cdebug_log(160,0) << " Interval tree *before* insertion." << endl;
|
||||||
|
// for ( auto elt : intvTree->second.getElements() ) {
|
||||||
|
// cdebug_log(160,0) << " | in tree:" << elt << endl;
|
||||||
|
// if (elt.getData()->getBoundingBox().getXMax() < tile->getLeftEdge())
|
||||||
|
// cdebug_log(160,0) << " * Should have been removed !" << endl;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
for ( const TileIntv& overlap : intvTree->second.getOverlaps(
|
||||||
|
Interval(tile->getYMin(), tile->getYMax() ))) {
|
||||||
|
cdebug_log(160,0) << " | intersect " << overlap.getData() << endl;
|
||||||
|
tile->merge( overlap.getData() );
|
||||||
|
}
|
||||||
|
cdebug_log(160,0) << " | insert tile" << endl;
|
||||||
|
// if (tile->getId() == 60117) {
|
||||||
|
// cerr << " | insert in " << element.getMask() << endl;
|
||||||
|
// cerr << " | " << tile << endl;
|
||||||
|
// }
|
||||||
|
// if (tile->getId() == 46373) {
|
||||||
|
// cerr << " | insert " << tile << endl;
|
||||||
|
// }
|
||||||
|
intvTree->second.insert( tileIntv );
|
||||||
|
if (tile->getOccurrence().getEntity()->getId() == 3348) {
|
||||||
|
//if (not written) intvTree->second.write( "tree-after.gv" );
|
||||||
|
//written = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// if (tile->getId() == 289) {
|
||||||
|
// DebugSession::open( 0, 169 );
|
||||||
|
// }
|
||||||
|
// cdebug_log(160,0) << " | remove tile from " << element.getMask() << endl;
|
||||||
|
// cdebug_log(160,0) << " | " << tile << endl;
|
||||||
|
// if ((tile->getId() == 289) and not written) {
|
||||||
|
// cerr << "(before) written is " << written << endl;
|
||||||
|
// DebugSession::open( 0, 169 );
|
||||||
|
// intvTree->second.write( "tree-before.gv" );
|
||||||
|
// //DebugSession::close();
|
||||||
|
// for ( auto elt : intvTree->second.getElements() ) {
|
||||||
|
// cerr << " | in tree:" << elt << endl;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
cdebug_log(160,0) << " | remove tile" << endl;
|
||||||
|
intvTree->second.remove( tileIntv );
|
||||||
|
// DebugSession::open( 0, 169 );
|
||||||
|
// intvTree->second.checkVMax();
|
||||||
|
// DebugSession::close();
|
||||||
|
// if ((tile->getId() == 289) and not written) {
|
||||||
|
// //DebugSession::open( 0, 169 );
|
||||||
|
// written = true;
|
||||||
|
// cerr << "(after) written is " << written << endl;
|
||||||
|
// intvTree->second.write( "tree-after.gv" );
|
||||||
|
// DebugSession::close();
|
||||||
|
// }
|
||||||
|
// if (intvTree->second.find( tileIntv ) != intvTree->second.end()) {
|
||||||
|
// cerr << "NOT Removed " << tileIntv << endl;
|
||||||
|
// }
|
||||||
|
// if (tile->getId() == 289) {
|
||||||
|
// cerr << " | removed " << tile << endl;
|
||||||
|
// intvTree->second.write( "tree.gv" );
|
||||||
|
// for ( auto elt : intvTree->second.getElements() ) {
|
||||||
|
// cerr << " | in tree:" << elt << endl;
|
||||||
|
// }
|
||||||
|
// DebugSession::close();
|
||||||
|
// }
|
||||||
|
// if (tile->getId() == 46055) {
|
||||||
|
// intvTree->second.write( "we_at_remove.gv" );
|
||||||
|
// for ( auto tile : intvTree->second.getElements() ) {
|
||||||
|
// cerr << "| in tree:" << tile << endl;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
//intvTree->second.checkVMax();
|
||||||
|
// cdebug_tabw(160,-1);
|
||||||
|
// if (tile->getOccurrence().getEntity()->getId() == 3348) {
|
||||||
|
// DebugSession::close();
|
||||||
|
// }
|
||||||
|
cdebug_tabw(160,-1);
|
||||||
|
}
|
||||||
|
//if (debugOn) DebugSession::close();
|
||||||
|
cdebug_tabw(160,-1);
|
||||||
|
//DebugSession::close();
|
||||||
|
mergeEquipotentials();
|
||||||
|
deleteTiles();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SweepLine::loadTiles ()
|
||||||
|
{
|
||||||
|
//cerr << "SweepLine::loadTiles()" << endl;
|
||||||
|
|
||||||
|
for ( const BasicLayer* layer : _extracteds ) {
|
||||||
|
_intervalTrees.insert( make_pair( layer->getMask(), TileIntvTree() ));
|
||||||
|
}
|
||||||
|
|
||||||
|
QueryTiles query ( this );
|
||||||
|
for ( const BasicLayer* layer : _extracteds ) {
|
||||||
|
query.setBasicLayer( layer );
|
||||||
|
query.doQuery();
|
||||||
|
}
|
||||||
|
cmess2 << " - Loaded " << query.getGoMatchCount() << " tiles." << endl;
|
||||||
|
|
||||||
|
// for ( Occurrence occurrence : getCell()->getOccurrencesUnder( getCell()->getBoundingBox() ) ) {
|
||||||
|
// vector<Tile*> tiles;
|
||||||
|
// Component* component = dynamic_cast<Component*>( occurrence.getEntity() );
|
||||||
|
// if (occurrence.getPath().getInstances().getSize() > 0) {
|
||||||
|
// cerr << occurrence << endl;
|
||||||
|
// }
|
||||||
|
// if (not component) continue;
|
||||||
|
// for ( const BasicLayer* layer : extracteds ) {
|
||||||
|
// if (not component->getLayer()->getMask().intersect(layer->getMask())) continue;
|
||||||
|
// tiles.push_back( Tile::create( occurrence, layer ));
|
||||||
|
// _tiles.push_back( Element( tiles.back(), Tile::LeftEdge ) );
|
||||||
|
// _tiles.push_back( Element( tiles.back(), Tile::RightEdge ) );
|
||||||
|
// if (tiles.size() > 1)
|
||||||
|
// tiles.back()->setParent( tiles[0] );
|
||||||
|
// }
|
||||||
|
// tiles.clear();
|
||||||
|
// }
|
||||||
|
sort( _tiles.begin(), _tiles.end() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SweepLine::deleteTiles ()
|
||||||
|
{
|
||||||
|
Tile::deleteAllTiles();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SweepLine::mergeEquipotentials ()
|
||||||
|
{
|
||||||
|
//DebugSession::open( 160, 169 );
|
||||||
|
cdebug_log(160,1) << "SweepLine::mergeEquipotentials()" << endl;
|
||||||
|
//cerr << "SweepLine::mergeEquipotentials()" << endl;
|
||||||
|
Tile::timeTick();
|
||||||
|
for ( Tile* tile : Tile::getAllTiles() ) {
|
||||||
|
tile->getRoot( Tile::MergeEqui|Tile::MakeLeafEqui );
|
||||||
|
}
|
||||||
|
cdebug_tabw(160,-1);
|
||||||
|
//DebugSession::close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string SweepLine::_getTypeName () const
|
||||||
|
{ return "Tramontana::SweepLine"; }
|
||||||
|
|
||||||
|
|
||||||
|
string SweepLine::_getString () const
|
||||||
|
{
|
||||||
|
ostringstream os;
|
||||||
|
os << "<SweepLine \"" << _tramontana->getCell()->getName() << "\">";
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Record* SweepLine::_getRecord () const
|
||||||
|
{
|
||||||
|
Record* record = new Record ( _getString() );
|
||||||
|
if (record) {
|
||||||
|
record->add( getSlot( "_tramontana" , &_tramontana ) );
|
||||||
|
record->add( getSlot( "_tiles" , &_tiles ) );
|
||||||
|
}
|
||||||
|
return record;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // Tramontana namespace.
|
|
@ -0,0 +1,161 @@
|
||||||
|
// -*- C++ -*-
|
||||||
|
//
|
||||||
|
// This file is part of the Coriolis Software.
|
||||||
|
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||||
|
//
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
// | C O R I O L I S |
|
||||||
|
// | T r a m o n t a n a - Extractor & LVX |
|
||||||
|
// | |
|
||||||
|
// | Algorithm : Christian MASSON |
|
||||||
|
// | First impl. : Yifei WU |
|
||||||
|
// | Second impl. : Jean-Paul CHAPUT |
|
||||||
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||||
|
// | =============================================================== |
|
||||||
|
// | C++ Module : "./TabEquipotentials.cpp" |
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
#include <QAction>
|
||||||
|
#include <QFrame>
|
||||||
|
#include <QHBoxLayout>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
#include <QCheckBox>
|
||||||
|
#include <QComboBox>
|
||||||
|
#include "tramontana/TabEquipotentials.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Tramontana {
|
||||||
|
|
||||||
|
using std::cerr;
|
||||||
|
using std::endl;
|
||||||
|
using Hurricane::Graphics;
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : "Tramontana::TabEquipotentials".
|
||||||
|
|
||||||
|
|
||||||
|
TabEquipotentials::TabEquipotentials ( QWidget* parent )
|
||||||
|
: ControllerTab (parent)
|
||||||
|
, _browser (new EquipotentialsWidget())
|
||||||
|
, _syncEquipotentials (new QCheckBox())
|
||||||
|
, _syncSelection (new QCheckBox())
|
||||||
|
, _showBuried (new QCheckBox())
|
||||||
|
, _cwCumulativeSelection(false)
|
||||||
|
{
|
||||||
|
_browser->setObjectName ( "controller.tabEquipotentials.browser" );
|
||||||
|
|
||||||
|
QVBoxLayout* wLayout = new QVBoxLayout ();
|
||||||
|
wLayout->setContentsMargins( 10, 0, 10, 0 );
|
||||||
|
wLayout->setSpacing( 0 );
|
||||||
|
|
||||||
|
_syncEquipotentials->setText ( tr("Sync Equipotentials") );
|
||||||
|
_syncEquipotentials->setChecked( false );
|
||||||
|
_syncEquipotentials->setFont ( Graphics::getFixedFont(QFont::Bold,false,false) );
|
||||||
|
connect( _syncEquipotentials, SIGNAL(toggled(bool)), this, SLOT(setSyncEquipotentials(bool)) );
|
||||||
|
|
||||||
|
_syncSelection->setText ( tr("Sync Selection") );
|
||||||
|
_syncSelection->setChecked( false );
|
||||||
|
_syncSelection->setFont ( Graphics::getFixedFont(QFont::Bold,false,false) );
|
||||||
|
connect( _syncSelection, SIGNAL(toggled(bool)), this, SLOT(setSyncSelection(bool)) );
|
||||||
|
|
||||||
|
_showBuried->setText ( tr("Show Buried") );
|
||||||
|
_showBuried->setChecked( false );
|
||||||
|
_showBuried->setFont ( Graphics::getFixedFont(QFont::Bold,false,false) );
|
||||||
|
connect( _showBuried, SIGNAL(toggled(bool)), this, SLOT(setShowBuried(bool)) );
|
||||||
|
|
||||||
|
QHBoxLayout* commands = new QHBoxLayout ();
|
||||||
|
commands->setContentsMargins( 0, 0, 0, 0 );
|
||||||
|
commands->addStretch();
|
||||||
|
commands->addWidget ( _syncEquipotentials );
|
||||||
|
commands->addStretch();
|
||||||
|
commands->addWidget ( _showBuried );
|
||||||
|
commands->addStretch();
|
||||||
|
commands->addWidget ( _syncSelection );
|
||||||
|
commands->addStretch();
|
||||||
|
wLayout->addLayout ( commands );
|
||||||
|
|
||||||
|
QFrame* separator = new QFrame ();
|
||||||
|
separator->setFrameShape ( QFrame::HLine );
|
||||||
|
separator->setFrameShadow( QFrame::Sunken );
|
||||||
|
wLayout->addWidget( separator );
|
||||||
|
wLayout->addWidget( _browser );
|
||||||
|
|
||||||
|
setLayout( wLayout );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TabEquipotentials::setSyncEquipotentials ( bool state )
|
||||||
|
{
|
||||||
|
if (state and getCellWidget()) {
|
||||||
|
_browser->setCell( getCellWidget()->getCell() );
|
||||||
|
} else {
|
||||||
|
_browser->setCell( nullptr );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TabEquipotentials::setSyncSelection ( bool state )
|
||||||
|
{
|
||||||
|
if (state and getCellWidget() and _syncEquipotentials->isChecked()) {
|
||||||
|
_cwCumulativeSelection = getCellWidget()->cumulativeSelection();
|
||||||
|
if (not _cwCumulativeSelection) {
|
||||||
|
getCellWidget()->openRefreshSession ();
|
||||||
|
getCellWidget()->unselectAll ();
|
||||||
|
getCellWidget()->closeRefreshSession ();
|
||||||
|
}
|
||||||
|
getCellWidget()->setShowSelection( true );
|
||||||
|
connect( _browser, SIGNAL(equipotentialSelect (Occurrences)), getCellWidget(), SLOT(select (Occurrences)) );
|
||||||
|
connect( _browser, SIGNAL(equipotentialUnselect(Occurrences)), getCellWidget(), SLOT(unselect(Occurrences)) );
|
||||||
|
_browser->updateSelecteds();
|
||||||
|
} else {
|
||||||
|
getCellWidget()->setShowSelection( false );
|
||||||
|
getCellWidget()->setCumulativeSelection( _cwCumulativeSelection );
|
||||||
|
_browser->disconnect( getCellWidget(), SLOT(select (Occurrences)) );
|
||||||
|
_browser->disconnect( getCellWidget(), SLOT(unselect(Occurrences)) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TabEquipotentials::setShowBuried ( bool state )
|
||||||
|
{
|
||||||
|
if (not getCellWidget()) return;
|
||||||
|
_browser->setShowBuried( state );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TabEquipotentials::setCell ( Cell* cell )
|
||||||
|
{
|
||||||
|
setSyncEquipotentials( _syncEquipotentials->isChecked() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TabEquipotentials::setCellWidget ( CellWidget* cellWidget )
|
||||||
|
{
|
||||||
|
if (getCellWidget() != cellWidget) {
|
||||||
|
ControllerTab::setCellWidget( cellWidget );
|
||||||
|
_browser->setCellWidget( cellWidget );
|
||||||
|
if (getCellWidget()) {
|
||||||
|
connect( getCellWidget(), SIGNAL(cellChanged(Cell*)), this, SLOT(setCell(Cell*)) );
|
||||||
|
}
|
||||||
|
setSyncEquipotentials( _syncEquipotentials->isChecked() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TabEquipotentials::cellPreModificate ()
|
||||||
|
{
|
||||||
|
_browser->setCell( nullptr );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TabEquipotentials::cellPostModificate ()
|
||||||
|
{
|
||||||
|
setSyncEquipotentials( _syncEquipotentials->isChecked() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,362 @@
|
||||||
|
// -*- C++ -*-
|
||||||
|
//
|
||||||
|
// This file is part of the Coriolis Software.
|
||||||
|
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||||
|
//
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
// | C O R I O L I S |
|
||||||
|
// | T r a m o n t a n a - Extractor & LVX |
|
||||||
|
// | |
|
||||||
|
// | Algorithm : Christian MASSON |
|
||||||
|
// | First impl. : Yifei WU |
|
||||||
|
// | Second impl. : Jean-Paul CHAPUT |
|
||||||
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||||
|
// | =============================================================== |
|
||||||
|
// | C++ Module : "./Tile.cpp" |
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
#include <iomanip>
|
||||||
|
#include "hurricane/utilities/Path.h"
|
||||||
|
#include "hurricane/DebugSession.h"
|
||||||
|
#include "hurricane/UpdateSession.h"
|
||||||
|
#include "hurricane/Bug.h"
|
||||||
|
#include "hurricane/Error.h"
|
||||||
|
#include "hurricane/Warning.h"
|
||||||
|
#include "hurricane/Breakpoint.h"
|
||||||
|
#include "hurricane/Timer.h"
|
||||||
|
#include "hurricane/Layer.h"
|
||||||
|
#include "hurricane/Net.h"
|
||||||
|
#include "hurricane/Pad.h"
|
||||||
|
#include "hurricane/Plug.h"
|
||||||
|
#include "hurricane/Cell.h"
|
||||||
|
#include "hurricane/Instance.h"
|
||||||
|
#include "hurricane/Vertical.h"
|
||||||
|
#include "hurricane/Horizontal.h"
|
||||||
|
#include "hurricane/Diagonal.h"
|
||||||
|
#include "hurricane/Rectilinear.h"
|
||||||
|
#include "hurricane/Polygon.h"
|
||||||
|
#include "hurricane/RoutingPad.h"
|
||||||
|
#include "crlcore/Utilities.h"
|
||||||
|
#include "tramontana/Tile.h"
|
||||||
|
#include "tramontana/Equipotential.h"
|
||||||
|
#include "tramontana/SweepLine.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Tramontana {
|
||||||
|
|
||||||
|
using std::cout;
|
||||||
|
using std::cerr;
|
||||||
|
using std::endl;
|
||||||
|
using std::dec;
|
||||||
|
using std::setw;
|
||||||
|
using std::setfill;
|
||||||
|
using std::left;
|
||||||
|
using std::string;
|
||||||
|
using std::ostream;
|
||||||
|
using std::ofstream;
|
||||||
|
using std::ostringstream;
|
||||||
|
using std::setprecision;
|
||||||
|
using std::vector;
|
||||||
|
using std::make_pair;
|
||||||
|
using Hurricane::dbo_ptr;
|
||||||
|
using Hurricane::UpdateSession;
|
||||||
|
using Hurricane::DebugSession;
|
||||||
|
using Hurricane::tab;
|
||||||
|
using Hurricane::Bug;
|
||||||
|
using Hurricane::Error;
|
||||||
|
using Hurricane::Warning;
|
||||||
|
using Hurricane::Breakpoint;
|
||||||
|
using Hurricane::Box;
|
||||||
|
using Hurricane::Layer;
|
||||||
|
using Hurricane::Entity;
|
||||||
|
using Hurricane::Horizontal;
|
||||||
|
using Hurricane::Vertical;
|
||||||
|
using Hurricane::Vertical;
|
||||||
|
using Hurricane::Diagonal;
|
||||||
|
using Hurricane::Rectilinear;
|
||||||
|
using Hurricane::Polygon;
|
||||||
|
using Hurricane::Cell;
|
||||||
|
using Hurricane::Instance;
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : "Tramontana::Tile".
|
||||||
|
|
||||||
|
|
||||||
|
uint32_t Tile::_idCounter = 0;
|
||||||
|
uint32_t Tile::_time = 0;
|
||||||
|
vector<Tile*> Tile::_allocateds;
|
||||||
|
|
||||||
|
|
||||||
|
Tile::Tile ( Occurrence occurrence, const BasicLayer* layer, const Box& boundingBox, Tile* parent )
|
||||||
|
: _id (_idCounter++)
|
||||||
|
, _occurrence (occurrence)
|
||||||
|
, _layer (layer)
|
||||||
|
, _boundingBox (boundingBox)
|
||||||
|
, _equipotential(nullptr)
|
||||||
|
, _flags (0)
|
||||||
|
, _parent (parent)
|
||||||
|
, _rank (0)
|
||||||
|
, _timeStamp (0)
|
||||||
|
{
|
||||||
|
cdebug_log(160,0) << "Tile::Tile() " << this << endl;
|
||||||
|
_allocateds.push_back( this );
|
||||||
|
if (occurrence.getPath().isEmpty() and not occurrence.getEntity())
|
||||||
|
cerr << "Tile with empty occurrence!!" << endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Tile* Tile::create ( Occurrence occurrence
|
||||||
|
, const BasicLayer* layer
|
||||||
|
, Tile* rootTile
|
||||||
|
, SweepLine* sweepLine
|
||||||
|
, uint32_t flags )
|
||||||
|
{
|
||||||
|
Component* component = dynamic_cast<Component*>( occurrence.getEntity() );
|
||||||
|
if (not component) {
|
||||||
|
cerr << Error( "Tile::create(): Must be build over an occurrence of *Component*.\n"
|
||||||
|
" (%s)"
|
||||||
|
, getString(occurrence).c_str()
|
||||||
|
) << endl;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (not (flags & ForceLayer) and not component->getLayer()->contains(layer)) {
|
||||||
|
cerr << "Intersect:" << component->getLayer()->getMask().intersect(layer->getMask()) << endl;
|
||||||
|
cerr << Error( "Tile::create(): Component layer \"%s\" does not contains \"%s\".\n"
|
||||||
|
" (%s)\n"
|
||||||
|
" component :%s\n"
|
||||||
|
" basicLayer:%s"
|
||||||
|
, getString(component->getLayer()->getName()).c_str()
|
||||||
|
, getString(layer->getName()).c_str()
|
||||||
|
, getString(occurrence).c_str()
|
||||||
|
, getString(component->getLayer()->getMask()).c_str()
|
||||||
|
, getString(layer->getMask()).c_str()
|
||||||
|
) << endl;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (dynamic_cast<Polygon*>(component)) {
|
||||||
|
cerr << Error( "Tile::create(): Polygon are not supported for extraction.\n"
|
||||||
|
" (%s)"
|
||||||
|
, getString(occurrence).c_str()
|
||||||
|
) << endl;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (dynamic_cast<Diagonal*>(component)) {
|
||||||
|
cerr << Error( "Tile::create(): Diagonal are not supported for extraction.\n"
|
||||||
|
" (%s)"
|
||||||
|
, getString(occurrence).c_str()
|
||||||
|
) << endl;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Occurrence childEqui = occurrence;
|
||||||
|
if (not childEqui.getPath().isEmpty())
|
||||||
|
childEqui = Equipotential::getChildEqui( occurrence );
|
||||||
|
|
||||||
|
Rectilinear* rectilinear = dynamic_cast<Rectilinear*>( component );
|
||||||
|
if (rectilinear) {
|
||||||
|
if (not rectilinear->isRectilinear()) {
|
||||||
|
cerr << Error( "Tile::create(): Rectilinear with 45/135 edges are not supported for extraction.\n"
|
||||||
|
" (%s)"
|
||||||
|
, getString(occurrence).c_str()
|
||||||
|
) << endl;
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
if (rectilinear->getId() == 3367) {
|
||||||
|
DebugSession::open( 160, 169 );
|
||||||
|
cdebug_log(160,0) << "Tiling: " << rectilinear << endl;
|
||||||
|
}
|
||||||
|
vector<Box> boxes;
|
||||||
|
rectilinear->getAsRectangles( boxes );
|
||||||
|
for ( Box bb : boxes ) {
|
||||||
|
occurrence.getPath().getTransformation().applyOn( bb );
|
||||||
|
Tile* tile = new Tile ( childEqui, layer, bb, rootTile );
|
||||||
|
sweepLine->add( tile );
|
||||||
|
cdebug_log(160,0) << "| " << tile << endl;
|
||||||
|
if (not rootTile) rootTile = tile;
|
||||||
|
}
|
||||||
|
if (rectilinear->getId() == 3367) {
|
||||||
|
DebugSession::close();
|
||||||
|
}
|
||||||
|
return rootTile;
|
||||||
|
}
|
||||||
|
|
||||||
|
Box bb = component->getBoundingBox( layer );
|
||||||
|
occurrence.getPath().getTransformation().applyOn( bb );
|
||||||
|
|
||||||
|
Tile* tile = new Tile ( childEqui, layer, bb, rootTile );
|
||||||
|
sweepLine->add( tile );
|
||||||
|
return tile;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Tile::destroy ()
|
||||||
|
{
|
||||||
|
cdebug_log(160,1) << "Tile::destroy() " << this << endl;
|
||||||
|
cdebug_tabw(160,-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Tile::~Tile ()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
void Tile::deleteAllTiles ()
|
||||||
|
{
|
||||||
|
for ( Tile* tile : _allocateds) delete tile;
|
||||||
|
_allocateds.clear();
|
||||||
|
_idCounter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Net* Tile::getNet () const
|
||||||
|
// { return dynamic_cast<Component*>( _occurrence.getEntity() )->getNet(); }
|
||||||
|
|
||||||
|
|
||||||
|
Tile* Tile::getRoot ( uint32_t flags )
|
||||||
|
{
|
||||||
|
cdebug_log(160,1) << "Tile::getRoot() tid=" << getId() << " " << getOccurrence() << endl;
|
||||||
|
cdebug_log(160,0) << "+ " << (getEquipotential() ? getString(getEquipotential()) : "equi=NULL") << endl;
|
||||||
|
if (not getParent()) {
|
||||||
|
if ((flags & MakeLeafEqui) and not getEquipotential()) {
|
||||||
|
newEquipotential();
|
||||||
|
}
|
||||||
|
cdebug_tabw(160,-1);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Tile* root = this;
|
||||||
|
while ( root->getParent() ) {
|
||||||
|
// if (flags & MergeEqui) {
|
||||||
|
// if (not root->getParent()->getEquipotential() and root->getEquipotential()) {
|
||||||
|
// cdebug_log(160,0) << "| tile has no equi, immediate merge" << endl;
|
||||||
|
// root->getParent()->setEquipotential( root->getEquipotential() );
|
||||||
|
// root->getEquipotential()->add( root->getParent()->getOccurrence ()
|
||||||
|
// , root->getParent()->getBoundingBox() );
|
||||||
|
// root->getParent()->setOccMerged( true );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
root = root->getParent();
|
||||||
|
cdebug_log(160,0) << "| parent tid=" << root->getId() << " " << root->getOccurrence() << endl;
|
||||||
|
}
|
||||||
|
cdebug_log(160,0) << "> root tid=" << root->getId() << " "
|
||||||
|
<< (root->getEquipotential() ? getString(root->getEquipotential()) : "equi=NULL") << endl;
|
||||||
|
|
||||||
|
|
||||||
|
if (flags & MergeEqui) {
|
||||||
|
Equipotential* rootEqui = root->getEquipotential();
|
||||||
|
if (not rootEqui) {
|
||||||
|
rootEqui = root->newEquipotential();
|
||||||
|
}
|
||||||
|
|
||||||
|
Tile* current = this;
|
||||||
|
while ((current != root) and current) {
|
||||||
|
if (current->isUpToDate()) {
|
||||||
|
cdebug_log(160,0) << "> Up to date current: tid=" << current->getId() << endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (not current->isOccMerged()) {
|
||||||
|
if (current->getEquipotential()) {
|
||||||
|
if (current->getEquipotential() != rootEqui) {
|
||||||
|
cdebug_log(160,0) << "| merge tid=" << current->getId() << " => tid=" << root->getId() << endl;
|
||||||
|
cdebug_log(160,0) << "| tid=" << current->getEquipotential() << endl;
|
||||||
|
rootEqui->merge( current->getEquipotential() );
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
cdebug_log(160,0) << "| add " << current->getOccurrence() << endl;
|
||||||
|
rootEqui->add( current->getOccurrence(), _boundingBox );
|
||||||
|
}
|
||||||
|
current->setOccMerged( true );
|
||||||
|
current->syncTime();
|
||||||
|
cdebug_log(160,0) << "| current up to date: time=" << current->_timeStamp
|
||||||
|
<< " " << current->isUpToDate() << endl;
|
||||||
|
}
|
||||||
|
current = current->getParent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & Compress) {
|
||||||
|
Tile* current = this;
|
||||||
|
while ( current != root ) {
|
||||||
|
Tile* curParent = current->getParent();
|
||||||
|
current->setParent( root );
|
||||||
|
current = curParent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cdebug_tabw(160,-1);
|
||||||
|
return root;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Tile* Tile::merge ( Tile* other )
|
||||||
|
{
|
||||||
|
cdebug_log(160,1) << "Tile::merge() this->tid:" << getId()
|
||||||
|
<< " + other->tid:" << other->getId() << endl;
|
||||||
|
Tile* root1 = getRoot( Compress|MergeEqui );
|
||||||
|
Tile* root2 = other->getRoot( Compress|MergeEqui );
|
||||||
|
if (root1 and (root1 == root2)) {
|
||||||
|
cdebug_log(160,0) << "Already have same root tid:" << root1->getId() << endl;
|
||||||
|
cdebug_tabw(160,-1);
|
||||||
|
return root1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (root1->getRank() < root2->getRank())
|
||||||
|
std::swap( root1, root2 );
|
||||||
|
if (root1->getRank() == root2->getRank())
|
||||||
|
root1->incRank();
|
||||||
|
root2->setParent( root1 );
|
||||||
|
cdebug_log(160,0) << "New root tid:" << root1->getId()
|
||||||
|
<< " child tid:" << root2->getId() << endl;
|
||||||
|
// Fuse root2 into root1 here!
|
||||||
|
|
||||||
|
cdebug_tabw(160,-1);
|
||||||
|
return root1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Equipotential* Tile::newEquipotential ()
|
||||||
|
{
|
||||||
|
if (_equipotential) {
|
||||||
|
cerr << Error( "Tile::newEquipotential(): Equipotential already created (ignoring).\n"
|
||||||
|
" (on: %s)"
|
||||||
|
, getString(this).c_str()
|
||||||
|
) << endl;
|
||||||
|
return _equipotential;
|
||||||
|
}
|
||||||
|
|
||||||
|
_equipotential = Equipotential::create( _occurrence.getOwnerCell() );
|
||||||
|
_equipotential->add( _occurrence, _boundingBox );
|
||||||
|
cdebug_log(160,0) << "new " << _equipotential << endl;
|
||||||
|
cdebug_log(160,0) << "| " << _occurrence << endl;
|
||||||
|
return _equipotential;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string Tile::_getTypeName () const
|
||||||
|
{ return "Tramontana::Tile"; }
|
||||||
|
|
||||||
|
|
||||||
|
string Tile::_getString () const
|
||||||
|
{
|
||||||
|
ostringstream os;
|
||||||
|
os << "<Tile tid:" << _id
|
||||||
|
<< " " << _boundingBox << " " << _layer->getName() << " " << _occurrence << ">";
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Record* Tile::_getRecord () const
|
||||||
|
{
|
||||||
|
Record* record = new Record ( _getString() );
|
||||||
|
if (record) {
|
||||||
|
record->add( getSlot( "_occurrence" , &_occurrence ) );
|
||||||
|
record->add( getSlot( "_layer" , _layer ) );
|
||||||
|
record->add( getSlot( "_boundingBox", &_boundingBox ) );
|
||||||
|
record->add( getSlot( "_flags" , &_flags ) );
|
||||||
|
}
|
||||||
|
return record;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // Tramontana namespace.
|
|
@ -0,0 +1,245 @@
|
||||||
|
// -*- C++ -*-
|
||||||
|
//
|
||||||
|
// This file is part of the Coriolis Software.
|
||||||
|
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||||
|
//
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
// | C O R I O L I S |
|
||||||
|
// | T r a m o n t a n a - Extractor & LVX |
|
||||||
|
// | |
|
||||||
|
// | Algorithm : Christian MASSON |
|
||||||
|
// | First impl. : Yifei WU |
|
||||||
|
// | Second impl. : Jean-Paul CHAPUT |
|
||||||
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||||
|
// | =============================================================== |
|
||||||
|
// | C++ Module : "./TramontanaEngine.cpp" |
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
#include <Python.h>
|
||||||
|
#include <sstream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iomanip>
|
||||||
|
#include "hurricane/utilities/Path.h"
|
||||||
|
#include "hurricane/DebugSession.h"
|
||||||
|
#include "hurricane/UpdateSession.h"
|
||||||
|
#include "hurricane/Bug.h"
|
||||||
|
#include "hurricane/Error.h"
|
||||||
|
#include "hurricane/Warning.h"
|
||||||
|
#include "hurricane/Breakpoint.h"
|
||||||
|
#include "hurricane/Timer.h"
|
||||||
|
#include "hurricane/Layer.h"
|
||||||
|
#include "hurricane/Net.h"
|
||||||
|
#include "hurricane/Pad.h"
|
||||||
|
#include "hurricane/Plug.h"
|
||||||
|
#include "hurricane/Cell.h"
|
||||||
|
#include "hurricane/Instance.h"
|
||||||
|
#include "hurricane/Vertical.h"
|
||||||
|
#include "hurricane/Horizontal.h"
|
||||||
|
#include "hurricane/RoutingPad.h"
|
||||||
|
#include "hurricane/viewer/Script.h"
|
||||||
|
#include "crlcore/Measures.h"
|
||||||
|
#include "crlcore/Utilities.h"
|
||||||
|
#include "crlcore/AllianceFramework.h"
|
||||||
|
#include "tramontana/SweepLine.h"
|
||||||
|
#include "tramontana/TramontanaEngine.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Tramontana {
|
||||||
|
|
||||||
|
using std::cout;
|
||||||
|
using std::cerr;
|
||||||
|
using std::endl;
|
||||||
|
using std::dec;
|
||||||
|
using std::setw;
|
||||||
|
using std::setfill;
|
||||||
|
using std::left;
|
||||||
|
using std::string;
|
||||||
|
using std::ostream;
|
||||||
|
using std::ofstream;
|
||||||
|
using std::ostringstream;
|
||||||
|
using std::setprecision;
|
||||||
|
using std::vector;
|
||||||
|
using std::make_pair;
|
||||||
|
using Hurricane::dbo_ptr;
|
||||||
|
using Hurricane::UpdateSession;
|
||||||
|
using Hurricane::DebugSession;
|
||||||
|
using Hurricane::tab;
|
||||||
|
using Hurricane::ForEachIterator;
|
||||||
|
using Hurricane::Bug;
|
||||||
|
using Hurricane::Error;
|
||||||
|
using Hurricane::Warning;
|
||||||
|
using Hurricane::Breakpoint;
|
||||||
|
using Hurricane::Timer;
|
||||||
|
using Hurricane::Box;
|
||||||
|
using Hurricane::Layer;
|
||||||
|
using Hurricane::Entity;
|
||||||
|
using Hurricane::Horizontal;
|
||||||
|
using Hurricane::Vertical;
|
||||||
|
using Hurricane::RoutingPad;
|
||||||
|
using Hurricane::Cell;
|
||||||
|
using Hurricane::Instance;
|
||||||
|
using CRL::Catalog;
|
||||||
|
using CRL::AllianceFramework;
|
||||||
|
using CRL::addMeasure;
|
||||||
|
using CRL::Measures;
|
||||||
|
using CRL::MeasuresSet;
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : "Tramontana::TramontanaEngine".
|
||||||
|
|
||||||
|
Name TramontanaEngine::_toolName = "Tramontana";
|
||||||
|
|
||||||
|
|
||||||
|
const Name& TramontanaEngine::staticGetName ()
|
||||||
|
{ return _toolName; }
|
||||||
|
|
||||||
|
|
||||||
|
TramontanaEngine* TramontanaEngine::get ( const Cell* cell )
|
||||||
|
{ return static_cast<TramontanaEngine*>(ToolEngine::get(cell,staticGetName())); }
|
||||||
|
|
||||||
|
|
||||||
|
TramontanaEngine::TramontanaEngine ( Cell* cell, uint32_t depth )
|
||||||
|
: Super (cell, (depth==0))
|
||||||
|
, _viewer (NULL)
|
||||||
|
, _depth (depth)
|
||||||
|
, _equipotentials()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
void TramontanaEngine::_postCreate ()
|
||||||
|
{
|
||||||
|
Super::_postCreate();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TramontanaEngine* TramontanaEngine::create ( Cell* cell, uint32_t depth )
|
||||||
|
{
|
||||||
|
TramontanaEngine* tramontana = new TramontanaEngine ( cell, depth );
|
||||||
|
|
||||||
|
tramontana->_postCreate();
|
||||||
|
|
||||||
|
return tramontana;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TramontanaEngine::_preDestroy ()
|
||||||
|
{
|
||||||
|
cdebug_log(160,1) << "TramontanaEngine::_preDestroy()" << endl;
|
||||||
|
|
||||||
|
cmess1 << " o Deleting ToolEngine<" << getName() << "> from Cell <"
|
||||||
|
<< _cell->getName() << ">" << endl;
|
||||||
|
Super::_preDestroy();
|
||||||
|
|
||||||
|
cdebug_tabw(160,-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
TramontanaEngine::~TramontanaEngine ()
|
||||||
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
const Name& TramontanaEngine::getName () const
|
||||||
|
{ return _toolName; }
|
||||||
|
|
||||||
|
|
||||||
|
void TramontanaEngine::extract ()
|
||||||
|
{
|
||||||
|
if (getDepth() == 0) {
|
||||||
|
cmess1 << " o Extracting " << getCell() << endl;
|
||||||
|
startMeasures();
|
||||||
|
}
|
||||||
|
|
||||||
|
cdebug_log(160,0) << "EXTRACTING " << getCell() << endl;
|
||||||
|
for ( Instance* instance : getCell()->getInstances() ) {
|
||||||
|
Cell* master = instance->getMasterCell();
|
||||||
|
TramontanaEngine* extractor = TramontanaEngine::get( master );
|
||||||
|
if (not extractor) {
|
||||||
|
extractor = TramontanaEngine::create( master, getDepth()+1 );
|
||||||
|
extractor->extract();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_extract();
|
||||||
|
|
||||||
|
if (getDepth() == 0) {
|
||||||
|
stopMeasures();
|
||||||
|
printMeasures();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TramontanaEngine::_extract ()
|
||||||
|
{
|
||||||
|
if (getDepth()) {
|
||||||
|
startMeasures();
|
||||||
|
}
|
||||||
|
|
||||||
|
SweepLine sweepLine ( this );
|
||||||
|
sweepLine.run();
|
||||||
|
consolidate();
|
||||||
|
//showEquipotentials();
|
||||||
|
|
||||||
|
if (getDepth()) {
|
||||||
|
stopMeasures();
|
||||||
|
|
||||||
|
ostringstream header;
|
||||||
|
ostringstream result;
|
||||||
|
|
||||||
|
header << " ";
|
||||||
|
for ( size_t i=0 ; i<getDepth() ; ++i ) header << " ";
|
||||||
|
header << "- " << getString( getCell()->getName() );
|
||||||
|
result << Timer::getStringTime (getTimer().getCombTime())
|
||||||
|
<< ", " << Timer::getStringMemory(getTimer().getIncrease());
|
||||||
|
cmess1 << Dots::asString( header.str(), result.str() ) << endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TramontanaEngine::showEquipotentials () const
|
||||||
|
{
|
||||||
|
cerr << "Equipotentials:" << endl;
|
||||||
|
for ( Equipotential* equi : _equipotentials ) {
|
||||||
|
equi->show();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TramontanaEngine::consolidate ()
|
||||||
|
{
|
||||||
|
//cerr << "Tramontana::consolidate()" << endl;
|
||||||
|
for ( Equipotential* equi : _equipotentials )
|
||||||
|
equi->consolidate();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TramontanaEngine::add ( Equipotential* equi )
|
||||||
|
{
|
||||||
|
_equipotentials.insert( equi );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string TramontanaEngine::_getTypeName () const
|
||||||
|
{ return "Tramontana::TramontanaEngine"; }
|
||||||
|
|
||||||
|
|
||||||
|
string TramontanaEngine::_getString () const
|
||||||
|
{
|
||||||
|
ostringstream os;
|
||||||
|
os << "<TramontanaEngine " << _cell->getName () << ">";
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Record* TramontanaEngine::_getRecord () const
|
||||||
|
{
|
||||||
|
Record* record = Super::_getRecord ();
|
||||||
|
|
||||||
|
if (record) {
|
||||||
|
record->add( getSlot( "_equipotentials", &_equipotentials ) );
|
||||||
|
}
|
||||||
|
return record;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // Tramontana namespace.
|
|
@ -0,0 +1,175 @@
|
||||||
|
// -*- C++ -*-
|
||||||
|
//
|
||||||
|
// This file is part of the Coriolis Software.
|
||||||
|
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||||
|
//
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
// | C O R I O L I S |
|
||||||
|
// | T r a m o n t a n a - Extractor & LVX |
|
||||||
|
// | |
|
||||||
|
// | Algorithm : Christian MASSON |
|
||||||
|
// | First impl. : Yifei WU |
|
||||||
|
// | Second impl. : Jean-Paul CHAPUT |
|
||||||
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||||
|
// | =============================================================== |
|
||||||
|
// | C++ Header : "./tramontana/Equipotential.h" |
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <iostream>
|
||||||
|
#include <set>
|
||||||
|
#include "hurricane/Net.h"
|
||||||
|
#include "hurricane/Component.h"
|
||||||
|
#include "hurricane/Occurrence.h"
|
||||||
|
#include "hurricane/Occurrences.h"
|
||||||
|
#include "tramontana/EquipotentialRelation.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Tramontana {
|
||||||
|
|
||||||
|
using Hurricane::Record;
|
||||||
|
using Hurricane::Box;
|
||||||
|
using Hurricane::DbU;
|
||||||
|
using Hurricane::DBo;
|
||||||
|
using Hurricane::Entity;
|
||||||
|
using Hurricane::Layer;
|
||||||
|
using Hurricane::BasicLayer;
|
||||||
|
using Hurricane::Net;
|
||||||
|
using Hurricane::NetSet;
|
||||||
|
using Hurricane::Cell;
|
||||||
|
using Hurricane::Component;
|
||||||
|
using Hurricane::OccurrenceSet;
|
||||||
|
using Hurricane::Occurrence;
|
||||||
|
using Hurricane::Occurrences;
|
||||||
|
|
||||||
|
|
||||||
|
class NetCompareByName {
|
||||||
|
public:
|
||||||
|
bool operator() ( const Net* lhs, const Net* rhs ) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class OccNetCompareByName {
|
||||||
|
public:
|
||||||
|
bool operator() ( const Occurrence& lhs, const Occurrence& rhs ) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : "Tramontana::ShortCircuit".
|
||||||
|
|
||||||
|
class ShortCircuit {
|
||||||
|
public:
|
||||||
|
inline ShortCircuit ( Net*, Net*, Component* );
|
||||||
|
private:
|
||||||
|
Net* _netA;
|
||||||
|
Net* _netB;
|
||||||
|
Component* _shortCircuit;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
inline ShortCircuit::ShortCircuit ( Net* a, Net* b, Component* shortCircuit )
|
||||||
|
: _netA (a)
|
||||||
|
, _netB (b)
|
||||||
|
, _shortCircuit(shortCircuit)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : "Tramontana::Equipotential".
|
||||||
|
|
||||||
|
class Equipotential : public Entity {
|
||||||
|
public:
|
||||||
|
typedef Entity Super;
|
||||||
|
typedef std::map< Net*, std::pair<uint32_t,uint32_t>, NetCompareByName > NetMap;
|
||||||
|
public:
|
||||||
|
static Equipotential* get ( Component* );
|
||||||
|
static Equipotential* get ( Occurrence );
|
||||||
|
static Occurrence getChildEqui ( Occurrence );
|
||||||
|
public:
|
||||||
|
static Equipotential* create ( Cell* );
|
||||||
|
inline bool isEmpty () const;
|
||||||
|
inline bool isBuried () const;
|
||||||
|
virtual Cell* getCell () const;
|
||||||
|
virtual Box getBoundingBox () const;
|
||||||
|
inline std::string getName () const;
|
||||||
|
std::string getFlagsAsString () const;
|
||||||
|
inline Net::Type getType () const;
|
||||||
|
inline Net::Direction getDirection () const;
|
||||||
|
void show () const;
|
||||||
|
inline bool hasComponent ( Component* ) const;
|
||||||
|
void add ( Occurrence, const Box& boundingBox=Box() );
|
||||||
|
void merge ( Equipotential* );
|
||||||
|
inline void add ( ShortCircuit* );
|
||||||
|
void consolidate ();
|
||||||
|
void clear ();
|
||||||
|
inline const OccurrenceSet& getComponents () const;
|
||||||
|
inline const OccurrenceSet& getChilds () const;
|
||||||
|
inline const NetMap& getNets () const;
|
||||||
|
Occurrences getFlatComponents () const;
|
||||||
|
inline const std::vector<ShortCircuit*>&
|
||||||
|
getShortCircuits () const;
|
||||||
|
Record* _getRecord () const;
|
||||||
|
std::string _getString () const;
|
||||||
|
std::string _getTypeName () const;
|
||||||
|
protected:
|
||||||
|
virtual void _postCreate ();
|
||||||
|
virtual void _preDestroy ();
|
||||||
|
private:
|
||||||
|
Equipotential ( Cell* );
|
||||||
|
~Equipotential ();
|
||||||
|
private:
|
||||||
|
Equipotential ( const Equipotential& ) = delete;
|
||||||
|
Equipotential& operator= ( const Equipotential& ) = delete;
|
||||||
|
private:
|
||||||
|
Cell* _owner;
|
||||||
|
Box _boundingBox;
|
||||||
|
NetMap _nets;
|
||||||
|
OccurrenceSet _components;
|
||||||
|
OccurrenceSet _childs;
|
||||||
|
std::string _name;
|
||||||
|
Net::Type _type;
|
||||||
|
Net::Direction _direction;
|
||||||
|
uint32_t _netCount;
|
||||||
|
bool _isBuried;
|
||||||
|
bool _isExternal;
|
||||||
|
bool _isGlobal;
|
||||||
|
bool _isAutomatic;
|
||||||
|
bool _hasFused;
|
||||||
|
std::vector<ShortCircuit*> _shortCircuits;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
inline bool Equipotential::isEmpty () const { return _components.empty() and _childs.empty(); }
|
||||||
|
inline bool Equipotential::isBuried () const { return _isBuried; }
|
||||||
|
inline const OccurrenceSet& Equipotential::getComponents () const { return _components; }
|
||||||
|
inline const OccurrenceSet& Equipotential::getChilds () const { return _childs; }
|
||||||
|
inline const Equipotential::NetMap&
|
||||||
|
Equipotential::getNets () const { return _nets; }
|
||||||
|
inline std::string Equipotential::getName () const { return _name; }
|
||||||
|
inline Net::Type Equipotential::getType () const { return _type; }
|
||||||
|
inline Net::Direction Equipotential::getDirection () const { return _direction; }
|
||||||
|
inline const std::vector<ShortCircuit*>&
|
||||||
|
Equipotential::getShortCircuits () const { return _shortCircuits; }
|
||||||
|
inline void Equipotential::add ( ShortCircuit* s ) { _shortCircuits.push_back( s ); }
|
||||||
|
|
||||||
|
inline bool Equipotential::hasComponent ( Component* component ) const
|
||||||
|
{
|
||||||
|
if (component->getCell() != getCell()) return false;
|
||||||
|
EquipotentialRelation* relation = dynamic_cast<EquipotentialRelation*>(
|
||||||
|
component->getNet()->getProperty( EquipotentialRelation::staticGetName() ));
|
||||||
|
if (not relation) {
|
||||||
|
relation = dynamic_cast<EquipotentialRelation*>(
|
||||||
|
component->getProperty( EquipotentialRelation::staticGetName() ));
|
||||||
|
}
|
||||||
|
if (not relation) return false;
|
||||||
|
return (relation->getMasterOwner() == this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
} // Tramontana namespace.
|
||||||
|
|
||||||
|
|
||||||
|
INSPECTOR_P_SUPPORT(Tramontana::Equipotential);
|
|
@ -0,0 +1,110 @@
|
||||||
|
// -*- C++ -*-
|
||||||
|
//
|
||||||
|
// This file is part of the Coriolis Software.
|
||||||
|
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||||
|
//
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
// | C O R I O L I S |
|
||||||
|
// | T r a m o n t a n a - Extractor & LVX |
|
||||||
|
// | |
|
||||||
|
// | Algorithm : Christian MASSON |
|
||||||
|
// | First impl. : Yifei WU |
|
||||||
|
// | Second impl. : Jean-Paul CHAPUT |
|
||||||
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||||
|
// | =============================================================== |
|
||||||
|
// | C++ Header : "./tramontana/EquipotentialComponents.h" |
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include <list>
|
||||||
|
#include <vector>
|
||||||
|
#include <array>
|
||||||
|
#include <map>
|
||||||
|
#include "hurricane/Collection.h"
|
||||||
|
#include "hurricane/DbU.h"
|
||||||
|
#include "hurricane/Box.h"
|
||||||
|
#include "hurricane/Net.h"
|
||||||
|
#include "hurricane/Occurrence.h"
|
||||||
|
#include "tramontana/Equipotential.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Tramontana {
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using std::pair;
|
||||||
|
using std::list;
|
||||||
|
using std::vector;
|
||||||
|
using std::map;
|
||||||
|
using Hurricane::Record;
|
||||||
|
using Hurricane::DbU;
|
||||||
|
using Hurricane::Box;
|
||||||
|
using Hurricane::Entity;
|
||||||
|
using Hurricane::Component;
|
||||||
|
using Hurricane::Net;
|
||||||
|
using Hurricane::NetSet;
|
||||||
|
using Hurricane::Occurrence;
|
||||||
|
using Hurricane::OccurrenceSet;
|
||||||
|
using Hurricane::Filter;
|
||||||
|
using Hurricane::Locator;
|
||||||
|
using Hurricane::Collection;
|
||||||
|
using Hurricane::GenericFilter;
|
||||||
|
using Hurricane::GenericLocator;
|
||||||
|
using Hurricane::GenericCollection;
|
||||||
|
|
||||||
|
typedef Hurricane::Locator<Component*> ComponentsLocator;
|
||||||
|
typedef Hurricane::Locator<Occurrence> OccurrencesLocator;
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : "Tramontana::EquipotentialComponents".
|
||||||
|
|
||||||
|
class EquipotentialComponents : public Collection<Occurrence> {
|
||||||
|
public:
|
||||||
|
typedef Collection<Occurrence> Super;
|
||||||
|
static const uint16_t Constructed = (1<<0);
|
||||||
|
static const uint16_t InComponents = (1<<1);
|
||||||
|
static const uint16_t InNets = (1<<2);
|
||||||
|
static const uint16_t InChildEquis = (1<<3);
|
||||||
|
static const uint16_t Finished = (1<<4);
|
||||||
|
public:
|
||||||
|
class Locator : public Hurricane::Locator<Occurrence> {
|
||||||
|
public:
|
||||||
|
typedef Hurricane::Locator<Occurrence> Super;
|
||||||
|
public:
|
||||||
|
Locator ();
|
||||||
|
Locator ( const Equipotential* );
|
||||||
|
Locator ( const Locator& );
|
||||||
|
Locator& operator= ( const Locator& );
|
||||||
|
virtual Occurrence getElement () const;
|
||||||
|
virtual Hurricane::Locator<Occurrence>*
|
||||||
|
getClone () const;
|
||||||
|
virtual bool isValid () const;
|
||||||
|
virtual void progress ();
|
||||||
|
virtual std::string _getString () const;
|
||||||
|
private:
|
||||||
|
const Equipotential* _equipotential;
|
||||||
|
uint16_t _state;
|
||||||
|
OccurrenceSet::iterator _componentsIterator;
|
||||||
|
Equipotential::NetMap::const_iterator _netsIterator;
|
||||||
|
OccurrenceSet::iterator _childsIterator;
|
||||||
|
OccurrencesLocator* _childCompsLocator;
|
||||||
|
ComponentsLocator* _componentsLocator;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
EquipotentialComponents ();
|
||||||
|
EquipotentialComponents ( const Equipotential* );
|
||||||
|
EquipotentialComponents ( const EquipotentialComponents& );
|
||||||
|
EquipotentialComponents& operator= ( const EquipotentialComponents& );
|
||||||
|
virtual Collection<Occurrence>* getClone () const;
|
||||||
|
virtual Hurricane::Locator<Occurrence>* getLocator () const;
|
||||||
|
virtual std::string _getString () const;
|
||||||
|
private:
|
||||||
|
const Equipotential* _equipotential;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} // Tramontana namespace.
|
|
@ -0,0 +1,56 @@
|
||||||
|
// -*- C++ -*-
|
||||||
|
//
|
||||||
|
// This file is part of the Coriolis Software.
|
||||||
|
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||||
|
//
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
// | C O R I O L I S |
|
||||||
|
// | T r a m o n t a n a - Extractor & LVX |
|
||||||
|
// | |
|
||||||
|
// | Algorithm : Christian MASSON |
|
||||||
|
// | First impl. : Yifei WU |
|
||||||
|
// | Second impl. : Jean-Paul CHAPUT |
|
||||||
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||||
|
// | =============================================================== |
|
||||||
|
// | C++ Header : "./tramontana/EquipotentialRelation.h" |
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "hurricane/Relation.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Tramontana {
|
||||||
|
|
||||||
|
using Hurricane::Name;
|
||||||
|
using Hurricane::Record;
|
||||||
|
using Hurricane::Relation;
|
||||||
|
using Hurricane::Component;
|
||||||
|
class Equipotential;
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : "Tramontana::EquipotentialRelation".
|
||||||
|
|
||||||
|
class EquipotentialRelation : public Relation {
|
||||||
|
public:
|
||||||
|
typedef Relation Super;
|
||||||
|
public:
|
||||||
|
static EquipotentialRelation* get ( const Component* );
|
||||||
|
static EquipotentialRelation* create ( Equipotential* );
|
||||||
|
static Name staticGetName ();
|
||||||
|
public:
|
||||||
|
virtual Name getName () const;
|
||||||
|
virtual std::string _getTypeName () const;
|
||||||
|
virtual Record* _getRecord () const;
|
||||||
|
private:
|
||||||
|
EquipotentialRelation ( Equipotential* );
|
||||||
|
protected:
|
||||||
|
virtual void _preDestroy ();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // Tramontana namespace.
|
||||||
|
|
||||||
|
|
||||||
|
INSPECTOR_P_SUPPORT(Tramontana::EquipotentialRelation);
|
|
@ -0,0 +1,62 @@
|
||||||
|
// -*- C++ -*-
|
||||||
|
//
|
||||||
|
// This file is part of the Coriolis Software.
|
||||||
|
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||||
|
//
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
// | C O R I O L I S |
|
||||||
|
// | T r a m o n t a n a - Extractor & LVX |
|
||||||
|
// | |
|
||||||
|
// | Algorithm : Christian MASSON |
|
||||||
|
// | First impl. : Yifei WU |
|
||||||
|
// | Second impl. : Jean-Paul CHAPUT |
|
||||||
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||||
|
// | =============================================================== |
|
||||||
|
// | C++ Header : "./tramontana/EquipotentialsModel.h" |
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <vector>
|
||||||
|
#include <QFont>
|
||||||
|
#include <QApplication>
|
||||||
|
#include <QAbstractTableModel>
|
||||||
|
#include "hurricane/Commons.h"
|
||||||
|
#include "hurricane/Name.h"
|
||||||
|
#include "hurricane/Net.h"
|
||||||
|
#include "hurricane/Cell.h"
|
||||||
|
#include "hurricane/viewer/Graphics.h"
|
||||||
|
#include "tramontana/Equipotential.h"
|
||||||
|
#include "tramontana/TramontanaEngine.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Tramontana {
|
||||||
|
|
||||||
|
using Hurricane::Cell;
|
||||||
|
|
||||||
|
|
||||||
|
class EquipotentialsModel : public QAbstractTableModel {
|
||||||
|
Q_OBJECT;
|
||||||
|
|
||||||
|
public:
|
||||||
|
EquipotentialsModel ( QObject* parent=NULL );
|
||||||
|
void setCell ( Cell* cell );
|
||||||
|
int rowCount ( const QModelIndex& parent=QModelIndex() ) const;
|
||||||
|
int columnCount ( const QModelIndex& parent=QModelIndex() ) const;
|
||||||
|
QVariant data ( const QModelIndex& index, int role=Qt::DisplayRole ) const;
|
||||||
|
QVariant headerData ( int section, Qt::Orientation orientation, int role=Qt::DisplayRole ) const;
|
||||||
|
inline Cell* getCell ();
|
||||||
|
const Equipotential* getEqui ( int row );
|
||||||
|
|
||||||
|
private:
|
||||||
|
Cell* _cell;
|
||||||
|
std::vector<Equipotential*> _equipotentials;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Inline Functions.
|
||||||
|
|
||||||
|
inline Cell* EquipotentialsModel::getCell () { return _cell; }
|
||||||
|
|
||||||
|
|
||||||
|
} // Hurricane namespace.
|
|
@ -0,0 +1,186 @@
|
||||||
|
// -*- C++ -*-
|
||||||
|
//
|
||||||
|
// This file is part of the Coriolis Software.
|
||||||
|
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||||
|
//
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
// | C O R I O L I S |
|
||||||
|
// | T r a m o n t a n a - Extractor & LVX |
|
||||||
|
// | |
|
||||||
|
// | Algorithm : Christian MASSON |
|
||||||
|
// | First impl. : Yifei WU |
|
||||||
|
// | Second impl. : Jean-Paul CHAPUT |
|
||||||
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||||
|
// | =============================================================== |
|
||||||
|
// | C++ Header : "./tramontana/EquipotentialsWidget.h" |
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <set>
|
||||||
|
#include <QWidget>
|
||||||
|
#include <QTableView>
|
||||||
|
#include <QHeaderView>
|
||||||
|
#include <QItemDelegate>
|
||||||
|
#include <QSortFilterProxyModel>
|
||||||
|
#include "hurricane/Commons.h"
|
||||||
|
#include "hurricane/Bug.h"
|
||||||
|
#include "hurricane/viewer/CellWidget.h"
|
||||||
|
#include "hurricane/viewer/CellWidget.h"
|
||||||
|
#include "tramontana/EquipotentialsModel.h"
|
||||||
|
|
||||||
|
|
||||||
|
class QSortFilterProxyModel;
|
||||||
|
class QModelIndex;
|
||||||
|
class QTableView;
|
||||||
|
class QLineEdit;
|
||||||
|
class QComboBox;
|
||||||
|
class QHeaderView;
|
||||||
|
|
||||||
|
|
||||||
|
namespace Tramontana {
|
||||||
|
|
||||||
|
using std::string;
|
||||||
|
using std::set;
|
||||||
|
using Hurricane::Cell;
|
||||||
|
using Hurricane::CellWidget;
|
||||||
|
using Hurricane::OccurrenceSet;
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : EquiFilterProxyModel".
|
||||||
|
|
||||||
|
|
||||||
|
class EquiFilterProxyModel : public QSortFilterProxyModel {
|
||||||
|
Q_OBJECT;
|
||||||
|
public:
|
||||||
|
typedef QSortFilterProxyModel Super;
|
||||||
|
static const uint32_t NoFilter = 0;
|
||||||
|
static const uint32_t ShowBuried = (1<<0);
|
||||||
|
public:
|
||||||
|
EquiFilterProxyModel ( QObject* );
|
||||||
|
void setFilter ( uint32_t );
|
||||||
|
virtual bool filterAcceptsRow ( int row, const QModelIndex& ) const;
|
||||||
|
private:
|
||||||
|
uint32_t _filter;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : "SelectedEqui".
|
||||||
|
|
||||||
|
|
||||||
|
class SelectedEqui {
|
||||||
|
public:
|
||||||
|
inline SelectedEqui ();
|
||||||
|
inline SelectedEqui ( const Equipotential*, size_t access=0 );
|
||||||
|
inline const Equipotential* getEqui () const;
|
||||||
|
inline size_t getAccesses () const;
|
||||||
|
inline void incAccesses () const;
|
||||||
|
inline void setInserted () const;
|
||||||
|
inline void resetAccesses () const;
|
||||||
|
private:
|
||||||
|
const Equipotential* _equi;
|
||||||
|
mutable size_t _accesses;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
inline SelectedEqui::SelectedEqui () : _equi(nullptr), _accesses(0) { }
|
||||||
|
inline SelectedEqui::SelectedEqui ( const Equipotential* equi, size_t accesses ) : _equi(equi), _accesses(accesses) { }
|
||||||
|
inline const Equipotential* SelectedEqui::getEqui () const { return _equi; }
|
||||||
|
inline void SelectedEqui::setInserted () const { _accesses = 64; }
|
||||||
|
inline size_t SelectedEqui::getAccesses () const { return _accesses; }
|
||||||
|
inline void SelectedEqui::incAccesses () const { ++_accesses; }
|
||||||
|
inline void SelectedEqui::resetAccesses () const { _accesses = 0; }
|
||||||
|
|
||||||
|
|
||||||
|
struct SelectedEquiCompare {
|
||||||
|
inline bool operator() ( const SelectedEqui& lhs, const SelectedEqui& rhs ) const;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
inline bool SelectedEquiCompare::operator() ( const SelectedEqui& lhs, const SelectedEqui& rhs ) const
|
||||||
|
{
|
||||||
|
return lhs.getEqui()->getId() < rhs.getEqui()->getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : "SelectedEquiSet".
|
||||||
|
|
||||||
|
|
||||||
|
class SelectedEquiSet : public set<SelectedEqui,SelectedEquiCompare>{
|
||||||
|
public:
|
||||||
|
void insert ( const Equipotential* );
|
||||||
|
void forceInserteds ();
|
||||||
|
void resetAccesses ();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
inline void SelectedEquiSet::insert ( const Equipotential* equi )
|
||||||
|
{
|
||||||
|
iterator iselected = find(SelectedEqui(equi));
|
||||||
|
if (iselected != end())
|
||||||
|
iselected->incAccesses();
|
||||||
|
else
|
||||||
|
set<SelectedEqui,SelectedEquiCompare>::insert( SelectedEqui(equi,64) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void SelectedEquiSet::forceInserteds ()
|
||||||
|
{
|
||||||
|
for ( iterator iselected=begin() ; iselected != end() ; ++iselected )
|
||||||
|
iselected->setInserted();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void SelectedEquiSet::resetAccesses ()
|
||||||
|
{
|
||||||
|
for ( iterator iselected=begin() ; iselected != end() ; ++iselected )
|
||||||
|
iselected->resetAccesses();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : "EquipotentialsWidget".
|
||||||
|
|
||||||
|
|
||||||
|
class EquipotentialsWidget : public QWidget {
|
||||||
|
Q_OBJECT;
|
||||||
|
|
||||||
|
public:
|
||||||
|
EquipotentialsWidget ( QWidget* parent=nullptr );
|
||||||
|
inline Cell* getCell ();
|
||||||
|
void setShowBuried ( bool );
|
||||||
|
void setCellWidget ( CellWidget* );
|
||||||
|
void setCell ( Cell* );
|
||||||
|
void goTo ( int );
|
||||||
|
void updateSelecteds ();
|
||||||
|
QModelIndex mapToSource ( QModelIndex ) const;
|
||||||
|
signals:
|
||||||
|
void equipotentialSelect ( Occurrences );
|
||||||
|
void equipotentialUnselect ( Occurrences );
|
||||||
|
void reframe ( const Box& );
|
||||||
|
private slots:
|
||||||
|
void textFilterChanged ();
|
||||||
|
void updateSelecteds ( const QItemSelection& , const QItemSelection& );
|
||||||
|
void fitToEqui ();
|
||||||
|
|
||||||
|
private:
|
||||||
|
CellWidget* _cellWidget;
|
||||||
|
Cell* _cell;
|
||||||
|
EquipotentialsModel* _baseModel;
|
||||||
|
QSortFilterProxyModel* _sortModel;
|
||||||
|
EquiFilterProxyModel* _filterModel;
|
||||||
|
QTableView* _view;
|
||||||
|
QLineEdit* _filterPatternLineEdit;
|
||||||
|
int _rowHeight;
|
||||||
|
SelectedEquiSet _selecteds;
|
||||||
|
bool _forceReselect;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
inline Cell* EquipotentialsWidget::getCell () { return _cell; }
|
||||||
|
|
||||||
|
|
||||||
|
} // Hurricane namespace.
|
|
@ -0,0 +1,83 @@
|
||||||
|
// -*- C++ -*-
|
||||||
|
//
|
||||||
|
// This file is part of the Coriolis Software.
|
||||||
|
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||||
|
//
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
// | C O R I O L I S |
|
||||||
|
// | T r a m o n t a n a - Extractor & LVX |
|
||||||
|
// | |
|
||||||
|
// | Algorithm : Christian MASSON |
|
||||||
|
// | First impl. : Yifei WU |
|
||||||
|
// | Second impl. : Jean-Paul CHAPUT |
|
||||||
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||||
|
// | =============================================================== |
|
||||||
|
// | C++ Header : "./tramontana/GraphicTramontanaEngine.h" |
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <functional>
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
namespace Hurricane {
|
||||||
|
class Go;
|
||||||
|
class BasicLayer;
|
||||||
|
class Transformation;
|
||||||
|
class CellWidget;
|
||||||
|
class CellViewer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include "crlcore/GraphicToolEngine.h"
|
||||||
|
#include "tramontana/TramontanaEngine.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Tramontana {
|
||||||
|
|
||||||
|
using Hurricane::Go;
|
||||||
|
using Hurricane::Box;
|
||||||
|
using Hurricane::BasicLayer;
|
||||||
|
using Hurricane::Transformation;
|
||||||
|
using Hurricane::CellWidget;
|
||||||
|
using Hurricane::CellViewer;
|
||||||
|
using CRL::GraphicTool;
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : "Tramontana::GraphicTramontanaEngine".
|
||||||
|
|
||||||
|
class GraphicTramontanaEngine : public GraphicTool {
|
||||||
|
Q_OBJECT;
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum FunctionFlags { NoFlags=0x0000, CreateEngine=0x0001 };
|
||||||
|
public:
|
||||||
|
#if THIS_IS_DISABLED
|
||||||
|
static void initGCell ( CellWidget* );
|
||||||
|
static void drawGCell ( CellWidget*
|
||||||
|
, const Go*
|
||||||
|
, const BasicLayer*
|
||||||
|
, const Box&
|
||||||
|
, const Transformation&
|
||||||
|
);
|
||||||
|
#endif
|
||||||
|
TramontanaEngine* createEngine ();
|
||||||
|
TramontanaEngine* getForFramework ( uint32_t flags );
|
||||||
|
static GraphicTramontanaEngine* grab ();
|
||||||
|
virtual const Name& getName () const;
|
||||||
|
Cell* getCell ();
|
||||||
|
virtual size_t release ();
|
||||||
|
virtual void addToMenu ( CellViewer* );
|
||||||
|
void postEvent ();
|
||||||
|
protected:
|
||||||
|
static size_t _references;
|
||||||
|
static GraphicTramontanaEngine* _singleton;
|
||||||
|
CellViewer* _viewer;
|
||||||
|
protected:
|
||||||
|
GraphicTramontanaEngine ();
|
||||||
|
virtual ~GraphicTramontanaEngine ();
|
||||||
|
void _extract ();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // Tramontana namespace.
|
|
@ -0,0 +1,53 @@
|
||||||
|
// -*- C++ -*-
|
||||||
|
//
|
||||||
|
// This file is part of the Coriolis Software.
|
||||||
|
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||||
|
//
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
// | C O R I O L I S |
|
||||||
|
// | T r a m o n t a n a - Extractor & LVX |
|
||||||
|
// | |
|
||||||
|
// | Algorithm : Christian MASSON |
|
||||||
|
// | First impl. : Yifei WU |
|
||||||
|
// | Second impl. : Jean-Paul CHAPUT |
|
||||||
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||||
|
// | =============================================================== |
|
||||||
|
// | C++ Header : "./tramontana/PyGraphicTramontanaEngine.h" |
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "crlcore/PyGraphicToolEngine.h"
|
||||||
|
#include "tramontana/GraphicTramontanaEngine.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Tramontana {
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Python Object : "PyGraphicTramontanaEngine".
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
CRL::PyGraphicTool _baseObject;
|
||||||
|
} PyGraphicTramontanaEngine;
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Functions & Types exported to "PyTramontana.ccp".
|
||||||
|
|
||||||
|
extern PyTypeObject PyTypeGraphicTramontanaEngine;
|
||||||
|
extern PyMethodDef PyGraphicTramontanaEngine_Methods[];
|
||||||
|
|
||||||
|
extern void PyGraphicTramontanaEngine_LinkPyType ();
|
||||||
|
|
||||||
|
|
||||||
|
#define IsPyGraphicTramontanaEngine(v) ( (v)->ob_type == &PyTypeGraphicTramontanaEngine )
|
||||||
|
#define PY_GRAPHIC_TRAMONTANA_ENGINE(v) ( (PyGraphicTramontanaEngine*)(v) )
|
||||||
|
#define PY_GRAPHIC_TRAMONTANA_ENGINE_O(v) ( PY_GRAPHIC_TRAMONTANA_ENGINE(v)->_baseObject._object )
|
||||||
|
|
||||||
|
|
||||||
|
} // extern "C".
|
||||||
|
|
||||||
|
} // Tramontana namespace.
|
|
@ -0,0 +1,56 @@
|
||||||
|
// -*- C++ -*-
|
||||||
|
//
|
||||||
|
// This file is part of the Coriolis Software.
|
||||||
|
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||||
|
//
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
// | C O R I O L I S |
|
||||||
|
// | T r a m o n t a n a - Extractor & LVX |
|
||||||
|
// | |
|
||||||
|
// | Algorithm : Christian MASSON |
|
||||||
|
// | First impl. : Yifei WU |
|
||||||
|
// | Second impl. : Jean-Paul CHAPUT |
|
||||||
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||||
|
// | =============================================================== |
|
||||||
|
// | C++ Header : "./tramontana/PyTramontanaEngine.h" |
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "hurricane/isobar/PyHurricane.h"
|
||||||
|
#include "crlcore/PyToolEngine.h"
|
||||||
|
#include "tramontana/TramontanaEngine.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Tramontana {
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Python Object : "PyTramontanaEngine".
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
CRL::PyToolEngine _baseObject;
|
||||||
|
} PyTramontanaEngine;
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Functions & Types exported to "PyTramontana.ccp".
|
||||||
|
|
||||||
|
extern PyTypeObject PyTypeTramontanaEngine;
|
||||||
|
extern PyMethodDef PyTramontanaEngine_Methods[];
|
||||||
|
|
||||||
|
extern PyObject* PyTramontanaEngine_Link ( Tramontana::TramontanaEngine* );
|
||||||
|
extern void PyTramontanaEngine_LinkPyType ();
|
||||||
|
//extern void PyTramontanaEngine_postModuleInit ();
|
||||||
|
|
||||||
|
|
||||||
|
#define IsPyTramontanaEngine(v) ( (v)->ob_type == &PyTypeTramontanaEngine )
|
||||||
|
#define PYTRAMONTANAENGINE(v) ( (PyTramontanaEngine*)(v) )
|
||||||
|
#define PYTRAMONTANAENGINE_O(v) ( PYTRAMONTANAENGINE(v)->_baseObject._object )
|
||||||
|
|
||||||
|
|
||||||
|
} // extern "C".
|
||||||
|
|
||||||
|
} // Tramontana namespace.
|
|
@ -0,0 +1,60 @@
|
||||||
|
// -*- C++ -*-
|
||||||
|
//
|
||||||
|
// This file is part of the Coriolis Software.
|
||||||
|
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||||
|
//
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
// | C O R I O L I S |
|
||||||
|
// | T r a m o n t a n a - Extractor & LVX |
|
||||||
|
// | |
|
||||||
|
// | Algorithm : Christian MASSON |
|
||||||
|
// | First impl. : Yifei WU |
|
||||||
|
// | Second impl. : Jean-Paul CHAPUT |
|
||||||
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||||
|
// | =============================================================== |
|
||||||
|
// | C++ Header : "./tramontana/QueryTiles.h" |
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "hurricane/Query.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Tramontana {
|
||||||
|
|
||||||
|
using Hurricane::Box;
|
||||||
|
using Hurricane::DbU;
|
||||||
|
using Hurricane::Layer;
|
||||||
|
using Hurricane::BasicLayer;
|
||||||
|
using Hurricane::Go;
|
||||||
|
using Hurricane::Component;
|
||||||
|
using Hurricane::Rubber;
|
||||||
|
using Hurricane::Query;
|
||||||
|
class SweepLine;
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : "Tramontana::QueryTiles".
|
||||||
|
|
||||||
|
class QueryTiles : public Query {
|
||||||
|
public:
|
||||||
|
QueryTiles ( SweepLine* );
|
||||||
|
bool isProcessed ( Component* ) const;
|
||||||
|
virtual void setBasicLayer ( const BasicLayer* );
|
||||||
|
virtual bool hasGoCallback () const;
|
||||||
|
virtual void goCallback ( Go* );
|
||||||
|
virtual void rubberCallback ( Rubber* );
|
||||||
|
virtual void extensionGoCallback ( Go* );
|
||||||
|
virtual void masterCellCallback ();
|
||||||
|
inline uint32_t getGoMatchCount () const;
|
||||||
|
private:
|
||||||
|
SweepLine* _sweepLine;
|
||||||
|
uint32_t _goMatchCount;
|
||||||
|
Layer::Mask _processedLayers;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
inline uint32_t QueryTiles::getGoMatchCount () const { return _goMatchCount; }
|
||||||
|
|
||||||
|
|
||||||
|
} // Tramontana namespace.
|
|
@ -0,0 +1,137 @@
|
||||||
|
// -*- C++ -*-
|
||||||
|
//
|
||||||
|
// This file is part of the Coriolis Software.
|
||||||
|
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||||
|
//
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
// | C O R I O L I S |
|
||||||
|
// | T r a m o n t a n a - Extractor & LVX |
|
||||||
|
// | |
|
||||||
|
// | Algorithm : Christian MASSON |
|
||||||
|
// | First impl. : Yifei WU |
|
||||||
|
// | Second impl. : Jean-Paul CHAPUT |
|
||||||
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||||
|
// | =============================================================== |
|
||||||
|
// | C++ Header : "./tramontana/SweepLine.h" |
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include <list>
|
||||||
|
#include <map>
|
||||||
|
#include "hurricane/BasicLayer.h"
|
||||||
|
namespace Hurricane {
|
||||||
|
class Net;
|
||||||
|
}
|
||||||
|
#include "tramontana/Tile.h"
|
||||||
|
#include "tramontana/TramontanaEngine.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Tramontana {
|
||||||
|
|
||||||
|
using Hurricane::Record;
|
||||||
|
using Hurricane::Box;
|
||||||
|
using Hurricane::DbU;
|
||||||
|
using Hurricane::DBo;
|
||||||
|
using Hurricane::Cell;
|
||||||
|
using Hurricane::Layer;
|
||||||
|
using Hurricane::BasicLayer;
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : "Tramontana::SweepLine".
|
||||||
|
|
||||||
|
class SweepLine {
|
||||||
|
private:
|
||||||
|
typedef std::map<Layer::Mask, TileIntvTree> IntervalTrees;
|
||||||
|
public:
|
||||||
|
typedef std::set<const BasicLayer*, DBo::CompareById> LayerSet;
|
||||||
|
typedef std::map<const BasicLayer*, LayerSet, DBo::CompareById> ConnexityMap;
|
||||||
|
private:
|
||||||
|
class Element {
|
||||||
|
public:
|
||||||
|
inline Element ( Tile*, uint32_t flags );
|
||||||
|
inline bool operator< ( const Element& ) const;
|
||||||
|
inline bool operator== ( const Element& ) const;
|
||||||
|
inline bool isLeftEdge () const;
|
||||||
|
inline Tile* getTile () const;
|
||||||
|
inline DbU::Unit getX () const;
|
||||||
|
inline DbU::Unit getY () const;
|
||||||
|
inline DbU::Unit getId () const;
|
||||||
|
inline Layer::Mask getMask () const;
|
||||||
|
private:
|
||||||
|
Tile* _tile;
|
||||||
|
uint32_t _flags;
|
||||||
|
};
|
||||||
|
public:
|
||||||
|
SweepLine ( TramontanaEngine* );
|
||||||
|
~SweepLine ();
|
||||||
|
inline Cell* getCell ();
|
||||||
|
inline const std::vector<const BasicLayer*>&
|
||||||
|
getExtracteds () const;
|
||||||
|
inline Layer::Mask getExtractedMask () const;
|
||||||
|
const LayerSet& getCutConnexLayers ( const BasicLayer* ) const;
|
||||||
|
void run ();
|
||||||
|
void loadTiles ();
|
||||||
|
void deleteTiles ();
|
||||||
|
inline void add ( Tile* );
|
||||||
|
void mergeEquipotentials ();
|
||||||
|
Record* _getRecord () const;
|
||||||
|
std::string _getString () const;
|
||||||
|
std::string _getTypeName () const;
|
||||||
|
private:
|
||||||
|
SweepLine ( const SweepLine& ) = delete;
|
||||||
|
SweepLine& operator= ( const SweepLine& ) = delete;
|
||||||
|
void _buildCutConnexMap ();
|
||||||
|
private:
|
||||||
|
TramontanaEngine* _tramontana;
|
||||||
|
std::vector<const BasicLayer*> _extracteds;
|
||||||
|
Layer::Mask _extractedsMask;
|
||||||
|
ConnexityMap _connexityMap;
|
||||||
|
std::vector<Element> _tiles;
|
||||||
|
IntervalTrees _intervalTrees;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// SweepLine::Element.
|
||||||
|
inline SweepLine::Element::Element ( Tile* tile, uint32_t flags ) : _tile(tile), _flags(flags) { }
|
||||||
|
inline bool SweepLine::Element::isLeftEdge () const { return _flags & Tile::LeftEdge; }
|
||||||
|
inline Tile* SweepLine::Element::getTile () const { return _tile; }
|
||||||
|
inline DbU::Unit SweepLine::Element::getX () const { return isLeftEdge() ? _tile->getLeftEdge() : _tile->getRightEdge(); }
|
||||||
|
inline DbU::Unit SweepLine::Element::getY () const { return _tile->getBoundingBox().getYMin(); }
|
||||||
|
inline DbU::Unit SweepLine::Element::getId () const { return _tile->getId(); }
|
||||||
|
inline Layer::Mask SweepLine::Element::getMask () const { return _tile->getMask(); }
|
||||||
|
|
||||||
|
inline bool SweepLine::Element::operator< ( const Element& rhs ) const
|
||||||
|
{
|
||||||
|
if (getX() != rhs.getX()) return (getX() < rhs.getX());
|
||||||
|
if (isLeftEdge() xor rhs.isLeftEdge()) return isLeftEdge();
|
||||||
|
if (getY() != rhs.getY()) return (getY() < rhs.getY());
|
||||||
|
if (getMask() != rhs.getMask()) return (getMask() < rhs.getMask());
|
||||||
|
return TileCompare() ( getTile(), rhs.getTile() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline bool SweepLine::Element::operator== ( const Element& rhs ) const
|
||||||
|
{ return getTile() == rhs.getTile(); }
|
||||||
|
|
||||||
|
|
||||||
|
// SweepLine.
|
||||||
|
inline Cell* SweepLine::getCell () { return _tramontana->getCell(); }
|
||||||
|
inline const std::vector<const BasicLayer*>& SweepLine::getExtracteds () const { return _extracteds; }
|
||||||
|
inline Layer::Mask SweepLine::getExtractedMask () const { return _extractedsMask; }
|
||||||
|
|
||||||
|
inline void SweepLine::add ( Tile* tile )
|
||||||
|
{
|
||||||
|
_tiles.push_back( Element( tile, Tile::LeftEdge ) );
|
||||||
|
_tiles.push_back( Element( tile, Tile::RightEdge ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} // Tramontana namespace.
|
||||||
|
|
||||||
|
|
||||||
|
INSPECTOR_P_SUPPORT(Tramontana::SweepLine);
|
|
@ -0,0 +1,60 @@
|
||||||
|
// -*- C++ -*-
|
||||||
|
//
|
||||||
|
// This file is part of the Coriolis Software.
|
||||||
|
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||||
|
//
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
// | C O R I O L I S |
|
||||||
|
// | T r a m o n t a n a - Extractor & LVX |
|
||||||
|
// | |
|
||||||
|
// | Algorithm : Christian MASSON |
|
||||||
|
// | First impl. : Yifei WU |
|
||||||
|
// | Second impl. : Jean-Paul CHAPUT |
|
||||||
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||||
|
// | =============================================================== |
|
||||||
|
// | C++ Header : "./tramontana/TabEquipotentials.h" |
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "hurricane/viewer/ControllerWidget.h"
|
||||||
|
#include "tramontana/EquipotentialsWidget.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Tramontana {
|
||||||
|
|
||||||
|
using Hurricane::ControllerTab;
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : "Tramontana::TabEquipotentials".
|
||||||
|
|
||||||
|
|
||||||
|
class TabEquipotentials : public ControllerTab {
|
||||||
|
Q_OBJECT;
|
||||||
|
|
||||||
|
public:
|
||||||
|
TabEquipotentials ( QWidget* parent=NULL );
|
||||||
|
inline EquipotentialsWidget* getBrowser ();
|
||||||
|
virtual void cellPreModificate ();
|
||||||
|
virtual void cellPostModificate ();
|
||||||
|
public slots:
|
||||||
|
virtual void setCell ( Cell* );
|
||||||
|
virtual void setCellWidget ( CellWidget* );
|
||||||
|
virtual void setSyncEquipotentials ( bool );
|
||||||
|
virtual void setSyncSelection ( bool );
|
||||||
|
virtual void setShowBuried ( bool );
|
||||||
|
|
||||||
|
protected:
|
||||||
|
EquipotentialsWidget* _browser;
|
||||||
|
QCheckBox* _syncEquipotentials;
|
||||||
|
QCheckBox* _syncSelection;
|
||||||
|
QCheckBox* _showBuried;
|
||||||
|
bool _cwCumulativeSelection;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
inline EquipotentialsWidget* TabEquipotentials::getBrowser () { return _browser; }
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,173 @@
|
||||||
|
// -*- C++ -*-
|
||||||
|
//
|
||||||
|
// This file is part of the Coriolis Software.
|
||||||
|
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||||
|
//
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
// | C O R I O L I S |
|
||||||
|
// | T r a m o n t a n a - Extractor & LVX |
|
||||||
|
// | |
|
||||||
|
// | Algorithm : Christian MASSON |
|
||||||
|
// | First impl. : Yifei WU |
|
||||||
|
// | Second impl. : Jean-Paul CHAPUT |
|
||||||
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||||
|
// | =============================================================== |
|
||||||
|
// | C++ Header : "./tramontana/Tile.h" |
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <iostream>
|
||||||
|
#include <vector>
|
||||||
|
#include "hurricane/Box.h"
|
||||||
|
#include "hurricane/BasicLayer.h"
|
||||||
|
#include "hurricane/Component.h"
|
||||||
|
#include "hurricane/Occurrence.h"
|
||||||
|
#include "hurricane/IntervalTree.h"
|
||||||
|
namespace Hurricane {
|
||||||
|
class Net;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
namespace Tramontana {
|
||||||
|
|
||||||
|
using Hurricane::Record;
|
||||||
|
using Hurricane::Box;
|
||||||
|
using Hurricane::DbU;
|
||||||
|
using Hurricane::Layer;
|
||||||
|
using Hurricane::BasicLayer;
|
||||||
|
using Hurricane::Net;
|
||||||
|
using Hurricane::Cell;
|
||||||
|
using Hurricane::Component;
|
||||||
|
using Hurricane::Occurrence;
|
||||||
|
using Hurricane::RbTree;
|
||||||
|
using Hurricane::IntervalData;
|
||||||
|
using Hurricane::IntervalTree;
|
||||||
|
class Equipotential;
|
||||||
|
class SweepLine;
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : "Tramontana::Tile".
|
||||||
|
|
||||||
|
class Tile {
|
||||||
|
public:
|
||||||
|
static const uint32_t NoFlags = 0;
|
||||||
|
static const uint32_t LeftEdge = (1<<0);
|
||||||
|
static const uint32_t RightEdge = (1<<1);
|
||||||
|
static const uint32_t Compress = (1<<2);
|
||||||
|
static const uint32_t MergeEqui = (1<<3);
|
||||||
|
static const uint32_t MakeLeafEqui = (1<<4);
|
||||||
|
static const uint32_t ForceLayer = (1<<5);
|
||||||
|
static const uint32_t OccMerged = (1<<6);
|
||||||
|
public:
|
||||||
|
static inline const std::vector<Tile*> getAllTiles ();
|
||||||
|
static void deleteAllTiles ();
|
||||||
|
static inline void timeTick ();
|
||||||
|
static Tile* create ( Occurrence
|
||||||
|
, const BasicLayer*
|
||||||
|
, Tile* rootTile
|
||||||
|
, SweepLine*
|
||||||
|
, uint32_t flags=NoFlags );
|
||||||
|
void destroy ();
|
||||||
|
inline bool isUpToDate () const;
|
||||||
|
inline bool isOccMerged () const;
|
||||||
|
inline unsigned int getId () const;
|
||||||
|
inline uint32_t getRank () const;
|
||||||
|
inline Tile* getParent () const;
|
||||||
|
Tile* getRoot ( uint32_t flags=Compress );
|
||||||
|
//inline Component* getComponent () const;
|
||||||
|
inline Occurrence getOccurrence () const;
|
||||||
|
// Net* getNet () const;
|
||||||
|
inline Layer::Mask getMask () const;
|
||||||
|
inline const BasicLayer* getLayer () const;
|
||||||
|
inline const Box& getBoundingBox () const;
|
||||||
|
inline Equipotential* getEquipotential () const;
|
||||||
|
inline DbU::Unit getLeftEdge () const;
|
||||||
|
inline DbU::Unit getRightEdge () const;
|
||||||
|
inline DbU::Unit getYMin () const;
|
||||||
|
inline DbU::Unit getYMax () const;
|
||||||
|
inline uint32_t getFlags () const;
|
||||||
|
inline void incRank ();
|
||||||
|
inline void syncTime ();
|
||||||
|
inline void setParent ( Tile* );
|
||||||
|
Tile* merge ( Tile* );
|
||||||
|
inline void setOccMerged ( bool state );
|
||||||
|
inline void setEquipotential ( Equipotential* );
|
||||||
|
Equipotential* newEquipotential ();
|
||||||
|
Record* _getRecord () const;
|
||||||
|
std::string _getString () const;
|
||||||
|
std::string _getTypeName () const;
|
||||||
|
private:
|
||||||
|
Tile ( Occurrence, const BasicLayer*, const Box&, Tile* parent );
|
||||||
|
~Tile ();
|
||||||
|
private:
|
||||||
|
Tile ( const Tile& ) = delete;
|
||||||
|
Tile& operator= ( const Tile& ) = delete;
|
||||||
|
private:
|
||||||
|
static uint32_t _idCounter;
|
||||||
|
static uint32_t _time;
|
||||||
|
static std::vector<Tile*> _allocateds;
|
||||||
|
uint32_t _id;
|
||||||
|
Occurrence _occurrence;
|
||||||
|
const BasicLayer* _layer;
|
||||||
|
Box _boundingBox;
|
||||||
|
Equipotential* _equipotential;
|
||||||
|
uint32_t _flags;
|
||||||
|
Tile* _parent;
|
||||||
|
uint32_t _rank;
|
||||||
|
uint32_t _timeStamp;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline const std::vector<Tile*> Tile::getAllTiles () { return _allocateds; }
|
||||||
|
inline void Tile::timeTick () { _time++; }
|
||||||
|
inline bool Tile::isUpToDate () const { return _timeStamp >= _time; }
|
||||||
|
inline bool Tile::isOccMerged () const { return _flags & OccMerged; }
|
||||||
|
inline unsigned int Tile::getId () const { return _id; }
|
||||||
|
//inline Component* Tile::getComponent () const { return dynamic_cast<Component*>( _occurrence.getEntity() ); }
|
||||||
|
inline Occurrence Tile::getOccurrence () const { return _occurrence; }
|
||||||
|
inline Layer::Mask Tile::getMask () const { return _layer->getMask(); }
|
||||||
|
inline const BasicLayer* Tile::getLayer () const { return _layer; }
|
||||||
|
inline const Box& Tile::getBoundingBox () const { return _boundingBox; }
|
||||||
|
inline Equipotential* Tile::getEquipotential () const { return _equipotential; }
|
||||||
|
inline DbU::Unit Tile::getLeftEdge () const { return _boundingBox.getXMin(); }
|
||||||
|
inline DbU::Unit Tile::getRightEdge () const { return _boundingBox.getXMax(); }
|
||||||
|
inline DbU::Unit Tile::getYMin () const { return _boundingBox.getYMin(); }
|
||||||
|
inline DbU::Unit Tile::getYMax () const { return _boundingBox.getYMax(); }
|
||||||
|
inline uint32_t Tile::getFlags () const { return _flags; }
|
||||||
|
inline uint32_t Tile::getRank () const { return _rank; }
|
||||||
|
inline Tile* Tile::getParent () const { return _parent; }
|
||||||
|
inline void Tile::incRank () { _rank++; }
|
||||||
|
inline void Tile::syncTime () { _timeStamp=_time; }
|
||||||
|
inline void Tile::setParent ( Tile* parent ) { _parent=parent; }
|
||||||
|
inline void Tile::setEquipotential ( Equipotential* equi ) { _equipotential=equi; }
|
||||||
|
|
||||||
|
inline void Tile::setOccMerged ( bool state )
|
||||||
|
{ if (state) _flags |= OccMerged;
|
||||||
|
else _flags &= ~OccMerged; }
|
||||||
|
|
||||||
|
|
||||||
|
class TileCompare {
|
||||||
|
public:
|
||||||
|
inline bool operator() ( const Tile* lhs, const Tile* rhs ) const
|
||||||
|
{
|
||||||
|
cdebug_log(0,0) << "TileCompare::operator()" << std::endl;
|
||||||
|
return lhs->getId() < rhs->getId();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : "Tramontana::TileIntvTree".
|
||||||
|
|
||||||
|
|
||||||
|
typedef IntervalData<Tile*> TileIntv;
|
||||||
|
typedef IntervalTree<Tile*,TileCompare> TileIntvTree;
|
||||||
|
|
||||||
|
|
||||||
|
} // Tramontana namespace.
|
||||||
|
|
||||||
|
|
||||||
|
INSPECTOR_P_SUPPORT(Tramontana::Tile);
|
||||||
|
INSPECTOR_PR_SUPPORT(Tramontana::TileIntv);
|
||||||
|
INSPECTOR_PR_SUPPORT(Tramontana::TileIntvTree);
|
|
@ -0,0 +1,98 @@
|
||||||
|
// -*- C++ -*-
|
||||||
|
//
|
||||||
|
// This file is part of the Coriolis Software.
|
||||||
|
// Copyright (c) Sorbonne Université 2007-2023, All Rights Reserved
|
||||||
|
//
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
// | C O R I O L I S |
|
||||||
|
// | T r a m o n t a n a - Extractor & LVX |
|
||||||
|
// | |
|
||||||
|
// | Algorithm : Christian MASSON |
|
||||||
|
// | First impl. : Yifei WU |
|
||||||
|
// | Second impl. : Jean-Paul CHAPUT |
|
||||||
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||||
|
// | =============================================================== |
|
||||||
|
// | C++ Header : "./tramontana/TramontanaEngine.h" |
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "hurricane/Name.h"
|
||||||
|
namespace Hurricane {
|
||||||
|
class Layer;
|
||||||
|
class Net;
|
||||||
|
class Cell;
|
||||||
|
class CellViewer;
|
||||||
|
}
|
||||||
|
#include "crlcore/ToolEngine.h"
|
||||||
|
#include "tramontana/Equipotential.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Tramontana {
|
||||||
|
|
||||||
|
using Hurricane::Record;
|
||||||
|
using Hurricane::Name;
|
||||||
|
using Hurricane::Layer;
|
||||||
|
using Hurricane::Net;
|
||||||
|
using Hurricane::Cell;
|
||||||
|
using Hurricane::CellViewer;
|
||||||
|
using CRL::ToolEngine;
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : "Tramontana::TramontanaEngine".
|
||||||
|
|
||||||
|
class TramontanaEngine : public ToolEngine {
|
||||||
|
public:
|
||||||
|
typedef ToolEngine Super;
|
||||||
|
public:
|
||||||
|
static const Name& staticGetName ();
|
||||||
|
static TramontanaEngine* create ( Cell*, uint32_t depth=0 );
|
||||||
|
static TramontanaEngine* get ( const Cell* );
|
||||||
|
public:
|
||||||
|
const Name& getName () const;
|
||||||
|
inline uint32_t getDepth () const;
|
||||||
|
inline const std::set<Equipotential*,DBo::CompareById>
|
||||||
|
getEquipotentials () const;
|
||||||
|
inline void setViewer ( CellViewer* );
|
||||||
|
inline CellViewer* getViewer ();
|
||||||
|
void extract ();
|
||||||
|
void _extract ();
|
||||||
|
void consolidate ();
|
||||||
|
void showEquipotentials () const;
|
||||||
|
void add ( Equipotential* );
|
||||||
|
virtual Record* _getRecord () const;
|
||||||
|
virtual std::string _getString () const;
|
||||||
|
virtual std::string _getTypeName () const;
|
||||||
|
private:
|
||||||
|
// Attributes.
|
||||||
|
static Name _toolName;
|
||||||
|
private:
|
||||||
|
CellViewer* _viewer;
|
||||||
|
uint32_t _depth;
|
||||||
|
std::set<Equipotential*,DBo::CompareById> _equipotentials;
|
||||||
|
protected:
|
||||||
|
// Constructors & Destructors.
|
||||||
|
TramontanaEngine ( Cell*, uint32_t depth );
|
||||||
|
virtual ~TramontanaEngine ();
|
||||||
|
virtual void _postCreate ();
|
||||||
|
virtual void _preDestroy ();
|
||||||
|
private:
|
||||||
|
TramontanaEngine ( const TramontanaEngine& ) = delete;
|
||||||
|
TramontanaEngine& operator= ( const TramontanaEngine& ) = delete;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
inline void TramontanaEngine::setViewer ( CellViewer* viewer ) { _viewer=viewer; }
|
||||||
|
inline CellViewer* TramontanaEngine::getViewer () { return _viewer; }
|
||||||
|
inline uint32_t TramontanaEngine::getDepth () const { return _depth; }
|
||||||
|
inline const std::set<Equipotential*,DBo::CompareById>
|
||||||
|
TramontanaEngine::getEquipotentials () const { return _equipotentials; }
|
||||||
|
|
||||||
|
|
||||||
|
} // Tramontana namespace.
|
||||||
|
|
||||||
|
|
||||||
|
INSPECTOR_P_SUPPORT(Tramontana::TramontanaEngine);
|
|
@ -38,8 +38,8 @@
|
||||||
#find_package(KNIK REQUIRED)
|
#find_package(KNIK REQUIRED)
|
||||||
#find_package(KATABATIC REQUIRED)
|
#find_package(KATABATIC REQUIRED)
|
||||||
#find_package(KITE REQUIRED)
|
#find_package(KITE REQUIRED)
|
||||||
find_package(EQUINOX REQUIRED)
|
#find_package(EQUINOX REQUIRED)
|
||||||
find_package(SOLSTICE REQUIRED)
|
#find_package(SOLSTICE REQUIRED)
|
||||||
#find_package(TUTORIAL REQUIRED) # FIXME: make FindTUTORIAL.cmake
|
#find_package(TUTORIAL REQUIRED) # FIXME: make FindTUTORIAL.cmake
|
||||||
find_package(Doxygen)
|
find_package(Doxygen)
|
||||||
|
|
||||||
|
|
|
@ -58,8 +58,8 @@ using namespace CRL;
|
||||||
#include "katana/GraphicKatanaEngine.h"
|
#include "katana/GraphicKatanaEngine.h"
|
||||||
#include "etesian/GraphicEtesianEngine.h"
|
#include "etesian/GraphicEtesianEngine.h"
|
||||||
#include "katana/GraphicKatanaEngine.h"
|
#include "katana/GraphicKatanaEngine.h"
|
||||||
#include "equinox/GraphicEquinoxEngine.h"
|
//#include "equinox/GraphicEquinoxEngine.h"
|
||||||
#include "solstice/GraphicSolsticeEngine.h"
|
//#include "solstice/GraphicSolsticeEngine.h"
|
||||||
#include "unicorn/UnicornGui.h"
|
#include "unicorn/UnicornGui.h"
|
||||||
using namespace Unicorn;
|
using namespace Unicorn;
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ try:
|
||||||
from coriolis import helpers
|
from coriolis import helpers
|
||||||
helpers.loadUserSettings()
|
helpers.loadUserSettings()
|
||||||
from coriolis import Cfg, Hurricane, Viewer, CRL, Etesian, Anabatic, \
|
from coriolis import Cfg, Hurricane, Viewer, CRL, Etesian, Anabatic, \
|
||||||
Katana, Bora, Tutorial, Unicorn
|
Katana, Tramontana, Bora, Tutorial, Unicorn
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
helpers.io.showPythonTrace( sys.argv[0], e )
|
helpers.io.showPythonTrace( sys.argv[0], e )
|
||||||
sys.exit(2)
|
sys.exit(2)
|
||||||
|
@ -179,8 +179,8 @@ if __name__ == '__main__':
|
||||||
unicorn = Unicorn.UnicornGui.create()
|
unicorn = Unicorn.UnicornGui.create()
|
||||||
unicorn.setApplicationName ('cgt')
|
unicorn.setApplicationName ('cgt')
|
||||||
unicorn.registerTool (Etesian.GraphicEtesianEngine.grab())
|
unicorn.registerTool (Etesian.GraphicEtesianEngine.grab())
|
||||||
#unicorn.registerTool (Kite.GraphicKiteEngine.grab())
|
|
||||||
unicorn.registerTool (Katana.GraphicKatanaEngine.grab())
|
unicorn.registerTool (Katana.GraphicKatanaEngine.grab())
|
||||||
|
unicorn.registerTool (Tramontana.GraphicTramontanaEngine.grab())
|
||||||
unicorn.registerTool (Bora.GraphicBoraEngine.grab())
|
unicorn.registerTool (Bora.GraphicBoraEngine.grab())
|
||||||
unicorn.registerTool (Tutorial.GraphicTutorialEngine.grab())
|
unicorn.registerTool (Tutorial.GraphicTutorialEngine.grab())
|
||||||
#unicorn.setAnonNetSelectable(False)
|
#unicorn.setAnonNetSelectable(False)
|
||||||
|
|
|
@ -0,0 +1,168 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from coriolis.Hurricane import DataBase, Net, \
|
||||||
|
DbU, Point, Box, Pad, Rectilinear
|
||||||
|
from coriolis import Cfg
|
||||||
|
from coriolis.CRL import AllianceFramework, Catalog, Gds
|
||||||
|
from coriolis.helpers import l, u
|
||||||
|
from coriolis.helpers.overlay import CfgCache, UpdateSession
|
||||||
|
|
||||||
|
|
||||||
|
def testRectilinear ( editor ):
|
||||||
|
"""Check Hurricane.Rectilinear class."""
|
||||||
|
with CfgCache(priority=Cfg.Parameter.Priority.UserFile) as cfg:
|
||||||
|
cfg.misc.minTraceLevel = 17000
|
||||||
|
cfg.misc.maxTraceLevel = 18000
|
||||||
|
with UpdateSession():
|
||||||
|
cell = AllianceFramework.get().createCell( 'Rectilinear' )
|
||||||
|
cell.setTerminalNetlist( True )
|
||||||
|
cell.setAbutmentBox( Box( l(-5.0), l(-5.0), l(400.0), l(200.0) ) )
|
||||||
|
#cell.setAbutmentBox( Box( l(-5.0), l(-5.0), l(21.0), l(35.0) ) )
|
||||||
|
if editor:
|
||||||
|
editor.setCell( cell )
|
||||||
|
editor.fit()
|
||||||
|
|
||||||
|
technology = DataBase.getDB().getTechnology()
|
||||||
|
metal1 = technology.getLayer( "METAL1" )
|
||||||
|
metal2 = technology.getLayer( "METAL2" )
|
||||||
|
metal3 = technology.getLayer( "METAL3" )
|
||||||
|
metal4 = technology.getLayer( "METAL4" )
|
||||||
|
poly = technology.getLayer( "POLY" )
|
||||||
|
ptrans = technology.getLayer( "PTRANS" )
|
||||||
|
ntrans = technology.getLayer( "NTRANS" )
|
||||||
|
pdif = technology.getLayer( "PDIF" )
|
||||||
|
ndif = technology.getLayer( "NDIF" )
|
||||||
|
contdifn = technology.getLayer( "CONT_DIF_N" )
|
||||||
|
contdifp = technology.getLayer( "CONT_DIF_P" )
|
||||||
|
nwell = technology.getLayer( "NWELL" )
|
||||||
|
contpoly = technology.getLayer( "CONT_POLY" )
|
||||||
|
ntie = technology.getLayer( "NTIE" )
|
||||||
|
|
||||||
|
with UpdateSession():
|
||||||
|
net = Net.create( cell, 'my_net' )
|
||||||
|
net.setExternal( True )
|
||||||
|
|
||||||
|
points = [ Point( l( 0.0), l( 0.0) )
|
||||||
|
, Point( l( 0.0), l( 10.0) )
|
||||||
|
, Point( l( 20.0), l( 30.0) )
|
||||||
|
, Point( l( 30.0), l( 30.0) )
|
||||||
|
, Point( l( 30.0), l( 20.0) )
|
||||||
|
, Point( l( 10.0), l( 0.0) )
|
||||||
|
, Point( l( 0.0), l( 0.0) ) ]
|
||||||
|
r = Rectilinear.create( net, metal2, points )
|
||||||
|
|
||||||
|
#print( 'Normalized and manhattanized contour:' )
|
||||||
|
#i = 0
|
||||||
|
#for point in p.getMContour():
|
||||||
|
# print( '| %d '%i, point, '[%fum %fum]' % ( u(point.getX()), u(point.getY()) ))
|
||||||
|
# i += 1
|
||||||
|
|
||||||
|
#points = [ Point( l( 0.0), l( 40.0) ) # 0
|
||||||
|
# , Point( l( 30.0), l( 40.0) ) # 1
|
||||||
|
# , Point( l( 30.0), l( 60.0) ) # 2
|
||||||
|
# , Point( l( 50.0), l( 60.0) ) # 3
|
||||||
|
# , Point( l( 50.0), l( 80.0) ) # 4
|
||||||
|
# , Point( l( 90.0), l( 80.0) ) # 5
|
||||||
|
# , Point( l( 90.0), l( 50.0) ) # 6
|
||||||
|
# , Point( l( 60.0), l( 50.0) ) # 7
|
||||||
|
# , Point( l( 60.0), l( 30.0) ) # 8
|
||||||
|
# , Point( l( 70.0), l( 30.0) ) # 9
|
||||||
|
# , Point( l( 70.0), l( 20.0) ) # 10
|
||||||
|
# , Point( l( 90.0), l( 20.0) ) # 11
|
||||||
|
# , Point( l( 90.0), l( 0.0) ) # 12
|
||||||
|
# , Point( l( 20.0), l( 0.0) ) # 13
|
||||||
|
# , Point( l( 20.0), l( 20.0) ) # 14
|
||||||
|
# , Point( l( 0.0), l( 20.0) ) # 15
|
||||||
|
# , Point( l( 0.0), l( 40.0) ) ] # 16
|
||||||
|
# Super-test rectilinear.
|
||||||
|
points = [ Point( l( 0.0), l( 0.0) ) # 0
|
||||||
|
, Point( l( 0.0), l( 20.0) ) # 1
|
||||||
|
, Point( l( 10.0), l( 20.0) ) # 2
|
||||||
|
, Point( l( 10.0), l( 30.0) ) # 3
|
||||||
|
, Point( l( 20.0), l( 30.0) ) # 4
|
||||||
|
, Point( l( 20.0), l( 40.0) ) # 5
|
||||||
|
, Point( l( 40.0), l( 40.0) ) # 6
|
||||||
|
, Point( l( 40.0), l( 80.0) ) # 7
|
||||||
|
, Point( l( 20.0), l( 80.0) ) # 8
|
||||||
|
, Point( l( 20.0), l( 70.0) ) # 9
|
||||||
|
|
||||||
|
, Point( l( 10.0), l( 70.0) ) # 10
|
||||||
|
, Point( l( 10.0), l( 60.0) ) # 11
|
||||||
|
, Point( l( 0.0), l( 60.0) ) # 12
|
||||||
|
, Point( l( 0.0), l(120.0) ) # 13
|
||||||
|
, Point( l( 10.0), l(120.0) ) # 14
|
||||||
|
, Point( l( 10.0), l(110.0) ) # 15
|
||||||
|
, Point( l( 20.0), l(110.0) ) # 16
|
||||||
|
, Point( l( 20.0), l(100.0) ) # 17
|
||||||
|
, Point( l( 40.0), l(100.0) ) # 18
|
||||||
|
, Point( l( 40.0), l(140.0) ) # 19
|
||||||
|
|
||||||
|
, Point( l( 20.0), l(140.0) ) # 20
|
||||||
|
, Point( l( 20.0), l(150.0) ) # 21
|
||||||
|
, Point( l( 10.0), l(150.0) ) # 22
|
||||||
|
, Point( l( 10.0), l(160.0) ) # 23
|
||||||
|
, Point( l( 0.0), l(160.0) ) # 24
|
||||||
|
, Point( l( 0.0), l(180.0) ) # 25
|
||||||
|
, Point( l( 40.0), l(180.0) ) # 26
|
||||||
|
, Point( l( 40.0), l(170.0) ) # 27
|
||||||
|
, Point( l( 50.0), l(170.0) ) # 28
|
||||||
|
, Point( l( 50.0), l(160.0) ) # 29
|
||||||
|
|
||||||
|
, Point( l(150.0), l(160.0) ) # 30
|
||||||
|
, Point( l(150.0), l(150.0) ) # 31
|
||||||
|
, Point( l(130.0), l(150.0) ) # 32
|
||||||
|
, Point( l(130.0), l(140.0) ) # 33
|
||||||
|
, Point( l(120.0), l(140.0) ) # 34
|
||||||
|
, Point( l(120.0), l(130.0) ) # 35
|
||||||
|
, Point( l(110.0), l(130.0) ) # 36
|
||||||
|
, Point( l(110.0), l(110.0) ) # 37
|
||||||
|
, Point( l(120.0), l(110.0) ) # 38
|
||||||
|
, Point( l(120.0), l(100.0) ) # 39
|
||||||
|
|
||||||
|
, Point( l(130.0), l(100.0) ) # 40
|
||||||
|
, Point( l(130.0), l( 90.0) ) # 41
|
||||||
|
, Point( l(150.0), l( 90.0) ) # 42
|
||||||
|
, Point( l(150.0), l( 80.0) ) # 43
|
||||||
|
, Point( l(120.0), l( 80.0) ) # 44
|
||||||
|
, Point( l(120.0), l( 70.0) ) # 45
|
||||||
|
, Point( l(110.0), l( 70.0) ) # 46
|
||||||
|
, Point( l(110.0), l( 50.0) ) # 47
|
||||||
|
, Point( l(120.0), l( 50.0) ) # 48
|
||||||
|
, Point( l(120.0), l( 40.0) ) # 49
|
||||||
|
|
||||||
|
, Point( l(130.0), l( 40.0) ) # 50
|
||||||
|
, Point( l(130.0), l( 30.0) ) # 51
|
||||||
|
, Point( l(150.0), l( 30.0) ) # 52
|
||||||
|
, Point( l(150.0), l( 20.0) ) # 53
|
||||||
|
, Point( l( 50.0), l( 20.0) ) # 54
|
||||||
|
, Point( l( 50.0), l( 10.0) ) # 55
|
||||||
|
, Point( l( 40.0), l( 10.0) ) # 56
|
||||||
|
, Point( l( 40.0), l( 0.0) ) # 57
|
||||||
|
, Point( l( 0.0), l( 0.0) ) ] # 57
|
||||||
|
#points = [ Point( l( 0.0), l( 0.0) ) # 0
|
||||||
|
# , Point( l( 0.0), l( 80.0) ) # 1
|
||||||
|
# , Point( l( 40.0), l( 80.0) ) # 2
|
||||||
|
# , Point( l( 40.0), l( 60.0) ) # 3
|
||||||
|
# , Point( l( 20.0), l( 60.0) ) # 4
|
||||||
|
# , Point( l( 20.0), l( 0.0) ) # 5
|
||||||
|
# , Point( l( 0.0), l( 0.0) ) ] # 6
|
||||||
|
r = Rectilinear.create( net, metal2, points )
|
||||||
|
|
||||||
|
boxes = []
|
||||||
|
r.getAsRectangles( boxes )
|
||||||
|
#print( 'boxes={}'.format( boxes ))
|
||||||
|
for box in boxes:
|
||||||
|
box.translate( l(180.0), l(0.0) )
|
||||||
|
Pad.create( net, metal3, box )
|
||||||
|
|
||||||
|
Gds.save( cell )
|
||||||
|
|
||||||
|
|
||||||
|
def scriptMain ( **kw ):
|
||||||
|
"""The mandatory function to be called by Coriolis CGT/Unicorn."""
|
||||||
|
editor = None
|
||||||
|
if 'editor' in kw and kw['editor']:
|
||||||
|
editor = kw['editor']
|
||||||
|
testRectilinear( editor )
|
||||||
|
return True
|
|
@ -65,6 +65,7 @@ namespace {
|
||||||
cerr << endl << endl;
|
cerr << endl << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rb.remove( Interval( l(3), l(4) ));
|
||||||
rb.write( "finalRbTree.gv" );
|
rb.write( "finalRbTree.gv" );
|
||||||
|
|
||||||
for ( Interval intv : rb.getElements() ) {
|
for ( Interval intv : rb.getElements() ) {
|
||||||
|
@ -100,6 +101,7 @@ namespace {
|
||||||
cerr << endl << endl;
|
cerr << endl << endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
itree.remove( IntvString( "a", l(3), l(4) ));
|
||||||
itree.write( "finalIntervalTree.gv" );
|
itree.write( "finalIntervalTree.gv" );
|
||||||
|
|
||||||
for ( IntervalData<string> intv : itree.getElements() ) {
|
for ( IntervalData<string> intv : itree.getElements() ) {
|
||||||
|
|
Loading…
Reference in New Issue