2 # -*- coding: utf-8 -*-
3 from __future__
import print_function
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
16 import symbolic
.cmos
# do not remove
22 with
Config(Cfg
.Parameter
.Priority
.UserFile
) as cfg
:
23 cfg
.misc_catchCore
= False
25 cfg
.misc_paranoid
= 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
42 env
= af
.getEnvironment()
43 env
.setCLOCK('^clk$|m_clock')
53 with
SessionManager():
58 self
.editor
.setCell(self
.cell
)
60 result
= self
.place_and_route()
62 with
SessionManager():
72 def match_instance(datapath_insts
, op
, plug_name
, inst
):
74 Guess the position of an instance from its nets connections,
75 and put it at the right place in the datapath vector.
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.
83 if not inst
.getMasterCell().getName().startswith(op
):
85 re_net_index
= re
.compile(r
'[^(]+\((?P<index>[\d]+)\)$')
86 for plug
in inst
.getPlugs():
87 if plug
.getMasterNet().getName() != plug_name
:
89 m
= re_net_index
.match(plug
.getNet().getName())
92 bit_slice
= datapath_insts
[int(m
.group('index'))]
93 for column
in bit_slice
:
96 print ("match", plug_name
, int(m
.group('index')),
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
)):
108 x
= self
.to_dbu(x_orig
)
111 y
= self
.to_dbu(y_orig
) + slice_height
*(slice+1)
112 orient
= Transformation
.Orientation
.MY
114 y
= self
.to_dbu(y_orig
) + slice_height
*slice
115 orient
= Transformation
.Orientation
.ID
117 for (opname
, inst
) in datapath_insts
[i
]:
120 inst
.setTransformation(Transformation(x
, y
, orient
))
121 inst
.setPlacementStatus(Instance
.PlacementStatus
.PLACED
)
122 x
+= inst
.getAbutmentBox().getWidth()
125 """ALU16.place(), manual placement overload."""
127 for i
in range(BIT_WIDTH
):
128 datapath_insts
.append([['nmx2', None],
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
)):
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)
144 self
.name
= self
.name
+ '_r'
145 self
.af
.saveCell(self
.cell
, CRL
.Catalog
.State
.Views
)
146 super(ALU16
, self
).save()
153 if not self
.build_submodules():
156 # at this point we have the (auto-calculated) submodules' dimensions
157 # in their `ab` properties.
159 add
, sub
= self
.submodules
161 with
SessionManager():
164 width
= self
.from_dbu(
165 self
.ab
.getWidth() + add
.ab
.getWidth() + sub
.ab
.getWidth()
167 height
= self
.from_dbu(max([
168 self
.ab
.getHeight(), add
.ab
.getHeight(), sub
.ab
.getHeight()
171 # experiment, over-ride
176 self
.ab
= Box(0, 0, self
.to_dbu(width
), self
.to_dbu(height
))
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())
182 self
.place_submodule(add
, 0, v_margin
)
183 self
.place_submodule(sub
, width
-sub_wid
, v_margin
)
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
193 self
.editor
.setCell(self
.cell
)
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
200 # XXX this doesn't work: box is far too big, covers the entire
201 # area (including "under" the add and sub)
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)
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
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()
222 def scriptMain(editor
=None, **kwargs
):
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'},
236 'b({})'.format(BIT_WIDTH
-1): (
237 'BLOCKAGE2', 'BLOCKAGE3', 'BLOCKAGE4',
240 orientation
=Transformation
.Orientation
.ID
,
242 add
.set_ab(160.0, 800.0)
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'},
254 'b({})'.format(BIT_WIDTH
-1): (
255 'BLOCKAGE2', 'BLOCKAGE3', 'BLOCKAGE4',
258 orientation
=Transformation
.Orientation
.ID
,
260 sub
.set_ab(165.0, 800.0)
264 'alu16', editor
, submodules
=[add
, sub
],
266 {'net': 'o({})', 'x': 245.0+o
, 'delta': 5.0, 'repeat': BIT_WIDTH
},
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
},
274 {'net': 'rst', 'y': 10.0, 'layer': 'METAL2'},
280 if __name__
== '__main__':
282 success
= scriptMain(**kwargs
)
287 sys
.exit(shellSuccess
)