use --recursive on git submodule not --remote - one does a "latest update"
[soclayout.git] / experiments7 / doAlu16.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 from __future__ import print_function
4 import sys
5
6 import CRL
7 import Cfg
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
14 import Etesian
15 import helpers
16 from helpers.overlay import UpdateSession
17
18 import symbolic.cmos # do not remove
19
20 BIT_WIDTH = 16
21 widths = {32: 600.0, 16: 490}
22
23 def coriolis_setup():
24 with Config(Cfg.Parameter.Priority.UserFile) as cfg:
25 cfg.misc_catchCore = False
26 cfg.misc_info = False
27 cfg.misc_paranoid = False
28 cfg.misc_bug = 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
43
44 env = af.getEnvironment()
45 env.setCLOCK('^clk$|m_clock')
46 env.setPOWER('vdd')
47 env.setGROUND('vss')
48
49
50 class AddSub(Module):
51
52 def build(self):
53 """ Main routine. """
54
55 with SessionManager():
56 #self.compute_ab()
57 self.create_pins()
58
59 if self.editor:
60 self.editor.setCell(self.cell)
61
62 result = self.place_and_route()
63
64 with SessionManager():
65 self.create_pads()
66
67 self.save()
68 return result
69
70
71 class ALU16(Module):
72
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)):
78 if not i%fold:
79 x = self.to_dbu(x_orig)
80 slice = i/fold
81 if slice%2:
82 y = self.to_dbu(y_orig) + slice_height*(slice+1)
83 orient = Transformation.Orientation.MY
84 else:
85 y = self.to_dbu(y_orig) + slice_height*slice
86 orient = Transformation.Orientation.ID
87
88 for (opname, inst) in datapath_insts[i]:
89 if opname == 'sff1':
90 x += channel_sff1
91 inst.setTransformation(Transformation(x, y, orient))
92 inst.setPlacementStatus(Instance.PlacementStatus.PLACED)
93 x += inst.getAbutmentBox().getWidth()
94
95 def place(self):
96 """ALU16.place(), manual placement overload."""
97 datapath_insts = []
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
103
104 for i in range(BIT_WIDTH):
105 dp = [['nmx2', None],
106 ['no2', None],
107 ['sff1', None]]
108
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.
112 y = 40.0 + i * 50
113 y1 = y + 50
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()))
118
119 # automatically locate all non-placed cells connected to
120 # o(0)....o(15)
121 find = self.get_net_connections(['o(%d)' % i],
122 ['clk', 'rst', 'op'])
123 for inst in find:
124 print (inst, inst.getName(), dir(inst))
125 print ("place", ab, inst, dir(inst))
126 for column in dp:
127 if inst.getName().find(column[0]) != -1:
128 column[1] = inst
129 # XXX TODO: want to auto-place the instances
130 #with SessionManager():
131 #cell.setAbutmentBox(ab)
132 #etesian = Etesian.EtesianEngine.create(cell)
133 #etesian.place()
134 datapath_insts.append(dp)
135
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)
140
141 def _old_place(self):
142 """ALU16.place(), manual placement overload."""
143 datapath_insts = []
144 for i in range(BIT_WIDTH):
145 datapath_insts.append([['nmx2', None],
146 ['no2', None],
147 ['sff1', None]])
148
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)):
153 continue
154
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)
159
160 def save(self):
161 self.name = self.name + '_r'
162 self.af.saveCell(self.cell, CRL.Catalog.State.Views)
163 super(ALU16, self).save()
164
165 def build(self):
166
167 h_margin = 0.0
168 v_margin = 40.0
169
170 if not self.build_submodules():
171 return False
172
173 # at this point we have the (auto-calculated) submodules' dimensions
174 # in their `ab` properties.
175
176 add, sub = self.submodules
177
178 with SessionManager():
179 self.compute_ab()
180
181 width = self.from_dbu(
182 self.ab.getWidth() + add.ab.getWidth() + sub.ab.getWidth()
183 ) + 4*h_margin
184 height = self.from_dbu(max([
185 self.ab.getHeight(), add.ab.getHeight(), sub.ab.getHeight()
186 ])) + v_margin
187
188 # experiment, over-ride
189 width = widths[BIT_WIDTH]
190 #width = 1310
191 #height = 370
192
193 self.ab = Box(0, 0, self.to_dbu(width), self.to_dbu(height))
194
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())
198
199 self.place_submodule(add, 0, v_margin)
200 self.place_submodule(sub, width-sub_wid, v_margin)
201
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
206
207 self.create_pins()
208
209 if False:
210 find = self.get_net_connections(['o(15)'],
211 ['clk', 'rst', 'op'])
212 print (find)
213 sys.exit(0)
214 find = self.get_net_connections(['o_next(0)'],
215 ['clk', 'vss', 'vdd', 'rst'])
216 print (find)
217
218 if self.editor:
219 self.editor.setCell(self.cell)
220
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
225
226 # XXX this doesn't work: box is far too big, covers the entire
227 # area (including "under" the add and sub)
228 #self.ab = Box(
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)
233 #)
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
238
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()
243
244 self.save()
245 return result
246
247
248 def scriptMain(editor=None, **kwargs):
249 coriolis_setup()
250
251 add = AddSub(
252 'add', editor,
253 east_pins=[
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'},
260 ],
261 pads={
262 'b({})'.format(BIT_WIDTH-1): (
263 'BLOCKAGE2', 'BLOCKAGE3', 'BLOCKAGE4',
264 ),
265 },
266 orientation=Transformation.Orientation.ID,
267 )
268 add.set_ab(160.0, 50.0 * BIT_WIDTH)
269 sub = AddSub(
270 'sub', editor,
271 west_pins=[
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'},
278 ],
279 pads={
280 'b({})'.format(BIT_WIDTH-1): (
281 'BLOCKAGE2', 'BLOCKAGE3', 'BLOCKAGE4',
282 ),
283 },
284 orientation=Transformation.Orientation.ID,
285 )
286 sub.set_ab(165.0, 50.0 * BIT_WIDTH)
287
288 o = 00.0
289 alu16 = ALU16(
290 'alu16', editor, submodules=[add, sub],
291 north_pins=[
292 {'net': 'o({})', 'x': 245.0+o, 'delta': 5.0, 'repeat': BIT_WIDTH},
293 {'net': 'op'},
294 ],
295 south_pins=[
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},
298 ],
299 east_pins=[
300 {'net': 'rst', 'y': 10.0, 'layer': 'METAL2'},
301 ],
302 )
303 return alu16.build()
304
305
306 if __name__ == '__main__':
307 kwargs = {}
308 success = scriptMain(**kwargs)
309 shellSuccess = 0
310 if not success:
311 shellSuccess = 1
312
313 sys.exit(shellSuccess)