From: Jock Tanner Date: Fri, 13 Mar 2020 14:45:20 +0000 (+0000) Subject: Add experiment #7. X-Git-Tag: partial-core-ls180-gdsii~175 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=d9d23ead3891fd27550c98edd044acb225fa6ecd;p=soclayout.git Add experiment #7. --- diff --git a/experiments7/Makefile b/experiments7/Makefile new file mode 100755 index 0000000..37e242d --- /dev/null +++ b/experiments7/Makefile @@ -0,0 +1,26 @@ + LOGICAL_SYNTHESIS = Yosys + PHYSICAL_SYNTHESIS = Coriolis + DESIGN_KIT = sxlib + + USE_CLOCKTREE = No + USE_DEBUG = No + USE_KITE = No + + NETLISTS = alu16 \ + add \ + sub + PATTERNS = alu16_r + + + include ./mk/design-flow.mk + + +blif: alu16.blif +vst: alu16.vst +layout: alu16_r.ap +gds: alu16_r.gds + +lvx: lvx-alu16_r +druc: druc-alu16_r +view: cgt-alu16_r +sim: asimut-alu16_r diff --git a/experiments7/alu16.py b/experiments7/alu16.py new file mode 100644 index 0000000..8fa8055 --- /dev/null +++ b/experiments7/alu16.py @@ -0,0 +1,65 @@ +from nmigen import * +from nmigen.cli import rtlil + + +class Adder(Elaboratable): + def __init__(self, width): + self.a = Signal(width) + self.b = Signal(width) + self.o = Signal(width) + + def elaborate(self, platform): + m = Module() + m.d.comb += self.o.eq(self.a + self.b) + return m + + +class Subtractor(Elaboratable): + def __init__(self, width): + self.a = Signal(width) + self.b = Signal(width) + self.o = Signal(width) + + def elaborate(self, platform): + m = Module() + m.d.comb += self.o.eq(self.a - self.b) + return m + + +class ALU(Elaboratable): + def __init__(self, width): + self.op = Signal() + self.a = Signal(width) + self.b = Signal(width) + self.o = Signal(width) + + self.add = Adder(width) + self.sub = Subtractor(width) + + def elaborate(self, platform): + m = Module() + + m.submodules.add = self.add + m.submodules.sub = self.sub + m.d.comb += [ + self.add.a.eq(self.a), + self.sub.a.eq(self.a), + self.add.b.eq(self.b), + self.sub.b.eq(self.b), + ] + with m.If(self.op): + m.d.sync += self.o.eq(self.sub.o) + with m.Else(): + m.d.sync += self.o.eq(self.add.o) + return m + + +def create_ilang(dut, ports, test_name): + vl = rtlil.convert(dut, name=test_name, ports=ports) + with open("%s.il" % test_name, "w") as f: + f.write(vl) + + +if __name__ == "__main__": + alu = ALU(width=16) + create_ilang(alu, [alu.op, alu.a, alu.b, alu.o], "alu16") diff --git a/experiments7/coriolis2/__init__.py b/experiments7/coriolis2/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/experiments7/coriolis2/katana.py b/experiments7/coriolis2/katana.py new file mode 100644 index 0000000..2ad53d3 --- /dev/null +++ b/experiments7/coriolis2/katana.py @@ -0,0 +1,14 @@ + +from Hurricane import DebugSession + +#DebugSession.addToTrace( katana.getCell().getNet( 'abc_12494_n543' ) ) +#DebugSession.addToTrace( katana.getCell().getNet( 'dl(6)' ) ) +#DebugSession.addToTrace( katana.getCell().getNet( 'n0_dl_7_0_6' ) ) +#DebugSession.addToTrace( katana.getCell().getNet( 'abc_12509_n822' ) ) +#DebugSession.addToTrace( katana.getCell().getNet( 'abc_12509_n734' ) ) +#DebugSession.addToTrace( katana.getCell().getNet( 'abc_12509_n1386' ) ) +#DebugSession.addToTrace( katana.getCell().getNet( 'abc_12494_n763' ) ) +#DebugSession.addToTrace( katana.getCell().getNet( 'abc_12494_n800' ) ) +#DebugSession.addToTrace( katana.getCell().getNet( 'b(0)' ) ) +#DebugSession.addToTrace( katana.getCell().getNet( 'o_next(4)' ) ) +#DebugSession.addToTrace( katana.getCell().getNet( 'rst' ) ) diff --git a/experiments7/coriolis2/settings.py b/experiments7/coriolis2/settings.py new file mode 100644 index 0000000..be3fe76 --- /dev/null +++ b/experiments7/coriolis2/settings.py @@ -0,0 +1,56 @@ +# -*- Mode:Python -*- + +import os +import Cfg +import CRL +import Viewer +#import node180.scn6m_deep_09 +import symbolic.cmos +from helpers import l, u, n + + +Cfg.Configuration.pushDefaultPriority( Cfg.Parameter.Priority.UserFile ) + + +Viewer.Graphics.setStyle( 'Alliance.Classic [black]' ) + +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) ) + +Cfg.Configuration.popDefaultPriority() + +#cellsTop = os.path.abspath( os.getcwd()+'/../cells' ) +if os.environ.has_key('CELLS_TOP'): + cellsTop = os.environ['CELLS_TOP'] +else: + cellsTop = '../../../cells' + +af = CRL.AllianceFramework.get() +env = af.getEnvironment() +env.addSYSTEM_LIBRARY( library=cellsTop+'/nsxlib', mode=CRL.Environment.Prepend ) +env.addSYSTEM_LIBRARY( library=cellsTop+'/mpxlib', mode=CRL.Environment.Prepend ) +env.setCLOCK( '^clk$|m_clock' ) +env.setPOWER( 'vdd' ) +env.setGROUND( 'vss' ) + + +print 'Successfully read user configuration' + diff --git a/experiments7/doAlu16.py b/experiments7/doAlu16.py new file mode 100755 index 0000000..395b657 --- /dev/null +++ b/experiments7/doAlu16.py @@ -0,0 +1,539 @@ +#!/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 Net +from Hurricane import Contact +from Hurricane import Vertical +from Hurricane import Pad +from Hurricane import Pin +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 toDbU(l): return DbU.fromLambda(l) + + +def createVertical(contacts, x, layer, width=None): + def yincrease(lhs, rhs): + return int(lhs.getY() - rhs.getY()) + + contacts.sort(yincrease) + + if width is None: width = l(2.0) + + for i in range(1, len(contacts)): + print "create vert", contacts[i - 1], contacts[i], layer, x, width + v = Vertical.create(contacts[i - 1], contacts[i], layer, x, width) + print "v", v + + +def createHorizontal(contactPaths, y, layer, width=None): + def xincrease(lhs, rhs): + return int(lhs.getX() - rhs.getX()) + + contacts = contactPaths + + if width is None: width = toDbU(2.0) + + contacts.sort(xincrease) + + for i in range(1, len(contacts)): + Horizontal.create(contacts[i - 1], contacts[i], layer, y, width) + + +def build_downtrace(net, layer, x, y, y1): + contacts = \ + [Contact.create(net, layer, l(x), l(y), l(2.0), l(2.0)) + , Contact.create(net, layer, l(x), l(y1), l(2.0), l(2.0)) + ] + + createVertical(contacts, l(x), layer) + print "slaves", contacts[-1].getSlaveComponents() + for component in contacts[-1].getSlaveComponents(): + NetExternalComponents.setExternal(component) + + +def placeAndRoute(cell): + etesian = Etesian.EtesianEngine.create(cell) + etesian.place() + + katana = Katana.KatanaEngine.create(cell) + katana.digitalInit() + katana.runGlobalRouter(Katana.Flags.NoFlags) + katana.loadGlobalRouting(Anabatic.EngineLoadGrByNet) + katana.layerAssign(Anabatic.EngineNoNetLayerAssign) + katana.runNegociate(Katana.Flags.NoFlags) + katana.finalizeLayout() + success = katana.isDetailedRoutingSuccess() + katana.destroy() + + return success + + +def coriolisSetup(): + 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 ( 111 ) + # Cfg.getParamInt ( 'misc.maxTraceLevel' ).setInt ( 112 ) + 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.searchHalo').setInt(30) + 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(**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') + BLOCKAGE2 = DataBase.getDB().getTechnology().getLayer('BLOCKAGE2') + BLOCKAGE3 = DataBase.getDB().getTechnology().getLayer('BLOCKAGE3') + BLOCKAGE4 = DataBase.getDB().getTechnology().getLayer('BLOCKAGE4') + BLOCKAGE5 = DataBase.getDB().getTechnology().getLayer('BLOCKAGE5') + + cell = af.getCell('add', CRL.Catalog.State.Logical) + print cell.getNet('a(0)') + + if not cell: + print '[ERROR] Unable to load cell "add.vst", aborting .' + return False + + kw['cell'] = cell + + width = 350.0 + height = 400.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 + pin = Pin.create(cell.getNet('a(%d)' % i) + , 'a(%d).0' % i + , Pin.Direction.NORTH + , Pin.PlacementStatus.FIXED + , METAL3 + , l(x), l(y - 0) # Position. + , l(2.0), l(2.0) # Size. + ) + pin.getNet().setExternal(True) + NetExternalComponents.setExternal(pin) + for i in range(16): + if True: + pin = 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. + ) + pin.getNet().setExternal(True) + NetExternalComponents.setExternal(pin) + + 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 = 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. + ) + pin.getNet().setExternal(True) + NetExternalComponents.setExternal(pin) + if False: + pin = 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) + ) + pin.getNet().setExternal(True) + NetExternalComponents.setExternal(pin) + + UpdateSession.close() + + if True: + if editor: editor.setCell(cell) + + placeAndRoute(cell) + + UpdateSession.open() + blockageNet = cell.getNet('blockagenet') + + ab = cell.getAbutmentBox() + ab.inflate(toDbU(-5.0)) + Pad.create(net, BLOCKAGE2, ab) + Pad.create(net, BLOCKAGE3, ab) + Pad.create(net, BLOCKAGE4, ab) + # Pad.create( net, BLOCKAGE5, ab ) + UpdateSession.close() + + if False: + UpdateSession.open() + cell.setAbutmentBox(ab) + for i in range(16): + if True: + net = cell.getNet('b(%d)' % i) + x = 20.0 * i + 10.0 + 10 + y = height - 10 + build_downtrace(net, METAL2, x, y, y + 10) + UpdateSession.close() + + # af.saveCell( cell, CRL.Catalog.State.Views ) + plugins.RSavePlugin.ScriptMain(**kw) + + +# ------------------------------------------------------------------------------- +# sub + +def sub(**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') + BLOCKAGE2 = DataBase.getDB().getTechnology().getLayer('BLOCKAGE2') + BLOCKAGE3 = DataBase.getDB().getTechnology().getLayer('BLOCKAGE3') + BLOCKAGE4 = DataBase.getDB().getTechnology().getLayer('BLOCKAGE4') + BLOCKAGE5 = DataBase.getDB().getTechnology().getLayer('BLOCKAGE5') + + cell = af.getCell('sub', 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 = 400.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 + pin = Pin.create(cell.getNet('a(%d)' % i) + , 'a(%d).0' % i + , Pin.Direction.NORTH + , Pin.PlacementStatus.FIXED + , METAL3 + , l(x), l(y - 0) # Position. + , l(2.0), l(2.0) # Size. + ) + pin.getNet().setExternal(True) + NetExternalComponents.setExternal(pin) + + for i in range(16): + if True: + pin = 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. + ) + pin.getNet().setExternal(True) + NetExternalComponents.setExternal(pin) + + 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 = Pin.create(net + , 'b(%d).0' % i + , Pin.Direction.NORTH + , Pin.PlacementStatus.FIXED + , METAL3 + , l(x), l(y) # Position. + , l(2.0), l(2.0) # Size. + ) + pin.getNet().setExternal(True) + NetExternalComponents.setExternal(pin) + + if False: + pin = 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) + ) + pin.getNet().setExternal(True) + NetExternalComponents.setExternal(pin) + UpdateSession.close() + + if True: + if editor: editor.setCell(cell) + + placeAndRoute(cell) + + UpdateSession.open() + blockageNet = cell.getNet('blockagenet') + + ab = cell.getAbutmentBox() + ab.inflate(toDbU(-5.0)) + Pad.create(net, BLOCKAGE2, ab) + Pad.create(net, BLOCKAGE3, ab) + Pad.create(net, BLOCKAGE4, ab) + # Pad.create( net, BLOCKAGE5, ab ) + UpdateSession.close() + + if False: + UpdateSession.open() + cell.setAbutmentBox(ab) + for i in range(16): + if True: + net = cell.getNet('b(%d)' % i) + x = 20.0 * i + 10.0 + 10 + y = height - 10 + build_downtrace(net, METAL2, x, y, y + 10) + UpdateSession.close() + + # af.saveCell( cell, CRL.Catalog.State.Views ) + plugins.RSavePlugin.ScriptMain(**kw) + + +# ------------------------------------------------------------------------------- +# alu16() + +def alu16(**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') + + cell = af.getCell('add', CRL.Catalog.State.Views) + cell = af.getCell('sub', CRL.Catalog.State.Views) + cell = af.getCell('alu16', CRL.Catalog.State.Logical) + if not cell: + print '[ERROR] Unable to load cell "alu16.vst", aborting .' + return False + kw['cell'] = cell + + ab = Box(l(0.0) + , l(0.0) + , l(1050.0) + , l(700.0)) + + UpdateSession.open() + cell.setAbutmentBox(ab) + + ins = cell.getInstance('subckt_48_add') + ins.setTransformation(Transformation(toDbU(100.0), toDbU(150.0), + Transformation.Orientation.ID)) + ins.setPlacementStatus(Instance.PlacementStatus.FIXED) + + ins = cell.getInstance('subckt_49_sub') + ins.setTransformation(Transformation(toDbU(600.0), toDbU(150.0), + Transformation.Orientation.ID)) + ins.setPlacementStatus(Instance.PlacementStatus.FIXED) + + yNorth = cell.getAbutmentBox().getYMax() + + for i in range(16): + Pin.create(cell.getNet('a(%d)' % i) + , 'a(%d).0' % i + , Pin.Direction.SOUTH + , Pin.PlacementStatus.FIXED + , METAL3 + , l(60.0 * i + 50.0), l(0.0) # Position. + , l(2.0), l(2.0) # Size. + ) + Pin.create(cell.getNet('b(%d)' % i) + , 'b(%d).0' % i + , Pin.Direction.SOUTH + , Pin.PlacementStatus.FIXED + , METAL3 + , l(60.0 * i + 80.0), l(0.0) # Position. + , l(2.0), l(2.0) # Size. + ) + Pin.create(cell.getNet('o(%d)' % i) + , 'o(%d).0' % i + , Pin.Direction.NORTH + , Pin.PlacementStatus.FIXED + , METAL3 + , l(60.0 * i + 50.0), yNorth # Position. + , l(2.0), l(2.0) # Size. + ) + + Pin.create(cell.getNet('rst') + , 'rst.0' + , Pin.Direction.WEST + , Pin.PlacementStatus.FIXED + , METAL2 + , l(0.0) + , l(140.0) + , l(2.0) + , l(2.0) + ) + UpdateSession.close() + + if editor: editor.setCell(cell) + + print "editor", editor, dir(editor) + + success = placeAndRoute(cell) + + af.saveCell(cell, CRL.Catalog.State.Views) + plugins.RSavePlugin.ScriptMain(**kw) + + return success + + +def ScriptMain(**kw): + coriolisSetup() + add(**kw) + sub(**kw) + success = alu16(**kw) + return success + + +if __name__ == '__main__': + try: + kw = {} + success = ScriptMain(**kw) + shellSuccess = 0 + if not success: shellSuccess = 1 + except ImportError, e: + showPythonTrace(__file__, e, False) + sys.exit(1) + except Exception, e: + showPythonTrace(__file__, e) + sys.exit(2) + + sys.exit(shellSuccess) + +