290 lines
11 KiB
Python
290 lines
11 KiB
Python
import numpy as np
|
|
import os
|
|
from operator import itemgetter
|
|
from itertools import combinations
|
|
|
|
import sys
|
|
if os.path.exists('benchmark/ariane'):
|
|
sys.path.append('benchmark/ariane')
|
|
from ariane.read_info import get_netlist_info_dict
|
|
from place_db_proto import get_node_info
|
|
from place_db_proto import get_net_info
|
|
|
|
|
|
def read_node_file(fopen, benchmark):
|
|
node_info = {}
|
|
node_info_raw_id_name ={}
|
|
port_info = {}
|
|
node_cnt = 0
|
|
for line in fopen.readlines():
|
|
if not line.startswith("\t") and not line.startswith(" "):
|
|
continue
|
|
line = line.strip().split()
|
|
if line[-1] != "terminal":
|
|
continue
|
|
node_name = line[0]
|
|
x = int(line[1])
|
|
y = int(line[2])
|
|
node_info[node_name] = {"id": node_cnt, "x": x , "y": y }
|
|
node_info_raw_id_name[node_cnt] = node_name
|
|
node_cnt += 1
|
|
|
|
print("len node_info", len(node_info))
|
|
return node_info, node_info_raw_id_name, port_info
|
|
|
|
|
|
def read_net_file(fopen, node_info):
|
|
net_info = {}
|
|
net_name = None
|
|
net_cnt = 0
|
|
for line in fopen.readlines():
|
|
if not line.startswith("\t") and not line.startswith(" ") and \
|
|
not line.startswith("NetDegree"):
|
|
continue
|
|
line = line.strip().split()
|
|
if line[0] == "NetDegree":
|
|
net_name = line[-1]
|
|
else:
|
|
node_name = line[0]
|
|
if node_name in node_info:
|
|
if not net_name in net_info:
|
|
net_info[net_name] = {}
|
|
net_info[net_name]["nodes"] = {}
|
|
net_info[net_name]["ports"] = {}
|
|
if not node_name.startswith("p") and not node_name in net_info[net_name]["nodes"]:
|
|
x_offset = float(line[-2])
|
|
y_offset = float(line[-1])
|
|
net_info[net_name]["nodes"][node_name] = {}
|
|
net_info[net_name]["nodes"][node_name] = {"x_offset": x_offset, "y_offset": y_offset}
|
|
elif node_name.startswith("p") and node_name in net_info[net_name]["ports"]:
|
|
x_offset = float(line[-2])
|
|
y_offset = float(line[-1])
|
|
net_info[net_name]["ports"][node_name] = {}
|
|
net_info[net_name]["ports"][node_name] = {"x_offset": x_offset, "y_offset": y_offset}
|
|
for net_name in list(net_info.keys()):
|
|
if len(net_info[net_name]["nodes"]) <= 1:
|
|
net_info.pop(net_name)
|
|
for net_name in net_info:
|
|
net_info[net_name]['id'] = net_cnt
|
|
net_cnt += 1
|
|
print("adjust net size = {}".format(len(net_info)))
|
|
return net_info
|
|
|
|
|
|
def get_comp_hpwl_dict(node_info, net_info):
|
|
comp_hpwl_dict = {}
|
|
for net_name in net_info:
|
|
max_idx = 0
|
|
for node_name in net_info[net_name]["nodes"]:
|
|
max_idx = max(max_idx, node_info[node_name]["id"])
|
|
if not max_idx in comp_hpwl_dict:
|
|
comp_hpwl_dict[max_idx] = []
|
|
comp_hpwl_dict[max_idx].append(net_name)
|
|
return comp_hpwl_dict
|
|
|
|
|
|
def get_node_to_net_dict(node_info, net_info):
|
|
node_to_net_dict = {}
|
|
for node_name in node_info:
|
|
node_to_net_dict[node_name] = set()
|
|
for net_name in net_info:
|
|
for node_name in net_info[net_name]["nodes"]:
|
|
node_to_net_dict[node_name].add(net_name)
|
|
return node_to_net_dict
|
|
|
|
|
|
def get_port_to_net_dict(port_info, net_info):
|
|
port_to_net_dict = {}
|
|
for port_name in port_info:
|
|
port_to_net_dict[port_name] = set()
|
|
for net_name in net_info:
|
|
for port_name in net_info[net_name]["ports"]:
|
|
port_to_net_dict[port_name].add(net_name)
|
|
return port_to_net_dict
|
|
|
|
|
|
def read_pl_file(fopen, node_info):
|
|
max_height = 0
|
|
max_width = 0
|
|
for line in fopen.readlines():
|
|
if not line.startswith('o'):
|
|
continue
|
|
line = line.strip().split()
|
|
node_name = line[0]
|
|
if not node_name in node_info:
|
|
continue
|
|
place_x = int(line[1])
|
|
place_y = int(line[2])
|
|
max_height = max(max_height, node_info[node_name]["x"] + place_x)
|
|
max_width = max(max_width, node_info[node_name]["y"] + place_y)
|
|
node_info[node_name]["raw_x"] = place_x
|
|
node_info[node_name]["raw_y"] = place_y
|
|
return max(max_height, max_width), max(max_height, max_width)
|
|
|
|
|
|
def read_scl_file(fopen, benchmark):
|
|
assert "ibm" in benchmark
|
|
for line in fopen.readlines():
|
|
if not "Numsites" in line:
|
|
continue
|
|
line = line.strip().split()
|
|
max_height = int(line[-1])
|
|
break
|
|
return max_height, max_height
|
|
|
|
|
|
def get_node_id_to_name(node_info, node_to_net_dict):
|
|
node_name_and_num = []
|
|
for node_name in node_info:
|
|
node_name_and_num.append((node_name, len(node_to_net_dict[node_name])))
|
|
node_name_and_num = sorted(node_name_and_num, key=itemgetter(1), reverse = True)
|
|
print("node_name_and_num", node_name_and_num)
|
|
node_id_to_name = [node_name for node_name, _ in node_name_and_num]
|
|
for i, node_name in enumerate(node_id_to_name):
|
|
node_info[node_name]["id"] = i
|
|
return node_id_to_name
|
|
|
|
|
|
def get_node_id_to_name_topology(node_info, node_to_net_dict, net_info, benchmark):
|
|
node_id_to_name = []
|
|
adjacency = {}
|
|
for net_name in net_info:
|
|
for node_name_1, node_name_2 in list(combinations(net_info[net_name]['nodes'],2)):
|
|
if node_name_1 not in adjacency:
|
|
adjacency[node_name_1] = set()
|
|
if node_name_2 not in adjacency:
|
|
adjacency[node_name_2] = set()
|
|
adjacency[node_name_1].add(node_name_2)
|
|
adjacency[node_name_2].add(node_name_1)
|
|
|
|
visited_node = set()
|
|
|
|
node_net_num = {}
|
|
for node_name in node_info:
|
|
node_net_num[node_name] = len(node_to_net_dict[node_name])
|
|
|
|
node_net_num_fea= {}
|
|
node_net_num_max = max(node_net_num.values())
|
|
print("node_net_num_max", node_net_num_max)
|
|
for node_name in node_info:
|
|
node_net_num_fea[node_name] = node_net_num[node_name]/node_net_num_max
|
|
|
|
node_area_fea = {}
|
|
node_area_max_node = max(node_info, key = lambda x : node_info[x]['x'] * node_info[x]['y'])
|
|
node_area_max = node_info[node_area_max_node]['x'] * node_info[node_area_max_node]['y']
|
|
print("node_area_max = {}".format(node_area_max))
|
|
for node_name in node_info:
|
|
node_area_fea[node_name] = node_info[node_name]['x'] * node_info[node_name]['y'] / node_area_max
|
|
|
|
if "V" in node_info:
|
|
add_node = "V"
|
|
visited_node.add(add_node)
|
|
node_id_to_name.append((add_node, node_net_num[add_node]))
|
|
node_net_num.pop(add_node)
|
|
|
|
add_node = max(node_net_num, key = lambda v: node_net_num[v])
|
|
visited_node.add(add_node)
|
|
node_id_to_name.append((add_node, node_net_num[add_node]))
|
|
node_net_num.pop(add_node)
|
|
|
|
while len(node_id_to_name) < len(node_info):
|
|
candidates = {}
|
|
for node_name in visited_node:
|
|
if node_name not in adjacency:
|
|
continue
|
|
for node_name_2 in adjacency[node_name]:
|
|
if node_name_2 in visited_node:
|
|
continue
|
|
if node_name_2 not in candidates:
|
|
candidates[node_name_2] = 0
|
|
candidates[node_name_2] += 1
|
|
for node_name in node_info:
|
|
if node_name not in candidates and node_name not in visited_node:
|
|
candidates[node_name] = 0
|
|
if len(candidates) > 0:
|
|
if benchmark != 'ariane':
|
|
add_node = max(candidates, key = lambda v: candidates[v]*1 + node_net_num[v]*1000 +\
|
|
node_info[v]['x']*node_info[v]['y'] * 1 +int(hash(v)%10000)*1e-6)
|
|
else:
|
|
add_node = max(candidates, key = lambda v: candidates[v]*30000 + node_net_num[v]*1000 +\
|
|
node_info[v]['x']*node_info[v]['y']*1 +int(hash(v)%10000)*1e-6)
|
|
else:
|
|
add_node = max(node_net_num, key = lambda v: node_net_num[v]*1000 + node_info[v]['x']*node_info[v]['y']*1)
|
|
|
|
visited_node.add(add_node)
|
|
node_id_to_name.append((add_node, node_net_num[add_node]))
|
|
node_net_num.pop(add_node)
|
|
for i, (node_name, _) in enumerate(node_id_to_name):
|
|
node_info[node_name]["id"] = i
|
|
print("node_id_to_name")
|
|
print(node_id_to_name)
|
|
node_id_to_name_res = [x for x, _ in node_id_to_name]
|
|
return node_id_to_name_res
|
|
|
|
|
|
def get_pin_cnt(net_info):
|
|
pin_cnt = 0
|
|
for net_name in net_info:
|
|
pin_cnt += len(net_info[net_name]["nodes"])
|
|
return pin_cnt
|
|
|
|
|
|
def get_total_area(node_info):
|
|
area = 0
|
|
for node_name in node_info:
|
|
area += node_info[node_name]["x"] * node_info[node_name]["y"]
|
|
return area
|
|
|
|
|
|
class PlaceDB():
|
|
def __init__(self, benchmark = "adaptec1"):
|
|
self.benchmark = benchmark
|
|
if benchmark == "ariane":
|
|
path = benchmark + '/netlist.pb.txt'
|
|
pbtxt = get_netlist_info_dict(path)
|
|
self.node_info, self.node_info_raw_id_name = get_node_info(pbtxt)
|
|
self.node_cnt = len(self.node_info)
|
|
self.net_info, self.port_info = get_net_info(pbtxt)
|
|
self.net_cnt = len(self.net_info)
|
|
self.max_height, self.max_width = 357, 357
|
|
self.port_to_net_dict = get_port_to_net_dict(self.port_info, self.net_info)
|
|
else:
|
|
assert os.path.exists(os.path.join("benchmark", benchmark))
|
|
node_file = open(os.path.join("benchmark", benchmark, benchmark+".nodes"), "r")
|
|
self.node_info, self.node_info_raw_id_name, self.port_info = read_node_file(node_file, benchmark)
|
|
pl_file = open(os.path.join("benchmark", benchmark, benchmark+".pl"), "r")
|
|
self.node_cnt = len(self.node_info)
|
|
node_file.close()
|
|
net_file = open(os.path.join("benchmark", benchmark, benchmark+".nets"), "r")
|
|
self.net_info = read_net_file(net_file, self.node_info)
|
|
self.net_cnt = len(self.net_info)
|
|
net_file.close()
|
|
pl_file = open(os.path.join("benchmark", benchmark, benchmark+".pl"), "r")
|
|
self.max_height, self.max_width = read_pl_file(pl_file, self.node_info)
|
|
pl_file.close()
|
|
if not "ibm" in benchmark:
|
|
self.port_to_net_dict = {}
|
|
else:
|
|
self.port_to_net_dict = get_port_to_net_dict(self.port_info, self.net_info)
|
|
scl_file = open(os.path.join("benchmark", benchmark, benchmark+".scl"), "r")
|
|
self.max_height, self.max_width = read_scl_file(scl_file, benchmark)
|
|
|
|
self.node_to_net_dict = get_node_to_net_dict(self.node_info, self.net_info)
|
|
self.node_id_to_name = get_node_id_to_name_topology(self.node_info, self.node_to_net_dict, self.net_info, self.benchmark)
|
|
self.node_name_to_id = dict((t, i) for i, t in enumerate(self.node_id_to_name))
|
|
|
|
def debug_str(self):
|
|
print("node_cnt = {}".format(len(self.node_info)))
|
|
print("net_cnt = {}".format(len(self.net_info)))
|
|
print("max_height = {}".format(self.max_height))
|
|
print("max_width = {}".format(self.max_width))
|
|
print("pin_cnt = {}".format(get_pin_cnt(self.net_info)))
|
|
print("port_cnt = {}".format(len(self.port_info)))
|
|
print("area_ratio = {}".format(get_total_area(self.node_info)/(self.max_height*self.max_height)))
|
|
|
|
|
|
if __name__ == "__main__":
|
|
placedb = PlaceDB("adaptec1")
|
|
placedb.debug_str()
|
|
|