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