Commit f81e4bdf by lvzhengyang

build graph, and model runs

parent d689adc4
place_parser
data/asap7
*/__pycache__
*.log
......@@ -827,6 +827,7 @@ def create_graph6(data_dir, parsed_libs_dir, parsed_sdf_dir, save_dir, block_nam
# NOTE: this assume that the path has only buffers inserted,
# and each buffer has only one input and one output
delay += path.value # is it right??
arc.delay = delay
rebuild = False
if rebuild:
......@@ -865,7 +866,7 @@ def create_graph6(data_dir, parsed_libs_dir, parsed_sdf_dir, save_dir, block_nam
faninfanout[pin_id] = 1
# find primary_io_pin
types = {'inport2d', 'inport2clk', 'inport2pin', 'inport2outport'}
types = {'inport2d', 'inport2clk', 'inport2in', 'inport2outport'}
if arc.type in types:
pin_id = place_pin2id_map[arc.src]
is_primary_io_pin[pin_id] = 1
......@@ -895,17 +896,30 @@ def create_graph6(data_dir, parsed_libs_dir, parsed_sdf_dir, save_dir, block_nam
'inport2d', 'inport2clk', 'inport2in',
'q2outport', 'out2outport', 'inport2outport',
'q2in', 'out2in', 'out2d', 'q2d']
# type net_in is a reverse of net_out's src and dst
# build DGL edge types
for arc_type, types in dgl_edge_types.items():
edges[arc_type] = []
for merge_type in types:
edges[arc_type] += edges[merge_type]
# type net_in is a reverse of net_out's src and dst
edges['net_in'] = []
for edge in edges['net_out']:
edges['net_in'].append((edge[1], edge[0]))
dgl_graph = {}
for arc_type in edges:
dgl_graph[('node', arc_type, 'node')] = edges[arc_type]
g = dgl.heterograph(dgl_graph)
"""
g = dgl.heterograph({
# for training
('node', 'net_out', 'node'): edges['net_out'],
('node', 'net_in', 'node'): edges['net_in'],
('node', 'cell_out', 'node'): edges['cell_out'],
})
"""
# test
try:
......@@ -957,12 +971,171 @@ def create_graph6(data_dir, parsed_libs_dir, parsed_sdf_dir, save_dir, block_nam
######## End build DGL graph ########
######## fill data into graph ########
# node data
num_pins = pin_cnt
valid_pin_list = place_pins_list
src_pin2path_map_place = dict()
for arc in timing_graph.all_arcs:
if not arc.src in src_pin2path_map_place:
src_pin2path_map_place[arc.src] = []
src_pin2path_map_place[arc.src].append(arc)
net_delays_at_fanin = np.zeros((num_pins, 4))
for edge in edges['net_out']:
src = edge[0]
dst = edge[1]
src_pin = place_pins_list[src]
dst_pin = place_pins_list[dst]
paths = src_pin2path_map_place[src_pin]
flag = False
for path in paths:
if path.dst == dst_pin:
net_delays_at_fanin[dst] = np.maximum(path.delay, net_delays_at_fanin[dst])
flag = True
break
if not flag:
pdb.set_trace()
assert(False)
pin_loc = np.zeros((num_pins, 4))
for i in range(num_pins):
pin_name = valid_pin_list[i]
inst_name = pin_name.split('/')[0]
place_node_id = node_name2id_map[inst_name]
place_node_x = node_x[place_node_id]
place_node_y = node_y[place_node_id]
place_node_pins = node2pin_map[place_node_id]
if inst_name == pin_name: # port
assert(place_node_pins.size == 1)
place_node_pin_id = place_node_pins[0]
else:
num_node_pins = place_node_pins.size
for pi in range(num_node_pins):
place_node_pin_id = place_node_pins[pi]
place_node_pin_name = pin_names_raw[place_node_pin_id].decode()
if pin_name.split('/')[1] == place_node_pin_name:
break
place_pin_x_off = pin_offset_x[place_node_pin_id]
place_pin_y_off = pin_offset_y[place_node_pin_id]
pin_x = place_node_x + place_pin_x_off
pin_y = place_node_y + place_pin_y_off
pin_loc[i] = np.array([pin_x - xl, pin_y - yl, xh - pin_x, yh - pin_y])
ndata = dict()
ndata["n_rats"] = torch.zeros(num_pins, 4)
ndata["n_ats"] = torch.zeros(num_pins, 4)
ndata["n_slews"] = torch.zeros(num_pins, 4)
ndata["n_net_delays"] = torch.from_numpy(net_delays_at_fanin).float()
ndata["nf"] = torch.zeros(num_pins, 10)
ndata["n_is_timing_endpt"] = torch.from_numpy(is_timing_endpoint).float()
for pi in range(num_pins):
pin_name = valid_pin_list[pi]
ndata["n_rats"][pi] = torch.from_numpy(pin_time[pin_name].rat)
ndata["n_ats"][pi] = torch.from_numpy(pin_time[pin_name].at)
ndata["n_slews"][pi] = torch.from_numpy(pin_time[pin_name].slew)
ndata['nf'][pi][0] = is_primary_io_pin[pi]
ndata['nf'][pi][1] = faninfanout[pi]
ndata['nf'][pi][2:6] = torch.from_numpy(pin_loc[pi])
# cap data
if is_primary_io_pin[pi]:
ndata["nf"][pi][6:10] = torch.zeros(4)
else:
inst = pin_name.split('/')[0]
pin_name_str = pin_name.split('/')[1]
celltype = inst2libcell_map[inst]
cap_data = np.zeros(4)
cap_data[0] = pin_caps['fast'][celltype][pin_name_str]['rise_capacitance']
cap_data[1] = pin_caps['fast'][celltype][pin_name_str]['fall_capacitance']
cap_data[2] = pin_caps['slow'][celltype][pin_name_str]['rise_capacitance']
cap_data[3] = pin_caps['slow'][celltype][pin_name_str]['fall_capacitance']
ndata["nf"][pi][6:10] = torch.from_numpy(cap_data)
# edge data
edges_features = dict()
edges_features['net_out'] = []
edges_features['net_in'] = []
edges_features['cell_out'] = []
for edge in edges['net_out']:
src = edge[0]
dst = edge[1]
srcx = pin_loc[src][0] + xl
srcy = pin_loc[src][1] + yl
dstx = pin_loc[dst][0] + xl
dsty = pin_loc[dst][1] + yl
ef = np.array([dstx - srcx, dsty - srcy])
edges_features['net_out'].append(ef)
edges_features['net_in'].append(-ef)
for edge in edges['cell_out']:
src = edge[0]
dst = edge[1]
src_pin = valid_pin_list[src]
dst_pin = valid_pin_list[dst]
inst = src_pin.split('/')[0]
assert(inst == dst_pin.split('/')[0])
path_key = dst_pin.split('/')[1] + '/' + src_pin.split('/')[1]
celltype = inst2libcell_map[inst]
ef = np.zeros(512)
ef[:4*15] = lib_data['fast'][celltype][path_key][:4*15]
ef[4*15 : 2*4*15] = lib_data['slow'][celltype][path_key][:4*15]
ef[2*4*15 : 2*4*15+4*49] = lib_data['fast'][celltype][path_key][-4*49:]
ef[-4*49:] = lib_data['slow'][celltype][path_key][-4*49:]
edges_features['cell_out'].append(ef)
edges_delay = dict()
edges_delay['net_out'] = []
edges_delay['cell_out'] = []
for edge in edges['net_out']:
src = edge[0]
dst = edge[1]
src_pin = valid_pin_list[src]
dst_pin = valid_pin_list[dst]
paths = src_pin2path_map_place[src_pin]
flag = False
for path in paths:
if path.dst == dst_pin:
flag = True
edges_delay['net_out'].append(path.delay)
break
if not flag:
pdb.set_trace()
assert(False)
for edge in edges['cell_out']:
src = edge[0]
dst = edge[1]
src_pin = valid_pin_list[src]
dst_pin = valid_pin_list[dst]
paths = src_pin2path_map_place[src_pin]
flag = False
for path in paths:
if path.dst == dst_pin:
flag = True
edges_delay['cell_out'].append(path.delay)
break
if not flag:
pdb.set_trace()
assert(False)
g = g_hetero
g.ndata['n_rats'] = ndata['n_rats'].float()
g.ndata['n_ats'] = ndata['n_ats'].float()
g.ndata['n_slews'] = ndata['n_slews'].float()
g.ndata['nf'] = ndata['nf'].float()
g.ndata['n_is_timing_endpt'] = ndata['n_is_timing_endpt'].float()
g.edges['cell_out'].data['e_delay'] = torch.tensor(edges_delay['cell_out']).float()
g.edges['cell_out'].data['ef'] = torch.tensor(edges_features['cell_out']).float()
g.edges['net_out'].data['e_delay'] = torch.tensor(edges_delay['net_out']).float()
g.edges['net_out'].data['ef'] = torch.tensor(edges_features['net_out']).float()
g.edges['net_in'].data['ef'] = torch.tensor(edges_features['net_in']).float()
######## End fill data into graph ########
######## save graph ########
dgl.save_graphs(os.path.join(save_dir, f'{block_name}.graph.bin'), [g])
######## End save graph ########
if __name__ == '__main__':
pdk = "asap7"
......@@ -979,7 +1152,7 @@ if __name__ == '__main__':
# blocks = "ethmac".split()
# blocks = "mock-alu".split()
raw_data_dir = f"/cyberpi/OpenROAD-flow-scripts/flow/parse/{pdk}"
raw_data_dir = f"../data/{pdk}"
techlib_dir = os.path.join(raw_data_dir, "techlib")
do_parse_libs = 0
......@@ -1027,13 +1200,6 @@ if __name__ == '__main__':
sdf_dir = os.path.join(block_dir, 'parsed')
lib_dir = os.path.join(techlib_dir, 'parsed_lib')
# NOTE: skip error blocks
# error_blocks = {'ethmac', 'ibex', 'jpeg', 'mock-alu'}
# if block in error_blocks:
# print('skip')
# continue
# check_legal(data_dir, lib_dir, sdf_dir, save_dir, block)
create_graph6(data_dir, lib_dir, sdf_dir, save_dir, block)
......@@ -400,6 +400,7 @@ def parse_libs(libs, save_dir):
print(f'finish reading {liberty_file}')
# pickle and save libdata and pin_cap
os.makedirs(save_dir, exist_ok=True)
with open(os.path.join(save_dir, "lib_data.pkl"), 'wb') as f:
pickle.dump(libdata, f)
f.close()
......@@ -465,7 +466,7 @@ class TimingArc:
self.type = None
self.buffers = [] # an ordered sequence of buffer, src->dst, (buf_in, buf_out)
self.delays = None # delays from src->dst
self.delay = None # delays from src->dst
class TimingGraph:
def __init__(self, inst2libcell_map):
......
......@@ -14,7 +14,7 @@ from model import PredModel
pdk = "asap7"
tag = "no_timing_opt"
dir_prefix = f"/cyberpi/OpenROAD-flow-scripts/flow/parse/{pdk}/{tag}"
dir_prefix = f"../data/{pdk}/{tag}"
# blocks = "aes aes-mbff ethmac gcd ibex jpeg mock-alu uart".split()
blocks = "aes aes-mbff gcd ibex jpeg uart".split()
......@@ -33,20 +33,10 @@ groundtruth = True
def gen_topo(g_hetero):
torch.cuda.synchronize()
time_s = time.time()
# na, nb = g_hetero.edges(etype='fanout2fanin', form='uv')
# ca, cb = g_hetero.edges(etype='in2out', form='uv')
# ffa, ffb = g_hetero.edges(etype='clk2q', form='uv')
# eda, edb = g_hetero.edges(etype='fanout2d', form='uv')
# g = dgl.graph((torch.cat([na, ca, ffa, eda]).cpu(), torch.cat([nb, cb, ffb, edb]).cpu()))
# na, nb = g_hetero.edges(etype='net_out', form='uv')
# ca, cb = g_hetero.edges(etype='cell_out', form='uv')
# g = dgl.graph((torch.cat([na, ca]).cpu(), torch.cat([nb, cb]).cpu()))
na, nb = g_hetero.edges(etype='fanout2fanin', form='uv')
ca, cb = g_hetero.edges(etype='in2out', form='uv')
pa, pb = g_hetero.edges(etype='_2outport', form='uv')
g = dgl.graph((torch.cat([na, ca, pa]).cpu(), torch.cat([nb, cb, pb]).cpu()))
na, nb = g_hetero.edges(etype='net_out', form='uv')
ca, cb = g_hetero.edges(etype='cell_out', form='uv')
g = dgl.graph((torch.cat([na, ca]).cpu(), torch.cat([nb, cb]).cpu()))
topo = dgl.topological_nodes_generator(g) # this seems like topo-sort
ret = [t.cuda() for t in topo]
......@@ -57,14 +47,17 @@ def gen_topo(g_hetero):
def load_data():
data = {}
for block in blocks:
graph_path = os.path.join(dir_prefix, block, "parsed", f"{block}.2.graph.bin")
graph_path = os.path.join(dir_prefix, block, "parsed", f"{block}.graph.bin")
g = dgl.load_graphs(graph_path)[0][0].to('cuda')
topo, topo_time = gen_topo(g)
ts = {
# 'fanin_nodes': g.edges(etype='fanout2fanin')[1].long(),
# 'fanout_nodes': g.edges(etype='fanout2fanin')[0].long(),
'input_nodes': (g.ndata['nf'][:, 1] < 0.5).nonzero().flatten().type(torch.int64),
'output_nodes': (g.ndata['nf'][:, 1] > 0.5).nonzero().flatten().type(torch.int64),
'output_nodes_nonpi': torch.logical_and(g.ndata['nf'][:, 1] > 0.5, g.ndata['nf'][:, 0] < 0.5).nonzero().flatten().type(torch.int64),
# pi/po: primary input/output
'pi_nodes': torch.logical_and(g.ndata['nf'][:, 1] > 0.5, g.ndata['nf'][:, 0] > 0.5).nonzero().flatten().type(torch.int64),
'po_nodes': torch.logical_and(g.ndata['nf'][:, 1] < 0.5, g.ndata['nf'][:, 0] > 0.5).nonzero().flatten().type(torch.int64),
'endpoints': (g.ndata['n_is_timing_endpt'] > 0.5).nonzero().flatten().type(torch.long),
'topo': topo,
}
data[block] = g, ts
......
......@@ -54,14 +54,6 @@ class NetConv(torch.nn.Module):
with g.local_scope():
g.ndata['nf'] = nf
# # fanin nodes
# g.update_all(self.edge_msg_i, fn.sum('efi', 'new_nf'), etype='fanout2fanin')
# # fanout nodes
# g.apply_edges(self.edge_msg_o, etype='fanin2fanout')
# g.update_all(fn.copy_e('efo1', 'efo1'), fn.sum('efo1', 'nfo1'), etype='fanin2fanout')
# g.update_all(fn.copy_e('efo2', 'efo2'), fn.max('efo2', 'nfo2'), etype='fanin2fanout')
# g.apply_nodes(self.node_reduce_o, ts['fanout_nodes'])
# input nodes
g.update_all(self.edge_msg_i, fn.sum('efi', 'new_nf'), etype='net_out')
# output nodes
......@@ -155,16 +147,9 @@ class SignalProp(torch.nn.Module):
# g.apply_nodes(self.node_skip_level_o, ts['pi_nodes'])
def prop_net(nodes, groundtruth):
g.pull(nodes, functools.partial(self.edge_msg_net, groundtruth=groundtruth), fn.sum('efn', 'new_nf'), etype='fanout2fanin')
g.pull(nodes, functools.partial(self.edge_msg_net, groundtruth=groundtruth), fn.sum('efn', 'new_nf'), etype='net_out')
def prop_cell(nodes, groundtruth):
# cell_edges = ['in2out', 'clk2q', 'fanout2d']
# for etype in cell_edges:
# es = g.in_edges(nodes, etype=etype)
# g.apply_edges(functools.partial(self.edge_msg_cell, groundtruth=groundtruth), es, etype=etype)
# g.send_and_recv(es, fn.copy_e('efc1', 'efc1'), fn.sum('efc1', 'nfc1'), etype=etype)
# g.send_and_recv(es, fn.copy_e('efc2', 'efc2'), fn.max('efc2', 'nfc2'), etype=etype)
etype = 'cell_out'
es = g.in_edges(nodes, etype=etype)
g.apply_edges(functools.partial(self.edge_msg_cell, groundtruth=groundtruth), es, etype=etype)
......@@ -204,4 +189,3 @@ class PredModel(torch.nn.Module):
nf1 = torch.cat([nf0, x], dim=1)
nf2, cell_delays = self.prop(g, ts, nf1)
return net_delays, cell_delays, nf2
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