--- /dev/null
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+import sys
+import re
+import traceback
+import os.path
+import optparse
+import Cfg
+import Hurricane
+from Hurricane import DbU
+from Hurricane import DataBase
+from Hurricane import UpdateSession
+from Hurricane import Breakpoint
+from Hurricane import Box
+from Hurricane import Transformation
+from Hurricane import Instance
+from Hurricane import Contact
+from Hurricane import Vertical
+from Hurricane import Horizontal
+from Hurricane import Pin
+from Hurricane import Net
+from Hurricane import NetExternalComponents
+import Viewer
+import CRL
+import Etesian
+import Anabatic
+import Katana
+import Unicorn
+from helpers import l, u, n
+import clocktree.ClockTree
+import plugins.RSavePlugin
+import plugins.ClockTreePlugin
+import symbolic.cmos
+
+af = CRL.AllianceFramework.get()
+
+
+def build_crosstrace(net, via, layer, x, x1, y):
+
+ contacts = \
+ [ Contact.create( net, via, l(x), l(y), l(1.0), l(1.0) )
+ , Contact.create( net, via, l(x1), l(y), l(1.0), l(1.0) )
+ ]
+
+ createHorizontal( contacts, l(y), layer )
+ print "slaves", contacts[-1].getSlaveComponents()
+ for component in contacts[-1].getSlaveComponents():
+ NetExternalComponents.setExternal(component)
+
+def build_downtrace(net, via, layer, x, y, y1):
+
+ contacts = \
+ [ Contact.create( net, via, l(x), l(y), l(1.0), l(1.0) )
+ , Contact.create( net, via, l(x), l(y1), l(1.0), l(1.0) )
+ ]
+
+ createVertical( contacts, l(x), layer )
+ print "slaves", contacts[-1].getSlaveComponents()
+ for component in contacts[-1].getSlaveComponents():
+ NetExternalComponents.setExternal(component)
+
+#print "af", dir(af)
+#sys.exit(0)
+
+Cfg.Configuration.pushDefaultPriority( Cfg.Parameter.Priority.UserFile )
+
+cellsTop = '~/alliance-check-toolkit/cells'
+env = af.getEnvironment()
+env.addSYSTEM_LIBRARY( library=cellsTop+'/nsxlib', mode=CRL.Environment.Prepend )
+env.addSYSTEM_LIBRARY( library=cellsTop+'/mpxlib', mode=CRL.Environment.Prepend )
+
+
+Cfg.getParamBool ( 'misc.catchCore' ).setBool ( False )
+Cfg.getParamBool ( 'misc.info' ).setBool ( False )
+Cfg.getParamBool ( 'misc.paranoid' ).setBool ( False )
+Cfg.getParamBool ( 'misc.bug' ).setBool ( False )
+Cfg.getParamBool ( 'misc.logMode' ).setBool ( True )
+Cfg.getParamBool ( 'misc.verboseLevel1' ).setBool ( True )
+Cfg.getParamBool ( 'misc.verboseLevel2' ).setBool ( True )
+Cfg.getParamInt ( 'misc.minTraceLevel' ).setInt ( 159 )
+#Cfg.getParamInt ( 'misc.maxTraceLevel' ).setInt ( 160 )
+Cfg.getParamEnumerate ( 'etesian.effort' ).setInt ( 2 )
+Cfg.getParamPercentage( 'etesian.spaceMargin' ).setPercentage( 20.0 )
+Cfg.getParamPercentage( 'etesian.aspectRatio' ).setPercentage( 100.0 )
+Cfg.getParamBool ( 'etesian.uniformDensity' ).setBool ( True )
+Cfg.getParamInt ( 'anabatic.edgeLenght' ).setInt ( 24 )
+Cfg.getParamInt ( 'anabatic.edgeWidth' ).setInt ( 8 )
+Cfg.getParamString ( 'anabatic.topRoutingLayer' ).setString ( 'METAL5')
+Cfg.getParamInt ( 'katana.eventsLimit' ).setInt ( 1000000 )
+Cfg.getParamInt ( 'katana.hTracksReservedLocal' ).setInt ( 7 )
+Cfg.getParamInt ( 'katana.vTracksReservedLocal' ).setInt ( 6 )
+#Cfg.getParamInt ( 'clockTree.minimumSide' ).setInt ( l(1000) )
+
+env = af.getEnvironment()
+env.setCLOCK( '^clk$|m_clock' )
+env.setPOWER( 'vdd' )
+env.setGROUND( 'vss' )
+
+Cfg.Configuration.popDefaultPriority()
+
+###################
+# add
+
+def add ( cell, **kw ):
+ editor = None
+ if kw.has_key('editor') and kw['editor']:
+ editor = kw['editor']
+
+ db = DataBase.getDB()
+ print db, dir(db)
+ metal2 = DataBase.getDB().getTechnology().getLayer( 'metal2' )
+ metal3 = DataBase.getDB().getTechnology().getLayer( 'metal3' )
+ metal5 = DataBase.getDB().getTechnology().getLayer( 'metal5' )
+
+ #cell = af.getCell( 'add', CRL.Catalog.State.Logical )
+ print cell.getNet('a(0)')
+
+ if not cell:
+ print '[ERROR] Unable to load cell "alu16.vst", aborting .'
+ return False
+ kw[ 'cell' ] = cell
+
+ width = 350.0
+ height = 405.0
+
+ ab = Box( l( 0.0 )
+ , l( 0.0 )
+ , l( width )
+ , l( height ) )
+
+ cellGauge = af.getCellGauge()
+ spaceMargin = (Cfg.getParamPercentage('etesian.spaceMargin').asPercentage()+5) / 100.0
+ aspectRatio = Cfg.getParamPercentage('etesian.aspectRatio').asPercentage() / 100.0
+ clocktree.ClockTree.computeAbutmentBox( cell,
+ spaceMargin, aspectRatio, cellGauge )
+ ab2 = cell.getAbutmentBox()
+ print "box", ab, ab.getHeight(), ab.getWidth()
+ print "calc box", ab2, ab2.getHeight(), ab2.getWidth()
+
+ #height = ab.getHeight()
+ #width = ab.getWidth()
+
+ #UpdateSession.open()
+ cell.setAbutmentBox( ab )
+
+ for i in range(16):
+ if True:
+ x = 20.0*i + 10.0
+ y = height
+ net = cell.getNet('a(%d)' % i)
+ print "net", net
+ Pin.create( net
+ , 'a(%d).0' % i
+ , Pin.Direction.NORTH
+ , Pin.PlacementStatus.FIXED
+ , metal3
+ , l( x ), l( y - 0 ) # Position.
+ , l( 2.0 ) , l( 2.0 ) # Size.
+ )
+ for i in range(16):
+ if True:
+ Pin.create( cell.getNet('o(%d)' % i)
+ , 'o(%d).0' % i
+ , Pin.Direction.SOUTH
+ , Pin.PlacementStatus.FIXED
+ , metal3
+ , l( 10.0*i + 100.0 ), l( 0) # Position.
+ , l( 2.0 ) , l( 2.0 ) # Size.
+ )
+
+ for i in range(16):
+ if True:
+ net = cell.getNet('b(%d)' % i)
+ x = 20.0*i + 10.0 + 10
+ y = height - 0
+ #build_downtrace(net, metal3, x, y+11, y)
+ #continue
+ Pin.create( net
+ , 'b(%d).0' % i
+ , Pin.Direction.NORTH
+ , Pin.PlacementStatus.FIXED
+ , metal3
+ , l( x ), l( y - 0 ) # Position.
+ , l( 2.0 ) , l( 2.0 ) # Size.
+ )
+ if False:
+ Pin.create( cell.getNet('rst')
+ , 'p_reset.0'
+ , Pin.Direction.WEST
+ , Pin.PlacementStatus.FIXED
+ , metal2
+ , l( 0.0 )
+ , l( 140.0 )
+ , l( 2.0 )
+ , l( 2.0 )
+ )
+ #UpdateSession.close()
+
+ if True:
+ if editor: editor.setCell( cell )
+
+ etesian = Etesian.EtesianEngine.create(cell)
+ etesian.place()
+
+ katana = Katana.KatanaEngine.create(cell)
+ katana.digitalInit ()
+ #katana.runNegociatePreRouted()
+ print dir(katana)
+ katana.runGlobalRouter (0)
+ katana.loadGlobalRouting ( Anabatic.EngineLoadGrByNet )
+ katana.layerAssign ( Anabatic.EngineNoNetLayerAssign )
+ katana.runNegociate ( Katana.Flags.NoFlags )
+ katana.finalizeLayout ()
+ print dir(katana)
+ success = katana.getSuccessState()
+ katana.destroy()
+
+ if False:
+ VIA23 = DataBase.getDB().getTechnology().getLayer( 'VIA23' )
+ UpdateSession.open()
+ #net = cell.getNet('b(%d)' % 0)
+ net = cell.getNet('vdd')
+ build_downtrace(net, VIA23, metal2, -5, -10, -20)
+ build_downtrace(net, VIA23, metal2, -10, -10, -20)
+ build_crosstrace(net, VIA23, metal2, -5, -10, -10)
+ build_crosstrace(net, VIA23, metal2, -5, -10, -20)
+ for i in range(16):
+ if False:
+ net = cell.getNet('b(%d)' % i)
+ x = 20.0*i + 10.0 + 10
+ y = height-10
+ build_downtrace(net, metal2, x, y, y+10)
+ ab.inflate ( l(30.0) )
+ cell.setAbutmentBox( ab )
+ UpdateSession.close()
+
+ #af.saveCell( cell, CRL.Catalog.State.Views )
+ #plugins.RSavePlugin.ScriptMain( **kw )
+
+
+
+#def toDbU(v): return DbU.fromLambda(v)
+def toDbU(v): return l(v)
+
+
+
+def doBreak(level, message):
+ UpdateSession.close()
+ Breakpoint.stop(level, message)
+ UpdateSession.open()
+
+
+class Model (object):
+
+ HorizontalAccess = 1
+ VerticalAccess = 2
+
+ def __init__(self, modelName):
+ UpdateSession.open()
+ self.fillerCount = 0
+ self.af = CRL.AllianceFramework.get()
+ #self.cell = af.createCell(modelName)
+ self.cell = af.getCell( modelName, CRL.Catalog.State.Logical )
+ self.createNet('vss', direction=Net.Direction.IN,
+ isExternal=True, isGlobal=True, type=Net.Type.POWER)
+ self.createNet('vdd', direction=Net.Direction.IN,
+ isExternal=True, isGlobal=True, type=Net.Type.GROUND)
+
+ self.build()
+ UpdateSession.close()
+ return
+
+ def createNet(self, netName, **attributes):
+ net = self.cell.getNet(netName)
+ if not net:
+ net = Net.create(self.cell, netName)
+
+ if 'direction' in attributes:
+ net.setDirection(attributes['direction'])
+ if 'isExternal' in attributes:
+ net.setExternal(attributes['isExternal'])
+ if 'isGlobal' in attributes:
+ net.setGlobal(attributes['isGlobal'])
+ if 'type' in attributes:
+ net.setType(attributes['type'])
+ return net
+
+ def getNet(self, netName):
+ return self.createNet(netName)
+
+ def connect(self, instanceRef, pin, netRef):
+ if isinstance(instanceRef, str):
+ instance = self.getInstance(instanceRef)
+ else:
+ instance = instanceRef
+
+ if isinstance(netRef, str):
+ net = self.getNet(netRef)
+ else:
+ net = netRef
+
+ masterNet = instance.getMasterCell().getNet(pin)
+ if not masterNet:
+ print '[ERROR] Master cell "%s" of instance "%s" ' \
+ 'has no connector named "%s".' \
+ % (instance.getMasterCell().getName(), instance.getName(), pin)
+
+ instance.getPlug(instance.getMasterCell().getNet(pin)).setNet(net)
+ return
+
+ def place(self, instanceRef, x, y, orient):
+ if isinstance(instanceRef, str):
+ instance = self.getInstance(instanceRef)
+ else:
+ instance = instanceRef
+
+ instance.setTransformation(Transformation(x, y, orient))
+ instance.setPlacementStatus(Instance.PlacementStatus.PLACED)
+ return
+
+ def createInstance(self, instanceName, modelRef, portmap={}, transf=None):
+ instance = self.cell.getInstance(instanceName)
+ if not instance:
+ if isinstance(modelRef, str):
+ model = af.getCell(modelRef, CRL.Catalog.State.Views)
+ else:
+ model = modelRef
+ instance = Instance.create(self.cell, instanceName, model)
+ for pin, net in portmap.items():
+ self.connect(instance, pin, net)
+
+ if transf:
+ self.place(instance, transf[0], transf[1], transf[2])
+ return instance
+
+ def createAccess(self, termPath, x, y, flags):
+ insName, pinName = termPath.split('.')
+ instance = self.cell.getInstance(insName)
+ if not instance:
+ print '[ERROR] Model "%s" has no instance named "%s"' \
+ % (self.cell.getName(), insName)
+ try:
+ plug = instance.getPlug(instance.getMasterCell().getNet(pinName))
+ except BaseException:
+ print '[ERROR] Model "%s" of instance "%s" has ' \
+ 'no terminal named "%s"' \
+ % (instance.getMasterCell().getName(),
+ instance.getName(), pinName)
+
+ net = plug.getNet()
+ VIA12 = self.getLayer('VIA12')
+ VIA23 = self.getLayer('VIA23')
+ METAL2 = self.getLayer('METAL2')
+
+ rp = RoutingPad.create(
+ net, Occurrence(plug), RoutingPad.BiggestArea)
+ rpCenter = rp.getPosition()
+
+ if y is None:
+ y = rpCenter.getY()
+ contact1 = Contact.create(rp, VIA12, toDbU(0.0), y - rpCenter.getY())
+
+ if flags & Model.VerticalAccess:
+ contact2 = contact1
+ contact1 = Contact.create(net, VIA23, x, y)
+ Horizontal.create(contact2, contact1, METAL2, y, toDbU(2.0))
+ return contact1
+
+ def createVertical(self, contacts, x, width=None, layer=None):
+ def yincrease(lhs, rhs): return int(lhs.getY() - rhs.getY())
+
+ contacts.sort(yincrease)
+
+ if width is None:
+ width = toDbU(2.0)
+
+ if layer is None:
+ layer = self.getLayer("METAL3")
+ for i in range(1, len(contacts)):
+ Vertical.create(contacts[i - 1], contacts[i], layer, x, width)
+ return
+
+ def createHorizontal(self, contactPaths, y, width=None, layer=None):
+ def xincrease(lhs, rhs): return int(lhs.getX() - rhs.getX())
+
+ if isinstance(contactPaths[0], str):
+ contacts = []
+ for termPath in contactPaths:
+ contacts.append(self.createAccess(
+ termPath, None, y, Model.HorizontalAccess))
+ else:
+ contacts = contactPaths
+
+ if width is None:
+ width = toDbU(2.0)
+
+ contacts.sort(xincrease)
+
+ if layer is None:
+ layer = self.getLayer("METAL2")
+ for i in range(1, len(contacts)):
+ Horizontal.create(contacts[i - 1], contacts[i], layer, y, width)
+ return
+
+ def createSerpentine(
+ self, contactPaths, ymin, ymax, width=None, layer=None):
+ def xincrease(lhs, rhs): return int(lhs.getX() - rhs.getX())
+
+ if isinstance(contactPaths[0], str):
+ contacts = []
+ for termPath in contactPaths:
+ contacts.append(self.createAccess(
+ termPath, None, None, Model.HorizontalAccess))
+ else:
+ contacts = contactPaths
+
+ if len(contacts) != 2:
+ print '[ERROR] Model.createSerpentine() takes exactly ' \
+ 'two points, not %d.' % len( contacts)
+
+ if layer is None:
+ layer = self.getLayer("METAL2")
+ if width is None:
+ width = toDbU(2.0)
+
+ contacts.sort(xincrease)
+
+ turn0 = contacts[0]
+ trackPitch = toDbU(5.0)
+ for i in range((contacts[1].getX() - contacts[0].getX()) / trackPitch):
+ y = ymin
+ if i % 2:
+ y = ymax
+
+ x = turn0.getX()
+ turn1 = Contact.create(
+ turn0.getNet(), layer, x, y, width, width)
+ turn2 = Contact.create(
+ turn0.getNet(), layer, x + trackPitch, y, width, width)
+ Vertical .create(turn0, turn1, layer, x, width)
+ Horizontal.create(turn1, turn2, layer, y, width)
+
+ turn0 = turn2
+
+ Vertical.create(turn0, contacts[1], layer, contacts[1].getX(), width)
+
+ return
+
+ def addFillersRow(self, x, y, orient, length):
+ tieWidth = self.getMasterCell("tie_x0").getAbutmentBox().getWidth()
+ i = 0
+ for i in range(length / tieWidth):
+ self.createInstance(
+ "filler_%d_i" %
+ self. fillerCount, "tie_x0", transf=(
+ x + tieWidth * i, y, orient))
+ self.fillerCount += 1
+ if length % tieWidth:
+ delta = 0
+ if length > tieWidth:
+ delta = 1
+ self.createInstance("filler_%d_i" % self.fillerCount, "rowend_x0",
+ transf=(x + tieWidth * (i + delta), y, orient))
+ self.fillerCount += 1
+ return
+
+ def getLayer(self, name):
+ return DataBase.getDB().getTechnology().getLayer(name)
+
+ def getCell(self): return self.cell
+
+ def getMasterCell( self, name):
+ return self.af.getCell(name, CRL.Catalog.State.Views)
+
+ def setAbutmentBox(self, ab): self.cell.setAbutmentBox(ab)
+
+ def getAbutmentBox(self): return self.cell.getAbutmentBox()
+
+ def getCellWidth(self, name):
+ return self.getMasterCell(name).getAbutmentBox().getWidth()
+
+ def save(self):
+ self.af.saveCell(self.cell, CRL.Catalog.State.Physical)
+
+ def build(self):
+ print '[ERROR] Model.build() base class method should never be called.'
+
+
+class Add (Model):
+
+ def build(self):
+ #self.setAbutmentBox(
+ #Box(toDbU(0.0), toDbU(0.0), toDbU(1595.0), toDbU(450.0)))
+ add(self.cell)
+ self.buildPower()
+
+ def addFillers(self):
+ self.addFillersRow(toDbU(1580.0), toDbU(0.0),
+ Transformation.Orientation.ID, toDbU(15.0))
+ self.addFillersRow(toDbU(1570.0), toDbU(100.0),
+ Transformation.Orientation.MY, toDbU(5.0))
+ self.addFillersRow(toDbU(1570.0), toDbU(100.0),
+ Transformation.Orientation.ID, toDbU(25.0))
+ self.addFillersRow(toDbU(1530.0), toDbU(200.0),
+ Transformation.Orientation.MY, toDbU(45.0))
+ self.addFillersRow(toDbU(1550.0), toDbU(200.0),
+ Transformation.Orientation.ID, toDbU(10.0))
+ self.addFillersRow(toDbU(1550.0), toDbU(300.0),
+ Transformation.Orientation.MY, toDbU(25.0))
+ self.addFillersRow(toDbU(1570.0), toDbU(300.0),
+ Transformation.Orientation.ID, toDbU(25.0))
+ self.addFillersRow(toDbU(1550.0), toDbU(400.0),
+ Transformation.Orientation.MY, toDbU(25.0))
+
+ def buildPower(self):
+ METAL1 = self.getLayer("METAL1")
+ METAL2 = self.getLayer("METAL2")
+ METAL3 = self.getLayer("METAL3")
+ VIA12 = self.getLayer("VIA12")
+ VIA23 = self.getLayer("VIA23")
+ powerWidth = toDbU(2.0)
+ powerSpacing = toDbU(5.0)
+ ab = self.getAbutmentBox()
+ vdd = self.getNet("vdd")
+ vss = self.getNet("vss")
+ vddAxis = Box(ab).inflate(powerSpacing + powerWidth / 2)
+ vssAxis = Box(ab).inflate(
+ powerSpacing + powerWidth / 2 + powerWidth + toDbU(5.0))
+
+ # Building "vdd" power ring.
+ westContactsVdd = [
+ Contact.create( vdd, VIA23, vddAxis.getXMin(), vddAxis.getYMin(),
+ powerWidth, powerWidth),
+ Contact.create( vdd, VIA23, vddAxis.getXMin(), vddAxis.getYMax(),
+ powerWidth, powerWidth)]
+ eastContactsVdd = [
+ Contact.create( vdd, VIA23, vddAxis.getXMax(), vddAxis.getYMin(),
+ powerWidth, powerWidth),
+ Contact.create( vdd, VIA23, vddAxis.getXMax(), vddAxis.getYMax(),
+ powerWidth, powerWidth)]
+
+ for i in range(0):
+ ywidth = toDbU(12.0)
+ if i == 4:
+ ywidth = toDbU(6.0)
+ yaxis = ab.getXMin() + toDbU(50.0) * (1 + i * 2)
+
+ westContact = Contact.create( vdd, VIA12, vddAxis.getXMin(),
+ yaxis, powerWidth, ywidth)
+ eastContact = Contact.create( vdd, VIA12, vddAxis.getXMax(),
+ yaxis, powerWidth, ywidth)
+ self.createHorizontal( [westContact, eastContact],
+ yaxis, ywidth, layer=METAL1)
+
+ westContact = Contact.create(
+ vdd, VIA23, vddAxis.getXMin(), yaxis, powerWidth, ywidth)
+ eastContact = Contact.create(
+ vdd, VIA23, vddAxis.getXMax(), yaxis, powerWidth, ywidth)
+
+ westContactsVdd.insert(-1, westContact)
+ eastContactsVdd.insert(-1, eastContact)
+
+ self.createVertical(westContactsVdd, vddAxis.getXMin(), powerWidth)
+ self.createVertical(eastContactsVdd, vddAxis.getXMax(), powerWidth)
+
+ xcenter = vddAxis.getCenter().getX() + powerWidth / 2 + toDbU(5.0)
+ if False:
+ accessContactsVdd = [
+ Contact.create(
+ vdd,
+ VIA23,
+ xcenter,
+ vddAxis.getYMax(),
+ powerWidth,
+ powerWidth),
+ Contact.create(
+ vdd,
+ METAL3,
+ xcenter,
+ toDbU(528.0),
+ powerWidth,
+ toDbU(2.0))]
+
+ northContactsVdd = \
+ [westContactsVdd[-1],
+ #accessContactsVdd[0],
+ eastContactsVdd[-1]
+ ]
+ southContactsVdd = \
+ [westContactsVdd[0], eastContactsVdd[0]
+ ]
+ self.createHorizontal(
+ southContactsVdd, vddAxis.getYMin(), powerWidth)
+ self.createHorizontal(
+ northContactsVdd, vddAxis.getYMax(), powerWidth)
+ #self.createVertical(
+ #accessContactsVdd, xcenter, powerWidth)
+ #for component in accessContactsVdd[-1].getSlaveComponents():
+ #NetExternalComponents.setExternal(component)
+
+ # Building "vss" power ring.
+ westContactsVss = [
+ Contact.create(
+ vss,
+ VIA23,
+ vssAxis.getXMin(),
+ vssAxis.getYMin(),
+ powerWidth,
+ powerWidth),
+ Contact.create(
+ vss,
+ VIA23,
+ vssAxis.getXMin(),
+ vssAxis.getYMax(),
+ powerWidth,
+ powerWidth)]
+ eastContactsVss = [
+ Contact.create(
+ vss,
+ VIA23,
+ vssAxis.getXMax(),
+ vssAxis.getYMin(),
+ powerWidth,
+ powerWidth),
+ Contact.create(
+ vss,
+ VIA23,
+ vssAxis.getXMax(),
+ vssAxis.getYMax(),
+ powerWidth,
+ powerWidth)]
+
+ for i in range(5):
+ ywidth = toDbU(12.0)
+ if i == 0:
+ ywidth = toDbU(6.0)
+ yaxis = ab.getXMin() + toDbU(50.0) * (i * 2)
+
+ westContact = Contact.create(
+ vss, VIA12, vssAxis.getXMin(), yaxis, powerWidth, ywidth)
+ eastContact = Contact.create(
+ vss, VIA12, vssAxis.getXMax(), yaxis, powerWidth, ywidth)
+ self.createHorizontal(
+ [westContact, eastContact], yaxis, ywidth, layer=METAL1)
+
+ westContact = Contact.create(
+ vss, VIA23, vssAxis.getXMin(), yaxis, powerWidth, ywidth)
+ eastContact = Contact.create(
+ vss, VIA23, vssAxis.getXMax(), yaxis, powerWidth, ywidth)
+
+ westContactsVss.insert(-1, westContact)
+ eastContactsVss.insert(-1, eastContact)
+
+ self.createVertical(westContactsVss, vssAxis.getXMin(), powerWidth)
+ self.createVertical(eastContactsVss, vssAxis.getXMax(), powerWidth)
+
+ xcenter = vssAxis.getCenter().getX() - powerWidth / 2 - toDbU(5.0)
+ if False:
+ accessContactsVss = [
+ Contact.create(
+ vss,
+ VIA23,
+ xcenter,
+ vssAxis.getYMax(),
+ powerWidth,
+ powerWidth),
+ Contact.create(
+ vss,
+ METAL3,
+ xcenter,
+ toDbU(528.0),
+ powerWidth,
+ toDbU(2.0))]
+ northContactsVss = \
+ [westContactsVss[-1],
+ # accessContactsVss[0],
+ eastContactsVss[-1]
+ ]
+ southContactsVss = \
+ [westContactsVss[0], eastContactsVss[0]
+ ]
+
+ self.createHorizontal(
+ southContactsVss, vssAxis.getYMin(), powerWidth)
+ self.createHorizontal(
+ northContactsVss, vssAxis.getYMax(), powerWidth)
+ #self.createVertical(
+ # accessContactsVss, xcenter, powerWidth)
+ #for component in accessContactsVss[-1].getSlaveComponents():
+ #NetExternalComponents.setExternal(component)
+
+ ab.inflate(powerSpacing + powerWidth * 2 + toDbU(20.0))
+ self.setAbutmentBox(ab)
+
+ return
+
+
+def ScriptMain(**kw):
+ editor = None
+ if "editor" in kw and kw["editor"]:
+ editor = kw["editor"]
+
+ ringo = Add('add')
+ ringo.save()
+ if editor:
+ editor.setCell(ringo.getCell())
+ editor.fit()
+ return True
+
+
+if __name__ == "__main__":
+ ScriptMain()
+ sys.exit(0)