AMF-Placer  2.0
An Open-Source Timing-driven Analytical Mixed-size FPGA Placer
exportDeviceLocation.py
Go to the documentation of this file.
1 import matplotlib.cm as cm
2 import matplotlib as matplotlib
3 from matplotlib.colors import Normalize
4 import matplotlib.pyplot as plt
5 import matplotlib.patches as patches
6 from PIL import Image
7 import numpy as np
8 from matplotlib.patches import Patch
9 import zipfile
10 import os
11 import sys
12 gw = 0.3
13 
14 assert(len(sys.argv) == 3)
15 
16 targetPath = sys.argv[1]
17 deviceName = sys.argv[2]
18 
19 
20 class siteInfo(object):
21  def __init__(self, siteName, tileName, clockRegionName, siteType, tileType):
22  self.siteName = siteName
23  self.tileName = tileName
24  self.clockRegionName = clockRegionName
25  self.siteType = siteType
26  self.tileType = tileType
27  self.L = not (tileName.find("_R_") >= 0 or tileName.find(
28  "DSP") >= 0 or tileName.find("PCIE_X") == 0)
29 
30  self.X = int(tileName[tileName.rfind("_X")+2:tileName.rfind("Y")])
31 
32  if (tileName.find("CLE_M_R_X84") >= 0):
33  self.L = True
34 
35  self.Y = int(tileName[tileName.rfind("Y")+1:])
36 
37  if (tileName.find("DSP") >= 0):
38  if (int(siteName[siteName.rfind("Y")+1:]) % 2 == 1):
39  self.siteType += "_T"
40  else:
41  self.siteType += "_B"
42 
43  if (siteType.find("BUFCE_LEAF_X16") >= 0):
44  if (int(siteName[siteName.rfind("Y")+1:]) % 2 == 1):
45  self.Y += 2/3 + gw/2 - gw*0.3/2
46  else:
47  self.Y += 1/3 + gw/2 - gw*0.3/2
48  if (siteType.find("BUFCE_ROW") >= 0):
49  self.Y += 1/2 + gw/2 - gw*0.3/2
50 
51  self.siteX = int(siteName[siteName.rfind("_X")+2:siteName.rfind("Y")])
52  self.siteY = int(siteName[siteName.rfind("Y")+1:])
53 
54  if (siteType == "HPIOB" or siteType == "HRIO" or siteType == "BITSLICE_RX_TX"):
55  self.Y = self.siteY//26 * 30 + ((self.siteY) % 26+1)/28*30
56  if (siteType == "BITSLICE_CONTROL" or siteType == "BITSLICE_TX"):
57  self.Y = self.siteY//4 * 30 + ((self.siteY) % 4+0.5)/5*30
58  if (siteType == "RIU_OR"):
59  self.Y = self.siteY//2 * 30 + ((self.siteY) % 2+0.5)/3*30
60  if (siteType == "PLLE3_ADV"):
61  self.Y += 13
62 
63  self.centerX = 0
64  self.centerY = 0
65 
66  self.BELs = []
67 
68 
70  sites_in_GTH_R = dict()
71 
72  for curSite in sites:
73  if (curSite.tileName.find("GTH_R") == 0):
74  if (not curSite.tileName in sites_in_GTH_R.keys()):
75  sites_in_GTH_R[curSite.tileName] = []
76  sites_in_GTH_R[curSite.tileName].append(curSite)
77 
78  for tileName in sites_in_GTH_R.keys():
79  BUFG_GT_SYNCs = []
80  GTHE3_CHANNELs = []
81  BUFG_GTs = []
82  GTHE3_COMMON = []
83  for curSite in sites_in_GTH_R[tileName]:
84  if (curSite.siteType == "BUFG_GT_SYNC"):
85  BUFG_GT_SYNCs.append(curSite)
86  elif (curSite.siteType == "GTHE3_CHANNEL"):
87  GTHE3_CHANNELs.append(curSite)
88  elif (curSite.siteType == "BUFG_GT"):
89  BUFG_GTs.append(curSite)
90  elif (curSite.siteType == "GTHE3_COMMON"):
91  GTHE3_COMMON.append(curSite)
92 
93  BUFG_GT_SYNCs = sorted(
94  BUFG_GT_SYNCs, key=lambda curSite: curSite.siteY)
95  GTHE3_CHANNELs = sorted(
96  GTHE3_CHANNELs, key=lambda curSite: curSite.siteY)
97  BUFG_GTs = sorted(BUFG_GTs, key=lambda curSite: curSite.siteY)
98 
99  GTHE3_COMMON[0].Y = GTHE3_COMMON[0].Y + (59+gw)/2 - 1
100  BUFG_GT_SYNCs[5].Y = GTHE3_COMMON[0].Y + 1
101 
102  GTHE3_CHANNELs[0].Y = GTHE3_COMMON[0].Y - 5
103  GTHE3_CHANNELs[1].Y = GTHE3_CHANNELs[0].Y + 2
104  GTHE3_CHANNELs[3].Y = GTHE3_COMMON[0].Y + 5
105  GTHE3_CHANNELs[2].Y = GTHE3_CHANNELs[3].Y - 2
106 
107  for curSite in BUFG_GT_SYNCs:
108  curSite.X += 0.15
109 
110  initOffset = 12
111  step = 5/12
112  for curSite in BUFG_GTs[:12]:
113  curSite.Y += initOffset
114  initOffset += step
115 
116  initOffset = 46
117  step = 5/12
118  for curSite in reversed(BUFG_GTs[12:]):
119  curSite.Y += initOffset
120  initOffset -= step
121 
122  initOffset = 13
123  step = 3/5
124  for curSite in BUFG_GT_SYNCs[:5]:
125  curSite.Y += initOffset
126  initOffset += step
127 
128  initOffset = 45
129  step = 3/5
130  for curSite in reversed(BUFG_GT_SYNCs[6:]):
131  curSite.Y += initOffset
132  initOffset -= step
133 
134 
136  sites_in_GTY_Quad = dict()
137 
138  for curSite in sites:
139  if (curSite.tileName.find("GTY_QUAD_LEFT_FT") == 0):
140  if (not curSite.tileName in sites_in_GTY_Quad.keys()):
141  sites_in_GTY_Quad[curSite.tileName] = []
142  sites_in_GTY_Quad[curSite.tileName].append(curSite)
143 
144  for tileName in sites_in_GTY_Quad.keys():
145  BUFG_GT_SYNCs = []
146  GTYE3_CHANNELs = []
147  BUFG_GTs = []
148  GTYE3_COMMON = []
149  for curSite in sites_in_GTY_Quad[tileName]:
150  if (curSite.siteType == "BUFG_GT_SYNC"):
151  BUFG_GT_SYNCs.append(curSite)
152  elif (curSite.siteType == "GTYE3_CHANNEL"):
153  GTYE3_CHANNELs.append(curSite)
154  elif (curSite.siteType == "BUFG_GT"):
155  BUFG_GTs.append(curSite)
156  elif (curSite.siteType == "GTYE3_COMMON"):
157  GTYE3_COMMON.append(curSite)
158 
159  BUFG_GT_SYNCs = sorted(
160  BUFG_GT_SYNCs, key=lambda curSite: curSite.siteY)
161  GTYE3_CHANNELs = sorted(
162  GTYE3_CHANNELs, key=lambda curSite: curSite.siteY)
163  BUFG_GTs = sorted(BUFG_GTs, key=lambda curSite: curSite.siteY)
164 
165  GTYE3_COMMON[0].Y = GTYE3_COMMON[0].Y + (59+gw)/2 - 1
166  BUFG_GT_SYNCs[5].Y = GTYE3_COMMON[0].Y + 1
167 
168  GTYE3_CHANNELs[0].Y = GTYE3_COMMON[0].Y - 5
169  GTYE3_CHANNELs[1].Y = GTYE3_CHANNELs[0].Y + 2
170  GTYE3_CHANNELs[3].Y = GTYE3_COMMON[0].Y + 5
171  GTYE3_CHANNELs[2].Y = GTYE3_CHANNELs[3].Y - 2
172 
173  for curSite in BUFG_GT_SYNCs:
174  curSite.X -= 0.15
175 
176  initOffset = 12
177  step = 5/12
178  for curSite in BUFG_GTs[:12]:
179  curSite.Y += initOffset
180  initOffset += step
181 
182  initOffset = 46
183  step = 5/12
184  for curSite in reversed(BUFG_GTs[12:]):
185  curSite.Y += initOffset
186  initOffset -= step
187 
188  initOffset = 13
189  step = 3/5
190  for curSite in BUFG_GT_SYNCs[:5]:
191  curSite.Y += initOffset
192  initOffset += step
193 
194  initOffset = 45
195  step = 3/5
196  for curSite in reversed(BUFG_GT_SYNCs[6:]):
197  curSite.Y += initOffset
198  initOffset -= step
199 
200 
201 # deviceInfoFile = open("VCU108DeviceSite","r")
202 
203 # site=> HPIOBDIFFINBUF_X1Y59 tile=> HPIO_L_X51Y120 type=> HPIOBDIFFINBUF
204 # site=> RIU_OR_X1Y8 tile=> XIPHY_L_X52Y120 type=> RIU_OR
205 # site=> SLICE_X96Y475 tile=> CLEL_L_X58Y475 type=> SLICEL
206 
207 # lines = deviceInfoFile.readlines()
208 
209 archive = zipfile.ZipFile(targetPath+"/"+deviceName +
210  "/"+deviceName+"_DeviceSite.zip", 'r')
211 lines = archive.read(deviceName+"_DeviceSite").decode('utf-8').split("\n")
212 
213 plotPriority = dict()
214 
215 
216 sites = []
217 siteTypes = set()
218 siteType2id = dict()
219 
220 insertedSite = set()
221 siteName2site = dict()
222 
223 for line in lines:
224  # puts $fo "bel=> $curBEL site=> $curSite tile=> $curTile type=> $siteType"
225  # "bel=> $curBEL site=> $curSite tile=> $curTile clockRegion=> $clockRegion sitetype=> $siteType tiletype=> $tileType"
226  bel_site_tile_clockRegion_sitetype_tiletype = line.replace("\n", "").replace("bel=> ", "").replace(
227  " site=> ", ";").replace(" tile=> ", ";").replace(" sitetype=> ", ";").replace(" clockRegion=> ", ";").replace(" tiletype=> ", ";").split(";")
228  if (len(bel_site_tile_clockRegion_sitetype_tiletype) < 2):
229  continue
230 
231  if (bel_site_tile_clockRegion_sitetype_tiletype[1] in insertedSite):
232  siteName2site[bel_site_tile_clockRegion_sitetype_tiletype[1]].BELs.append(
233  bel_site_tile_clockRegion_sitetype_tiletype[0])
234  continue
235  else:
236  insertedSite.add(bel_site_tile_clockRegion_sitetype_tiletype[1])
237  tmpSiteInfo = siteInfo(bel_site_tile_clockRegion_sitetype_tiletype[1], bel_site_tile_clockRegion_sitetype_tiletype[2], bel_site_tile_clockRegion_sitetype_tiletype[3],
238  bel_site_tile_clockRegion_sitetype_tiletype[4], bel_site_tile_clockRegion_sitetype_tiletype[5])
239  sites.append(tmpSiteInfo)
240  siteName2site[tmpSiteInfo.siteName] = tmpSiteInfo
241  siteName2site[bel_site_tile_clockRegion_sitetype_tiletype[1]].BELs.append(
242  bel_site_tile_clockRegion_sitetype_tiletype[0])
243  siteTypes.add(tmpSiteInfo.siteType)
244  if (not tmpSiteInfo.siteType in siteType2id.keys()):
245  siteType2id[tmpSiteInfo.siteType] = len(siteTypes)
246 
247 cmap = cm.hsv
248 norm = Normalize(vmin=0, vmax=len(siteTypes))
249 
250 plotPriority = dict()
251 for name in siteTypes:
252  plotPriority[name] = 0
253 plotPriority['RAMBFIFO36'] = -1
254 
255 priorityArr = []
256 for curSite in sites:
257  priorityArr.append(plotPriority[curSite.siteType])
258 priorityArr = np.array(priorityArr)
259 order = np.argsort(priorityArr)
260 
261 
262 height = dict()
263 for name in siteTypes:
264  height[name] = gw
265 height['RAMBFIFO36'] = 4 + gw
266 height['RAMB181'] = height['RAMBFIFO36']/2 - gw/4
267 height['RAMBFIFO18'] = height['RAMBFIFO36']/2 - gw/4
268 height['DSP48E2_T'] = height['RAMBFIFO36']/2 - gw/4
269 height['DSP48E2_B'] = height['RAMBFIFO36']/2 - gw/4
270 #height['PCIE_3_1'] = 6 + gw
271 height['BUFCE_LEAF_X16'] = gw*0.3
272 height['BUFCE_ROW'] = gw*0.3
273 
274 weight = dict()
275 for name in siteTypes:
276  weight[name] = gw
277 weight['RAMBFIFO36'] = gw*1.3
278 weight['BUFG_GT'] = gw*0.3
279 weight['BUFG_GT_SYNC'] = gw*0.3
280 weight['BUFCE_LEAF_X16'] = gw*0.3
281 weight['BUFCE_ROW'] = gw*0.3
282 
283 yoffset = dict()
284 for name in siteTypes:
285  yoffset[name] = 0
286 yoffset['RAMB181'] = 2 + gw/2 + gw/4/2
287 yoffset['RAMBFIFO18'] = gw/4/2
288 yoffset['DSP48E2_T'] = 2 + gw/2 + gw/4/2
289 yoffset['DSP48E2_B'] = gw/4/2
290 #yoffset['PCIE_3_1'] = (59+gw-height['PCIE_3_1'])/2
291 
292 # insert HPIO/HRIO bank
293 for curSite in sites:
294  if (curSite.X >= 34):
295  curSite.X += 1
296  if (curSite.X >= 53):
297  curSite.X += 1
298  if (curSite.tileName.find("HRIO_L_X") == 0):
299  curSite.X += 1
300  if (curSite.tileName.find("HPIO_L_X") == 0):
301  curSite.X += 1
302 
305 
306 fig, ax = plt.subplots(1)
307 ax.set_xlim([0, 90])
308 ax.set_ylim([0, 500])
309 plt.axis('scaled')
310 arr = np.arange(len(siteTypes)+1)
311 # arr = np.concatenate((arr[0::2],arr[1::2]))
312 np.random.shuffle(arr)
313 
314 
315 legend_elements = []
316 
317 sites = np.array(sites)
318 sites = sites[order]
319 
320 addedPatchTypes = set()
321 for curSite in sites:
322  if (curSite.L):
323  rect = patches.Rectangle(((curSite.X-0.25-weight[curSite.siteType]/2), curSite.Y-gw/2 + yoffset[curSite.siteType]),
324  weight[curSite.siteType], height[curSite.siteType], color=cmap(norm(arr[siteType2id[curSite.siteType]])))
325  curSite.centerX = (
326  curSite.X-0.25-weight[curSite.siteType]/2) + weight[curSite.siteType]/2
327  curSite.centerY = curSite.Y-gw/2 + \
328  yoffset[curSite.siteType] + height[curSite.siteType]/2
329  else:
330  rect = patches.Rectangle(((curSite.X+0.25-weight[curSite.siteType]/2), curSite.Y-gw/2 + yoffset[curSite.siteType]),
331  weight[curSite.siteType], height[curSite.siteType], color=cmap(norm(arr[siteType2id[curSite.siteType]])))
332  curSite.centerX = (
333  curSite.X+0.25-weight[curSite.siteType]/2) + weight[curSite.siteType]/2
334  curSite.centerY = curSite.Y-gw/2 + \
335  yoffset[curSite.siteType] + height[curSite.siteType]/2
336 
337  if (not curSite.siteType in addedPatchTypes):
338  addedPatchTypes.add(curSite.siteType)
339  legend_elements.append(Patch(color=cmap(
340  norm(arr[siteType2id[curSite.siteType]])), label=curSite.siteType))
341 
342 # ax.add_patch(rect)
343 
344 # ax.legend(handles=legend_elements, bbox_to_anchor=(
345 # 1.05, 1.0), loc='upper left')
346 # plt.tight_layout()
347 # plt.show()
348 
349 
350 exportfile = open(targetPath+"/"+deviceName+"/" +
351  deviceName+"_exportSiteLocation", "w")
352 
353 for curSite in sites:
354  cx = curSite.centerX
355  cy = curSite.centerY
356  if (curSite.siteType.find("DSP") >= 0):
357  curSite.siteType = curSite.siteType[:-2]
358  if (curSite.siteName.find("DSP") >= 0 or curSite.siteName.find("RAMB") >= 0):
359  if (curSite.siteY % 2 == 1):
360  cy = curSite.centerY + (1-gw)/2
361 
362  print("site=> " + curSite.siteName
363  + " tile=> " + curSite.tileName
364  + " clockRegionName=> " + curSite.clockRegionName
365  + " sitetype=> " + curSite.siteType
366  + " tiletype=> " + curSite.tileType
367  + " centerx=> " + str(cx)
368  + " centery=> " + str(cy)
369  + " BELs=> " + str(curSite.BELs).replace(" ", "").replace("\'", ""), file=exportfile)
370 
371 exportfile.close()
372 os.system("zip -j "+targetPath+"/"+deviceName+"/" +
373  deviceName+"_exportSiteLocation.zip "+targetPath+"/"+deviceName+"/" +
374  deviceName+"_exportSiteLocation")
exportDeviceLocation.siteInfo.__init__
def __init__(self, siteName, tileName, clockRegionName, siteType, tileType)
Definition: exportDeviceLocation.py:21
exportDeviceLocation.siteInfo.siteY
siteY
Definition: exportDeviceLocation.py:52
exportDeviceLocation.siteInfo.tileName
tileName
Definition: exportDeviceLocation.py:23
exportDeviceLocation.processGTY_QuadSites
def processGTY_QuadSites()
Definition: exportDeviceLocation.py:135
exportDeviceLocation.siteInfo.siteType
siteType
Definition: exportDeviceLocation.py:25
exportDeviceLocation.siteInfo.siteName
siteName
Definition: exportDeviceLocation.py:22
exportDeviceLocation.siteInfo.X
X
Definition: exportDeviceLocation.py:30
exportDeviceLocation.siteInfo.centerX
centerX
Definition: exportDeviceLocation.py:63
exportDeviceLocation.siteInfo
Definition: exportDeviceLocation.py:20
exportDeviceLocation.norm
norm
Definition: exportDeviceLocation.py:248
exportDeviceLocation.cmap
cmap
Definition: exportDeviceLocation.py:247
exportDeviceLocation.siteInfo.tileType
tileType
Definition: exportDeviceLocation.py:26
exportDeviceLocation.siteInfo.BELs
BELs
Definition: exportDeviceLocation.py:66
exportDeviceLocation.siteInfo.centerY
centerY
Definition: exportDeviceLocation.py:64
exportDeviceLocation.processGTH_RSites
def processGTH_RSites()
Definition: exportDeviceLocation.py:69
exportDeviceLocation.siteInfo.L
L
Definition: exportDeviceLocation.py:27
exportDeviceLocation.siteInfo.Y
Y
Definition: exportDeviceLocation.py:35
exportDeviceLocation.siteInfo.clockRegionName
clockRegionName
Definition: exportDeviceLocation.py:24
exportDeviceLocation.siteInfo.siteX
siteX
Definition: exportDeviceLocation.py:51