Commit c612bdbc by Dinple

Overhaul WIP + redo testbench

parent 3dfa0aa5
......@@ -2,4 +2,8 @@ Flows/*/*/run/*/
Flows/*/*/run-*
Flows/job
CodeElements/*/*/__pycache__
CodeElements/Plc_client/test/*
\ No newline at end of file
CodeElements/Plc_client/test/
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
sudo curl https://storage.googleapis.com/rl-infra-public/circuit-training/placement_cost/plc_wrapper_main \
-o /usr/local/bin/plc_wrapper_main
# 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
......@@ -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)]
$$
## Density Cost Computation
## Density Cost Computation
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.
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.
......
......@@ -41,10 +41,12 @@ class PlacementCost(object):
self.macro_macro_x_spacing = macro_macro_x_spacing
self.macro_macro_y_spacing = macro_macro_y_spacing
# Update cost computation flags
# Update flags
self.FLAG_UPDATE_WIRELENGTH = True
self.FLAG_UPDATE_DENSITY = True
self.FLAG_UPDATE_CONGESTION = True
self.FLAG_UPDATE_MACRO_ADJ = True
self.FLAG_UPDATE_MACRO_AND_CLUSTERED_PORT_ADJ = True
# Check netlist existance
assert os.path.isfile(self.netlist_file)
......@@ -59,9 +61,9 @@ class PlacementCost(object):
self.overlap_thres = 0.0
self.hrouting_alloc = 0.0
self.vrouting_alloc = 0.0
self.macro_horizontal_routing_allocation = 0.0
self.macro_vertical_routing_allocation = 0.0
self.canvas_boundary_check = True
# net information
self.net_cnt = 0
......@@ -99,16 +101,16 @@ class PlacementCost(object):
# initial grid mask
self.global_node_mask = [0] * self.grid_col * self.grid_row
# 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_pin_cnt = len(self.hard_macro_pin_indices)
self.soft_macro_cnt = len(self.soft_macro_indices)
self.soft_macro_pin_cnt = len(self.soft_macro_pin_indices)
self.module_cnt = self.hard_macro_cnt + self.soft_macro_cnt + self.port_cnt
self.hard_macro_pins_cnt = len(self.hard_macro_pin_indices)
self.soft_macros_cnt = len(self.soft_macro_indices)
self.soft_macro_pins_cnt = len(self.soft_macro_pin_indices)
self.module_cnt = self.hard_macro_cnt + self.soft_macros_cnt + self.ports_cnt
# assert module and pin count are correct
assert (len(self.modules)) == self.module_cnt
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
def __peek(self, f:io.TextIOWrapper):
......@@ -206,12 +208,12 @@ class PlacementCost(object):
try:
assert 'x' in attr_dict.keys()
except AssertionError:
logging.warning('x is not defined')
logging.warning('[NETLIST PARSER ERROR] x is not defined')
try:
assert 'y' in attr_dict.keys()
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],
height = attr_dict['height'][1],
......@@ -375,15 +377,15 @@ class PlacementCost(object):
# skip empty lines
if len(line_item) == 0:
continue
# # skip comments
# if re.search(r"\S", line)[0] == '#':
# continue
if 'Columns' in line_item and 'Rows' in line_item:
# Columns and Rows should be defined on the same one-line
_columns = int(line_item[1])
_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:
# Total core area of modules
_area = float(line_item[1])
......@@ -428,7 +430,7 @@ class PlacementCost(object):
and len(line_item) == 2:
_macros_cnt = int(line_item[1])
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:]
# return as dictionary
......@@ -457,11 +459,15 @@ class PlacementCost(object):
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
NOTE: DO NOT always set self.init_plc because
this function is also used to read final placement file
NOTE: DO NOT always set self.init_plc because this function is also
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 ifInital:
......@@ -474,10 +480,10 @@ class PlacementCost(object):
if ifValidate:
try:
assert(self.hard_macro_cnt == info_dict['hard_macros_cnt'])
assert(self.hard_macro_pin_cnt == info_dict['hard_macro_pins_cnt'])
assert(self.soft_macro_cnt == info_dict['soft_macros_cnt'])
assert(self.soft_macro_pin_cnt == info_dict['soft_macro_pins_cnt'])
assert(self.port_cnt == info_dict['ports_cnt'])
assert(self.hard_macro_pins_cnt == info_dict['hard_macro_pins_cnt'])
assert(self.soft_macros_cnt == info_dict['soft_macros_cnt'])
assert(self.soft_macro_pins_cnt == info_dict['soft_macro_pins_cnt'])
assert(self.ports_cnt == info_dict['ports_cnt'])
except AssertionError:
_, _, tb = sys.exc_info()
traceback.print_tb(tb)
......@@ -506,6 +512,8 @@ class PlacementCost(object):
except Exception as 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)
if mod_orient and mod_orient != '-':
......@@ -517,16 +525,20 @@ class PlacementCost(object):
self.modules_w_pins[mod_idx].set_fix_flag(True)
# set meta information
self.set_canvas_size(info_dict['width'], info_dict['height'])
self.set_placement_grid(info_dict['columns'], info_dict['rows'])
self.set_block_name(info_dict['block'])
self.set_routes_per_micron(info_dict['routes_per_micron_hor'],\
info_dict['routes_per_micron_ver'])
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'])
if ifReadComment:
self.set_canvas_size(info_dict['width'], info_dict['height'])
self.set_placement_grid(info_dict['columns'], info_dict['rows'])
self.set_block_name(info_dict['block'])
self.set_routes_per_micron(
info_dict['routes_per_micron_hor'],
info_dict['routes_per_micron_ver']
)
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):
"""
......@@ -558,34 +570,12 @@ class PlacementCost(object):
weight = pin.get_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:
"""
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]\
+ self.get_canvas_width_height()[1]) * self.net_cnt)
......@@ -599,20 +589,20 @@ class PlacementCost(object):
total_area += mod.get_area()
return total_area
def get_hard_macro_count(self) -> int:
def get_hard_macros_count(self) -> int:
return self.hard_macro_cnt
def get_port_count(self) -> int:
return self.port_cnt
def get_ports_count(self) -> int:
return self.ports_cnt
def get_soft_macro_count(self) -> int:
return self.soft_macro_cnt
def get_soft_macros_count(self) -> int:
return self.soft_macros_cnt
def get_hard_macro_pin_count(self) -> int:
return self.hard_macro_pin_cnt
def get_hard_macro_pins_count(self) -> int:
return self.hard_macro_pins_cnt
def get_soft_macro_pin_count(self) -> int:
return self.soft_macro_pin_cnt
def get_soft_macro_pins_count(self) -> int:
return self.soft_macro_pins_cnt
def get_wirelength(self) -> float:
"""
......@@ -734,6 +724,8 @@ class PlacementCost(object):
"""
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)
col = math.floor(x_pos / self.grid_width)
return row, col
......@@ -847,6 +839,10 @@ class PlacementCost(object):
"""
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)
density_cost = 0.0
......@@ -874,6 +870,11 @@ class PlacementCost(object):
self.width = width
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_height = float(self.height/self.grid_row)
return True
......@@ -892,6 +893,11 @@ class PlacementCost(object):
self.grid_col = grid_col
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.H_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):
Set Routes 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.vroutes_per_micron = vroutes_per_micron
......@@ -950,6 +959,9 @@ class PlacementCost(object):
Set congestion 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)
def get_congestion_smooth_range(self) -> float:
......@@ -971,13 +983,25 @@ class PlacementCost(object):
"""
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:
return False
"""
return canvas_boundary_check
"""
return self.canvas_boundary_check
def set_macro_routing_allocation(self, hrouting_alloc:float, vrouting_alloc:float) -> None:
"""
Set Vertical/Horizontal Macro Allocation
"""
# Flag updates
self.FLAG_UPDATE_CONGESTION = True
self.hrouting_alloc = hrouting_alloc
self.vrouting_alloc = vrouting_alloc
......@@ -1111,7 +1135,6 @@ class PlacementCost(object):
self.t_routing(temp_gcell, weight)
return
def __macro_route_over_grid_cell(self, mod_x, mod_y, mod_w, mod_h):
"""
private function for add module to grid cells
......@@ -1215,29 +1238,38 @@ class PlacementCost(object):
def get_vertical_routing_congestion(self):
# TODO: detect if we need to run
self.get_routing()
if self.FLAG_UPDATE_CONGESTION:
self.get_routing()
return self.V_routing_cong
def get_horizontal_routing_congestion(self):
# TODO: detect if we need to run
self.get_routing()
if self.FLAG_UPDATE_CONGESTION:
self.get_routing()
return self.H_routing_cong
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
self.grid_h_routes = self.grid_height * self.hroutes_per_micron
# reset grid
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_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.V_macro_routing_cong = [0] * self.grid_row * self.grid_col
self.H_macro_routing_cong = [0] * self.grid_row * self.grid_col
self.V_macro_routing_cong = [0] * self.grid_row * self.grid_col
self.FLAG_UPDATE_CONGESTION = False
net_count = 0
for mod in self.modules_w_pins:
norm_fact = 1.0
curr_type = mod.get_type()
......@@ -1313,8 +1345,7 @@ class PlacementCost(object):
# 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.H_routing_cong = [sum(x) for x in zip(self.H_routing_cong, self.H_macro_routing_cong)]
def __smooth_routing_cong(self):
temp_V_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):
"""
# NOTE: in pb.txt, netlist input count exceed certain threshold will be ommitted
#[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
macro_adj = [0] * (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_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_macros_cnt) * (self.hard_macro_cnt + self.soft_macros_cnt)
for row_idx, module_idx in enumerate(sorted(module_indices)):
# row index
......@@ -1426,34 +1462,17 @@ class PlacementCost(object):
if h_module_name in curr_module.get_connection():
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[col_idx * (self.hard_macro_cnt + self.soft_macro_cnt) + row_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_macros_cnt) + row_idx] = entry
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):
"""
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]
module_indices = self.hard_macro_indices + self.soft_macro_indices
......@@ -1548,6 +1567,24 @@ class PlacementCost(object):
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):
pass
......@@ -1662,19 +1699,6 @@ class PlacementCost(object):
plt.show()
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
class Port:
def __init__(self, name, x = 0.0, y = 0.0, side = "BOTTOM"):
......@@ -2072,13 +2096,13 @@ def main():
print(plc.get_block_name())
print("Area: ", plc.get_area())
print("Wirelength: ", plc.get_wirelength())
print("# HARD_MACROs : %d"%(plc.get_hard_macro_count()))
print("# HARD_MACRO_PINs : %d"%(plc.get_hard_macro_pin_count()))
print("# MACROs : %d"%(plc.get_hard_macro_count() + plc.get_soft_macro_count()))
print("# MACRO_PINs : %d"%(plc.get_hard_macro_pin_count() + plc.get_soft_macro_pin_count()))
print("# PORTs : %d"%(plc.get_port_count()))
print("# SOFT_MACROs : %d"%(plc.get_soft_macro_count()))
print("# SOFT_MACRO_PINs : %d"%(plc.get_soft_macro_pin_count()))
print("# HARD_MACROs : %d"%(plc.get_hard_macros_count()))
print("# HARD_MACRO_PINs : %d"%(plc.get_hard_macro_pins_count()))
print("# MACROs : %d"%(plc.get_hard_macros_count() + plc.get_soft_macros_count()))
print("# MACRO_PINs : %d"%(plc.get_hard_macro_pins_count() + plc.get_soft_macro_pins_count()))
print("# PORTs : %d"%(plc.get_ports_count()))
print("# SOFT_MACROs : %d"%(plc.get_soft_macros_count()))
print("# SOFT_MACRO_PINs : %d"%(plc.get_soft_macro_pins_count()))
print("# STDCELLs : 0")
if __name__ == '__main__':
......
import numpy as np
import sys,os,traceback
import argparse
import math
from absl import flags
from absl.flags import argparse_flags
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 as plc_client
import numpy as np
import sys
import time
import math
try:
from Plc_client import plc_client as plc_client
except ImportError:
print("[PLC CLIENT MISSING] Downloading Google's API for testing!")
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)
FLAGS = flags.FLAGS
import argparse
# FLAGS = flags.FLAGS
"""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_
Example:
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:
* Clean up code
......@@ -29,45 +43,244 @@ Todo:
class PlacementCostTest():
# Google's Ariane
CANVAS_WIDTH = 356.592
CANVAS_HEIGHT = 356.640
GRID_COL = 35
GRID_ROW = 33
# Ariane133
# CANVAS_WIDTH = 1599.99
# CANVAS_HEIGHT = 1600.06
# GRID_COL = 24
# GRID_ROW = 21
# Sample clustered
# CANVAS_WIDTH = 400
# CANVAS_HEIGHT = 400
# GRID_COL = 4
# GRID_ROW = 4
# PMm
# CANVAS_WIDTH = 100
# CANVAS_HEIGHT = 100
# GRID_COL = 5
# GRID_ROW = 5
def __init__(self, NETLIST_PATH, PLC_PATH=None) -> None:
""" Canvas Setting Reference Table
++ Google's Ariane ++
- CANVAS_WIDTH = 356.592
- CANVAS_HEIGHT = 356.640
- GRID_COL = 35
- GRID_ROW = 33
++ Ariane133 ++
- CANVAS_WIDTH = 1599.99
- CANVAS_HEIGHT = 1600.06
- GRID_COL = 24
- GRID_ROW = 21
++ Sample clustered ++
- CANVAS_WIDTH = 400
- CANVAS_HEIGHT = 400
- GRID_COL = 4
- GRID_ROW = 4
++ PMm ++
- CANVAS_WIDTH = 100
- CANVAS_HEIGHT = 100
- GRID_COL = 5
- GRID_ROW = 5
"""
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
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)
# 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,
macro_macro_x_spacing = 50,
macro_macro_y_spacing = 50)
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)
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):
# Google's API
self.plc = plc_client.PlacementCost(self.NETLIST_PATH)
......@@ -77,9 +290,6 @@ class PlacementCostTest():
self.plc.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_os.set_macro_routing_allocation(10, 10)
......@@ -91,11 +301,7 @@ class PlacementCostTest():
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("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_os_h = np.array(self.plc_os.get_horizontal_routing_congestion())
print(temp_gl_h.reshape(self.GRID_COL, self.GRID_ROW))
......@@ -147,159 +353,44 @@ class PlacementCostTest():
####################################################################### BY ENTRY
print("**************BY ENTRY DIFF")
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])
######################################################################
# end = time.time()
# print("time elapsed:", end - start)
# for idx in range(len(temp_gl_h)):
# print("gl, os:", temp_gl_h[idx], temp_os_h[idx], temp_gl_v[idx], temp_os_v[idx])
# print("congestion summation gl os", sum(temp_gl_h), sum(temp_os_h), sum(temp_gl_v), sum(temp_os_v))
def view_canvas(self):
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):
# 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)
print("************ SETTING UP CANVAS ************")
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])
def parse_flags(argv):
parser = argparse_flags.ArgumentParser(description='An argparse + app.run example')
parser.add_argument("--netlist", required=True,
help="Path to netlist in pb.txt")
parser.add_argument("--plc", required=False,
help="Path to plc in .plc")
parser.add_argument("--width", type=float, required=True,
help="Canvas width")
parser.add_argument("--height", type=float, required=True,
help="Canvas height")
parser.add_argument("--col", type=int, required=True,
help="Grid column")
parser.add_argument("--row", type=int, required=True,
help="Grid row")
parser.add_argument("--rpmh", type=float, default=10, required=False,
help="Grid row")
parser.add_argument("--rpmv", type=float, default=10, required=False,
help="Grid row")
parser.add_argument("--marh", type=float, default=10, required=False,
help="Grid row")
parser.add_argument("--marv", type=float, default=10, required=False,
help="Grid row")
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)
else:
# netlist
PCT = PlacementCostTest(args[0])
PCT.test_input()
# PCT.test_proxy_congestion()
# PCT.test_proxy_cost()
# PCT.test_metadata()
# PCT.test_miscellaneous()
if __name__ == "__main__":
app.run(main)
\ No newline at end of file
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.test_proxy_cost()
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