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_2G_1PinM3:
|
||||
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_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 ()
|
||||
{
|
||||
throw Error ( "%s::_do_3G_xM1_1PinM3() method *not* reimplemented from base class.", getTypeName().c_str() );
|
||||
|
|
|
@ -266,11 +266,10 @@ namespace Anabatic {
|
|||
} else {
|
||||
currContact = AutoContactTurn::create( getGCell(), getNet(), Session::getContactLayer(0) );
|
||||
}
|
||||
AutoSegment::create( currTerm, currContact, Flags::Vertical );
|
||||
} else {
|
||||
currContact = AutoContactHTee::create( getGCell(), getNet(), Session::getContactLayer(0) );
|
||||
}
|
||||
|
||||
AutoSegment::create( currTerm , currContact, Flags::Vertical );
|
||||
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 )
|
||||
{
|
||||
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_1G_1M3 ();
|
||||
virtual bool _do_xG_xM3 ();
|
||||
virtual bool _do_1G_xM1_1PinM1 ();
|
||||
virtual bool _do_1G_xM1_1PinM2 ();
|
||||
virtual bool _do_2G_xM1_1PinM2 ();
|
||||
virtual bool _do_1G_1M1_1PinM3 ();
|
||||
|
@ -344,6 +345,8 @@ namespace Anabatic {
|
|||
, Conn_1G_1PinM2 = CONNEXITY_VALUE( 1, 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_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_2M1_1PinM2 = CONNEXITY_VALUE( 1, 2, 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_1M1_1M2 ();
|
||||
virtual bool _do_xG_xM1_xM3 ();
|
||||
virtual bool _do_1G_xM1_1PinM1 ();
|
||||
virtual bool _do_1G_xM1_1PinM2 ();
|
||||
// virtual bool _do_4G_1M2 ();
|
||||
virtual bool _do_2G ();
|
||||
|
|
|
@ -161,6 +161,7 @@ class Side ( object ):
|
|||
check for out of bounds coordinates.
|
||||
"""
|
||||
|
||||
trace( 550, '\tSide.place() {}\n'.format(ioPin) )
|
||||
status = 0
|
||||
if self.side & (IoPin.NORTH | IoPin.SOUTH):
|
||||
gauge = self.conf.vDeepRG
|
||||
|
@ -298,6 +299,7 @@ class Block ( object ):
|
|||
Create a Block object. The only parameter ``conf`` must be a BlockConf
|
||||
object which contains the complete block configuration.
|
||||
"""
|
||||
conf._postInit()
|
||||
self.flags = 0
|
||||
self.conf = conf
|
||||
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.
|
||||
(mainly due to Pins outside the side range)
|
||||
"""
|
||||
trace( 550, ',+', '\tBlock.placeIoPins().\n' )
|
||||
faileds = 0
|
||||
with UpdateSession():
|
||||
for ioPin in self.conf.ioPins:
|
||||
|
@ -625,6 +628,7 @@ class Block ( object ):
|
|||
elif ioPin.flags & IoPin.EAST: side = self.sides[IoPin.EAST ]
|
||||
else: side = self.sides[IoPin.WEST ]
|
||||
faileds += side.place( ioPin )
|
||||
trace( 550, ',-' )
|
||||
if faileds:
|
||||
raise ErrorMessage( 3, 'Block.placeIoPins(): Cell "{}" has {} badly placed pins.' \
|
||||
.format(self.conf.cell.getName(),faileds) )
|
||||
|
@ -846,6 +850,8 @@ class Block ( object ):
|
|||
break
|
||||
self.splitHTrees()
|
||||
self.spares.removeUnusedBuffers()
|
||||
for trackAvoid in self.conf.trackAvoids:
|
||||
self.etesian.addTrackAvoid( trackAvoid )
|
||||
self.etesian.toHurricane()
|
||||
self.etesian.flattenPower()
|
||||
if self.conf.isCoreBlock: self.doConnectCore()
|
||||
|
|
|
@ -135,8 +135,11 @@ class GaugeConf ( object ):
|
|||
|
||||
def _loadRoutingGauge ( self ):
|
||||
trace( 550, ',+', '\tGaugeConf._loadRoutingGauge()\n' )
|
||||
gaugeName = Cfg.getParamString('anabatic.routingGauge').asString()
|
||||
self._cellGauge = CRL.AllianceFramework.get().getCellGauge( gaugeName )
|
||||
gaugeName = Cfg.getParamString('anabatic.routingGauge').asString()
|
||||
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 )
|
||||
|
||||
if not self._routingGauge:
|
||||
|
@ -882,8 +885,8 @@ class BufferConf ( object ):
|
|||
instance = Instance.create( cell, 'spare_buffer_{}'.format(self.count), self.masterCell )
|
||||
trace( 550, '\tBufferConf.createBuffer(): cell={}, instance={}\n' \
|
||||
.format( cell, instance ))
|
||||
trace( 550, '\tplug={}\n'.format( instance.getPlug( self.masterCell.getNet('q') ) ))
|
||||
trace( 550, '\tplug.getCell()={}\n'.format( instance.getPlug( self.masterCell.getNet('q') ).getCell() ))
|
||||
trace( 550, '\tplug={}\n'.format( instance.getPlug( self.masterCell.getNet(self.output) ) ))
|
||||
trace( 550, '\tplug.getCell()={}\n'.format( instance.getPlug( self.masterCell.getNet(self.output) ).getCell() ))
|
||||
self.count += 1
|
||||
return instance
|
||||
|
||||
|
@ -988,9 +991,11 @@ class FeedsConf ( object ):
|
|||
trace( 550, ',+', '\tFeedsConf.__init__()\n' )
|
||||
cfg.etesian.feedNames = None
|
||||
cfg.etesian.latchUpDistance = None
|
||||
cfg.etesian.defaultFeed = None
|
||||
feeds = cfg.etesian.feedNames.split(',')
|
||||
self.count = 0
|
||||
self.feeds = []
|
||||
self.count = 0
|
||||
self.feeds = []
|
||||
self.defaultFeed = 0
|
||||
for feedName in feeds:
|
||||
feedCell = framework.getCell( feedName, CRL.Catalog.State.Views )
|
||||
if not feedCell:
|
||||
|
@ -1006,16 +1011,20 @@ class FeedsConf ( object ):
|
|||
for i in range(len(self.feeds)):
|
||||
trace( 550, '\t[{:>2}] {:>10} {}\n' \
|
||||
.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, '-' )
|
||||
return
|
||||
|
||||
def tieWidth ( self ):
|
||||
"""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
|
||||
|
||||
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
|
||||
return instance
|
||||
|
||||
|
@ -1152,6 +1161,14 @@ class IoPin ( object ):
|
|||
s += 'IoPin.'+name
|
||||
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 ):
|
||||
"""
|
||||
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.framework = CRL.AllianceFramework.get()
|
||||
self.cfg = CfgCache('',Cfg.Parameter.Priority.Interactive)
|
||||
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 )
|
||||
self.chipConf = ChipConf( self )
|
||||
self.bufferConf = None
|
||||
self.constantsConf = None
|
||||
self.feedsConf = None
|
||||
self.powersConf = None
|
||||
self.chipConf = None
|
||||
self.bColumns = 2
|
||||
self.bRows = 2
|
||||
self.sparesTies = True
|
||||
self.cloneds = []
|
||||
self.cell = cell
|
||||
self.icore = None
|
||||
|
@ -1324,22 +1342,33 @@ class BlockConf ( GaugeConf ):
|
|||
self.hTreeDatas = [ ]
|
||||
self.useHFNS = False
|
||||
self.useSpares = True
|
||||
self.trackAvoids = []
|
||||
self.isBuilt = False
|
||||
self.useHarness = False
|
||||
self.ioPins = []
|
||||
self.ioPinsCounts = {}
|
||||
for ioPinSpec in ioPins:
|
||||
self.ioPins.append( IoPin( *ioPinSpec ) )
|
||||
for line in range(len(ioPads)):
|
||||
self.chipConf.addIoPad( ioPads[line], line )
|
||||
self.ioPinsArg = ioPins
|
||||
self.ioPadsArg = ioPads
|
||||
self.cfg.etesian.aspectRatio = None
|
||||
self.cfg.etesian.spaceMargin = None
|
||||
self.cfg.etesian.latchUpDistance = None
|
||||
self.cfg.block.spareSide = None
|
||||
self.cfg.block.vRailsPeriod = None
|
||||
self.cfg.katana.dumpMeasures = None
|
||||
self.etesian = None
|
||||
self.katana = None
|
||||
self.chipConf = ChipConf( self )
|
||||
self.etesian = 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
|
||||
def isCoreBlock ( self ): return self.chip is not None
|
||||
|
@ -1437,6 +1466,10 @@ class BlockConf ( GaugeConf ):
|
|||
.format(netName)) )
|
||||
return
|
||||
self.hTreeDatas.append( [ netName, flags ] );
|
||||
|
||||
def addTrackAvoid ( self, trackAvoid ):
|
||||
if self.cfg.anabatic.netBuilderStyle == 'VH,2RL':
|
||||
self.trackAvoids.append( trackAvoid )
|
||||
|
||||
def save ( self, flags ):
|
||||
"""
|
||||
|
|
|
@ -100,6 +100,7 @@ class HTree ( object ):
|
|||
return True
|
||||
|
||||
def _connectLeaf ( self, leaf, ckNet, forkContact, contact, x, y ):
|
||||
trace( 550, ',+', '\tHTree.connectLeaf() contact={}\n'.format( contact ))
|
||||
gaugeConf = self.spares.conf
|
||||
bufferConf = self.spares.conf.bufferConf
|
||||
hLeafDepth = gaugeConf.horizontalDepth
|
||||
|
@ -107,20 +108,24 @@ class HTree ( object ):
|
|||
hLeafDepth = gaugeConf.horizontalDepth - 2
|
||||
gaugeConf.setStackPosition( contact, x, y )
|
||||
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:
|
||||
tl1Contact = gaugeConf.rpAccessByPlugName( leaf.buffers[1], bufferConf.input , ckNet, GaugeConf.DeepDepth|GaugeConf.HAccess )
|
||||
tl2Contact = gaugeConf.rpAccessByPlugName( leaf.buffers[2], bufferConf.input , ckNet )
|
||||
tl1Contact = gaugeConf.rpAccessByPlugName( leaf.buffers[1], bufferConf.input, ckNet, GaugeConf.DeepDepth|GaugeConf.HAccess )
|
||||
tl2Contact = gaugeConf.rpAccessByPlugName( leaf.buffers[2], bufferConf.input, ckNet )
|
||||
tl2Y = gaugeConf.getTrack( tl2Contact.getY(), hLeafDepth, 2 )
|
||||
left1X = gaugeConf.getNearestVerticalTrack( tl1Contact.getX(), 0, 0 )
|
||||
left1Y = gaugeConf.getStackY( contact, GaugeConf.DeepDepth )
|
||||
trace( 550, '\tleft1Y: {}\n'.format( DbU.getValueString(left1Y) ))
|
||||
dxLeft = contact.getX() - gaugeConf.getStackX( contact, GaugeConf.DeepDepth )
|
||||
trace( 550, '\ttl2Contact: {}\n'.format( tl2Contact ))
|
||||
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.createHorizontal( contact , tl1Contact, left1Y , GaugeConf.DeepDepth|GaugeConf.SourceExtend )
|
||||
gaugeConf.createHorizontal( contact , tl1Contact, left1Y , GaugeConf.DeepDepth, dxLeft )
|
||||
gaugeConf.createVertical ( contact , tl2Contact, x, 0 )
|
||||
trace( 550, ',-' )
|
||||
|
||||
def _rrouteHTree ( self, qt ):
|
||||
"""
|
||||
|
@ -211,8 +216,10 @@ class HTree ( object ):
|
|||
if qt.bl:
|
||||
trace( 550, '\tConnect BL leaf, leftX={} blY={}\n'.format( DbU.getValueString(leftX), DbU.getValueString(blY) ))
|
||||
self._connectLeaf( qt.bl, ckNet, leftContact, blContact, leftX, blY )
|
||||
#gaugeConf.addTrackAvoid( Box( leftX, leftSourceY, leftX, blY ) )
|
||||
if qt.tr:
|
||||
self._connectLeaf( qt.tr, ckNet, rightContact, trContact, rightX, tlY )
|
||||
#gaugeConf.addTrackAvoid( Box( rightX, rightSourceY, rightX, tlY ) )
|
||||
if qt.br:
|
||||
self._connectLeaf( qt.br, ckNet, rightContact, brContact, rightX, blY )
|
||||
if qt.isRoot():
|
||||
|
|
|
@ -146,8 +146,10 @@ class BufferPool ( object ):
|
|||
yoffset = self.quadTree.spares.conf.icore.getTransformation().getTy()
|
||||
conf = self.quadTree.spares.conf
|
||||
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
|
||||
if conf.sparesTies:
|
||||
poolHalfWidth += conf.feedsConf.tieWidth()
|
||||
x = self.quadTree.spares.toXPitch( self.quadTree.area.getXCenter() - poolHalfWidth )
|
||||
y = self.quadTree.spares.toYSlice( self.quadTree.area.getYCenter() - poolHalfHeight )
|
||||
slice = (y - yoffset) // sliceHeight
|
||||
|
@ -159,11 +161,14 @@ class BufferPool ( object ):
|
|||
if (slice+row)%2:
|
||||
orientation = Transformation.Orientation.MY
|
||||
y += sliceHeight
|
||||
length = 0
|
||||
for column in range(self.columns+2):
|
||||
length = 0
|
||||
tieCols = 0
|
||||
if conf.sparesTies:
|
||||
tieCols = 2
|
||||
for column in range(self.columns+tieCols):
|
||||
transf = Transformation( x + length, y, orientation )
|
||||
if (column > 0) and (column <= self.columns):
|
||||
index = self.toIndex(column-1,row)
|
||||
if (not conf.sparesTies) or ((column > 0) and (column <= self.columns)):
|
||||
index = self.toIndex(column-tieCols//2,row)
|
||||
instance = conf.createBuffer()
|
||||
self.buffers[ index ][1] = instance
|
||||
trace( 540, '\tBuffer[{}]: {} @{}\n'.format(index,self.buffers[index],transf) )
|
||||
|
@ -845,6 +850,7 @@ class QuadTree ( object ):
|
|||
coreTransf = self.spares.conf.icore.getTransformation()
|
||||
maxSinks = self.spares.conf.bufferConf.maxSinks
|
||||
#maxSinks = 7
|
||||
trace( 540, '\tconf.bufferConf.maxSinks={}\n'.format(maxSinks) )
|
||||
plugOccsByAngle = []
|
||||
areaCenter = self.area.getCenter()
|
||||
#coreTransf.applyOn( areaCenter )
|
||||
|
|
|
@ -519,6 +519,7 @@ class CoreToChip ( object ):
|
|||
.format( core.getName() )
|
||||
] )
|
||||
conf = block.state
|
||||
conf._postInit()
|
||||
self.conf = conf
|
||||
self.conf.useHarness = False
|
||||
self.ringNetNames = []
|
||||
|
|
|
@ -158,14 +158,18 @@ namespace Etesian {
|
|||
|
||||
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;
|
||||
for ( Net* net : cell->getNets() ) {
|
||||
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;
|
||||
float termRatio = (float)terminals / (float)(ab.getWidth() / vpitch);
|
||||
if (termRatio > 0.8) extra += 1;
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
// -*- C++ -*-
|
||||
//
|
||||
// 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 |
|
||||
// | 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 |
|
||||
// | E-mail : Jean-Paul.Chaput@asim.lip6.fr |
|
||||
// | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||
// | =============================================================== |
|
||||
// | C++ Module : "./EtesianEngine.cpp" |
|
||||
// +-----------------------------------------------------------------+
|
||||
|
@ -46,6 +46,7 @@
|
|||
#include "hurricane/viewer/CellViewer.h"
|
||||
#include "crlcore/Utilities.h"
|
||||
#include "crlcore/Measures.h"
|
||||
#include "crlcore/Histogram.h"
|
||||
#include "crlcore/AllianceFramework.h"
|
||||
#include "etesian/EtesianEngine.h"
|
||||
|
||||
|
@ -302,6 +303,7 @@ namespace Etesian {
|
|||
, _ySpinSet (false)
|
||||
, _flatDesign (false)
|
||||
, _placeArea (cell->getAbutmentBox())
|
||||
, _trackAvoids ()
|
||||
, _surface (NULL)
|
||||
, _circuit (NULL)
|
||||
, _placementLB (NULL)
|
||||
|
@ -709,6 +711,14 @@ namespace Etesian {
|
|||
DbU::Unit sliceHeight = getSliceHeight();
|
||||
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 << ::Dots::asString(" - H-pitch" , DbU::getValueString(hpitch)) << 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 );
|
||||
stdCellSizes.addSample( (float)(instanceAb.getWidth() / vpitch), 1 );
|
||||
|
||||
Transformation instanceTransf = instance->getTransformation();
|
||||
occurrence.getPath().getTransformation().applyOn( instanceTransf );
|
||||
|
@ -1067,6 +1079,11 @@ namespace Etesian {
|
|||
}
|
||||
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 ();
|
||||
_surface = new box<int_t>( (int_t)(topAb.getXMin() / vpitch)
|
||||
, (int_t)(topAb.getXMax() / vpitch)
|
||||
|
|
|
@ -23,6 +23,8 @@
|
|||
#include "hurricane/DeepNet.h"
|
||||
#include "hurricane/Plug.h"
|
||||
#include "hurricane/RoutingPad.h"
|
||||
#include "hurricane/Vertical.h"
|
||||
#include "hurricane/NetExternalComponents.h"
|
||||
#include "hurricane/Path.h"
|
||||
#include "hurricane/Library.h"
|
||||
#include "hurricane/viewer/CellWidget.h"
|
||||
|
@ -43,9 +45,12 @@ namespace Etesian {
|
|||
using Hurricane::Transformation;
|
||||
using Hurricane::DataBase;
|
||||
using Hurricane::Library;
|
||||
using Hurricane::Component;
|
||||
using Hurricane::DeepNet;
|
||||
using Hurricane::Plug;
|
||||
using Hurricane::RoutingPad;
|
||||
using Hurricane::Vertical;
|
||||
using Hurricane::NetExternalComponents;
|
||||
using Hurricane::DebugSession;
|
||||
using Hurricane::UpdateSession;
|
||||
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 )
|
||||
{
|
||||
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 iend = (flatAb.getYMax()-_placeArea.getYMin()) / _sliceHeight;
|
||||
|
||||
for ( size_t islice=ibegin ; islice<iend ; ++islice ) {
|
||||
_slices[islice]->merge( occurrence, flatAb );
|
||||
}
|
||||
|
@ -544,6 +562,29 @@ namespace Etesian {
|
|||
{ 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 )
|
||||
{
|
||||
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
|
||||
{
|
||||
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 )
|
||||
{
|
||||
size_t count = 0;
|
||||
|
@ -838,6 +981,8 @@ namespace Etesian {
|
|||
|
||||
_area->buildSubSlices();
|
||||
_area->showSubSlices();
|
||||
for ( const Box& trackAvoid : _trackAvoids )
|
||||
_area->trackAvoid( trackAvoid );
|
||||
#if DISABLED_TIE_INSERTION
|
||||
if (getConfiguration()->getLatchUpDistance()) {
|
||||
Cell* feed = getFeedCells().getBiggestFeed();
|
||||
|
|
|
@ -188,8 +188,6 @@ extern "C" {
|
|||
Py_RETURN_NONE;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// Attribute Method : "PyEtesianEngine_setPLaceArea ()"
|
||||
|
||||
static PyObject* PyEtesianEngine_setPlaceArea ( PyEtesianEngine *self, PyObject* args )
|
||||
{
|
||||
|
@ -224,6 +222,22 @@ extern "C" {
|
|||
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).
|
||||
// DirectVoidMethod(EtesianEngine,etesian,runNegociate)
|
||||
// DirectGetBoolAttribute(PyEtesianEngine_getToolSuccess,getToolSuccess,PyEtesianEngine,EtesianEngine)
|
||||
|
@ -271,6 +285,8 @@ extern "C" {
|
|||
, "Build abstract interface in top cell for supply & blockages." }
|
||||
, { "doHFNS" , (PyCFunction)PyEtesianEngine_doHFNS , METH_NOARGS
|
||||
, "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
|
||||
, "Build the Hurricane post-placement manipulation structure." }
|
||||
, { "destroy" , (PyCFunction)PyEtesianEngine_destroy , METH_NOARGS
|
||||
|
|
|
@ -117,12 +117,13 @@ namespace Etesian {
|
|||
|
||||
class BloatCells {
|
||||
public:
|
||||
inline BloatCells ( EtesianEngine* );
|
||||
inline ~BloatCells ();
|
||||
bool select ( std::string );
|
||||
Box getAb ( Occurrence );
|
||||
inline DbU::Unit getDxSpace () const;
|
||||
inline void resetDxSpace ();
|
||||
inline BloatCells ( EtesianEngine* );
|
||||
inline ~BloatCells ();
|
||||
bool select ( std::string );
|
||||
Box getAb ( Occurrence );
|
||||
inline const BloatCell* getSelected () const;
|
||||
inline DbU::Unit getDxSpace () const;
|
||||
inline void resetDxSpace ();
|
||||
private:
|
||||
EtesianEngine* _etesian;
|
||||
BloatCell* _selected;
|
||||
|
@ -153,8 +154,9 @@ namespace Etesian {
|
|||
}
|
||||
|
||||
|
||||
inline DbU::Unit BloatCells::getDxSpace () const { return _dxSpace; }
|
||||
inline void BloatCells::resetDxSpace () { _dxSpace = 0; }
|
||||
inline DbU::Unit BloatCells::getDxSpace () const { return _dxSpace; }
|
||||
inline void BloatCells::resetDxSpace () { _dxSpace = 0; }
|
||||
inline const BloatCell* BloatCells::getSelected () const { return _selected; }
|
||||
|
||||
|
||||
} // Etesian namespace.
|
||||
|
|
|
@ -73,80 +73,82 @@ namespace Etesian {
|
|||
typedef std::map<Net*,size_t,DBo::CompareById> NetsToIds;
|
||||
typedef std::set<std::string> NetNameSet;
|
||||
public:
|
||||
static const Name& staticGetName ();
|
||||
static EtesianEngine* create ( Cell* );
|
||||
static EtesianEngine* get ( const Cell* );
|
||||
public:
|
||||
inline bool isExcluded ( std::string ) const;
|
||||
virtual Configuration* getConfiguration ();
|
||||
virtual const Configuration* getConfiguration () const;
|
||||
virtual const Name& getName () const;
|
||||
inline RoutingGauge* getGauge () const;
|
||||
inline CellGauge* getCellGauge () const;
|
||||
inline DbU::Unit getHorizontalPitch () const;
|
||||
inline DbU::Unit getVerticalPitch () const;
|
||||
inline DbU::Unit getSliceHeight () const;
|
||||
inline DbU::Unit getSliceStep () const;
|
||||
inline DbU::Unit getFixedAbHeight () const;
|
||||
inline DbU::Unit getFixedAbWidth () const;
|
||||
inline Effort getPlaceEffort () const;
|
||||
inline GraphicUpdate getUpdateConf () const;
|
||||
inline Density getSpreadingConf () const;
|
||||
inline double getSpaceMargin () const;
|
||||
inline double getAspectRatio () const;
|
||||
inline double getAntennaInsertThreshold () const;
|
||||
inline DbU::Unit getAntennaGateMaxWL () const;
|
||||
inline DbU::Unit getAntennaDiodeMaxWL () const;
|
||||
inline DbU::Unit getLatchUpDistance () const;
|
||||
inline const FeedCells& getFeedCells () const;
|
||||
inline const BufferCells& getBufferCells () const;
|
||||
inline Cell* getDiodeCell () const;
|
||||
std::string getUniqueDiodeName ();
|
||||
inline const Box& getPlaceArea () const;
|
||||
inline Area* getArea () const;
|
||||
inline Hurricane::CellViewer* getViewer () const;
|
||||
inline void setViewer ( Hurricane::CellViewer* );
|
||||
inline Cell* getBlockCell () const;
|
||||
inline Instance* getBlockInstance () const;
|
||||
inline const NetNameSet& getExcludedNets () const;
|
||||
inline void setBlock ( Instance* );
|
||||
inline void setFixedAbHeight ( DbU::Unit );
|
||||
inline void setFixedAbWidth ( DbU::Unit );
|
||||
inline void setSpaceMargin ( double );
|
||||
inline void setAspectRatio ( double );
|
||||
void setDefaultAb ();
|
||||
void adjustSliceHeight ();
|
||||
void resetPlacement ();
|
||||
void clearColoquinte ();
|
||||
void loadLeafCellLayouts ();
|
||||
inline DbU::Unit toDbU ( int64_t ) const;
|
||||
inline Occurrence toCell ( Occurrence ) const;
|
||||
inline Point toCell ( const Point& ) const;
|
||||
inline Box toCell ( const Box& ) const;
|
||||
inline Transformation toCell ( Transformation ) const;
|
||||
inline Path toBlock ( Path ) const;
|
||||
inline Occurrence toBlock ( Occurrence ) const;
|
||||
inline Point toBlock ( const Point& ) const;
|
||||
inline Transformation toBlock ( const Transformation& ) const;
|
||||
void setPlaceArea ( const Box& );
|
||||
size_t toColoquinte ();
|
||||
void preplace ();
|
||||
void roughLegalize ( float minDisruption, unsigned options );
|
||||
void globalPlace ( float initPenalty, float minDisruption, float targetImprovement, float minInc, float maxInc, unsigned options=0 );
|
||||
void detailedPlace ( int iterations, int effort, unsigned options=0 );
|
||||
void antennaProtect ();
|
||||
void place ();
|
||||
uint32_t doHFNS ();
|
||||
inline void useFeed ( Cell* );
|
||||
size_t findYSpin ();
|
||||
inline void exclude ( string netName );
|
||||
void addFeeds ();
|
||||
void toHurricane ();
|
||||
void flattenPower ();
|
||||
inline void selectBloat ( std::string );
|
||||
virtual Record* _getRecord () const;
|
||||
virtual std::string _getString () const;
|
||||
virtual std::string _getTypeName () const;
|
||||
static const Name& staticGetName ();
|
||||
static EtesianEngine* create ( Cell* );
|
||||
static EtesianEngine* get ( const Cell* );
|
||||
public:
|
||||
inline bool isExcluded ( std::string ) const;
|
||||
virtual Configuration* getConfiguration ();
|
||||
virtual const Configuration* getConfiguration () const;
|
||||
virtual const Name& getName () const;
|
||||
inline RoutingGauge* getGauge () const;
|
||||
inline CellGauge* getCellGauge () const;
|
||||
inline DbU::Unit getHorizontalPitch () const;
|
||||
inline DbU::Unit getVerticalPitch () const;
|
||||
inline DbU::Unit getSliceHeight () const;
|
||||
inline DbU::Unit getSliceStep () const;
|
||||
inline DbU::Unit getFixedAbHeight () const;
|
||||
inline DbU::Unit getFixedAbWidth () const;
|
||||
inline Effort getPlaceEffort () const;
|
||||
inline GraphicUpdate getUpdateConf () const;
|
||||
inline Density getSpreadingConf () const;
|
||||
inline double getSpaceMargin () const;
|
||||
inline double getAspectRatio () const;
|
||||
inline double getAntennaInsertThreshold () const;
|
||||
inline DbU::Unit getAntennaGateMaxWL () const;
|
||||
inline DbU::Unit getAntennaDiodeMaxWL () const;
|
||||
inline DbU::Unit getLatchUpDistance () const;
|
||||
inline const FeedCells& getFeedCells () const;
|
||||
inline const BufferCells& getBufferCells () const;
|
||||
inline Cell* getDiodeCell () const;
|
||||
std::string getUniqueDiodeName ();
|
||||
inline const Box& getPlaceArea () const;
|
||||
inline Area* getArea () const;
|
||||
inline Hurricane::CellViewer* getViewer () const;
|
||||
inline void setViewer ( Hurricane::CellViewer* );
|
||||
inline Cell* getBlockCell () const;
|
||||
inline Instance* getBlockInstance () const;
|
||||
inline const NetNameSet& getExcludedNets () const;
|
||||
inline const std::vector<Box>& getTrackAvoids () const;
|
||||
inline void setBlock ( Instance* );
|
||||
inline void setFixedAbHeight ( DbU::Unit );
|
||||
inline void setFixedAbWidth ( DbU::Unit );
|
||||
inline void setSpaceMargin ( double );
|
||||
inline void setAspectRatio ( double );
|
||||
void setDefaultAb ();
|
||||
void adjustSliceHeight ();
|
||||
void resetPlacement ();
|
||||
void clearColoquinte ();
|
||||
void loadLeafCellLayouts ();
|
||||
inline DbU::Unit toDbU ( int64_t ) const;
|
||||
inline Occurrence toCell ( Occurrence ) const;
|
||||
inline Point toCell ( const Point& ) const;
|
||||
inline Box toCell ( const Box& ) const;
|
||||
inline Transformation toCell ( Transformation ) const;
|
||||
inline Path toBlock ( Path ) const;
|
||||
inline Occurrence toBlock ( Occurrence ) const;
|
||||
inline Point toBlock ( const Point& ) const;
|
||||
inline Transformation toBlock ( const Transformation& ) const;
|
||||
void setPlaceArea ( const Box& );
|
||||
size_t toColoquinte ();
|
||||
void preplace ();
|
||||
void roughLegalize ( float minDisruption, unsigned options );
|
||||
void globalPlace ( float initPenalty, float minDisruption, float targetImprovement, float minInc, float maxInc, unsigned options=0 );
|
||||
void detailedPlace ( int iterations, int effort, unsigned options=0 );
|
||||
void antennaProtect ();
|
||||
void place ();
|
||||
uint32_t doHFNS ();
|
||||
inline void useFeed ( Cell* );
|
||||
size_t findYSpin ();
|
||||
inline void exclude ( string netName );
|
||||
void addFeeds ();
|
||||
void toHurricane ();
|
||||
void flattenPower ();
|
||||
inline void selectBloat ( std::string );
|
||||
inline void addTrackAvoid ( const Box& );
|
||||
virtual Record* _getRecord () const;
|
||||
virtual std::string _getString () const;
|
||||
virtual std::string _getTypeName () const;
|
||||
private:
|
||||
// Attributes.
|
||||
static Name _toolName;
|
||||
|
@ -157,6 +159,7 @@ namespace Etesian {
|
|||
bool _ySpinSet;
|
||||
bool _flatDesign;
|
||||
Box _placeArea;
|
||||
std::vector<Box> _trackAvoids;
|
||||
coloquinte::box<coloquinte::int_t>* _surface;
|
||||
coloquinte::netlist* _circuit;
|
||||
coloquinte::placement_t* _placementLB;
|
||||
|
@ -236,6 +239,14 @@ namespace Etesian {
|
|||
inline Area* EtesianEngine::getArea () const { return _area; }
|
||||
inline const EtesianEngine::NetNameSet&
|
||||
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 )
|
||||
{
|
||||
|
|
|
@ -219,7 +219,9 @@ namespace Etesian {
|
|||
inline DbU::Unit getYBottom () const;
|
||||
inline DbU::Unit getXMin () const;
|
||||
inline DbU::Unit getXMax () const;
|
||||
size_t getUsedVTracks ( const Tile& , std::set<DbU::Unit>& vtracks );
|
||||
DbU::Unit getAverageChunk ( size_t& ) const;
|
||||
void trackAvoid ( DbU::Unit xTrack );
|
||||
void insertTies ( DbU::Unit latchUpMax );
|
||||
private:
|
||||
Slice* _slice;
|
||||
|
@ -257,6 +259,7 @@ namespace Etesian {
|
|||
, size_t yspin );
|
||||
void buildSubSlices ();
|
||||
void showSubSlices ();
|
||||
void trackAvoid ( DbU::Unit xTrack );
|
||||
void insertTies ( DbU::Unit latchUpMax );
|
||||
Instance* createDiodeUnder ( RoutingPad*, const Box&, DbU::Unit xHint );
|
||||
inline std::string _getString () const;
|
||||
|
@ -296,6 +299,7 @@ namespace Etesian {
|
|||
void addFeeds ();
|
||||
void buildSubSlices ();
|
||||
void showSubSlices ();
|
||||
void trackAvoid ( const Box& trackAvoid );
|
||||
void insertTies ( DbU::Unit latchUpMax );
|
||||
Instance* createDiodeUnder ( RoutingPad*, const Box&, DbU::Unit xHint );
|
||||
inline std::string _getString () const;
|
||||
|
|
|
@ -231,6 +231,7 @@ namespace Cfg {
|
|||
|
||||
bool Parameter::setInt ( int i, Priority priority )
|
||||
{
|
||||
std::cout.flush();
|
||||
if ( not _updatePriority(priority) ) return false;
|
||||
|
||||
if ( (_type != Int) and (_type != Enumerate) )
|
||||
|
@ -353,11 +354,12 @@ namespace Cfg {
|
|||
}
|
||||
}
|
||||
|
||||
//cerr << " updated" << endl;
|
||||
|
||||
_value = svalue.str();
|
||||
_onValueChanged();
|
||||
|
||||
//cerr << " updated _value=\"" << _value << "\"" << endl;
|
||||
|
||||
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>" -*-
|
||||
//
|
||||
// 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 |
|
||||
|
|
Loading…
Reference in New Issue