Unverified Commit 05951de7 by Yucheng Wang Committed by GitHub

Add FDPlacer as Zhiang's implementation

parent f9ba641c
...@@ -55,6 +55,10 @@ class PlacementCost(object): ...@@ -55,6 +55,10 @@ class PlacementCost(object):
# Check netlist existance # Check netlist existance
assert os.path.isfile(self.netlist_file) assert os.path.isfile(self.netlist_file)
# [Experimental] Net Data Structure
# nets[driver] => [list of sinks]
self.nets = {}
# Set meta information # Set meta information
self.init_plc = None self.init_plc = None
self.project_name = "circuit_training" self.project_name = "circuit_training"
...@@ -294,6 +298,8 @@ class PlacementCost(object): ...@@ -294,6 +298,8 @@ class PlacementCost(object):
else: else:
self.net_cnt += 1 self.net_cnt += 1
soft_macro_pin.add_sinks(input_list) soft_macro_pin.add_sinks(input_list)
# add net
self.nets[node_name] = input_list
self.modules_w_pins.append(soft_macro_pin) self.modules_w_pins.append(soft_macro_pin)
# mapping node_name ==> node idx # mapping node_name ==> node idx
...@@ -351,6 +357,7 @@ class PlacementCost(object): ...@@ -351,6 +357,7 @@ class PlacementCost(object):
else: else:
self.net_cnt += 1 self.net_cnt += 1
hard_macro_pin.add_sinks(input_list) hard_macro_pin.add_sinks(input_list)
self.nets[node_name] = input_list
self.modules_w_pins.append(hard_macro_pin) self.modules_w_pins.append(hard_macro_pin)
# mapping node_name ==> node idx # mapping node_name ==> node idx
...@@ -381,6 +388,7 @@ class PlacementCost(object): ...@@ -381,6 +388,7 @@ class PlacementCost(object):
port.add_sinks(input_list) port.add_sinks(input_list)
# ports does not have pins so update connection immediately # ports does not have pins so update connection immediately
port.add_connections(input_list) port.add_connections(input_list)
self.nets[node_name] = input_list
self.modules_w_pins.append(port) self.modules_w_pins.append(port)
self.modules.append(port) self.modules.append(port)
...@@ -663,6 +671,9 @@ class PlacementCost(object): ...@@ -663,6 +671,9 @@ class PlacementCost(object):
""" """
Compute wirelength cost from wirelength Compute wirelength cost from wirelength
""" """
if self.net_cnt == 0:
self.net_cnt = 1
if self.FLAG_UPDATE_WIRELENGTH: if self.FLAG_UPDATE_WIRELENGTH:
self.FLAG_UPDATE_WIRELENGTH = False self.FLAG_UPDATE_WIRELENGTH = False
return self.get_wirelength() / ((self.get_canvas_width_height()[0]\ return self.get_wirelength() / ((self.get_canvas_width_height()[0]\
...@@ -707,13 +718,14 @@ class PlacementCost(object): ...@@ -707,13 +718,14 @@ class PlacementCost(object):
print("[ERROR PIN POSITION] Not a MACRO PIN", self.modules_w_pins[pin_idx].get_name()) print("[ERROR PIN POSITION] Not a MACRO PIN", self.modules_w_pins[pin_idx].get_name())
exit(1) 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 # Retrieve node that this pin instantiated on
ref_node_idx = self.get_ref_node_id(pin_idx) ref_node_idx = self.get_ref_node_id(pin_idx)
if ref_node_idx == -1: 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.") print("[ERROR PIN POSITION] Parent Node Not Found.")
exit(1) exit(1)
...@@ -730,6 +742,38 @@ class PlacementCost(object): ...@@ -730,6 +742,38 @@ class PlacementCost(object):
def get_wirelength(self) -> float: 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 Proxy HPWL computation
""" """
# NOTE: in pb.txt, netlist input count exceed certain threshold will be ommitted # NOTE: in pb.txt, netlist input count exceed certain threshold will be ommitted
...@@ -1930,9 +1974,6 @@ class PlacementCost(object): ...@@ -1930,9 +1974,6 @@ class PlacementCost(object):
return mod.get_fix_flag() return mod.get_fix_flag()
def optimize_stdcells(self):
pass
def update_node_coords(self, node_idx, x_pos, y_pos): def update_node_coords(self, node_idx, x_pos, y_pos):
""" """
Update Node location if node is 'MACRO', 'STDCELL', 'PORT' Update Node location if node is 'MACRO', 'STDCELL', 'PORT'
...@@ -2286,7 +2327,11 @@ class PlacementCost(object): ...@@ -2286,7 +2327,11 @@ class PlacementCost(object):
def get_ref_node_id(self, node_idx=-1): def get_ref_node_id(self, node_idx=-1):
""" """
ref_node_id is used for macro_pins. Refers to the macro it belongs to. 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 != -1:
if node_idx in self.soft_macro_pin_indices or node_idx in self.hard_macro_pin_indices: 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] pin = self.modules_w_pins[node_idx]
...@@ -2323,7 +2368,8 @@ class PlacementCost(object): ...@@ -2323,7 +2368,8 @@ class PlacementCost(object):
def display_canvas( self, def display_canvas( self,
annotate=True, annotate=True,
amplify=False, amplify=False,
saveName=None): saveName=None,
show=True):
""" """
Non-google function, For quick canvas view Non-google function, For quick canvas view
""" """
...@@ -2383,6 +2429,7 @@ class PlacementCost(object): ...@@ -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') # ax.annotate(mod.get_name(), mod.get_pos(), wrap=True,color='r', weight='bold', fontsize=FONT_SIZE, ha='center', va='center')
if saveName: if saveName:
plt.savefig(saveName) plt.savefig(saveName)
if show:
plt.show() plt.show()
plt.close('all') plt.close('all')
...@@ -2410,12 +2457,6 @@ class PlacementCost(object): ...@@ -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 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): 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 Calculate repulsive force between two nodes node_i, node_j
...@@ -2564,6 +2605,13 @@ class PlacementCost(object): ...@@ -2564,6 +2605,13 @@ class PlacementCost(object):
mod = self.modules_w_pins[mod_id] mod = self.modules_w_pins[mod_id]
mod.set_pos(self.width/2, self.height/2) 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): def __boundary_check(self, mod_id):
''' '''
Make sure all the clusters are placed within the canvas Make sure all the clusters are placed within the canvas
...@@ -2585,15 +2633,12 @@ class PlacementCost(object): ...@@ -2585,15 +2633,12 @@ class PlacementCost(object):
mod.set_pos(mod_x, mod_y) 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 Force-directed Placement for standard-cell clusters
''' '''
i += 1
# store x/y displacement for all soft macro disp # store x/y displacement for all soft macro disp
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): def check_OOB(mod_id, x_disp, y_disp):
mod = self.modules_w_pins[mod_id] mod = self.modules_w_pins[mod_id]
...@@ -2601,47 +2646,97 @@ class PlacementCost(object): ...@@ -2601,47 +2646,97 @@ class PlacementCost(object):
mod_height = mod.get_height() mod_height = mod.get_height()
mod_width = mod.get_width() mod_width = mod.get_width()
canvas_block = Block(x_max=self.width, # print(x_disp, y_disp, mod_x, mod_y, mod_width, mod_height)
y_max=self.height, # boundary after displacement
x_min=0, x_max = mod_x + mod_width/2 + x_disp
y_min=0) 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 # print(x_max, x_min, y_max, y_min)
mod_block = Block(x_max=mod_x + mod_width/2 + x_disp, # determine if move
y_max=mod_y + mod_height/2 + y_disp, if x_min <= 0.0 or x_max >= self.width:
x_min=mod_x - mod_width/2 + x_disp, x_disp = 0.0
y_min=mod_y - mod_height/2 + y_disp) 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 return x_disp, y_disp
# 2. if only x displacement can be used def getBBox(mod_id):
mod_block = Block(x_max=mod_x + mod_width/2 + x_disp, mod = self.modules_w_pins[mod_id]
y_max=mod_y + mod_height/2, x, y = mod.get_pos()
x_min=mod_x - mod_width/2 + x_disp, width = mod.get_width()
y_min=mod_y - mod_height/2) 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 (u_lx >= v_ux or u_ux <= v_lx or u_ly >= v_uy or u_uy <= v_ly):
if abs(self.__overlap_area(block_i=mod_block, block_j=canvas_block) - mod_height * mod_width) <= 1e-3: # no overlap
return x_disp, y_disp 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 def check_overlap(mod_u, mod_v):
mod_block = Block(x_max=mod_x + mod_width/2, u_lx, u_ly, u_ux, u_uy = getBBox(mod_u)
y_max=mod_y + mod_height/2 + y_disp, v_lx, v_ly, v_ux, v_uy = getBBox(mod_v)
x_min=mod_x - mod_width/2,
y_min=mod_y - mod_height/2 + y_disp)
# if fully containing the block on canvas if (u_lx >= v_ux or u_ux <= v_lx or u_ly >= v_uy or u_uy <= v_ly):
if abs(self.__overlap_area(block_i=mod_block, block_j=canvas_block) - mod_height * mod_width) <= 1e-3: return 1, 1
return x_disp, y_disp 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): def add_displace(mod_id, x_disp, y_disp):
''' '''
Add the displacement Add the displacement
''' '''
if mod_id in self.soft_macro_indices:
soft_macro_disp[mod_id][0] += x_disp soft_macro_disp[mod_id][0] += x_disp
soft_macro_disp[mod_id][1] += y_disp soft_macro_disp[mod_id][1] += y_disp
...@@ -2650,155 +2745,147 @@ class PlacementCost(object): ...@@ -2650,155 +2745,147 @@ class PlacementCost(object):
Update the displacement to the coordiante Update the displacement to the coordiante
''' '''
x_pos, y_pos = self.modules_w_pins[mod_id].get_pos() 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) 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) self.modules_w_pins[mod_id].set_pos(x_pos + x_disp, y_pos + y_disp)
##SOFT_SOFT REPEL############################################################################################### def move_soft_macros(attract_factor, repel_factor, io_factor, max_displacement):
# calculate the repulsive forces # map to soft macro index
# repulsive forces between stdcell clusters for mod_idx in self.soft_macro_indices:
if repel_factor != 0.0: soft_macro_disp[mod_idx] = [0.0, 0.0]
# temp storing the soft macro count calcAttractiveForce(attract_factor, io_factor, max_displacement)
xr_collection = [0] * len(self.modules_w_pins) calcRepulsiveForce(repel_factor, max_displacement)
yr_collection = [0] * len(self.modules_w_pins) max_x_disp = 0.0
max_y_disp = 0.0
# 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
for mod_idx in self.soft_macro_indices: 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) 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]))
##SOFT_HARD REPEL###############################################################################################
if repel_factor != 0.0: # normalization
# temp storing the soft macro count if max_x_disp > 0.0:
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
for mod_idx in self.soft_macro_indices: 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_macro_disp[mod_idx][0] = (soft_macro_disp[mod_idx][0] / max_x_disp) * max_displacement
if max_y_disp > 0.0:
##NET ATTRACT################################################################################################### for mod_idx in self.soft_macro_indices:
for driver_pin_idx, driver_pin in enumerate(self.modules_w_pins): soft_macro_disp[mod_idx][1] = (soft_macro_disp[mod_idx][1] / max_y_disp) * max_displacement
# print(driver_pin_idx) for mod_idx in self.soft_macro_indices:
# print(self.soft_macro_pin_indices) update_location(mod_idx, soft_macro_disp[mod_idx][0], soft_macro_disp[mod_idx][1])
# print(self.hard_macro_pin_indices)
# For soft macro def checkPinRelativePos(pin_u, pin_v):
if driver_pin_idx in self.soft_macro_pin_indices: ux, uy = self.__get_pin_position(pin_u)
# print(driver_pin.get_sink()) vx, vy = self.__get_pin_position(pin_v)
for mod_k in driver_pin.get_sink().keys(): return -1.0 * (ux - vx), -1.0 * (uy - vy)
# sink mod key
for sink_pin_name in driver_pin.get_sink()[mod_k]: def check_if_pin_close(pin_u, pin_v):
sink_pin_idx = self.mod_name_to_indices[sink_pin_name] ux, uy = self.__get_pin_position(pin_u)
self.__attractive_force(io_factor=0, attract_factor=0, pin_i_idx=driver_pin_idx, pin_j_idx=sink_pin_idx, i=i) vx, vy = self.__get_pin_position(pin_v)
# For hard macro move_x = True
if driver_pin_idx in self.hard_macro_pin_indices : move_y = True
for mod_k in driver_pin.get_sink().keys():
# only if sink is a soft macro # needs to be determined
if self.mod_name_to_indices[mod_k] in self.soft_macro_indices: dist_thre = 1
# 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)
for mod_idx in soft_macro_disp.keys(): if abs(ux - uy) <= dist_thre:
# push all the macros to the nearest center of gridcell move_x = False
update_location(mod_idx, *soft_macro_disp[mod_idx]) if abs(vx - vy) <= dist_thre:
# Moved to here to save a for loop move_y = False
# 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)
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, def optimize_stdcells(self, use_current_loc, move_stdcells, move_macros,
log_scale_conns, use_sizes, io_factor, num_steps, log_scale_conns, use_sizes, io_factor, num_steps,
max_move_distance, attract_factor, repel_factor): max_move_distance, attract_factor, repel_factor):
self.__fd_placement(io_factor, num_steps, max_move_distance, attract_factor, repel_factor, use_current_loc, verbose=True)
# 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)))
# Board Entity Definition # Board Entity Definition
class Port: class Port:
...@@ -2826,6 +2913,9 @@ class PlacementCost(object): ...@@ -2826,6 +2913,9 @@ class PlacementCost(object):
def get_width(self): def get_width(self):
return 0 return 0
def get_weight(self):
return 1.0
def add_connection(self, module_name): def add_connection(self, module_name):
# NOTE: assume PORT names does not contain slash # NOTE: assume PORT names does not contain slash
ifPORT = False ifPORT = False
...@@ -3059,9 +3149,6 @@ class PlacementCost(object): ...@@ -3059,9 +3149,6 @@ class PlacementCost(object):
def get_sink(self): def get_sink(self):
return self.sink return self.sink
def get_weight(self):
return self.weight
def get_type(self): def get_type(self):
return "MACRO_PIN" return "MACRO_PIN"
......
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