Commit 46970f7b by Dinple

update

parent a3650a41
......@@ -74,15 +74,18 @@ class PlacementCost(object):
# All modules look-up table
self.modules = []
self.modules_w_pins = []
# modules to index look-up table
self.indices_to_mod_name = {}
self.mod_name_to_indices = {}
# indices storage
self.port_indices = []
self.hard_macro_indices = []
self.hard_macro_pin_indices = []
self.soft_macro_indices = []
self.soft_macro_pin_indices = []
# macro to pins look-up table: [MACRO_NAME] => [PIN_NAME]
self.hard_macros_to_inpins = {}
self.soft_macros_to_inpins = {}
......@@ -90,7 +93,7 @@ class PlacementCost(object):
# Placed macro
self.placed_macro = []
# unknown
# not used
self.use_incremental_cost = False
# blockage
self.blockages = []
......@@ -100,11 +103,12 @@ class PlacementCost(object):
# default canvas width/height based on cell area
self.width = math.sqrt(self.get_area()/0.6)
self.height = math.sqrt(self.get_area()/0.6)
# default gridding
self.grid_col = 10
self.grid_row = 10
# initialize congestion map
# TODO recompute after new gridding
self.V_routing_cong = [0] * (self.grid_col * self.grid_row)
self.H_routing_cong = [0] * (self.grid_col * self.grid_row)
self.V_macro_routing_cong = [0] * (self.grid_col * self.grid_row)
......@@ -112,6 +116,7 @@ class PlacementCost(object):
# initial grid mask, flatten before output
self.node_mask = np.array([1] * (self.grid_col * self.grid_row))\
.reshape(self.grid_row, self.grid_col)
# store module/component count
self.ports_cnt = len(self.port_indices)
self.hard_macro_cnt = len(self.hard_macro_indices)
......@@ -119,6 +124,7 @@ class PlacementCost(object):
self.soft_macros_cnt = len(self.soft_macro_indices)
self.soft_macro_pins_cnt = len(self.soft_macro_pin_indices)
self.module_cnt = self.hard_macro_cnt + self.soft_macros_cnt + self.ports_cnt
# assert module and pin count are correct
assert (len(self.modules)) == self.module_cnt
assert (len(self.modules_w_pins) - \
......@@ -136,7 +142,7 @@ class PlacementCost(object):
def __read_protobuf(self):
"""
Protobuf Netlist Parser
private function: Protobuf Netlist Parser
"""
with open(self.netlist_file) as fp:
line = fp.readline()
......@@ -168,10 +174,10 @@ class PlacementCost(object):
# retrieve node name
if line_item[0] == 'name':
node_name = line_item[1]
# skip metadata header
if node_name == "__metadata__":
pass
else:
# print(node_name)
node_cnt += 1
else:
node_name = 'N/A name'
......@@ -237,19 +243,20 @@ class PlacementCost(object):
line_item = re.findall(r'\w+', line)
if node_name == "__metadata__":
logging.info('[NETLIST PARSER INFO] skipping invalid net input')
# skipping metadata header
logging.info('[INFO NETLIST PARSER] skipping invalid net input')
elif attr_dict['type'][1] == 'macro':
# soft macro
# check if all required information is obtained
try:
assert 'x' in attr_dict.keys()
except AssertionError:
logging.warning('[NETLIST PARSER ERROR] x is not defined')
logging.warning('[ERROR NETLIST PARSER] x is not defined')
try:
assert 'y' in attr_dict.keys()
except AssertionError:
logging.warning('[NETLIST PARSER ERROR] y is not defined')
logging.warning('[ERROR NETLIST PARSER] y is not defined')
soft_macro = self.SoftMacro(name=node_name, width=attr_dict['width'][1],
height = attr_dict['height'][1],
......@@ -272,16 +279,18 @@ class PlacementCost(object):
y = attr_dict['y'][1],
macro_name = attr_dict['macro_name'][1])
if 'weight' in attr_dict.keys():
soft_macro_pin.set_weight(float(attr_dict['weight'][1]))
# if pin has net info
if input_list:
# net count should be factored by net weight
if 'weight' in attr_dict.keys():
self.net_cnt += 1 * float(attr_dict['weight'][1])
else:
self.net_cnt += 1
soft_macro_pin.add_sinks(input_list)
if 'weight' in attr_dict.keys():
soft_macro_pin.set_weight(float(attr_dict['weight'][1]))
self.modules_w_pins.append(soft_macro_pin)
# mapping node_name ==> node idx
self.mod_name_to_indices[node_name] = node_cnt-1
......@@ -326,10 +335,13 @@ class PlacementCost(object):
y_offset = attr_dict['y_offset'][1],
macro_name = attr_dict['macro_name'][1])
# if net weight is defined, set weight
if 'weight' in attr_dict.keys():
hard_macro_pin.set_weight(float(attr_dict['weight'][1]))
# if pin has net info
if input_list:
# net count should be factored by net weight
if 'weight' in attr_dict.keys():
self.net_cnt += 1 * float(attr_dict['weight'][1])
else:
......@@ -359,6 +371,7 @@ class PlacementCost(object):
y = attr_dict['y'][1],
side = attr_dict['side'][1])
# if pin has net info
if input_list:
self.net_cnt += 1
port.add_sinks(input_list)
......@@ -537,7 +550,7 @@ class PlacementCost(object):
traceback.print_tb(tb)
tb_info = traceback.extract_tb(tb)
_, line, _, text = tb_info[-1]
print('[NETLIST/PLC MISMATCH ERROR] at line {} in statement {}'\
print('[ERROR NETLIST/PLC MISMATCH] at line {} in statement {}'\
.format(line, text))
exit(1)
......@@ -547,7 +560,7 @@ class PlacementCost(object):
self.hard_macro_indices +\
self.soft_macro_indices) == list(info_dict['node_plc'].keys())
except AssertionError:
print('[PLC INDICES MISMATCH ERROR]', len(sorted(self.port_indices +\
print('[ERROR PLC INDICES MISMATCH]', len(sorted(self.port_indices +\
self.hard_macro_indices +\
self.soft_macro_indices)), len(list(info_dict['node_plc'].keys())))
exit(1)
......@@ -560,7 +573,7 @@ class PlacementCost(object):
mod_orient = info_dict['node_plc'][mod_idx][2]
mod_ifFixed = int(info_dict['node_plc'][mod_idx][3])
except Exception as e:
print('[PLC PARSER ERROR] %s' % str(e))
print('[ERROR PLC PARSER] %s' % str(e))
#TODO ValueError: Error in calling RestorePlacement with ('./Plc_client/test/ariane/initial.plc',): Can't place macro i_ariane/i_frontend/i_icache/sram_block_3__tag_sram/mem/mem_inst_mem_256x45_256x16_0x0 at (341.75, 8.8835). Exceeds the boundaries of the placement area..
......@@ -665,8 +678,10 @@ class PlacementCost(object):
def __get_pin_position(self, pin_idx):
"""
private function for getting pin location
* PORT = its own position
* MACRO PIN = ref position + offset position87654321
* HARD MACRO PIN = ref position + offset position
* SOFT MACRO PIN = ref position
"""
try:
assert (self.modules_w_pins[pin_idx].get_type() == 'MACRO_PIN' or\
......@@ -675,16 +690,15 @@ class PlacementCost(object):
print("[ERROR PIN POSITION] Not a MACRO PIN")
exit(1)
# 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:
# cannot be 'MACRO'
exit(1)
# print("ref_node_idx", ref_node_idx)
ref_node = self.modules_w_pins[ref_node_idx]
ref_node_x, ref_node_y = ref_node.get_pos()
......@@ -718,10 +732,17 @@ class PlacementCost(object):
sink_idx = self.mod_name_to_indices[sink_pin]
# retrieve sink object
sink = self.modules_w_pins[sink_idx]
# only consider placed sink
ref_sink = self.modules_w_pins[self.get_ref_node_id(sink_idx)]
if not ref_sink.get_placed_flag():
continue
# retrieve location
x_coord.append(self.__get_pin_position(sink_idx)[0])
y_coord.append(self.__get_pin_position(sink_idx)[1])
elif curr_type == "MACRO_PIN":
ref_mod = self.modules_w_pins[self.get_ref_node_id(mod_idx)]
if not ref_mod.get_placed_flag():
continue
# add source position
x_coord.append(self.__get_pin_position(mod_idx)[0])
y_coord.append(self.__get_pin_position(mod_idx)[1])
......@@ -734,7 +755,6 @@ class PlacementCost(object):
# retrieve indx in modules_w_pins
input_idx = self.mod_name_to_indices[sink_name]
# retrieve location
# print(self.__get_pin_position(input_idx))
x_coord.append(self.__get_pin_position(input_idx)[0])
y_coord.append(self.__get_pin_position(input_idx)[1])
......@@ -804,8 +824,9 @@ class PlacementCost(object):
return float(sum_cong / cong_cnt)
def get_congestion_cost(self):
#return max(self.get_H_congestion_cost(), self.get_V_congestion_cost())
# TODO need to test if cong is smaller than 5
"""
Return congestion cost based on routing and macro placement
"""
if self.FLAG_UPDATE_CONGESTION:
self.get_routing()
......@@ -813,7 +834,7 @@ class PlacementCost(object):
def __get_grid_cell_location(self, x_pos, y_pos):
"""
private function for getting grid cell row/col ranging from 0...N
private function: for getting grid cell row/col ranging from 0...N
"""
self.grid_width = float(self.width/self.grid_col)
self.grid_height = float(self.height/self.grid_row)
......@@ -823,7 +844,7 @@ class PlacementCost(object):
def __get_grid_location_position(self, col:int, row:int):
"""
private function for getting x y coord from grid cell row/col
private function: for getting x y coord from grid cell row/col
"""
self.grid_width = float(self.width/self.grid_col)
self.grid_height = float(self.height/self.grid_row)
......@@ -834,7 +855,7 @@ class PlacementCost(object):
def __get_grid_cell_position(self, grid_cell_idx:int):
"""
private function for getting x y coord from grid cell row/col
private function: for getting x y coord from grid cell row/col
"""
row = grid_cell_idx // self.grid_col
col = grid_cell_idx % self.grid_col
......@@ -848,7 +869,7 @@ class PlacementCost(object):
mod_height:float
):
"""
private function for updating node mask after a placement
private function: for updating node mask after a placement
"""
row = grid_cell_idx // self.grid_col
col = grid_cell_idx % self.grid_col
......@@ -862,7 +883,7 @@ class PlacementCost(object):
def __unplace_node_mask(self, grid_cell_idx:int):
"""
private function for updating node mask after unplacing a node
private function: for updating node mask after unplacing a node
"""
row = grid_cell_idx // self.grid_col
col = grid_cell_idx % self.grid_col
......@@ -872,7 +893,7 @@ class PlacementCost(object):
def __overlap_area(self, block_i, block_j, return_pos=False):
"""
private function for computing block overlapping
private function: for computing block overlapping
"""
x_min_max = min(block_i.x_max, block_j.x_max)
x_max_min = max(block_i.x_min, block_j.x_min)
......@@ -890,7 +911,7 @@ class PlacementCost(object):
def __overlap_dist(self, block_i, block_j):
"""
private function for computing block overlapping
private function: for computing block overlapping
"""
x_diff = min(block_i.x_max, block_j.x_max) - max(block_i.x_min, block_j.x_min)
y_diff = min(block_i.y_max, block_j.y_max) - max(block_i.y_min, block_j.y_min)
......@@ -900,7 +921,7 @@ class PlacementCost(object):
def __add_module_to_grid_cells(self, mod_x, mod_y, mod_w, mod_h):
"""
private function for add module to grid cells
private function: for add module to grid cells
"""
# Two corners
ur = (mod_x + (mod_w/2), mod_y + (mod_h/2))
......@@ -1170,6 +1191,9 @@ class PlacementCost(object):
return self.hrouting_alloc, self.vrouting_alloc
def __two_pin_net_routing(self, source_gcell, node_gcells, weight):
"""
private function: Routing between 2-pin nets
"""
temp_gcell = list(node_gcells)
if temp_gcell[0] == source_gcell:
sink_gcell = temp_gcell[1]
......@@ -1196,7 +1220,10 @@ class PlacementCost(object):
col = sink_gcell[1]
self.V_routing_cong[row * self.grid_col + col] += weight
def l_routing(self, node_gcells, weight):
def __l_routing(self, node_gcells, weight):
"""
private function: L_shape routing in 3-pin nets
"""
node_gcells.sort(key = lambda x: (x[1], x[0]))
y1, x1 = node_gcells[0]
y2, x2 = node_gcells[1]
......@@ -1220,11 +1247,13 @@ class PlacementCost(object):
for row in range(min(y2, y3), max(y2, y3)):
col = x3
self.V_routing_cong[row * self.grid_col + col] += weight
return
def t_routing(self, node_gcells, weight):
def __t_routing(self, node_gcells, weight):
"""
private function: T_shape routing in 3-pin nets
"""
node_gcells.sort()
#print(node_gcells)
y1, x1 = node_gcells[0]
y2, x2 = node_gcells[1]
y3, x3 = node_gcells[2]
......@@ -1245,9 +1274,11 @@ class PlacementCost(object):
for row in range(min(y2, y3), max(y2, y3)):
col = x3
self.V_routing_cong[row * self.grid_col + col] += weight
pass
def __three_pin_net_routing(self, node_gcells, weight):
"""
private_function: Routing Scheme for 3-pin nets
"""
temp_gcell = list(node_gcells)
## Sorted based on X
temp_gcell.sort(key = lambda x: (x[1], x[0]))
......@@ -1256,12 +1287,8 @@ class PlacementCost(object):
y3, x3 = temp_gcell[2]
if x1 < x2 and x2 < x3 and min(y1, y3) < y2 and max(y1, y3) > y2:
# print('sk1')
self.l_routing(temp_gcell, weight)
return
if x2 == x3 and x1 < x2 and y1 < min(y2, y3):
# print('sk2')
self.__l_routing(temp_gcell, weight)
elif x2 == x3 and x1 < x2 and y1 < min(y2, y3):
for col_idx in range(x1,x2,1):
row = y1
col = col_idx
......@@ -1271,10 +1298,7 @@ class PlacementCost(object):
col = x2
row = row_idx
self.V_routing_cong[row * self.grid_col + col] += weight
return
if y2 == y3:
# print('sk3')
elif y2 == y3:
for col in range(x1, x2):
row = y1
self.H_routing_cong[row * self.grid_col + col] += weight
......@@ -1286,12 +1310,8 @@ class PlacementCost(object):
for row in range(min(y2, y1), max(y2, y1)):
col = x2
self.V_routing_cong[row * self.grid_col + col] += weight
return
# print('sk4')
self.t_routing(temp_gcell, weight)
return
else:
self.__t_routing(temp_gcell, weight)
def __macro_route_over_grid_cell(self, mod_x, mod_y, mod_w, mod_h):
"""
......@@ -1388,6 +1408,9 @@ class PlacementCost(object):
self.H_macro_routing_cong[r_i * self.grid_col + c_i] -= y_dist * self.hrouting_alloc
def __split_net(self, source_gcell, node_gcells):
"""
private function: Split >3 pin net into multiple two-pin nets
"""
splitted_netlist = []
for node_gcell in node_gcells:
if node_gcell != source_gcell:
......@@ -1395,14 +1418,18 @@ class PlacementCost(object):
return splitted_netlist
def get_vertical_routing_congestion(self):
# TODO: detect if we need to run
"""
Return Vertical Routing Congestion
"""
if self.FLAG_UPDATE_CONGESTION:
self.get_routing()
return self.V_routing_cong
def get_horizontal_routing_congestion(self):
# TODO: detect if we need to run
"""
Return Horizontal Routing Congestion
"""
if self.FLAG_UPDATE_CONGESTION:
self.get_routing()
......@@ -1410,7 +1437,7 @@ class PlacementCost(object):
def get_routing(self):
"""
Route between modules
H/V Routing Before Computing Routing Congestions
"""
if self.FLAG_UPDATE_CONGESTION:
self.grid_width = float(self.width/self.grid_col)
......@@ -1483,8 +1510,6 @@ class PlacementCost(object):
for curr_net in self.__split_net(source_gcell=source_gcell, node_gcells=node_gcells):
self.__two_pin_net_routing(source_gcell=source_gcell, node_gcells=curr_net, weight=weight)
# print("V_routing_cong", self.V_routing_cong)
# print("H_routing_cong", self.H_routing_cong)
# normalize routing congestion
for idx, v_gcell in enumerate(self.V_routing_cong):
self.V_routing_cong[idx] = float(v_gcell / self.grid_v_routes)
......@@ -1505,6 +1530,9 @@ class PlacementCost(object):
self.H_routing_cong = [sum(x) for x in zip(self.H_routing_cong, self.H_macro_routing_cong)]
def __smooth_routing_cong(self):
"""
Smoothing V/H Routing congestion
"""
temp_V_routing_cong = [0] * self.grid_col * self.grid_row
temp_H_routing_cong = [0] * self.grid_col * self.grid_row
......@@ -1550,65 +1578,50 @@ class PlacementCost(object):
def is_node_soft_macro(self, node_idx) -> bool:
"""
Return None or return ref_id
Return if node is a soft macro
"""
try:
return node_idx in self.soft_macro_indices
except IndexError:
print("[ERROR INDEX OUT OF RANGE] Can not process index at {}".format(node_idx))
exit(0)
exit(1)
def is_node_hard_macro(self, node_idx) -> bool:
"""
Return None or return ref_id
Return if node is a hard macro
"""
try:
return node_idx in self.hard_macro_indices
except IndexError:
print("[ERROR INDEX OUT OF RANGE] Can not process index at {}".format(node_idx))
exit(0)
exit(1)
def get_node_name(self, node_idx: int) -> str:
"""
Return node name based on given node index
"""
try:
return self.indices_to_mod_name[node_idx]
except Exception:
print("[ERROR NODE INDEX] Node not found!")
exit(1)
def _get_node_mask(self, node_idx: int, node_name: str=None) -> list:
def get_node_index(self, node_name: str) -> int:
"""
Return Grid_col x Grid_row:
1 == placable
0 == unplacable
Placement Constraint:
- center @ grid cell
- no overlapping other macro
- no OOB
Return node index based on given node name
"""
if self.FLAG_UPDATE_NODE_MASK:
self.__update_node_mask()
module = self.modules_w_pins[node_idx]
temp_node_mask = np.array([0] * (self.grid_col * self.grid_row))\
.reshape(self.grid_row, self.grid_col)
if module.get_placed_flag():
pass
else:
hor_pad, ver_pad = self.__node_pad_cell(mod_width=module.get_width(),
mod_height=module.get_height())
# row, along y-axis, height
for i in range(ver_pad, self.grid_row - ver_pad):
for j in range(hor_pad, self.grid_col - hor_pad):
cell_region = self.node_mask[i - ver_pad : i + ver_pad + 1,
j - hor_pad : j + hor_pad + 1]
if (cell_region == 1).all():
temp_node_mask[i][j] = 1
return temp_node_mask.flatten()
try:
return self.mod_name_to_indices[node_name]
except Exception:
print("[ERROR NODE NAME] Node not found!")
exit(1)
def get_node_mask(self, node_idx: int, node_name: str=None) -> list:
"""
Return node mask based on given node
All legal positions must satisfy:
- No Out-of-Bound
- No Overlapping with previously placed MACROs
"""
mod = self.modules_w_pins[node_idx]
......@@ -1629,15 +1642,10 @@ class PlacementCost(object):
self.grid_width = float(self.width/self.grid_col)
self.grid_height = float(self.height/self.grid_row)
# print(self.grid_col, self.grid_row)
# print(mod_w*mod_h)
for i in range(self.grid_row):
for j in range(self.grid_col):
# try every location
# construct block based on current module
# construct block based on current module dimenstion
temp_x = j * self.grid_width + (self.grid_width/2)
temp_y = i * self.grid_height + (self.grid_height/2)
......@@ -1650,10 +1658,9 @@ class PlacementCost(object):
# check OOB
if abs(self.__overlap_area(
block_i=canvas_block, block_j=mod_block) - (mod_w*mod_h)) > 1e-8:
# print(i, j, self.__overlap_area(
# block_i=canvas_block, block_j=mod_block))
temp_node_mask[i][j] = 0
else:
# check overlapping
for pmod_idx in self.placed_macro:
pmod = self.modules_w_pins[pmod_idx]
if not pmod.get_placed_flag():
......@@ -1668,7 +1675,7 @@ class PlacementCost(object):
x_min=p_x - (p_w/2),
y_min=p_y - (p_h/2)
)
# overlap with placed module
# if overlap with placed module
if self.__overlap_area(block_i=pmod_block, block_j=mod_block) > 0:
temp_node_mask[i][j] = 0
......@@ -1683,7 +1690,7 @@ class PlacementCost(object):
return self.modules_w_pins[node_idx].get_type()
except IndexError:
# NOTE: Google's API return NONE if out of range
print("[INDEX OUT OF RANGE WARNING] Can not process index at {}".format(node_idx))
print("[WARNING INDEX OUT OF RANGE] Can not process index at {}".format(node_idx))
return None
......@@ -1729,9 +1736,15 @@ class PlacementCost(object):
self.modules_w_pins[node_idx].set_pos(x_pos, y_pos)
def set_use_incremental_cost(self, use_incremental_cost):
"""
NOT IMPLEMENTED
"""
self.use_incremental_cost = use_incremental_cost
def get_use_incremental_cost(self):
"""
NOT IMPLEMENTED
"""
return self.use_incremental_cost
def get_macro_adjacency(self) -> list:
......@@ -1840,8 +1853,6 @@ class PlacementCost(object):
# instantiate clustered ports
for row_idx, cluster_cell in enumerate(sorted(clustered_ports, key=lambda tup: tup[1])):
# print("cluster_cell", cluster_cell)
# print("port cnt", len(clustered_ports[cluster_cell]))
# add cell location
cell_location[row_idx] = cluster_cell[0] * self.grid_col + cluster_cell[1]
......@@ -1852,7 +1863,6 @@ class PlacementCost(object):
for curr_port in clustered_ports[cluster_cell]:
# get module name
curr_port_name = curr_port.get_name()
# print("curr_port_name", curr_port_name, curr_port.get_pos())
# assuming ports only connects to macros
for col_idx, h_module_idx in enumerate(module_indices):
# col index
......@@ -1862,8 +1872,6 @@ class PlacementCost(object):
# get connected module name
h_module_name = h_module.get_name()
# print("other connections", h_module.get_connection(), curr_port_name)
if curr_port_name in h_module.get_connection():
entry += h_module.get_connection()[curr_port_name]
......@@ -2133,13 +2141,21 @@ class PlacementCost(object):
exit(1)
if not mod.get_fix_flag():
mod.set_placed_flag(True)
if node_idx in self.hard_macro_indices:
mod.set_placed_flag(False)
self.placed_macro.remove(node_idx)
# update flag
self.FLAG_UPDATE_CONGESTION = True
self.FLAG_UPDATE_DENSITY = True
# self.FLAG_UPDATE_NODE_MASK = True # placeholder
self.FLAG_UPDATE_WIRELENGTH = True
elif node_idx in self.soft_macro_indices:
mod.set_placed_flag(False)
# update flag
self.FLAG_UPDATE_CONGESTION = True
self.FLAG_UPDATE_DENSITY = True
# self.FLAG_UPDATE_NODE_MASK = True # placeholder
self.FLAG_UPDATE_WIRELENGTH = True
else:
print("[WARNING UNPLACE NODE] Trying to unplace a fixed node")
......@@ -2206,7 +2222,7 @@ class PlacementCost(object):
return self.mod_name_to_indices[pin.get_macro_name()]
return -1
def save_placement(self, filename, info):
def save_placement(self, filename, info=""):
"""
When writing out info line-by-line, add a "#" at front
"""
......
from ast import Assert
import numpy as np
import pandas as pd
import sys
......@@ -138,7 +139,7 @@ class PlacementCostTest():
self.plc_os.set_placement_grid(self.GRID_COL, self.GRID_ROW)
if self.PLC_PATH:
print("[PLC FILE FOUND] Loading info from .plc file")
print("#[PLC FILE FOUND] Loading info from .plc file")
self.plc_os.set_canvas_boundary_check(False)
self.plc_os.restore_placement(self.PLC_PATH,
ifInital=True,
......@@ -147,7 +148,7 @@ class PlacementCostTest():
self.plc.set_canvas_boundary_check(False)
self.plc.restore_placement(self.PLC_PATH)
else:
print("[PLC FILE MISSING] Using only netlist info")
print("#[PLC FILE MISSING] Using only netlist info")
try:
assert int(self.plc_os.get_area()) == int(self.plc.get_area())
......@@ -223,7 +224,7 @@ class PlacementCostTest():
self.plc_os.set_placement_grid(self.GRID_COL, self.GRID_ROW)
if self.PLC_PATH:
print("[PLC FILE FOUND] Loading info from .plc file")
print("#[PLC FILE FOUND] Loading info from .plc file")
self.plc_os.set_canvas_boundary_check(False)
self.plc_os.restore_placement(self.PLC_PATH,
ifInital=ifInital,
......@@ -246,7 +247,7 @@ class PlacementCostTest():
print("overlap_threshold default", self.plc.get_overlap_threshold())
if self.PLC_PATH:
print("[PLC FILE FOUND] Loading info from .plc file")
print("#[PLC FILE FOUND] Loading info from .plc file")
self.plc_os.set_canvas_boundary_check(False)
self.plc_os.restore_placement(self.PLC_PATH,
ifInital=True,
......@@ -255,7 +256,7 @@ class PlacementCostTest():
self.plc.set_canvas_boundary_check(False)
self.plc.restore_placement(self.PLC_PATH)
else:
print("[PLC FILE MISSING] Using only netlist info")
print("#[PLC FILE MISSING] Using only netlist info")
self.plc.set_routes_per_micron(self.RPMH, self.RPMV)
self.plc_os.set_routes_per_micron(self.RPMH, self.RPMV)
......@@ -271,12 +272,11 @@ class PlacementCostTest():
self.plc_os.set_canvas_size(self.CANVAS_WIDTH, self.CANVAS_HEIGHT)
self.plc_os.set_placement_grid(self.GRID_COL, self.GRID_ROW)
# SUBJECT TO DELETE
self.plc.make_soft_macros_square()
print(self.plc.get_wirelength())
print(self.plc_os.get_wirelength())
# self.plc.make_soft_macros_square()
# self.plc_os.make_soft_macros_square()
# TODO: [IGNORE] create_blockage must be defined BEFORE set_canvas_size and set_placement_grid in order to be considered on the canvas
# [IGNORE] create_blockage must be defined BEFORE set_canvas_size
# and set_placement_grid in order to be considered on the canvas
if False:
self.plc.create_blockage(0.0, 100.0, 300.0, 300.0, 1.0)
self.plc.create_blockage(300, 0, 500, 200, 1)
......@@ -287,15 +287,26 @@ class PlacementCostTest():
# HPWL
try:
assert int(self.plc_os.get_wirelength()) == int(
self.plc.get_wirelength())
assert int(self.plc_os.get_wirelength()) == int(self.plc.get_wirelength())
assert abs(self.plc.get_cost() - self.plc_os.get_cost()) <= 1e-3
print("#[INFO WIRELENGTH] Matched irelength cost -- GL {}, OS {}".format(
str(self.plc.get_cost()), self.plc_os.get_cost()))
except Exception as e:
print("[ERROR WIRELENGTH] Discrepancies found when computing wirelength -- GL {}, OS {}".format(
str(self.plc.get_cost()), self.plc_os.get_cost()))
exit(1)
soft_macro_indices = [
m for m in self.plc.get_macro_indices() if self.plc.is_node_soft_macro(m)
]
for mod_idx in soft_macro_indices:
self.plc_os.unplace_node(mod_idx)
self.plc.unplace_node(mod_idx)
print("GL WIRELENGTH: ", self.plc.get_wirelength())
print("OS WIRELENGTH: ", self.plc_os.get_wirelength())
# exit(1)
# self.plc_os.display_canvas(annotate=False)
# Density
try:
......@@ -392,7 +403,7 @@ class PlacementCostTest():
self.plc_os.set_placement_grid(self.GRID_COL, self.GRID_ROW)
if self.PLC_PATH:
print("[PLC FILE FOUND] Loading info from .plc file")
print("#[PLC FILE FOUND] Loading info from .plc file")
self.plc_os.set_canvas_boundary_check(False)
self.plc_os.restore_placement(self.PLC_PATH,
ifInital=True,
......@@ -401,7 +412,7 @@ class PlacementCostTest():
self.plc.set_canvas_boundary_check(False)
self.plc.restore_placement(self.PLC_PATH)
else:
print("[PLC FILE MISSING] Using only netlist info")
print("#[PLC FILE MISSING] Using only netlist info")
temp_gl_h = np.array(self.plc.get_horizontal_routing_congestion())
temp_os_h = np.array(self.plc_os.get_horizontal_routing_congestion())
......@@ -480,6 +491,7 @@ class PlacementCostTest():
assert self.PLC_PATH
except AssertionError:
print("[ERROR PLACEMENT UTIL TEST] Facilitate required .plc file")
exit(1)
self.plc_util = placement_util.create_placement_cost(
plc_client=plc_client,
......@@ -542,6 +554,7 @@ class PlacementCostTest():
except AssertionError:
print("[ERROR PLACEMENT UTIL] Saved PLC Discrepency found at line {}".format(
str(idx)))
exit(1)
# if keep plc file for detailed comparison
if not keep_save_file:
......@@ -575,7 +588,7 @@ class PlacementCostTest():
assert self.PLC_PATH
except AssertionError:
print("[ERROR OBSERVATION EXTRACTOR TEST] Facilitate required .plc file")
exit(0)
exit(1)
# Using the default edge/node
self._observation_config = observation_config.ObservationConfig(
......@@ -594,7 +607,7 @@ class PlacementCostTest():
)
if self.PLC_PATH:
print("[PLC FILE FOUND] Loading info from .plc file")
print("#[PLC FILE FOUND] Loading info from .plc file")
self.plc_util_os.set_canvas_boundary_check(False)
self.plc_util_os.restore_placement(self.PLC_PATH,
ifInital=True,
......@@ -603,7 +616,7 @@ class PlacementCostTest():
self.plc_util.set_canvas_boundary_check(False)
self.plc_util.restore_placement(self.PLC_PATH)
else:
print("[PLC FILE MISSING] Using only netlist info")
print("#[PLC FILE MISSING] Using only netlist info")
self.extractor = observation_extractor.ObservationExtractor(
plc=self.plc_util, observation_config=self._observation_config
......@@ -612,21 +625,27 @@ class PlacementCostTest():
self.extractor_os = observation_extractor.ObservationExtractor(
plc=self.plc_util_os, observation_config=self._observation_config
)
# Unplacing all the nodes b/c by default everything is placed on board at initialization
self.plc_util_os.unplace_all_nodes()
self.plc_util.unplace_all_nodes()
# Static features that are invariant across training steps
static_feature_gl = self.extractor._extract_static_features()
static_feature_os = self.extractor_os._extract_static_features()
#
for feature_gl, feature_os in zip(static_feature_gl, static_feature_os):
try:
assert (static_feature_gl[feature_gl] ==
static_feature_os[feature_os]).all()
except AssertionError:
print(
"[ERROR OBSERVATION EXTRACTOR TEST] Failing on "+str(feature_gl))
"[ERROR OBSERVATION EXTRACTOR TEST] Observation Feature Mismatch on "+str(feature_gl))
print("GL FEATURE:")
print(static_feature_gl[feature_gl])
print("OS FEATURE:")
print(static_feature_os[feature_os])
exit(0)
exit(1)
print(" ++++++++++++++++++++++++++++++++++++++++")
print(" +++ TEST OBSERVATION EXTRACTOR: PASS +++")
......@@ -660,12 +679,16 @@ 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)
# MACRO placement order
ordered_node_gl = placement_util.get_ordered_node_indices(
mode='descending_size_macro_first', plc=self.plc_util)
ordered_node_os = placement_util.get_ordered_node_indices(
mode='descending_size_macro_first', plc=self.plc_util_os)
try:
assert (np.array(ordered_node_gl) == np.array(ordered_node_os)).all()
except:
print("[ERROR PLACE NODE] Node Ordering not matching!")
# Initialize Placement
self.plc_util_os.unplace_all_nodes()
......@@ -678,8 +701,9 @@ class PlacementCostTest():
]
NODE_TO_PLACE_IDX = self._hard_macro_indices[0]
# make sure this is within grid cell range
CELL_TO_PLACE_IDX = 6
print("MASK FOR PLACING FIRST NODE:")
print("[INFO PLACE NODE] MASK FOR PLACING FIRST NODE:")
self.plc_util_os.display_canvas(annotate=False)
print("OS NODE MASK:")
print(np.flip(np.array(self.plc_util_os.get_node_mask(
......@@ -693,8 +717,9 @@ class PlacementCostTest():
# place node NODE_TO_PLACE_IDX @ position CELL_TO_PLACE_IDX
NODE_TO_PLACE_IDX = self._hard_macro_indices[1]
# make sure this is within grid cell range
CELL_TO_PLACE_IDX = 18
print("MASK FOR PLACING SECOND NODE:")
print("[INFO PLACE NODE] MASK FOR PLACING SECOND NODE:")
print("OS NODE MASK:")
print(np.flip(np.array(self.plc_util_os.get_node_mask(
NODE_TO_PLACE_IDX)).reshape(self.GRID_ROW, self.GRID_COL), axis=0))
......@@ -735,22 +760,33 @@ class PlacementCostTest():
print(np.flip(np.array(env_os._plc.get_node_mask(node_idx)).reshape(
env_os._plc.get_grid_num_columns_rows()), axis=0))
# check if node information is matching
for idx in env._plc.get_macro_indices():
if (env._plc.get_node_location(idx) != env_os._plc.get_node_location(idx)):
print("something wrong")
if abs(env._plc.get_node_width_height(idx)[0] - env_os._plc.get_node_width_height(idx)[0]) >= 1e-3:
print(idx, env._plc.get_node_width_height(idx), env_os._plc.get_node_width_height(idx))
try:
assert (env._plc.get_node_location(idx) != env_os._plc.get_node_location(idx))
except AssertionError:
print("[ERROR ENVIRONMENT TEST] Node location not matching!")
print(idx, env._plc.get_node_location(idx), env_os._plc.get_node_location(idx))
exit(1)
if abs(env._plc.get_node_width_height(idx)[1] - env_os._plc.get_node_width_height(idx)[1]) >= 1e-3:
try:
assert abs(env._plc.get_node_width_height(idx)[0] - env_os._plc.get_node_width_height(idx)[0]) >= 1e-3 and \
abs(env._plc.get_node_width_height(idx)[1] - env_os._plc.get_node_width_height(idx)[1]) >= 1e-3
except AssertionError:
print("[ERROR ENVIRONMENT TEST] Node dimension not matching!")
print(idx, env._plc.get_node_width_height(idx), env_os._plc.get_node_width_height(idx))
exit(1)
env_os._plc.display_canvas(annotate=False)
exit(1)
# check observation state
obs_gl = env._get_obs()
obs_os = env_os._get_obs()
env_os.reset()
env.reset()
# env_os.reset()
# env.reset()
for feature_gl, feature_os in zip(obs_gl, obs_os):
try:
......@@ -758,6 +794,7 @@ class PlacementCostTest():
except AssertionError:
print("[ERROR ENVIRONMENT TEST] Failing on "+str(feature_gl))
print(np.where(obs_gl[feature_gl] != obs_os[feature_os]))
exit(1)
print(" ++++++++++++++++++++++++++++++")
print(" +++ TEST ENVIRONMENT: PASS +++")
......@@ -817,15 +854,18 @@ def main(args):
marv=args.marv,
smooth=args.smooth)
"""
Uncomment any available tests
"""
# PCT.test_metadata()
# PCT.test_proxy_cost()
PCT.test_proxy_cost()
# PCT.test_proxy_congestion()
# PCT.test_placement_util(keep_save_file=False)
# PCT.test_place_node()
# PCT.test_miscellaneous()
# PCT.test_observation_extractor()
# PCT.view_canvas()
# PCT.test_proxy_congestion()
PCT.test_environment()
# PCT.test_environment()
if __name__ == '__main__':
......
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