Commit 3c1362f8 by Dinple

placement_util test done + updated plc_client_os

parent 7474f481
......@@ -44,7 +44,7 @@ def nodes_of_types(plc: plc_client.PlacementCost,
yield i
i += 1
# done
def get_node_xy_coordinates(
plc: plc_client.PlacementCost) -> Dict[int, Tuple[float, float]]:
"""Returns all node x,y coordinates (canvas) in a dict."""
......@@ -54,7 +54,7 @@ def get_node_xy_coordinates(
node_coords[node_index] = plc.get_node_location(node_index)
return node_coords
# done
def get_macro_orientations(plc: plc_client.PlacementCost) -> Dict[int, int]:
"""Returns all macros' orientations in a dict."""
macro_orientations = dict()
......@@ -62,7 +62,7 @@ def get_macro_orientations(plc: plc_client.PlacementCost) -> Dict[int, int]:
macro_orientations[node_index] = plc.get_macro_orientation(node_index)
return macro_orientations
# done
def restore_node_xy_coordinates(
plc: plc_client.PlacementCost,
node_coords: Dict[int, Tuple[float, float]]) -> None:
......@@ -70,13 +70,13 @@ def restore_node_xy_coordinates(
if not plc.is_node_fixed(node_index):
plc.update_node_coords(node_index, coords[0], coords[1])
# done
def restore_macro_orientations(plc: plc_client.PlacementCost,
macro_orientations: Dict[int, int]) -> None:
for node_index, orientation in macro_orientations.items():
plc.update_macro_orientation(node_index, orientation)
#
# done
def extract_attribute_from_comments(attribute: str,
filenames: List[str]) -> Optional[str]:
"""Parses the files' comments section, tries to extract the attribute.
......@@ -104,7 +104,7 @@ def extract_attribute_from_comments(attribute: str,
break
return None
#done
# done
def get_blockages_from_comments(
filenames: Union[str, List[str]]) -> Optional[List[List[float]]]:
"""Returns list of blockages if they exist in the file's comments section."""
......@@ -171,7 +171,7 @@ def extract_sizes_from_comments(
if canvas_width and canvas_height and grid_cols and grid_rows:
return canvas_width, canvas_height, grid_cols, grid_rows
# done
def fix_port_coordinates(plc: plc_client.PlacementCost) -> None:
"""Find all ports and fix their coordinates.
......@@ -182,12 +182,13 @@ def fix_port_coordinates(plc: plc_client.PlacementCost) -> None:
# print("node to fix:", node)
plc.fix_node_coord(node)
# done
# The routing capacities are calculated based on the public information about
# 7nm technology (https://en.wikichip.org/wiki/7_nm_lithography_process)
# with an arbitary, yet reasonable, assumption of 18% of the tracks for
# the power grids.
def create_placement_cost(
plc_client: None,
netlist_file: str,
init_placement: Optional[str] = None,
overlap_threshold: float = 4e-3,
......@@ -300,20 +301,21 @@ def get_node_type_counts(plc: plc_client.PlacementCost) -> Dict[str, int]:
counts['HARD_MACRO'] += 1
if node_type == 'MACRO_PIN':
ref_id = plc.get_ref_node_id(node_index)
# print("ref_id: ", ref_id)
if plc.is_node_soft_macro(ref_id):
counts['SOFT_MACRO_PIN'] += 1
else:
counts['HARD_MACRO_PIN'] += 1
return counts
# done
def make_blockage_text(plc: plc_client.PlacementCost) -> str:
ret = ''
for blockage in plc.get_blockages():
ret += 'Blockage : {}\n'.format(' '.join([str(b) for b in blockage]))
return ret
# done
def save_placement(plc: plc_client.PlacementCost,
filename: str,
user_comments: str = '') -> None:
......@@ -372,9 +374,12 @@ def save_placement(plc: plc_client.PlacementCost,
if user_comments:
info += '\nUser comments:\n' + user_comments + '\n'
info += '\nnode_index x y orientation fixed'
# print(info)
return plc.save_placement(filename, info)
# TODO: plc.optimize_stdcells
def fd_placement_schedule(plc: plc_client.PlacementCost,
num_steps: Tuple[int, ...] = (100, 100, 100),
io_factor: float = 1.0,
......@@ -415,7 +420,7 @@ def fd_placement_schedule(plc: plc_client.PlacementCost,
log_scale_conns, use_sizes, io_factor, num_steps,
max_move_distance, attract_factor, repel_factor)
# not tested
def get_ordered_node_indices(mode: str,
plc: plc_client.PlacementCost,
exclude_fixed_nodes: bool = True) -> List[int]:
......@@ -456,7 +461,7 @@ def get_ordered_node_indices(mode: str,
ordered_indices = [m for m in ordered_indices if not plc.is_node_fixed(m)]
return ordered_indices
# done
def extract_parameters_from_comments(
filename: str) -> Tuple[float, float, int, int]:
"""Parses the file's comments section, tries to extract canvas/grid sizes.
......@@ -476,6 +481,7 @@ def extract_parameters_from_comments(
fp_re = re.search(
r'FP bbox: \{([\d\.]+) ([\d\.]+)\} \{([\d\.]+) ([\d\.]+)\}', line)
if fp_re:
# NOTE: first two argument contains origin coord but not used
canvas_width = float(fp_re.group(3))
canvas_height = float(fp_re.group(4))
continue
......@@ -494,7 +500,7 @@ def extract_parameters_from_comments(
break
return canvas_width, canvas_height, grid_cols, grid_rows
# done
def get_routing_resources() -> Dict[str, float]:
"""Currently we only use default parameter settings.
......@@ -512,6 +518,7 @@ def get_routing_resources() -> Dict[str, float]:
}
# done
def nodes_of_types(plc: plc_client.PlacementCost, type_list: List[str]):
"""Yields the index of a node of certain types."""
i = 0
......@@ -523,7 +530,7 @@ def nodes_of_types(plc: plc_client.PlacementCost, type_list: List[str]):
yield i
i += 1
# done
def num_nodes_of_type(plc, node_type):
"""Returns number of node of a particular type."""
count = 0
......@@ -532,6 +539,7 @@ def num_nodes_of_type(plc, node_type):
return count
# not tested
def extract_blockages_from_tcl(filename: str,
block_name: str,
canvas_width: float,
......@@ -606,7 +614,7 @@ def extract_blockages_from_tcl(filename: str,
index += 1
return blockages
# done
def get_ascii_picture(vect: List[Any],
cols: int,
rows: int,
......@@ -636,7 +644,7 @@ def get_ascii_picture(vect: List[Any],
ret_str += ' -' + '-' * 2 * cols + '\n'
return ret_str
# done
def get_hard_macro_density_map(plc: plc_client.PlacementCost) -> List[float]:
"""Returns the placement density map for hard macros only."""
# Unplaces all standard cells and soft macros, so that grid cell density
......@@ -660,7 +668,7 @@ def get_hard_macro_density_map(plc: plc_client.PlacementCost) -> List[float]:
plc.set_canvas_boundary_check(check_boundary)
return hard_macro_density
# done
def save_placement_with_info(plc: plc_client.PlacementCost,
filename: str,
user_comments: str = '') -> None:
......@@ -755,8 +763,9 @@ def save_placement_with_info(plc: plc_client.PlacementCost,
info += '\nnode_index x y orientation fixed'
return plc.save_placement(filename, info)
# done
def create_placement_cost_using_common_arguments(
plc_client:None,
netlist_file: str,
init_placement: Optional[str] = None,
canvas_width: Optional[float] = None,
......@@ -847,7 +856,7 @@ def create_placement_cost_using_common_arguments(
return plc
# done, but need verify
def get_node_locations(plc: plc_client.PlacementCost) -> Dict[int, int]:
"""Returns all node grid locations (macros and stdcells) in a dict."""
node_locations = dict()
......@@ -866,7 +875,7 @@ def get_node_ordering_by_size(plc: plc_client.PlacementCost) -> List[int]:
node_areas[i] = w * h
return sorted(node_areas, key=node_areas.get, reverse=True)
# not tested
def grid_locations_near(plc: plc_client.PlacementCost,
start_grid_index: int) -> Iterator[int]:
"""Yields node indices closest to the start_grid_index."""
......@@ -894,7 +903,7 @@ def grid_locations_near(plc: plc_client.PlacementCost,
continue
yield int(new_col + new_row * cols)
# not tested
def place_near(plc: plc_client.PlacementCost, node_index: int,
location: int) -> bool:
"""Places a node (legally) closest to the given location.
......@@ -913,7 +922,7 @@ def place_near(plc: plc_client.PlacementCost, node_index: int,
return True
return False
# not tested
def disconnect_high_fanout_nets(plc: plc_client.PlacementCost,
max_allowed_fanouts: int = 500) -> None:
high_fanout_nets = []
......@@ -925,7 +934,7 @@ def disconnect_high_fanout_nets(plc: plc_client.PlacementCost,
high_fanout_nets.append(i)
plc.disconnect_nets(high_fanout_nets)
# not tested
def legalize_placement(plc: plc_client.PlacementCost) -> bool:
"""Places the nodes to legal positions snapping to grid cells."""
# Unplace all except i/o's.
......@@ -963,10 +972,44 @@ def main():
test_netlist_dir = './Plc_client/test/'+'ariane'
netlist_file = os.path.join(test_netlist_dir,'netlist.pb.txt')
init_placement = os.path.join(test_netlist_dir,'initial.plc')
plc = create_placement_cost(netlist_file=netlist_file, init_placement=init_placement)
plc = create_placement_cost_using_common_arguments(netlist_file=netlist_file, init_placement=init_placement,
grid_cols=10, grid_rows=10, congestion_smooth_range=2.0, overlap_threshold=0.004, use_incremental_cost=False)
plc = create_placement_cost(plc_client=plc_client, netlist_file=netlist_file, init_placement=init_placement)
# plc = create_placement_cost_using_common_arguments(netlist_file=netlist_file, init_placement=init_placement,
# grid_cols=10, grid_rows=10, congestion_smooth_range=2.0, overlap_threshold=0.004, use_incremental_cost=False)
print(make_blockage_text(plc))
# save_placement(plc, "save_test", 'this is a comment')
# plc.nodes_of_types()
# node_xy_coordinates
NODE_XY_DICT = {}
for i in nodes_of_types(plc, ['MACRO', 'macro', 'STDCELL', 'PORT']):
NODE_XY_DICT[i] = (100, 100)
restore_node_xy_coordinates(plc, NODE_XY_DICT)
# print(get_node_xy_coordinates(plc))
# macro_orientation
MACRO_ORIENTATION = {}
for i in nodes_of_types(plc, ['MACRO', 'macro']):
MACRO_ORIENTATION[i] = "S"
restore_macro_orientations(plc, MACRO_ORIENTATION)
# print(get_macro_orientations(plc))
fix_port_coordinates(plc)
# write out new plc
save_placement(plc, "save_test", 'this is a comment')
# needs more testing
print(get_node_locations(plc))
# num_nodes_of_type
print("num_nodes_of_type 'MACRO':", num_nodes_of_type(plc, "MACRO"))
# get_hard_macro_density_map
print("get_hard_macro_density_map: \n", get_hard_macro_density_map(plc))
print("get_hard_macro_density_map in ASCII: \n", get_ascii_picture(get_hard_macro_density_map(plc), *plc.get_grid_num_columns_rows()))
print()
if __name__ == '__main__':
main()
\ No newline at end of file
"""Open-Sourced PlacementCost client class."""
from ast import Assert
import os, io
from platform import node
import re
......@@ -238,7 +239,7 @@ class PlacementCost(object):
# [MACRO_NAME]/[PIN_NAME]
soft_macro_name = node_name.rsplit('/', 1)[0]
# soft macro pin
soft_macro_pin = self.SoftMacroPin(name=node_name,
soft_macro_pin = self.SoftMacroPin(name=node_name,ref_id=None,
x = attr_dict['x'][1],
y = attr_dict['y'][1],
macro_name = attr_dict['macro_name'][1])
......@@ -290,7 +291,7 @@ class PlacementCost(object):
# [MACRO_NAME]/[PIN_NAME]
hard_macro_name = node_name.rsplit('/', 1)[0]
# hard macro pin
hard_macro_pin = self.HardMacroPin(name=node_name,
hard_macro_pin = self.HardMacroPin(name=node_name,ref_id=None,
x = attr_dict['x'][1],
y = attr_dict['y'][1],
x_offset = attr_dict['x_offset'][1],
......@@ -562,18 +563,20 @@ class PlacementCost(object):
for macro_idx in (self.hard_macro_indices + self.soft_macro_indices):
macro = self.modules_w_pins[macro_idx]
macro_name = macro.get_name()
macro_type = macro.get_type()
if macro_type == "MACRO":
if not self.is_node_soft_macro(macro_idx):
if macro_name in self.hard_macros_to_inpins.keys():
pin_names = self.hard_macros_to_inpins[macro_name]
else:
return
elif macro_type == "macro":
print("[ERROR UPDATE CONNECTION] MACRO not found")
exit(1)
# use is_node_soft_macro()
elif self.is_node_soft_macro(macro_idx):
if macro_name in self.soft_macros_to_inpins.keys():
pin_names = self.soft_macros_to_inpins[macro_name]
else:
return
print("[ERROR UPDATE CONNECTION] MACRO not found")
exit(1)
for pin_name in pin_names:
pin = self.modules_w_pins[self.mod_name_to_indices[pin_name]]
......@@ -581,7 +584,7 @@ class PlacementCost(object):
if inputs:
for k in inputs.keys():
if macro_type == "MACRO" or macro_type == "macro":
if self.get_node_type(macro_idx) == "MACRO":
weight = pin.get_weight()
macro.add_connections(inputs[k], weight)
......@@ -647,7 +650,7 @@ class PlacementCost(object):
# retrieve location
x_coord.append(sink.get_pos()[0])
y_coord.append(sink.get_pos()[1])
elif curr_type == "macro_pin" or curr_type == "MACRO_PIN":
elif curr_type == "MACRO_PIN":
# add source position
x_coord.append(mod.get_pos()[0])
y_coord.append(mod.get_pos()[1])
......@@ -733,6 +736,9 @@ class PlacementCost(object):
def get_congestion_cost(self):
#return max(self.get_H_congestion_cost(), self.get_V_congestion_cost())
# TODO need to test if cong is smaller than 5
if self.FLAG_UPDATE_CONGESTION:
self.get_routing()
return self.abu(self.V_routing_cong + self.H_routing_cong, 0.05)
def __get_grid_cell_location(self, x_pos, y_pos):
......@@ -1292,7 +1298,6 @@ class PlacementCost(object):
self.FLAG_UPDATE_CONGESTION = False
for mod in self.modules_w_pins:
norm_fact = 1.0
curr_type = mod.get_type()
# bounding box data structure
node_gcells = set()
......@@ -1314,7 +1319,7 @@ class PlacementCost(object):
# retrieve grid location
node_gcells.add(self.__get_grid_cell_location(*(sink.get_pos())))
elif (curr_type == "macro_pin" or curr_type == "MACRO_PIN") and mod.get_sink():
elif curr_type == "MACRO_PIN" and mod.get_sink():
# add source position
node_gcells.add(self.__get_grid_cell_location(*(mod.get_pos())))
source_gcell = self.__get_grid_cell_location(*(mod.get_pos()))
......@@ -1328,10 +1333,10 @@ class PlacementCost(object):
sink_idx = self.mod_name_to_indices[sink_name]
# retrieve sink object
sink = self.modules_w_pins[sink_idx]
# retrieve grid location
# retrieve grid location
node_gcells.add(self.__get_grid_cell_location(*(sink.get_pos())))
elif curr_type == "MACRO":
elif curr_type == "MACRO" and self.is_node_hard_macro(self.mod_name_to_indices[mod.get_name()]):
module_h = mod.get_height()
module_w = mod.get_width()
module_x, module_y = mod.get_pos()
......@@ -1412,10 +1417,24 @@ class PlacementCost(object):
self.H_routing_cong = temp_H_routing_cong
def is_node_soft_macro(self, node_idx) -> bool:
return self.get_node_type(node_idx) == "soft_macro"
"""
Return None or return ref_id
"""
try:
return node_idx in self.soft_macro_indices
except IndexError:
print("[ERROR INDEX OUT OF RANGE] Can not process index at {}".format(node_idx))
exit(0)
def is_node_hard_macro(self, node_idx) -> bool:
return self.get_node_type(node_idx) == "hard_macro"
"""
Return None or return ref_id
"""
try:
return node_idx in self.hard_macro_indices
except IndexError:
print("[ERROR INDEX OUT OF RANGE] Can not process index at {}".format(node_idx))
exit(0)
def get_node_name(self, node_idx: int) -> str:
return self.indices_to_mod_name[node_idx]
......@@ -1440,7 +1459,7 @@ class PlacementCost(object):
def get_node_type(self, node_idx: int) -> str:
"""
Return Vertical/Horizontal Macro Allocation
Return node type
"""
try:
return self.modules_w_pins[node_idx].get_type()
......@@ -1449,6 +1468,25 @@ class PlacementCost(object):
print("[INDEX OUT OF RANGE WARNING] Can not process index at {}".format(node_idx))
return None
def get_node_width_height(self, node_idx: int):
"""
Return node dimension
"""
mod = None
try:
mod = self.modules_w_pins[node_idx]
assert mod.get_type() in ['MACRO', 'macro', 'STDCELL', 'PORT']
except AssertionError:
print("[ERROR NODE FIXED] Found {}. Only 'MACRO', 'macro', 'STDCELL'".format(mod.get_type())
+"'PORT' are considered to be fixable nodes")
exit(1)
except Exception:
print("[ERROR NODE FIXED] Could not find module by node index")
exit(1)
return mod.get_width(), mod.get_height()
def make_soft_macros_square(self):
pass
......@@ -1599,14 +1637,62 @@ class PlacementCost(object):
return macro_adj, sorted(cell_location)
def is_node_fixed(self):
pass
def is_node_fixed(self, node_idx: int):
mod = None
try:
mod = self.modules_w_pins[node_idx]
assert mod.get_type() in ['MACRO', 'macro', 'STDCELL', 'PORT']
except AssertionError:
print("[ERROR NODE FIXED] Found {}. Only 'MACRO', 'macro', 'STDCELL'".format(mod.get_type())
+"'PORT' are considered to be fixable nodes")
exit(1)
except Exception:
print("[ERROR NODE FIXED] Could not find module by node index")
exit(1)
return mod.get_fix_flag()
def optimize_stdcells(self):
pass
def update_node_coords(self):
pass
def update_node_coords(self, node_idx, x_pos, y_pos):
"""
Update Node location if node is 'MACRO', 'macro', 'STDCELL', 'PORT'
"""
mod = None
try:
mod = self.modules_w_pins[node_idx]
assert mod.get_type() in ['MACRO', 'macro', 'STDCELL', 'PORT']
except AssertionError:
print("[ERROR NODE LOCATION] Found {}. Only 'MACRO', 'macro', 'STDCELL'".format(mod.get_type())
+"'PORT' are considered to be placable nodes")
exit(1)
except Exception:
print("[ERROR NODE LOCATION] Could not find module by node index")
exit(1)
mod.set_pos(x_pos, y_pos)
def update_macro_orientation(self, node_idx, orientation):
"""
Update macro orientation if node is 'MACRO', 'macro'
"""
mod = None
try:
mod = self.modules_w_pins[node_idx]
assert mod.get_type() in ['MACRO', 'macro']
except AssertionError:
print("[ERROR MACRO ORIENTATION] Found {}. Only 'MACRO', 'macro'".format(mod.get_type())
+" are considered to be ORIENTED")
exit(1)
except Exception:
print("[ERROR MACRO ORIENTATION] Could not find module by node index")
exit(1)
mod.set_orientation(orientation)
def update_port_sides(self):
pass
......@@ -1615,31 +1701,110 @@ class PlacementCost(object):
pass
def get_node_location(self, node_idx):
pass
"""
Return Node location if node is 'MACRO', 'macro', 'STDCELL', 'PORT'
"""
mod = None
try:
mod = self.modules_w_pins[node_idx]
assert mod.get_type() in ['MACRO', 'macro', 'STDCELL', 'PORT']
except AssertionError:
print("[ERROR NODE LOCATION] Found {}. Only 'MACRO', 'macro', 'STDCELL'".format(mod.get_type())
+"'PORT' are considered to be placable nodes")
exit(1)
except Exception:
print("[ERROR NODE PLACED] Could not find module by node index")
exit(1)
return mod.get_pos()
def get_grid_cell_of_node(self, node_idx):
""" if grid_cell at grid crossing, break-tie to upper right
"""
return self.modules_w_pins(node_idx).get_location()
mod = None
try:
mod = self.modules_w_pins[node_idx]
assert mod.get_type() in ['MACRO', 'macro']
except AssertionError:
print("[ERROR NODE LOCATION] Found {}. Only 'MACRO', 'macro'".format(mod.get_type())
+" can be called")
exit(1)
except Exception:
print("[ERROR NODE LOCATION] Could not find module by node index")
exit(1)
row, col = self.__get_grid_cell_location(*mod.get_pos())
def update_macro_orientation(self, node_idx, orientation):
pass
return row * self.grid_col + col
def get_macro_orientation(self):
pass
def get_macro_orientation(self, node_idx):
mod = None
try:
mod = self.modules_w_pins[node_idx]
assert mod.get_type() in ['MACRO', 'macro']
except AssertionError:
print("[ERROR MACRO ORIENTATION] Found {}. Only 'MACRO', 'macro'".format(mod.get_type())
+" are considered to be ORIENTED")
exit(1)
except Exception:
print("[ERROR MACRO ORIENTATION] Could not find module by node index")
exit(1)
return mod.get_orientation()
def unfix_node_coord(self):
"""In case plc is loaded with fixed macros
def unfix_node_coord(self, node_idx):
"""
pass
Unfix a module
"""
mod = None
try:
mod = self.modules_w_pins[node_idx]
assert mod.get_type() in ['MACRO', 'macro', 'STDCELL', 'PORT']
except AssertionError:
print("[ERROR UNFIX NODE] Found {}. Only 'MACRO', 'macro', 'STDCELL'".format(mod.get_type())
+"'PORT' are considered to be fixable nodes")
exit(1)
except Exception:
print("[ERROR UNFIX NODE] Could not find module by node index")
exit(1)
self.modules_w_pins[node_idx].set_fix_flag(False)
def fix_node_coord(self, node_idx):
"""
Fix a module
"""
mod = None
try:
mod = self.modules_w_pins[node_idx]
assert mod.get_type() in ['MACRO', 'macro', 'STDCELL', 'PORT']
except AssertionError:
print("[ERROR FIX NODE] Found {}. Only 'MACRO', 'macro', 'STDCELL'".format(mod.get_type())
+"'PORT' are considered to be fixable nodes")
exit(1)
except Exception:
print("[ERROR FIX NODE] Could not find module by node index")
exit(1)
self.modules_w_pins[node_idx].set_fix_flag(True)
def unplace_all_nodes(self):
pass
def place_node(self, node_idx, grid_cell_idx):
mod = None
try:
mod = self.modules_w_pins[node_idx]
except AssertionError:
pass
except Exception:
pass
pass
def can_place_node(self, node_idx, grid_cell_idx):
......@@ -1650,7 +1815,21 @@ class PlacementCost(object):
pass
def is_node_placed(self, node_idx):
pass
mod = None
try:
mod = self.modules_w_pins[node_idx]
assert mod.get_type() in ['MACRO', 'macro', 'STDCELL', 'PORT']
except AssertionError:
print("[ERROR NODE PLACED] Found {}. Only 'MACRO', 'STDCELL',".format(mod.get_type())
+"'PORT' are considered to be placable nodes")
exit(1)
except Exception:
print("[ERROR NODE PLACED] Could not find module by node index")
exit(1)
mod = self.modules_w_pins[node_idx]
return mod.get_placed_flag()
def disconnect_nets(self):
pass
......@@ -1661,7 +1840,7 @@ class PlacementCost(object):
return self.netlist_file
def get_blockages(self):
pass
return self.blockages
def create_blockage(self, minx, miny, maxx, maxy, blockage_rate):
self.blockages.append([minx, miny, maxx, maxy, blockage_rate])
......@@ -1678,8 +1857,32 @@ class PlacementCost(object):
return self.mod_name_to_indices[pin.get_macro_name()]
return -1
def save_placement(self):
pass
def save_placement(self, filename, info):
"""
When writing out info line-by-line, add a "#" at front
"""
with open(filename, 'w+') as f:
for line in info.split('\n'):
f.write("# " + line + '\n')
# if first, no \newline
HEADER = True
for mod_idx in sorted(self.hard_macro_indices + self.soft_macro_indices + self.port_indices):
# [node_index] [x] [y] [orientation] [fixed]
mod = self.modules_w_pins[mod_idx]
if HEADER:
f.write("{} {:g} {:g} {} {}".format(mod_idx,
*mod.get_pos(),
mod.get_orientation() if mod.get_orientation() else "-",
"1" if mod.get_fix_flag() else "0"))
HEADER = False
else:
f.write("\n{} {:g} {:g} {} {}".format(mod_idx,
*mod.get_pos(),
mod.get_orientation() if mod.get_orientation() else "-",
"1" if mod.get_fix_flag() else "0"))
def display_canvas( self,
annotate=True,
......@@ -1740,9 +1943,14 @@ class PlacementCost(object):
self.connection = {} # [module_name] => edge degree
self.fix_flag = True
self.placement = 0 # needs to be updated
self.orientation = None
self.ifPlaced = True
def get_name(self):
return self.name
def get_orientation(self):
return self.orientation
def add_connection(self, module_name):
# NOTE: assume PORT names does not contain slash
......@@ -1813,6 +2021,12 @@ class PlacementCost(object):
def get_fix_flag(self):
return self.fix_flag
def set_placed_flag(self, ifPlaced):
self.ifPlaced = ifPlaced
def get_placed_flag(self):
return self.ifPlaced
class SoftMacro:
def __init__(self, name, width, height, x = 0.0, y = 0.0):
self.name = name
......@@ -1860,7 +2074,7 @@ class PlacementCost(object):
return self.x, self.y
def get_type(self):
return "macro"
return "MACRO"
def get_connection(self):
return self.connection
......@@ -1892,11 +2106,18 @@ class PlacementCost(object):
def get_fix_flag(self):
return self.fix_flag
def set_placed_flag(self, ifPlaced):
self.ifPlaced = ifPlaced
def get_placed_flag(self):
return self.ifPlaced
class SoftMacroPin:
def __init__( self, name,
x = 0.0, y = 0.0,
macro_name = "", weight = 1.0):
def __init__(self, name, ref_id,
x = 0.0, y = 0.0,
macro_name = "", weight = 1.0):
self.name = name
self.ref_id = ref_id
self.x = float(x)
self.y = float(y)
self.x_offset = 0.0 # not used
......@@ -1908,6 +2129,12 @@ class PlacementCost(object):
def set_weight(self, weight):
self.weight = weight
def set_ref_id(self, ref_id):
self.ref_id = ref_id
def get_ref_id(self):
return self.ref_id
def get_weight(self):
return self.weight
......@@ -1956,7 +2183,7 @@ class PlacementCost(object):
return self.weight
def get_type(self):
return "macro_pin"
return "MACRO_PIN"
class HardMacro:
def __init__(self, name, width, height,
......@@ -2037,13 +2264,20 @@ class PlacementCost(object):
def get_fix_flag(self):
return self.fix_flag
def set_placed_flag(self, ifPlaced):
self.ifPlaced = ifPlaced
def get_placed_flag(self):
return self.ifPlaced
class HardMacroPin:
def __init__(self, name,
def __init__(self, name, ref_id,
x = 0.0, y = 0.0,
x_offset = 0.0, y_offset = 0.0,
macro_name = "", weight = 1.0):
self.name = name
self.ref_id = ref_id
self.x = float(x)
self.y = float(y)
self.x_offset = float(x_offset)
......@@ -2053,6 +2287,12 @@ class PlacementCost(object):
self.sink = {}
self.ifPlaced = True
def set_ref_id(self, ref_id):
self.ref_id = ref_id
def get_ref_id(self):
return self.ref_id
def set_weight(self, weight):
self.weight = weight
......
import numpy as np
import sys,os,traceback
import argparse
import math
import math,re
from absl import flags
from absl.flags import argparse_flags
from absl import app
from Plc_client import plc_client_os as plc_client_os
from Plc_client import placement_util_os as placement_util
try:
from Plc_client import plc_client as plc_client
except ImportError:
......@@ -28,10 +30,10 @@ Example:
--height 356.640\
--col 35\
--row 33\
--rpmh 10\
--rpmv 10\
--marh 5\
--marv 5\
--rpmh 70.330\
--rpmv 74.510\
--marh 51.790\
--marv 51.790\
--smooth 2
$ python3 -m Plc_client.plc_client_os_test --netlist ./Plc_client/test/ariane133/netlist.pb.txt\
......@@ -100,7 +102,6 @@ class PlacementCostTest():
self.MARV = marv
self.SMOOTH = smooth
def test_metadata(self):
print("############################ TEST METADATA ############################")
# Google's Binary Executable
......@@ -211,6 +212,9 @@ class PlacementCostTest():
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")
......@@ -232,16 +236,16 @@ class PlacementCostTest():
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)
# TODO: [IGNORE] Setting blockage has no effect on proxy cost computation
# TODO: [IGNORE] create_blockage must be defined BEFORE set_canvas_size and set_placement_grid in order to be considered on the canvas
if False:
self.plc.create_blockage(0, 0, 400, 400, 1)
self.plc.create_blockage(0, 0, 200, 200, 1)
self.plc.create_blockage(0.0, 100.0, 300.0, 300.0, 1.0)
self.plc.create_blockage(300,0,500,200,1)
print(self.plc.get_blockages())
print(self.plc.make_soft_macros_square())
print(self.plc.set_use_incremental_cost(True))
......@@ -257,7 +261,9 @@ class PlacementCostTest():
# Density
try:
print(self.plc_os.get_density_cost())
assert int(sum(self.plc_os.get_grid_cells_density())) == int(sum(self.plc.get_grid_cells_density()))
print(self.plc_os.get_density_cost())
assert int(self.plc_os.get_density_cost()) == int(self.plc.get_density_cost())
except Exception as e:
print("[DENSITY ERROR] Discrepancies found when computing density -- {}, {}".format(str(self.plc.get_density_cost()), self.plc_os.get_density_cost()))
......@@ -265,8 +271,10 @@ class PlacementCostTest():
# Congestion
try:
print(self.plc_os.get_congestion_cost())
assert abs(sum(self.plc_os.get_horizontal_routing_congestion()) - sum(self.plc.get_horizontal_routing_congestion())) < 1e-3
assert abs(sum(self.plc_os.get_vertical_routing_congestion()) - sum(self.plc.get_vertical_routing_congestion())) < 1e-3
print(self.plc_os.get_congestion_cost())
assert abs(self.plc.get_congestion_cost() - self.plc_os.get_congestion_cost()) < 1e-3
except Exception as e:
print("[CONGESTION ERROR] Discrepancies found when computing congestion -- {}".format(str(e)))
......@@ -287,19 +295,19 @@ class PlacementCostTest():
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)
NODE_IDX = 0
print("get_macro_indices", self.plc.get_macro_indices(), self.plc_os.get_macro_indices())
NODE_IDX = 22853
print("get_macro_indices", self.plc.get_macro_indices())
print("get_node_name", self.plc.get_node_name(NODE_IDX))
print("get_node_type", self.plc.get_node_type(NODE_IDX))
print("get_node_location", self.plc.get_node_location(NODE_IDX))
print("get_grid_cell_of_node", self.plc.get_grid_cell_of_node(NODE_IDX))
print("get_node_location", self.plc.get_node_location(NODE_IDX))
print("get_macro_orientation", self.plc.get_macro_orientation(NODE_IDX))
print("is_node_placed", self.plc.is_node_placed(NODE_IDX))
print("get_source_filename", self.plc.get_source_filename())
print("get_blockages", self.plc.get_blockages())
print("get_ref_node_id", self.plc.get_ref_node_id(NODE_IDX), self.plc.get_ref_node_id(NODE_IDX))
print("get_node_mask\n", np.array(self.plc.get_node_mask(NODE_IDX)).reshape((4,4)))
print("can_place_node", self.plc.can_place_node(0, 1))
# print("get_node_mask\n", np.array(self.plc.get_node_mask(NODE_IDX)).reshape((4,4)))
# print("can_place_node", self.plc.can_place_node(0, 1))
print("***************************************************")
def test_proxy_congestion(self):
......@@ -375,6 +383,87 @@ class PlacementCostTest():
print("**************BY ENTRY DIFF")
print(temp_gl_h_mc[0][6], temp_os_h_mc[0][6])
def test_placement_util(self, keep_save_file=False):
"""
* Read same input, perturb placement and orientation, write to new .plc
"""
print("############################ TEST PLACEMENT UTIL ############################")
try:
assert self.PLC_PATH
except AssertionError:
print("[ERROR PLACEMENT UTIL TEST] Facilitate required .plc file")
self.plc_util = placement_util.create_placement_cost(
plc_client=plc_client,
netlist_file=self.NETLIST_PATH,
init_placement=self.PLC_PATH
)
self.plc_util_os = placement_util.create_placement_cost(
plc_client=plc_client_os,
netlist_file=self.NETLIST_PATH,
init_placement=self.PLC_PATH
)
# ********************** plc_client_os **********************
# node_xy_coordinates
# NODE_XY_DICT = {}
# for i in placement_util.nodes_of_types(self.plc_util_os, ['MACRO', 'STDCELL', 'PORT']):
# NODE_XY_DICT[i] = (100, 100)
# placement_util.restore_node_xy_coordinates(self.plc_util_os, NODE_XY_DICT)
# macro_orientation
MACRO_ORIENTATION = {}
for i in placement_util.nodes_of_types(self.plc_util_os, ['MACRO']):
MACRO_ORIENTATION[i] = "S"
placement_util.restore_macro_orientations(self.plc_util_os, MACRO_ORIENTATION)
# fix ports
placement_util.fix_port_coordinates(self.plc_util_os)
# write out new plc
placement_util.save_placement(self.plc_util_os, "save_test_os.plc", 'this is a comment')
# ********************** plc_client **********************
# # node_xy_coordinates
# NODE_XY_DICT = {}
# for i in placement_util.nodes_of_types(self.plc_util, ['MACRO', 'STDCELL', 'PORT']):
# NODE_XY_DICT[i] = (100, 100)
# placement_util.restore_node_xy_coordinates(self.plc_util, NODE_XY_DICT)
# macro_orientation
MACRO_ORIENTATION = {}
for i in placement_util.nodes_of_types(self.plc_util, ['MACRO']):
MACRO_ORIENTATION[i] = "S"
placement_util.restore_macro_orientations(self.plc_util, MACRO_ORIENTATION)
# fix ports
placement_util.fix_port_coordinates(self.plc_util)
# write out new plc
placement_util.save_placement(self.plc_util, "save_test_gl.plc", 'this is a comment')
print(" +++++++++++++++++++++++++++++++++")
print(" +++ TEST PLACEMENT UTIL: PASS +++")
print(" +++++++++++++++++++++++++++++++++")
# This is only for node information, line-by-line test
try:
with open('save_test_gl.plc') as f1, open('save_test_os.plc') as f2:
for idx, (line1, line2) in enumerate(zip(f1, f2)):
if line1.strip() != line2.strip():
if not re.match(r"(# )\w+", line1.strip()):
print("PLC MISMATCH (GL, OS)\n", line1.strip(), "\n", line2.strip())
raise AssertionError ("false")
except AssertionError:
print("[ERROR PLACEMENT UTIL] Saved PLC Discrepency found at line {}".format(str(idx)))
def test_environment(self):
pass
def parse_flags(argv):
parser = argparse_flags.ArgumentParser(description='An argparse + app.run example')
parser.add_argument("--netlist", required=True,
......@@ -400,18 +489,36 @@ def parse_flags(argv):
parser.add_argument("--smooth", type=float, default=1, required=False,
help="Grid row")
return parser.parse_args(argv[1:])
def main(args):
if args.plc:
PCT = PlacementCostTest(args.netlist, args.plc, args.width, args.height,
args.col, args.row, args.rpmv, args.rpmv,
args.marh, args.marv, args.smooth)
PCT = PlacementCostTest(NETLIST_PATH=args.netlist,
PLC_PATH=args.plc,
width=args.width,
height=args.height,
column=args.col,
row=args.row,
rpmv=args.rpmv,
rpmh=args.rpmh,
marh=args.marh,
marv=args.marv,
smooth=args.smooth)
else:
PCT = PlacementCostTest(args.netlist, args.width, args.height,
args.col, args.row, args.rpmv, args.rpmv,
args.marh, args.marv, args.smooth)
PCT.test_metadata()
PCT = PlacementCostTest(NETLIST_PATH=args.netlist,
width=args.width,
height=args.height,
column=args.col,
row=args.row,
rpmv=args.rpmv,
rpmh=args.rpmh,
marh=args.marh,
marv=args.marv,
smooth=args.smooth)
# PCT.test_metadata()
PCT.test_proxy_cost()
PCT.test_placement_util()
# PCT.test_miscellaneous()
if __name__ == '__main__':
app.run(main, flags_parser=parse_flags)
\ No newline at end of file
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