Commit 91c4afa6 by Dinple

restore placement WIP

parent fc82171e
......@@ -9,6 +9,22 @@ from collections import namedtuple
import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle
import numpy as np
from optax import smooth_labels
"""plc_client_os docstrings.
Open-sourced effort for plc_client and Google's API, plc_wrapper_main. This module
is used to initialize a PlacementCost object that computes the meta-information and
proxy cost function for RL agent's reward signal at the end of each placement.
Example:
For testing, please refer to plc_client_os_test.py for more information.
Todo:
* Add Documentation
* Clean up
"""
Block = namedtuple('Block', 'x_max y_max x_min y_min')
......@@ -317,30 +333,151 @@ class PlacementCost(object):
# mapping connection degree to each macros
self.__update_connection()
def __read_plc(self):
def __read_plc(self, plc_pth: str):
"""
Plc file Parser
"""
with open(self.init_plc) as fp:
line = fp.readline()
while line:
# skip comments
if re.search(r"\S", line)[0] == '#':
# IMPORTANT: Advance pt
line = fp.readline()
continue
# words itemize into list
# meta information
_columns = 0
_rows = 0
_width = 0.0
_height = 0.0
_area = 0.0
_block = None
_routes_per_micron_hor = 0.0
_routes_per_micron_ver = 0.0
_routes_used_by_macros_hor = 0.0
_routes_used_by_macros_ver = 0.0
_smoothing_factor = 0
_overlap_threshold = 0.0
# node information
_hard_macros_cnt = 0
_hard_macro_pins_cnt = 0
_macro_cnt = 0
_macro_pin_cnt = 0
_port_cnt = 0
_soft_macros_cnt = 0
_soft_macro_pins_cnt = 0
_stdcells_cnt = 0
# node placement
_node_plc = {}
for cnt, line in enumerate(open(plc_pth, 'r')):
line_item = re.findall(r'[0-9A-Za-z\.\-]+', line)
# skip empty lines
if len(line_item) == 0:
# IMPORTANT: Advance pt
line = fp.readline()
continue
line = fp.readline()
# # 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
print("HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH")
_columns = int(line_item[1])
_rows = int(line_item[3])
elif "Area" in line_item:
print("WTFFFFFFFFFf")
# Total core area of modules
_area = float(line_item[1])
elif "Block" in line_item:
# The block name of the testcase
_block = str(line_item[1])
elif all(it in line_item for it in\
['Routes', 'per', 'micron', 'hor', 'ver']):
print("HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH")
# For routing congestion computation
_routes_per_micron_hor = float(line_item[4])
_routes_per_micron_ver = float(line_item[6])
elif all(it in line_item for it in\
['Routes', 'used', 'by', 'macros', 'hor', 'ver']):
# For MACRO congestion computation
_routes_used_by_macros_hor = float(line_item[5])
_routes_used_by_macros_ver = float(line_item[7])
elif all(it in line_item for it in ['Smoothing', 'factor']):
# smoothing factor for routing congestion
_smoothing_factor = int(line_item[2])
elif all(it in line_item for it in ['Overlap', 'threshold']):
# overlap
_overlap_threshold = float(line_item[2])
elif all(it in line_item for it in ['HARD', 'MACROs'])\
and len(line_item) == 3:
_hard_macros_cnt = int(line_item[2])
elif all(it in line_item for it in ['HARD', 'MACRO', 'PINs'])\
and len(line_item) == 4:
_hard_macro_pins_cnt = int(line_item[3])
elif all(it in line_item for it in ['PORTs'])\
and len(line_item) == 2:
_port_cnt = int(line_item[1])
elif all(it in line_item for it in ['SOFT', 'MACROs'])\
and len(line_item) == 3:
_soft_macros_cnt = int(line_item[2])
elif all(it in line_item for it in ['SOFT', 'MACRO', 'PINs'])\
and len(line_item) == 4:
_soft_macros_pin_cnt = int(line_item[3])
elif all(it in line_item for it in ['STDCELLs'])\
and len(line_item) == 2:
_stdcells_cnt = int(line_item[1])
elif all(it in line_item for it in ['MACROs'])\
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_plc[int(line_item[0])] = line_item[1:]
# return as dictionary
info_dict = { "columns":_columns,
"rows":_rows,
"width":_width,
"height":_height,
"area":_area,
"block":_block,
"routes_per_micron_hor":_routes_per_micron_hor,
"routes_per_micron_ver":_routes_per_micron_ver,
"routes_used_by_macros_hor":_routes_used_by_macros_hor,
"routes_used_by_macros_ver":_routes_used_by_macros_ver,
"smoothing_factor":_smoothing_factor,
"overlap_threshold":_overlap_threshold,
"hard_macros_cnt":_hard_macros_cnt,
"hard_macro_pins_cnt":_hard_macro_pins_cnt,
"macro_cnt":_macro_cnt,
"macro_pin_cnt":_macro_pin_cnt,
"port_cnt":_port_cnt,
"soft_macros_cnt":_soft_macros_cnt,
"soft_macro_pins_cnt":_soft_macro_pins_cnt,
"stdcells_cnt":_stdcells_cnt,
"node_plc":_node_plc
}
return info_dict
def restore_placement(self, plc_pth: str, ifInital=True, ifValidate=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
"""
# if plc is an initial placement
if ifInital:
self.init_plc = plc_pth
# extracted information from .plc file
info_dict = self.__read_plc(plc_pth)
# validate netlist.pb.txt is on par with .plc
if ifValidate:
print(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.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'])
# TODO restore placement for each module
def __update_connection(self):
"""
......@@ -372,11 +509,6 @@ class PlacementCost(object):
weight = pin.get_weight()
macro.add_connections(inputs[k], weight)
def __update_placement(self):
# assign modules to grid cells
pass
def get_cost(self) -> float:
"""
Compute wirelength cost from wirelength
......@@ -1238,13 +1370,6 @@ class PlacementCost(object):
def is_node_fixed(self):
pass
def restore_placement(self, init_plc_pth: str):
"""
Read and retrieve .plc file information
"""
self.init_plc = init_plc_pth
self.__read_plc()
def optimize_stdcells(self):
pass
......@@ -1473,6 +1598,18 @@ class PlacementCost(object):
plt.show()
plt.close('all')
# Internal Util Function For Testing, Not visible at original CT
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:
......
......@@ -9,35 +9,37 @@ import time
import math
np.set_printoptions(threshold=sys.maxsize)
FLAGS = flags.FLAGS
import argparse
class CircuitDataBaseTest():
# NETLIST_PATH = "./Plc_client/test/sample_clustered_uniform_two_soft/netlist.pb.txt"
# NETLIST_PATH = "./Plc_client/test/ariane_hard2soft/netlist.pb.txt"
# NETLIST_PATH = "./Plc_client/test/ariane_soft2hard/netlist.pb.txt"
# NETLIST_PATH = "./Plc_client/test/ariane_port2soft/netlist.pb.txt"
# NETLIST_PATH = "./Plc_client/test/sample_clustered_nomacro/netlist.pb.txt"
# NETLIST_PATH = "./Plc_client/test/sample_clustered_macroxy/netlist.pb.txt"
# NETLIST_PATH = "./Plc_client/test/ariane/netlist.pb.txt"
# NETLIST_PATH = "./Plc_client/test/ariane133/netlist.pb.txt"
NETLIST_PATH = "./Plc_client/test/testcases/TC1_MP1_0_0_P2_0_1.pb.txt"
# NETLIST_PATH = "./Plc_client/test/testcases/TC24_MP1_0_0_MP2_4_4.pb.txt"
# NETLIST_PATH = "./Plc_client/test/0P1M1m/netlist.pb.txt"
# NETLIST_PATH = "./Plc_client/test/0P2M0m/netlist.pb.txt"
# NETLIST_PATH = "./Plc_client/test/0P3M0m/netlist.pb.txt"
# NETLIST_PATH = "./Plc_client/test/0P4M0m/netlist.pb.txt"
# NETLIST_PATH = "./Plc_client/test/testcases_xm/TC_MP1_4_1_MP2_2_2_MP3_3_4_MP4_0_0.pb.txt"
"""plc_client_os_test docstrings
Test Utility Class for Google's API plc_wrapper_main with plc_client.py and plc_client_os.py
Example:
At ./MacroPlacement/CodeElement, run the following command:
$ python -m Plc_client.plc_client_os_test
Todo:
* Clean up code
* Extract argument from command line
* Report index for each mismatch array entry
"""
class PlacementCostTest():
# Google's Ariane
# CANVAS_WIDTH = 356.592
# CANVAS_HEIGHT = 356.640
# GRID_COL = 35
# GRID_ROW = 33
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
# CANVAS_WIDTH = 1599.99
# CANVAS_HEIGHT = 1600.06
# GRID_COL = 24
# GRID_ROW = 21
# Sample clustered
# CANVAS_WIDTH = 400
......@@ -51,11 +53,23 @@ class CircuitDataBaseTest():
# GRID_COL = 5
# GRID_ROW = 5
def __init__(self, NETLIST_PATH) -> None:
def __init__(self, NETLIST_PATH, PLC_PATH=None) -> None:
self.NETLIST_PATH = NETLIST_PATH
if PLC_PATH:
self.PLC_PATH = PLC_PATH
def test_input(self):
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)
if self.PLC_PATH:
self.plc_os.restore_placement(self.PLC_PATH,
ifInital=True, ifValidate=True)
def test_proxy_congestion(self):
# Google's Binary Executable
# Google's API
self.plc = plc_client.PlacementCost(self.NETLIST_PATH)
self.plc_os = plc_client_os.PlacementCost(self.NETLIST_PATH)
......@@ -66,8 +80,8 @@ class CircuitDataBaseTest():
# self.plc.set_macro_routing_allocation(5, 5)
# self.plc_os.set_macro_routing_allocation(5, 5)
self.plc.set_macro_routing_allocation(0, 0)
self.plc_os.set_macro_routing_allocation(0, 0)
self.plc.set_macro_routing_allocation(10, 10)
self.plc_os.set_macro_routing_allocation(10, 10)
self.plc.set_congestion_smooth_range(0.0)
self.plc_os.set_congestion_smooth_range(0.0)
......@@ -87,8 +101,8 @@ class CircuitDataBaseTest():
print(temp_gl_h.reshape(self.GRID_COL, self.GRID_ROW))
print(temp_os_h.reshape(self.GRID_COL, self.GRID_ROW))
print("GL H Congestion: ", temp_gl_h)
print("OS H Congestion: ", temp_os_h)
print("GL H Congestion: ", self.plc.get_horizontal_routing_congestion())
print("OS H Congestion: ", self.plc_os.get_horizontal_routing_congestion())
temp_gl_v = np.array(self.plc.get_vertical_routing_congestion())
temp_os_v = np.array(self.plc_os.get_vertical_routing_congestion())
......@@ -145,6 +159,18 @@ class CircuitDataBaseTest():
# 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)
......@@ -154,13 +180,12 @@ class CircuitDataBaseTest():
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.display_canvas())
print(self.plc_os.get_wirelength(), self.plc.get_wirelength())
assert int(self.plc_os.get_wirelength()) == int(self.plc.get_wirelength())
......@@ -262,11 +287,19 @@ class CircuitDataBaseTest():
def main(argv):
args = sys.argv[1:]
temp = CircuitDataBaseTest(args[0])
temp.test_proxy_congestion()
# temp.test_proxy_cost()
# temp.test_metadata()
# temp.test_miscellaneous()
if len(args) > 1:
# netlist+plc file
PCT = PlacementCostTest(args[0], args[1])
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
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