whoops
[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
15 import symbolic.cmos # do not remove
16
17 BIT_WIDTH = 16
18 widths = {32: 600.0, 16: 490}
19
20 def coriolis_setup():
21 with Config(Cfg.Parameter.Priority.UserFile) as cfg:
22 cfg.misc_catchCore = False
23 cfg.misc_info = False
24 cfg.misc_paranoid = False
25 cfg.misc_bug = False
26 cfg.misc_logMode = True
27 cfg.misc_verboseLevel1 = True
28 cfg.misc_verboseLevel2 = True
29 cfg.etesian_effort = 2
30 cfg.etesian_spaceMargin = "10.0%"
31 cfg.etesian_aspectRatio = "100.0%"
32 cfg.etesian_uniformDensity = True
33 cfg.anabatic_edgeLenght = 24
34 cfg.anabatic_edgeWidth = 8
35 cfg.anabatic_topRoutingLayer = 'METAL5'
36 cfg.katana_searchHalo = 30
37 cfg.katana_eventsLimit = 1000000
38 cfg.katana_hTracksReservedLocal = 7
39 cfg.katana_vTracksReservedLocal = 6
40
41 env = af.getEnvironment()
42 env.setCLOCK('^clk$|m_clock')
43 env.setPOWER('vdd')
44 env.setGROUND('vss')
45
46
47 class AddSub(Module):
48
49 def build(self):
50 """ Main routine. """
51
52 with SessionManager():
53 #self.compute_ab()
54 self.create_pins()
55
56 if self.editor:
57 self.editor.setCell(self.cell)
58
59 result = self.place_and_route()
60
61 with SessionManager():
62 self.create_pads()
63
64 self.save()
65 return result
66
67
68 class ALU16(Module):
69
70 def place_datapath(self, datapath_insts, x_orig, y_orig, fold):
71 channel_sff1 = self.to_dbu(0)
72 with SessionManager():
73 slice_height = self.to_dbu(50.0)
74 for i in range(len(datapath_insts)):
75 if not i%fold:
76 x = self.to_dbu(x_orig)
77 slice = i/fold
78 if slice%2:
79 y = self.to_dbu(y_orig) + slice_height*(slice+1)
80 orient = Transformation.Orientation.MY
81 else:
82 y = self.to_dbu(y_orig) + slice_height*slice
83 orient = Transformation.Orientation.ID
84
85 for (opname, inst) in datapath_insts[i]:
86 if opname == 'sff1':
87 x += channel_sff1
88 inst.setTransformation(Transformation(x, y, orient))
89 inst.setPlacementStatus(Instance.PlacementStatus.PLACED)
90 x += inst.getAbutmentBox().getWidth()
91
92 def place(self):
93 """ALU16.place(), manual placement overload."""
94 datapath_insts = []
95 for i in range(BIT_WIDTH):
96 datapath_insts.append([['nmx2', None],
97 ['no2', None],
98 ['sff1', None]])
99
100 for inst in self.cell.getInstances():
101 if (Module.match_instance(datapath_insts, 'nmx2', 'i0', inst) or
102 Module.match_instance(datapath_insts, 'no2', 'nq', inst) or
103 Module.match_instance(datapath_insts, 'sff1', 'i', inst)):
104 continue
105
106 # place to right of add
107 add, sub = self.submodules
108 add_wid = self.from_dbu(add.ab.getWidth())
109 self.place_datapath(datapath_insts, add_wid, 40.0, 1)
110
111 def save(self):
112 self.name = self.name + '_r'
113 self.af.saveCell(self.cell, CRL.Catalog.State.Views)
114 super(ALU16, self).save()
115
116 def build(self):
117
118 h_margin = 0.0
119 v_margin = 40.0
120
121 if not self.build_submodules():
122 return False
123
124 # at this point we have the (auto-calculated) submodules' dimensions
125 # in their `ab` properties.
126
127 add, sub = self.submodules
128
129 with SessionManager():
130 self.compute_ab()
131
132 width = self.from_dbu(
133 self.ab.getWidth() + add.ab.getWidth() + sub.ab.getWidth()
134 ) + 4*h_margin
135 height = self.from_dbu(max([
136 self.ab.getHeight(), add.ab.getHeight(), sub.ab.getHeight()
137 ])) + v_margin
138
139 # experiment, over-ride
140 width = widths[BIT_WIDTH]
141 #width = 1310
142 #height = 370
143
144 self.ab = Box(0, 0, self.to_dbu(width), self.to_dbu(height))
145
146 add_wid = self.from_dbu(add.ab.getWidth())
147 sub_ht = self.from_dbu(sub.ab.getHeight())
148 sub_wid = self.from_dbu(sub.ab.getWidth())
149
150 self.place_submodule(add, 0, v_margin)
151 self.place_submodule(sub, width-sub_wid, v_margin)
152
153 # TODO: replace with some form of lazy evaluation?
154 y_north = self.from_dbu(self.ab.getYMax())
155 for pin_conf in self.north_pins:
156 pin_conf['y'] = y_north
157
158 self.create_pins()
159
160 if False:
161 print (dir(self.cell))
162 for net in self.cell.getNets():
163 print (net.getName())
164 print (self.cell.getNet("a(0)"))
165 print (dir(self.cell.getNet("a(0)")))
166 for inst in self.cell.getInstances():
167 for net in self.cell.getNets():
168 if net.getName() == "a(1)":
169 icell = inst.getMasterCell()
170 #if len(list(icell.getInstances())) > 0:
171 #continue # already placed, do not include it
172 for net in icell.getNets():
173 print ("inst", icell, "has nets", net.getName())
174 sys.exit(0)
175
176 if self.editor:
177 self.editor.setCell(self.cell)
178
179 # place first (in middle, between two)
180 # this puts all the remaining cells (little ones)
181 # into this (small) space so that they do not go
182 # "all over the place" around the add and sub
183
184 # XXX this doesn't work: box is far too big, covers the entire
185 # area (including "under" the add and sub)
186 #self.ab = Box(
187 # self.to_dbu((width-self.ab_width)/2 - h_margin),
188 # self.to_dbu(v_margin),
189 # self.to_dbu((width+self.ab_width)/2 + h_margin),
190 # self.to_dbu(height - v_margin)
191 #)
192 #self.ab = Box(self.to_dbu(475), self.to_dbu(10),
193 # self.to_dbu(840), self.to_dbu(360))
194 self.ab = Box(0, 0, self.to_dbu(width), self.to_dbu(height))
195 self.place() # place only
196
197 # then route (globally)
198 # this connects up not just in the remaining (little) cells,
199 # it connects *to add and sub and the outside world as well*
200 result = self.route()
201
202 self.save()
203 return result
204
205
206 def scriptMain(editor=None, **kwargs):
207 coriolis_setup()
208
209 add = AddSub(
210 'add', editor,
211 east_pins=[
212 {'net': 'a({})', 'y': 15.0, 'delta': 50.0,
213 'repeat': BIT_WIDTH, 'layer': 'METAL2'},
214 {'net': 'b({})', 'y': 20.0, 'delta': 50.0,
215 'repeat': BIT_WIDTH, 'layer': 'METAL2'},
216 {'net': 'o({})', 'y': 25.0, 'delta': 50.0,
217 'repeat': BIT_WIDTH, 'layer': 'METAL2'},
218 ],
219 pads={
220 'b({})'.format(BIT_WIDTH-1): (
221 'BLOCKAGE2', 'BLOCKAGE3', 'BLOCKAGE4',
222 ),
223 },
224 orientation=Transformation.Orientation.ID,
225 )
226 add.set_ab(160.0, 50.0 * BIT_WIDTH)
227 sub = AddSub(
228 'sub', editor,
229 west_pins=[
230 {'net': 'a({})', 'y': 15.0, 'delta': 50.0,
231 'repeat': BIT_WIDTH, 'layer': 'METAL2'},
232 {'net': 'b({})', 'y': 20.0, 'delta': 50.0,
233 'repeat': BIT_WIDTH, 'layer': 'METAL2'},
234 {'net': 'o({})', 'y': 25.0, 'delta': 50.0,
235 'repeat': BIT_WIDTH, 'layer': 'METAL2'},
236 ],
237 pads={
238 'b({})'.format(BIT_WIDTH-1): (
239 'BLOCKAGE2', 'BLOCKAGE3', 'BLOCKAGE4',
240 ),
241 },
242 orientation=Transformation.Orientation.ID,
243 )
244 sub.set_ab(165.0, 50.0 * BIT_WIDTH)
245
246 o = 00.0
247 alu16 = ALU16(
248 'alu16', editor, submodules=[add, sub],
249 north_pins=[
250 {'net': 'o({})', 'x': 245.0+o, 'delta': 5.0, 'repeat': BIT_WIDTH},
251 {'net': 'op'},
252 ],
253 south_pins=[
254 {'net': 'a({})', 'x': 195.0+o, 'delta': 10.0, 'repeat': BIT_WIDTH},
255 {'net': 'b({})', 'x': 200.0+o, 'delta': 10.0, 'repeat': BIT_WIDTH},
256 ],
257 east_pins=[
258 {'net': 'rst', 'y': 10.0, 'layer': 'METAL2'},
259 ],
260 )
261 return alu16.build()
262
263
264 if __name__ == '__main__':
265 kwargs = {}
266 success = scriptMain(**kwargs)
267 shellSuccess = 0
268 if not success:
269 shellSuccess = 1
270
271 sys.exit(shellSuccess)