Commit c612bdbc by Dinple

Overhaul WIP + redo testbench

parent 3dfa0aa5
...@@ -2,4 +2,8 @@ Flows/*/*/run/*/ ...@@ -2,4 +2,8 @@ Flows/*/*/run/*/
Flows/*/*/run-* Flows/*/*/run-*
Flows/job Flows/job
CodeElements/*/*/__pycache__ CodeElements/*/*/__pycache__
CodeElements/Plc_client/test/* CodeElements/Plc_client/test/
\ No newline at end of file CodeElements/Plc_client/test/*/*
CodeElements/Plc_client/plc_client_os.py
CodeElements/Plc_client/__pycache__/*
CodeElements/Plc_client/proto_reader.py
...@@ -9,7 +9,20 @@ curl 'https://raw.githubusercontent.com/google-research/circuit_training/main/ci ...@@ -9,7 +9,20 @@ curl 'https://raw.githubusercontent.com/google-research/circuit_training/main/ci
sudo curl https://storage.googleapis.com/rl-infra-public/circuit-training/placement_cost/plc_wrapper_main \ sudo curl https://storage.googleapis.com/rl-infra-public/circuit-training/placement_cost/plc_wrapper_main \
-o /usr/local/bin/plc_wrapper_main -o /usr/local/bin/plc_wrapper_main
# Run plc testbench # Run plc testbench
python -m Plc_client.plc_client_os_test # python -m Plc_client.plc_client_os_test [-h] [--helpfull] --netlist NETLIST [--plc PLC] --width WIDTH --height HEIGHT --col COL --row ROW [--rpmh RPMH] [--rpmv RPMV] [--marh MARH] [--marv MARV] [--smooth SMOOTH]
# Example
python -m Plc_client.plc_client_os_test --netlist ./Plc_client/test/ariane/netlist.pb.txt\
--plc ./Plc_client/test/ariane/initial.plc\
--width 356.592\
--height 356.640\
--col 35\
--row 33\
--rpmh 10\
--rpmv 10\
--marh 5\
--marv 5\
--smooth 2
``` ```
## HPWL Computation ## HPWL Computation
...@@ -27,15 +40,15 @@ $$ ...@@ -27,15 +40,15 @@ $$
HPWL(netlist) = \sum_{i}^{N_{netlist}} W_{i\_{source}} \cdot [max_{b\in i}(x_b) - min_{b\in i}(x_b) + max_{b\in i}(y_b) - min_{b\in i}(y_b)] HPWL(netlist) = \sum_{i}^{N_{netlist}} W_{i\_{source}} \cdot [max_{b\in i}(x_b) - min_{b\in i}(x_b) + max_{b\in i}(y_b) - min_{b\in i}(y_b)]
$$ $$
## Density Cost Computation ## Density Cost Computation
Density cost is computed from grid cells density. Density cost is computed from grid cells density.
By default, any given input will have grid col/row set to 10/10 until user later defines in the .plc file. By default, any given input will have grid col/row set to 10/10 until user later defines in the .plc file.
Grid cell density is represented as an 1D array where the length is set to be Grid cell density is represented as an 1D array where the length is set to be the following:
$$ $$
grid_\{col} \cdot grid_\{row} grid_{col} \cdot grid_{row}
$$ $$
Each entry of this array represents the current occupied precentage within this cell. Each entry of this array represents the current occupied precentage within this cell.
......
...@@ -41,10 +41,12 @@ class PlacementCost(object): ...@@ -41,10 +41,12 @@ class PlacementCost(object):
self.macro_macro_x_spacing = macro_macro_x_spacing self.macro_macro_x_spacing = macro_macro_x_spacing
self.macro_macro_y_spacing = macro_macro_y_spacing self.macro_macro_y_spacing = macro_macro_y_spacing
# Update cost computation flags # Update flags
self.FLAG_UPDATE_WIRELENGTH = True self.FLAG_UPDATE_WIRELENGTH = True
self.FLAG_UPDATE_DENSITY = True self.FLAG_UPDATE_DENSITY = True
self.FLAG_UPDATE_CONGESTION = True self.FLAG_UPDATE_CONGESTION = True
self.FLAG_UPDATE_MACRO_ADJ = True
self.FLAG_UPDATE_MACRO_AND_CLUSTERED_PORT_ADJ = True
# Check netlist existance # Check netlist existance
assert os.path.isfile(self.netlist_file) assert os.path.isfile(self.netlist_file)
...@@ -59,9 +61,9 @@ class PlacementCost(object): ...@@ -59,9 +61,9 @@ class PlacementCost(object):
self.overlap_thres = 0.0 self.overlap_thres = 0.0
self.hrouting_alloc = 0.0 self.hrouting_alloc = 0.0
self.vrouting_alloc = 0.0 self.vrouting_alloc = 0.0
self.macro_horizontal_routing_allocation = 0.0 self.macro_horizontal_routing_allocation = 0.0
self.macro_vertical_routing_allocation = 0.0 self.macro_vertical_routing_allocation = 0.0
self.canvas_boundary_check = True
# net information # net information
self.net_cnt = 0 self.net_cnt = 0
...@@ -99,16 +101,16 @@ class PlacementCost(object): ...@@ -99,16 +101,16 @@ class PlacementCost(object):
# initial grid mask # initial grid mask
self.global_node_mask = [0] * self.grid_col * self.grid_row self.global_node_mask = [0] * self.grid_col * self.grid_row
# store module/component count # store module/component count
self.port_cnt = len(self.port_indices) self.ports_cnt = len(self.port_indices)
self.hard_macro_cnt = len(self.hard_macro_indices) self.hard_macro_cnt = len(self.hard_macro_indices)
self.hard_macro_pin_cnt = len(self.hard_macro_pin_indices) self.hard_macro_pins_cnt = len(self.hard_macro_pin_indices)
self.soft_macro_cnt = len(self.soft_macro_indices) self.soft_macros_cnt = len(self.soft_macro_indices)
self.soft_macro_pin_cnt = len(self.soft_macro_pin_indices) self.soft_macro_pins_cnt = len(self.soft_macro_pin_indices)
self.module_cnt = self.hard_macro_cnt + self.soft_macro_cnt + self.port_cnt self.module_cnt = self.hard_macro_cnt + self.soft_macros_cnt + self.ports_cnt
# assert module and pin count are correct # assert module and pin count are correct
assert (len(self.modules)) == self.module_cnt assert (len(self.modules)) == self.module_cnt
assert (len(self.modules_w_pins) - \ assert (len(self.modules_w_pins) - \
self.hard_macro_pin_cnt - self.soft_macro_pin_cnt) \ self.hard_macro_pins_cnt - self.soft_macro_pins_cnt) \
== self.module_cnt == self.module_cnt
def __peek(self, f:io.TextIOWrapper): def __peek(self, f:io.TextIOWrapper):
...@@ -206,12 +208,12 @@ class PlacementCost(object): ...@@ -206,12 +208,12 @@ class PlacementCost(object):
try: try:
assert 'x' in attr_dict.keys() assert 'x' in attr_dict.keys()
except AssertionError: except AssertionError:
logging.warning('x is not defined') logging.warning('[NETLIST PARSER ERROR] x is not defined')
try: try:
assert 'y' in attr_dict.keys() assert 'y' in attr_dict.keys()
except AssertionError: except AssertionError:
logging.warning('y is not defined') logging.warning('[NETLIST PARSER ERROR] y is not defined')
soft_macro = self.SoftMacro(name=node_name, width=attr_dict['width'][1], soft_macro = self.SoftMacro(name=node_name, width=attr_dict['width'][1],
height = attr_dict['height'][1], height = attr_dict['height'][1],
...@@ -375,15 +377,15 @@ class PlacementCost(object): ...@@ -375,15 +377,15 @@ class PlacementCost(object):
# skip empty lines # skip empty lines
if len(line_item) == 0: if len(line_item) == 0:
continue continue
# # skip comments
# if re.search(r"\S", line)[0] == '#':
# continue
if 'Columns' in line_item and 'Rows' in line_item: if 'Columns' in line_item and 'Rows' in line_item:
# Columns and Rows should be defined on the same one-line # Columns and Rows should be defined on the same one-line
_columns = int(line_item[1]) _columns = int(line_item[1])
_rows = int(line_item[3]) _rows = int(line_item[3])
elif "Width" in line_item and "Height" in line_item:
# Width and Height should be defined on the same one-line
_width = float(line_item[1])
_height = float(line_item[3])
elif "Area" in line_item: elif "Area" in line_item:
# Total core area of modules # Total core area of modules
_area = float(line_item[1]) _area = float(line_item[1])
...@@ -428,7 +430,7 @@ class PlacementCost(object): ...@@ -428,7 +430,7 @@ class PlacementCost(object):
and len(line_item) == 2: and len(line_item) == 2:
_macros_cnt = int(line_item[1]) _macros_cnt = int(line_item[1])
elif all(re.match(r'[0-9N\.\-]+', it) for it in line_item): elif all(re.match(r'[0-9N\.\-]+', it) for it in line_item):
# NOTE: [node_index] [x] [y] [orientation] [fixed] # [node_index] [x] [y] [orientation] [fixed]
_node_plc[int(line_item[0])] = line_item[1:] _node_plc[int(line_item[0])] = line_item[1:]
# return as dictionary # return as dictionary
...@@ -457,11 +459,15 @@ class PlacementCost(object): ...@@ -457,11 +459,15 @@ class PlacementCost(object):
return info_dict return info_dict
def restore_placement(self, plc_pth: str, ifInital=True, ifValidate=False): def restore_placement(self, plc_pth: str, ifInital=True, ifValidate=False, ifReadComment = False):
""" """
Read and retrieve .plc file information Read and retrieve .plc file information
NOTE: DO NOT always set self.init_plc because NOTE: DO NOT always set self.init_plc because this function is also
this function is also used to read final placement file used to read final placement file.
ifReadComment: By default, Google's plc_client does not extract
information from .plc comment. This is purely done in
placement_util.py. For purpose of testing, we included this option.
""" """
# if plc is an initial placement # if plc is an initial placement
if ifInital: if ifInital:
...@@ -474,10 +480,10 @@ class PlacementCost(object): ...@@ -474,10 +480,10 @@ class PlacementCost(object):
if ifValidate: if ifValidate:
try: try:
assert(self.hard_macro_cnt == info_dict['hard_macros_cnt']) assert(self.hard_macro_cnt == info_dict['hard_macros_cnt'])
assert(self.hard_macro_pin_cnt == info_dict['hard_macro_pins_cnt']) assert(self.hard_macro_pins_cnt == info_dict['hard_macro_pins_cnt'])
assert(self.soft_macro_cnt == info_dict['soft_macros_cnt']) assert(self.soft_macros_cnt == info_dict['soft_macros_cnt'])
assert(self.soft_macro_pin_cnt == info_dict['soft_macro_pins_cnt']) assert(self.soft_macro_pins_cnt == info_dict['soft_macro_pins_cnt'])
assert(self.port_cnt == info_dict['ports_cnt']) assert(self.ports_cnt == info_dict['ports_cnt'])
except AssertionError: except AssertionError:
_, _, tb = sys.exc_info() _, _, tb = sys.exc_info()
traceback.print_tb(tb) traceback.print_tb(tb)
...@@ -506,6 +512,8 @@ class PlacementCost(object): ...@@ -506,6 +512,8 @@ class PlacementCost(object):
except Exception as e: except Exception as e:
print('[PLC PARSER ERROR] %s' % str(e)) print('[PLC PARSER ERROR] %s' % str(e))
#TODO ValueError: Error in calling RestorePlacement with ('./Plc_client/test/ariane/initial.plc',): Can't place macro i_ariane/i_frontend/i_icache/sram_block_3__tag_sram/mem/mem_inst_mem_256x45_256x16_0x0 at (341.75, 8.8835). Exceeds the boundaries of the placement area..
self.modules_w_pins[mod_idx].set_pos(mod_x, mod_y) self.modules_w_pins[mod_idx].set_pos(mod_x, mod_y)
if mod_orient and mod_orient != '-': if mod_orient and mod_orient != '-':
...@@ -517,16 +525,20 @@ class PlacementCost(object): ...@@ -517,16 +525,20 @@ class PlacementCost(object):
self.modules_w_pins[mod_idx].set_fix_flag(True) self.modules_w_pins[mod_idx].set_fix_flag(True)
# set meta information # set meta information
self.set_canvas_size(info_dict['width'], info_dict['height']) if ifReadComment:
self.set_placement_grid(info_dict['columns'], info_dict['rows']) self.set_canvas_size(info_dict['width'], info_dict['height'])
self.set_block_name(info_dict['block']) self.set_placement_grid(info_dict['columns'], info_dict['rows'])
self.set_routes_per_micron(info_dict['routes_per_micron_hor'],\ self.set_block_name(info_dict['block'])
info_dict['routes_per_micron_ver']) self.set_routes_per_micron(
self.set_macro_routing_allocation(info_dict['routes_used_by_macros_hor'],\ info_dict['routes_per_micron_hor'],
info_dict['routes_used_by_macros_ver']) info_dict['routes_per_micron_ver']
self.set_congestion_smooth_range(info_dict['smoothing_factor']) )
self.set_overlap_threshold(info_dict['overlap_threshold']) self.set_macro_routing_allocation(
info_dict['routes_used_by_macros_hor'],
info_dict['routes_used_by_macros_ver']
)
self.set_congestion_smooth_range(info_dict['smoothing_factor'])
self.set_overlap_threshold(info_dict['overlap_threshold'])
def __update_connection(self): def __update_connection(self):
""" """
...@@ -558,34 +570,12 @@ class PlacementCost(object): ...@@ -558,34 +570,12 @@ class PlacementCost(object):
weight = pin.get_weight() weight = pin.get_weight()
macro.add_connections(inputs[k], weight) macro.add_connections(inputs[k], weight)
def __update_cost_info(self):
"""
Update wirelength/density/congestion related computation
"""
pass
def __update_wirelength(self):
"""
Update wirelength computation
"""
pass
def __update_density(self):
"""
Update density computation
"""
pass
def __update_congestion(self):
"""
Update congestion computation
"""
pass
def get_cost(self) -> float: def get_cost(self) -> float:
""" """
Compute wirelength cost from wirelength Compute wirelength cost from wirelength
""" """
if self.FLAG_UPDATE_WIRELENGTH:
self.FLAG_UPDATE_WIRELENGTH = False
return self.get_wirelength() / ((self.get_canvas_width_height()[0]\ return self.get_wirelength() / ((self.get_canvas_width_height()[0]\
+ self.get_canvas_width_height()[1]) * self.net_cnt) + self.get_canvas_width_height()[1]) * self.net_cnt)
...@@ -599,20 +589,20 @@ class PlacementCost(object): ...@@ -599,20 +589,20 @@ class PlacementCost(object):
total_area += mod.get_area() total_area += mod.get_area()
return total_area return total_area
def get_hard_macro_count(self) -> int: def get_hard_macros_count(self) -> int:
return self.hard_macro_cnt return self.hard_macro_cnt
def get_port_count(self) -> int: def get_ports_count(self) -> int:
return self.port_cnt return self.ports_cnt
def get_soft_macro_count(self) -> int: def get_soft_macros_count(self) -> int:
return self.soft_macro_cnt return self.soft_macros_cnt
def get_hard_macro_pin_count(self) -> int: def get_hard_macro_pins_count(self) -> int:
return self.hard_macro_pin_cnt return self.hard_macro_pins_cnt
def get_soft_macro_pin_count(self) -> int: def get_soft_macro_pins_count(self) -> int:
return self.soft_macro_pin_cnt return self.soft_macro_pins_cnt
def get_wirelength(self) -> float: def get_wirelength(self) -> float:
""" """
...@@ -734,6 +724,8 @@ class PlacementCost(object): ...@@ -734,6 +724,8 @@ class PlacementCost(object):
""" """
private function for getting grid cell row/col ranging from 0...N private function for getting grid cell row/col ranging from 0...N
""" """
self.grid_width = float(self.width/self.grid_col)
self.grid_height = float(self.height/self.grid_row)
row = math.floor(y_pos / self.grid_height) row = math.floor(y_pos / self.grid_height)
col = math.floor(x_pos / self.grid_width) col = math.floor(x_pos / self.grid_width)
return row, col return row, col
...@@ -847,6 +839,10 @@ class PlacementCost(object): ...@@ -847,6 +839,10 @@ class PlacementCost(object):
""" """
compute average of top 10% of grid cell density and take half of it compute average of top 10% of grid cell density and take half of it
""" """
if self.FLAG_UPDATE_DENSITY:
self.get_grid_cells_density()
self.FLAG_UPDATE_DENSITY=False
occupied_cells = sorted([gc for gc in self.grid_cells if gc != 0.0], reverse=True) occupied_cells = sorted([gc for gc in self.grid_cells if gc != 0.0], reverse=True)
density_cost = 0.0 density_cost = 0.0
...@@ -874,6 +870,11 @@ class PlacementCost(object): ...@@ -874,6 +870,11 @@ class PlacementCost(object):
self.width = width self.width = width
self.height = height self.height = height
# Flag updates
self.FLAG_UPDATE_CONGESTION = True
self.FLAG_UPDATE_DENSITY = True
self.FLAG_UPDATE_MACRO_AND_CLUSTERED_PORT_ADJ = True
self.grid_width = float(self.width/self.grid_col) self.grid_width = float(self.width/self.grid_col)
self.grid_height = float(self.height/self.grid_row) self.grid_height = float(self.height/self.grid_row)
return True return True
...@@ -892,6 +893,11 @@ class PlacementCost(object): ...@@ -892,6 +893,11 @@ class PlacementCost(object):
self.grid_col = grid_col self.grid_col = grid_col
self.grid_row = grid_row self.grid_row = grid_row
# Flag updates
self.FLAG_UPDATE_CONGESTION = True
self.FLAG_UPDATE_DENSITY = True
self.FLAG_UPDATE_MACRO_AND_CLUSTERED_PORT_ADJ = True
self.V_routing_cong = [0] * self.grid_col * self.grid_row self.V_routing_cong = [0] * self.grid_col * self.grid_row
self.H_routing_cong = [0] * self.grid_col * self.grid_row self.H_routing_cong = [0] * self.grid_col * self.grid_row
self.V_macro_routing_cong = [0] * self.grid_col * self.grid_row self.V_macro_routing_cong = [0] * self.grid_col * self.grid_row
...@@ -936,6 +942,9 @@ class PlacementCost(object): ...@@ -936,6 +942,9 @@ class PlacementCost(object):
Set Routes per Micron Set Routes per Micron
""" """
print("#[ROUTES PER MICRON] Hor: %.2f, Ver: %.2f" % (hroutes_per_micron, vroutes_per_micron)) print("#[ROUTES PER MICRON] Hor: %.2f, Ver: %.2f" % (hroutes_per_micron, vroutes_per_micron))
# Flag updates
self.FLAG_UPDATE_CONGESTION = True
self.hroutes_per_micron = hroutes_per_micron self.hroutes_per_micron = hroutes_per_micron
self.vroutes_per_micron = vroutes_per_micron self.vroutes_per_micron = vroutes_per_micron
...@@ -950,6 +959,9 @@ class PlacementCost(object): ...@@ -950,6 +959,9 @@ class PlacementCost(object):
Set congestion smooth range Set congestion smooth range
""" """
print("#[CONGESTION SMOOTH RANGE] Smooth Range: %d" % (smooth_range)) print("#[CONGESTION SMOOTH RANGE] Smooth Range: %d" % (smooth_range))
# Flag updates
self.FLAG_UPDATE_CONGESTION = True
self.smooth_range = math.floor(smooth_range) self.smooth_range = math.floor(smooth_range)
def get_congestion_smooth_range(self) -> float: def get_congestion_smooth_range(self) -> float:
...@@ -971,13 +983,25 @@ class PlacementCost(object): ...@@ -971,13 +983,25 @@ class PlacementCost(object):
""" """
return self.overlap_thres return self.overlap_thres
def set_canvas_boundary_check(self, ifCheck:bool) -> None:
"""
boundary_check: Do a boundary check during node placement.
"""
self.canvas_boundary_check = ifCheck
def get_canvas_boundary_check(self) -> bool: def get_canvas_boundary_check(self) -> bool:
return False """
return canvas_boundary_check
"""
return self.canvas_boundary_check
def set_macro_routing_allocation(self, hrouting_alloc:float, vrouting_alloc:float) -> None: def set_macro_routing_allocation(self, hrouting_alloc:float, vrouting_alloc:float) -> None:
""" """
Set Vertical/Horizontal Macro Allocation Set Vertical/Horizontal Macro Allocation
""" """
# Flag updates
self.FLAG_UPDATE_CONGESTION = True
self.hrouting_alloc = hrouting_alloc self.hrouting_alloc = hrouting_alloc
self.vrouting_alloc = vrouting_alloc self.vrouting_alloc = vrouting_alloc
...@@ -1111,7 +1135,6 @@ class PlacementCost(object): ...@@ -1111,7 +1135,6 @@ class PlacementCost(object):
self.t_routing(temp_gcell, weight) self.t_routing(temp_gcell, weight)
return return
def __macro_route_over_grid_cell(self, mod_x, mod_y, mod_w, mod_h): def __macro_route_over_grid_cell(self, mod_x, mod_y, mod_w, mod_h):
""" """
private function for add module to grid cells private function for add module to grid cells
...@@ -1215,29 +1238,38 @@ class PlacementCost(object): ...@@ -1215,29 +1238,38 @@ class PlacementCost(object):
def get_vertical_routing_congestion(self): def get_vertical_routing_congestion(self):
# TODO: detect if we need to run # TODO: detect if we need to run
self.get_routing() if self.FLAG_UPDATE_CONGESTION:
self.get_routing()
return self.V_routing_cong return self.V_routing_cong
def get_horizontal_routing_congestion(self): def get_horizontal_routing_congestion(self):
# TODO: detect if we need to run # TODO: detect if we need to run
self.get_routing() if self.FLAG_UPDATE_CONGESTION:
self.get_routing()
return self.H_routing_cong return self.H_routing_cong
def get_routing(self): def get_routing(self):
self.grid_width = float(self.width/self.grid_col) """
self.grid_height = float(self.height/self.grid_row) Route between modules
"""
if self.FLAG_UPDATE_CONGESTION:
self.grid_width = float(self.width/self.grid_col)
self.grid_height = float(self.height/self.grid_row)
self.grid_v_routes = self.grid_width * self.vroutes_per_micron
self.grid_h_routes = self.grid_height * self.hroutes_per_micron
self.grid_v_routes = self.grid_width * self.vroutes_per_micron # reset grid
self.grid_h_routes = self.grid_height * self.hroutes_per_micron self.H_routing_cong = [0] * self.grid_row * self.grid_col
self.V_routing_cong = [0] * self.grid_row * self.grid_col
# reset grid self.H_macro_routing_cong = [0] * self.grid_row * self.grid_col
self.H_routing_cong = [0] * self.grid_row * self.grid_col self.V_macro_routing_cong = [0] * self.grid_row * self.grid_col
self.V_routing_cong = [0] * self.grid_row * self.grid_col
self.H_macro_routing_cong = [0] * self.grid_row * self.grid_col self.FLAG_UPDATE_CONGESTION = False
self.V_macro_routing_cong = [0] * self.grid_row * self.grid_col
net_count = 0
for mod in self.modules_w_pins: for mod in self.modules_w_pins:
norm_fact = 1.0 norm_fact = 1.0
curr_type = mod.get_type() curr_type = mod.get_type()
...@@ -1313,8 +1345,7 @@ class PlacementCost(object): ...@@ -1313,8 +1345,7 @@ class PlacementCost(object):
# sum up routing congestion with macro congestion # sum up routing congestion with macro congestion
self.V_routing_cong = [sum(x) for x in zip(self.V_routing_cong, self.V_macro_routing_cong)] self.V_routing_cong = [sum(x) for x in zip(self.V_routing_cong, self.V_macro_routing_cong)]
self.H_routing_cong = [sum(x) for x in zip(self.H_routing_cong, self.H_macro_routing_cong)] self.H_routing_cong = [sum(x) for x in zip(self.H_routing_cong, self.H_macro_routing_cong)]
def __smooth_routing_cong(self): def __smooth_routing_cong(self):
temp_V_routing_cong = [0] * self.grid_col * self.grid_row temp_V_routing_cong = [0] * self.grid_col * self.grid_row
temp_H_routing_cong = [0] * self.grid_col * self.grid_row temp_H_routing_cong = [0] * self.grid_col * self.grid_row
...@@ -1401,9 +1432,14 @@ class PlacementCost(object): ...@@ -1401,9 +1432,14 @@ class PlacementCost(object):
""" """
# NOTE: in pb.txt, netlist input count exceed certain threshold will be ommitted # NOTE: in pb.txt, netlist input count exceed certain threshold will be ommitted
#[MACRO][macro] #[MACRO][macro]
if self.FLAG_UPDATE_MACRO_ADJ:
# do some update
self.FLAG_UPDATE_MACRO_ADJ = False
module_indices = self.hard_macro_indices + self.soft_macro_indices module_indices = self.hard_macro_indices + self.soft_macro_indices
macro_adj = [0] * (self.hard_macro_cnt + self.soft_macro_cnt) * (self.hard_macro_cnt + self.soft_macro_cnt) macro_adj = [0] * (self.hard_macro_cnt + self.soft_macros_cnt) * (self.hard_macro_cnt + self.soft_macros_cnt)
assert len(macro_adj) == (self.hard_macro_cnt + self.soft_macro_cnt) * (self.hard_macro_cnt + self.soft_macro_cnt) assert len(macro_adj) == (self.hard_macro_cnt + self.soft_macros_cnt) * (self.hard_macro_cnt + self.soft_macros_cnt)
for row_idx, module_idx in enumerate(sorted(module_indices)): for row_idx, module_idx in enumerate(sorted(module_indices)):
# row index # row index
...@@ -1426,34 +1462,17 @@ class PlacementCost(object): ...@@ -1426,34 +1462,17 @@ class PlacementCost(object):
if h_module_name in curr_module.get_connection(): if h_module_name in curr_module.get_connection():
entry += curr_module.get_connection()[h_module_name] entry += curr_module.get_connection()[h_module_name]
macro_adj[row_idx * (self.hard_macro_cnt + self.soft_macro_cnt) + col_idx] = entry macro_adj[row_idx * (self.hard_macro_cnt + self.soft_macros_cnt) + col_idx] = entry
macro_adj[col_idx * (self.hard_macro_cnt + self.soft_macro_cnt) + row_idx] = entry macro_adj[col_idx * (self.hard_macro_cnt + self.soft_macros_cnt) + row_idx] = entry
return macro_adj return macro_adj
def is_node_fixed(self):
pass
def optimize_stdcells(self):
pass
def update_node_coords(self):
pass
def fix_node_coord(self):
pass
def update_port_sides(self):
pass
def snap_ports_to_edges(self):
pass
def get_macro_and_clustered_port_adjacency(self): def get_macro_and_clustered_port_adjacency(self):
""" """
Compute Adjacency Matrix (Unclustered PORTs) Compute Adjacency Matrix (Unclustered PORTs)
if module is a PORT, assign nearest cell location even if OOB if module is a PORT, assign it to nearest cell location even if OOB
""" """
#[MACRO][macro] #[MACRO][macro]
module_indices = self.hard_macro_indices + self.soft_macro_indices module_indices = self.hard_macro_indices + self.soft_macro_indices
...@@ -1548,6 +1567,24 @@ class PlacementCost(object): ...@@ -1548,6 +1567,24 @@ class PlacementCost(object):
return macro_adj, sorted(cell_location) return macro_adj, sorted(cell_location)
def is_node_fixed(self):
pass
def optimize_stdcells(self):
pass
def update_node_coords(self):
pass
def fix_node_coord(self):
pass
def update_port_sides(self):
pass
def snap_ports_to_edges(self):
pass
def get_node_location(self, node_idx): def get_node_location(self, node_idx):
pass pass
...@@ -1662,19 +1699,6 @@ class PlacementCost(object): ...@@ -1662,19 +1699,6 @@ class PlacementCost(object):
plt.show() plt.show()
plt.close('all') plt.close('all')
# [TEST FLAG] Internal Util Function For Testing
def __random_swap_placement(self, final_plc, same_block=False):
"""
Swapping HARD MACRO placement from final_plc file.
- swapping between i_icache, tag sram
- swapping between i_icache, data sram
- swapping between i_nbdcache, tag sram
- swapping between i_nbdcache, data sram
"""
pass
# Board Entity Definition # Board Entity Definition
class Port: class Port:
def __init__(self, name, x = 0.0, y = 0.0, side = "BOTTOM"): def __init__(self, name, x = 0.0, y = 0.0, side = "BOTTOM"):
...@@ -2072,13 +2096,13 @@ def main(): ...@@ -2072,13 +2096,13 @@ def main():
print(plc.get_block_name()) print(plc.get_block_name())
print("Area: ", plc.get_area()) print("Area: ", plc.get_area())
print("Wirelength: ", plc.get_wirelength()) print("Wirelength: ", plc.get_wirelength())
print("# HARD_MACROs : %d"%(plc.get_hard_macro_count())) print("# HARD_MACROs : %d"%(plc.get_hard_macros_count()))
print("# HARD_MACRO_PINs : %d"%(plc.get_hard_macro_pin_count())) print("# HARD_MACRO_PINs : %d"%(plc.get_hard_macro_pins_count()))
print("# MACROs : %d"%(plc.get_hard_macro_count() + plc.get_soft_macro_count())) print("# MACROs : %d"%(plc.get_hard_macros_count() + plc.get_soft_macros_count()))
print("# MACRO_PINs : %d"%(plc.get_hard_macro_pin_count() + plc.get_soft_macro_pin_count())) print("# MACRO_PINs : %d"%(plc.get_hard_macro_pins_count() + plc.get_soft_macro_pins_count()))
print("# PORTs : %d"%(plc.get_port_count())) print("# PORTs : %d"%(plc.get_ports_count()))
print("# SOFT_MACROs : %d"%(plc.get_soft_macro_count())) print("# SOFT_MACROs : %d"%(plc.get_soft_macros_count()))
print("# SOFT_MACRO_PINs : %d"%(plc.get_soft_macro_pin_count())) print("# SOFT_MACRO_PINs : %d"%(plc.get_soft_macro_pins_count()))
print("# STDCELLs : 0") print("# STDCELLs : 0")
if __name__ == '__main__': if __name__ == '__main__':
......
import numpy as np
import sys,os,traceback
import argparse
import math
from absl import flags from absl import flags
from absl.flags import argparse_flags
from absl import app from absl import app
from torch import feature_alpha_dropout
from Plc_client import plc_client_os as plc_client_os from Plc_client import plc_client_os as plc_client_os
from Plc_client import plc_client as plc_client try:
import numpy as np from Plc_client import plc_client as plc_client
import sys except ImportError:
import time print("[PLC CLIENT MISSING] Downloading Google's API for testing!")
import math os.system("curl 'https://raw.githubusercontent.com/google-research/circuit_training/main/circuit_training/environment/plc_client.py' > ./Plc_client/plc_client.py")
from Plc_client import plc_client as plc_client
np.set_printoptions(threshold=sys.maxsize) np.set_printoptions(threshold=sys.maxsize)
FLAGS = flags.FLAGS # FLAGS = flags.FLAGS
import argparse
"""plc_client_os_test docstrings """plc_client_os_test docstrings
...@@ -18,7 +22,17 @@ Test Utility Class for Google's API plc_wrapper_main with plc_client.py and plc_ ...@@ -18,7 +22,17 @@ Test Utility Class for Google's API plc_wrapper_main with plc_client.py and plc_
Example: Example:
At ./MacroPlacement/CodeElement, run the following command: At ./MacroPlacement/CodeElement, run the following command:
$ python -m Plc_client.plc_client_os_test [NETLIST_PATH] [PLC_PATH] $ python3 -m Plc_client.plc_client_os_test --netlist ./Plc_client/test/ariane/netlist.pb.txt\
--plc ./Plc_client/test/ariane/initial.plc\
--width 356.592\
--height 356.640\
--col 35\
--row 33\
--rpmh 10\
--rpmv 10\
--marh 5\
--marv 5\
--smooth 2
Todo: Todo:
* Clean up code * Clean up code
...@@ -29,45 +43,244 @@ Todo: ...@@ -29,45 +43,244 @@ Todo:
class PlacementCostTest(): class PlacementCostTest():
# Google's Ariane """ Canvas Setting Reference Table
CANVAS_WIDTH = 356.592 ++ Google's Ariane ++
CANVAS_HEIGHT = 356.640 - CANVAS_WIDTH = 356.592
GRID_COL = 35 - CANVAS_HEIGHT = 356.640
GRID_ROW = 33 - GRID_COL = 35
- GRID_ROW = 33
# Ariane133
# CANVAS_WIDTH = 1599.99 ++ Ariane133 ++
# CANVAS_HEIGHT = 1600.06 - CANVAS_WIDTH = 1599.99
# GRID_COL = 24 - CANVAS_HEIGHT = 1600.06
# GRID_ROW = 21 - GRID_COL = 24
- GRID_ROW = 21
# Sample clustered
# CANVAS_WIDTH = 400 ++ Sample clustered ++
# CANVAS_HEIGHT = 400 - CANVAS_WIDTH = 400
# GRID_COL = 4 - CANVAS_HEIGHT = 400
# GRID_ROW = 4 - GRID_COL = 4
- GRID_ROW = 4
# PMm
# CANVAS_WIDTH = 100 ++ PMm ++
# CANVAS_HEIGHT = 100 - CANVAS_WIDTH = 100
# GRID_COL = 5 - CANVAS_HEIGHT = 100
# GRID_ROW = 5 - GRID_COL = 5
- GRID_ROW = 5
def __init__(self, NETLIST_PATH, PLC_PATH=None) -> None: """
def __init__(self, NETLIST_PATH, PLC_PATH=None,
width=0, height=0,
column=0, row=0, rpmv=10, rpmh=10,
marh=10, marv=10, smooth=1) -> None:
self.NETLIST_PATH = NETLIST_PATH self.NETLIST_PATH = NETLIST_PATH
if PLC_PATH: self.PLC_PATH = PLC_PATH
self.PLC_PATH = PLC_PATH self.CANVAS_WIDTH = width
self.CANVAS_HEIGHT = height
self.GRID_COL = column
self.GRID_ROW = row
# for congestion computation
self.RPMV = rpmv
self.RPMH = rpmh
self.MARH = marh
self.MARV = marv
self.SMOOTH = smooth
def test_input(self):
def test_metadata(self):
print("############################ TEST METADATA ############################")
# Google's Binary Executable
self.plc = plc_client.PlacementCost(self.NETLIST_PATH) 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)
# NOTE: must set canvas before restoring placement, otherwise OOB error
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)
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")
try:
assert int(self.plc_os.get_area()) == int(self.plc.get_area())
self.plc.set_routes_per_micron(1.0, 2.0)
self.plc_os.set_routes_per_micron(1.0, 2.0)
assert self.plc.get_routes_per_micron() == self.plc_os.get_routes_per_micron()
self.plc.set_overlap_threshold(2.0)
self.plc_os.set_overlap_threshold(2.0)
assert self.plc.get_overlap_threshold() == self.plc_os.get_overlap_threshold()
self.plc.set_congestion_smooth_range(2.0)
self.plc_os.set_congestion_smooth_range(2.0)
assert self.plc.get_congestion_smooth_range() == self.plc_os.get_congestion_smooth_range()
self.plc.set_macro_routing_allocation(3.0, 4.0)
self.plc_os.set_macro_routing_allocation(3.0, 4.0)
assert self.plc.get_macro_routing_allocation() == self.plc_os.get_macro_routing_allocation()
except Exception as e:
_, _, tb = sys.exc_info()
traceback.print_tb(tb)
tb_info = traceback.extract_tb(tb)
_, line, _, text = tb_info[-1]
print('[METADATA ERROR] at line {} in statement {}'\
.format(line, text))
exit(1)
# test get_macro_adjacency
plc_macroadj = self.plc.get_macro_adjacency()
plc_macroadj = np.array(plc_macroadj).reshape(int(math.sqrt(len(plc_macroadj))),\
int(math.sqrt(len(plc_macroadj))))
plcos_macroadj = self.plc_os.get_macro_adjacency()
plcos_macroadj = np.array(plcos_macroadj).reshape(int(math.sqrt(len(plcos_macroadj))),\
int(math.sqrt(len(plcos_macroadj))))
try:
assert(np.sum(np.nonzero(plc_macroadj - plcos_macroadj)) == 0)
except Exception as e:
print("[MACRO ADJ ERROR] Mismatched found -- {}".format(str(e)))
exit(1)
# test get_macro_and_clustered_port_adjacency
plc_clusteradj, plc_cell = self.plc.get_macro_and_clustered_port_adjacency()
plc_clusteradj = np.array(plc_clusteradj).reshape(int(math.sqrt(len(plc_clusteradj))),\
int(math.sqrt(len(plc_clusteradj))))
plcos_clusteradj, plcos_cell = self.plc_os.get_macro_and_clustered_port_adjacency()
plcos_clusteradj = np.array(plcos_clusteradj).reshape(int(math.sqrt(len(plcos_clusteradj))),\
int(math.sqrt(len(plcos_clusteradj))))
try:
for plc_adj, plcos_adj in zip(plc_clusteradj, plcos_clusteradj):
assert(np.sum(np.nonzero(plc_adj - plcos_adj)) == 0)
except Exception as e:
print("[MACRO AND CLUSTERED PORT ADJ ERROR] Mismatched found -- {}".format(str(e)))
exit(1)
print(" +++++++++++++++++++++++++++")
print(" +++ TEST METADATA: PASS +++")
print(" +++++++++++++++++++++++++++")
def view_canvas(self):
print("############################ VIEW CANVAS ############################")
self.plc_os = plc_client_os.PlacementCost(netlist_file=self.NETLIST_PATH,
macro_macro_x_spacing = 50,
macro_macro_y_spacing = 50)
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)
# show canvas
self.plc_os.display_canvas()
def test_proxy_cost(self):
print("############################ TEST PROXY COST ############################")
# 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, self.plc_os = plc_client_os.PlacementCost(netlist_file=self.NETLIST_PATH,
macro_macro_x_spacing = 50, macro_macro_x_spacing = 50,
macro_macro_y_spacing = 50) macro_macro_y_spacing = 50)
if self.PLC_PATH: 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, self.plc_os.restore_placement(self.PLC_PATH,
ifInital=True, ifValidate=True) 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-3
except Exception as e:
print("[WIRELENGTH ERROR] Discrepancies found when computing wirelength -- {}".format(str(e)))
exit(1)
# 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())
except Exception as e:
print("[DENSITY ERROR] Discrepancies found when computing density -- {}".format(str(e)))
exit(1)
# Congestion
try:
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
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)))
exit(1)
print(" +++++++++++++++++++++++++++++")
print(" +++ TEST PROXY COST: PASS +++")
print(" +++++++++++++++++++++++++++++")
def test_miscellaneous(self):
# Google's Binary Executable
self.plc = plc_client.PlacementCost(self.NETLIST_PATH)
self.plc_os = plc_client_os.PlacementCost(netlist_file=self.NETLIST_PATH,
macro_macro_x_spacing = 50,
macro_macro_y_spacing = 50)
print("****************** miscellaneous ******************")
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)
NODE_IDX = 0
print("get_macro_indices", self.plc.get_macro_indices(), self.plc_os.get_macro_indices())
print("get_node_name", self.plc.get_node_name(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("***************************************************")
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)
...@@ -77,9 +290,6 @@ class PlacementCostTest(): ...@@ -77,9 +290,6 @@ class PlacementCostTest():
self.plc.set_routes_per_micron(10, 10) self.plc.set_routes_per_micron(10, 10)
self.plc_os.set_routes_per_micron(10, 10) self.plc_os.set_routes_per_micron(10, 10)
# self.plc.set_macro_routing_allocation(5, 5)
# self.plc_os.set_macro_routing_allocation(5, 5)
self.plc.set_macro_routing_allocation(10, 10) self.plc.set_macro_routing_allocation(10, 10)
self.plc_os.set_macro_routing_allocation(10, 10) self.plc_os.set_macro_routing_allocation(10, 10)
...@@ -91,11 +301,7 @@ class PlacementCostTest(): ...@@ -91,11 +301,7 @@ 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)
print("Name: ", self.plc.get_source_filename().rsplit("/", 1)[1])
# self.plc_os.display_canvas(amplify=True)
# start = time.time()
temp_gl_h = np.array(self.plc.get_horizontal_routing_congestion()) temp_gl_h = np.array(self.plc.get_horizontal_routing_congestion())
temp_os_h = np.array(self.plc_os.get_horizontal_routing_congestion()) temp_os_h = np.array(self.plc_os.get_horizontal_routing_congestion())
print(temp_gl_h.reshape(self.GRID_COL, self.GRID_ROW)) print(temp_gl_h.reshape(self.GRID_COL, self.GRID_ROW))
...@@ -147,159 +353,44 @@ class PlacementCostTest(): ...@@ -147,159 +353,44 @@ class PlacementCostTest():
####################################################################### BY ENTRY ####################################################################### BY ENTRY
print("**************BY ENTRY DIFF") print("**************BY ENTRY DIFF")
print(temp_gl_h_mc[0][6], temp_os_h_mc[0][6]) print(temp_gl_h_mc[0][6], temp_os_h_mc[0][6])
# print(temp_gl_v_mc[1][6], temp_os_v_mc[1][6])
###################################################################### def parse_flags(argv):
# end = time.time() parser = argparse_flags.ArgumentParser(description='An argparse + app.run example')
# print("time elapsed:", end - start) parser.add_argument("--netlist", required=True,
help="Path to netlist in pb.txt")
# for idx in range(len(temp_gl_h)): parser.add_argument("--plc", required=False,
# print("gl, os:", temp_gl_h[idx], temp_os_h[idx], temp_gl_v[idx], temp_os_v[idx]) help="Path to plc in .plc")
parser.add_argument("--width", type=float, required=True,
# print("congestion summation gl os", sum(temp_gl_h), sum(temp_os_h), sum(temp_gl_v), sum(temp_os_v)) help="Canvas width")
parser.add_argument("--height", type=float, required=True,
def view_canvas(self): help="Canvas height")
self.plc_os = plc_client_os.PlacementCost(netlist_file=self.NETLIST_PATH, parser.add_argument("--col", type=int, required=True,
macro_macro_x_spacing = 50, help="Grid column")
macro_macro_y_spacing = 50) parser.add_argument("--row", type=int, required=True,
self.plc.set_canvas_size(self.CANVAS_WIDTH, self.CANVAS_HEIGHT) help="Grid row")
self.plc.set_placement_grid(self.GRID_COL, self.GRID_ROW) parser.add_argument("--rpmh", type=float, default=10, required=False,
self.plc_os.set_canvas_size(self.CANVAS_WIDTH, self.CANVAS_HEIGHT) help="Grid row")
self.plc_os.set_placement_grid(self.GRID_COL, self.GRID_ROW) parser.add_argument("--rpmv", type=float, default=10, required=False,
# show canvas help="Grid row")
self.plc_os.display_canvas() parser.add_argument("--marh", type=float, default=10, required=False,
help="Grid row")
parser.add_argument("--marv", type=float, default=10, required=False,
def test_proxy_cost(self): help="Grid row")
# Google's Binary Executable parser.add_argument("--smooth", type=float, default=1, required=False,
self.plc = plc_client.PlacementCost(self.NETLIST_PATH) help="Grid row")
return parser.parse_args(argv[1:])
# Open-sourced Implementation
self.plc_os = plc_client_os.PlacementCost(netlist_file=self.NETLIST_PATH, def main(args):
macro_macro_x_spacing = 50, if args.plc:
macro_macro_y_spacing = 50) PCT = PlacementCostTest(args.netlist, args.plc, args.width, args.height,
args.col, args.row, args.rpmv, args.rpmv,
print("************ SETTING UP CANVAS ************") args.marh, args.marv, args.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)
print(self.plc_os.get_wirelength(), self.plc.get_wirelength())
assert int(self.plc_os.get_wirelength()) == int(self.plc.get_wirelength())
print("os wl cost", self.plc_os.get_cost())
print("gl wl cost", self.plc.get_cost())
assert abs(self.plc.get_cost() - self.plc_os.get_cost()) <= 10e-3
print("gl density\n", np.array(self.plc.get_grid_cells_density()).reshape(self.GRID_COL, self.GRID_ROW))
print("os density\n", np.array(self.plc_os.get_grid_cells_density()).reshape(self.GRID_COL, self.GRID_ROW))
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("os density cost", self.plc_os.get_density_cost())
print("gl density cost", self.plc.get_density_cost())
def test_metadata(self):
# 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.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_os.get_grid_cells_density()
assert int(self.plc_os.get_area()) == int(self.plc.get_area())
self.plc.set_routes_per_micron(1.0, 2.0)
self.plc_os.set_routes_per_micron(1.0, 2.0)
assert self.plc.get_routes_per_micron() == self.plc_os.get_routes_per_micron()
self.plc.set_overlap_threshold(2.0)
self.plc_os.set_overlap_threshold(2.0)
assert self.plc.get_overlap_threshold() == self.plc_os.get_overlap_threshold()
self.plc.set_congestion_smooth_range(2.0)
self.plc_os.set_congestion_smooth_range(2.0)
assert self.plc.get_congestion_smooth_range() == self.plc_os.get_congestion_smooth_range()
self.plc.set_macro_routing_allocation(3.0, 4.0)
self.plc_os.set_macro_routing_allocation(3.0, 4.0)
assert self.plc.get_macro_routing_allocation() == self.plc_os.get_macro_routing_allocation()
# test get_macro_adjacency
plc_macroadj = self.plc.get_macro_adjacency()
plc_macroadj = np.array(plc_macroadj).reshape(int(math.sqrt(len(plc_macroadj))),\
int(math.sqrt(len(plc_macroadj))))
plcos_macroadj = self.plc_os.get_macro_adjacency()
plcos_macroadj = np.array(plcos_macroadj).reshape(int(math.sqrt(len(plcos_macroadj))),\
int(math.sqrt(len(plcos_macroadj))))
assert(np.sum(np.nonzero(plc_macroadj - plcos_macroadj)) == 0)
# test get_macro_and_clustered_port_adjacency
plc_clusteradj, plc_cell = self.plc.get_macro_and_clustered_port_adjacency()
plc_clusteradj = np.array(plc_clusteradj).reshape(int(math.sqrt(len(plc_clusteradj))),\
int(math.sqrt(len(plc_clusteradj))))
plcos_clusteradj, plcos_cell = self.plc_os.get_macro_and_clustered_port_adjacency()
plcos_clusteradj = np.array(plcos_clusteradj).reshape(int(math.sqrt(len(plcos_clusteradj))),\
int(math.sqrt(len(plcos_clusteradj))))
assert(plc_cell == plcos_cell)
for plc_adj, plcos_adj in zip(plc_clusteradj, plcos_clusteradj):
assert(np.sum(np.nonzero(plc_adj - plcos_adj)) == 0)
def test_miscellaneous(self):
# Google's Binary Executable
self.plc = plc_client.PlacementCost(self.NETLIST_PATH)
self.plc_os = plc_client_os.PlacementCost(netlist_file=self.NETLIST_PATH,
macro_macro_x_spacing = 50,
macro_macro_y_spacing = 50)
print("****************** miscellaneous ******************")
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)
NODE_IDX = 0
print("get_macro_indices", self.plc.get_macro_indices(), self.plc_os.get_macro_indices())
print("get_node_name", self.plc.get_node_name(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("***************************************************")
def main(argv):
args = sys.argv[1:]
if len(args) > 1:
# netlist+plc file
PCT = PlacementCostTest(args[0], args[1])
else: else:
# netlist PCT = PlacementCostTest(args.netlist, args.width, args.height,
PCT = PlacementCostTest(args[0]) args.col, args.row, args.rpmv, args.rpmv,
args.marh, args.marv, args.smooth)
PCT.test_input() PCT.test_metadata()
# PCT.test_proxy_congestion() PCT.test_proxy_cost()
# PCT.test_proxy_cost()
# PCT.test_metadata() if __name__ == '__main__':
# PCT.test_miscellaneous() app.run(main, flags_parser=parse_flags)
\ No newline at end of file
if __name__ == "__main__":
app.run(main)
\ 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