Support for avoidance of vertical tracks in low metal techs.
* New: In NetBuilderHybridVH::_do_1G_xM1_1PinM1(), added configuration to manage pins on the north/south sides for VH,2RL. * Bug: In NetBuilderHybridVH::doRp_xG_xM1_xM3(), correct misplaced vertical creation (buildind invalid topologies). * New: EtesianEngine::toColoquinte(), display histograms of the cells widths (in pitch) before and after bloating to get a better feeling of the behavior. * New: In EtesianEngine, add support for track avoidance. Portions of tracks to avoid are specified by a Box, which should flat and on the axis of the request track. This feature is used by the H-Tree to clear the vertical tracks under the tree from any terminal. * New: In Etesian::Area, Slice and SubSlice, add support for track avoidance. Exported to the Python wrapper. * New: SubSlice::getUsedVTracks() to get a set of tracks blocked by the cell. * New: SubSlice::trackAvoid(), shift left/rigth the cell under the requested vertical track. Try only to move the cell under the track and not it's neighbor, so it assume that there is sufficient space left or right of the cell. * Bug: In cumulus/plugins.block.configuration.BlockConf, the Cfg parameters may be read too early from the Cfg space into the various sub-conf objects (like FeedsConf). Delay the reading of the parameters in a _postInit() functions. Modify Block and CoreToChip to call _postInit(). * New: In cumulus/plugins.block.configuration.BlockConf._loadRoutingGauge, allow the cell gauge name to differ from the routing gauge name. * New: In cumulus/plugins.block.configuration.FeedsConf, allow to select the default feed to be used with 'etesian.defaultFeed' parameter. * New: In cumulus/plugins.block.spares.BufferPool, allow to control whether or not we want tie to either side of the pool. (for latch up). * New: In cumulus/plugins.block.HTree._connectLeaf(), add support for track avoidance. * Bug: In cumulus/plugins.block.HTree._connectLeaf(), the TL2 contact, the one on the *top* auxiliary buffer seemed to have been badly positioned until now (too low, not using tl2Y). This is strange because it should have caused disconnections, but I didn't see it in the wiring and the regressions tests didn't flag anything wrong. Still a bit weird and worrying.
This commit is contained in:
parent
49bcdb3195
commit
ca41dbd5ef
|
@ -772,6 +772,7 @@ namespace Anabatic {
|
||||||
case Conn_1G_1PinM3: _do_1G_1PinM3 (); break;
|
case Conn_1G_1PinM3: _do_1G_1PinM3 (); break;
|
||||||
case Conn_2G_1PinM3:
|
case Conn_2G_1PinM3:
|
||||||
case Conn_3G_1PinM3: _do_xG_1PinM3 (); break;
|
case Conn_3G_1PinM3: _do_xG_1PinM3 (); break;
|
||||||
|
case Conn_1G_2M1_1PinM1: _do_1G_xM1_1PinM1(); break;
|
||||||
case Conn_1G_1M1_1PinM3: _do_1G_1M1_1PinM3(); break;
|
case Conn_1G_1M1_1PinM3: _do_1G_1M1_1PinM3(); break;
|
||||||
case Conn_1G_1M1_1PinM2:
|
case Conn_1G_1M1_1PinM2:
|
||||||
case Conn_1G_2M1_1PinM2:
|
case Conn_1G_2M1_1PinM2:
|
||||||
|
@ -1268,6 +1269,13 @@ namespace Anabatic {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool NetBuilder::_do_1G_xM1_1PinM1 ()
|
||||||
|
{
|
||||||
|
throw Error ( "%s::_do_1G_xM1_1PinM1() method *not* reimplemented from base class.", getTypeName().c_str() );
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool NetBuilder::_do_3G_xM1_1PinM3 ()
|
bool NetBuilder::_do_3G_xM1_1PinM3 ()
|
||||||
{
|
{
|
||||||
throw Error ( "%s::_do_3G_xM1_1PinM3() method *not* reimplemented from base class.", getTypeName().c_str() );
|
throw Error ( "%s::_do_3G_xM1_1PinM3() method *not* reimplemented from base class.", getTypeName().c_str() );
|
||||||
|
|
|
@ -266,11 +266,10 @@ namespace Anabatic {
|
||||||
} else {
|
} else {
|
||||||
currContact = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(0) );
|
currContact = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(0) );
|
||||||
}
|
}
|
||||||
AutoSegment::create( currTerm, currContact, Flags::Vertical );
|
|
||||||
} else {
|
} else {
|
||||||
currContact = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(0) );
|
currContact = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(0) );
|
||||||
}
|
}
|
||||||
|
AutoSegment::create( currTerm , currContact, Flags::Vertical );
|
||||||
AutoSegment::create( prevContact, currContact, Flags::Horizontal );
|
AutoSegment::create( prevContact, currContact, Flags::Horizontal );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,6 +379,38 @@ namespace Anabatic {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool NetBuilderHybridVH::_do_1G_xM1_1PinM1 ()
|
||||||
|
{
|
||||||
|
cdebug_log(145,1) << getTypeName() << "::_do_1G_xM1_1PinM1() [Managed Configuration - Optimized] " << getTopology() << endl;
|
||||||
|
|
||||||
|
sortRpByX( getRoutingPads(), NoFlags ); // increasing X.
|
||||||
|
|
||||||
|
vector<RoutingPad*> rpsM1;
|
||||||
|
RoutingPad* rpM2 = nullptr;
|
||||||
|
for ( RoutingPad* rp : getRoutingPads() ) {
|
||||||
|
if (dynamic_cast<Pin*>(rp->getOccurrence().getEntity())) rpM2 = rp;
|
||||||
|
else rpsM1.push_back( rp );
|
||||||
|
}
|
||||||
|
if (rpsM1.size() > 1)
|
||||||
|
doRp_xG_xM1_xM3( rpsM1 );
|
||||||
|
else
|
||||||
|
doRp_xG_1M1( rpsM1[0] );
|
||||||
|
|
||||||
|
Pin* pin = dynamic_cast<Pin*>( rpM2->getOccurrence().getEntity() );
|
||||||
|
Pin::AccessDirection pinDir = pin->getAccessDirection();
|
||||||
|
AutoContact* rpContact = doRp_AccessNorthSouthPin( getGCell(), rpM2 );
|
||||||
|
AutoContact* rpM1Contact = doRp_Access( getGCell(), rpsM1.front(), NoFlags );
|
||||||
|
AutoContact* turn1 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(0) );
|
||||||
|
AutoContact* turn2 = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(0) );
|
||||||
|
AutoSegment::create( rpM1Contact, turn1, Flags::Vertical );
|
||||||
|
AutoSegment::create( rpContact , turn2, Flags::Vertical );
|
||||||
|
AutoSegment::create( turn1 , turn2, Flags::Horizontal );
|
||||||
|
|
||||||
|
cdebug_tabw(145,-1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool NetBuilderHybridVH::doRp_1G_1PinM2 ( RoutingPad* rp )
|
bool NetBuilderHybridVH::doRp_1G_1PinM2 ( RoutingPad* rp )
|
||||||
{
|
{
|
||||||
cdebug_log(145,1) << getTypeName() << "::doRp_1G_1PinM2() [Managed Configuration - Optimized] " << getTopology() << endl;
|
cdebug_log(145,1) << getTypeName() << "::doRp_1G_1PinM2() [Managed Configuration - Optimized] " << getTopology() << endl;
|
||||||
|
|
|
@ -236,6 +236,7 @@ namespace Anabatic {
|
||||||
virtual bool _do_xG_xM2 ();
|
virtual bool _do_xG_xM2 ();
|
||||||
virtual bool _do_1G_1M3 ();
|
virtual bool _do_1G_1M3 ();
|
||||||
virtual bool _do_xG_xM3 ();
|
virtual bool _do_xG_xM3 ();
|
||||||
|
virtual bool _do_1G_xM1_1PinM1 ();
|
||||||
virtual bool _do_1G_xM1_1PinM2 ();
|
virtual bool _do_1G_xM1_1PinM2 ();
|
||||||
virtual bool _do_2G_xM1_1PinM2 ();
|
virtual bool _do_2G_xM1_1PinM2 ();
|
||||||
virtual bool _do_1G_1M1_1PinM3 ();
|
virtual bool _do_1G_1M1_1PinM3 ();
|
||||||
|
@ -344,6 +345,8 @@ namespace Anabatic {
|
||||||
, Conn_1G_1PinM2 = CONNEXITY_VALUE( 1, 0, 1, 0, 0 , 1 )
|
, Conn_1G_1PinM2 = CONNEXITY_VALUE( 1, 0, 1, 0, 0 , 1 )
|
||||||
, Conn_2G_1PinM2 = CONNEXITY_VALUE( 2, 0, 1, 0, 0 , 1 )
|
, Conn_2G_1PinM2 = CONNEXITY_VALUE( 2, 0, 1, 0, 0 , 1 )
|
||||||
, Conn_3G_1PinM2 = CONNEXITY_VALUE( 3, 0, 1, 0, 0 , 1 )
|
, Conn_3G_1PinM2 = CONNEXITY_VALUE( 3, 0, 1, 0, 0 , 1 )
|
||||||
|
, Conn_1G_1M1_1PinM1 = CONNEXITY_VALUE( 1, 1, 0, 0, 0 , 1 )
|
||||||
|
, Conn_1G_2M1_1PinM1 = CONNEXITY_VALUE( 1, 2, 0, 0, 0 , 1 )
|
||||||
, Conn_1G_1M1_1PinM2 = CONNEXITY_VALUE( 1, 1, 1, 0, 0 , 1 )
|
, Conn_1G_1M1_1PinM2 = CONNEXITY_VALUE( 1, 1, 1, 0, 0 , 1 )
|
||||||
, Conn_1G_2M1_1PinM2 = CONNEXITY_VALUE( 1, 2, 1, 0, 0 , 1 )
|
, Conn_1G_2M1_1PinM2 = CONNEXITY_VALUE( 1, 2, 1, 0, 0 , 1 )
|
||||||
, Conn_1G_3M1_1PinM2 = CONNEXITY_VALUE( 1, 3, 1, 0, 0 , 1 )
|
, Conn_1G_3M1_1PinM2 = CONNEXITY_VALUE( 1, 3, 1, 0, 0 , 1 )
|
||||||
|
|
|
@ -51,6 +51,7 @@ namespace Anabatic {
|
||||||
// virtual bool _do_xG_xM3 ();
|
// virtual bool _do_xG_xM3 ();
|
||||||
// virtual bool _do_xG_1M1_1M2 ();
|
// virtual bool _do_xG_1M1_1M2 ();
|
||||||
virtual bool _do_xG_xM1_xM3 ();
|
virtual bool _do_xG_xM1_xM3 ();
|
||||||
|
virtual bool _do_1G_xM1_1PinM1 ();
|
||||||
virtual bool _do_1G_xM1_1PinM2 ();
|
virtual bool _do_1G_xM1_1PinM2 ();
|
||||||
// virtual bool _do_4G_1M2 ();
|
// virtual bool _do_4G_1M2 ();
|
||||||
virtual bool _do_2G ();
|
virtual bool _do_2G ();
|
||||||
|
|
|
@ -161,6 +161,7 @@ class Side ( object ):
|
||||||
check for out of bounds coordinates.
|
check for out of bounds coordinates.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
trace( 550, '\tSide.place() {}\n'.format(ioPin) )
|
||||||
status = 0
|
status = 0
|
||||||
if self.side & (IoPin.NORTH | IoPin.SOUTH):
|
if self.side & (IoPin.NORTH | IoPin.SOUTH):
|
||||||
gauge = self.conf.vDeepRG
|
gauge = self.conf.vDeepRG
|
||||||
|
@ -298,6 +299,7 @@ class Block ( object ):
|
||||||
Create a Block object. The only parameter ``conf`` must be a BlockConf
|
Create a Block object. The only parameter ``conf`` must be a BlockConf
|
||||||
object which contains the complete block configuration.
|
object which contains the complete block configuration.
|
||||||
"""
|
"""
|
||||||
|
conf._postInit()
|
||||||
self.flags = 0
|
self.flags = 0
|
||||||
self.conf = conf
|
self.conf = conf
|
||||||
self.spares = Spares( self )
|
self.spares = Spares( self )
|
||||||
|
@ -617,6 +619,7 @@ class Block ( object ):
|
||||||
Place the Pins on all the sides. Raise an exception in case of failure.
|
Place the Pins on all the sides. Raise an exception in case of failure.
|
||||||
(mainly due to Pins outside the side range)
|
(mainly due to Pins outside the side range)
|
||||||
"""
|
"""
|
||||||
|
trace( 550, ',+', '\tBlock.placeIoPins().\n' )
|
||||||
faileds = 0
|
faileds = 0
|
||||||
with UpdateSession():
|
with UpdateSession():
|
||||||
for ioPin in self.conf.ioPins:
|
for ioPin in self.conf.ioPins:
|
||||||
|
@ -625,6 +628,7 @@ class Block ( object ):
|
||||||
elif ioPin.flags & IoPin.EAST: side = self.sides[IoPin.EAST ]
|
elif ioPin.flags & IoPin.EAST: side = self.sides[IoPin.EAST ]
|
||||||
else: side = self.sides[IoPin.WEST ]
|
else: side = self.sides[IoPin.WEST ]
|
||||||
faileds += side.place( ioPin )
|
faileds += side.place( ioPin )
|
||||||
|
trace( 550, ',-' )
|
||||||
if faileds:
|
if faileds:
|
||||||
raise ErrorMessage( 3, 'Block.placeIoPins(): Cell "{}" has {} badly placed pins.' \
|
raise ErrorMessage( 3, 'Block.placeIoPins(): Cell "{}" has {} badly placed pins.' \
|
||||||
.format(self.conf.cell.getName(),faileds) )
|
.format(self.conf.cell.getName(),faileds) )
|
||||||
|
@ -846,6 +850,8 @@ class Block ( object ):
|
||||||
break
|
break
|
||||||
self.splitHTrees()
|
self.splitHTrees()
|
||||||
self.spares.removeUnusedBuffers()
|
self.spares.removeUnusedBuffers()
|
||||||
|
for trackAvoid in self.conf.trackAvoids:
|
||||||
|
self.etesian.addTrackAvoid( trackAvoid )
|
||||||
self.etesian.toHurricane()
|
self.etesian.toHurricane()
|
||||||
self.etesian.flattenPower()
|
self.etesian.flattenPower()
|
||||||
if self.conf.isCoreBlock: self.doConnectCore()
|
if self.conf.isCoreBlock: self.doConnectCore()
|
||||||
|
|
|
@ -136,7 +136,10 @@ class GaugeConf ( object ):
|
||||||
def _loadRoutingGauge ( self ):
|
def _loadRoutingGauge ( self ):
|
||||||
trace( 550, ',+', '\tGaugeConf._loadRoutingGauge()\n' )
|
trace( 550, ',+', '\tGaugeConf._loadRoutingGauge()\n' )
|
||||||
gaugeName = Cfg.getParamString('anabatic.routingGauge').asString()
|
gaugeName = Cfg.getParamString('anabatic.routingGauge').asString()
|
||||||
self._cellGauge = CRL.AllianceFramework.get().getCellGauge( gaugeName )
|
cellGaugeName = Cfg.getParamString('anabatic.cellGauge').asString()
|
||||||
|
if not cellGaugeName or cellGaugeName == '<undefined>':
|
||||||
|
cellGaugeName = gaugeName
|
||||||
|
self._cellGauge = CRL.AllianceFramework.get().getCellGauge( cellGaugeName )
|
||||||
self._routingGauge = CRL.AllianceFramework.get().getRoutingGauge( gaugeName )
|
self._routingGauge = CRL.AllianceFramework.get().getRoutingGauge( gaugeName )
|
||||||
|
|
||||||
if not self._routingGauge:
|
if not self._routingGauge:
|
||||||
|
@ -882,8 +885,8 @@ class BufferConf ( object ):
|
||||||
instance = Instance.create( cell, 'spare_buffer_{}'.format(self.count), self.masterCell )
|
instance = Instance.create( cell, 'spare_buffer_{}'.format(self.count), self.masterCell )
|
||||||
trace( 550, '\tBufferConf.createBuffer(): cell={}, instance={}\n' \
|
trace( 550, '\tBufferConf.createBuffer(): cell={}, instance={}\n' \
|
||||||
.format( cell, instance ))
|
.format( cell, instance ))
|
||||||
trace( 550, '\tplug={}\n'.format( instance.getPlug( self.masterCell.getNet('q') ) ))
|
trace( 550, '\tplug={}\n'.format( instance.getPlug( self.masterCell.getNet(self.output) ) ))
|
||||||
trace( 550, '\tplug.getCell()={}\n'.format( instance.getPlug( self.masterCell.getNet('q') ).getCell() ))
|
trace( 550, '\tplug.getCell()={}\n'.format( instance.getPlug( self.masterCell.getNet(self.output) ).getCell() ))
|
||||||
self.count += 1
|
self.count += 1
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
|
@ -988,9 +991,11 @@ class FeedsConf ( object ):
|
||||||
trace( 550, ',+', '\tFeedsConf.__init__()\n' )
|
trace( 550, ',+', '\tFeedsConf.__init__()\n' )
|
||||||
cfg.etesian.feedNames = None
|
cfg.etesian.feedNames = None
|
||||||
cfg.etesian.latchUpDistance = None
|
cfg.etesian.latchUpDistance = None
|
||||||
|
cfg.etesian.defaultFeed = None
|
||||||
feeds = cfg.etesian.feedNames.split(',')
|
feeds = cfg.etesian.feedNames.split(',')
|
||||||
self.count = 0
|
self.count = 0
|
||||||
self.feeds = []
|
self.feeds = []
|
||||||
|
self.defaultFeed = 0
|
||||||
for feedName in feeds:
|
for feedName in feeds:
|
||||||
feedCell = framework.getCell( feedName, CRL.Catalog.State.Views )
|
feedCell = framework.getCell( feedName, CRL.Catalog.State.Views )
|
||||||
if not feedCell:
|
if not feedCell:
|
||||||
|
@ -1006,16 +1011,20 @@ class FeedsConf ( object ):
|
||||||
for i in range(len(self.feeds)):
|
for i in range(len(self.feeds)):
|
||||||
trace( 550, '\t[{:>2}] {:>10} {}\n' \
|
trace( 550, '\t[{:>2}] {:>10} {}\n' \
|
||||||
.format(i,DbU.getValueString(self.feeds[i][0]),self.feeds[i][1]) )
|
.format(i,DbU.getValueString(self.feeds[i][0]),self.feeds[i][1]) )
|
||||||
|
if self.feeds[i][1].getName() == cfg.etesian.defaultFeed:
|
||||||
|
self.defaultFeed = i
|
||||||
trace( 550, '-' )
|
trace( 550, '-' )
|
||||||
return
|
return
|
||||||
|
|
||||||
def tieWidth ( self ):
|
def tieWidth ( self ):
|
||||||
"""Returns the master cell abutment box width of the tie."""
|
"""Returns the master cell abutment box width of the tie."""
|
||||||
if self.feeds: return self.feeds[0][0]
|
if self.feeds: return self.feeds[ self.defaultFeed ][0]
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def createFeed ( self, cell ):
|
def createFeed ( self, cell ):
|
||||||
instance = Instance.create( cell, 'spare_feed_{}'.format(self.count), self.feeds[0][1] )
|
instance = Instance.create( cell
|
||||||
|
, 'spare_feed_{}'.format(self.count)
|
||||||
|
, self.feeds[self.defaultFeed][1] )
|
||||||
self.count += 1
|
self.count += 1
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
|
@ -1152,6 +1161,14 @@ class IoPin ( object ):
|
||||||
s += 'IoPin.'+name
|
s += 'IoPin.'+name
|
||||||
return s
|
return s
|
||||||
|
|
||||||
|
def __repr__ ( self ):
|
||||||
|
s = '<IoPin "{}" {} @({},{},{})>'.format( self.stem
|
||||||
|
, IoPin.toStr(self.flags)
|
||||||
|
, DbU.getValueString(self.upos)
|
||||||
|
, DbU.getValueString(self.ustep)
|
||||||
|
, self.count )
|
||||||
|
return s
|
||||||
|
|
||||||
def __init__ ( self, flags, stem, upos, ustep=0, count=1 ):
|
def __init__ ( self, flags, stem, upos, ustep=0, count=1 ):
|
||||||
"""
|
"""
|
||||||
Create an I/O Pin(s) on the abutment box of a block. Could be for one
|
Create an I/O Pin(s) on the abutment box of a block. Could be for one
|
||||||
|
@ -1304,13 +1321,14 @@ class BlockConf ( GaugeConf ):
|
||||||
self.editor = None
|
self.editor = None
|
||||||
self.framework = CRL.AllianceFramework.get()
|
self.framework = CRL.AllianceFramework.get()
|
||||||
self.cfg = CfgCache('',Cfg.Parameter.Priority.Interactive)
|
self.cfg = CfgCache('',Cfg.Parameter.Priority.Interactive)
|
||||||
self.bufferConf = BufferConf( self.framework )
|
self.bufferConf = None
|
||||||
self.constantsConf = ConstantsConf( self.framework, self.cfg )
|
self.constantsConf = None
|
||||||
self.feedsConf = FeedsConf( self.framework, self.cfg )
|
self.feedsConf = None
|
||||||
self.powersConf = PowersConf( self.framework, self.cfg )
|
self.powersConf = None
|
||||||
self.chipConf = ChipConf( self )
|
self.chipConf = None
|
||||||
self.bColumns = 2
|
self.bColumns = 2
|
||||||
self.bRows = 2
|
self.bRows = 2
|
||||||
|
self.sparesTies = True
|
||||||
self.cloneds = []
|
self.cloneds = []
|
||||||
self.cell = cell
|
self.cell = cell
|
||||||
self.icore = None
|
self.icore = None
|
||||||
|
@ -1324,23 +1342,34 @@ class BlockConf ( GaugeConf ):
|
||||||
self.hTreeDatas = [ ]
|
self.hTreeDatas = [ ]
|
||||||
self.useHFNS = False
|
self.useHFNS = False
|
||||||
self.useSpares = True
|
self.useSpares = True
|
||||||
|
self.trackAvoids = []
|
||||||
self.isBuilt = False
|
self.isBuilt = False
|
||||||
self.useHarness = False
|
self.useHarness = False
|
||||||
self.ioPins = []
|
self.ioPins = []
|
||||||
self.ioPinsCounts = {}
|
self.ioPinsCounts = {}
|
||||||
for ioPinSpec in ioPins:
|
self.ioPinsArg = ioPins
|
||||||
self.ioPins.append( IoPin( *ioPinSpec ) )
|
self.ioPadsArg = ioPads
|
||||||
for line in range(len(ioPads)):
|
|
||||||
self.chipConf.addIoPad( ioPads[line], line )
|
|
||||||
self.cfg.etesian.aspectRatio = None
|
self.cfg.etesian.aspectRatio = None
|
||||||
self.cfg.etesian.spaceMargin = None
|
self.cfg.etesian.spaceMargin = None
|
||||||
self.cfg.etesian.latchUpDistance = None
|
self.cfg.etesian.latchUpDistance = None
|
||||||
self.cfg.block.spareSide = None
|
self.cfg.block.spareSide = None
|
||||||
self.cfg.block.vRailsPeriod = None
|
self.cfg.block.vRailsPeriod = None
|
||||||
self.cfg.katana.dumpMeasures = None
|
self.cfg.katana.dumpMeasures = None
|
||||||
|
self.chipConf = ChipConf( self )
|
||||||
self.etesian = None
|
self.etesian = None
|
||||||
self.katana = None
|
self.katana = None
|
||||||
|
|
||||||
|
def _postInit ( self ):
|
||||||
|
self.cfg.apply()
|
||||||
|
self.bufferConf = BufferConf( self.framework )
|
||||||
|
self.constantsConf = ConstantsConf( self.framework, self.cfg )
|
||||||
|
self.feedsConf = FeedsConf( self.framework, self.cfg )
|
||||||
|
self.powersConf = PowersConf( self.framework, self.cfg )
|
||||||
|
for ioPinSpec in self.ioPinsArg:
|
||||||
|
self.ioPins.append( IoPin( *ioPinSpec ) )
|
||||||
|
for line in range(len(self.ioPadsArg)):
|
||||||
|
self.chipConf.addIoPad( self.ioPadsArg[line], line )
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def isCoreBlock ( self ): return self.chip is not None
|
def isCoreBlock ( self ): return self.chip is not None
|
||||||
|
|
||||||
|
@ -1438,6 +1467,10 @@ class BlockConf ( GaugeConf ):
|
||||||
return
|
return
|
||||||
self.hTreeDatas.append( [ netName, flags ] );
|
self.hTreeDatas.append( [ netName, flags ] );
|
||||||
|
|
||||||
|
def addTrackAvoid ( self, trackAvoid ):
|
||||||
|
if self.cfg.anabatic.netBuilderStyle == 'VH,2RL':
|
||||||
|
self.trackAvoids.append( trackAvoid )
|
||||||
|
|
||||||
def save ( self, flags ):
|
def save ( self, flags ):
|
||||||
"""
|
"""
|
||||||
Frontend to BlockConf.rsave(). Append the "_cts" suffix to the cloned
|
Frontend to BlockConf.rsave(). Append the "_cts" suffix to the cloned
|
||||||
|
|
|
@ -100,6 +100,7 @@ class HTree ( object ):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _connectLeaf ( self, leaf, ckNet, forkContact, contact, x, y ):
|
def _connectLeaf ( self, leaf, ckNet, forkContact, contact, x, y ):
|
||||||
|
trace( 550, ',+', '\tHTree.connectLeaf() contact={}\n'.format( contact ))
|
||||||
gaugeConf = self.spares.conf
|
gaugeConf = self.spares.conf
|
||||||
bufferConf = self.spares.conf.bufferConf
|
bufferConf = self.spares.conf.bufferConf
|
||||||
hLeafDepth = gaugeConf.horizontalDepth
|
hLeafDepth = gaugeConf.horizontalDepth
|
||||||
|
@ -107,20 +108,24 @@ class HTree ( object ):
|
||||||
hLeafDepth = gaugeConf.horizontalDepth - 2
|
hLeafDepth = gaugeConf.horizontalDepth - 2
|
||||||
gaugeConf.setStackPosition( contact, x, y )
|
gaugeConf.setStackPosition( contact, x, y )
|
||||||
gaugeConf.createVertical ( contact, forkContact, x, 0 )
|
gaugeConf.createVertical ( contact, forkContact, x, 0 )
|
||||||
trace( 550, '\tLeaf contact:{}\n'.format( contact ))
|
gaugeConf.addTrackAvoid( Box( x, forkContact.getY(), x, y ) )
|
||||||
if len(leaf.buffers) > 1:
|
if len(leaf.buffers) > 1:
|
||||||
tl1Contact = gaugeConf.rpAccessByPlugName( leaf.buffers[1], bufferConf.input, ckNet, GaugeConf.DeepDepth|GaugeConf.HAccess )
|
tl1Contact = gaugeConf.rpAccessByPlugName( leaf.buffers[1], bufferConf.input, ckNet, GaugeConf.DeepDepth|GaugeConf.HAccess )
|
||||||
tl2Contact = gaugeConf.rpAccessByPlugName( leaf.buffers[2], bufferConf.input, ckNet )
|
tl2Contact = gaugeConf.rpAccessByPlugName( leaf.buffers[2], bufferConf.input, ckNet )
|
||||||
tl2Y = gaugeConf.getTrack( tl2Contact.getY(), hLeafDepth, 2 )
|
tl2Y = gaugeConf.getTrack( tl2Contact.getY(), hLeafDepth, 2 )
|
||||||
left1X = gaugeConf.getNearestVerticalTrack( tl1Contact.getX(), 0, 0 )
|
left1X = gaugeConf.getNearestVerticalTrack( tl1Contact.getX(), 0, 0 )
|
||||||
left1Y = gaugeConf.getStackY( contact, GaugeConf.DeepDepth )
|
left1Y = gaugeConf.getStackY( contact, GaugeConf.DeepDepth )
|
||||||
|
trace( 550, '\tleft1Y: {}\n'.format( DbU.getValueString(left1Y) ))
|
||||||
dxLeft = contact.getX() - gaugeConf.getStackX( contact, GaugeConf.DeepDepth )
|
dxLeft = contact.getX() - gaugeConf.getStackX( contact, GaugeConf.DeepDepth )
|
||||||
|
trace( 550, '\ttl2Contact: {}\n'.format( tl2Contact ))
|
||||||
gaugeConf.setStackPosition( tl1Contact, left1X, left1Y )
|
gaugeConf.setStackPosition( tl1Contact, left1X, left1Y )
|
||||||
gaugeConf.setStackPosition( tl2Contact, x , left1Y )
|
gaugeConf.setStackPosition( tl2Contact, x , tl2Y )
|
||||||
|
trace( 550, '\ttl2Contact: {}\n'.format( tl2Contact ))
|
||||||
gaugeConf.expandMinArea( tl2Contact )
|
gaugeConf.expandMinArea( tl2Contact )
|
||||||
#gaugeConf.createHorizontal( contact , tl1Contact, left1Y , GaugeConf.DeepDepth|GaugeConf.SourceExtend )
|
#gaugeConf.createHorizontal( contact , tl1Contact, left1Y , GaugeConf.DeepDepth|GaugeConf.SourceExtend )
|
||||||
gaugeConf.createHorizontal( contact , tl1Contact, left1Y , GaugeConf.DeepDepth, dxLeft )
|
gaugeConf.createHorizontal( contact , tl1Contact, left1Y , GaugeConf.DeepDepth, dxLeft )
|
||||||
gaugeConf.createVertical ( contact , tl2Contact, x, 0 )
|
gaugeConf.createVertical ( contact , tl2Contact, x, 0 )
|
||||||
|
trace( 550, ',-' )
|
||||||
|
|
||||||
def _rrouteHTree ( self, qt ):
|
def _rrouteHTree ( self, qt ):
|
||||||
"""
|
"""
|
||||||
|
@ -211,8 +216,10 @@ class HTree ( object ):
|
||||||
if qt.bl:
|
if qt.bl:
|
||||||
trace( 550, '\tConnect BL leaf, leftX={} blY={}\n'.format( DbU.getValueString(leftX), DbU.getValueString(blY) ))
|
trace( 550, '\tConnect BL leaf, leftX={} blY={}\n'.format( DbU.getValueString(leftX), DbU.getValueString(blY) ))
|
||||||
self._connectLeaf( qt.bl, ckNet, leftContact, blContact, leftX, blY )
|
self._connectLeaf( qt.bl, ckNet, leftContact, blContact, leftX, blY )
|
||||||
|
#gaugeConf.addTrackAvoid( Box( leftX, leftSourceY, leftX, blY ) )
|
||||||
if qt.tr:
|
if qt.tr:
|
||||||
self._connectLeaf( qt.tr, ckNet, rightContact, trContact, rightX, tlY )
|
self._connectLeaf( qt.tr, ckNet, rightContact, trContact, rightX, tlY )
|
||||||
|
#gaugeConf.addTrackAvoid( Box( rightX, rightSourceY, rightX, tlY ) )
|
||||||
if qt.br:
|
if qt.br:
|
||||||
self._connectLeaf( qt.br, ckNet, rightContact, brContact, rightX, blY )
|
self._connectLeaf( qt.br, ckNet, rightContact, brContact, rightX, blY )
|
||||||
if qt.isRoot():
|
if qt.isRoot():
|
||||||
|
|
|
@ -146,8 +146,10 @@ class BufferPool ( object ):
|
||||||
yoffset = self.quadTree.spares.conf.icore.getTransformation().getTy()
|
yoffset = self.quadTree.spares.conf.icore.getTransformation().getTy()
|
||||||
conf = self.quadTree.spares.conf
|
conf = self.quadTree.spares.conf
|
||||||
sliceHeight = conf.sliceHeight
|
sliceHeight = conf.sliceHeight
|
||||||
poolHalfWidth = (conf.bufferConf.width * self.columns)//2 + conf.feedsConf.tieWidth()
|
poolHalfWidth = (conf.bufferConf.width * self.columns)//2
|
||||||
poolHalfHeight = (conf.bufferConf.height * self.rows)//2
|
poolHalfHeight = (conf.bufferConf.height * self.rows)//2
|
||||||
|
if conf.sparesTies:
|
||||||
|
poolHalfWidth += conf.feedsConf.tieWidth()
|
||||||
x = self.quadTree.spares.toXPitch( self.quadTree.area.getXCenter() - poolHalfWidth )
|
x = self.quadTree.spares.toXPitch( self.quadTree.area.getXCenter() - poolHalfWidth )
|
||||||
y = self.quadTree.spares.toYSlice( self.quadTree.area.getYCenter() - poolHalfHeight )
|
y = self.quadTree.spares.toYSlice( self.quadTree.area.getYCenter() - poolHalfHeight )
|
||||||
slice = (y - yoffset) // sliceHeight
|
slice = (y - yoffset) // sliceHeight
|
||||||
|
@ -160,10 +162,13 @@ class BufferPool ( object ):
|
||||||
orientation = Transformation.Orientation.MY
|
orientation = Transformation.Orientation.MY
|
||||||
y += sliceHeight
|
y += sliceHeight
|
||||||
length = 0
|
length = 0
|
||||||
for column in range(self.columns+2):
|
tieCols = 0
|
||||||
|
if conf.sparesTies:
|
||||||
|
tieCols = 2
|
||||||
|
for column in range(self.columns+tieCols):
|
||||||
transf = Transformation( x + length, y, orientation )
|
transf = Transformation( x + length, y, orientation )
|
||||||
if (column > 0) and (column <= self.columns):
|
if (not conf.sparesTies) or ((column > 0) and (column <= self.columns)):
|
||||||
index = self.toIndex(column-1,row)
|
index = self.toIndex(column-tieCols//2,row)
|
||||||
instance = conf.createBuffer()
|
instance = conf.createBuffer()
|
||||||
self.buffers[ index ][1] = instance
|
self.buffers[ index ][1] = instance
|
||||||
trace( 540, '\tBuffer[{}]: {} @{}\n'.format(index,self.buffers[index],transf) )
|
trace( 540, '\tBuffer[{}]: {} @{}\n'.format(index,self.buffers[index],transf) )
|
||||||
|
@ -845,6 +850,7 @@ class QuadTree ( object ):
|
||||||
coreTransf = self.spares.conf.icore.getTransformation()
|
coreTransf = self.spares.conf.icore.getTransformation()
|
||||||
maxSinks = self.spares.conf.bufferConf.maxSinks
|
maxSinks = self.spares.conf.bufferConf.maxSinks
|
||||||
#maxSinks = 7
|
#maxSinks = 7
|
||||||
|
trace( 540, '\tconf.bufferConf.maxSinks={}\n'.format(maxSinks) )
|
||||||
plugOccsByAngle = []
|
plugOccsByAngle = []
|
||||||
areaCenter = self.area.getCenter()
|
areaCenter = self.area.getCenter()
|
||||||
#coreTransf.applyOn( areaCenter )
|
#coreTransf.applyOn( areaCenter )
|
||||||
|
|
|
@ -519,6 +519,7 @@ class CoreToChip ( object ):
|
||||||
.format( core.getName() )
|
.format( core.getName() )
|
||||||
] )
|
] )
|
||||||
conf = block.state
|
conf = block.state
|
||||||
|
conf._postInit()
|
||||||
self.conf = conf
|
self.conf = conf
|
||||||
self.conf.useHarness = False
|
self.conf.useHarness = False
|
||||||
self.ringNetNames = []
|
self.ringNetNames = []
|
||||||
|
|
|
@ -158,14 +158,18 @@ namespace Etesian {
|
||||||
|
|
||||||
DbU::Unit BloatChannel::getDx ( const Cell* cell, const EtesianEngine* etesian ) const
|
DbU::Unit BloatChannel::getDx ( const Cell* cell, const EtesianEngine* etesian ) const
|
||||||
{
|
{
|
||||||
|
Box ab ( cell->getAbutmentBox() );
|
||||||
|
DbU::Unit vpitch = etesian->getSliceStep();;
|
||||||
|
int xsize = (ab.getWidth() + vpitch - 1) / vpitch;
|
||||||
|
#if THIS_IS_DISABLED
|
||||||
|
return (xsize < 5) ? ((5-xsize)*vpitch) : 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
int terminals = 0;
|
int terminals = 0;
|
||||||
for ( Net* net : cell->getNets() ) {
|
for ( Net* net : cell->getNets() ) {
|
||||||
if (net->isExternal() and not net->isPower()) ++terminals;
|
if (net->isExternal() and not net->isPower()) ++terminals;
|
||||||
}
|
}
|
||||||
|
|
||||||
Box ab ( cell->getAbutmentBox() );
|
|
||||||
DbU::Unit vpitch = etesian->getSliceStep();;
|
|
||||||
int xsize = (ab.getWidth() + vpitch - 1) / vpitch;
|
|
||||||
int extra = 0;
|
int extra = 0;
|
||||||
float termRatio = (float)terminals / (float)(ab.getWidth() / vpitch);
|
float termRatio = (float)terminals / (float)(ab.getWidth() / vpitch);
|
||||||
if (termRatio > 0.8) extra += 1;
|
if (termRatio > 0.8) extra += 1;
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
// -*- C++ -*-
|
// -*- C++ -*-
|
||||||
//
|
//
|
||||||
// This file is part of the Coriolis Software.
|
// This file is part of the Coriolis Software.
|
||||||
// Copyright (c) UPMC 2014-2018, All Rights Reserved
|
// Copyright (c) Sorbonne Université 2014-2022, All Rights Reserved
|
||||||
//
|
//
|
||||||
// +-----------------------------------------------------------------+
|
// +-----------------------------------------------------------------+
|
||||||
// | C O R I O L I S |
|
// | C O R I O L I S |
|
||||||
// | E t e s i a n - A n a l y t i c P l a c e r |
|
// | E t e s i a n - A n a l y t i c P l a c e r |
|
||||||
// | |
|
// | |
|
||||||
// | Author : Jean-Paul CHAPUT |
|
// | Author : Jean-Paul CHAPUT |
|
||||||
// | E-mail : Jean-Paul.Chaput@asim.lip6.fr |
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||||
// | =============================================================== |
|
// | =============================================================== |
|
||||||
// | C++ Module : "./EtesianEngine.cpp" |
|
// | C++ Module : "./EtesianEngine.cpp" |
|
||||||
// +-----------------------------------------------------------------+
|
// +-----------------------------------------------------------------+
|
||||||
|
@ -46,6 +46,7 @@
|
||||||
#include "hurricane/viewer/CellViewer.h"
|
#include "hurricane/viewer/CellViewer.h"
|
||||||
#include "crlcore/Utilities.h"
|
#include "crlcore/Utilities.h"
|
||||||
#include "crlcore/Measures.h"
|
#include "crlcore/Measures.h"
|
||||||
|
#include "crlcore/Histogram.h"
|
||||||
#include "crlcore/AllianceFramework.h"
|
#include "crlcore/AllianceFramework.h"
|
||||||
#include "etesian/EtesianEngine.h"
|
#include "etesian/EtesianEngine.h"
|
||||||
|
|
||||||
|
@ -302,6 +303,7 @@ namespace Etesian {
|
||||||
, _ySpinSet (false)
|
, _ySpinSet (false)
|
||||||
, _flatDesign (false)
|
, _flatDesign (false)
|
||||||
, _placeArea (cell->getAbutmentBox())
|
, _placeArea (cell->getAbutmentBox())
|
||||||
|
, _trackAvoids ()
|
||||||
, _surface (NULL)
|
, _surface (NULL)
|
||||||
, _circuit (NULL)
|
, _circuit (NULL)
|
||||||
, _placementLB (NULL)
|
, _placementLB (NULL)
|
||||||
|
@ -709,6 +711,14 @@ namespace Etesian {
|
||||||
DbU::Unit sliceHeight = getSliceHeight();
|
DbU::Unit sliceHeight = getSliceHeight();
|
||||||
bool isFlexLib = (getGauge()->getName() == "FlexLib");
|
bool isFlexLib = (getGauge()->getName() == "FlexLib");
|
||||||
|
|
||||||
|
CRL::Histogram stdCellSizes ( 0.0, 1.0, 2 );
|
||||||
|
stdCellSizes.setTitle ( "Width" , 0 );
|
||||||
|
stdCellSizes.setColor ( "green" , 0 );
|
||||||
|
stdCellSizes.setIndent( " ", 0 );
|
||||||
|
stdCellSizes.setTitle ( "Bloat" , 1 );
|
||||||
|
stdCellSizes.setColor ( "red" , 1 );
|
||||||
|
stdCellSizes.setIndent( " ", 1 );
|
||||||
|
|
||||||
cmess1 << " o Converting \"" << getCell()->getName() << "\" into Coloquinte." << endl;
|
cmess1 << " o Converting \"" << getCell()->getName() << "\" into Coloquinte." << endl;
|
||||||
cmess1 << ::Dots::asString(" - H-pitch" , DbU::getValueString(hpitch)) << endl;
|
cmess1 << ::Dots::asString(" - H-pitch" , DbU::getValueString(hpitch)) << endl;
|
||||||
cmess1 << ::Dots::asString(" - V-pitch" , DbU::getValueString(vpitch)) << endl;
|
cmess1 << ::Dots::asString(" - V-pitch" , DbU::getValueString(vpitch)) << endl;
|
||||||
|
@ -885,7 +895,9 @@ namespace Etesian {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
stdCellSizes.addSample( (float)(masterCell->getAbutmentBox().getWidth() / vpitch), 0 );
|
||||||
Box instanceAb = _bloatCells.getAb( occurrence );
|
Box instanceAb = _bloatCells.getAb( occurrence );
|
||||||
|
stdCellSizes.addSample( (float)(instanceAb.getWidth() / vpitch), 1 );
|
||||||
|
|
||||||
Transformation instanceTransf = instance->getTransformation();
|
Transformation instanceTransf = instance->getTransformation();
|
||||||
occurrence.getPath().getTransformation().applyOn( instanceTransf );
|
occurrence.getPath().getTransformation().applyOn( instanceTransf );
|
||||||
|
@ -1067,6 +1079,11 @@ namespace Etesian {
|
||||||
}
|
}
|
||||||
dots.finish( Dots::Reset );
|
dots.finish( Dots::Reset );
|
||||||
|
|
||||||
|
cmess1 << " - Standard cells widths:" << endl;
|
||||||
|
cmess2 << stdCellSizes.toString(0) << endl;
|
||||||
|
if (_bloatCells.getSelected()->getName() != "disabled")
|
||||||
|
cmess2 << stdCellSizes.toString(1) << endl;
|
||||||
|
|
||||||
_densityLimits = new coloquinte::density_restrictions ();
|
_densityLimits = new coloquinte::density_restrictions ();
|
||||||
_surface = new box<int_t>( (int_t)(topAb.getXMin() / vpitch)
|
_surface = new box<int_t>( (int_t)(topAb.getXMin() / vpitch)
|
||||||
, (int_t)(topAb.getXMax() / vpitch)
|
, (int_t)(topAb.getXMax() / vpitch)
|
||||||
|
|
|
@ -23,6 +23,8 @@
|
||||||
#include "hurricane/DeepNet.h"
|
#include "hurricane/DeepNet.h"
|
||||||
#include "hurricane/Plug.h"
|
#include "hurricane/Plug.h"
|
||||||
#include "hurricane/RoutingPad.h"
|
#include "hurricane/RoutingPad.h"
|
||||||
|
#include "hurricane/Vertical.h"
|
||||||
|
#include "hurricane/NetExternalComponents.h"
|
||||||
#include "hurricane/Path.h"
|
#include "hurricane/Path.h"
|
||||||
#include "hurricane/Library.h"
|
#include "hurricane/Library.h"
|
||||||
#include "hurricane/viewer/CellWidget.h"
|
#include "hurricane/viewer/CellWidget.h"
|
||||||
|
@ -43,9 +45,12 @@ namespace Etesian {
|
||||||
using Hurricane::Transformation;
|
using Hurricane::Transformation;
|
||||||
using Hurricane::DataBase;
|
using Hurricane::DataBase;
|
||||||
using Hurricane::Library;
|
using Hurricane::Library;
|
||||||
|
using Hurricane::Component;
|
||||||
using Hurricane::DeepNet;
|
using Hurricane::DeepNet;
|
||||||
using Hurricane::Plug;
|
using Hurricane::Plug;
|
||||||
using Hurricane::RoutingPad;
|
using Hurricane::RoutingPad;
|
||||||
|
using Hurricane::Vertical;
|
||||||
|
using Hurricane::NetExternalComponents;
|
||||||
using Hurricane::DebugSession;
|
using Hurricane::DebugSession;
|
||||||
using Hurricane::UpdateSession;
|
using Hurricane::UpdateSession;
|
||||||
using CRL::AllianceFramework;
|
using CRL::AllianceFramework;
|
||||||
|
@ -180,6 +185,20 @@ namespace Etesian {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Slice::trackAvoid ( DbU::Unit xTrack )
|
||||||
|
{
|
||||||
|
cdebug_log(121,1) << "Slice::trackAvoid() " << this << " @" << DbU::getValueString(xTrack) << endl;
|
||||||
|
for ( SubSlice& subSlice : _subSlices ) {
|
||||||
|
if (subSlice.getXMax() == xTrack) break;
|
||||||
|
if (subSlice.getXMax() > xTrack) {
|
||||||
|
subSlice.trackAvoid( xTrack );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
cdebug_tabw(121,-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Slice::insertTies ( DbU::Unit latchUpMax )
|
void Slice::insertTies ( DbU::Unit latchUpMax )
|
||||||
{
|
{
|
||||||
cdebug_log(121,1) << "Slice::insertTies() @" << DbU::getValueString(_ybottom) << endl;
|
cdebug_log(121,1) << "Slice::insertTies() @" << DbU::getValueString(_ybottom) << endl;
|
||||||
|
@ -521,7 +540,6 @@ namespace Etesian {
|
||||||
|
|
||||||
size_t ibegin = (flatAb.getYMin()-_placeArea.getYMin()) / _sliceHeight;
|
size_t ibegin = (flatAb.getYMin()-_placeArea.getYMin()) / _sliceHeight;
|
||||||
size_t iend = (flatAb.getYMax()-_placeArea.getYMin()) / _sliceHeight;
|
size_t iend = (flatAb.getYMax()-_placeArea.getYMin()) / _sliceHeight;
|
||||||
|
|
||||||
for ( size_t islice=ibegin ; islice<iend ; ++islice ) {
|
for ( size_t islice=ibegin ; islice<iend ; ++islice ) {
|
||||||
_slices[islice]->merge( occurrence, flatAb );
|
_slices[islice]->merge( occurrence, flatAb );
|
||||||
}
|
}
|
||||||
|
@ -544,6 +562,29 @@ namespace Etesian {
|
||||||
{ for ( Slice* slice : _slices ) slice->showSubSlices(); }
|
{ for ( Slice* slice : _slices ) slice->showSubSlices(); }
|
||||||
|
|
||||||
|
|
||||||
|
void Area::trackAvoid ( const Box& trackAvoid )
|
||||||
|
{
|
||||||
|
cdebug_log(121,1) << "Area::trackAvoid() over " << trackAvoid << endl;
|
||||||
|
Box areaTrackAvoid = _placeArea.getIntersection( trackAvoid );
|
||||||
|
if (areaTrackAvoid.isEmpty()) {
|
||||||
|
cerr << Warning( "Area::trackAvoid(): Track avoid area %s fully outside placement area %s."
|
||||||
|
, getString(trackAvoid).c_str()
|
||||||
|
, getString(_placeArea).c_str()
|
||||||
|
) << endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DbU::Unit xTrack = areaTrackAvoid.getXCenter();
|
||||||
|
size_t ibegin = (areaTrackAvoid.getYMin()-_placeArea.getYMin()) / _sliceHeight;
|
||||||
|
size_t iend = (areaTrackAvoid.getYMax()-_placeArea.getYMin()) / _sliceHeight + 1;
|
||||||
|
if (iend and (iend >= _slices.size())) --iend;
|
||||||
|
for ( size_t islice=ibegin ; islice<iend ; ++islice ) {
|
||||||
|
_slices[islice]->trackAvoid( xTrack );
|
||||||
|
}
|
||||||
|
cdebug_tabw(121,-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Area::insertTies ( DbU::Unit latchUpMax )
|
void Area::insertTies ( DbU::Unit latchUpMax )
|
||||||
{
|
{
|
||||||
for ( Slice* slice : _slices ) slice->insertTies( latchUpMax );
|
for ( Slice* slice : _slices ) slice->insertTies( latchUpMax );
|
||||||
|
@ -577,6 +618,34 @@ namespace Etesian {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size_t SubSlice::getUsedVTracks ( const Tile& tile, set<DbU::Unit>& vtracks )
|
||||||
|
{
|
||||||
|
DbU::Unit vpitch = _slice->getArea()->getEtesian()->getSliceStep();
|
||||||
|
Cell* cell = tile.getMasterCell();
|
||||||
|
for ( Net* net : cell->getNets() ) {
|
||||||
|
if (not net->isExternal()) continue;
|
||||||
|
if (net->isPower() or net->isGround()) continue;
|
||||||
|
for ( Component* component : NetExternalComponents::get(net) ) {
|
||||||
|
Vertical* v = dynamic_cast<Vertical*>( component );
|
||||||
|
if (not v) continue;
|
||||||
|
|
||||||
|
Transformation transf = tile.getInstance()->getTransformation();
|
||||||
|
tile.getOccurrence().getPath().getTransformation().applyOn( transf );
|
||||||
|
Point center = transf.getPoint( v->getBoundingBox().getCenter() );
|
||||||
|
if (center.getX() % vpitch) {
|
||||||
|
cerr << Error( "Slice::getUsedVTracks(): Misaligned terminal %s.\n"
|
||||||
|
" (in %s)"
|
||||||
|
, getString(v).c_str()
|
||||||
|
, getString(tile.getOccurrence()).c_str()
|
||||||
|
) << endl;
|
||||||
|
}
|
||||||
|
vtracks.insert( center.getX() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return vtracks.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
DbU::Unit SubSlice::getAverageChunk ( size_t& count ) const
|
DbU::Unit SubSlice::getAverageChunk ( size_t& count ) const
|
||||||
{
|
{
|
||||||
count = 0;
|
count = 0;
|
||||||
|
@ -598,6 +667,80 @@ namespace Etesian {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SubSlice::trackAvoid ( DbU::Unit xTrack )
|
||||||
|
{
|
||||||
|
DbU::Unit xMin = getXMin();
|
||||||
|
DbU::Unit xMax = getXMax();
|
||||||
|
auto beginTile = _beginTile;
|
||||||
|
auto endTile = _endTile;
|
||||||
|
if ((*beginTile).isFixed()) {
|
||||||
|
xMin += (*beginTile).getWidth();
|
||||||
|
++beginTile;
|
||||||
|
}
|
||||||
|
if (endTile == _slice->getTiles().end()) {
|
||||||
|
--endTile;
|
||||||
|
} else if ((*endTile).isFixed()) {
|
||||||
|
xMax = (*endTile).getXMin();
|
||||||
|
--endTile;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto iTile = _beginTile;
|
||||||
|
while ( true ) {
|
||||||
|
Instance* instance = (*iTile).getInstance();
|
||||||
|
|
||||||
|
if ((*iTile).getXMin() >= xTrack) break;
|
||||||
|
if ((*iTile).getXMax() == xTrack) break;
|
||||||
|
if ((*iTile).getXMax() > xTrack) {
|
||||||
|
cdebug_log(121,0) << instance->getName() << " accross V-Track @" << DbU::getValueString(xTrack) << endl;
|
||||||
|
set<DbU::Unit> usedVTracks;
|
||||||
|
getUsedVTracks( *iTile, usedVTracks );
|
||||||
|
for ( DbU::Unit x : usedVTracks )
|
||||||
|
cdebug_log(121,0) << "| V-Track @" << DbU::getValueString(x) << endl;
|
||||||
|
if (not usedVTracks.count(xTrack)) break;
|
||||||
|
|
||||||
|
DbU::Unit vpitch = _slice->getArea()->getEtesian()->getSliceStep();
|
||||||
|
DbU::Unit maxDxLeft = 0;
|
||||||
|
DbU::Unit maxDxRight = 0;
|
||||||
|
if (iTile != beginTile) {
|
||||||
|
auto prevTile = iTile;
|
||||||
|
--prevTile;
|
||||||
|
maxDxLeft = (*prevTile).getXMax() - (*iTile).getXMin();
|
||||||
|
}
|
||||||
|
if (iTile != endTile) {
|
||||||
|
auto nextTile = iTile;
|
||||||
|
--nextTile;
|
||||||
|
maxDxRight = (*nextTile).getXMin() - (*iTile).getXMax();
|
||||||
|
}
|
||||||
|
DbU::Unit xShift = 0;
|
||||||
|
for ( ; xShift <= maxDxLeft ; xShift += vpitch ) {
|
||||||
|
cdebug_log(121,0) << "| try left shift " << DbU::getValueString(-xShift) << endl;
|
||||||
|
if (not usedVTracks.count( xTrack + xShift )) break;
|
||||||
|
}
|
||||||
|
if (xShift > maxDxLeft) {
|
||||||
|
xShift = - vpitch;
|
||||||
|
for ( ; xShift > maxDxRight ; xShift -= vpitch ) {
|
||||||
|
cdebug_log(121,0) << "| try right shift " << DbU::getValueString(-xShift) << endl;
|
||||||
|
if (not usedVTracks.count( xTrack + xShift )) break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (xShift < maxDxRight) {
|
||||||
|
cerr << Error( "SubSlice::trackAvoid(): Unable to put out of the way %s."
|
||||||
|
, getString(*iTile).c_str()
|
||||||
|
) << endl;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cdebug_log(121,0) << "Shifting " << (*iTile) << " by " << DbU::getValueString(-xShift) << endl;
|
||||||
|
(*iTile).translate( -xShift );
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iTile == endTile) break;
|
||||||
|
++iTile;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void SubSlice::insertTies ( DbU::Unit latchUpMax )
|
void SubSlice::insertTies ( DbU::Unit latchUpMax )
|
||||||
{
|
{
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
|
@ -838,6 +981,8 @@ namespace Etesian {
|
||||||
|
|
||||||
_area->buildSubSlices();
|
_area->buildSubSlices();
|
||||||
_area->showSubSlices();
|
_area->showSubSlices();
|
||||||
|
for ( const Box& trackAvoid : _trackAvoids )
|
||||||
|
_area->trackAvoid( trackAvoid );
|
||||||
#if DISABLED_TIE_INSERTION
|
#if DISABLED_TIE_INSERTION
|
||||||
if (getConfiguration()->getLatchUpDistance()) {
|
if (getConfiguration()->getLatchUpDistance()) {
|
||||||
Cell* feed = getFeedCells().getBiggestFeed();
|
Cell* feed = getFeedCells().getBiggestFeed();
|
||||||
|
|
|
@ -188,8 +188,6 @@ extern "C" {
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------
|
|
||||||
// Attribute Method : "PyEtesianEngine_setPLaceArea ()"
|
|
||||||
|
|
||||||
static PyObject* PyEtesianEngine_setPlaceArea ( PyEtesianEngine *self, PyObject* args )
|
static PyObject* PyEtesianEngine_setPlaceArea ( PyEtesianEngine *self, PyObject* args )
|
||||||
{
|
{
|
||||||
|
@ -224,6 +222,22 @@ extern "C" {
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static PyObject* PyEtesianEngine_addTrackAvoid ( PyEtesianEngine *self, PyObject* args )
|
||||||
|
{
|
||||||
|
cdebug_log(34,0) << "EtesianEngine.addTrackAvoid()" << endl;
|
||||||
|
HTRY
|
||||||
|
METHOD_HEAD ( "EtesianEngine.addTrackAvoid()" )
|
||||||
|
PyBox* pyBox;
|
||||||
|
if (not PyArg_ParseTuple(args,"O!:EtesianEngine.addTrackAvoid", &PyTypeBox, &pyBox)) {
|
||||||
|
PyErr_SetString( ConstructorError, "EtesianEngine.addTrackAvoid(): Parameter is not an Box." );
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
etesian->addTrackAvoid( *PYBOX_O(pyBox) );
|
||||||
|
HCATCH
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
// Standart Accessors (Attributes).
|
// Standart Accessors (Attributes).
|
||||||
// DirectVoidMethod(EtesianEngine,etesian,runNegociate)
|
// DirectVoidMethod(EtesianEngine,etesian,runNegociate)
|
||||||
// DirectGetBoolAttribute(PyEtesianEngine_getToolSuccess,getToolSuccess,PyEtesianEngine,EtesianEngine)
|
// DirectGetBoolAttribute(PyEtesianEngine_getToolSuccess,getToolSuccess,PyEtesianEngine,EtesianEngine)
|
||||||
|
@ -271,6 +285,8 @@ extern "C" {
|
||||||
, "Build abstract interface in top cell for supply & blockages." }
|
, "Build abstract interface in top cell for supply & blockages." }
|
||||||
, { "doHFNS" , (PyCFunction)PyEtesianEngine_doHFNS , METH_NOARGS
|
, { "doHFNS" , (PyCFunction)PyEtesianEngine_doHFNS , METH_NOARGS
|
||||||
, "Perform the high fanout net synthesis." }
|
, "Perform the high fanout net synthesis." }
|
||||||
|
, { "addTrackAvoid" , (PyCFunction)PyEtesianEngine_addTrackAvoid , METH_VARARGS
|
||||||
|
, "Mark a vertical track under which no terminal should be present." }
|
||||||
, { "toHurricane" , (PyCFunction)PyEtesianEngine_toHurricane , METH_NOARGS
|
, { "toHurricane" , (PyCFunction)PyEtesianEngine_toHurricane , METH_NOARGS
|
||||||
, "Build the Hurricane post-placement manipulation structure." }
|
, "Build the Hurricane post-placement manipulation structure." }
|
||||||
, { "destroy" , (PyCFunction)PyEtesianEngine_destroy , METH_NOARGS
|
, { "destroy" , (PyCFunction)PyEtesianEngine_destroy , METH_NOARGS
|
||||||
|
|
|
@ -121,6 +121,7 @@ namespace Etesian {
|
||||||
inline ~BloatCells ();
|
inline ~BloatCells ();
|
||||||
bool select ( std::string );
|
bool select ( std::string );
|
||||||
Box getAb ( Occurrence );
|
Box getAb ( Occurrence );
|
||||||
|
inline const BloatCell* getSelected () const;
|
||||||
inline DbU::Unit getDxSpace () const;
|
inline DbU::Unit getDxSpace () const;
|
||||||
inline void resetDxSpace ();
|
inline void resetDxSpace ();
|
||||||
private:
|
private:
|
||||||
|
@ -155,6 +156,7 @@ namespace Etesian {
|
||||||
|
|
||||||
inline DbU::Unit BloatCells::getDxSpace () const { return _dxSpace; }
|
inline DbU::Unit BloatCells::getDxSpace () const { return _dxSpace; }
|
||||||
inline void BloatCells::resetDxSpace () { _dxSpace = 0; }
|
inline void BloatCells::resetDxSpace () { _dxSpace = 0; }
|
||||||
|
inline const BloatCell* BloatCells::getSelected () const { return _selected; }
|
||||||
|
|
||||||
|
|
||||||
} // Etesian namespace.
|
} // Etesian namespace.
|
||||||
|
|
|
@ -109,6 +109,7 @@ namespace Etesian {
|
||||||
inline Cell* getBlockCell () const;
|
inline Cell* getBlockCell () const;
|
||||||
inline Instance* getBlockInstance () const;
|
inline Instance* getBlockInstance () const;
|
||||||
inline const NetNameSet& getExcludedNets () const;
|
inline const NetNameSet& getExcludedNets () const;
|
||||||
|
inline const std::vector<Box>& getTrackAvoids () const;
|
||||||
inline void setBlock ( Instance* );
|
inline void setBlock ( Instance* );
|
||||||
inline void setFixedAbHeight ( DbU::Unit );
|
inline void setFixedAbHeight ( DbU::Unit );
|
||||||
inline void setFixedAbWidth ( DbU::Unit );
|
inline void setFixedAbWidth ( DbU::Unit );
|
||||||
|
@ -144,6 +145,7 @@ namespace Etesian {
|
||||||
void toHurricane ();
|
void toHurricane ();
|
||||||
void flattenPower ();
|
void flattenPower ();
|
||||||
inline void selectBloat ( std::string );
|
inline void selectBloat ( std::string );
|
||||||
|
inline void addTrackAvoid ( const Box& );
|
||||||
virtual Record* _getRecord () const;
|
virtual Record* _getRecord () const;
|
||||||
virtual std::string _getString () const;
|
virtual std::string _getString () const;
|
||||||
virtual std::string _getTypeName () const;
|
virtual std::string _getTypeName () const;
|
||||||
|
@ -157,6 +159,7 @@ namespace Etesian {
|
||||||
bool _ySpinSet;
|
bool _ySpinSet;
|
||||||
bool _flatDesign;
|
bool _flatDesign;
|
||||||
Box _placeArea;
|
Box _placeArea;
|
||||||
|
std::vector<Box> _trackAvoids;
|
||||||
coloquinte::box<coloquinte::int_t>* _surface;
|
coloquinte::box<coloquinte::int_t>* _surface;
|
||||||
coloquinte::netlist* _circuit;
|
coloquinte::netlist* _circuit;
|
||||||
coloquinte::placement_t* _placementLB;
|
coloquinte::placement_t* _placementLB;
|
||||||
|
@ -236,6 +239,14 @@ namespace Etesian {
|
||||||
inline Area* EtesianEngine::getArea () const { return _area; }
|
inline Area* EtesianEngine::getArea () const { return _area; }
|
||||||
inline const EtesianEngine::NetNameSet&
|
inline const EtesianEngine::NetNameSet&
|
||||||
EtesianEngine::getExcludedNets () const { return _excludedNets; }
|
EtesianEngine::getExcludedNets () const { return _excludedNets; }
|
||||||
|
inline const std::vector<Box>&
|
||||||
|
EtesianEngine::getTrackAvoids () const { return _trackAvoids; }
|
||||||
|
|
||||||
|
inline void EtesianEngine::addTrackAvoid ( const Box& box )
|
||||||
|
{
|
||||||
|
cdebug_log(121,0) << "EtesianEngine::trackAvoid() over " << box << std::endl;
|
||||||
|
_trackAvoids.push_back( box );
|
||||||
|
}
|
||||||
|
|
||||||
inline void EtesianEngine::setBlock ( Instance* block )
|
inline void EtesianEngine::setBlock ( Instance* block )
|
||||||
{
|
{
|
||||||
|
|
|
@ -219,7 +219,9 @@ namespace Etesian {
|
||||||
inline DbU::Unit getYBottom () const;
|
inline DbU::Unit getYBottom () const;
|
||||||
inline DbU::Unit getXMin () const;
|
inline DbU::Unit getXMin () const;
|
||||||
inline DbU::Unit getXMax () const;
|
inline DbU::Unit getXMax () const;
|
||||||
|
size_t getUsedVTracks ( const Tile& , std::set<DbU::Unit>& vtracks );
|
||||||
DbU::Unit getAverageChunk ( size_t& ) const;
|
DbU::Unit getAverageChunk ( size_t& ) const;
|
||||||
|
void trackAvoid ( DbU::Unit xTrack );
|
||||||
void insertTies ( DbU::Unit latchUpMax );
|
void insertTies ( DbU::Unit latchUpMax );
|
||||||
private:
|
private:
|
||||||
Slice* _slice;
|
Slice* _slice;
|
||||||
|
@ -257,6 +259,7 @@ namespace Etesian {
|
||||||
, size_t yspin );
|
, size_t yspin );
|
||||||
void buildSubSlices ();
|
void buildSubSlices ();
|
||||||
void showSubSlices ();
|
void showSubSlices ();
|
||||||
|
void trackAvoid ( DbU::Unit xTrack );
|
||||||
void insertTies ( DbU::Unit latchUpMax );
|
void insertTies ( DbU::Unit latchUpMax );
|
||||||
Instance* createDiodeUnder ( RoutingPad*, const Box&, DbU::Unit xHint );
|
Instance* createDiodeUnder ( RoutingPad*, const Box&, DbU::Unit xHint );
|
||||||
inline std::string _getString () const;
|
inline std::string _getString () const;
|
||||||
|
@ -296,6 +299,7 @@ namespace Etesian {
|
||||||
void addFeeds ();
|
void addFeeds ();
|
||||||
void buildSubSlices ();
|
void buildSubSlices ();
|
||||||
void showSubSlices ();
|
void showSubSlices ();
|
||||||
|
void trackAvoid ( const Box& trackAvoid );
|
||||||
void insertTies ( DbU::Unit latchUpMax );
|
void insertTies ( DbU::Unit latchUpMax );
|
||||||
Instance* createDiodeUnder ( RoutingPad*, const Box&, DbU::Unit xHint );
|
Instance* createDiodeUnder ( RoutingPad*, const Box&, DbU::Unit xHint );
|
||||||
inline std::string _getString () const;
|
inline std::string _getString () const;
|
||||||
|
|
|
@ -231,6 +231,7 @@ namespace Cfg {
|
||||||
|
|
||||||
bool Parameter::setInt ( int i, Priority priority )
|
bool Parameter::setInt ( int i, Priority priority )
|
||||||
{
|
{
|
||||||
|
std::cout.flush();
|
||||||
if ( not _updatePriority(priority) ) return false;
|
if ( not _updatePriority(priority) ) return false;
|
||||||
|
|
||||||
if ( (_type != Int) and (_type != Enumerate) )
|
if ( (_type != Int) and (_type != Enumerate) )
|
||||||
|
@ -353,11 +354,12 @@ namespace Cfg {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//cerr << " updated" << endl;
|
|
||||||
|
|
||||||
_value = svalue.str();
|
_value = svalue.str();
|
||||||
_onValueChanged();
|
_onValueChanged();
|
||||||
|
|
||||||
|
//cerr << " updated _value=\"" << _value << "\"" << endl;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
// -*- C++ -*-
|
||||||
|
//
|
||||||
|
// This file is part of the Coriolis Software.
|
||||||
|
// Copyright (c) Sorbonne Université 2008-2022, All Rights Reserved
|
||||||
|
//
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
// | C O R I O L I S |
|
||||||
|
// | I s o b a r - Hurricane / Python Interface |
|
||||||
|
// | |
|
||||||
|
// | Author : Jean-Paul CHAPUT |
|
||||||
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||||
|
// | =============================================================== |
|
||||||
|
// | C++ Module : "./PyAttributesHolder.cpp" |
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
#include "hurricane/isobar/PyAttributesHolder.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Isobar {
|
||||||
|
|
||||||
|
using namespace Hurricane;
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
|
||||||
|
// +=================================================================+
|
||||||
|
// | "PyAttributesHolder" Python Module Code Part |
|
||||||
|
// +=================================================================+
|
||||||
|
|
||||||
|
#if defined(__PYTHON_MODULE__)
|
||||||
|
|
||||||
|
|
||||||
|
static PyObject* PyAttributesHolder_NEW ( PyObject *module, PyObject *args )
|
||||||
|
{
|
||||||
|
cdebug_log(20,0) << "PyAttributesHolder_NEW()" << endl;
|
||||||
|
PyAttributesHolder* pyAttributeHolder = PyObject_NEW(PyAttributesHolder, &PyTypeAttributesHolder);
|
||||||
|
if (pyAttributeHolder == NULL) return NULL;
|
||||||
|
return ( (PyObject*)pyAttributeHolder );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int PyAttributesHolder_Init ( PyAttributesHolder* self, PyObject* args, PyObject* kwargs )
|
||||||
|
{
|
||||||
|
cdebug_log(20,0) << "PyAttributesHolder_Init(): " << (void*)self << endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PyMethodDef PyAttributesHolder_Methods[] =
|
||||||
|
{ {NULL, NULL, 0, NULL} /* sentinel */
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//DirectDeleteMethod(PyAttributesHolder_DeAlloc,PyAttributesHolder)
|
||||||
|
|
||||||
|
#else // End of Python Module Code Part.
|
||||||
|
|
||||||
|
|
||||||
|
// +=================================================================+
|
||||||
|
// | "PyAttributesHolder" Shared Library Code Part |
|
||||||
|
// +=================================================================+
|
||||||
|
|
||||||
|
|
||||||
|
PyTypeInheritedObjectDefinitions(AttributesHolder,PyList_Type)
|
||||||
|
|
||||||
|
# endif // End of Shared Library Code Part.
|
||||||
|
|
||||||
|
} // End of extern "C".
|
||||||
|
|
||||||
|
} // End of Isobar namespace.
|
||||||
|
|
|
@ -0,0 +1,48 @@
|
||||||
|
// -*- C++ -*-
|
||||||
|
//
|
||||||
|
// This file is part of the Coriolis Software.
|
||||||
|
// Copyright (c) Sorbonne Université 2022-2022, All Rights Reserved
|
||||||
|
//
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
// | C O R I O L I S |
|
||||||
|
// | I s o b a r - Hurricane / Python Interface |
|
||||||
|
// | |
|
||||||
|
// | Author : Jean-Paul CHAPUT |
|
||||||
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||||
|
// | =============================================================== |
|
||||||
|
// | C++ Header : "./hurricane/isobar/PyAttributesHolder.h" |
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include "hurricane/isobar/PyHurricane.h"
|
||||||
|
#include "hurricane/Box.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Isobar {
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Python Object : "PyAttributesHolder".
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
PyObject _base;
|
||||||
|
} PyAttributesHolder;
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Functions & Types exported to "PyHurricane.cpp".
|
||||||
|
|
||||||
|
extern PyTypeObject PyTypeAttributesHolder;
|
||||||
|
extern PyMethodDef PyAttributesHolder_Methods[];
|
||||||
|
|
||||||
|
|
||||||
|
#define IsPyAttributesHolder(v) ( (v)->ob_type == &PyTypeAttributesHolder )
|
||||||
|
#define PYATTRIBUTESHOLDER(v) ( (PyAttributesHolder*)(v) )
|
||||||
|
#define PYATTRIBUTESHOLDER_O(v) ( PYATTRIBUTESHOLDER(v)->_object )
|
||||||
|
|
||||||
|
|
||||||
|
} // extern "C".
|
||||||
|
|
||||||
|
} // Isobar namespace.
|
|
@ -0,0 +1,393 @@
|
||||||
|
// -*- C++ -*-
|
||||||
|
//
|
||||||
|
// This file is part of the Coriolis Software.
|
||||||
|
// Copyright (c) UPMC 2022-2022, All Rights Reserved
|
||||||
|
//
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
// | C O R I O L I S |
|
||||||
|
// | I s o b a r - Hurricane / Python Interface |
|
||||||
|
// | |
|
||||||
|
// | Author : Jean-Paul Chaput |
|
||||||
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||||
|
// | =============================================================== |
|
||||||
|
// | C++ Module : "./PythonProperties.cpp" |
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
#include "hurricane/isobar/PythonProperties.h"
|
||||||
|
#include <iomanip>
|
||||||
|
#include <ctime>
|
||||||
|
#include "hurricane/Error.h"
|
||||||
|
#include "hurricane/Warning.h"
|
||||||
|
#include "hurricane/Cell.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Isobar {
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
using Hurricane::Error;
|
||||||
|
using Hurricane::Warning;
|
||||||
|
using Hurricane::Property;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef PROPERTY_MAP_IMPLEMENTATION
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : "::PyObjectsMap".
|
||||||
|
|
||||||
|
ptrdiff_t PyObjectsMap::_offset = 0;
|
||||||
|
|
||||||
|
|
||||||
|
string PyObjectsMap::toPythonName ( std::string name )
|
||||||
|
{
|
||||||
|
if (name.substr(0,7) != "Python.") {
|
||||||
|
cerr << Error( "PyObjectsMap::toPythonName(): Python properties *must* start with \"Python.\"\n"
|
||||||
|
" (name \"%s\")"
|
||||||
|
, name.c_str() ) << endl;
|
||||||
|
return string();
|
||||||
|
}
|
||||||
|
return name.substr( 7 );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PyObjectsMap::PyObjectsMap ( PyObjectsProperty* property )
|
||||||
|
: _pyObjects()
|
||||||
|
{
|
||||||
|
if (not _offset) {
|
||||||
|
_offset = (ptrdiff_t)this - (ptrdiff_t)property;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PyObjectsMap::~PyObjectsMap ()
|
||||||
|
{
|
||||||
|
for ( auto item : _pyObjects ) {
|
||||||
|
Py_DECREF( item.second );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObjectsProperty* PyObjectsMap::getProperty () const
|
||||||
|
{ return reinterpret_cast<PyObjectsProperty*>( (ptrdiff_t)this - _offset ); }
|
||||||
|
|
||||||
|
|
||||||
|
DBo* PyObjectsMap::getOwner () const
|
||||||
|
{ return getProperty()->getOwner(); }
|
||||||
|
|
||||||
|
|
||||||
|
void PyObjectsMap::add ( std::string name, PyObject* object )
|
||||||
|
{
|
||||||
|
string pyPropName = toPythonName( name );
|
||||||
|
if (pyPropName.empty()) return;
|
||||||
|
|
||||||
|
auto imap = _pyObjects.find( name );
|
||||||
|
if (imap != _pyObjects.end()) {
|
||||||
|
cerr << Error( "PyObjectsMap::add(): Overwritting Python property \"%s\"\n"
|
||||||
|
" (name \"%s\")"
|
||||||
|
, name.c_str() ) << endl;
|
||||||
|
Py_DECREF( imap->second );
|
||||||
|
_pyObjects.erase( imap );
|
||||||
|
}
|
||||||
|
|
||||||
|
Py_INCREF( object );
|
||||||
|
_pyObjects.insert( make_pair(name,object) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PyObject* PyObjectsMap::get ( std::string name ) const
|
||||||
|
{
|
||||||
|
string pyPropName = toPythonName( name );
|
||||||
|
if (pyPropName.empty()) return NULL;
|
||||||
|
|
||||||
|
auto imap = _pyObjects.find( name );
|
||||||
|
if (imap == _pyObjects.end()) return NULL;
|
||||||
|
return imap->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PyObjectsMap::remove ( std::string name )
|
||||||
|
{
|
||||||
|
string pyPropName = toPythonName( name );
|
||||||
|
if (pyPropName.empty()) return;
|
||||||
|
|
||||||
|
auto imap = _pyObjects.find( name );
|
||||||
|
if (imap != _pyObjects.end()) {
|
||||||
|
Py_DECREF( imap->second );
|
||||||
|
_pyObjects.erase( imap );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
string PyObjectsMap::_getString () const
|
||||||
|
{
|
||||||
|
string s = "<PyObjectsMap " + getString(getOwner()) + ">";
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Record* PyObjectsMap::_getRecord () const
|
||||||
|
{
|
||||||
|
Record* record = new Record ( _getString() );
|
||||||
|
if (record != NULL) {
|
||||||
|
record->add( getSlot("_pyObjects", &_pyObjects) );
|
||||||
|
}
|
||||||
|
return record;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : "PyObjectsProperty"
|
||||||
|
|
||||||
|
Name PyObjectsProperty::_name = "Isobar::PyObjectsProperty";
|
||||||
|
|
||||||
|
|
||||||
|
PyObjectsProperty* PyObjectsProperty::create ( DBo* owner )
|
||||||
|
{
|
||||||
|
PyObjectsProperty *property = new PyObjectsProperty();
|
||||||
|
|
||||||
|
property->_postCreate ();
|
||||||
|
return property;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PyObjectsProperty::onReleasedBy ( DBo* owner )
|
||||||
|
{ PrivateProperty::onReleasedBy( owner ); }
|
||||||
|
|
||||||
|
|
||||||
|
Name PyObjectsProperty::getPropertyName ()
|
||||||
|
{ return _name; }
|
||||||
|
|
||||||
|
|
||||||
|
Name PyObjectsProperty::getName () const
|
||||||
|
{ return getPropertyName(); }
|
||||||
|
|
||||||
|
|
||||||
|
string PyObjectsProperty::_getTypeName () const
|
||||||
|
{ return "Isobar::PyObjectsProperty"; }
|
||||||
|
|
||||||
|
|
||||||
|
string PyObjectsProperty::_getString () const
|
||||||
|
{
|
||||||
|
string s = PrivateProperty::_getString ();
|
||||||
|
s.insert ( s.length() - 1 , " " + getString(&_pyObjectsMap) );
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Record* PyObjectsProperty::_getRecord () const
|
||||||
|
{
|
||||||
|
Record* record = PrivateProperty::_getRecord();
|
||||||
|
if ( record ) {
|
||||||
|
record->add( getSlot( "_name" , _name ) );
|
||||||
|
record->add( getSlot( "_pyObjectsMap", &_pyObjectsMap ) );
|
||||||
|
}
|
||||||
|
return record;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : "PythonProperties"
|
||||||
|
|
||||||
|
std::vector<PyObjectsProperty*> PythonProperties::_allocateds;
|
||||||
|
|
||||||
|
|
||||||
|
PyObjectsMap* PythonProperties::getMap ( const DBo* dbo )
|
||||||
|
{
|
||||||
|
Property* property = dbo->getProperty( PyObjectsProperty::getPropertyName() );
|
||||||
|
if (property)
|
||||||
|
return static_cast<PyObjectsProperty*>( property )->getMap();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PyObjectsMap* PythonProperties::create ( DBo* dbo )
|
||||||
|
{
|
||||||
|
PyObjectsProperty* property = static_cast<PyObjectsProperty*>
|
||||||
|
( dbo->getProperty( PyObjectsProperty::getPropertyName() ));
|
||||||
|
if (not property) {
|
||||||
|
property = PyObjectsProperty::create( dbo );
|
||||||
|
dbo->put( property );
|
||||||
|
_allocateds.push_back( property );
|
||||||
|
}
|
||||||
|
return property->getMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PythonProperties::destroy ( DBo* dbo )
|
||||||
|
{
|
||||||
|
Property* property = dbo->getProperty( PyObjectsProperty::getPropertyName() );
|
||||||
|
if (property) {
|
||||||
|
dbo->remove( property );
|
||||||
|
for ( size_t i=0 ; i<_allocateds.size(); ++i ) {
|
||||||
|
if (_allocateds[i] == property) {
|
||||||
|
_allocateds[i] = _allocateds[ _allocateds.size() - 1 ];
|
||||||
|
_allocateds.resize( _allocateds.size() - 1 );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PythonProperties::removeAll ( std::string name )
|
||||||
|
{
|
||||||
|
if (_allocateds.empty()) return;
|
||||||
|
|
||||||
|
size_t removeds = 0;
|
||||||
|
if (not name.empty()) {
|
||||||
|
for ( size_t i=0 ; i+removeds<_allocateds.size() ; ) {
|
||||||
|
PyObjectsMap* pyMap = _allocateds[i]->getMap();
|
||||||
|
pyMap->remove( name );
|
||||||
|
if (pyMap->empty()) {
|
||||||
|
_allocateds[i]->getOwner()->remove( _allocateds[i] );
|
||||||
|
++removeds;
|
||||||
|
_allocateds[i] = _allocateds[ _allocateds.size()-removeds ];
|
||||||
|
} else
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
if (removeds)
|
||||||
|
_allocateds.resize( _allocateds.size() - removeds );
|
||||||
|
} else {
|
||||||
|
for ( size_t i=0 ; i<_allocateds.size() ; ++i ) {
|
||||||
|
_allocateds[i]->getOwner()->remove( _allocateds[i] );
|
||||||
|
}
|
||||||
|
_allocateds.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : "PyObjectsProperty"
|
||||||
|
|
||||||
|
Name PyObjectsProperty::_name = "Isobar::PyObjectsProperty";
|
||||||
|
|
||||||
|
|
||||||
|
PyObjectsProperty* PyObjectsProperty::create ( DBo* owner )
|
||||||
|
{
|
||||||
|
PyObjectsProperty *property = new PyObjectsProperty();
|
||||||
|
|
||||||
|
property->_postCreate ();
|
||||||
|
return property;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PyObjectsProperty::_preDestroy ()
|
||||||
|
{
|
||||||
|
Py_DECREF( _pyObject );
|
||||||
|
Super::_preDestroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PyObjectsProperty::onReleasedBy ( DBo* owner )
|
||||||
|
{ PrivateProperty::onReleasedBy( owner ); }
|
||||||
|
|
||||||
|
|
||||||
|
Name PyObjectsProperty::getPropertyName ()
|
||||||
|
{ return _name; }
|
||||||
|
|
||||||
|
|
||||||
|
Name PyObjectsProperty::getName () const
|
||||||
|
{ return getPropertyName(); }
|
||||||
|
|
||||||
|
|
||||||
|
string PyObjectsProperty::_getTypeName () const
|
||||||
|
{ return "Isobar::PyObjectsProperty"; }
|
||||||
|
|
||||||
|
|
||||||
|
string PyObjectsProperty::_getString () const
|
||||||
|
{
|
||||||
|
string s = PrivateProperty::_getString ();
|
||||||
|
s.insert ( s.length() - 1 , " " + getString(_pyObject) );
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Record* PyObjectsProperty::_getRecord () const
|
||||||
|
{
|
||||||
|
Record* record = PrivateProperty::_getRecord();
|
||||||
|
if ( record ) {
|
||||||
|
record->add( getSlot( "_name" , _name ) );
|
||||||
|
record->add( getSlot( "_pyObject", _pyObject ) );
|
||||||
|
}
|
||||||
|
return record;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : "PythonProperties"
|
||||||
|
|
||||||
|
std::vector<PyObjectsProperty*> PythonProperties::_allocateds;
|
||||||
|
|
||||||
|
|
||||||
|
PyObject* PythonProperties::get ( const DBo* dbo )
|
||||||
|
{
|
||||||
|
Property* property = dbo->getProperty( PyObjectsProperty::getPropertyName() );
|
||||||
|
if (property)
|
||||||
|
return property->getHolder();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
PyObject* PythonProperties::create ( DBo* dbo )
|
||||||
|
{
|
||||||
|
PyObjectsProperty* property = static_cast<PyObjectsProperty*>
|
||||||
|
( dbo->getProperty( PyObjectsProperty::getPropertyName() ));
|
||||||
|
if (not property) {
|
||||||
|
property = PyObjectsProperty::create( dbo );
|
||||||
|
dbo->put( property );
|
||||||
|
_allocateds.push_back( property );
|
||||||
|
}
|
||||||
|
return property->getPyObject();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PythonProperties::destroy ( DBo* dbo )
|
||||||
|
{
|
||||||
|
Property* property = dbo->getProperty( PyObjectsProperty::getPropertyName() );
|
||||||
|
if (property) {
|
||||||
|
dbo->remove( property );
|
||||||
|
for ( size_t i=0 ; i<_allocateds.size(); ++i ) {
|
||||||
|
if (_allocateds[i] == property) {
|
||||||
|
_allocateds[i] = _allocateds[ _allocateds.size() - 1 ];
|
||||||
|
_allocateds.resize( _allocateds.size() - 1 );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PythonProperties::removeAll ( std::string name )
|
||||||
|
{
|
||||||
|
if (_allocateds.empty()) return;
|
||||||
|
|
||||||
|
size_t removeds = 0;
|
||||||
|
if (not name.empty()) {
|
||||||
|
for ( size_t i=0 ; i+removeds<_allocateds.size() ; ) {
|
||||||
|
// PyObject* pyObject = _allocateds[i]->getPyObject();
|
||||||
|
// pyMap->remove( name );
|
||||||
|
// if (pyMap->empty()) {
|
||||||
|
// _allocateds[i]->getOwner()->remove( _allocateds[i] );
|
||||||
|
// ++removeds;
|
||||||
|
// _allocateds[i] = _allocateds[ _allocateds.size()-removeds ];
|
||||||
|
// } else
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
if (removeds)
|
||||||
|
_allocateds.resize( _allocateds.size() - removeds );
|
||||||
|
} else {
|
||||||
|
for ( size_t i=0 ; i<_allocateds.size() ; ++i ) {
|
||||||
|
_allocateds[i]->getOwner()->remove( _allocateds[i] );
|
||||||
|
}
|
||||||
|
_allocateds.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
} // Isobar namespace.
|
|
@ -0,0 +1,205 @@
|
||||||
|
// -*- C++ -*-
|
||||||
|
//
|
||||||
|
// This file is part of the Coriolis Software.
|
||||||
|
// Copyright (c) Sorbonne Université 2022-2022, All Rights Reserved
|
||||||
|
//
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
// | C O R I O L I S |
|
||||||
|
// | I s o b a r - Hurricane / Python Interface |
|
||||||
|
// | |
|
||||||
|
// | Author : Jean-Paul Chaput |
|
||||||
|
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||||
|
// | =============================================================== |
|
||||||
|
// | C++ Header : "./hurricane/isobar/PythonProperties.h" |
|
||||||
|
// +-----------------------------------------------------------------+
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <Python.h>
|
||||||
|
#include <string>
|
||||||
|
#include "hurricane/Name.h"
|
||||||
|
#include "hurricane/Property.h"
|
||||||
|
#include "hurricane/Slot.h"
|
||||||
|
#include "hurricane/DBo.h"
|
||||||
|
#include "hurricane/isobar/PyAttributesHolder.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace Isobar {
|
||||||
|
|
||||||
|
using Hurricane::Record;
|
||||||
|
using Hurricane::Name;
|
||||||
|
using Hurricane::DBo;
|
||||||
|
using Hurricane::PrivateProperty;
|
||||||
|
class PyObjectsProperty;
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef PROPERTY_MAP_IMPLEMENTATION
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : "Isobar::PyObjectsMap".
|
||||||
|
|
||||||
|
class PyObjectsMap {
|
||||||
|
public:
|
||||||
|
static std::string toPythonName ( std::string );
|
||||||
|
public:
|
||||||
|
PyObjectsMap ( PyObjectsProperty* );
|
||||||
|
~PyObjectsMap ();
|
||||||
|
inline bool empty () const;
|
||||||
|
PyObjectsProperty* getProperty () const;
|
||||||
|
DBo* getOwner () const;
|
||||||
|
void add ( std::string, PyObject* );
|
||||||
|
PyObject* get ( std::string ) const;
|
||||||
|
void remove ( std::string );
|
||||||
|
std::string _getString () const;
|
||||||
|
Record* _getRecord () const;
|
||||||
|
private:
|
||||||
|
static std::ptrdiff_t _offset;
|
||||||
|
std::map<std::string,PyObject*> _pyObjects;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
inline bool PyObjectsMap::empty () const { return _pyObjects.empty(); }
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : "Isobar::PyObjectsProperty".
|
||||||
|
|
||||||
|
class PyObjectsProperty : public Hurricane::PrivateProperty {
|
||||||
|
friend class PythonProperties;
|
||||||
|
public:
|
||||||
|
static Name _name;
|
||||||
|
public:
|
||||||
|
static PyObjectsProperty* create ( DBo* );
|
||||||
|
static Name getPropertyName ();
|
||||||
|
virtual Name getName () const;
|
||||||
|
inline PyObjectsMap* getMap ();
|
||||||
|
virtual void onReleasedBy ( DBo* owner );
|
||||||
|
virtual std::string _getTypeName () const;
|
||||||
|
virtual std::string _getString () const;
|
||||||
|
virtual Record* _getRecord () const;
|
||||||
|
protected:
|
||||||
|
// Attributes.
|
||||||
|
PyObjectsMap _pyObjectsMap;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Constructor.
|
||||||
|
inline PyObjectsProperty ();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
inline PyObjectsProperty::PyObjectsProperty ()
|
||||||
|
: PrivateProperty(), _pyObjectsMap(this)
|
||||||
|
{ }
|
||||||
|
|
||||||
|
|
||||||
|
inline PyObjectsMap* PyObjectsProperty::getMap () { return &_pyObjectsMap; }
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : "Isobar::PythonProperties".
|
||||||
|
|
||||||
|
class PythonProperties {
|
||||||
|
public:
|
||||||
|
static PyObjectsMap* getMap ( const DBo* );
|
||||||
|
static PyObjectsMap* create ( DBo* );
|
||||||
|
static void destroy ( DBo* );
|
||||||
|
static inline PyObject* get ( const DBo*, std::string );
|
||||||
|
static inline void add ( DBo*, std::string, PyObject* );
|
||||||
|
static inline void remove ( DBo*, std::string );
|
||||||
|
static void removeAll ( std::string );
|
||||||
|
private:
|
||||||
|
static std::vector<PyObjectsProperty*> _allocateds;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
inline PyObject* PythonProperties::get ( const DBo* dbo, std::string name )
|
||||||
|
{
|
||||||
|
PyObjectsMap* pyMap = getMap( dbo );
|
||||||
|
return (pyMap == nullptr) ? nullptr : pyMap->get( name );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void PythonProperties::add ( DBo* dbo, std::string name, PyObject* pyObject )
|
||||||
|
{
|
||||||
|
PyObjectsMap* pyMap = getMap( dbo );
|
||||||
|
if (pyMap == nullptr)
|
||||||
|
pyMap = create( dbo );
|
||||||
|
pyMap->add( name, pyObject );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void PythonProperties::remove ( DBo* dbo, std::string name )
|
||||||
|
{
|
||||||
|
PyObjectsMap* pyMap = getMap( dbo );
|
||||||
|
if (pyMap == nullptr) return;
|
||||||
|
pyMap->remove( name );
|
||||||
|
if (pyMap->empty()) {
|
||||||
|
destroy( dbo );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : "Isobar::PyObjectsProperty".
|
||||||
|
|
||||||
|
class PyObjectsProperty : public Hurricane::PrivateProperty {
|
||||||
|
friend class PythonProperties;
|
||||||
|
public:
|
||||||
|
typedef Hurricane::PrivateProperty Super;
|
||||||
|
static Name _name;
|
||||||
|
public:
|
||||||
|
static PyObjectsProperty* create ( DBo* );
|
||||||
|
static Name getPropertyName ();
|
||||||
|
virtual Name getName () const;
|
||||||
|
inline PyObject* getPyObject ();
|
||||||
|
virtual void onReleasedBy ( DBo* owner );
|
||||||
|
virtual std::string _getTypeName () const;
|
||||||
|
virtual std::string _getString () const;
|
||||||
|
virtual Record* _getRecord () const;
|
||||||
|
protected:
|
||||||
|
virtual void _preDestroy ();
|
||||||
|
protected:
|
||||||
|
// Attributes.
|
||||||
|
PyObject* _pyObject;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Constructor.
|
||||||
|
inline PyObjectsProperty ();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
inline PyObjectsProperty::PyObjectsProperty ()
|
||||||
|
: PrivateProperty(), _pyObject(NULL)
|
||||||
|
{
|
||||||
|
_pyObject = (PyObject*)PyObject_NEW( PyAttributesHolder, &PyTypeAttributesHolder );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline PyObject* PyObjectsProperty::getPyObject () { return _pyObject; }
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Class : "Isobar::PythonProperties".
|
||||||
|
|
||||||
|
class PythonProperties {
|
||||||
|
public:
|
||||||
|
static PyObject* get ( const DBo* );
|
||||||
|
static PyObject* create ( DBo* );
|
||||||
|
static void destroy ( DBo* );
|
||||||
|
static void removeAll ( std::string );
|
||||||
|
private:
|
||||||
|
static std::vector<PyObjectsProperty*> _allocateds;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
} // Isobar Namespace.
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef PROPERTY_MAP_IMPLEMENTATION
|
||||||
|
INSPECTOR_P_SUPPORT(Isobar::PyObjectsMap);
|
||||||
|
INSPECTOR_P_SUPPORT(Isobar::PyObjectsProperty);
|
||||||
|
#endif
|
|
@ -1,7 +1,7 @@
|
||||||
// -*- mode: C++; explicit-buffer-name: "GlobalRoute.cpp<katana>" -*-
|
// -*- mode: C++; explicit-buffer-name: "GlobalRoute.cpp<katana>" -*-
|
||||||
//
|
//
|
||||||
// This file is part of the Coriolis Software.
|
// This file is part of the Coriolis Software.
|
||||||
// Copyright (c) UPMC 2016-2018, All Rights Reserved
|
// Copyright (c) Sorbonne Université 2016-2022, All Rights Reserved
|
||||||
//
|
//
|
||||||
// +-----------------------------------------------------------------+
|
// +-----------------------------------------------------------------+
|
||||||
// | C O R I O L I S |
|
// | C O R I O L I S |
|
||||||
|
|
Loading…
Reference in New Issue