Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
M
macroplacement
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
lvzhengyang
macroplacement
Commits
05951de7
Unverified
Commit
05951de7
authored
Dec 21, 2022
by
Yucheng Wang
Committed by
GitHub
Dec 21, 2022
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Add FDPlacer as Zhiang's implementation
parent
f9ba641c
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
271 additions
and
184 deletions
+271
-184
CodeElements/Plc_client/plc_client_os.py
+271
-184
No files found.
CodeElements/Plc_client/plc_client_os.py
View file @
05951de7
...
...
@@ -55,6 +55,10 @@ class PlacementCost(object):
# Check netlist existance
assert
os
.
path
.
isfile
(
self
.
netlist_file
)
# [Experimental] Net Data Structure
# nets[driver] => [list of sinks]
self
.
nets
=
{}
# Set meta information
self
.
init_plc
=
None
self
.
project_name
=
"circuit_training"
...
...
@@ -294,6 +298,8 @@ class PlacementCost(object):
else
:
self
.
net_cnt
+=
1
soft_macro_pin
.
add_sinks
(
input_list
)
# add net
self
.
nets
[
node_name
]
=
input_list
self
.
modules_w_pins
.
append
(
soft_macro_pin
)
# mapping node_name ==> node idx
...
...
@@ -351,6 +357,7 @@ class PlacementCost(object):
else
:
self
.
net_cnt
+=
1
hard_macro_pin
.
add_sinks
(
input_list
)
self
.
nets
[
node_name
]
=
input_list
self
.
modules_w_pins
.
append
(
hard_macro_pin
)
# mapping node_name ==> node idx
...
...
@@ -381,6 +388,7 @@ class PlacementCost(object):
port
.
add_sinks
(
input_list
)
# ports does not have pins so update connection immediately
port
.
add_connections
(
input_list
)
self
.
nets
[
node_name
]
=
input_list
self
.
modules_w_pins
.
append
(
port
)
self
.
modules
.
append
(
port
)
...
...
@@ -663,6 +671,9 @@ class PlacementCost(object):
"""
Compute wirelength cost from wirelength
"""
if
self
.
net_cnt
==
0
:
self
.
net_cnt
=
1
if
self
.
FLAG_UPDATE_WIRELENGTH
:
self
.
FLAG_UPDATE_WIRELENGTH
=
False
return
self
.
get_wirelength
()
/
((
self
.
get_canvas_width_height
()[
0
]
\
...
...
@@ -707,13 +718,14 @@ class PlacementCost(object):
print
(
"[ERROR PIN POSITION] Not a MACRO PIN"
,
self
.
modules_w_pins
[
pin_idx
]
.
get_name
())
exit
(
1
)
# PORT pin pos is itself
if
self
.
modules_w_pins
[
pin_idx
]
.
get_type
()
==
'PORT'
:
return
self
.
modules_w_pins
[
pin_idx
]
.
get_pos
()
# Retrieve node that this pin instantiated on
ref_node_idx
=
self
.
get_ref_node_id
(
pin_idx
)
if
ref_node_idx
==
-
1
:
if
self
.
modules_w_pins
[
pin_idx
]
.
get_type
()
==
'PORT'
:
return
self
.
modules_w_pins
[
pin_idx
]
.
get_pos
()
else
:
print
(
"[ERROR PIN POSITION] Parent Node Not Found."
)
exit
(
1
)
...
...
@@ -730,6 +742,38 @@ class PlacementCost(object):
def
get_wirelength
(
self
)
->
float
:
"""
Proxy HPWL computation w/ [Experimental] net
"""
total_hpwl
=
0.0
for
driver_pin_name
in
self
.
nets
.
keys
():
weight_fact
=
1.0
x_coord
=
[]
y_coord
=
[]
# extract driver pin
driver_pin_idx
=
self
.
mod_name_to_indices
[
driver_pin_name
]
driver_pin
=
self
.
modules_w_pins
[
driver_pin_idx
]
# extract net weight
weight_fact
=
driver_pin
.
get_weight
()
x_coord
.
append
(
self
.
__get_pin_position
(
driver_pin_idx
)[
0
])
y_coord
.
append
(
self
.
__get_pin_position
(
driver_pin_idx
)[
1
])
# iterate through each sink
for
sink_pin_name
in
self
.
nets
[
driver_pin_name
]:
sink_pin_idx
=
self
.
mod_name_to_indices
[
sink_pin_name
]
x_coord
.
append
(
self
.
__get_pin_position
(
sink_pin_idx
)[
0
])
y_coord
.
append
(
self
.
__get_pin_position
(
sink_pin_idx
)[
1
])
if
x_coord
:
total_hpwl
+=
weight_fact
*
\
(
abs
(
max
(
x_coord
)
-
min
(
x_coord
))
+
\
abs
(
max
(
y_coord
)
-
min
(
y_coord
)))
return
total_hpwl
def
_get_wirelength
(
self
)
->
float
:
"""
Proxy HPWL computation
"""
# NOTE: in pb.txt, netlist input count exceed certain threshold will be ommitted
...
...
@@ -1930,9 +1974,6 @@ class PlacementCost(object):
return
mod
.
get_fix_flag
()
def
optimize_stdcells
(
self
):
pass
def
update_node_coords
(
self
,
node_idx
,
x_pos
,
y_pos
):
"""
Update Node location if node is 'MACRO', 'STDCELL', 'PORT'
...
...
@@ -2286,7 +2327,11 @@ class PlacementCost(object):
def
get_ref_node_id
(
self
,
node_idx
=-
1
):
"""
ref_node_id is used for macro_pins. Refers to the macro it belongs to.
if input PORT, return itself
"""
if
self
.
modules_w_pins
[
node_idx
]
.
get_type
()
==
"PORT"
:
return
node_idx
if
node_idx
!=
-
1
:
if
node_idx
in
self
.
soft_macro_pin_indices
or
node_idx
in
self
.
hard_macro_pin_indices
:
pin
=
self
.
modules_w_pins
[
node_idx
]
...
...
@@ -2323,7 +2368,8 @@ class PlacementCost(object):
def
display_canvas
(
self
,
annotate
=
True
,
amplify
=
False
,
saveName
=
None
):
saveName
=
None
,
show
=
True
):
"""
Non-google function, For quick canvas view
"""
...
...
@@ -2383,6 +2429,7 @@ class PlacementCost(object):
# ax.annotate(mod.get_name(), mod.get_pos(), wrap=True,color='r', weight='bold', fontsize=FONT_SIZE, ha='center', va='center')
if
saveName
:
plt
.
savefig
(
saveName
)
if
show
:
plt
.
show
()
plt
.
close
(
'all'
)
...
...
@@ -2410,12 +2457,6 @@ class PlacementCost(object):
return
u_x1
<
v_x2
and
u_x2
>
v_x1
and
u_y1
>
v_y2
and
u_y2
<
v_y1
def
__i_force
(
self
,
i
):
'''
Force computation based on current iteration
'''
return
max
(
self
.
width
,
self
.
height
)
/
i
def
__repulsive_force
(
self
,
repel_factor
,
mod_i_idx
,
mod_j_idx
,
with_initialization
=
False
):
'''
Calculate repulsive force between two nodes node_i, node_j
...
...
@@ -2564,6 +2605,13 @@ class PlacementCost(object):
mod
=
self
.
modules_w_pins
[
mod_id
]
mod
.
set_pos
(
self
.
width
/
2
,
self
.
height
/
2
)
def
__initialization
(
self
):
'''
Initialize soft macros to the center
'''
for
mod_idx
in
self
.
soft_macro_indices
:
self
.
__centralize_soft_macro
(
mod_idx
)
def
__boundary_check
(
self
,
mod_id
):
'''
Make sure all the clusters are placed within the canvas
...
...
@@ -2585,15 +2633,12 @@ class PlacementCost(object):
mod
.
set_pos
(
mod_x
,
mod_y
)
def
__fd_placement
(
self
,
io_factor
,
max_displacement
,
attract_factor
,
repel_factor
,
use_current_loc
,
i
):
def
__fd_placement
(
self
,
io_factor
,
num_steps
,
max_move_distance
,
attract_factor
,
repel_factor
,
use_current_loc
,
verbose
=
True
):
'''
Force-directed Placement for standard-cell clusters
'''
i
+=
1
# store x/y displacement for all soft macro disp
soft_macro_disp
=
{}
for
mod_idx
in
self
.
soft_macro_indices
:
soft_macro_disp
[
mod_idx
]
=
[
0.0
,
0.0
]
def
check_OOB
(
mod_id
,
x_disp
,
y_disp
):
mod
=
self
.
modules_w_pins
[
mod_id
]
...
...
@@ -2601,47 +2646,97 @@ class PlacementCost(object):
mod_height
=
mod
.
get_height
()
mod_width
=
mod
.
get_width
()
canvas_block
=
Block
(
x_max
=
self
.
width
,
y_max
=
self
.
height
,
x_min
=
0
,
y_min
=
0
)
# print(x_disp, y_disp, mod_x, mod_y, mod_width, mod_height)
# boundary after displacement
x_max
=
mod_x
+
mod_width
/
2
+
x_disp
y_max
=
mod_y
+
mod_height
/
2
+
y_disp
x_min
=
mod_x
-
mod_width
/
2
+
x_disp
y_min
=
mod_y
-
mod_height
/
2
+
y_disp
# 1. if both x/y displacement can be used
mod_block
=
Block
(
x_max
=
mod_x
+
mod_width
/
2
+
x_disp
,
y_max
=
mod_y
+
mod_height
/
2
+
y_disp
,
x_min
=
mod_x
-
mod_width
/
2
+
x_disp
,
y_min
=
mod_y
-
mod_height
/
2
+
y_disp
)
# print(x_max, x_min, y_max, y_min)
# determine if move
if
x_min
<=
0.0
or
x_max
>=
self
.
width
:
x_disp
=
0.0
if
y_min
<=
0.0
or
y_max
>=
self
.
height
:
y_disp
=
0.0
# if fully containing the block on canvas
if
abs
(
self
.
__overlap_area
(
block_i
=
mod_block
,
block_j
=
canvas_block
)
-
mod_height
*
mod_width
)
<=
1e-3
:
return
x_disp
,
y_disp
# 2. if only x displacement can be used
mod_block
=
Block
(
x_max
=
mod_x
+
mod_width
/
2
+
x_disp
,
y_max
=
mod_y
+
mod_height
/
2
,
x_min
=
mod_x
-
mod_width
/
2
+
x_disp
,
y_min
=
mod_y
-
mod_height
/
2
)
def
getBBox
(
mod_id
):
mod
=
self
.
modules_w_pins
[
mod_id
]
x
,
y
=
mod
.
get_pos
()
width
=
mod
.
get_width
()
height
=
mod
.
get_height
()
lx
=
x
-
width
/
2.0
ly
=
y
-
height
/
2.0
ux
=
x
+
width
/
2.0
uy
=
y
+
height
/
2.0
return
lx
,
ly
,
ux
,
uy
def
_check_overlap
(
mod_u
,
mod_v
):
'''
Zhiang's implmentation
'''
u_lx
,
u_ly
,
u_ux
,
u_uy
=
getBBox
(
mod_u
)
v_lx
,
v_ly
,
v_ux
,
v_uy
=
getBBox
(
mod_v
)
# if fully containing the block on canvas
if
abs
(
self
.
__overlap_area
(
block_i
=
mod_block
,
block_j
=
canvas_block
)
-
mod_height
*
mod_width
)
<=
1e-3
:
return
x_disp
,
y_disp
if
(
u_lx
>=
v_ux
or
u_ux
<=
v_lx
or
u_ly
>=
v_uy
or
u_uy
<=
v_ly
):
# no overlap
return
None
,
None
else
:
u_cx
=
(
u_lx
+
u_ux
)
/
2.0
u_cy
=
(
u_ly
+
u_uy
)
/
2.0
v_cx
=
(
v_lx
+
v_ux
)
/
2.0
v_cy
=
(
v_ly
+
v_uy
)
/
2.0
if
u_cx
==
v_cx
and
u_cy
==
v_cy
:
# fully overlap
x_dir
=
-
1.0
/
math
.
sqrt
(
2.0
)
y_dir
=
-
1.0
/
math
.
sqrt
(
2.0
)
return
x_dir
,
y_dir
else
:
x_dir
=
u_cx
-
v_cx
y_dir
=
u_cy
-
v_cy
dist
=
math
.
sqrt
(
x_dir
*
x_dir
+
y_dir
*
y_dir
)
return
x_dir
/
dist
,
y_dir
/
dist
# 3. if only y displacement can be used
mod_block
=
Block
(
x_max
=
mod_x
+
mod_width
/
2
,
y_max
=
mod_y
+
mod_height
/
2
+
y_disp
,
x_min
=
mod_x
-
mod_width
/
2
,
y_min
=
mod_y
-
mod_height
/
2
+
y_disp
)
def
check_overlap
(
mod_u
,
mod_v
):
u_lx
,
u_ly
,
u_ux
,
u_uy
=
getBBox
(
mod_u
)
v_lx
,
v_ly
,
v_ux
,
v_uy
=
getBBox
(
mod_v
)
# if fully containing the block on canvas
if
abs
(
self
.
__overlap_area
(
block_i
=
mod_block
,
block_j
=
canvas_block
)
-
mod_height
*
mod_width
)
<=
1e-3
:
return
x_disp
,
y_disp
if
(
u_lx
>=
v_ux
or
u_ux
<=
v_lx
or
u_ly
>=
v_uy
or
u_uy
<=
v_ly
):
return
1
,
1
else
:
u_cx
=
(
u_lx
+
u_ux
)
/
2.0
u_cy
=
(
u_ly
+
u_uy
)
/
2.0
v_cx
=
(
v_lx
+
v_ux
)
/
2.0
v_cy
=
(
v_ly
+
v_uy
)
/
2.0
x_d
=
u_cx
-
v_cx
y_d
=
u_cy
-
v_cy
# set the minimum val to 1e-12
# min_dist = 1e-2
# if abs(x_d) <= min_dist:
# x_d = -1.0 * min_dist
# if abs(y_d) <= min_dist:
# y_d = -1.0 * min_dist
if
x_d
==
0
:
x_d
=
1
else
:
x_d
/=
abs
(
x_d
)
return
0.0
,
0.0
if
y_d
==
0
:
y_d
=
1
else
:
y_d
/=
abs
(
y_d
)
return
x_d
,
y_d
def
add_displace
(
mod_id
,
x_disp
,
y_disp
):
'''
Add the displacement
'''
if
mod_id
in
self
.
soft_macro_indices
:
soft_macro_disp
[
mod_id
][
0
]
+=
x_disp
soft_macro_disp
[
mod_id
][
1
]
+=
y_disp
...
...
@@ -2650,155 +2745,147 @@ class PlacementCost(object):
Update the displacement to the coordiante
'''
x_pos
,
y_pos
=
self
.
modules_w_pins
[
mod_id
]
.
get_pos
()
# logging.info("{} {} {} {}".format(x_pos, y_pos, x_disp, y_disp))
x_disp
,
y_disp
=
check_OOB
(
mod_id
,
x_disp
,
y_disp
)
print
(
mod_id
,
x_disp
,
y_disp
)
# for debug purpose
with
open
(
'os_debug.txt'
,
'a+'
)
as
the_file
:
the_file
.
write
(
"{} {} {} {} {}
\n
"
.
format
(
mod_id
,
x_pos
+
x_disp
,
y_pos
+
y_disp
,
x_disp
,
y_disp
))
self
.
modules_w_pins
[
mod_id
]
.
set_pos
(
x_pos
+
x_disp
,
y_pos
+
y_disp
)
##SOFT_SOFT REPEL###############################################################################################
# calculate the repulsive forces
# repulsive forces between stdcell clusters
if
repel_factor
!=
0.0
:
# temp storing the soft macro count
xr_collection
=
[
0
]
*
len
(
self
.
modules_w_pins
)
yr_collection
=
[
0
]
*
len
(
self
.
modules_w_pins
)
# repulsive forces between stdcell clusters and stdcell clusters
for
mod_i
in
self
.
soft_macro_indices
:
for
mod_j
in
self
.
soft_macro_indices
:
if
(
mod_i
<=
mod_j
):
continue
repul_x
,
repul_y
=
self
.
__repulsive_force
(
repel_factor
=
repel_factor
,
node_i
=
mod_i
,
node_j
=
mod_j
)
xr_collection
[
mod_i
]
+=
1.0
*
repul_x
yr_collection
[
mod_i
]
+=
1.0
*
repul_y
xr_collection
[
mod_j
]
+=
-
1.0
*
repul_x
yr_collection
[
mod_j
]
+=
-
1.0
*
repul_y
# finding max x y displacement
max_x_disp
,
max_y_disp
=
(
0.0
,
0.0
)
for
xr
,
yr
in
zip
(
xr_collection
,
yr_collection
):
if
xr
!=
0.0
:
max_x_disp
=
max
(
max_x_disp
,
abs
(
xr
))
if
yr
!=
0.0
:
max_y_disp
=
max
(
max_y_disp
,
abs
(
yr
))
# prevent zero division
if
max_x_disp
==
0.0
:
max_x_disp
=
1.0
if
max_y_disp
==
0.0
:
max_y_disp
=
1.0
scaling
=
2.0
def
move_soft_macros
(
attract_factor
,
repel_factor
,
io_factor
,
max_displacement
):
# map to soft macro index
for
mod_idx
in
self
.
soft_macro_indices
:
soft_macro_disp
[
mod_idx
]
=
[
0.0
,
0.0
]
calcAttractiveForce
(
attract_factor
,
io_factor
,
max_displacement
)
calcRepulsiveForce
(
repel_factor
,
max_displacement
)
max_x_disp
=
0.0
max_y_disp
=
0.0
for
mod_idx
in
self
.
soft_macro_indices
:
add_displace
(
mod_idx
,
scaling
*
xr_collection
[
mod_idx
]
/
max_x_disp
,
scaling
*
yr_collection
[
mod_idx
]
/
max_y_disp
)
##SOFT_HARD REPEL###############################################################################################
if
repel_factor
!=
0.0
:
# temp storing the soft macro count
xr_collection
=
[
0
]
*
len
(
self
.
modules_w_pins
)
yr_collection
=
[
0
]
*
len
(
self
.
modules_w_pins
)
# repulsive forces between stdcell clusters and macros
for
mod_i
in
self
.
soft_macro_indices
:
for
mod_j
in
self
.
hard_macro_indices
:
repul_x
,
repul_y
=
self
.
__repulsive_force_hard_macro
(
repel_factor
=
repel_factor
,
h_node_i
=
mod_i
,
s_node_j
=
mod_j
)
xr_collection
[
mod_i
]
+=
1.0
*
repul_x
yr_collection
[
mod_i
]
+=
1.0
*
repul_y
# finding max x y displacement
max_x_disp
,
max_y_disp
=
(
0.0
,
0.0
)
for
xr
,
yr
in
zip
(
xr_collection
,
yr_collection
):
if
xr
!=
0.0
:
max_x_disp
=
max
(
max_x_disp
,
abs
(
xr
))
if
yr
!=
0.0
:
max_y_disp
=
max
(
max_y_disp
,
abs
(
yr
))
# prevent zero division
if
max_x_disp
==
0.0
:
max_x_disp
=
1.0
if
max_y_disp
==
0.0
:
max_y_disp
=
1.0
scaling
=
4.0
max_x_disp
=
max
(
max_x_disp
,
abs
(
soft_macro_disp
[
mod_idx
][
0
]))
max_y_disp
=
max
(
max_y_disp
,
abs
(
soft_macro_disp
[
mod_idx
][
1
]))
# normalization
if
max_x_disp
>
0.0
:
for
mod_idx
in
self
.
soft_macro_indices
:
add_displace
(
mod_idx
,
scaling
*
xr_collection
[
mod_idx
]
/
max_x_disp
,
scaling
*
yr_collection
[
mod_idx
]
/
max_y_disp
)
##NET ATTRACT###################################################################################################
for
driver_pin_idx
,
driver_pin
in
enumerate
(
self
.
modules_w_pins
):
# print(driver_pin_idx)
# print(self.soft_macro_pin_indices)
# print(self.hard_macro_pin_indices)
# For soft macro
if
driver_pin_idx
in
self
.
soft_macro_pin_indices
:
# print(driver_pin.get_sink())
for
mod_k
in
driver_pin
.
get_sink
()
.
keys
():
# sink mod key
for
sink_pin_name
in
driver_pin
.
get_sink
()[
mod_k
]:
sink_pin_idx
=
self
.
mod_name_to_indices
[
sink_pin_name
]
self
.
__attractive_force
(
io_factor
=
0
,
attract_factor
=
0
,
pin_i_idx
=
driver_pin_idx
,
pin_j_idx
=
sink_pin_idx
,
i
=
i
)
# For hard macro
if
driver_pin_idx
in
self
.
hard_macro_pin_indices
:
for
mod_k
in
driver_pin
.
get_sink
()
.
keys
():
# only if sink is a soft macro
if
self
.
mod_name_to_indices
[
mod_k
]
in
self
.
soft_macro_indices
:
# sink mod key
for
sink_pin_name
in
driver_pin
.
get_sink
()[
mod_k
]:
sink_pin_idx
=
self
.
mod_name_to_indices
[
sink_pin_name
]
# pin_i_idx: MACRO
# pin_j_idx: macro
i_dispx
,
i_dispy
,
j_dispx
,
j_dispy
=
self
.
__attractive_force
(
io_factor
=
0
,
attract_factor
=
0
,
pin_i_idx
=
driver_pin_idx
,
pin_j_idx
=
sink_pin_idx
,
i
=
i
)
add_displace
(
self
.
mod_name_to_indices
[
mod_k
],
j_dispx
,
j_dispy
)
# For Port
if
driver_pin_idx
in
self
.
port_indices
and
driver_pin
.
get_sink
():
for
mod_k
in
driver_pin
.
get_sink
()
.
keys
():
# only if sink is a soft macro
if
self
.
mod_name_to_indices
[
mod_k
]
in
self
.
soft_macro_pin_indices
:
# sink mod key
for
sink_pin_name
in
driver_pin
.
get_sink
()[
mod_k
]:
sink_pin_idx
=
self
.
mod_name_to_indices
[
sink_pin_name
]
self
.
__attractive_force
(
io_factor
=
0
,
attract_factor
=
0
,
pin_i_idx
=
driver_pin_idx
,
pin_j_idx
=
sink_pin_idx
)
soft_macro_disp
[
mod_idx
][
0
]
=
(
soft_macro_disp
[
mod_idx
][
0
]
/
max_x_disp
)
*
max_displacement
if
max_y_disp
>
0.0
:
for
mod_idx
in
self
.
soft_macro_indices
:
soft_macro_disp
[
mod_idx
][
1
]
=
(
soft_macro_disp
[
mod_idx
][
1
]
/
max_y_disp
)
*
max_displacement
for
mod_idx
in
self
.
soft_macro_indices
:
update_location
(
mod_idx
,
soft_macro_disp
[
mod_idx
][
0
],
soft_macro_disp
[
mod_idx
][
1
])
def
checkPinRelativePos
(
pin_u
,
pin_v
):
ux
,
uy
=
self
.
__get_pin_position
(
pin_u
)
vx
,
vy
=
self
.
__get_pin_position
(
pin_v
)
return
-
1.0
*
(
ux
-
vx
),
-
1.0
*
(
uy
-
vy
)
def
check_if_pin_close
(
pin_u
,
pin_v
):
ux
,
uy
=
self
.
__get_pin_position
(
pin_u
)
vx
,
vy
=
self
.
__get_pin_position
(
pin_v
)
move_x
=
True
move_y
=
True
# needs to be determined
dist_thre
=
1
for
mod_idx
in
soft_macro_disp
.
keys
()
:
# push all the macros to the nearest center of gridcell
if
abs
(
ux
-
uy
)
<=
dist_thre
:
move_x
=
False
update_location
(
mod_idx
,
*
soft_macro_disp
[
mod_idx
])
# Moved to here to save a for loop
# Based on our understanding, the stdcell clusters can be placed
# at any place in the canvas instead of the center of gridcells
self
.
__boundary_check
(
mod_idx
)
if
abs
(
vx
-
vy
)
<=
dist_thre
:
move_y
=
False
return
move_x
,
move_y
def
calcRepulsiveForce
(
repel_factor
,
max_displacement
):
macro_list
=
sorted
(
self
.
hard_macro_indices
+
self
.
soft_macro_indices
)
for
i
in
range
(
len
(
macro_list
)):
mod_u_idx
=
macro_list
[
i
]
for
j
in
range
(
i
+
1
,
len
(
macro_list
)):
mod_v_idx
=
macro_list
[
j
]
# if not self.__ifOverlap(mod_u_idx, mod_v_idx):
# # if not overlapping, dont exert force
# continue
x_d
,
y_d
=
_check_overlap
(
mod_u_idx
,
mod_v_idx
)
x_disp
=
0.0
y_disp
=
0.0
# print("debugging overlap: ", x_d, y_d)
# No overlap
if
x_d
==
None
:
x_disp
=
0.0
else
:
# x_disp = repel_factor * 1.0 / x_d
x_disp
=
repel_factor
*
1.0
*
max_displacement
*
x_d
# No overlap
if
y_d
==
None
:
y_disp
=
0.0
else
:
# y_disp = repel_factor * 1.0 / y_d
y_disp
=
repel_factor
*
1.0
*
max_displacement
*
y_d
# print("debugging: ", x_disp, y_disp)
add_displace
(
mod_u_idx
,
x_disp
,
y_disp
)
add_displace
(
mod_v_idx
,
-
1.0
*
x_disp
,
-
1.0
*
y_disp
)
def
calcAttractiveForce
(
attract_factor
,
io_factor
,
max_displacement
):
for
driver_pin_name
in
self
.
nets
.
keys
():
# extract driver pin
driver_pin_idx
=
self
.
mod_name_to_indices
[
driver_pin_name
]
driver_pin
=
self
.
modules_w_pins
[
driver_pin_idx
]
# extract driver macro
driver_macro_idx
=
self
.
get_ref_node_id
(
driver_pin_idx
)
# extract net weight
weight_factor
=
driver_pin
.
get_weight
()
for
sink_pin_name
in
self
.
nets
[
driver_pin_name
]:
sink_pin_idx
=
self
.
mod_name_to_indices
[
sink_pin_name
]
sink_macro_idx
=
self
.
get_ref_node_id
(
sink_pin_idx
)
# compute directional vector
x_d
,
y_d
=
checkPinRelativePos
(
driver_pin_idx
,
sink_pin_idx
)
# if connection has port
if
sink_pin_idx
in
self
.
port_indices
or
driver_pin_idx
in
self
.
port_indices
:
force
=
weight_factor
*
io_factor
*
attract_factor
else
:
force
=
weight_factor
*
attract_factor
# only move when pin are not too close
# move_x, move_y = check_if_pin_close(driver_pin_idx, sink_pin_idx)
# x_disp = 0.0 if not move_x else force * x_d
# y_disp = 0.0 if not move_y else force * y_d
x_disp
=
force
*
x_d
y_disp
=
force
*
y_d
# add displacement to driver/sink pin
add_displace
(
driver_macro_idx
,
x_disp
,
y_disp
)
add_displace
(
sink_macro_idx
,
-
1.0
*
x_disp
,
-
1.0
*
y_disp
)
if
use_current_loc
==
False
:
self
.
__initialization
()
for
i
in
range
(
len
(
num_steps
)):
if
verbose
:
print
(
"[OPTIMIZING STDCELs] at num_step {}"
.
format
(
i
))
attractive_factor
=
attract_factor
[
i
]
repulsive_factor
=
repel_factor
[
i
]
num_step
=
num_steps
[
i
]
max_displacement
=
max_move_distance
[
i
]
for
j
in
range
(
num_step
):
if
verbose
:
print
(
"[INFO] number of step {}"
.
format
(
j
))
move_soft_macros
(
attractive_factor
,
repulsive_factor
,
io_factor
,
max_displacement
)
def
optimize_stdcells
(
self
,
use_current_loc
,
move_stdcells
,
move_macros
,
log_scale_conns
,
use_sizes
,
io_factor
,
num_steps
,
max_move_distance
,
attract_factor
,
repel_factor
):
# initialize the position for all the macros and stdcell clusters
# YW: here I will ignore centering Macros since CT placement does that
if
not
use_current_loc
:
for
mod_idx
in
self
.
soft_macro_indices
:
self
.
__centralize_soft_macro
(
mod_id
=
mod_idx
)
for
epoch_id
,
iterations
in
enumerate
(
num_steps
):
logging
.
info
(
"#[OPTIMIZING STDCELs] at num_step {}:"
.
format
(
str
(
epoch_id
)))
print
(
"[INFO] max_displaccment = "
,
max_move_distance
[
epoch_id
])
print
(
"[INFO] attractive_factor = "
,
attract_factor
[
epoch_id
])
print
(
"[INFO] repulsive_factor = "
,
repel_factor
[
epoch_id
])
print
(
"[INFO] io_factor = "
,
io_factor
)
print
(
"[INFO] number of iteration = "
,
iterations
)
for
iter
in
range
(
iterations
):
logging
.
info
(
"# iteration {}:"
.
format
(
str
(
iter
)))
self
.
__fd_placement
(
io_factor
=
io_factor
,
max_displacement
=
max_move_distance
[
epoch_id
],
attract_factor
=
attract_factor
[
epoch_id
],
repel_factor
=
repel_factor
[
epoch_id
],
use_current_loc
=
use_current_loc
,
i
=
iter
)
self
.
save_placement
(
'epoch_{}.plc'
.
format
(
str
(
epoch_id
)))
self
.
__fd_placement
(
io_factor
,
num_steps
,
max_move_distance
,
attract_factor
,
repel_factor
,
use_current_loc
,
verbose
=
True
)
# Board Entity Definition
class
Port
:
...
...
@@ -2826,6 +2913,9 @@ class PlacementCost(object):
def
get_width
(
self
):
return
0
def
get_weight
(
self
):
return
1.0
def
add_connection
(
self
,
module_name
):
# NOTE: assume PORT names does not contain slash
ifPORT
=
False
...
...
@@ -3059,9 +3149,6 @@ class PlacementCost(object):
def
get_sink
(
self
):
return
self
.
sink
def
get_weight
(
self
):
return
self
.
weight
def
get_type
(
self
):
return
"MACRO_PIN"
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment