Commit 91c4afa6 by Dinple

restore placement WIP

parent fc82171e
...@@ -9,6 +9,22 @@ from collections import namedtuple ...@@ -9,6 +9,22 @@ from collections import namedtuple
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
from matplotlib.patches import Rectangle from matplotlib.patches import Rectangle
import numpy as np 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') Block = namedtuple('Block', 'x_max y_max x_min y_min')
...@@ -317,30 +333,151 @@ class PlacementCost(object): ...@@ -317,30 +333,151 @@ class PlacementCost(object):
# mapping connection degree to each macros # mapping connection degree to each macros
self.__update_connection() self.__update_connection()
def __read_plc(self): def __read_plc(self, plc_pth: str):
""" """
Plc file Parser Plc file Parser
""" """
with open(self.init_plc) as fp: # meta information
line = fp.readline() _columns = 0
_rows = 0
while line: _width = 0.0
# skip comments _height = 0.0
if re.search(r"\S", line)[0] == '#': _area = 0.0
# IMPORTANT: Advance pt _block = None
line = fp.readline() _routes_per_micron_hor = 0.0
continue _routes_per_micron_ver = 0.0
_routes_used_by_macros_hor = 0.0
# words itemize into list _routes_used_by_macros_ver = 0.0
line_item = re.findall(r'[0-9A-Za-z\.\-]+', line) _smoothing_factor = 0
_overlap_threshold = 0.0
# skip empty lines
if len(line_item) == 0: # node information
# IMPORTANT: Advance pt _hard_macros_cnt = 0
line = fp.readline() _hard_macro_pins_cnt = 0
continue _macro_cnt = 0
_macro_pin_cnt = 0
line = fp.readline() _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:
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
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): def __update_connection(self):
""" """
...@@ -371,11 +508,6 @@ class PlacementCost(object): ...@@ -371,11 +508,6 @@ class PlacementCost(object):
if macro_type == "MACRO" or macro_type == "macro": if macro_type == "MACRO" or macro_type == "macro":
weight = pin.get_weight() weight = pin.get_weight()
macro.add_connections(inputs[k], weight) macro.add_connections(inputs[k], weight)
def __update_placement(self):
# assign modules to grid cells
pass
def get_cost(self) -> float: def get_cost(self) -> float:
""" """
...@@ -1238,13 +1370,6 @@ class PlacementCost(object): ...@@ -1238,13 +1370,6 @@ class PlacementCost(object):
def is_node_fixed(self): def is_node_fixed(self):
pass 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): def optimize_stdcells(self):
pass pass
...@@ -1473,6 +1598,18 @@ class PlacementCost(object): ...@@ -1473,6 +1598,18 @@ class PlacementCost(object):
plt.show() plt.show()
plt.close('all') 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 # Board Entity Definition
class Port: class Port:
......
...@@ -9,35 +9,37 @@ import time ...@@ -9,35 +9,37 @@ import time
import math import math
np.set_printoptions(threshold=sys.maxsize) np.set_printoptions(threshold=sys.maxsize)
FLAGS = flags.FLAGS FLAGS = flags.FLAGS
import argparse
class CircuitDataBaseTest(): """plc_client_os_test docstrings
# NETLIST_PATH = "./Plc_client/test/sample_clustered_uniform_two_soft/netlist.pb.txt"
# NETLIST_PATH = "./Plc_client/test/ariane_hard2soft/netlist.pb.txt" Test Utility Class for Google's API plc_wrapper_main with plc_client.py and plc_client_os.py
# NETLIST_PATH = "./Plc_client/test/ariane_soft2hard/netlist.pb.txt"
# NETLIST_PATH = "./Plc_client/test/ariane_port2soft/netlist.pb.txt" Example:
# NETLIST_PATH = "./Plc_client/test/sample_clustered_nomacro/netlist.pb.txt" At ./MacroPlacement/CodeElement, run the following command:
# NETLIST_PATH = "./Plc_client/test/sample_clustered_macroxy/netlist.pb.txt"
# NETLIST_PATH = "./Plc_client/test/ariane/netlist.pb.txt" $ python -m Plc_client.plc_client_os_test
# NETLIST_PATH = "./Plc_client/test/ariane133/netlist.pb.txt"
NETLIST_PATH = "./Plc_client/test/testcases/TC1_MP1_0_0_P2_0_1.pb.txt" Todo:
# NETLIST_PATH = "./Plc_client/test/testcases/TC24_MP1_0_0_MP2_4_4.pb.txt" * Clean up code
# NETLIST_PATH = "./Plc_client/test/0P1M1m/netlist.pb.txt" * Extract argument from command line
# NETLIST_PATH = "./Plc_client/test/0P2M0m/netlist.pb.txt" * Report index for each mismatch array entry
# 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"
class PlacementCostTest():
# Google's Ariane # Google's Ariane
# CANVAS_WIDTH = 356.592 CANVAS_WIDTH = 356.592
# CANVAS_HEIGHT = 356.640 CANVAS_HEIGHT = 356.640
# GRID_COL = 35 GRID_COL = 35
# GRID_ROW = 33 GRID_ROW = 33
# Ariane133 # Ariane133
CANVAS_WIDTH = 1599.99 # CANVAS_WIDTH = 1599.99
CANVAS_HEIGHT = 1600.06 # CANVAS_HEIGHT = 1600.06
GRID_COL = 24 # GRID_COL = 24
GRID_ROW = 21 # GRID_ROW = 21
# Sample clustered # Sample clustered
# CANVAS_WIDTH = 400 # CANVAS_WIDTH = 400
...@@ -51,11 +53,23 @@ class CircuitDataBaseTest(): ...@@ -51,11 +53,23 @@ class CircuitDataBaseTest():
# GRID_COL = 5 # GRID_COL = 5
# GRID_ROW = 5 # GRID_ROW = 5
def __init__(self, NETLIST_PATH) -> None: def __init__(self, NETLIST_PATH, PLC_PATH=None) -> None:
self.NETLIST_PATH = NETLIST_PATH 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): def test_proxy_congestion(self):
# Google's Binary Executable # Google's API
self.plc = plc_client.PlacementCost(self.NETLIST_PATH) self.plc = plc_client.PlacementCost(self.NETLIST_PATH)
self.plc_os = plc_client_os.PlacementCost(self.NETLIST_PATH) self.plc_os = plc_client_os.PlacementCost(self.NETLIST_PATH)
...@@ -66,8 +80,8 @@ class CircuitDataBaseTest(): ...@@ -66,8 +80,8 @@ class CircuitDataBaseTest():
# self.plc.set_macro_routing_allocation(5, 5) # self.plc.set_macro_routing_allocation(5, 5)
# self.plc_os.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.set_macro_routing_allocation(10, 10)
self.plc_os.set_macro_routing_allocation(0, 0) self.plc_os.set_macro_routing_allocation(10, 10)
self.plc.set_congestion_smooth_range(0.0) self.plc.set_congestion_smooth_range(0.0)
self.plc_os.set_congestion_smooth_range(0.0) self.plc_os.set_congestion_smooth_range(0.0)
...@@ -87,8 +101,8 @@ class CircuitDataBaseTest(): ...@@ -87,8 +101,8 @@ class CircuitDataBaseTest():
print(temp_gl_h.reshape(self.GRID_COL, self.GRID_ROW)) print(temp_gl_h.reshape(self.GRID_COL, self.GRID_ROW))
print(temp_os_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("GL H Congestion: ", self.plc.get_horizontal_routing_congestion())
print("OS H Congestion: ", temp_os_h) print("OS H Congestion: ", self.plc_os.get_horizontal_routing_congestion())
temp_gl_v = np.array(self.plc.get_vertical_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()) temp_os_v = np.array(self.plc_os.get_vertical_routing_congestion())
...@@ -144,7 +158,19 @@ class CircuitDataBaseTest(): ...@@ -144,7 +158,19 @@ class CircuitDataBaseTest():
# print("gl, os:", temp_gl_h[idx], temp_os_h[idx], temp_gl_v[idx], temp_os_v[idx]) # 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)) # 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): def test_proxy_cost(self):
# Google's Binary Executable # Google's Binary Executable
self.plc = plc_client.PlacementCost(self.NETLIST_PATH) self.plc = plc_client.PlacementCost(self.NETLIST_PATH)
...@@ -154,12 +180,11 @@ class CircuitDataBaseTest(): ...@@ -154,12 +180,11 @@ class CircuitDataBaseTest():
macro_macro_x_spacing = 50, macro_macro_x_spacing = 50,
macro_macro_y_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_canvas_size(self.CANVAS_WIDTH, self.CANVAS_HEIGHT)
self.plc.set_placement_grid(self.GRID_COL, self.GRID_ROW) self.plc.set_placement_grid(self.GRID_COL, self.GRID_ROW)
self.plc_os.set_canvas_size(self.CANVAS_WIDTH, self.CANVAS_HEIGHT) self.plc_os.set_canvas_size(self.CANVAS_WIDTH, self.CANVAS_HEIGHT)
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(self.plc_os.display_canvas())
print(self.plc_os.get_wirelength(), self.plc.get_wirelength()) print(self.plc_os.get_wirelength(), self.plc.get_wirelength())
...@@ -262,11 +287,19 @@ class CircuitDataBaseTest(): ...@@ -262,11 +287,19 @@ class CircuitDataBaseTest():
def main(argv): def main(argv):
args = sys.argv[1:] args = sys.argv[1:]
temp = CircuitDataBaseTest(args[0])
temp.test_proxy_congestion() if len(args) > 1:
# temp.test_proxy_cost() # netlist+plc file
# temp.test_metadata() PCT = PlacementCostTest(args[0], args[1])
# temp.test_miscellaneous() 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__": if __name__ == "__main__":
app.run(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