1 # -*- coding: utf-8 -*-
2 from __future__
import print_function
8 from Hurricane
import (
9 DbU
, DataBase
, UpdateSession
, Box
, Transformation
, Instance
, Pad
, Pin
,
10 NetExternalComponents
,
12 from plugins
import RSavePlugin
20 def __init__(self
, cell
, editor
, width
=None, height
=None, submodules
=None,
21 pin_width
=2.0, pin_height
=2.0, pin_suffix
='.0',
22 pin_layer
=None, north_pins
=None, east_pins
=None,
23 south_pins
=None, west_pins
=None, pads
=None, **kwargs
):
27 :param cell: cell name or Hurricane.Cell object,
28 :param editor: editor object when executing from cgt (or None),
29 :param width: module width,
30 :param height: module height,
31 :param submodules: submodules (Module objects),
32 :param pin_width: default pin width,
33 :param pin_height: default pin height,
34 :param pin_suffix: default pin suffix,
35 :param pin_layer: default layer for placing pins,
36 :param north_pins: list of pin configuration dictionaries for placing
37 pins on the north side,
38 :param east_pins: ditto (for the east side),
39 :param south_pins: ditto (for the south side),
40 :param west_pins: ditto (for the west side),
41 :param pads: dictionary of {net: list of layers} for creating pads,
42 :param kwargs: extra parameters to be implemented in derived classes.
45 self
.af
= CRL
.AllianceFramework
.get()
46 self
.db
= DataBase
.getDB()
50 if isinstance(cell
, basestring
):
51 self
.cell
= self
.af
.getCell(cell
, CRL
.Catalog
.State
.Logical
)
55 self
.pin_width
= pin_width
56 self
.pin_height
= pin_height
57 self
.pin_suffix
= pin_suffix
59 self
.pin_layer
= self
.get_layer('METAL3')
60 elif isinstance(pin_layer
, basestring
):
61 self
.pin_layer
= self
.get_layer(pin_layer
)
63 self
.pin_layer
= pin_layer
64 self
.north_pins
= north_pins
or []
65 self
.east_pins
= east_pins
or []
66 self
.south_pins
= south_pins
or []
67 self
.west_pins
= west_pins
or []
69 self
.pads
= pads
or {}
71 self
.submodules
= submodules
or []
75 return self
.cell
.getName()
82 """ The real abutment box. """
83 return self
.cell
.getAbutmentBox()
87 self
.cell
.setAbutmentBox(ab
)
91 """ Cached instances. """
92 if self
._instances
is None:
93 self
._instances
= self
.cell
.getInstances()
95 return self
._instances
97 def get_layer(self
, name
):
98 """ Creates a new layer or returns it from cache. """
99 if name
in self
._layer
_cache
:
100 return self
._layer
_cache
[name
]
102 layer
= self
.db
.getTechnology().getLayer(name
)
103 self
._layer
_cache
[name
] = layer
109 Convert lambdas to database units. (See Hurricane+Python Manual 3.4.)
111 return DbU
.fromLambda(lmb
)
116 Convert lambdas to database units. (See Hurricane+Python Manual 3.4.)
118 return DbU
.toLambda(dbu
)
120 def place_and_route(self
):
121 """ Places and routes. """
124 etesian
= Etesian
.EtesianEngine
.create(self
.cell
)
127 katana
= Katana
.KatanaEngine
.create(self
.cell
)
129 katana
.runGlobalRouter(Katana
.Flags
.NoFlags
)
130 katana
.loadGlobalRouting(Anabatic
.EngineLoadGrByNet
)
131 katana
.layerAssign(Anabatic
.EngineNoNetLayerAssign
)
132 katana
.runNegociate(Katana
.Flags
.NoFlags
)
133 katana
.finalizeLayout()
134 result
= katana
.isDetailedRoutingSuccess()
137 UpdateSession
.close()
140 def create_pin_series(self
, net
, direction
, name
=None,
141 status
=Pin
.PlacementStatus
.FIXED
, layer
=None,
142 x
=None, y
=None, width
=2.0, height
=2.0,
143 repeat
=1, delta
=0.0, external
=True):
145 Creates a series of pins in a cell.
147 :param net: Hurricane.Net object name or name template, taking a pin
148 enumeration parameter, i. e. pin number,
149 :param name: pin name or name template taking a pin enumeration
150 parameter (net name or template + suffix),
151 :param direction: Pin.Direction value,
152 :param status: Pin.PlacementStatus value (default is FIXED),
153 :param layer: Hurricane.Layer object or name (METAL3),
154 :param x: starting pin position (left to right, 0.0),
155 :param y: starting pin position (bottom to top, 0.0),
156 :param width: pin width (2,0),
157 :param height: pin height (2.0),
158 :param repeat: a number of pins to be placed or an iterable containing
159 pin template parameters (i. e. pin number, 1),
160 :param delta: next pin position offset (0.0),
161 :param external: mark pin as external (yes),
162 :return: tuple of next pin coordinates, or just (x, y), if delta
166 layer
= self
.pin_layer
167 elif isinstance(layer
, basestring
):
168 layer
= self
.get_layer(layer
)
170 if isinstance(repeat
, int):
171 if repeat
> 1 and delta
== 0.0:
172 raise Warning('You are trying to place pins on each other.')
173 iterator
= range(repeat
)
178 name
= net
+ self
.pin_suffix
181 pin
= Pin
.create(self
.cell
.getNet(net
.format(i
)),
182 name
.format(i
), direction
, status
, layer
,
183 self
.to_dbu(x
), self
.to_dbu(y
),
184 self
.to_dbu(width
), self
.to_dbu(height
))
185 if direction
in (Pin
.Direction
.NORTH
, Pin
.Direction
.SOUTH
):
192 pin
.getNet().setExternal(True)
193 NetExternalComponents
.setExternal(pin
)
197 def init_abutment_box(self
):
198 """ Create the abutment box with object's initial values. """
201 self
.ab
= Box(0, 0, self
.to_dbu(self
.width
), self
.to_dbu(self
.height
))
202 UpdateSession
.close()
204 def create_pins(self
):
205 """ Creates all pins set on Module object creation. """
208 if direction
== Pin
.Direction
.EAST
:
209 return self
.from_dbu(self
.ab
.getWidth())
210 if direction
== Pin
.Direction
.WEST
:
215 if direction
== Pin
.Direction
.NORTH
:
216 return self
.from_dbu(self
.ab
.getHeight())
217 if direction
== Pin
.Direction
.SOUTH
:
223 for pins
, direction
in (
224 (self
.north_pins
, Pin
.Direction
.NORTH
),
225 (self
.east_pins
, Pin
.Direction
.EAST
),
226 (self
.south_pins
, Pin
.Direction
.SOUTH
),
227 (self
.west_pins
, Pin
.Direction
.WEST
),
229 last_x
= last_y
= 0.0
230 for pin_config
in pins
:
231 net
= pin_config
.pop('net')
232 name
= pin_config
.pop('name', net
+ self
.pin_suffix
)
233 layer
= pin_config
.pop('layer', self
.pin_layer
)
234 x
= pin_config
.pop('x', default_x())
235 y
= pin_config
.pop('y', default_y())
236 last_x
, last_y
= self
.create_pin_series(
237 net
, direction
, name
=name
, layer
=layer
, x
=x
, y
=y
,
240 UpdateSession
.close()
242 def create_pads_for_net(self
, net
, layers
):
244 Creates a series of pads for a given net.
246 :param net: net name or Hurricane.Net object to create pads for,
247 :param layers: list of layer names or Hurricane.Layer objects
251 temp_ab
.inflate(self
.to_dbu(-5.0))
252 if isinstance(net
, basestring
):
253 net
= self
.cell
.getNet(net
)
256 if isinstance(layer
, basestring
):
257 layer
= self
.get_layer(layer
)
258 Pad
.create(net
, layer
, temp_ab
)
260 def create_pads(self
):
261 """ Create all pads for a given Module object. """
265 for net
, layers
in self
.pads
.items():
266 self
.create_pads_for_net(net
, layers
)
268 UpdateSession
.close()
270 def do_submodules(self
):
271 """ Execute submodules and gather their status. """
273 for submodule
, x
, y
in self
.submodules
:
275 if not submodule
.do():
280 def place_submodules(self
):
281 """ Place submodules in the current module. """
283 for submodule
, x
, y
in self
.submodules
:
286 inst
for inst
in self
.instances
if inst
.getName().endswith(
292 instance
.setTransformation(Transformation(
293 self
.to_dbu(x
), self
.to_dbu(y
), Transformation
.Orientation
.ID
295 instance
.setPlacementStatus(Instance
.PlacementStatus
.FIXED
)
298 """ Main routine. """
300 if not self
.do_submodules():
303 self
.init_abutment_box()
308 self
.editor
.setCell(self
.cell
)
310 result
= self
.place_and_route()
314 RSavePlugin
.ScriptMain(editor
=self
.editor
, cell
=self
.cell
)