Commit 06d79d2d by ZhiangWang033

fix gridding

parent db0819cc
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
### Input: a list of macros (each macro has a width and a height) ### Input: a list of macros (each macro has a width and a height)
### Output: best choice of n_rows and n_cols ### Output: best choice of n_rows and n_cols
import os import os
from math import floor from math import floor
from math import ceil from math import ceil
...@@ -22,6 +21,7 @@ class Grid: ...@@ -22,6 +21,7 @@ class Grid:
self.y_ = y self.y_ = y
self.placed_ = False # if there is macro placed on the center of this grid self.placed_ = False # if there is macro placed on the center of this grid
self.macros_id_ = [] # the id of macros intersecting with this grid self.macros_id_ = [] # the id of macros intersecting with this grid
self.macro_area = 0.0
# Check if there is an overlap with other placed macros # Check if there is an overlap with other placed macros
def CheckOverlap(lx, ly, ux, uy, macro_box): def CheckOverlap(lx, ly, ux, uy, macro_box):
...@@ -33,19 +33,30 @@ def CheckOverlap(lx, ly, ux, uy, macro_box): ...@@ -33,19 +33,30 @@ def CheckOverlap(lx, ly, ux, uy, macro_box):
pass pass
else: else:
return True # there is an overlap return True # there is an overlap
return False return False
# Get overlap area
def GetOverlapArea(box_a, box_b):
box_a_lx, box_a_ly, box_a_ux, box_a_uy = box_a
box_b_lx, box_b_ly, box_b_ux, box_b_uy = box_b
if (box_a_lx >= box_b_ux or box_a_ly >= box_b_uy or box_a_ux <= box_b_lx or box_a_uy <= box_b_ly):
return 0.0
else:
width = min(box_a_ux, box_b_ux) - max(box_a_lx, box_b_lx)
height = min(box_a_uy, box_b_uy) - max(box_a_ly, box_b_ly)
return width * height
# Place macros one by one # Place macros one by one
# n = num_cols # n = num_cols
def PlaceMacros(macro_map, grid_list, chip_width, chip_height, n): def PlaceMacros(macro_map, grid_list, chip_width, chip_height, n):
### All the macro must be placed on the center of one grid ### All the macro must be placed on the center of one grid
#Initialize the position of macros #Initialize the position of macros
ver_sum = 0.0
ver_span_sum = 0.0
hor_sum = 0.0
hor_span_sum = 0.0
macro_bbox = [] macro_bbox = []
# Place macro one by one # Place macro one by one
for key, value in macro_map.items(): for key, value in macro_map.items():
width = value[0] width = value[0]
...@@ -55,7 +66,6 @@ def PlaceMacros(macro_map, grid_list, chip_width, chip_height, n): ...@@ -55,7 +66,6 @@ def PlaceMacros(macro_map, grid_list, chip_width, chip_height, n):
for grid in grid_list: for grid in grid_list:
if (grid.placed_ == True): if (grid.placed_ == True):
continue # this grid has been occupied continue # this grid has been occupied
# if the macro is placed on this # if the macro is placed on this
x = grid.x_ x = grid.x_
y = grid.y_ y = grid.y_
...@@ -67,12 +77,10 @@ def PlaceMacros(macro_map, grid_list, chip_width, chip_height, n): ...@@ -67,12 +77,10 @@ def PlaceMacros(macro_map, grid_list, chip_width, chip_height, n):
# check if the macro is within the outline # check if the macro is within the outline
if (ux > chip_width or uy > chip_height): if (ux > chip_width or uy > chip_height):
continue continue
# check if there is an overlap with other macros # check if there is an overlap with other macros
if (CheckOverlap(lx, ly, ux, uy, macro_bbox) == True): if (CheckOverlap(lx, ly, ux, uy, macro_bbox) == True):
continue continue
# place current macro on this grid # place current macro on this grid
grid.placed_ = True grid.placed_ = True
placed_flag = True placed_flag = True
...@@ -91,22 +99,43 @@ def PlaceMacros(macro_map, grid_list, chip_width, chip_height, n): ...@@ -91,22 +99,43 @@ def PlaceMacros(macro_map, grid_list, chip_width, chip_height, n):
for j in range(min_col_id, max_col_id + 1): for j in range(min_col_id, max_col_id + 1):
grid_id = i * n + j # n is the num_cols grid_id = i * n + j # n is the num_cols
grid_list[grid_id].macros_id_.append(macro_id) grid_list[grid_id].macros_id_.append(macro_id)
grid_box = [i * grid_width, j * grid_height, (i + 1) * grid_width, (j + 1) * grid_height]
overlap_area = GetOverlapArea(grid_box, [lx, ly, ux, uy])
grid_list[grid_id].macro_area += overlap_area
ver_sum += height
ver_span_sum += (max_row_id + 1 - min_row_id) * grid_height
hor_sum += width
hor_span_sum += (max_col_id + 1 - min_col_id) * grid_width
break # stop search remaining candidates break # stop search remaining candidates
# cannot find a valid position for the macro # cannot find a valid position for the macro
if (placed_flag == False): if (placed_flag == False):
return False return False, [0.0, 0.0, 0.0, 0.0]
return True return True, [ver_sum, ver_span_sum, hor_sum, hor_span_sum]
# Define the gridding function # Define the gridding function
def Gridding(macro_width_list, macro_height_list, def Gridding(macro_width_list, macro_height_list,
chip_width, chip_height, tolerance = 0.1, chip_width, chip_height,
min_n_rows = 10, min_n_cols = 10, min_n_rows = 10, min_n_cols = 10,
max_n_rows = 100, max_n_cols = 100, max_n_rows = 128, max_n_cols = 128,
max_rows_times_cols = 3000, min_num_grid_cells = 500,
min_rows_times_cols = 500, max_num_grid_cells = 2500,
max_aspect_ratio = 1.5): max_aspect_ratio = 1.5,
tolerance = 0.05):
"""
Arguments:
macro_width_list, macro_height_list : macro information
chip_width, chip_height : canvas size or core size of the chip
min_n_rows, min_n_cols : mininum number of rows/cols sweep
max_n_rows, max_n_rows : maximum number of rows/cols sweep
min_num_grid_cells, max_num_grid_cells : mininum or maxinum grid cells
max_aspect_ratio : maximum aspect ratio of a grid cell (either w/h or h/w)
tolerance : tolerance to choose lower number of grids
Return:
the best number of rows and cols
"""
### Sort all the macros in a non-decreasing order ### Sort all the macros in a non-decreasing order
if (len(macro_width_list) != len(macro_height_list)): if (len(macro_width_list) != len(macro_height_list)):
print("[Error] The macro information is wrong!!!") print("[Error] The macro information is wrong!!!")
...@@ -116,30 +145,34 @@ def Gridding(macro_width_list, macro_height_list, ...@@ -116,30 +145,34 @@ def Gridding(macro_width_list, macro_height_list,
macro_map = { } macro_map = { }
for i in range(len(macro_width_list)): for i in range(len(macro_width_list)):
macro_map[i] = [macro_width_list[i], macro_height_list[i]] macro_map[i] = [macro_width_list[i], macro_height_list[i]]
macro_map = dict(sorted(macro_map.items(), key=lambda item: item[1][0] * item[1][1], reverse = True)) macro_map = dict(sorted(macro_map.items(), key=lambda item: item[1][0] * item[1][1], reverse = True))
macro_bbox = [] # (lx, ly, ux, uy) for each bounding box
### Print information
print("*"*80) print("*"*80)
print("[INFO] Outline Information : outline_width =", chip_width, " outline_height =", chip_height) print("[INFO] Canvas Information : canvas_width =", chip_width, "canvas_height =", chip_height)
print("\n") print("\n")
print("[INFO] Sorted Macro Information") print("[INFO] Sorted Macro Information")
for key, value in macro_map.items(): for key, value in macro_map.items():
print("macro_" + str(key), " macro_width =", round(value[0], 2), " macro_height =", round(value[1], 2), " macro_area =", round(value[0] * value[1], 2)) line = "macro_" + str(key) + " "
line += "macro_width = " + str(round(value[0], 2)) + " "
line += "macro_height = " + str(round(value[1], 2)) + " "
line += "macro_area = " + str(round(value[0] * value[1], 2))
print(line)
print("\n") print("\n")
### Sweep the n_rows (m) and n_cols (n) in a row-based manner
macro_bbox = [] # (lx, ly, ux, uy) for each bounding box
# we use m for max_n_rows and n for max_n_cols # we use m for max_n_rows and n for max_n_cols
m_best = -1 m_best = -1
n_best = -1 n_best = -1
best_cost = 2.0 # cost should be less than 2.0 based on definition best_metric = -1.0
choice_map = { } choice_map = { } # [m][n] : (ver_cost, hor_cost, empty_ratio)
for m in range(min_n_rows, max_n_rows):
for m in range(min_n_rows, max_n_rows + 1):
choice_map[m] = { } choice_map[m] = { }
for n in range(min_n_cols, max_n_cols + 1): for n in range(min_n_cols, max_n_cols):
if (m * n > max_rows_times_cols): if (m * n > max_num_grid_cells):
break break
if (m * n < min_rows_times_cols): if (m * n < min_num_grid_cells):
continue continue
### Step1: Divide the canvas into grids ### Step1: Divide the canvas into grids
...@@ -148,10 +181,10 @@ def Gridding(macro_width_list, macro_height_list, ...@@ -148,10 +181,10 @@ def Gridding(macro_width_list, macro_height_list,
grid_width = chip_width / n grid_width = chip_width / n
if (grid_height / grid_width > max_aspect_ratio): if (grid_height / grid_width > max_aspect_ratio):
continue continue
if (grid_width / grid_height > max_aspect_ratio): if (grid_width / grid_height > max_aspect_ratio):
continue continue
### Step2: Try to place macros on canvas
grid_list = [] grid_list = []
for i in range(m): for i in range(m):
for j in range(n): for j in range(n):
...@@ -160,24 +193,24 @@ def Gridding(macro_width_list, macro_height_list, ...@@ -160,24 +193,24 @@ def Gridding(macro_width_list, macro_height_list,
grid_id = len(grid_list) grid_id = len(grid_list)
grid_list.append(Grid(grid_id, grid_width, grid_height, x, y)) grid_list.append(Grid(grid_id, grid_width, grid_height, x, y))
value = [0.0, 0.0, 0.0, 0.0]
### Place macros one by one ### Place macros one by one
if (PlaceMacros(macro_map, grid_list, chip_width, chip_height, n) == False): result_flag, value = PlaceMacros(macro_map, grid_list, chip_width, chip_height, n)
if (result_flag == False):
continue continue
else: else:
### Calculate the cost ### compute the empty ratio
total_grid_width = 0.0 used_threshold = 1e-5
total_grid_height = 0.0 num_empty_grids = 0
for grid in grid_list: for grid in grid_list:
if (len(grid.macros_id_) > 0): if (grid.macro_area / (grid_width * grid_height) < used_threshold):
total_grid_width += grid.width_ num_empty_grids += 1
total_grid_height += grid.height_ metric = 1.0 - value[0] / value[1]
metric += 1.0 - value[2] / value[3]
# calculate h_cost metric += num_empty_grids / len(grid_list)
cost = 1.0 - sum(macro_width_list) / total_grid_width choice_map[m][n] = metric
cost += 1.0 - sum(macro_height_list) / total_grid_height if (metric > best_metric):
choice_map[m][n] = cost best_metric = metric
if (cost < best_cost):
best_cost = cost
m_best = m m_best = m
n_best = n n_best = n
m_opt = m_best m_opt = m_best
...@@ -188,9 +221,9 @@ def Gridding(macro_width_list, macro_height_list, ...@@ -188,9 +221,9 @@ def Gridding(macro_width_list, macro_height_list,
print("n_best = ", n_best) print("n_best = ", n_best)
print("tolerance = ", tolerance) print("tolerance = ", tolerance)
for [m, m_map] in choice_map.items(): for [m, m_map] in choice_map.items():
for [n, cost] in m_map.items(): for [n, metric] in m_map.items():
print("m = ", m , " n = ", n, " cost = ", cost) print("m = ", m , " n = ", n, " metric = ", metric)
if ((cost <= (1.0 + tolerance) * best_cost) and (m * n < num_grids_opt)): if ((metric >= (1.0 - tolerance) * best_metric) and (m * n < num_grids_opt)):
m_opt = m m_opt = m
n_opt = n n_opt = n
num_grids_opt = m * n num_grids_opt = m * n
...@@ -201,7 +234,7 @@ def Gridding(macro_width_list, macro_height_list, ...@@ -201,7 +234,7 @@ def Gridding(macro_width_list, macro_height_list,
class GriddingLefDefInterface: class GriddingLefDefInterface:
def __init__(self, src_dir, design, setup_file = "setup.tcl", tolerance = 0.05, def __init__(self, src_dir, design, setup_file = "setup.tcl", tolerance = 0.05,
halo_width = 5.0, min_n_rows = 10, min_n_cols = 10, max_n_rows = 128, halo_width = 0.0, min_n_rows = 10, min_n_cols = 10, max_n_rows = 128,
max_n_cols = 128, max_rows_times_cols = 2500, min_rows_times_cols = 500, max_n_cols = 128, max_rows_times_cols = 2500, min_rows_times_cols = 500,
max_aspect_ratio = 1.5): max_aspect_ratio = 1.5):
self.src_dir = src_dir self.src_dir = src_dir
...@@ -227,11 +260,11 @@ class GriddingLefDefInterface: ...@@ -227,11 +260,11 @@ class GriddingLefDefInterface:
self.GenerateHypergraph() self.GenerateHypergraph()
self.ExtractInputs() self.ExtractInputs()
self.m_opt, self.n_opt = Gridding(self.macro_width_list, self.macro_height_list, self.m_opt, self.n_opt = Gridding(self.macro_width_list, self.macro_height_list,
self.chip_width, self.chip_height, self.tolerance, self.chip_width, self.chip_height,
self.min_n_rows, self.min_n_cols, self.min_n_rows, self.min_n_cols,
self.max_n_rows, self.max_n_cols, self.max_n_rows, self.max_n_cols,
self.max_rows_times_cols, self.min_rows_times_cols, self.min_rows_times_cols, self.max_rows_times_cols,
self.max_aspect_ratio) self.max_aspect_ratio, self.tolerance)
def GetNumRows(self): def GetNumRows(self):
return self.m_opt return self.m_opt
...@@ -278,6 +311,7 @@ class GriddingLefDefInterface: ...@@ -278,6 +311,7 @@ class GriddingLefDefInterface:
f.close() f.close()
items = content[0].split() items = content[0].split()
print(items)
self.chip_width = float(items[2]) - float(items[0]) self.chip_width = float(items[2]) - float(items[0])
self.chip_height = float(items[3]) - float(items[1]) self.chip_height = float(items[3]) - float(items[1])
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment