2 # -*- coding: utf-8 -*-
3 from __future__
import print_function
8 from Hurricane
import Box
9 from Hurricane
import Transformation
10 from Hurricane
import Breakpoint
11 from Hurricane
import Instance
12 from coriolis2
.settings
import af
13 from utils
import Module
, SessionManager
, Config
16 from helpers
.overlay
import UpdateSession
18 import symbolic
.cmos
# do not remove
21 widths
= {32: 600.0, 16: 490}
24 with
Config(Cfg
.Parameter
.Priority
.UserFile
) as cfg
:
25 cfg
.misc_catchCore
= False
27 cfg
.misc_paranoid
= False
29 cfg
.misc_logMode
= True
30 cfg
.misc_verboseLevel1
= True
31 cfg
.misc_verboseLevel2
= True
32 cfg
.etesian_effort
= 2
33 cfg
.etesian_spaceMargin
= "10.0%"
34 cfg
.etesian_aspectRatio
= "100.0%"
35 cfg
.etesian_uniformDensity
= True
36 cfg
.anabatic_edgeLenght
= 24
37 cfg
.anabatic_edgeWidth
= 8
38 cfg
.anabatic_topRoutingLayer
= 'METAL5'
39 cfg
.katana_searchHalo
= 30
40 cfg
.katana_eventsLimit
= 1000000
41 cfg
.katana_hTracksReservedLocal
= 7
42 cfg
.katana_vTracksReservedLocal
= 6
44 env
= af
.getEnvironment()
45 env
.setCLOCK('^clk$|m_clock')
55 with
SessionManager():
60 self
.editor
.setCell(self
.cell
)
62 result
= self
.place_and_route()
64 with
SessionManager():
73 def place_datapath(self
, datapath_insts
, x_orig
, y_orig
, fold
):
74 channel_sff1
= self
.to_dbu(0)
75 with
SessionManager():
76 slice_height
= self
.to_dbu(50.0)
77 for i
in range(len(datapath_insts
)):
79 x
= self
.to_dbu(x_orig
)
82 y
= self
.to_dbu(y_orig
) + slice_height
*(slice+1)
83 orient
= Transformation
.Orientation
.MY
85 y
= self
.to_dbu(y_orig
) + slice_height
*slice
86 orient
= Transformation
.Orientation
.ID
88 for (opname
, inst
) in datapath_insts
[i
]:
91 inst
.setTransformation(Transformation(x
, y
, orient
))
92 inst
.setPlacementStatus(Instance
.PlacementStatus
.PLACED
)
93 x
+= inst
.getAbutmentBox().getWidth()
96 """ALU16.place(), manual placement overload."""
98 add
, sub
= self
.submodules
99 #print (sub.ab, dir(list(sub.cell.getInstances())[0]))
100 #print (list(sub.cell.getInstances())[0].getAbutmentBox())
101 subx
= widths
[BIT_WIDTH
] - 40 #self.from_dbu(sub.ab.getXMax())
102 addx
= self
.from_dbu(add
.ab
.getWidth()) + 5
104 for i
in range(BIT_WIDTH
):
105 dp
= [['nmx2', None],
109 # XXX here is the computed abutment box which we want to
110 # place the auto-located cells into, using *auto* place
111 # *not* manual place.
114 ab
= Box(self
.to_dbu(addx
), self
.to_dbu(y
),
115 self
.to_dbu(subx
), self
.to_dbu(y1
))
116 print ("ab", addx
, subx
, ab
, self
.from_dbu(ab
.getWidth()),
117 self
.from_dbu(ab
.getHeight()))
119 # automatically locate all non-placed cells connected to
121 find
= self
.get_net_connections(['o(%d)' % i
],
122 ['clk', 'rst', 'op'])
124 print (inst
, inst
.getName(), dir(inst
))
125 print ("place", ab
, inst
, dir(inst
))
127 if inst
.getName().find(column
[0]) != -1:
129 # XXX TODO: want to auto-place the instances
130 #with SessionManager():
131 #cell.setAbutmentBox(ab)
132 #etesian = Etesian.EtesianEngine.create(cell)
134 datapath_insts
.append(dp
)
136 # place to right of add
137 add
, sub
= self
.submodules
138 add_wid
= self
.from_dbu(add
.ab
.getWidth())
139 self
.place_datapath(datapath_insts
, add_wid
, 40.0, 1)
141 def _old_place(self
):
142 """ALU16.place(), manual placement overload."""
144 for i
in range(BIT_WIDTH
):
145 datapath_insts
.append([['nmx2', None],
149 for inst
in self
.cell
.getInstances():
150 if (Module
.match_instance(datapath_insts
, 'nmx2', 'i0', inst
) or
151 Module
.match_instance(datapath_insts
, 'no2', 'nq', inst
) or
152 Module
.match_instance(datapath_insts
, 'sff1', 'i', inst
)):
155 # place to right of add
156 add
, sub
= self
.submodules
157 add_wid
= self
.from_dbu(add
.ab
.getWidth())
158 self
.place_datapath(datapath_insts
, add_wid
, 40.0, 1)
161 self
.name
= self
.name
+ '_r'
162 self
.af
.saveCell(self
.cell
, CRL
.Catalog
.State
.Views
)
163 super(ALU16
, self
).save()
170 if not self
.build_submodules():
173 # at this point we have the (auto-calculated) submodules' dimensions
174 # in their `ab` properties.
176 add
, sub
= self
.submodules
178 with
SessionManager():
181 width
= self
.from_dbu(
182 self
.ab
.getWidth() + add
.ab
.getWidth() + sub
.ab
.getWidth()
184 height
= self
.from_dbu(max([
185 self
.ab
.getHeight(), add
.ab
.getHeight(), sub
.ab
.getHeight()
188 # experiment, over-ride
189 width
= widths
[BIT_WIDTH
]
193 self
.ab
= Box(0, 0, self
.to_dbu(width
), self
.to_dbu(height
))
195 add_wid
= self
.from_dbu(add
.ab
.getWidth())
196 sub_ht
= self
.from_dbu(sub
.ab
.getHeight())
197 sub_wid
= self
.from_dbu(sub
.ab
.getWidth())
199 self
.place_submodule(add
, 0, v_margin
)
200 self
.place_submodule(sub
, width
-sub_wid
, v_margin
)
202 # TODO: replace with some form of lazy evaluation?
203 y_north
= self
.from_dbu(self
.ab
.getYMax())
204 for pin_conf
in self
.north_pins
:
205 pin_conf
['y'] = y_north
210 find
= self
.get_net_connections(['o(15)'],
211 ['clk', 'rst', 'op'])
214 find
= self
.get_net_connections(['o_next(0)'],
215 ['clk', 'vss', 'vdd', 'rst'])
219 self
.editor
.setCell(self
.cell
)
221 # place first (in middle, between two)
222 # this puts all the remaining cells (little ones)
223 # into this (small) space so that they do not go
224 # "all over the place" around the add and sub
226 # XXX this doesn't work: box is far too big, covers the entire
227 # area (including "under" the add and sub)
229 # self.to_dbu((width-self.ab_width)/2 - h_margin),
230 # self.to_dbu(v_margin),
231 # self.to_dbu((width+self.ab_width)/2 + h_margin),
232 # self.to_dbu(height - v_margin)
234 #self.ab = Box(self.to_dbu(475), self.to_dbu(10),
235 # self.to_dbu(840), self.to_dbu(360))
236 self
.ab
= Box(0, 0, self
.to_dbu(width
), self
.to_dbu(height
))
237 self
.place() # place only
239 # then route (globally)
240 # this connects up not just in the remaining (little) cells,
241 # it connects *to add and sub and the outside world as well*
242 result
= self
.route()
248 def scriptMain(editor
=None, **kwargs
):
254 {'net': 'a({})', 'y': 15.0, 'delta': 50.0,
255 'repeat': BIT_WIDTH
, 'layer': 'METAL2'},
256 {'net': 'b({})', 'y': 20.0, 'delta': 50.0,
257 'repeat': BIT_WIDTH
, 'layer': 'METAL2'},
258 {'net': 'o({})', 'y': 25.0, 'delta': 50.0,
259 'repeat': BIT_WIDTH
, 'layer': 'METAL2'},
262 'b({})'.format(BIT_WIDTH
-1): (
263 'BLOCKAGE2', 'BLOCKAGE3', 'BLOCKAGE4',
266 orientation
=Transformation
.Orientation
.ID
,
268 add
.set_ab(160.0, 50.0 * BIT_WIDTH
)
272 {'net': 'a({})', 'y': 15.0, 'delta': 50.0,
273 'repeat': BIT_WIDTH
, 'layer': 'METAL2'},
274 {'net': 'b({})', 'y': 20.0, 'delta': 50.0,
275 'repeat': BIT_WIDTH
, 'layer': 'METAL2'},
276 {'net': 'o({})', 'y': 25.0, 'delta': 50.0,
277 'repeat': BIT_WIDTH
, 'layer': 'METAL2'},
280 'b({})'.format(BIT_WIDTH
-1): (
281 'BLOCKAGE2', 'BLOCKAGE3', 'BLOCKAGE4',
284 orientation
=Transformation
.Orientation
.ID
,
286 sub
.set_ab(165.0, 50.0 * BIT_WIDTH
)
290 'alu16', editor
, submodules
=[add
, sub
],
292 {'net': 'o({})', 'x': 245.0+o
, 'delta': 5.0, 'repeat': BIT_WIDTH
},
296 {'net': 'a({})', 'x': 195.0+o
, 'delta': 10.0, 'repeat': BIT_WIDTH
},
297 {'net': 'b({})', 'x': 200.0+o
, 'delta': 10.0, 'repeat': BIT_WIDTH
},
300 {'net': 'rst', 'y': 10.0, 'layer': 'METAL2'},
306 if __name__
== '__main__':
308 success
= scriptMain(**kwargs
)
313 sys
.exit(shellSuccess
)