Compare commits
2 Commits
93ac03af07
...
ef004a955b
Author | SHA1 | Date |
---|---|---|
Jean-Paul Chaput | ef004a955b | |
Jean-Paul Chaput | 205a6877db |
|
@ -1241,6 +1241,8 @@ namespace Anabatic {
|
|||
//AutoSegment::setShortNetMode( true );
|
||||
++shortNets;
|
||||
}
|
||||
if (NetRoutingExtension::isManualDetailRoute(net))
|
||||
continue;
|
||||
if ( NetRoutingExtension::isManualGlobalRoute(net)
|
||||
or NetRoutingExtension::isAutomaticGlobalRoute(net)) {
|
||||
DebugSession::open( net, 145, 150 );
|
||||
|
|
|
@ -1057,7 +1057,9 @@ namespace Anabatic {
|
|||
uint32_t total = 0;
|
||||
for ( Net* net : getCell()->getNets() ) {
|
||||
if (net->isSupply()) continue;
|
||||
if (net->isClock ()) continue;
|
||||
if ( NetRoutingExtension::isManualDetailRoute(net)
|
||||
or NetRoutingExtension::isFixed(net))
|
||||
continue;
|
||||
antennaProtect( net, failed, total );
|
||||
}
|
||||
cmess2 << Dots::asString ( " - Antenna gate maximum WL" , DbU::getValueString(etesian->getAntennaGateMaxWL()) ) << endl;
|
||||
|
|
|
@ -94,13 +94,13 @@ namespace Anabatic {
|
|||
}
|
||||
}
|
||||
|
||||
if (getId() == 1518590) {
|
||||
cerr << "AutoHorizontal::_postCreate(): " << this << endl;
|
||||
cerr << "| Source contact:" << source << endl;
|
||||
cerr << "| Source GCell: " << getGCell() << endl;
|
||||
cerr << "| Target contact:" << target << endl;
|
||||
cerr << "| Target GCell: " << target->getGCell() << endl;
|
||||
}
|
||||
// if (getId() == 1518590) {
|
||||
// cerr << "AutoHorizontal::_postCreate(): " << this << endl;
|
||||
// cerr << "| Source contact:" << source << endl;
|
||||
// cerr << "| Source GCell: " << getGCell() << endl;
|
||||
// cerr << "| Target contact:" << target << endl;
|
||||
// cerr << "| Target GCell: " << target->getGCell() << endl;
|
||||
// }
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@
|
|||
${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/block/bigvia.py
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/block/spares.py
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/block/block.py
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/block/clocktree.py
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/block/htree.py
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/block/timing.py
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/block/rsmt.py
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/plugins/alpha/block/hfns1.py
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
from __future__ import print_function
|
||||
import sys
|
||||
import os.path
|
||||
from copy import deepcopy
|
||||
import Cfg
|
||||
from Hurricane import Breakpoint, DbU, Box, Transformation, Point, \
|
||||
Box, Path, Layer, Occurrence, Net, \
|
||||
|
@ -35,7 +36,7 @@ from plugins import getParameter
|
|||
from plugins.alpha.macro.macro import Macro
|
||||
from plugins.alpha.block import timing
|
||||
from plugins.alpha.block.spares import Spares
|
||||
from plugins.alpha.block.clocktree import ClockTree
|
||||
from plugins.alpha.block.htree import HTree
|
||||
#from plugins.alpha.block.hfns1 import BufferTree
|
||||
#from plugins.alpha.block.hfns2 import BufferTree
|
||||
#from plugins.alpha.block.hfns3 import BufferTree
|
||||
|
@ -286,6 +287,7 @@ class Block ( object ):
|
|||
"""
|
||||
|
||||
LUT = {}
|
||||
FLATTENED = 0x0001
|
||||
|
||||
@staticmethod
|
||||
def lookup ( cell ):
|
||||
|
@ -300,10 +302,11 @@ class Block ( object ):
|
|||
self.flags = 0
|
||||
self.conf = conf
|
||||
self.spares = Spares( self )
|
||||
self.clockTrees = []
|
||||
self.hTrees = []
|
||||
self.hfnTrees = []
|
||||
self.blockInstances = []
|
||||
self.placeHolderCount = 0
|
||||
self.excludedNets = deepcopy( self.conf.hTreeNames )
|
||||
self.sides = { IoPin.WEST : Side( self.conf, IoPin.WEST )
|
||||
, IoPin.EAST : Side( self.conf, IoPin.EAST )
|
||||
, IoPin.SOUTH : Side( self.conf, IoPin.SOUTH )
|
||||
|
@ -329,7 +332,6 @@ class Block ( object ):
|
|||
.format(self.conf.cell.getName()) )
|
||||
Block.LUT[ self.conf.cell ] = self
|
||||
|
||||
|
||||
@staticmethod
|
||||
def _getInstance ( cell, pattern, level=0 ):
|
||||
"""
|
||||
|
@ -370,6 +372,35 @@ class Block ( object ):
|
|||
"""
|
||||
return Block._rgetInstance( self.conf.core, path )
|
||||
|
||||
@staticmethod
|
||||
def _rinstancesToPath ( path, instances ):
|
||||
instance = path.getTailInstance().getMasterCell().getInstance( instances[0] )
|
||||
path = Path( path, instance )
|
||||
if len(instances) > 1:
|
||||
return Block._rinstanceToPath( path, instances[1:] )
|
||||
return path
|
||||
|
||||
@staticmethod
|
||||
def _instancesToPath ( cell, instances ):
|
||||
instance = cell.getInstance( instances[0] )
|
||||
return Block._rinstancesToPath( Path(instance), instances[1:] )
|
||||
|
||||
def getFlattenedNet ( self, path ):
|
||||
"""
|
||||
Find a net in the hierarchy. The path argument is a list pathname of instance
|
||||
endind by a net name, like "instance1.instance2.net_name". The function returns
|
||||
a an Occurrence, the instance path and the Net, or None.
|
||||
"""
|
||||
for net in self.conf.cellPnR.getNets():
|
||||
if net.getName() == path:
|
||||
return Occurrence( net, Path() )
|
||||
elements = path.split('.')
|
||||
if len(elements) == 1:
|
||||
return None
|
||||
path = Block._instancesToPath( self.conf.cellPnR, elements[:-1] )
|
||||
net = path.getTailInstance().getMasterCell().getNet( elements[-1] )
|
||||
return Occurrence( net, path )
|
||||
|
||||
def setUnexpandPins ( self, sides ):
|
||||
"""
|
||||
Prevent Pins from the selected sides to be stick out of one pitch.
|
||||
|
@ -433,43 +464,65 @@ class Block ( object ):
|
|||
else:
|
||||
self.conf.setRoutingBb( self.conf.cell.getAbutmentBox() )
|
||||
|
||||
def addClockTrees ( self ):
|
||||
"""Create the trunk of all the clock trees (recursive H-Tree)."""
|
||||
print( ' o Building clock tree(s).' )
|
||||
af = CRL.AllianceFramework.get()
|
||||
clockNets = []
|
||||
for net in self.conf.cellPnR.getNets():
|
||||
if af.isCLOCK(net.getName()): 'CLOCK: {}'.format(net)
|
||||
if net.isClock():
|
||||
trace( 550, '\tBlock.addClockTrees(): Found clock {}.\n'.format(net) )
|
||||
clockNets.append( net )
|
||||
if not clockNets:
|
||||
raise ErrorMessage( 3, 'Block.clockTree(): Cell "{}" has no clock net(s).'.format(self.conf.cell.getName()) )
|
||||
with UpdateSession():
|
||||
for clockNet in clockNets:
|
||||
print( ' - "{}".'.format(clockNet.getName()) )
|
||||
trace( 550, ',+', '\tBlock.addClockTrees(): Build clock tree for {}.\n'.format(clockNet) )
|
||||
self.clockTrees.append( ClockTree(self.spares,clockNet,len(self.clockTrees)) )
|
||||
self.clockTrees[-1].buildHTree()
|
||||
trace( 550, '-' )
|
||||
Breakpoint.stop( 100, 'Block.addClockTrees() on {} done.'.format(self.conf.cellPnR) )
|
||||
def flattenNets ( self ):
|
||||
if self.flags & Block.FLATTENED: return
|
||||
if self.conf.isCoreBlock:
|
||||
self.conf.corona.flattenNets( self.conf.icore, self.conf.hTreeNames, Cell.Flags_NoClockFlatten )
|
||||
else:
|
||||
self.conf.cell.flattenNets( None, self.excludedNets, Cell.Flags_NoClockFlatten )
|
||||
self.flags |= Block.FLATTENED
|
||||
|
||||
def splitClocks ( self ):
|
||||
def addHTrees ( self ):
|
||||
"""Create the trunk of all the clock trees (recursive H-Tree)."""
|
||||
print( ' o Building H-Tree(s).' )
|
||||
af = CRL.AllianceFramework.get()
|
||||
hTreeNets = []
|
||||
netOcc = None
|
||||
self.flattenNets()
|
||||
for netName in self.conf.hTreeNames:
|
||||
netOcc = self.getFlattenedNet( netName )
|
||||
#if self.conf.isCoreBlock:
|
||||
# coreNet = self.conf.cell.getNet( netName )
|
||||
# if coreNet is not None:
|
||||
# trace( 550, '\tFound coreNet={}\n'.format(coreNet) )
|
||||
# for plug in self.conf.icore.getPlugs():
|
||||
# if plug.getMasterNet() == coreNet:
|
||||
# net = plug.getNet()
|
||||
# break
|
||||
#else:
|
||||
# net = self.conf.cellPnR.getNet( netName )
|
||||
if netOcc is None:
|
||||
print( ErrorMessage( 3, 'Block.addHTrees(): Cell "{}" has no H-Tree net "{}".' \
|
||||
.format( self.conf.cellPnR.getName(), netName )))
|
||||
continue
|
||||
trace( 550, '\tBlock.addHTrees(): Found H-Tree {}.\n'.format(netOcc) )
|
||||
hTreeNets.append( netOcc )
|
||||
self.etesian.exclude( netName )
|
||||
with UpdateSession():
|
||||
for hTreeNet in hTreeNets:
|
||||
print( ' - "{}".'.format(hTreeNet.getName()) )
|
||||
trace( 550, ',+', '\tBlock.addHTrees(): Build clock tree for {}.\n'.format(hTreeNet) )
|
||||
self.hTrees.append( HTree(self.spares,hTreeNet,len(self.hTrees)) )
|
||||
self.hTrees[-1].buildHTree()
|
||||
for net in self.hTrees[-1].subNets:
|
||||
self.etesian.exclude( net.getName() )
|
||||
self.excludedNets.append( net.getName() )
|
||||
trace( 550, '-' )
|
||||
Breakpoint.stop( 100, 'Block.addHTrees() on {} done.'.format(self.conf.cellPnR) )
|
||||
|
||||
def splitHTrees ( self ):
|
||||
"""
|
||||
Break the clock net and attach all it's Pins to the closest leaf
|
||||
Break the H-Tree root nets and attach all it's Pins to the closest leaf
|
||||
if the H-Tree.
|
||||
"""
|
||||
for clockTree in self.clockTrees:
|
||||
clockTree.splitClock()
|
||||
for hTree in self.hTrees:
|
||||
hTree.splitNet()
|
||||
|
||||
def findHfnTrees4 ( self ):
|
||||
"""Perform simple HFNS, just break nets regardless of placement."""
|
||||
print( ' o Building high fanout nets trees.' )
|
||||
if self.spares:
|
||||
if self.conf.isCoreBlock:
|
||||
self.conf.corona.flattenNets( self.conf.icore, Cell.Flags_NoClockFlatten )
|
||||
else:
|
||||
self.conf.cell.flattenNets( None, Cell.Flags_NoClockFlatten )
|
||||
self.flattenNets()
|
||||
beginCount = self.conf.bufferConf.count
|
||||
maxSinks = 10
|
||||
dots( 82
|
||||
|
@ -578,7 +631,7 @@ class Block ( object ):
|
|||
for side in self.sides.values():
|
||||
side.expand()
|
||||
|
||||
def place ( self ):
|
||||
def initEtesian ( self ):
|
||||
editor = self.conf.editor
|
||||
if self.conf.isCoreBlock:
|
||||
self.etesian = Etesian.EtesianEngine.create( self.conf.corona )
|
||||
|
@ -588,9 +641,11 @@ class Block ( object ):
|
|||
Breakpoint.stop( 100, 'Block.place(), corona loaded.')
|
||||
else:
|
||||
self.etesian = Etesian.EtesianEngine.create( self.conf.cell )
|
||||
self.etesian.getCell().flattenNets( None, self.excludedNets, Cell.Flags_NoClockFlatten )
|
||||
|
||||
def place ( self ):
|
||||
if self.conf.placeArea:
|
||||
self.etesian.setPlaceArea( self.conf.placeArea )
|
||||
self.etesian.getCell().flattenNets( None, Cell.Flags_NoClockFlatten )
|
||||
if self.conf.useHFNS: self.etesian.doHFNS()
|
||||
self.etesian.place()
|
||||
Breakpoint.stop( 100, 'Placement done.' )
|
||||
|
@ -738,6 +793,7 @@ class Block ( object ):
|
|||
blockInstance.block.build()
|
||||
if editor: editor.setCell( self.conf.cellPnR )
|
||||
self.conf.cfg.apply()
|
||||
self.initEtesian()
|
||||
iteration = -1
|
||||
while True:
|
||||
iteration += 1
|
||||
|
@ -748,14 +804,14 @@ class Block ( object ):
|
|||
self.checkIoPins()
|
||||
self.spares.build()
|
||||
#if self.conf.useHFNS: self.findHfnTrees4()
|
||||
if self.conf.useClockTree: self.addClockTrees()
|
||||
self.addHTrees()
|
||||
#if self.conf.useHFNS: self.addHfnBuffers()
|
||||
if editor: editor.fit()
|
||||
#Breakpoint.stop( 0, 'Clock tree(s) done.' )
|
||||
self.place()
|
||||
#if self.conf.useHFNS: self.findHfnTrees()
|
||||
break
|
||||
if self.conf.useClockTree: self.splitClocks()
|
||||
self.splitHTrees()
|
||||
self.spares.removeUnusedBuffers()
|
||||
self.etesian.toHurricane()
|
||||
self.etesian.flattenPower()
|
||||
|
|
|
@ -1109,6 +1109,7 @@ class BlockConf ( GaugeConf ):
|
|||
self.placeArea = None
|
||||
self.deltaAb = [ 0, 0, 0, 0 ]
|
||||
self.useClockTree = False
|
||||
self.hTreeNames = [ ]
|
||||
self.useHFNS = False
|
||||
self.useSpares = True
|
||||
self.isBuilt = False
|
||||
|
@ -1210,6 +1211,10 @@ class BlockConf ( GaugeConf ):
|
|||
trace( 550, '\tNew cloned cell: "{}"\n'.format(masterCell) )
|
||||
self.cloneds.append( masterCell )
|
||||
return
|
||||
|
||||
def useHTree ( self, netName ):
|
||||
if not netName in self.hTreeNames:
|
||||
self.hTreeNames.append( netName );
|
||||
|
||||
def save ( self, flags ):
|
||||
"""
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
# | Author : Jean-Paul CHAPUT |
|
||||
# | E-mail : Jean-Paul.Chaput@lip6.fr |
|
||||
# | =============================================================== |
|
||||
# | Python : "./plugins/block/clocktree.py" |
|
||||
# | Python : "./plugins/block/htree.py" |
|
||||
# +-----------------------------------------------------------------+
|
||||
|
||||
|
||||
|
@ -17,29 +17,14 @@ from __future__ import print_function
|
|||
import sys
|
||||
import os.path
|
||||
import Cfg
|
||||
from Hurricane import Breakpoint
|
||||
from Hurricane import DbU
|
||||
from Hurricane import Box
|
||||
from Hurricane import Transformation
|
||||
from Hurricane import Box
|
||||
from Hurricane import Path
|
||||
from Hurricane import Layer
|
||||
from Hurricane import Occurrence
|
||||
from Hurricane import Net
|
||||
from Hurricane import HyperNet
|
||||
from Hurricane import RoutingPad
|
||||
from Hurricane import Horizontal
|
||||
from Hurricane import Vertical
|
||||
from Hurricane import Contact
|
||||
from Hurricane import Pin
|
||||
from Hurricane import Plug
|
||||
from Hurricane import Instance
|
||||
from Hurricane import Breakpoint, DbU, Box, Transformation, Box, \
|
||||
Path, Layer, Occurrence, Net, HyperNet, \
|
||||
RoutingPad, Horizontal, Vertical, Contact, \
|
||||
Pin, Plug, Instance
|
||||
import CRL
|
||||
from CRL import RoutingLayerGauge
|
||||
from helpers import trace
|
||||
from helpers.io import ErrorMessage
|
||||
from helpers.io import WarningMessage
|
||||
from helpers.io import catch
|
||||
from helpers.io import ErrorMessage, WarningMessage, catch
|
||||
from helpers.overlay import UpdateSession
|
||||
from plugins import getParameter
|
||||
from plugins.alpha import utils
|
||||
|
@ -48,33 +33,47 @@ from plugins.alpha.block.spares import Spares
|
|||
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Class : "clocktree.ClockTree".
|
||||
# Class : "htree.HTree".
|
||||
|
||||
class ClockTree ( object ):
|
||||
class HTree ( object ):
|
||||
"""
|
||||
Build a clock tree on a block.
|
||||
Build a H-Tree on a net occurrene.
|
||||
"""
|
||||
|
||||
def __init__ ( self, spares, clockNet, index ):
|
||||
def __init__ ( self, spares, treeNetOcc, index ):
|
||||
self.spares = spares
|
||||
self.clockNet = clockNet
|
||||
self.clockIndex = index
|
||||
self.treeNetOcc = treeNetOcc
|
||||
self.treeIndex = index
|
||||
self.subNets = []
|
||||
if not self.clockNet.isClock():
|
||||
print( WarningMessage( 'ClockTree.__init__(): Net "{}" is not of CLOCK type.' \
|
||||
.format(self.clockNet.getName()) ))
|
||||
#if not self.treeNetOcc.getEntity().isClock():
|
||||
# print( WarningMessage( 'HTree.__init__(): Net "{}" is not of CLOCK type.' \
|
||||
# .format(self.treeNet.getEntity().getName()) ))
|
||||
if treeNetOcc.getPath().isEmpty():
|
||||
self.treeNet = self.treeNetOcc.getEntity()
|
||||
else:
|
||||
botNet = self.treeNetOcc.getEntity()
|
||||
botNet.setExternal( True )
|
||||
topNetName = self.treeNetOcc.getName()
|
||||
topNet = Net.create( self.treeNetOcc.getPath().getOwnerCell(), topNetName )
|
||||
topNet.setType ( botNet.getType() )
|
||||
topNet.setDirection( botNet.getDirection() )
|
||||
path = self.treeNetOcc.getPath().getHeadPath()
|
||||
self.spares.raddTransNet( topNet, path )
|
||||
botInstance = self.treeNetOcc.getPath().getTailInstance()
|
||||
botInstance.getPlug( botNet ).setNet( botInstance.getCell().getNet( topNetName ))
|
||||
self.treeNet = topNet
|
||||
|
||||
def destroy ( self ):
|
||||
trace( 550, ',+', '\tClockTree.destroy() "{}"\n'.format(self.clockNet.getName()) )
|
||||
trace( 550, ',+', '\tHTree.destroy() "{}"\n'.format(self.treeNet.getName()) )
|
||||
with UpdateSession():
|
||||
for subNet in self.subNets + [ self.clockNet ]:
|
||||
for subNet in self.subNets + [ self.treeNet ]:
|
||||
components = []
|
||||
for comp in subNet.getComponents():
|
||||
if isinstance(comp,RoutingPad): components.append( comp )
|
||||
if isinstance(comp,Pin ): components.append( comp )
|
||||
for comp in components:
|
||||
comp.destroy()
|
||||
if subNet != self.clockNet:
|
||||
if subNet != self.treeNet:
|
||||
subNet.destroy()
|
||||
trace( 550, '-' )
|
||||
|
||||
|
@ -82,7 +81,7 @@ class ClockTree ( object ):
|
|||
if qt.isLeaf(): return False
|
||||
qt.rconnectBuffer()
|
||||
driverNet = qt.bOutputPlug.getNet()
|
||||
driverNet.setType( Net.Type.CLOCK )
|
||||
driverNet.setType( self.treeNet.getType() )
|
||||
for leaf in qt.leafs:
|
||||
leaf.bInputPlug.setNet( driverNet )
|
||||
self._rconnectHTree( leaf )
|
||||
|
@ -92,7 +91,7 @@ class ClockTree ( object ):
|
|||
"""
|
||||
Recursively build one HTree branch for all non-terminal nodes of the QuadTree.
|
||||
"""
|
||||
trace( 550, ',+', '\tClockTree._rrouteHTree() {}\n'.format(qt.bOutputPlug.getNet()) )
|
||||
trace( 550, ',+', '\tHTree._rrouteHTree() {}\n'.format(qt.bOutputPlug.getNet()) )
|
||||
trace( 550, '\tOn: {}\n'.format(qt) )
|
||||
if qt.isLeaf():
|
||||
trace( 550, '-' )
|
||||
|
@ -165,13 +164,13 @@ class ClockTree ( object ):
|
|||
gaugeConf.setStackPosition( brContact, rightX, blY )
|
||||
gaugeConf.createVertical ( rightContact, brContact, rightX, 0 )
|
||||
if qt.isRoot():
|
||||
ckNet = self.clockNet
|
||||
ckNet = self.treeNet
|
||||
if not self.spares.conf.isCoreBlock:
|
||||
trace( 550, '\tRemoving any previous pin...\n' )
|
||||
pins = []
|
||||
for pin in ckNet.getPins(): pins.append( pin )
|
||||
for pin in pins:
|
||||
print( WarningMessage('ClockTree._rrouteHTree(): Removing {}.'.format(pin)) )
|
||||
print( WarningMessage('HTree._rrouteHTree(): Removing {}.'.format(pin)) )
|
||||
pin.destroy()
|
||||
layerGauge = gaugeConf.vRoutingGauge
|
||||
rootContact = gaugeConf.rpAccessByPlugName( qt.buffer, bufferConf.input, ckNet, 0 )
|
||||
|
@ -196,41 +195,44 @@ class ClockTree ( object ):
|
|||
|
||||
def buildHTree ( self ):
|
||||
"""
|
||||
Create the clock tree netlist in two steps:
|
||||
Create the tree tree netlist in two steps:
|
||||
1. Connect the buffers of the spares QuadTree to form a H-Tree.
|
||||
2. Detach the all the clock sink point and reconnect them to the
|
||||
2. Detach the all the tree sink point and reconnect them to the
|
||||
buffers of the leafs of the QuadTree.
|
||||
"""
|
||||
qt = self.spares.quadTree
|
||||
qt.bufferTag = self.clockNet.getName()
|
||||
qt.rselectBuffer( self.clockIndex, self.clockIndex, Spares.CHECK_USED|Spares.MARK_USED)
|
||||
qt.bufferTag = self.treeNet.getName()
|
||||
qt.rselectBuffer( self.treeIndex, self.treeIndex, Spares.CHECK_USED|Spares.MARK_USED)
|
||||
with UpdateSession():
|
||||
self._rconnectHTree( qt )
|
||||
self._rrouteHTree ( qt )
|
||||
|
||||
def splitClock ( self ):
|
||||
def splitNet ( self ):
|
||||
"""
|
||||
Disconnect the registers from the main clock and reconnect them to
|
||||
the leaf buffers of the clock tree.
|
||||
Disconnect the sinks from the main tree and reconnect them to
|
||||
the leaf buffers of the tree tree.
|
||||
"""
|
||||
bufferConf = self.spares.conf.bufferConf
|
||||
quadTree = self.spares.quadTree
|
||||
quadTree.bufferTag = self.clockNet.getName()
|
||||
quadTree.rselectBuffer( self.clockIndex, self.clockIndex, 0 )
|
||||
quadTree.bufferTag = self.treeNet.getName()
|
||||
quadTree.rselectBuffer( self.treeIndex, self.treeIndex, 0 )
|
||||
with UpdateSession():
|
||||
coronaPlugs = []
|
||||
hyperClock = HyperNet.create( Occurrence(self.clockNet) )
|
||||
for plugOccurrence in hyperClock.getTerminalNetlistPlugOccurrences():
|
||||
if quadTree.isUnderArea(plugOccurrence):
|
||||
quadTree.attachToLeaf( plugOccurrence )
|
||||
driverPlugs = []
|
||||
hyperNet = HyperNet.create( Occurrence(self.treeNet) )
|
||||
for plugOcc in hyperNet.getTerminalNetlistPlugOccurrences():
|
||||
trace( 550, '\tReattach "{}"\n'.format(plugOcc) )
|
||||
plug = plugOcc.getEntity()
|
||||
if not (plug.getMasterNet().getDirection() & Net.Direction.OUT) \
|
||||
and quadTree.isUnderArea(plugOcc):
|
||||
quadTree.attachToLeaf( plugOcc )
|
||||
else:
|
||||
coronaPlugs.append( plugOccurrence )
|
||||
driverPlugs.append( plugOcc )
|
||||
quadTree.rsplitNetlist()
|
||||
if self.spares.conf.isCoreBlock:
|
||||
plug = utils.getPlugByName( quadTree.buffer, bufferConf.input )
|
||||
plug.setNet( self.clockNet )
|
||||
trace( 550, '\tCore mode, setting only root plug "{}"\n'.format(self.clockNet.getName()) )
|
||||
trace( 550, '\tPlug of "{}" (Cell:{})\n'.format(self.clockNet.getName()
|
||||
,self.clockNet.getCell()) )
|
||||
for plug in self.clockNet.getPlugs():
|
||||
plug.setNet( self.treeNet )
|
||||
trace( 550, '\tCore mode, setting only root plug "{}"\n'.format(self.treeNet.getName()) )
|
||||
trace( 550, '\tPlug of "{}" (Cell:{})\n'.format(self.treeNet.getName()
|
||||
,self.treeNet.getCell()) )
|
||||
for plug in self.treeNet.getPlugs():
|
||||
trace( 550, '\t| {}\n'.format(plug) )
|
|
@ -120,7 +120,7 @@ class Chip ( Block ):
|
|||
if self.conf.routingGauge.hasPowerSupply():
|
||||
power = plugins.alpha.chip.powerplane.Builder( self.conf )
|
||||
power.connectPower()
|
||||
power.connectClocks()
|
||||
power.connectHTrees( self.hTrees )
|
||||
power.doLayout()
|
||||
Breakpoint.stop( 101, 'After Query power.' )
|
||||
else:
|
||||
|
|
|
@ -455,23 +455,23 @@ class Builder ( object ):
|
|||
trace( 550, '-' )
|
||||
self.activePlane = None
|
||||
|
||||
def _connectClock ( self, ck, trackNb ):
|
||||
trace( 550, '\tpower.Builder._connectClock() {}\n'.format(ck) )
|
||||
blockCk = None
|
||||
def _connectHTree ( self, coronaNet, trackNb ):
|
||||
trace( 550, '\tpower.Builder._connectHTree() {} on track {}\n'.format(coronaNet,trackNb) )
|
||||
coreNet = None
|
||||
for plug in self.conf.icore.getPlugs():
|
||||
if plug.getNet() == ck:
|
||||
blockCk = plug.getMasterNet()
|
||||
if not blockCk:
|
||||
raise ErrorMessage( 1, 'Block "{}" has no net connected to the clock "{}".' \
|
||||
.format(self.conf.icore.getName(),ck.getName()) )
|
||||
if plug.getNet() == coronaNet:
|
||||
coreNet = plug.getMasterNet()
|
||||
if not coreNet:
|
||||
raise ErrorMessage( 1, 'Block "{}" has no net connected to the H-Tree "{}".' \
|
||||
.format(self.conf.icore.getName(),coronaNet.getName()) )
|
||||
return
|
||||
htPlugs = []
|
||||
for plug in ck.getPlugs():
|
||||
for plug in coronaNet.getPlugs():
|
||||
if plug.getInstance().isTerminalNetlist():
|
||||
htPlugs.append( plug )
|
||||
if len(htPlugs) != 1:
|
||||
message = [ 'Clock "{}" of block "{}" is not organized as a H-Tree ({} plugs).' \
|
||||
.format( ck.getName()
|
||||
message = [ 'Net "{}" of block "{}" is not organized as a H-Tree ({} plugs).' \
|
||||
.format( coronaNet.getName()
|
||||
, self.conf.icore.getName()
|
||||
, len(htPlugs)) ]
|
||||
for plug in htPlugs:
|
||||
|
@ -479,17 +479,17 @@ class Builder ( object ):
|
|||
raise ErrorMessage( 1, message )
|
||||
return
|
||||
coronaPin = None
|
||||
for pin in ck.getPins():
|
||||
for pin in coronaNet.getPins():
|
||||
coronaPin = pin
|
||||
break
|
||||
if not coronaPin:
|
||||
message = [ 'Clock "{}" of block "{}" is not connected to a corona Pin.' \
|
||||
.format( ck.getName() , self.conf.icore.getName() ) ]
|
||||
message = [ 'Net "{}" of block "{}" is not connected to a corona Pin.' \
|
||||
.format( coronaNet.getName() , self.conf.icore.getName() ) ]
|
||||
raise ErrorMessage( 1, message )
|
||||
with UpdateSession():
|
||||
coronaAb = self.conf.cellPnR.getAbutmentBox()
|
||||
bufferRp = self.conf.rpAccessByOccurrence( Occurrence(htPlugs[0], Path()), ck, 0 )
|
||||
pinRp = self.conf.rpAccessByOccurrence( Occurrence(coronaPin , Path()), ck, 0 )
|
||||
bufferRp = self.conf.rpAccessByOccurrence( Occurrence(htPlugs[0], Path()), coronaNet, 0 )
|
||||
pinRp = self.conf.rpAccessByOccurrence( Occurrence(coronaPin , Path()), coronaNet, 0 )
|
||||
trace( 550, '\tpinRp={}\n'.format(pinRp) )
|
||||
self.conf.expandMinArea( bufferRp )
|
||||
self.conf.expandMinArea( pinRp )
|
||||
|
@ -508,40 +508,39 @@ class Builder ( object ):
|
|||
isVertical = False
|
||||
axis = coronaAb.getXMin()
|
||||
if isVertical:
|
||||
pitch = self.conf.vRoutingGauge.getPitch()
|
||||
yaxis = axis + pitch * trackNb
|
||||
pitch = self.conf.hRoutingGauge.getPitch()
|
||||
yaxis = axis + 2 * pitch * trackNb
|
||||
trace( 550, '\tyaxis(request)={}\n'.format(DbU.getValueString(yaxis)) )
|
||||
yaxis = self.conf.getNearestHorizontalTrack( yaxis, 0 )
|
||||
xaxisRp = self.conf.getNearestVerticalTrack( bufferRp.getX(), 0 )
|
||||
xaxisPin = self.conf.getNearestVerticalTrack( pin.getX(), 0 )
|
||||
contact1 = self.conf.createContact( ck, xaxisRp , yaxis, 0 )
|
||||
contact2 = self.conf.createContact( ck, xaxisPin, yaxis, 0 )
|
||||
contact1 = self.conf.createContact( coronaNet, xaxisRp , yaxis, 0 )
|
||||
contact2 = self.conf.createContact( coronaNet, xaxisPin, yaxis, 0 )
|
||||
self.conf.createVertical ( bufferRp, contact1, xaxisRp , 0 )
|
||||
self.conf.createHorizontal( contact1, contact2, yaxis , 0 )
|
||||
self.conf.createVertical ( contact2, pinRp , xaxisPin, 0 )
|
||||
trace( 550, '\tyaxis(track)={}\n'.format(DbU.getValueString(yaxis)) )
|
||||
trace( 550, '\tcontact1={}\n'.format(contact1) )
|
||||
trace( 550, '\tcontact2={}\n'.format(contact2) )
|
||||
else:
|
||||
pitch = self.conf.hRoutingGauge.getPitch()
|
||||
xaxis = axis + pitch * trackNb
|
||||
pitch = self.conf.vRoutingGauge.getPitch()
|
||||
xaxis = axis + 2 * pitch * trackNb
|
||||
trace( 550, '\txaxis(request)={} vpitch={}\n' \
|
||||
.format(DbU.getValueString(xaxis), DbU.getValueString(pitch)) )
|
||||
xaxis = self.conf.getNearestVerticalTrack( xaxis, 0 )
|
||||
yaxisRp = self.conf.getNearestHorizontalTrack( bufferRp.getY(), 0 )
|
||||
yaxisPin = self.conf.getNearestHorizontalTrack( pin.getY(), 0 )
|
||||
contact1 = self.conf.createContact( ck, xaxis, yaxisRp , 0 )
|
||||
contact2 = self.conf.createContact( ck, xaxis, yaxisPin, 0 )
|
||||
contact1 = self.conf.createContact( coronaNet, xaxis, yaxisRp , 0 )
|
||||
contact2 = self.conf.createContact( coronaNet, xaxis, yaxisPin, 0 )
|
||||
self.conf.createHorizontal( bufferRp, contact1, yaxisRp , 0 )
|
||||
self.conf.createVertical ( contact1, contact2, xaxis , 0 )
|
||||
self.conf.createHorizontal( contact2, pinRp , yaxisPin, 0 )
|
||||
trace( 550, '\txaxis(track)={}\n'.format(DbU.getValueString(xaxis)) )
|
||||
return
|
||||
|
||||
def connectClocks ( self ):
|
||||
if not self.conf.useClockTree:
|
||||
print( WarningMessage( "Clock tree generation has been disabled ('chip.clockTree':False)." ))
|
||||
return
|
||||
if len(self.conf.coronaCks) == 0:
|
||||
raise ErrorMessage( 1, 'Cannot build clock terminal as no clock is not known.' )
|
||||
return
|
||||
for i in range(len(self.conf.coronaCks)):
|
||||
self._connectClock( self.conf.coronaCks[i], i+2 )
|
||||
def connectHTrees ( self, hTrees ):
|
||||
for i in range(len(hTrees)):
|
||||
self._connectHTree( hTrees[i].treeNet, i+2 )
|
||||
|
||||
def doLayout ( self ):
|
||||
with UpdateSession():
|
||||
|
|
|
@ -323,6 +323,7 @@ namespace Etesian {
|
|||
, _fixedAbWidth (0)
|
||||
, _diodeCount (0)
|
||||
, _bufferCount (0)
|
||||
, _excludedNets ()
|
||||
{ }
|
||||
|
||||
|
||||
|
@ -792,7 +793,7 @@ namespace Etesian {
|
|||
cmess1 << " - Building RoutingPads (transhierarchical)" << endl;
|
||||
//getCell()->flattenNets( Cell::Flags::BuildRings|Cell::Flags::NoClockFlatten );
|
||||
//getCell()->flattenNets( getBlockInstance(), Cell::Flags::NoClockFlatten );
|
||||
getCell()->flattenNets( NULL, Cell::Flags::NoClockFlatten );
|
||||
getCell()->flattenNets( NULL, _excludedNets, Cell::Flags::NoClockFlatten );
|
||||
|
||||
bool tooManyInstances = false;
|
||||
index_t instanceId = 0;
|
||||
|
@ -929,9 +930,10 @@ namespace Etesian {
|
|||
for ( Net* net : getCell()->getNets() )
|
||||
{
|
||||
const char* excludedType = NULL;
|
||||
if (net->getType() == Net::Type::POWER ) excludedType = "POWER";
|
||||
if (net->getType() == Net::Type::GROUND) excludedType = "GROUND";
|
||||
if (net->getType() == Net::Type::CLOCK ) excludedType = "CLOCK";
|
||||
if (net->getType() == Net::Type::POWER ) excludedType = "POWER";
|
||||
if (net->getType() == Net::Type::GROUND) excludedType = "GROUND";
|
||||
if (net->getType() == Net::Type::CLOCK ) excludedType = "CLOCK";
|
||||
if (isExcluded(getString(net->getName()))) excludedType = "USER_EXCLUDED";
|
||||
if (excludedType) {
|
||||
cparanoid << Warning( "%s is not a routable net (%s,excluded)."
|
||||
, getString(net).c_str(), excludedType ) << endl;
|
||||
|
@ -952,9 +954,10 @@ namespace Etesian {
|
|||
for ( Net* net : getCell()->getNets() )
|
||||
{
|
||||
const char* excludedType = NULL;
|
||||
if (net->getType() == Net::Type::POWER ) excludedType = "POWER";
|
||||
if (net->getType() == Net::Type::GROUND) excludedType = "GROUND";
|
||||
if (net->getType() == Net::Type::CLOCK ) excludedType = "CLOCK";
|
||||
if (net->getType() == Net::Type::POWER ) excludedType = "POWER";
|
||||
if (net->getType() == Net::Type::GROUND) excludedType = "GROUND";
|
||||
if (net->getType() == Net::Type::CLOCK ) excludedType = "CLOCK";
|
||||
if (isExcluded(getString(net->getName()))) excludedType = "USER_EXCLUDED";
|
||||
if (excludedType) continue;
|
||||
if (af->isBLOCKAGE(net->getName())) continue;
|
||||
|
||||
|
|
|
@ -456,6 +456,8 @@ namespace Etesian {
|
|||
BufferDatas* bufferDatas = getBufferCells().getBiggestBuffer();
|
||||
vector< tuple<Net*,uint32_t> > netDatas;
|
||||
for ( Net* net : getCell()->getNets() ) {
|
||||
if (isExcluded(getString(net->getName()))) continue;
|
||||
|
||||
uint32_t rpCount = 0;
|
||||
for ( RoutingPad* rp : net->getRoutingPads() ) {
|
||||
Occurrence rpOcc = rp->getPlugOccurrence();
|
||||
|
|
|
@ -77,13 +77,14 @@ extern "C" {
|
|||
DirectVoidMethod(EtesianEngine,etesian,clearColoquinte)
|
||||
DirectVoidMethod(EtesianEngine,etesian,flattenPower)
|
||||
DirectVoidMethod(EtesianEngine,etesian,toHurricane)
|
||||
DirectGetUIntAttribute (PyEtesianEngine_doHFNS ,doHFNS ,PyEtesianEngine,EtesianEngine)
|
||||
DirectSetLongAttribute (PyEtesianEngine_setFixedAbHeight,setFixedAbHeight,PyEtesianEngine,EtesianEngine)
|
||||
DirectSetLongAttribute (PyEtesianEngine_setFixedAbWidth ,setFixedAbWidth ,PyEtesianEngine,EtesianEngine)
|
||||
DirectSetDoubleAttribute(PyEtesianEngine_setSpaceMargin ,setSpaceMargin ,PyEtesianEngine,EtesianEngine)
|
||||
DirectSetDoubleAttribute(PyEtesianEngine_setAspectRatio ,setAspectRatio ,PyEtesianEngine,EtesianEngine)
|
||||
DirectGetLongAttribute (PyEtesianEngine_getFixedAbHeight,getFixedAbHeight,PyEtesianEngine,EtesianEngine)
|
||||
DirectGetLongAttribute (PyEtesianEngine_getFixedAbWidth ,getFixedAbWidth ,PyEtesianEngine,EtesianEngine)
|
||||
DirectGetUIntAttribute (PyEtesianEngine_doHFNS ,doHFNS ,PyEtesianEngine,EtesianEngine)
|
||||
DirectSetLongAttribute (PyEtesianEngine_setFixedAbHeight,setFixedAbHeight,PyEtesianEngine,EtesianEngine)
|
||||
DirectSetLongAttribute (PyEtesianEngine_setFixedAbWidth ,setFixedAbWidth ,PyEtesianEngine,EtesianEngine)
|
||||
DirectSetDoubleAttribute (PyEtesianEngine_setSpaceMargin ,setSpaceMargin ,PyEtesianEngine,EtesianEngine)
|
||||
DirectSetDoubleAttribute (PyEtesianEngine_setAspectRatio ,setAspectRatio ,PyEtesianEngine,EtesianEngine)
|
||||
DirectGetLongAttribute (PyEtesianEngine_getFixedAbHeight,getFixedAbHeight,PyEtesianEngine,EtesianEngine)
|
||||
DirectGetLongAttribute (PyEtesianEngine_getFixedAbWidth ,getFixedAbWidth ,PyEtesianEngine,EtesianEngine)
|
||||
DirectSetCStringAttribute(PyEtesianEngine_exclude ,exclude ,PyEtesianEngine,EtesianEngine)
|
||||
|
||||
|
||||
static PyObject* PyEtesianEngine_get ( PyObject*, PyObject* args )
|
||||
|
@ -236,6 +237,8 @@ extern "C" {
|
|||
, "Returns the Etesian engine attached to the Cell, None if there isn't." }
|
||||
, { "create" , (PyCFunction)PyEtesianEngine_create , METH_VARARGS|METH_STATIC
|
||||
, "Create an Etesian engine on this cell." }
|
||||
, { "exclude" , (PyCFunction)PyEtesianEngine_exclude , METH_VARARGS
|
||||
, "Add the specified net to the exclusion list." }
|
||||
, { "getFixedAbHeight" , (PyCFunction)PyEtesianEngine_getFixedAbHeight , METH_NOARGS
|
||||
, "Returns the forced abutment box height." }
|
||||
, { "getFixedAbWidth" , (PyCFunction)PyEtesianEngine_getFixedAbWidth , METH_NOARGS
|
||||
|
|
|
@ -71,11 +71,13 @@ namespace Etesian {
|
|||
typedef std::tuple<Instance*, std::vector<RoutingPad*> > InstanceInfos;
|
||||
typedef std::map<Instance*,size_t,DBo::CompareById> InstancesToIds;
|
||||
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;
|
||||
|
@ -106,6 +108,7 @@ namespace Etesian {
|
|||
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 );
|
||||
|
@ -136,6 +139,7 @@ namespace Etesian {
|
|||
uint32_t doHFNS ();
|
||||
inline void useFeed ( Cell* );
|
||||
size_t findYSpin ();
|
||||
inline void exclude ( string netName );
|
||||
void addFeeds ();
|
||||
void toHurricane ();
|
||||
void flattenPower ();
|
||||
|
@ -174,6 +178,7 @@ namespace Etesian {
|
|||
DbU::Unit _fixedAbWidth;
|
||||
uint32_t _diodeCount;
|
||||
uint32_t _bufferCount;
|
||||
NetNameSet _excludedNets;
|
||||
|
||||
protected:
|
||||
// Constructors & Destructors.
|
||||
|
@ -229,6 +234,8 @@ namespace Etesian {
|
|||
inline uint32_t EtesianEngine::_getNewDiodeId () { return _diodeCount++; }
|
||||
inline const Box& EtesianEngine::getPlaceArea () const { return _placeArea; }
|
||||
inline Area* EtesianEngine::getArea () const { return _area; }
|
||||
inline const EtesianEngine::NetNameSet&
|
||||
EtesianEngine::getExcludedNets () const { return _excludedNets; }
|
||||
|
||||
inline void EtesianEngine::setBlock ( Instance* block )
|
||||
{
|
||||
|
@ -319,6 +326,24 @@ namespace Etesian {
|
|||
}
|
||||
|
||||
|
||||
inline bool EtesianEngine::isExcluded ( string netName ) const
|
||||
{ return (_excludedNets.find(netName) != _excludedNets.end()); }
|
||||
|
||||
|
||||
inline void EtesianEngine::exclude ( string netName )
|
||||
{
|
||||
// Net* net = getCell()->getNet( netName );
|
||||
// if (not net) {
|
||||
// std::cerr << Error( "EtesianEngine::exclude(Net*): %s has no net named \"%s\"."
|
||||
// , getString(getCell()).c_str()
|
||||
// , netName.c_str()
|
||||
// ) << std::endl;
|
||||
// return;
|
||||
// }
|
||||
if (isExcluded(netName)) return;
|
||||
_excludedNets.insert( netName );
|
||||
}
|
||||
|
||||
// Variables.
|
||||
extern const char* missingEtesian;
|
||||
|
||||
|
|
|
@ -820,6 +820,13 @@ void Cell::flattenNets (uint64_t flags )
|
|||
|
||||
void Cell::flattenNets ( const Instance* instance, uint64_t flags )
|
||||
// ****************************************************************
|
||||
{
|
||||
static set<string> excludeds;
|
||||
flattenNets( instance, excludeds, flags );
|
||||
}
|
||||
|
||||
void Cell::flattenNets ( const Instance* instance, const std::set<string>& excludeds, uint64_t flags )
|
||||
// ***************************************************************************************************
|
||||
{
|
||||
cdebug_log(18,1) << "Cell::flattenNets() flags:0x" << hex << flags << endl;
|
||||
|
||||
|
@ -837,6 +844,7 @@ void Cell::flattenNets ( const Instance* instance, uint64_t flags )
|
|||
|
||||
if (net->isClock() and (flags & Flags::NoClockFlatten)) continue;
|
||||
if (net->isPower() or net->isGround() or net->isBlockage()) continue;
|
||||
if (excludeds.find(getString(occurrence.getName())) != excludeds.end()) continue;
|
||||
|
||||
HyperNet hyperNet ( occurrence );
|
||||
if ( not occurrence.getPath().isEmpty() ) {
|
||||
|
|
|
@ -728,9 +728,6 @@ void Net::_preDestroy()
|
|||
// *******************
|
||||
{
|
||||
cdebug_log(18,1) << "entering Net::_preDestroy: " << this << endl;
|
||||
if (getName() == "pipe_middle_0_rb[0]")
|
||||
cerr << "entering Net::_preDestroy: " << this << endl;
|
||||
|
||||
Inherit::_preDestroy();
|
||||
|
||||
cdebug_log(18,0) << "Net::_preDestroy: " << this << " slave Plugs..." << endl;
|
||||
|
|
|
@ -507,6 +507,7 @@ class Cell : public Entity {
|
|||
public: void setAbstractedSupply(bool state) { _flags.set(Flags::AbstractedSupply,state); };
|
||||
public: void flattenNets(uint64_t flags=Flags::BuildRings);
|
||||
public: void flattenNets(const Instance* instance, uint64_t flags=Flags::BuildRings);
|
||||
public: void flattenNets(const Instance* instance, const std::set<std::string>& excludeds, uint64_t flags=Flags::BuildRings);
|
||||
public: void createRoutingPadRings(uint64_t flags=Flags::BuildRings);
|
||||
public: void setFlags(uint64_t flags) { _flags |= flags; }
|
||||
public: void resetFlags(uint64_t flags) { _flags &= ~flags; }
|
||||
|
|
|
@ -29,6 +29,24 @@
|
|||
|
||||
namespace Isobar {
|
||||
|
||||
|
||||
bool pyListToStringSet ( PyObject* list, set<string>& v )
|
||||
{
|
||||
if (not PyList_Check(list)) return false;
|
||||
|
||||
int length = PyList_Size( list );
|
||||
for ( int i=0 ; i<length ; ++i ) {
|
||||
PyObject* item = PyList_GetItem( list, i );
|
||||
if (not PyString_Check(item)) {
|
||||
string message = "pyListToStringSet: Item at position " + getString(i) + " is not a string.";
|
||||
PyErr_SetString( ConstructorError, message.c_str() );
|
||||
return false;
|
||||
}
|
||||
v.insert( PyString_AsString(item) );
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
using namespace Hurricane;
|
||||
|
||||
|
@ -730,30 +748,36 @@ extern "C" {
|
|||
{
|
||||
cdebug_log(20,0) << "PyCell_flattenNets()" << endl;
|
||||
|
||||
Instance* instance = NULL;
|
||||
PyObject* arg0 = NULL;
|
||||
PyObject* arg1 = NULL;
|
||||
uint64_t flags = 0;
|
||||
set<string> excludeds;
|
||||
Instance* instance = NULL;
|
||||
PyObject* arg0 = NULL;
|
||||
PyObject* arg1 = NULL;
|
||||
PyObject* arg2 = NULL;
|
||||
|
||||
HTRY
|
||||
METHOD_HEAD ( "Cell.flattenNets()" )
|
||||
__cs.init( "Cell.flattenNets" );
|
||||
if (not PyArg_ParseTuple(args,"O&O&:Cell.flattenNets"
|
||||
,Converter,&arg0
|
||||
,Converter,&arg1
|
||||
)) {
|
||||
PyErr_SetString( ConstructorError, "Cell.flattenNets(): Takes exactly two parameters." );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (arg0 == Py_None) {
|
||||
cell->flattenNets( NULL, PyInt_AsLong(arg1) );
|
||||
} else if (__cs.getObjectIds() == ":ent:int") {
|
||||
cell->flattenNets( PYINSTANCE_O(arg0), PyInt_AsLong(arg1) );
|
||||
} else {
|
||||
string message = "Cell.flattenNets(): Bad type of parameter(s), \"" + __cs.getObjectIds() + "\".";
|
||||
PyErr_SetString( ConstructorError, message.c_str() );
|
||||
if (not PyArg_ParseTuple(args,"OO|O:Cell.flattenNets", &arg0, &arg1, &arg2 )) {
|
||||
PyErr_SetString( ConstructorError, "Cell.flattenNets(): Takes between two and three parameters." );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (arg0 != Py_None) {
|
||||
if (not IsPyInstance(arg0)) {
|
||||
PyErr_SetString( ConstructorError, "Cell.flattenNets(): First argument must be None or an Instance." );
|
||||
return NULL;
|
||||
}
|
||||
instance = PYINSTANCE_O( arg0 );
|
||||
}
|
||||
if (arg2) {
|
||||
pyListToStringSet( arg1, excludeds );
|
||||
flags = PyInt_AsLong( arg2 );
|
||||
} else {
|
||||
flags = PyInt_AsLong( arg1 );
|
||||
}
|
||||
|
||||
cell->flattenNets( instance, excludeds, flags );
|
||||
HCATCH
|
||||
Py_RETURN_NONE;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue