Commit da3ae6a0 by Dinple

debugging on density + optimization

parent 46970f7b
...@@ -611,19 +611,21 @@ class PlacementCost(object): ...@@ -611,19 +611,21 @@ class PlacementCost(object):
macro = self.modules_w_pins[macro_idx] macro = self.modules_w_pins[macro_idx]
macro_name = macro.get_name() macro_name = macro.get_name()
# Hard macro
if not self.is_node_soft_macro(macro_idx): if not self.is_node_soft_macro(macro_idx):
if macro_name in self.hard_macros_to_inpins.keys(): if macro_name in self.hard_macros_to_inpins.keys():
pin_names = self.hard_macros_to_inpins[macro_name] pin_names = self.hard_macros_to_inpins[macro_name]
else: else:
print("[ERROR UPDATE CONNECTION] MACRO not found") print("[ERROR UPDATE CONNECTION] MACRO pins not found")
exit(1) continue
# use is_node_soft_macro()
# Soft macro
elif self.is_node_soft_macro(macro_idx): elif self.is_node_soft_macro(macro_idx):
if macro_name in self.soft_macros_to_inpins.keys(): if macro_name in self.soft_macros_to_inpins.keys():
pin_names = self.soft_macros_to_inpins[macro_name] pin_names = self.soft_macros_to_inpins[macro_name]
else: else:
print("[ERROR UPDATE CONNECTION] MACRO not found") print("[ERROR UPDATE CONNECTION] macro pins not found")
exit(1) continue
for pin_name in pin_names: for pin_name in pin_names:
pin = self.modules_w_pins[self.mod_name_to_indices[pin_name]] pin = self.modules_w_pins[self.mod_name_to_indices[pin_name]]
...@@ -697,11 +699,14 @@ class PlacementCost(object): ...@@ -697,11 +699,14 @@ class PlacementCost(object):
if self.modules_w_pins[pin_idx].get_type() == 'PORT': if self.modules_w_pins[pin_idx].get_type() == 'PORT':
return self.modules_w_pins[pin_idx].get_pos() return self.modules_w_pins[pin_idx].get_pos()
else: else:
print("[ERROR PIN POSITION] Parent Node Not Found.")
exit(1) exit(1)
# Parent node
ref_node = self.modules_w_pins[ref_node_idx] ref_node = self.modules_w_pins[ref_node_idx]
ref_node_x, ref_node_y = ref_node.get_pos() ref_node_x, ref_node_y = ref_node.get_pos()
# Retrieve current pin node position
pin_node = self.modules_w_pins[pin_idx] pin_node = self.modules_w_pins[pin_idx]
pin_node_x_offset, pin_node_y_offset = pin_node.get_offset() pin_node_x_offset, pin_node_y_offset = pin_node.get_offset()
...@@ -724,8 +729,9 @@ class PlacementCost(object): ...@@ -724,8 +729,9 @@ class PlacementCost(object):
# NOTE: connection only defined on PORT, soft/hard macro pins # NOTE: connection only defined on PORT, soft/hard macro pins
if curr_type == "PORT" and mod.get_sink(): if curr_type == "PORT" and mod.get_sink():
# add source position # add source position
x_coord.append(self.__get_pin_position(mod_idx)[0]) x_coord.append(mod.get_pos()[0])
y_coord.append(self.__get_pin_position(mod_idx)[1]) y_coord.append(mod.get_pos()[1])
# get sink
for sink_name in mod.get_sink(): for sink_name in mod.get_sink():
for sink_pin in mod.get_sink()[sink_name]: for sink_pin in mod.get_sink()[sink_name]:
# retrieve indx in modules_w_pins # retrieve indx in modules_w_pins
...@@ -881,16 +887,6 @@ class PlacementCost(object): ...@@ -881,16 +887,6 @@ class PlacementCost(object):
self.node_mask[ row - ver_pad:row + ver_pad + 1, self.node_mask[ row - ver_pad:row + ver_pad + 1,
col - hor_pad:col + hor_pad + 1] = 0 col - hor_pad:col + hor_pad + 1] = 0
def __unplace_node_mask(self, grid_cell_idx:int):
"""
private function: for updating node mask after unplacing a node
"""
row = grid_cell_idx // self.grid_col
col = grid_cell_idx % self.grid_col
assert row * self.grid_col + col == grid_cell_idx
pass
def __overlap_area(self, block_i, block_j, return_pos=False): def __overlap_area(self, block_i, block_j, return_pos=False):
""" """
private function: for computing block overlapping private function: for computing block overlapping
...@@ -972,6 +968,8 @@ class PlacementCost(object): ...@@ -972,6 +968,8 @@ class PlacementCost(object):
self.grid_occupied[self.grid_col * r_i + c_i] += \ self.grid_occupied[self.grid_col * r_i + c_i] += \
self.__overlap_area(grid_cell_block, module_block) self.__overlap_area(grid_cell_block, module_block)
def get_grid_cells_density(self): def get_grid_cells_density(self):
""" """
...@@ -988,6 +986,11 @@ class PlacementCost(object): ...@@ -988,6 +986,11 @@ class PlacementCost(object):
for module_idx in (self.soft_macro_indices + self.hard_macro_indices): for module_idx in (self.soft_macro_indices + self.hard_macro_indices):
# extract module information # extract module information
module = self.modules_w_pins[module_idx] module = self.modules_w_pins[module_idx]
# skipping unplaced module
if not module.get_placed_flag():
continue
module_h = module.get_height() module_h = module.get_height()
module_w = module.get_width() module_w = module.get_width()
module_x, module_y = module.get_pos() module_x, module_y = module.get_pos()
...@@ -1714,8 +1717,10 @@ class PlacementCost(object): ...@@ -1714,8 +1717,10 @@ class PlacementCost(object):
def make_soft_macros_square(self): def make_soft_macros_square(self):
""" """
[IGNORE] THIS DOES NOT AFFECT DENSITY. SHOULD WE IMPLEMENT THIS AT ALL?
make soft macros as squares make soft macros as squares
""" """
return
for mod_idx in self.soft_macro_indices: for mod_idx in self.soft_macro_indices:
mod = self.modules_w_pins[mod_idx] mod = self.modules_w_pins[mod_idx]
mod_area = mod.get_width() * mod.get_height() mod_area = mod.get_width() * mod.get_height()
...@@ -2200,7 +2205,8 @@ class PlacementCost(object): ...@@ -2200,7 +2205,8 @@ class PlacementCost(object):
pass pass
def get_source_filename(self): def get_source_filename(self):
"""return netlist path """
return netlist path
""" """
return self.netlist_file return self.netlist_file
...@@ -2211,20 +2217,18 @@ class PlacementCost(object): ...@@ -2211,20 +2217,18 @@ class PlacementCost(object):
self.blockages.append([minx, miny, maxx, maxy, blockage_rate]) self.blockages.append([minx, miny, maxx, maxy, blockage_rate])
def get_ref_node_id(self, node_idx=-1): def get_ref_node_id(self, node_idx=-1):
"""ref_node_id is used for macro_pins. Refers to the macro it belongs to. """
ref_node_id is used for macro_pins. Refers to the macro it belongs to.
""" """
if node_idx != -1: if node_idx != -1:
if node_idx in self.soft_macro_pin_indices: if node_idx in self.soft_macro_pin_indices or node_idx in self.hard_macro_pin_indices:
pin = self.modules_w_pins[node_idx]
return self.mod_name_to_indices[pin.get_macro_name()]
elif node_idx in self.hard_macro_pin_indices:
pin = self.modules_w_pins[node_idx] pin = self.modules_w_pins[node_idx]
return self.mod_name_to_indices[pin.get_macro_name()] return self.mod_name_to_indices[pin.get_macro_name()]
return -1 return -1
def save_placement(self, filename, info=""): def save_placement(self, filename, info=""):
""" """
When writing out info line-by-line, add a "#" at front When writing out info line-by-line, add a "#" at front
""" """
with open(filename, 'w+') as f: with open(filename, 'w+') as f:
for line in info.split('\n'): for line in info.split('\n'):
...@@ -2252,6 +2256,9 @@ class PlacementCost(object): ...@@ -2252,6 +2256,9 @@ class PlacementCost(object):
def display_canvas( self, def display_canvas( self,
annotate=True, annotate=True,
amplify=False): amplify=False):
"""
Non-google function, For quick canvas view
"""
#define Matplotlib figure and axis #define Matplotlib figure and axis
fig, ax = plt.subplots(figsize=(8,8), dpi=50) fig, ax = plt.subplots(figsize=(8,8), dpi=50)
......
...@@ -58,7 +58,6 @@ Example: ...@@ -58,7 +58,6 @@ Example:
--smooth 2 --smooth 2
$ python3 -m Plc_client.plc_client_os_test --netlist ./Plc_client/test/0P2M0m/netlist.pb.txt\ $ python3 -m Plc_client.plc_client_os_test --netlist ./Plc_client/test/0P2M0m/netlist.pb.txt\
--plc ./Plc_client/test/0P2M0m/initial.plc\
--width 500\ --width 500\
--height 500\ --height 500\
--col 5\ --col 5\
...@@ -272,8 +271,8 @@ class PlacementCostTest(): ...@@ -272,8 +271,8 @@ class PlacementCostTest():
self.plc_os.set_canvas_size(self.CANVAS_WIDTH, self.CANVAS_HEIGHT) self.plc_os.set_canvas_size(self.CANVAS_WIDTH, self.CANVAS_HEIGHT)
self.plc_os.set_placement_grid(self.GRID_COL, self.GRID_ROW) self.plc_os.set_placement_grid(self.GRID_COL, self.GRID_ROW)
# self.plc.make_soft_macros_square() self.plc.make_soft_macros_square()
# self.plc_os.make_soft_macros_square() self.plc_os.make_soft_macros_square()
# [IGNORE] create_blockage must be defined BEFORE set_canvas_size # [IGNORE] create_blockage must be defined BEFORE set_canvas_size
# and set_placement_grid in order to be considered on the canvas # and set_placement_grid in order to be considered on the canvas
...@@ -285,28 +284,20 @@ class PlacementCostTest(): ...@@ -285,28 +284,20 @@ class PlacementCostTest():
print(self.plc.set_use_incremental_cost(True)) print(self.plc.set_use_incremental_cost(True))
print(self.plc_os.get_soft_macros_count()) print(self.plc_os.get_soft_macros_count())
# self.plc_os.display_canvas(annotate=False)
# HPWL # HPWL
try: try:
assert int(self.plc_os.get_wirelength()) == int(self.plc.get_wirelength()) assert int(self.plc_os.get_wirelength()) == int(self.plc.get_wirelength())
assert abs(self.plc.get_cost() - self.plc_os.get_cost()) <= 1e-3 assert abs(self.plc.get_cost() - self.plc_os.get_cost()) <= 1e-2
print("#[INFO WIRELENGTH] Matched irelength cost -- GL {}, OS {}".format( print("#[INFO WIRELENGTH] Matched Wirelength cost -- GL {}, OS {}".format(
str(self.plc.get_cost()), self.plc_os.get_cost())) str(self.plc.get_cost()), self.plc_os.get_cost()))
except Exception as e: except Exception as e:
print("[ERROR WIRELENGTH] Discrepancies found when computing wirelength -- GL {}, OS {}".format( print("[ERROR WIRELENGTH] Discrepancies found when computing wirelength -- GL {}, OS {}".format(
str(self.plc.get_cost()), self.plc_os.get_cost())) str(self.plc.get_cost()), self.plc_os.get_cost()))
soft_macro_indices = [
m for m in self.plc.get_macro_indices() if self.plc.is_node_soft_macro(m)
]
for mod_idx in soft_macro_indices:
self.plc_os.unplace_node(mod_idx)
self.plc.unplace_node(mod_idx)
print("GL WIRELENGTH: ", self.plc.get_wirelength()) print("GL WIRELENGTH: ", self.plc.get_wirelength())
print("OS WIRELENGTH: ", self.plc_os.get_wirelength()) print("OS WIRELENGTH: ", self.plc_os.get_wirelength())
exit(1)
# exit(1)
# self.plc_os.display_canvas(annotate=False)
# Density # Density
try: try:
...@@ -326,7 +317,7 @@ class PlacementCostTest(): ...@@ -326,7 +317,7 @@ class PlacementCostTest():
# NOTE: [IGNORE] grid-wise congestion not tested because # NOTE: [IGNORE] grid-wise congestion not tested because
# miscellaneous implementation differences. # miscellaneous implementation differences.
assert abs(self.plc.get_congestion_cost() - assert abs(self.plc.get_congestion_cost() -
self.plc_os.get_congestion_cost()) < 1e-3 self.plc_os.get_congestion_cost()) <= 1e-2
print("#[INFO CONGESTION] Matched congestion cost -- GL {}, OS {}".format( print("#[INFO CONGESTION] Matched congestion cost -- GL {}, OS {}".format(
str(self.plc.get_congestion_cost()), self.plc_os.get_congestion_cost())) str(self.plc.get_congestion_cost()), self.plc_os.get_congestion_cost()))
except Exception as e: except Exception as e:
...@@ -340,6 +331,7 @@ class PlacementCostTest(): ...@@ -340,6 +331,7 @@ class PlacementCostTest():
print(" +++++++++++++++++++++++++++++") print(" +++++++++++++++++++++++++++++")
def test_miscellaneous(self): def test_miscellaneous(self):
print("****************** miscellaneous ******************")
# Google's Binary Executable # Google's Binary Executable
self.plc = plc_client.PlacementCost(self.NETLIST_PATH) self.plc = plc_client.PlacementCost(self.NETLIST_PATH)
self.plc_os = plc_client_os.PlacementCost(netlist_file=self.NETLIST_PATH, self.plc_os = plc_client_os.PlacementCost(netlist_file=self.NETLIST_PATH,
...@@ -362,7 +354,6 @@ class PlacementCostTest(): ...@@ -362,7 +354,6 @@ class PlacementCostTest():
print(np.flip(np.array(self.plc_util.get_node_mask(0)).reshape(35, 33), axis=0)) print(np.flip(np.array(self.plc_util.get_node_mask(0)).reshape(35, 33), axis=0))
print(np.flip(np.array(self.plc.get_node_mask(0)).reshape(35, 33), axis=0)) print(np.flip(np.array(self.plc.get_node_mask(0)).reshape(35, 33), axis=0))
print("****************** miscellaneous ******************")
# self.plc.set_canvas_size(self.CANVAS_WIDTH, self.CANVAS_HEIGHT) # self.plc.set_canvas_size(self.CANVAS_WIDTH, self.CANVAS_HEIGHT)
# self.plc.set_placement_grid(self.GRID_COL, self.GRID_ROW) # self.plc.set_placement_grid(self.GRID_COL, self.GRID_ROW)
# self.plc_os.set_canvas_size(self.CANVAS_WIDTH, self.CANVAS_HEIGHT) # self.plc_os.set_canvas_size(self.CANVAS_WIDTH, self.CANVAS_HEIGHT)
...@@ -382,6 +373,127 @@ class PlacementCostTest(): ...@@ -382,6 +373,127 @@ class PlacementCostTest():
# print("can_place_node", self.plc.can_place_node(0, 1)) # print("can_place_node", self.plc.can_place_node(0, 1))
print("***************************************************") print("***************************************************")
def test_proxy_hpwl(self):
print("############################ TEST PROXY WIRELENGTH ############################")
# Google's Binary Executable
self.plc = plc_client.PlacementCost(self.NETLIST_PATH)
# Open-sourced Implementation
self.plc_os = plc_client_os.PlacementCost(netlist_file=self.NETLIST_PATH,
macro_macro_x_spacing=50,
macro_macro_y_spacing=50)
self.plc.get_overlap_threshold()
print("overlap_threshold default", self.plc.get_overlap_threshold())
if self.PLC_PATH:
print("#[PLC FILE FOUND] Loading info from .plc file")
self.plc_os.set_canvas_boundary_check(False)
self.plc_os.restore_placement(self.PLC_PATH,
ifInital=True,
ifValidate=True,
ifReadComment=False)
self.plc.set_canvas_boundary_check(False)
self.plc.restore_placement(self.PLC_PATH)
else:
print("#[PLC FILE MISSING] Using only netlist info")
self.plc.set_routes_per_micron(self.RPMH, self.RPMV)
self.plc_os.set_routes_per_micron(self.RPMH, self.RPMV)
self.plc.set_macro_routing_allocation(self.MARH, self.MARV)
self.plc_os.set_macro_routing_allocation(self.MARH, self.MARV)
self.plc.set_congestion_smooth_range(self.SMOOTH)
self.plc_os.set_congestion_smooth_range(self.SMOOTH)
self.plc.set_canvas_size(self.CANVAS_WIDTH, self.CANVAS_HEIGHT)
self.plc.set_placement_grid(self.GRID_COL, self.GRID_ROW)
self.plc_os.set_canvas_size(self.CANVAS_WIDTH, self.CANVAS_HEIGHT)
self.plc_os.set_placement_grid(self.GRID_COL, self.GRID_ROW)
# HPWL
try:
assert int(self.plc_os.get_wirelength()) == int(self.plc.get_wirelength())
assert abs(self.plc.get_cost() - self.plc_os.get_cost()) <= 1e-2
print("#[INFO WIRELENGTH] Matched Wirelength cost -- GL {}, OS {}".format(
str(self.plc.get_cost()), self.plc_os.get_cost()))
except Exception as e:
print("[ERROR WIRELENGTH] Discrepancies found when computing wirelength -- GL {}, OS {}".format(
str(self.plc.get_cost()), self.plc_os.get_cost()))
# if remove all soft macros
# soft_macro_indices = [
# m for m in self.plc.get_macro_indices() if self.plc.is_node_soft_macro(m)
# ]
# for mod_idx in soft_macro_indices:
# self.plc_os.unplace_node(mod_idx)
# self.plc.unplace_node(mod_idx)
print("GL WIRELENGTH: ", self.plc.get_wirelength())
print("OS WIRELENGTH: ", self.plc_os.get_wirelength())
def test_proxy_density(self):
print("############################ TEST PROXY DENSITY ############################")
# Google's Binary Executable
self.plc = plc_client.PlacementCost(self.NETLIST_PATH)
# Open-sourced Implementation
self.plc_os = plc_client_os.PlacementCost(netlist_file=self.NETLIST_PATH,
macro_macro_x_spacing=50,
macro_macro_y_spacing=50)
self.plc.get_overlap_threshold()
print("overlap_threshold default", self.plc.get_overlap_threshold())
if self.PLC_PATH:
print("#[PLC FILE FOUND] Loading info from .plc file")
self.plc_os.set_canvas_boundary_check(False)
self.plc_os.restore_placement(self.PLC_PATH,
ifInital=True,
ifValidate=True,
ifReadComment=False)
self.plc.set_canvas_boundary_check(False)
self.plc.restore_placement(self.PLC_PATH)
else:
print("#[PLC FILE MISSING] Using only netlist info")
self.plc.set_routes_per_micron(self.RPMH, self.RPMV)
self.plc_os.set_routes_per_micron(self.RPMH, self.RPMV)
self.plc.set_macro_routing_allocation(self.MARH, self.MARV)
self.plc_os.set_macro_routing_allocation(self.MARH, self.MARV)
self.plc.set_congestion_smooth_range(self.SMOOTH)
self.plc_os.set_congestion_smooth_range(self.SMOOTH)
self.plc.set_canvas_size(self.CANVAS_WIDTH, self.CANVAS_HEIGHT)
self.plc.set_placement_grid(self.GRID_COL, self.GRID_ROW)
self.plc_os.set_canvas_size(self.CANVAS_WIDTH, self.CANVAS_HEIGHT)
self.plc_os.set_placement_grid(self.GRID_COL, self.GRID_ROW)
# self.plc.make_soft_macros_square()
# self.plc_os.make_soft_macros_square()
# Density
try:
assert int(sum(self.plc_os.get_grid_cells_density())) == int(
sum(self.plc.get_grid_cells_density()))
assert int(self.plc_os.get_density_cost()) == int(
self.plc.get_density_cost())
print("#[INFO DENSITY] Matched density cost -- GL {}, OS {}".format(
str(self.plc.get_density_cost()), self.plc_os.get_density_cost()))
except Exception as e:
print("[ERROR DENSITY] Discrepancies found when computing density -- GL {}, OS {}".format(
str(self.plc.get_density_cost()), self.plc_os.get_density_cost()))
gl_density = self.plc.get_grid_cells_density()
os_density = self.plc_os.get_grid_cells_density()
for cell_idx, (gl_dens, os_des) in enumerate(zip(gl_density, os_density)):
print("PASS {}".format(str(cell_idx)) if abs(gl_dens - os_des) <= 1e-3 else "FAILED", gl_dens, os_des)
if cell_idx == 0:
break
self.plc_os.display_canvas(annotate=True, amplify=True)
def test_proxy_congestion(self): def test_proxy_congestion(self):
# Google's API # Google's API
self.plc = plc_client.PlacementCost(self.NETLIST_PATH) self.plc = plc_client.PlacementCost(self.NETLIST_PATH)
...@@ -859,6 +971,7 @@ def main(args): ...@@ -859,6 +971,7 @@ def main(args):
""" """
# PCT.test_metadata() # PCT.test_metadata()
PCT.test_proxy_cost() PCT.test_proxy_cost()
# PCT.test_proxy_density()
# PCT.test_proxy_congestion() # PCT.test_proxy_congestion()
# PCT.test_placement_util(keep_save_file=False) # PCT.test_placement_util(keep_save_file=False)
# PCT.test_place_node() # PCT.test_place_node()
......
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