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:
Jean-Paul Chaput 2023-06-25 18:11:18 +02:00
commit 014ec72652
69 changed files with 5715 additions and 228 deletions

View File

@ -20,6 +20,7 @@
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}/Debug.Shared
buildDir=${commonRoot}/build
installDir=${commonRoot}/install

View File

@ -24,8 +24,9 @@ projects = [
#, "knik"
#, "katabatic"
#, "kite"
, "equinox"
, "solstice"
#, "equinox"
#, "solstice"
, "tramontana"
, "oroshi"
, "bora"
, "karakaze"

View File

@ -9,6 +9,7 @@
FindQwt.cmake
FindSphinx.cmake
FindPelican.cmake
FindCOLOQUINTE.cmake
GetGitRevisionDescription.cmake
GetGitRevisionDescription.cmake.in
)

View File

@ -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)

View File

@ -191,8 +191,9 @@ namespace CRL {
bool ToolEngine::_inDestroyAll = false;
ToolEngine::ToolEngine ( Cell* cell )
ToolEngine::ToolEngine ( Cell* cell, bool verbose )
: Super()
, _verbose (verbose)
, _cell (cell)
, _placementModificationFlag(0)
, _routingModificationFlag (0)
@ -219,11 +220,13 @@ namespace CRL {
put( enginesRelation );
cmess1 << " o Creating ToolEngine<" << getName() << "> for Cell <"
<< _cell->getName() << ">" << endl;
cmess1 << Dots::asString( " - Initial memory"
, Timer::getStringMemory(Timer::getMemorySize()) ) << endl;
if (_verbose) {
cmess1 << " o Creating ToolEngine<" << getName() << "> for Cell <"
<< _cell->getName() << ">" << endl;
cmess1 << Dots::asString( " - Initial memory"
, Timer::getStringMemory(Timer::getMemorySize()) ) << endl;
}
}

View File

@ -81,13 +81,14 @@ namespace CRL {
protected:
Cell* _cell;
private:
bool _verbose;
unsigned int _placementModificationFlag;
unsigned int _routingModificationFlag;
bool _inRelationDestroy;
Timer _timer;
uint32_t _passNumber;
protected:
ToolEngine ( Cell* cell );
ToolEngine ( Cell* cell, bool verbose=true );
virtual void _postCreate ();
virtual void _preDestroy ();
protected:

View File

@ -64,7 +64,7 @@ class PnR ( FlowTask ):
else:
print( 'PnR.doTask() run in interactive CGT mode.' )
PnR.textMode = False
from .. import Etesian, Anabatic, Katana, Bora, Tutorial, Viewer, Unicorn
from .. import Etesian, Anabatic, Katana, Bora, Tramontana, Tutorial, Viewer, Unicorn
ShellEnv().export()
if self.script and not callable(self.script):
@ -80,8 +80,8 @@ class PnR ( FlowTask ):
unicorn = Unicorn.UnicornGui.create()
unicorn.setApplicationName ( 'cgt')
unicorn.registerTool ( Etesian.GraphicEtesianEngine.grab() )
#unicorn.registerTool ( Kite.GraphicKiteEngine.grab() )
unicorn.registerTool ( Katana.GraphicKatanaEngine.grab() )
unicorn.registerTool ( Tramontana.GraphicTramontanaEngine.grab() )
unicorn.registerTool ( Bora.GraphicBoraEngine.grab() )
unicorn.registerTool ( Tutorial.GraphicTutorialEngine.grab() )
#unicorn.setAnonNetSelectable(False)

View File

@ -190,6 +190,7 @@ def setupSky130_c4m ( checkToolkit=None, pdkMasterTop=None ):
cfg.misc.logMode = True
cfg.misc.verboseLevel1 = False
cfg.misc.verboseLevel2 = False
cfg.viewer.pixelThreshold = 5
cfg.etesian.graphics = 2
cfg.anabatic.topRoutingLayer = 'm4'
cfg.katana.eventsLimit = 4000000

View File

@ -1204,8 +1204,8 @@ namespace Etesian {
Instance* instance = static_cast<Instance*>(occurrence.getEntity());
string instanceName = occurrence.getCompactString();
// Remove the enclosing brackets...
instanceName.erase( 0, 1 );
instanceName.erase( instanceName.size()-1 );
//instanceName.erase( 0, 1 );
//instanceName.erase( instanceName.size()-1 );
auto iid = _instsToIds.find( instance );
if (iid == _instsToIds.end() ) {

View File

@ -36,7 +36,7 @@ namespace Hurricane {
#ifdef HAVE_CXA_DEMANGLE
string demangle ( const char* symbol )
{
{
int status;
size_t length = 4096;
char demangled[length];
@ -49,13 +49,25 @@ string demangle ( const char* symbol )
#else
string demangle ( const char* symbol )
{
return symbol;
}
{ return symbol; }
#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.

View File

@ -111,21 +111,21 @@ bool Interval::intersect(const Interval& interval, bool strict) const
if (isEmpty() or interval.isEmpty()) 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
// *****************************************************************
{
if (_vMax < interval._vMin) return true;
return not strict and (_vMax == interval._vMin);
if (_vMax == interval._vMin) return not strict;
return (_vMax < interval._vMin);
}
bool Interval::superior(const Interval& interval, bool strict) const
// *****************************************************************
{
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

View File

@ -772,15 +772,23 @@ void Net::_preDestroy()
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 bs = Inherit::_getString();
string ds = "\"" + getString(_name) + "\" ";
ds += ((isDeepNet() ) ? "d" : "-");
ds += ((_isExternal ) ? "e" : "-");
ds += ((_isGlobal ) ? "g" : "-");
ds += ((_isAutomatic) ? "a" : "-");
ds += _getFlagsAsString();
ds += " ";
ds += getString(_type ) + " ";
ds += getString(_direction);

View File

@ -96,16 +96,27 @@ bool Occurrence::operator!=(const Occurrence& occurrence) const
bool Occurrence::operator<(const Occurrence& occurrence) const
// ********************************************************
{
if (not _entity and not occurrence._entity) return false;
if (not _entity) return true;
if (not occurrence._entity) return false;
cdebug_log(0,0) << "Occurrence::operator<()" << endl;
cdebug_log(0,0) << "| lhs=" << *this << endl;
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 (_entity->getId() > occurrence._entity->getId()) return false;
// if (not _sharedPath) return true;
// 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 _sharedPath) return true;
if (not occurrence._sharedPath) return false;
// if (not _entity and not occurrence._entity) return false;
// if (not _entity) return true;
// 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();
@ -274,11 +285,12 @@ string Occurrence::_getString() const
string Occurrence::getCompactString() const
// ****************************************
{
string s = "<";
string s;
if (_entity) {
s += getString(getOwnerCell()->getName());
s += ":";
if (_sharedPath) s += getString(_sharedPath->getName()) + ":";
if (_sharedPath) s += getString(_sharedPath->getName());
s += ":";
Instance* instance = dynamic_cast<Instance*>(_entity);
if (instance) {
s += "I."+getString(instance->getName());
@ -291,7 +303,6 @@ string Occurrence::getCompactString() const
}
}
}
s += ">";
return s;
}

View File

@ -40,6 +40,284 @@
#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 {
@ -50,6 +328,7 @@ namespace Hurricane {
: Super (net)
, _layer (layer)
, _points(points)
, _flags (IsRectilinear)
{ }
@ -58,9 +337,21 @@ namespace Hurricane {
if (not layer)
throw Error( "Rectilinear::create(): Can't create, NULL layer" );
if (points.size() > 1000)
throw Error( "Rectilinear::create(): Rectlinear polygons must not exceed 1000 vertexes." );
if (points.size() < 4)
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 );
for ( size_t i=0 ; i<points.size() ; ++i ) {
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 dy = std::abs( points[i].getY() - points[j].getY() );
if ( (dx != 0) and (dy != 0) and (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 ((dx != 0) and (dy != 0)) {
isRect = false;
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)
cerr << Warning( "Rectilinear::create(): In Cell \"%s\", Net \"%s\",\n"
@ -91,7 +385,7 @@ namespace Hurricane {
}
Rectilinear* rectilinear = new Rectilinear ( net, layer, points );
if (not isRect) rectilinear->_flags &= ~IsRectilinear;
rectilinear->_postCreate();
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
{
Inherit::_toJson( writer );

View File

@ -146,6 +146,9 @@ namespace Hurricane {
}
string& split ( std::string& );
} // End of Hurricane namespace.

View File

@ -21,6 +21,7 @@
#ifndef HURRICANE_COMPONENT_H
#define HURRICANE_COMPONENT_H
#include <set>
#include "hurricane/Points.h"
#include "hurricane/Go.h"
#include "hurricane/Components.h"
@ -170,6 +171,9 @@ namespace Hurricane {
};
typedef std::set<Component*,DBo::CompareById> ComponentSet;
} // Hurricane namespace.

View File

@ -1,6 +1,6 @@
// -*- 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.
//
@ -29,9 +29,7 @@
// +-----------------------------------------------------------------+
#ifndef HURRICANE_INTERVAL_H
#define HURRICANE_INTERVAL_H
#pragma once
#include "hurricane/DbU.h"
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;
};
class CompareByMinMax {
public:
inline bool operator() ( const Interval& rhs, const Interval& lhs ) const;
inline bool operator() ( const Interval* rhs, const Interval* lhs ) const;
};
public:
Interval ( bool makeEmpty=true );
Interval ( const DbU::Unit& );
@ -124,6 +127,20 @@ namespace Hurricane {
{ 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.
@ -136,7 +153,5 @@ inline void jsonWrite ( JsonWriter* w, const std::string& key, const Hurricane:
w->endArray();
}
INSPECTOR_PR_SUPPORT(Hurricane::Interval);
#endif // HURRICANE_INTERVAL_H

View File

@ -1,6 +1,6 @@
// -*- 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.
//
@ -34,9 +34,7 @@
// Third edition, MIT press, 2011, p. 348.
#ifndef HURRICANE_INTERVAL_TREE_H
#define HURRICANE_INTERVAL_TREE_H
#pragma once
#include "hurricane/Interval.h"
#include "hurricane/RbTree.h"
@ -57,6 +55,7 @@ namespace Hurricane {
inline Data& getData () const;
inline DbU::Unit getChildsVMax () const;
inline DbU::Unit updateChildsVMax ( DbU::Unit lvmax, DbU::Unit rvmax );
inline bool operator== ( const IntervalData& ) const;
string _getString () const;
Record* _getRecord () const;
private:
@ -64,7 +63,7 @@ namespace Hurricane {
Data data_;
};
template< typename Data >
inline IntervalData<Data>::IntervalData ()
: Interval(1,-1)
@ -93,7 +92,17 @@ namespace Hurricane {
template< typename Data >
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 >
@ -117,14 +126,35 @@ namespace Hurricane {
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".
template< typename Data >
class IntervalTree : public RbTree< IntervalData<Data>, Interval::CompareByMin > {
template< typename Data, typename DataCompare=std::less<Data> >
class IntervalTree : public RbTree< IntervalData<Data>, IntervalDataCompare<Data,DataCompare> > {
public:
typedef RbTree< IntervalData<Data>, Interval::CompareByMin > Super;
typedef RbTree< IntervalData<Data>, IntervalDataCompare<Data,DataCompare> > Super;
public:
class overlap_iterator : public Super::iterator {
public:
@ -171,31 +201,39 @@ namespace Hurricane {
size_t getThickness () const;
overlap_iterator beginOverlaps ( const Interval& ) const;
inline OverlapElements getOverlaps ( const Interval& ) const;
void checkVMax () const;
void checkVMax ( typename Super::Node* node ) const;
private:
inline void updateChildsVMax ( typename Super::Node* );
};
template< typename Data >
IntervalTree<Data>::overlap_iterator::overlap_iterator ( const typename Super::Node* node, const Interval& overlap )
template< typename Data, typename DataCompare >
IntervalTree<Data,DataCompare>::overlap_iterator::overlap_iterator ( const typename Super::Node* node, const Interval& overlap )
: Super::iterator(node)
, 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++();
if (not this->isValid()) break;
cdebug_log(0,0) << "IntervalTree::overlap_iterator::operator++() "
<< ::getString(this->getNode()) << std::endl;
cdebug_log(0,0) << " ==> " << ::getString(this->getNode()->getValue()) << std::endl;
if (this->getNode()->getValue().intersect(overlap_,true)) break;
cdebug_log(0,0) << "NO intersections" << endl;
if (overlap_.inferior(this->getNode()->getValue(),true)) {
cdebug_log(0,0) << "Node is inferior, stop here." << endl;
if (this->getNode()->getValue().intersect(overlap_,false)) break;
cdebug_log(0,0) << " NO intersections" << endl;
if (overlap_.inferior(this->getNode()->getValue(),false)) {
cdebug_log(0,0) << " Node is inferior, stop here." << endl;
this->setNode( NULL );
break;
}
@ -208,44 +246,45 @@ namespace Hurricane {
// Class : "Hurricane::IntervalTree::OverlapOverlapElements" (implementation)
template< typename Data >
inline IntervalTree<Data>::OverlapElements::Locator::Locator ( const Locator &locator )
template< typename Data, typename DataCompare >
inline IntervalTree<Data,DataCompare>::OverlapElements::Locator::Locator ( const Locator &locator )
: Hurricane::Locator< IntervalData<Data> >()
, iterator_(locator.iterator_)
{ }
template< typename Data >
IntervalTree<Data>::OverlapElements::Locator::Locator ( const IntervalTree<Data>& tree, const Interval& span )
template< typename Data, typename DataCompare >
IntervalTree<Data,DataCompare>::OverlapElements::Locator::Locator ( const IntervalTree<Data,DataCompare>& tree, const Interval& span )
: Hurricane::Locator< IntervalData<Data> >()
, iterator_(tree.beginOverlaps(span))
{ }
template< typename Data >
typename IntervalTree<Data>::OverlapElements::Locator* IntervalTree<Data>::OverlapElements::Locator::getClone () const
template< typename Data, typename DataCompare >
typename IntervalTree<Data,DataCompare>::OverlapElements::Locator*
IntervalTree<Data,DataCompare>::OverlapElements::Locator::getClone () const
{ return new Locator(*this); }
template< typename Data >
IntervalData<Data> IntervalTree<Data>::OverlapElements::Locator::getElement () const
template< typename Data, typename DataCompare >
IntervalData<Data> IntervalTree<Data,DataCompare>::OverlapElements::Locator::getElement () const
{ return (*iterator_); }
template< typename Data >
bool IntervalTree<Data>::OverlapElements::Locator::isValid () const
template< typename Data, typename DataCompare >
bool IntervalTree<Data,DataCompare>::OverlapElements::Locator::isValid () const
{ return iterator_.isValid(); }
template< typename Data >
void IntervalTree<Data>::OverlapElements::Locator::progress ()
template< typename Data, typename DataCompare >
void IntervalTree<Data,DataCompare>::OverlapElements::Locator::progress ()
{
if (isValid()) ++iterator_;
}
template< typename Data >
std::string IntervalTree<Data>::OverlapElements::Locator::_getString () const
template< typename Data, typename DataCompare >
std::string IntervalTree<Data,DataCompare>::OverlapElements::Locator::_getString () const
{
std::string s = "<" + _TName("OverlapElements::Locator")
+ ">";
@ -253,34 +292,34 @@ namespace Hurricane {
}
template< typename Data >
inline IntervalTree<Data>::OverlapElements::OverlapElements ( const IntervalTree& tree, const Interval& span )
template< typename Data, typename DataCompare >
inline IntervalTree<Data,DataCompare>::OverlapElements::OverlapElements ( const IntervalTree& tree, const Interval& span )
: Collection< IntervalData<Data> >()
, tree_(tree)
, span_(span)
{ }
template< typename Data >
inline IntervalTree<Data>::OverlapElements::OverlapElements ( const OverlapElements& elements )
template< typename Data, typename DataCompare >
inline IntervalTree<Data,DataCompare>::OverlapElements::OverlapElements ( const OverlapElements& elements )
: Collection< IntervalData<Data> >()
, tree_(elements.tree_)
, span_(elements.span_)
{ }
template< typename Data >
Collection< IntervalData<Data> >* IntervalTree<Data>::OverlapElements::getClone () const
template< typename Data, typename DataCompare >
Collection< IntervalData<Data> >* IntervalTree<Data,DataCompare>::OverlapElements::getClone () const
{ return new OverlapElements(*this); }
template< typename Data >
typename IntervalTree<Data>::OverlapElements::Locator* IntervalTree<Data>::OverlapElements::getLocator () const
template< typename Data, typename DataCompare >
typename IntervalTree<Data,DataCompare>::OverlapElements::Locator* IntervalTree<Data,DataCompare>::OverlapElements::getLocator () const
{ return new Locator( tree_, span_ ); }
template< typename Data >
std::string IntervalTree<Data>::OverlapElements::_getString () const
template< typename Data, typename DataCompare >
std::string IntervalTree<Data,DataCompare>::OverlapElements::_getString () const
{
std::string s = "<" + _TName("OverlapElements") + " "
+ getString(tree_)
@ -293,39 +332,45 @@ namespace Hurricane {
// Class : "Hurricane::IntervalTree" (implementation).
template< typename Data >
inline void IntervalTree<Data>::updateChildsVMax ( typename Super::Node* node )
template< typename Data, typename DataCompare >
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 rchildVMax = (node->getRight()) ? node->getRight()->getValue().getChildsVMax() : node->getValue().getVMax();
const_cast< IntervalData<Data>& >( node->getValue() ).updateChildsVMax( lchildVMax, rchildVMax );
cdebug_tabw(0,-1);
}
template< typename Data >
void IntervalTree<Data>::postRotateLeft ( typename Super::Node* node )
template< typename Data, typename DataCompare >
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 );
if (node->getParent()) updateChildsVMax( node->getParent() );
}
template< typename Data >
void IntervalTree<Data>::postRotateRight ( typename Super::Node* node )
template< typename Data, typename DataCompare >
void IntervalTree<Data,DataCompare>::postInsert ( typename Super::Node* node )
{
updateChildsVMax( node );
if (node->getParent()) updateChildsVMax( node->getParent() );
}
template< typename Data >
void IntervalTree<Data>::postInsert ( typename Super::Node* node )
{
cdebug_log(0,1) << "IntervalTree::postInsert() " << node << std::endl;
cdebug_log(0,1) << "IntervalTree::postInsert() "
<< ((node) ? ::getString(node->getValue()) : "node=NULL") << std::endl;
while ( node ) {
cdebug_log(0,0) << "| " << node << std::endl;
cdebug_log(0,0) << "| " << node->getValue() << std::endl;
updateChildsVMax( node );
node = node->getParent();
@ -335,26 +380,38 @@ namespace Hurricane {
}
template< typename Data >
void IntervalTree<Data>::postRemove ( typename Super::Node* node )
template< typename Data, typename DataCompare >
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();
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();
else child = parent->getLeft ();
DbU::Unit childVMax = (child) ? child->getValue().getChildsVMax() : parent->getValue().getVMax();
const_cast< IntervalData<Data>& >( parent->getValue() ).updateChildsVMax( childVMax, childVMax );
const_cast< IntervalData<Data>& >( parent->getValue() ).updateChildsVMax( childsVMax, childsVMax );
postInsert( parent->getParent() );
}
cdebug_tabw(0,-1);
}
template< typename Data >
size_t IntervalTree<Data>::getThickness () const
template< typename Data, typename DataCompare >
size_t IntervalTree<Data,DataCompare>::getThickness () const
{
cdebug_log(0,0) << "IntervalTree::getThickness() " << std::endl;
@ -382,36 +439,70 @@ namespace Hurricane {
}
template< typename Data >
typename IntervalTree<Data>::overlap_iterator IntervalTree<Data>::beginOverlaps ( const Interval& overlap ) const
template< typename Data, typename DataCompare >
typename IntervalTree<Data,DataCompare>::overlap_iterator
IntervalTree<Data,DataCompare>::beginOverlaps ( const Interval& overlap ) const
{
cdebug_log(0,0) << "IntervalTree::beginOverlaps() " << overlap << std::endl;
const typename Super::Node* current = this->getRoot();
const typename Super::Node* leftMost = NULL;
const typename Super::Node* leftMost = nullptr;
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()
and (overlap.getVMin() < current->getLeft()->getValue().getChildsVMax()) )
current = current->getLeft();
else
current = current->getRight();
and (overlap.getVMin() < current->getLeft()->getValue().getChildsVMax()) ) {
current = current->getLeft();
leftMost = nullptr;
} else {
if (not leftMost)
current = current->getRight();
else
current = nullptr;
}
}
return overlap_iterator( leftMost, overlap );
}
template< typename Data >
typename IntervalTree<Data>::OverlapElements IntervalTree<Data>::getOverlaps ( const Interval& overlap ) const
template< typename Data, typename DataCompare >
typename IntervalTree<Data,DataCompare>::OverlapElements
IntervalTree<Data,DataCompare>::getOverlaps ( const Interval& overlap ) const
{
cdebug_log(0,0) << "IntervalTree::getOverlaps() " << overlap << std::endl;
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.
#endif // HURRICANE_INTERVAL_TREE_H

View File

@ -17,9 +17,7 @@
// not, see <http://www.gnu.org/licenses/>.
// ****************************************************************************************************
#ifndef HURRICANE_NET
#define HURRICANE_NET
#pragma once
#include <functional>
#include "hurricane/Entity.h"
#include "hurricane/Nets.h"
@ -253,6 +251,7 @@ class Net : public Entity {
public: virtual void _toJsonSignature(JsonWriter*) const;
public: virtual void _toJsonCollections(JsonWriter*) const;
public: virtual string _getTypeName() const {return _TName("Net");};
public: string _getFlagsAsString() const;
public: virtual string _getString() const;
public: virtual Record* _getRecord() const;
public: NetMainName& _getMainName() { return _mainName; }
@ -445,9 +444,10 @@ namespace Hurricane {
// Because sometimes it didn't happens (?).
const SlotTemplate<Net*> dummyNetSlot ( string("dummyNetSlot"), NULL );
}
#endif // HURRICANE_NET
typedef std::set<Net*,DBo::CompareById> NetSet;
}
// ****************************************************************************************************

View File

@ -121,6 +121,10 @@ class JsonOccurrence : public JsonObject {
public: virtual void toData(JsonStack&);
};
typedef std::set<Occurrence> OccurrenceSet;
} // End of Hurricane namespace.

View File

@ -34,9 +34,7 @@
// Third edition, MIT press, 2011, p. 308.
#ifndef HURRICANE_RBTREE_H
#define HURRICANE_RBTREE_H
#pragma once
#include <functional>
#include <fstream>
#include <sstream>
@ -90,7 +88,7 @@ namespace Hurricane {
inline void copyColor ( Node* );
void updateEdge ( Node* oldChild, Node* newChild );
void clear ();
inline void copy ( const Node* );
inline void swap ( Node* );
virtual std::string _getString () const;
virtual Record* _getRecord () const;
private:
@ -284,8 +282,15 @@ namespace Hurricane {
template< typename Data, typename Compare >
inline void RbTree<Data,Compare>::Node::copy ( const Node* other )
{ value_ = other->value_; }
inline void RbTree<Data,Compare>::Node::swap ( Node* other )
{
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 >
@ -515,7 +520,7 @@ namespace Hurricane {
template< typename Data, typename Compare >
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();
@ -534,7 +539,7 @@ namespace Hurricane {
template< typename Data, typename Compare >
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();
@ -557,15 +562,21 @@ namespace Hurricane {
Node* current = root_;
while ( current ) {
cdebug_log(0,0) << "| " << current << std::endl;
cdebug_log(0,0) << "| " << current->getValue() << std::endl;
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);
}
if (compare_(value,current->getValue())) current = current->getLeft ();
else current = current->getRight();
if (compare_(value,current->getValue())) {
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;
@ -630,21 +641,22 @@ namespace Hurricane {
Node* rmNode = const_cast<Node*>( find( value ).getNode() );
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;
}
Node* rmLeaf = nullptr;
if (rmNode->getLeft() and rmNode->getRight()) {
Node* rmLeaf = rmNode->getLeft();
Node* rmMax = rmLeaf->getMax();
rmLeaf = rmNode->getLeft();
Node* rmMax = rmLeaf->getMax();
if (rmMax) rmLeaf = rmMax;
rmNode->copy( rmLeaf );
rmNode = rmLeaf;
rmNode->swap( rmLeaf );
std::swap( rmNode, rmLeaf );
}
postRemove ( rmNode );
removeRepair( rmNode, 0 );
postRemove ( rmNode );
Node* parent = rmNode->getParent();
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;
--count_;
cdebug_tabw(0,-1);
@ -671,8 +684,13 @@ namespace Hurricane {
template< typename Data, typename Compare >
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;
if (not rmNode) {
cdebug_tabw(0,-1);
return ;
}
if (rmNode->isBlack()) {
Node* parent = rmNode->getParent();
@ -979,6 +997,7 @@ namespace Hurricane {
void RbTreeToDot<Data,Compare,RbTree>::write ( std::ostream& o ) const
{
o << "digraph RbTree {\n";
o << " ratio=\"1.0\";\n";
toDot( o, tree_->getRoot() );
o << "}";
}
@ -989,8 +1008,9 @@ namespace Hurricane {
{
if (not node) return;
string svalue = ::getString( node->getValue() );
o << " id_" << getId(node) << " "
<< "[label=\"id:" << getId(node) << "\\n" << ::getString(node->getValue())
<< "[label=\"id:" << getId(node) << "\\n" << split( svalue )
<< "\""
<< ",color=" << (node->isRed() ? "red" : "black")
<< ",fontcolor=" << (node->isRed() ? "red" : "black")
@ -1031,6 +1051,3 @@ namespace Hurricane {
} // Hurricane namespace.
#endif // HURRICANE_RBTREE_H

View File

@ -1,6 +1,6 @@
// -*- 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.
//
@ -28,10 +28,7 @@
// | C++ Header : "./hurricane/Rectilinear.h" |
// +-----------------------------------------------------------------+
#ifndef HURRICANE_RECTILINEAR_H
#define HURRICANE_RECTILINEAR_H
#pragma once
#include "hurricane/Component.h"
@ -46,11 +43,13 @@ namespace Hurricane {
class Rectilinear : public Component {
public:
typedef Component Super;
static const uint32_t IsRectilinear = (1<<0);
public:
static Rectilinear* create ( Net*, const Layer*, const vector<Point>& );
// Accessors.
virtual bool isNonRectangle () const;
inline bool isRectilinear () const;
virtual DbU::Unit getX () const;
virtual DbU::Unit getY () const;
virtual Box getBoundingBox () const;
@ -59,6 +58,7 @@ namespace Hurricane {
virtual Point getPoint ( size_t i ) const;
virtual const Layer* getLayer () const;
inline Points getContour () const;
bool getAsRectangles ( std::vector<Box>& ) const;
inline const vector<Point>& getPoints () const;
// Mutators.
void setLayer ( const Layer* );
@ -75,11 +75,13 @@ namespace Hurricane {
private:
const Layer* _layer;
vector<Point> _points;
uint32_t _flags;
};
inline Points Rectilinear::getContour () const { return new VectorCollection<Point>(_points); }
inline const vector<Point>& Rectilinear::getPoints () const { return _points; }
inline bool Rectilinear::isRectilinear () const { return _flags & IsRectilinear; }
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);
#endif // HURRICANE_RECTILINEAR_H

View File

@ -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" {
@ -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.
PyMethodDef PyRectilinear_Methods[] =
{ { "create" , (PyCFunction)PyRectilinear_create , METH_VARARGS|METH_STATIC
, "Create a new Rectilinear polygon." }
, { "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." }
, { "getY" , (PyCFunction)PyRectilinear_getY , METH_NOARGS , "Return the Rectilinear Y value." }
, { "getBoundingBox", (PyCFunction)PyRectilinear_getBoundingBox, METH_NOARGS , "Return 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." }
, { "destroy" , (PyCFunction)PyRectilinear_destroy , METH_NOARGS
, "Destroy associated hurricane object, the python object remains." }
{ { "create" , (PyCFunction)PyRectilinear_create , METH_VARARGS|METH_STATIC
, "Create a new Rectilinear polygon." }
, { "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." }
, { "getY" , (PyCFunction)PyRectilinear_getY , METH_NOARGS , "Return the Rectilinear Y value." }
, { "getBoundingBox" , (PyCFunction)PyRectilinear_getBoundingBox , METH_NOARGS , "Return 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." }
, { "getAsRectangles", (PyCFunction)PyRectilinear_getAsRectangles, METH_VARARGS, "Return the rectangle coverage." }
, { "destroy" , (PyCFunction)PyRectilinear_destroy , METH_NOARGS
, "Destroy associated hurricane object, the python object remains." }
, {NULL, NULL, 0, NULL} /* sentinel */
};

View File

@ -1625,31 +1625,31 @@ extern "C" {
catch ( const Warning& w ) { \
std::string message = getString(w); \
PyErr_Warn ( HurricaneWarning, const_cast<char*>(message.c_str()) ); \
std::cerr << message << std::endl; \
std::cerr << message << std::endl; \
} \
catch ( const Error& e ) { \
std::string message = getString(e); \
if (not e.where().empty()) message += "\n" + e.where(); \
PyErr_SetString ( HurricaneError, message.c_str() ); \
std::cerr << message << std::endl; \
std::cerr << message << std::endl; \
return NULL; \
} \
catch ( const Bug& e ) { \
std::string message = getString(e); \
PyErr_SetString ( HurricaneError, message.c_str() ); \
std::cerr << message << std::endl; \
std::cerr << message << std::endl; \
return NULL; \
} \
catch ( const Exception& e ) { \
std::string message = "Unknown Hurricane::Exception"; \
PyErr_SetString ( HurricaneError, message.c_str() ); \
std::cerr << message << std::endl; \
std::cerr << message << std::endl; \
return NULL; \
} \
catch ( const std::exception& e ) { \
std::string message = std::string(e.what()); \
PyErr_SetString ( HurricaneError, message.c_str() ); \
std::cerr << message << std::endl; \
std::cerr << message << std::endl; \
return NULL; \
} \
catch ( ... ) { \
@ -1657,7 +1657,7 @@ extern "C" {
"Unmanaged exception, neither a Hurricane::Error nor" \
" a std::exception."; \
PyErr_SetString ( HurricaneError, message.c_str() ); \
std::cerr << message << std::endl; \
std::cerr << message << std::endl; \
return NULL; \
} \

View File

@ -157,8 +157,9 @@ namespace Hurricane {
//int scale = 80 * Cfg::getParamEnumerate("viewer.printer.mode")->asInt();
int scale = (Graphics::isHighDpi()) ? 4 : 2;
_drawingWidth = _cellWidget->width () * scale;
_drawingHeight = _cellWidget->height() * scale;
_drawingWidth = _screenCellWidget->geometry().width () * scale;
_drawingHeight = _screenCellWidget->geometry().height() * scale;
_cellWidget->resize( _drawingWidth, _drawingHeight );
_image = new QImage( _drawingWidth
, _drawingHeight + ((_flags&ShowScale) ? 60 : 0)
@ -188,7 +189,7 @@ namespace Hurricane {
setFitOnAbutmentBox( true );
_cellWidget->fitToContents();
} else {
//_cellWidget->reframe( _screenCellWidget->getVisibleArea() );
_cellWidget->reframe( _screenCellWidget->getVisibleArea() );
}
cerr << " After resize CellWidget: " << _cellWidget->geometry().width() << "x" << _cellWidget->geometry().height() << endl;

View File

@ -584,7 +584,7 @@ namespace Hurricane {
void CellViewer::refreshTitle ()
{
QString cellName = "None";
QString cellName = "empty";
if ( getCell() )
cellName = getString(getCell()->getName()).c_str();

View File

@ -2683,7 +2683,86 @@ namespace Hurricane {
} else
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 ( _state->showSelection() ) _redrawManager.refresh ();
emit selectionChanged(_selectors);
emit selectionChanged(_selectors);
}
}
@ -2782,7 +2861,47 @@ namespace Hurricane {
}
_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 ();
_unselectAll ();
if ( --_delaySelectionChanged == 0 ) emit selectionChanged(_selectors);
if ( --_delaySelectionChanged == 0 )
emit selectionChanged(_selectors);
}

View File

@ -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".

View File

@ -63,7 +63,7 @@ namespace Hurricane {
int SimpleNetInformations::getColumnCount ()
{ return 3; }
{ return 6; }
QVariant SimpleNetInformations::getColumnName ( int column )
@ -71,7 +71,10 @@ namespace Hurricane {
switch ( column ) {
case 0: return QVariant(QObject::tr("Net"));
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"));
}
@ -84,11 +87,15 @@ namespace Hurricane {
case 1: return (unsigned int)_plugsCount;
case 2:
if (_net->isGlobal()) {
if (not _rpsCount) return "N/A (global)";
string s = getString(_rpsCount) + " (global)";
if (not _rpsCount) return "N/A";
string s = getString(_rpsCount);
return s.c_str();
}
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"));
}

View File

@ -70,7 +70,7 @@ namespace Hurricane {
QHeaderView* horizontalHeader = _view->horizontalHeader();
horizontalHeader->setDefaultAlignment ( Qt::AlignHCenter );
horizontalHeader->setMinimumSectionSize( (Graphics::isHighDpi()) ? 300 : 150 );
horizontalHeader->setMinimumSectionSize( (Graphics::isHighDpi()) ? 150 : 75 );
horizontalHeader->setStretchLastSection( true );
QHeaderView* verticalHeader = _view->verticalHeader();
@ -151,24 +151,18 @@ namespace Hurricane {
_forceReselect = false;
}
SelectedNetSet::iterator remove;
SelectedNetSet::iterator isel = _selecteds.begin ();
SelectedNetSet::iterator isel = _selecteds.begin ();
while ( isel != _selecteds.end() ) {
switch ( isel->getAccesses() ) {
case 1: break;
case 64:
emit netSelected ( Occurrence(isel->getNet()) );
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;
SelectedNetSet::iterator remove = isel++;
if ( remove->getAccesses() == 0 ) {
emit netUnselected ( Occurrence(remove->getNet()) );
_selecteds.erase ( remove );
}
}
isel = _selecteds.begin ();
while ( isel != _selecteds.end() ) {
if ( isel->getAccesses() == 64 )
emit netSelected ( Occurrence(isel->getNet()) );
++isel;
}

View File

@ -219,6 +219,7 @@ extern "C" {
}
cw->setApplicationName ( name );
cw->refreshTitle ();
HCATCH
Py_RETURN_NONE;

View File

@ -91,8 +91,8 @@ namespace Hurricane {
{
if (not _cellWidget) return;
if (not isCumulative()) clear ();
beginResetModel();
if (not isCumulative()) _selection.clear ();
for ( Selector* selector : selection ) {
if (not selector->isInModel(_cellWidget)) {

View File

@ -87,6 +87,7 @@ namespace Hurricane {
CellViewer ( QWidget* parent=NULL );
virtual ~CellViewer ();
inline bool isToolInterrupted () const;
void refreshTitle ();
QMenu* createDebugMenu ();
bool hasMenu ( const QString& path ) const;
bool hasMenuAction ( const QString& path ) const;
@ -166,7 +167,6 @@ namespace Hurricane {
void cellPostModificated ();
protected:
void createMenus ();
void refreshTitle ();
void refreshHistory ();
void rebuildHistory ();
private:

View File

@ -265,10 +265,16 @@ namespace Hurricane {
inline DrawingPlanes& getDrawingPlanes ();
// void select ( const Net* );
void select ( Occurrence );
void select ( Occurrences );
void selectSet ( const OccurrenceSet& );
void selectSet ( const ComponentSet& );
bool isSelected ( Occurrence );
void selectOccurrencesUnder ( Box selectArea );
// void unselect ( const Net* );
void unselect ( Occurrence );
void unselect ( Occurrences );
void unselectSet ( const ComponentSet& );
void unselectSet ( const OccurrenceSet& );
void unselectAll ();
void toggleSelection ( Occurrence );
void setShowSelection ( bool state );

View File

@ -312,6 +312,7 @@ namespace Hurricane {
inline TabSettings* getSettings ();
void setCellWidget ( CellWidget* );
//inline int addSetting ( QWidget* page, const QString& label );
void insertTabAfter ( const QString& ref, QWidget*, const QString& label );
public slots:
void graphicsUpdated ();
void cellPreModificate ();

29
tramontana/CMakeLists.txt Normal file
View File

@ -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)

View File

@ -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 )

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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 );
}
}

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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() );
}
}

362
tramontana/src/Tile.cpp Normal file
View File

@ -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.

View File

@ -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.

View File

@ -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);

View File

@ -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.

View File

@ -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);

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -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);

View File

@ -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; }
}

View File

@ -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);

View File

@ -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);

View File

@ -38,8 +38,8 @@
#find_package(KNIK REQUIRED)
#find_package(KATABATIC REQUIRED)
#find_package(KITE REQUIRED)
find_package(EQUINOX REQUIRED)
find_package(SOLSTICE REQUIRED)
#find_package(EQUINOX REQUIRED)
#find_package(SOLSTICE REQUIRED)
#find_package(TUTORIAL REQUIRED) # FIXME: make FindTUTORIAL.cmake
find_package(Doxygen)

View File

@ -58,8 +58,8 @@ using namespace CRL;
#include "katana/GraphicKatanaEngine.h"
#include "etesian/GraphicEtesianEngine.h"
#include "katana/GraphicKatanaEngine.h"
#include "equinox/GraphicEquinoxEngine.h"
#include "solstice/GraphicSolsticeEngine.h"
//#include "equinox/GraphicEquinoxEngine.h"
//#include "solstice/GraphicSolsticeEngine.h"
#include "unicorn/UnicornGui.h"
using namespace Unicorn;

View File

@ -20,7 +20,7 @@ try:
from coriolis import helpers
helpers.loadUserSettings()
from coriolis import Cfg, Hurricane, Viewer, CRL, Etesian, Anabatic, \
Katana, Bora, Tutorial, Unicorn
Katana, Tramontana, Bora, Tutorial, Unicorn
except Exception as e:
helpers.io.showPythonTrace( sys.argv[0], e )
sys.exit(2)
@ -179,8 +179,8 @@ if __name__ == '__main__':
unicorn = Unicorn.UnicornGui.create()
unicorn.setApplicationName ('cgt')
unicorn.registerTool (Etesian.GraphicEtesianEngine.grab())
#unicorn.registerTool (Kite.GraphicKiteEngine.grab())
unicorn.registerTool (Katana.GraphicKatanaEngine.grab())
unicorn.registerTool (Tramontana.GraphicTramontanaEngine.grab())
unicorn.registerTool (Bora.GraphicBoraEngine.grab())
unicorn.registerTool (Tutorial.GraphicTutorialEngine.grab())
#unicorn.setAnonNetSelectable(False)

View File

@ -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

View File

@ -65,6 +65,7 @@ namespace {
cerr << endl << endl;
}
rb.remove( Interval( l(3), l(4) ));
rb.write( "finalRbTree.gv" );
for ( Interval intv : rb.getElements() ) {
@ -100,6 +101,7 @@ namespace {
cerr << endl << endl;
}
itree.remove( IntvString( "a", l(3), l(4) ));
itree.write( "finalIntervalTree.gv" );
for ( IntervalData<string> intv : itree.getElements() ) {