Commit 5bed6913 by sakundu

Merge branch 'main' of github.com:TILOS-AI-Institute/MacroPlacement into main

parents 78154279 fc4fd0a9
# PlacementCost
`plc_client_os` is a reversed-engineered work to provide almost the same functionaility with Google's plc_client API. The codebase is available in Cython for faster runtime while being easily accessible. While Circuit Training repository does provide [documentation](https://github.com/google-research/circuit_training/blob/main/docs/PLACEMENT_COST.md) for their plc_client, we provide complete functions and detailed documentations in our codebase.
## Quick Start
Under `MACROPLACEMENT/CodeElements` directory, run the following command:
```
......@@ -11,6 +11,9 @@ sudo curl https://storage.googleapis.com/rl-infra-public/circuit-training/placem
# Run plc testbench
# 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]
# Compile Cython
python Plc_client.setup.py build_ext --inplace
# Example
python -m Plc_client.plc_client_os_test --netlist ./Plc_client/test/ariane/netlist.pb.txt\
--plc ./Plc_client/test/ariane/initial.plc\
......@@ -27,13 +30,6 @@ python -m Plc_client.plc_client_os_test --netlist ./Plc_client/test/ariane/netli
You may uncomment any available tests and even run your own test dataset. We do not handle all corner cases since during RL placement, they are unlikely to occur. Our aim here is to reproduce Google's code as much as possible and be able to plug into Circuit Training Flow.
## How to run our code in Circuit Training?
Once you have downloaded Google's Circuit Training code, replace the environment.py with environment_ct.py (**you do need to change the name of the file**). Then, copy `plc_client_os.py` under the same directory (**you should not replace it with `plc_client.py` and should not change the name of the file**).
Since Force Directed Placer for the soft macros is not implemented yet, our code is essentially running Google's `plc_client.py` in parallel with our `plc_client_os.py` but extracting input from our code only except for soft macro positions. The memory usage will double and the runtime tends to be longer. However, with this "more open sourced" version of Circuit Training, we do see comparable training quality as using Google's API.
If you wish to find any discrepancies between these outputs, toggle `DEBUG` to `True` [here](https://github.com/TILOS-AI-Institute/MacroPlacement/blob/e634766f6aa53510c3fe8062896a6020f7ff18d1/CodeElements/Plc_client/environment_ct.py#L42) at the beginning of `environment_ct.py`. This will save all discrepancies into the corresponding folders.
## Implementation Details
For complete information on how the proxy cost is computed in our code, please refer to [Proxy Cost Documentation](https://tilos-ai-institute.github.io/MacroPlacement/Docs/ProxyCost/). Below is a quick overview of the formulation.
......@@ -97,6 +93,11 @@ $$
Notice a smoothing range can be set for congestion. This is only applied to congestion due to net routing which by counting adjacent cells and adding the averaged congestion to these adjacent cells. More details are provided in the document above.
## FD Placement
To enable FD placement, please forward to [FD Placement section](https://github.com/TILOS-AI-Institute/MacroPlacement/tree/main/CodeElements/FDPlacement) where we provide full implementation in C++ for faster runtime. Our Cython codebase is fully integrated with our FD implementation. Once you generated the FD executable `fd_placer`, move it under the same directory as your `plc_client_os.pyx` source code directory. Then, FD functionailty should be enabled without extra steps.
For Details on how FD works, we provide documentation [here](https://github.com/TILOS-AI-Institute/MacroPlacement/blob/main/CodeElements/FDPlacement/README.md).
## DISCLAIMER
**We DO NOT own the original content of placement_util_os.py, observation_extractor_os.py, environment_os.py, environment_ct.py, coordinate_descent_placer.py. All rights belong to Google Authors. These are modified version of the original code and we are including in the repo for the sake of testing. Original Code can be viewed [here](https://github.com/google-research/circuit_training/blob/main/circuit_training/environment/placement_util.py)**.
......
......@@ -308,15 +308,14 @@ class PlacementCostTest():
# self.plc.make_soft_macros_square()
self.plc.set_placement_grid(self.GRID_COL, self.GRID_ROW)
# self.plc.make_soft_macros_square() # in effect
self.plc.make_soft_macros_square() # in effect
self.plc.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.make_soft_macros_square()
# self.plc_os.make_soft_macros_square()
self.plc_os.make_soft_macros_square()
# [IGNORE] create_blockage must be defined BEFORE set_canvas_size
# and set_placement_grid in order to be considered on the canvas
......@@ -867,7 +866,7 @@ class PlacementCostTest():
self.plc_util_os.display_canvas(annotate=False)
def test_fd(self):
def test_google_fd(self):
print("############################ TEST GOOGLE's FD Placer ############################")
self.plc_util = placement_util.create_placement_cost(
plc_client=plc_client,
......@@ -875,33 +874,94 @@ class PlacementCostTest():
init_placement=self.PLC_PATH
)
self.plc_util.set_routes_per_micron(self.RPMH, self.RPMV)
self.plc_util.set_macro_routing_allocation(self.MARH, self.MARV)
self.plc_util.set_congestion_smooth_range(self.SMOOTH)
self.plc_util.make_soft_macros_square()
self.plc_util.set_canvas_size(self.CANVAS_WIDTH, self.CANVAS_HEIGHT)
self.plc_util.set_placement_grid(self.GRID_COL, self.GRID_ROW)
self.plc_util_os = placement_util.create_placement_cost(
plc_client=plc_client_os,
netlist_file=self.NETLIST_PATH,
init_placement=self.PLC_PATH
)
self.plc_util.set_routes_per_micron(self.RPMH, self.RPMV)
self.plc_util_os.set_routes_per_micron(self.RPMH, self.RPMV)
self.plc_util.set_macro_routing_allocation(self.MARH, self.MARV)
self.plc_util_os.set_macro_routing_allocation(self.MARH, self.MARV)
self.plc_util.set_congestion_smooth_range(self.SMOOTH)
self.plc_util_os.set_congestion_smooth_range(self.SMOOTH)
self.plc_util.set_canvas_size(self.CANVAS_WIDTH, self.CANVAS_HEIGHT)
self.plc_util.set_placement_grid(self.GRID_COL, self.GRID_ROW)
self.plc_util_os.make_soft_macros_square()
self.plc_util_os.set_canvas_size(self.CANVAS_WIDTH, self.CANVAS_HEIGHT)
self.plc_util_os.set_placement_grid(self.GRID_COL, self.GRID_ROW)
placement_util.fd_placement_schedule(self.plc_util)
## For final result
# placement_util.fd_placement_schedule(self.plc_util,
# num_steps=(100,100),
# io_factor=1.0,
# move_distance_factors=(1.0,1.0),
# attract_factor=(100.0,100.0),
# repel_factor=(0.0,0.0),
# use_current_loc=True,
# move_macros=False)
# for node_index in placement_util.nodes_of_types(self.plc_util, ['MACRO']):
# x_pos, y_pos = self.plc_util.get_node_location(node_index)
# print(x_pos, y_pos)
# self.plc_util_os.set_soft_macro_position(node_index, x_pos, y_pos)
# self.plc_util_os.display_canvas(annotate=False, amplify=False)
# For Step-by-step result
temp_pos_collection= [[0,0]] * 10
for node_index in placement_util.nodes_of_types(self.plc_util, ['MACRO']):
x_pos, y_pos = self.plc_util.get_node_location(node_index)
if self.plc_util.is_node_soft_macro(node_index):
print(0, node_index,
x_pos,
y_pos,
x_pos - temp_pos_collection[node_index][0],
y_pos - temp_pos_collection[node_index][1])
temp_pos_collection[node_index] = [x_pos, y_pos]
self.plc_util_os.set_soft_macro_position(node_index, x_pos, y_pos)
# Step by step iteration
for i in range(1, 41):
# resetting the placement util
self.plc_util = placement_util.create_placement_cost(
plc_client=plc_client,
netlist_file=self.NETLIST_PATH,
init_placement=self.PLC_PATH
)
self.plc_util.set_routes_per_micron(self.RPMH, self.RPMV)
self.plc_util.set_macro_routing_allocation(self.MARH, self.MARV)
self.plc_util.set_congestion_smooth_range(self.SMOOTH)
self.plc_util.make_soft_macros_square()
self.plc_util.set_canvas_size(self.CANVAS_WIDTH, self.CANVAS_HEIGHT)
self.plc_util.set_placement_grid(self.GRID_COL, self.GRID_ROW)
placement_util.fd_placement_schedule(
self.plc_util,
num_steps=(i,),
io_factor=1.0,
move_distance_factors=(1.0,),
attract_factor=(100.0,),
repel_factor=(100.0,),
use_current_loc=True,
move_macros=False)
# sync with plc_util_os for visualization
for node_index in placement_util.nodes_of_types(self.plc_util, ['MACRO']):
x_pos, y_pos = self.plc_util.get_node_location(node_index)
# print(temp_pos_collection)
if self.plc_util.is_node_soft_macro(node_index):
print(i, node_index,
x_pos,
y_pos,
x_pos - temp_pos_collection[node_index][0],
y_pos - temp_pos_collection[node_index][1])
temp_pos_collection[node_index] = [x_pos, y_pos]
self.plc_util_os.set_soft_macro_position(node_index, x_pos, y_pos)
self.plc_util_os.display_canvas(annotate=False, amplify=False)
self.plc_util_os.display_canvas(annotate=True, amplify=True, saveName=str(i))
def test_environment(self):
print("############################ TEST ENVIRONMENT ############################")
......@@ -951,8 +1011,6 @@ class PlacementCostTest():
env_os._plc.display_canvas(annotate=False)
exit(1)
# check observation state
obs_gl = env._get_obs()
obs_os = env_os._get_obs()
......@@ -974,6 +1032,7 @@ class PlacementCostTest():
def test_fd_placement(self):
print("############################ TEST FDPLACEMENT ############################")
# test FD placement in plc_client_os
self.plc_util_os = placement_util.create_placement_cost(
plc_client=plc_client_os,
netlist_file=self.NETLIST_PATH,
......@@ -989,9 +1048,42 @@ class PlacementCostTest():
self.plc_util_os.set_canvas_size(self.CANVAS_WIDTH, self.CANVAS_HEIGHT)
self.plc_util_os.set_placement_grid(self.GRID_COL, self.GRID_ROW)
placement_util.fd_placement_schedule(self.plc_util_os)
self.plc_util_os.display_canvas(annotate=False, amplify=False)
# placement_util.fd_placement_schedule(self.plc_util_os)
for i in range(1, 41):
placement_util.fd_placement_schedule(
self.plc_util_os,
num_steps=(i,),
io_factor=1.0,
move_distance_factors=(1.0,),
attract_factor=(100.0,),
repel_factor=(100.0,),
use_current_loc=False,
move_macros=False)
self.plc_util_os.display_canvas(annotate=True, amplify=True, saveName=str(i))
# test FD placement under FDPlacement folder
# print(os.getcwd())
# os.system("cd FDPlacement/ && python3 fd_placement_exp.py --netlist .{} \
# --width {} --height {} --col {} --row {} && cd -".format(
# self.NETLIST_PATH, self.CANVAS_WIDTH,
# self.CANVAS_HEIGHT, self.GRID_COL, self.GRID_ROW
# )
# )
# self.plc_util_os = placement_util.create_placement_cost(
# plc_client=plc_client_os,
# netlist_file=self.NETLIST_PATH + ".final",
# )
# print(self.CANVAS_WIDTH, self.CANVAS_HEIGHT)
# self.plc_util_os.set_canvas_size(self.CANVAS_WIDTH, self.CANVAS_HEIGHT)
# self.plc_util_os.set_placement_grid(self.GRID_COL, self.GRID_ROW)
# self.plc_util_os.make_soft_macros_square()
# print(self.plc_util_os.get_canvas_width_height())
# self.plc_util_os.display_canvas(annotate=True, amplify=True)
# os.chdir()
def parse_flags(argv):
parser = argparse_flags.ArgumentParser(
......@@ -1059,9 +1151,9 @@ def main(args):
# PCT.test_miscellaneous()
# PCT.test_observation_extractor()
# PCT.view_canvas()
# PCT.test_fd()
PCT.test_google_fd() # python3 -m Plc_client.plc_client_os_test --netlist ./Plc_client/test/1P1M2m/netlist.pb.txt --width 500 --height 500 --col 10 --row 10
# PCT.test_environment()
PCT.test_fd_placement()
# PCT.test_fd_placement()
if __name__ == '__main__':
......
# setup.py
from distutils.core import setup
from Cython.Build import cythonize
setup(
ext_modules=cythonize(
"plc_client_os.pyx", compiler_directives={"language_level": "3"}
)
)
\ 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