Commit 168fc2ed by sakundu

Updated Bookshelf to Protobuf translator. Added utility script for flat placement evaluation.

Signed-off-by: sakundu <sakundu@ucsd.edu>
parent 01109df1
''' '''
This Code converts the BookShelf format to Proto buf format This Code converts the Bookshelf netlist to Protobuf netlist.
Author: Sayak Kundu email: sakundu@ucsd.edu
Follow the below steps to convert bookshelf netlist to protobuf netlist.
1. bs_design = canvas_object(<design_name>)
2. bs_desing(<bookshelf_dir>, <output_pb_netlist>)
Here it expects <design_name>.scl, <design_name>.nets, <design_name>.nodes,
<design_name>.wts, <design_name>.pl files are present in the <bookshelf_dir>
<output_pb_netlist> is optional. If it is not provided then it will write out
the <design_name>.pb.txt in the <bookshelf_dir> directory.
''' '''
import re import re
import os import os
...@@ -69,14 +78,14 @@ class instance: ...@@ -69,14 +78,14 @@ class instance:
self.height = height self.height = height
self.width = width self.width = width
return return
def update_location(self, x, y, orient, pstatus = "UNPLACED"): def update_location(self, x, y, orient, pstatus = "UNPLACED"):
self.llx = float(x) self.llx = float(x)
self.lly = float(y) self.lly = float(y)
self.orient = orient.upper() self.orient = orient.upper()
self.pstatus = pstatus.upper() self.pstatus = pstatus.upper()
return return
def update_center(self): def update_center(self):
self.cx = self.llx + self.width/2 self.cx = self.llx + self.width/2
self.cy = self.lly + self.height/2 self.cy = self.lly + self.height/2
...@@ -909,7 +918,11 @@ class canvas_object: ...@@ -909,7 +918,11 @@ class canvas_object:
for port in self.ports: for port in self.ports:
port.name = port.name.replace("\\","") port.name = port.name.replace("\\","")
return return
def __call__(self, bookshelf_dir, output_pb_netlist = None):
self.read_BookShelf(bookshelf_dir)
self.gen_pb_netlist(output_pb_netlist)
return
def read_pb(self, pb_netlist): def read_pb(self, pb_netlist):
fp = open(pb_netlist, 'r') fp = open(pb_netlist, 'r')
lines = fp.readlines() lines = fp.readlines()
......
########################## Details to use this script ##########################
# Author: Sayak Kundu email: sakundu@ucsd.edu
# Date: 11-22-2022
# This script converts LEF / DEF format to Protobuf format using OpenROAD.
# Follow the below steps to generate protobuf netlist from LEF / DEF in the
# OpenROAD shell:
# 1. read_lef <tech lef>
# 2. read_lef <standard cell and macro lef one by one>
# 3. read_def <design def file>
# 4. source <This script file>
# 5. gen_pb_netlist <path of the output protobuf netlist>
################################################################################
#### Print the design header #### #### Print the design header ####
proc print_header { fp } { proc print_header { fp } {
set design [[ord::get_db_block] getName] set design [[ord::get_db_block] getName]
......
...@@ -39,7 +39,8 @@ The following screenshot shows the placed Ariane133-NG45 design generated using ...@@ -39,7 +39,8 @@ The following screenshot shows the placed Ariane133-NG45 design generated using
## *Baseline Macro Placement Generated by Human* ## *Baseline Macro Placement Generated by Human*
### Manual macro placement on a gridded canvas ### Manual macro placement on a gridded canvas
The following screenshots show the placed and routed Ariane133-NG45 design generated using [Flow-2](../../figures/flow-2.PNG), where the macros are placed manually on a gridded canvas. The following screenshots show the placed and routed Ariane133-NG45 design generated using [Flow-2](../../figures/flow-2.PNG), where the macros are placed manually on a gridded canvas by [Zhiang Wang](mailto:zhw033@eng.ucsd.edu).
<p align="center"> <p align="center">
<img height="400" src="./screenshots/Human_Gridded_Placement.png"> <img height="400" src="./screenshots/Human_Gridded_Placement.png">
<img height="400" src="./screenshots/Human_Gridded_Routing.png"> <img height="400" src="./screenshots/Human_Gridded_Routing.png">
......
'''
This script can be used to evaluate proxy cost of clustered netlist.
Author: Sayak Kundu email:sakundu@ucsd.edu
Requirements:
This code utilizes Google Circuit Training (CT)
(https://github.com/google-research/circuit_training) code and the plc_wrapper_main
(https://storage.googleapis.com/rl-infra-public/circuit-training/placement_cost/plc_wrapper_main)
binary to evaluate the proxy cost of the clustered netlist.
For more details please look into the README file in CT repo.
Steps to run this script:
1. First install CT
2. export PYTHONPATH=$PYTHONPATH:<CT Path>
3. python evaluate_clustered_netlist.py <pb_netlist> <plc_file> <output_dir/design>
Output:
This will print the initial proxy cost, final proxy cost (cost after FD repel).
It will save the following files:
1. initial placement image <output_dir/design>_init.png
2. final plc_file in as <output_dir/design>_post_repel.plc
3. final placement image (after FD repel) <output_dir/design>_final.png
If you do not provide <output_dir/design> it will only print the initial and
post FD repel proxy cost.
'''
import sys
import os
sys.path.append(os.path.dirname(__file__))
from extract_net import pb_design
from circuit_training.environment import plc_client
from circuit_training.environment import placement_util
import matplotlib.pyplot as plt
def get_plc(plc_file, pb_netlist):
plc = plc_client.PlacementCost(pb_netlist)
design = pb_design('block', pb_netlist)
design.read_netlist()
design.read_plc(plc_file)
plc.make_soft_macros_square()
plc.set_canvas_size(design.plc_info.width, design.plc_info.height)
plc.set_placement_grid(design.plc_info.columns, design.plc_info.rows)
plc.set_routes_per_micron(design.plc_info.route_hor, design.plc_info.route_ver)
plc.set_macro_routing_allocation(design.plc_info.macro_route_hor, design.plc_info.macro_route_ver)
plc.set_congestion_smooth_range(design.plc_info.sm_factor)
plc.set_overlap_threshold(design.plc_info.ovrlp_thrshld)
plc.set_canvas_boundary_check(True)
plc.restore_placement(plc_file)
return plc
def plot_from_plc(plc, png_file = None):
plt.figure(constrained_layout=True,figsize=(8,5),dpi=600)
canvas_width, canvas_height = plc.get_canvas_width_height()
for idx in plc.get_macro_indices():
color = 'blue'
if plc.is_node_soft_macro(idx):
color = 'red'
width, height = plc.get_node_width_height(idx)
cx, cy = plc.get_node_location(idx)
lx, ly = cx - width/2.0, cy - height/2
rectangle = plt.Rectangle((lx, ly), width, height, fc = color, ec = "black")
plt.gca().add_patch(rectangle)
lx, ly, lw = 0.0, 0.0, 1.0
ux, uy = lx + canvas_width, ly + canvas_height
x, y = [lx, ux], [ly, ly]
plt.plot(x,y, '-k', lw = lw)
x, y = [lx, ux], [uy, uy]
plt.plot(x,y, '-k', lw = lw)
x, y = [lx, lx], [ly, uy]
plt.plot(x,y, '-k', lw = lw)
x, y = [ux, ux], [ly, uy]
plt.plot(x,y, '-k', lw = lw)
plt.xlim(lx, ux)
plt.ylim(ly, uy)
plt.axis("scaled")
if png_file != None:
plt.savefig(png_file)
plt.show()
return
def get_cost(plc, isPrint = True):
wl_cost = plc.get_cost()
den_cost = plc.get_density_cost()
cong_cost = plc.get_congestion_cost()
proxy_cost = wl_cost + 0.5*den_cost + 0.5*cong_cost
if isPrint:
print(f'WL Cost:{wl_cost}\nCongestion Cost:{cong_cost}\nDensity Cost:{den_cost}')
print(f"Proxy Cost:{proxy_cost}")
return proxy_cost
## Run Placement schedule only with repeal and plot it again ##
def fix_all_hard_macros(plc):
for idx in plc.get_macro_indices():
if plc.is_node_soft_macro(idx):
plc.unfix_node_coord(idx)
else:
plc.fix_node_coord(idx)
return
def fix_all_ports(plc):
i = 0
while True:
node_type = plc.get_node_type(i)
if node_type == '':
break
elif node_type == 'PORT':
plc.fix_node_coord(i)
i += 1
return
def update_soft_macros_using_repeal(plc, isComplete = False):
if isComplete:
num_steps = (100, 100, 100)
move_distance_factors = (1.0, 1.0, 1.0)
attract_factor = (100, 1.0e-3, 1.0e-5)
repel_factor = (0.0, 1.0e6, 1.0e7)
use_current_loc = False
else:
num_steps = (100, 100)
move_distance_factors = (1.0, 1.0)
attract_factor = (1.0e-3, 1.0e-5)
repel_factor = (1.0e6, 1.0e7)
use_current_loc = True
io_factor = 1.0
move_macros = False
canvas_size = max(plc.get_canvas_width_height())
max_move_distance = [
f * canvas_size / s for s, f in zip(num_steps, move_distance_factors)
]
move_stdcells = True
log_scale_conns = False
use_sizes = False
plc.optimize_stdcells(use_current_loc, move_stdcells, move_macros,
log_scale_conns, use_sizes, io_factor, num_steps,
max_move_distance, attract_factor, repel_factor)
if __name__ == '__main__':
pb_netlist = sys.argv[1]
plc_netlist = sys.argv[2]
png_file = None
png_file_init_path = None
png_file_final_path = None
plc_file_final_path = None
if len(sys.argv) == 4:
png_file = sys.argv[3]
png_file_init_path = f"{png_file}_init.png"
png_file_final_path = f"{png_file}_final.png"
plc_file_final_path = f"{png_file}_post_repel.plc"
plc = get_plc(plc_netlist, pb_netlist)
print("Initial Proxy cost:")
_ = get_cost(plc)
plot_from_plc(plc, png_file_init_path)
fix_all_hard_macros(plc)
fix_all_ports(plc)
update_soft_macros_using_repeal(plc)
print("Final Proxy cost (After FD Repel):")
_ = get_cost(plc)
plot_from_plc(plc, png_file_final_path)
if plc_file_final_path:
placement_util.save_placement(plc, plc_file_final_path, 'Post FD repel placement')
#!/usr/bin/env bash #!/usr/bin/env bash
########################################################################## ##########################################################################
# Update HMETIS_DIR PLC_WRAPPER_MAIN and CT_PATH # Author: Sayak Kundu email: sakundu@ucsd.edu
# This script runs Circuit Training (CT) Grouping to generate clustered
# netlist from the Protobuf netlist. For more details please see CT
# Grouping README (Link:
# https://github.com/google-research/circuit_training/blob/main/circuit_training/grouping/README.md)
#
# Update the following environment variables to run CT Grouping using
# this script:
# 1. NETLIST_FILE: Provide the path of the input Protobuf netlist
# 2. HMETIS_DIR: Provide the directory path where the hMETIS executable
# files exist.
# 3. PLC_WRAPPER_MAIN: Provide the path of the plc_wrapper_main binary.
# This binary is downloaded from CT. Link to the binary:
# https://storage.googleapis.com/rl-infra-public/circuit-training/placement_cost/plc_wrapper_main
# 4. CT_PATH: Provide the directory path where CT is cloned.
# 5. OUTPUT_DIR: Provide the directory path where to save the final
# clustered netlist.
#
# Before launching the script make sure that PHY_SYNTH environment variables
# is set to 1.
########################################################################## ##########################################################################
if [ $PHY_SYNTH -eq 1 ]; then if [ $PHY_SYNTH -eq 1 ]; then
export PROJ_DIR=`pwd | grep -o '\S*/MacroPlacement'` export PROJ_DIR=`pwd | grep -o '\S*/MacroPlacement'`
...@@ -8,11 +27,8 @@ if [ $PHY_SYNTH -eq 1 ]; then ...@@ -8,11 +27,8 @@ if [ $PHY_SYNTH -eq 1 ]; then
export BLOCK_NAME=`basename ${NETLIST_FILE} | sed 's@.pb.txt@@'` export BLOCK_NAME=`basename ${NETLIST_FILE} | sed 's@.pb.txt@@'`
export TECH=`echo $PWD | awk -F'/' '{print $(NF-3)}'` export TECH=`echo $PWD | awk -F'/' '{print $(NF-3)}'`
export OUTPUT_DIR="./output_${BLOCK_NAME}_${TECH}" export OUTPUT_DIR="./output_${BLOCK_NAME}_${TECH}"
export HMETIS_DIR="/home/zf4_projects/DREAMPlace/sakundu/GB/CT/hmetis-1.5-linux" export HMETIS_DIR="${PROJ_DIR}/../../../GB/CT/hmetis-1.5-linux"
export PLC_WRAPPER_MAIN="/home/zf4_projects/DREAMPlace/sakundu/GB/CT/plc_wrapper_main" export PLC_WRAPPER_MAIN="${PROJ_DIR}/../../../GB/CT/plc_wrapper_main"
#export CT_PATH="${PROJ_DIR}/../../../GB/CT/circuit_training" export CT_PATH="${PROJ_DIR}/../../../GB/CT/circuit_training"
#export CT_PATH="/home/zf4_projects/DREAMPlace/sakundu/ABK_MP/CT/09092022/circuit_training" bash -i ${PROJ_DIR}/Flows/util/run_grp.sh 2>&1 | tee log/grouping.log
export CT_PATH="/home/zf4_projects/DREAMPlace/sakundu/ABK_MP/CT/11112022/circuit_training"
#export CT_PATH="/home/zf4_projects/macro_placer/google_brain/TILOS_repo/grouping/circuit_training"
bash -i ../../../../util/run_grp.sh 2>&1 | tee log/grouping.log
fi fi
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