from __future__ import print_function
import sys
-import Anabatic
import CRL
import Cfg
-import Etesian
-import Katana
-from Hurricane import (
- DbU, DataBase, UpdateSession, Box, Transformation, Instance, Pin,
- NetExternalComponents,
-)
-from helpers import l
+from Hurricane import Box
from plugins import RSavePlugin
from coriolis2.settings import af
-from utils import Module
+from utils import Module, SessionManager
import symbolic.cmos # do not remove
BIT_WIDTH = 16
-def get_layer(name, layer_cache={}):
- """ Creates a new layer or returns it from cache. """
- if name in layer_cache:
- return layer_cache[name]
-
- layer = DataBase.getDB().getTechnology().getLayer(name)
- layer_cache[name] = layer
- return layer
-
-
-def to_DbU(l):
- """
- Convert lambdas to database units. (See Hurricane+Python Manual 3.4.)
- """
- return DbU.fromLambda(l)
-
-
-def from_DbU(ph):
- """
- Convert database units to lambdas. (See Hurricane+Python Manual 3.4.)
- """
- return DbU.toLambda(ph)
-
-
-def create_pins(cell, net, name, direction,
- status=Pin.PlacementStatus.FIXED, layer=None,
- x=0.0, y=0.0, width=2.0, height=2.0,
- repeat=1, delta=0.0, external=True):
- """Creates a series of pins in a cell.
-
- :param cell: Hurricane.Cell object to place pins onto, or object name,
- :param net: Hurricane.Net object name or name template, taking a pin
- enumeration parameter, i. e. pin number,
- :param name: pin name or name template taking a pin enumeration parameter,
- :param direction: Pin.Direction value,
- :param status: Pin.PlacementStatus value (default is FIXED),
- :param layer: Hurricane.Layer object or name (METAL3),
- :param x: starting pin position (left to right, 0.0),
- :param y: starting pin position (bottom to top, 0.0),
- :param width: pin width (2,0),
- :param height: pin height (2.0),
- :param repeat: a number of pins to be placed or an iterable containing
- pin template parameters (i. e. pin number, 1),
- :param delta: next pin position offset (0.0),
- :param external: mark pin as external (yes),
- :return: tuple of next pin coordinates, or just (x, y), if delta was not
- provided.
- """
- if isinstance(cell, basestring):
- cell = af.getCell(cell, CRL.Catalog.State.Logical)
-
- if layer is None:
- layer = 'METAL3'
- if isinstance(layer, basestring):
- layer = get_layer(layer)
-
- if isinstance(repeat, int):
- if repeat > 1 and delta == 0.0:
- raise Warning('You are trying to place pins on each other.')
- iterator = range(repeat)
- else:
- iterator = repeat
-
- for i in iterator:
- pin = Pin.create(cell.getNet(net.format(i)), name.format(i),
- direction, status, layer,
- l(x), l(y), l(width), l(height))
- if direction in (Pin.Direction.NORTH, Pin.Direction.SOUTH):
- x += delta
- else:
- # EAST or WEST
- y += delta
-
- if external:
- pin.getNet().setExternal(True)
- NetExternalComponents.setExternal(pin)
-
- return x, y
-
-
-def place_and_route(cell):
- """
- Places and routes.
-
- :param cell: Hurricane.Cell object to operate on,
- :return: True on success, False otherwise.
- """
- 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 coriolis_setup():
Cfg.Configuration.pushDefaultPriority(Cfg.Parameter.Priority.UserFile)
-
- env = af.getEnvironment()
-
Cfg.getParamBool('misc.catchCore').setBool(False)
Cfg.getParamBool('misc.info').setBool(False)
Cfg.getParamBool('misc.paranoid').setBool(False)
Cfg.Configuration.popDefaultPriority()
-def alu16(editor=None, **kwargs):
+class AddSub(Module):
+
+ def do(self):
+ """ Main routine. """
+
+ with SessionManager():
+ self.init_abutment_box()
+ self.create_pins()
- db = DataBase.getDB()
- print(db, dir(db))
- METAL2 = get_layer('METAL2')
+ if self.editor:
+ self.editor.setCell(self.cell)
- cell = af.getCell('alu16', CRL.Catalog.State.Logical)
- if not cell:
- print('[ERROR] Unable to load cell "alu16.vst", aborting .')
- return False
+ result = self.place_and_route()
- width, height = 1100.0, 600.0
- ab = Box(l(0.0), l(0.0), l(width), l(height))
+ with SessionManager():
+ self.create_pads()
- UpdateSession.open()
- cell.setAbutmentBox(ab)
+ RSavePlugin.ScriptMain(editor=self.editor, cell=self.cell)
+ return result
- # get instances inside cell
- instances = cell.getInstances()
- # find adder instance
- add_inst = [x for x in instances if x.getName().endswith('add')][0]
- add_inst.setTransformation(Transformation(to_DbU(25.0), to_DbU(75.0),
- Transformation.Orientation.ID))
- add_inst.setPlacementStatus(Instance.PlacementStatus.FIXED)
+class ALU16(Module):
- # find subtractor instance
- sub_inst = [x for x in instances if x.getName().endswith('sub')][0]
- sub_inst.setTransformation(Transformation(to_DbU(725.0), to_DbU(75.0),
- Transformation.Orientation.ID))
- sub_inst.setPlacementStatus(Instance.PlacementStatus.FIXED)
+ def do(self):
- y_north = cell.getAbutmentBox().getYMax()
- create_pins(cell, 'a({})', 'a({}).0', Pin.Direction.SOUTH,
- x=50.0, y=0.0, delta=60.0, repeat=BIT_WIDTH)
- create_pins(cell, 'b({})', 'b({}).0', Pin.Direction.SOUTH,
- x=80.0, y=0.0, delta=60.0, repeat=BIT_WIDTH)
- create_pins(cell, 'o({})', 'o({}).0', Pin.Direction.NORTH,
- x=50.0, y=from_DbU(y_north),
- delta=60.0, repeat=BIT_WIDTH)
- create_pins(cell, 'rst', 'rst.0', Pin.Direction.WEST, layer=METAL2,
- x=0.0, y=140.0)
- UpdateSession.close()
+ if not self.do_submodules():
+ return False
- if editor:
- editor.setCell(cell)
+ with SessionManager():
+ self.init_abutment_box()
+ self.place_submodules()
- print("editor", editor, dir(editor))
+ # TODO: replace with some form of lazy evaluation?
+ y_north = self.from_dbu(self.cell.getAbutmentBox().getYMax())
+ for pin_conf in self.north_pins:
+ pin_conf['y'] = y_north
- # place first (in middle, between two)
- # this puts all the remaining cells (little ones)
- # into this (small) space so that they do not go
- # "all over the place" around the add and sub
- ab2 = Box(l(400.0), l(50.0), l(700.0), l(500.0))
+ self.create_pins()
- cell.setAbutmentBox(ab2)
- etesian = Etesian.EtesianEngine.create(cell)
- etesian.place()
+ if self.editor:
+ self.editor.setCell(self.cell)
- # then route (globally)
- # this connects up not just in the remaining (little) cells,
- # it connects *to add and sub and the outside world as well*
- cell.setAbutmentBox(ab)
+ # place first (in middle, between two)
+ # this puts all the remaining cells (little ones)
+ # into this (small) space so that they do not go
+ # "all over the place" around the add and sub
+ self.ab = Box(self.to_dbu(400.0), self.to_dbu(50.0),
+ self.to_dbu(700.0), self.to_dbu(500.0))
+ self.place()
- result = place_and_route(cell)
+ # then route (globally)
+ # this connects up not just in the remaining (little) cells,
+ # it connects *to add and sub and the outside world as well*
+ self.init_abutment_box()
+ result = self.place_and_route()
- cell.setName(cell.getName()+'_r')
- af.saveCell(cell, CRL.Catalog.State.Views)
- RSavePlugin.ScriptMain(editor=editor, cell=cell, **kwargs)
+ self.name = self.name + '_r'
+ self.af.saveCell(self.cell, CRL.Catalog.State.Views)
+ RSavePlugin.ScriptMain(editor=self.editor, cell=self.cell)
- return result
+ return result
def ScriptMain(editor=None, **kwargs):
coriolis_setup()
- add = Module(
+ add = AddSub(
'add', editor, width=350.0, height=400.0,
north_pins=[
{'net': 'a({})', 'x': 10.0, 'delta': 20.0, 'repeat': BIT_WIDTH},
south_pins=[
{'net': 'o({})', 'x': 100.0, 'delta': 10.0, 'repeat': BIT_WIDTH},
],
- pads={'b(15)': ('BLOCKAGE2', 'BLOCKAGE3', 'BLOCKAGE4')},
+ pads={
+ 'b({})'.format(BIT_WIDTH-1): (
+ 'BLOCKAGE2', 'BLOCKAGE3', 'BLOCKAGE4',
+ ),
+ },
)
-
- sub = Module(
+ sub = AddSub(
'sub', editor, width=350.0, height=400.0,
north_pins=[
{'net': 'a({})', 'x': 10.0, 'delta': 20.0, 'repeat': BIT_WIDTH},
south_pins=[
{'net': 'o({})', 'x': 100.0, 'delta': 10.0, 'repeat': BIT_WIDTH},
],
- pads={'b(15)': ('BLOCKAGE2', 'BLOCKAGE3', 'BLOCKAGE4')},
+ pads={
+ 'b({})'.format(BIT_WIDTH-1): (
+ 'BLOCKAGE2', 'BLOCKAGE3', 'BLOCKAGE4',
+ ),
+ },
)
- add.do()
- sub.do()
- return alu16(editor, **kwargs)
+ alu16 = ALU16(
+ 'alu16', editor, width=1100.0, height=600.0,
+ submodules=[(add, 25.0, 75.0), (sub, 725.0, 75.0)],
+ north_pins=[
+ {'net': 'o({})', 'x': 50.0, 'delta': 60.0, 'repeat': BIT_WIDTH},
+ {'net': 'op'},
+ ],
+ south_pins=[
+ {'net': 'a({})', 'x': 50.0, 'delta': 60.0, 'repeat': BIT_WIDTH},
+ {'net': 'b({})', 'x': 80.0, 'delta': 60.0, 'repeat': BIT_WIDTH},
+ ],
+ west_pins=[
+ {'net': 'rst', 'y': 140.0, 'layer': 'METAL2'},
+ ],
+ )
+ return alu16.do()
if __name__ == '__main__':