ADD file via upload

This commit is contained in:
dochejj 2023-10-08 16:02:02 +08:00
parent 973b2792b7
commit a34e77b300
1 changed files with 216 additions and 0 deletions

View File

@ -0,0 +1,216 @@
import numpy as np
import sys
import argparse
import matplotlib.pyplot as plt
import time
def clean_metal_paths_em_data(metal_layers):
"""
Concatenates the EM relevant data from Step 2/Prep_For_Sim.py into a single list. Assigns each useful
type of value (column) of the metal layer data to its own component of the instance. Has 7 outputs, each
a vector where each element relates to a single wire
:return: True
"""
# init array of null size
# must be numpy, as we will be reading in from text file
metal_em_info = np.zeros((0, 6), dtype=np.float32)
# load in metal path em info
print("Loading metal layer data...")
for metal in metal_layers:
metal_em_info = np.concatenate(
(metal_em_info, np.genfromtxt( metal + "_em.txt", delimiter=',', dtype=np.float32)))
print("Finished loading metal layer data!")
print("EM metal layers shape:", metal_em_info.shape)
# digest metal path info
width = metal_em_info[:, 0] * 1000000
x0 = metal_em_info[:, 2]
y0 = metal_em_info[:, 3]
x1 = metal_em_info[:, 4]
y1 = metal_em_info[:, 5]
# signed vector from x0 (y0) to x1 (y1)
x = x1 - x0
y = y1 - y0
# each is num_wires x 1
wire_widths, wire_x0, wire_x1, wire_y0, wire_y1, wire_x, wire_y = \
width, x0, x1, y0, y1, x, y
return wire_widths, wire_x0, wire_x1, wire_y0, wire_y1, wire_x, wire_y
def calculate_wire_distances_for_field(wire_widths, wire_x0, wire_x1, wire_y0, wire_y1, wire_x, wire_y):
"""
Calculates the distances used in the the field function all at once, so matrix operations
with them are possible. Assigns these as a component of the instance. Should be a 7 by the number
of wires matrix
:return: True
"""
# start with everything zero
# columns are [x_dir, y_dir, z_dir, p_x0, p_x1, p_y0, py_1]
# rows are for each wire
print("Calculating static wire distance matrix...")
# these calculations can only be done in numpy
out = np.zeros((wire_widths.shape[0], 7), dtype=np.float32)
# set values as desired in rows where wire widths are 0
vertical = np.asarray(wire_x == 0).nonzero()
# dir_y in column y_dir
out[vertical, 1] = np.sign(wire_y[vertical])
# x0_in - W_in / 2 in column p_x0
out[vertical, 3] = wire_x0[vertical] - wire_widths[vertical] / 2
# x0_in + W_in / 2 in column p_x1
out[vertical, 4] = wire_x0[vertical] + wire_widths[vertical] / 2
# y0_in in column p_y0
out[vertical, 5] = wire_y0[vertical]
# y1_in in column p_y1
out[vertical, 6] = wire_y1[vertical]
# set values as desired where wired lengths are 0
# dir_x
horizontal = np.asarray(wire_y == 0).nonzero()
out[horizontal, 0] = np.sign(wire_x[horizontal])
# y0_in - W_in / 2 in column p_y0
out[horizontal, 5] = wire_y0[horizontal] - wire_widths[horizontal] / 2
# y0_in + W_in / 2 in column p_y1
out[horizontal, 6] = wire_y0[horizontal] + wire_widths[horizontal] / 2
# x0_in in column p_x0
out[horizontal, 3] = wire_x0[horizontal]
# x1_in in column p_x1
out[horizontal, 4] = wire_x1[horizontal]
print("Finished calculating static wire distance matrix!")
print("Static wire distance matrix shape:", np.shape(out))
return out
# def grid_map_feature(out, layout_min_x, layout_min_y, target_area_x, target_area_y, num_probe_x_tiles,
# num_probe_y_tiles): """ extract the grid map for each design :return: grid map """ print(np.min(out[:, 3]),
# np.max(out[:, 4])) print(np.min(out[:, 5]), np.max(out[:, 6])) grid_map = np.zeros((num_probe_x_tiles,
# num_probe_y_tiles)) interval_x = target_area_x / num_probe_x_tiles interval_y = target_area_y / num_probe_y_tiles
#
# for current_grid in range(np.shape(out)[0]):
# tmp_x0 = int((out[current_grid, 3] - layout_min_x) // interval_x)
# tmp_x1 = int((out[current_grid, 4] - layout_min_x) // interval_x)
# if tmp_x0 > tmp_x1:
# tmp_x = np.arange(tmp_x1, tmp_x0 + 1, 1)
# else:
# tmp_x = np.arange(tmp_x0, tmp_x1 + 1, 1)
# tmp_y0 = int((out[current_grid, 5] - layout_min_y) // interval_y)
# tmp_y1 = int((out[current_grid, 6] - layout_min_y) // interval_y)
# if tmp_y0 > tmp_y1:
# tmp_y = np.arange(tmp_y1, tmp_y0 + 1, 1)
# else:
# tmp_y = np.arange(tmp_y0, tmp_y1 + 1, 1)
#
# for x_tile in range(np.shape(tmp_x)[0]): for y_tile in range(np.shape(tmp_y)[0]): if 0 <= tmp_x[x_tile] <
# num_probe_x_tiles and 0 <= tmp_y[y_tile] < num_probe_y_tiles: if grid_map[tmp_x[x_tile], tmp_y[y_tile]] == 0:
# grid_map[tmp_x[x_tile], tmp_y[y_tile]] = 1 # grid_map[tmp_x[x_tile], tmp_y[y_tile]] = (float(out[current_grid,
# 7]) + grid_map[tmp_x[x_tile], tmp_y[y_tile]])/2 # if float(out[current_grid, 7]) > grid_map[tmp_x[x_tile],
# tmp_y[y_tile]]: # grid_map[tmp_x[x_tile], tmp_y[y_tile]] = float(out[current_grid, 7]) # grid_map[tmp_x[
# x_tile], tmp_y[y_tile]] += float(out[current_grid, 7]) return grid_map
def grid_distance_feature(out, layout_min_x, layout_min_y, target_area_x, target_area_y, num_probe_x_tiles, num_probe_y_tiles):
"""
extract the grid map for each design
:return: grid map
"""
power_wire_attribute = []
for metal in metal_layers:
file = open( metal + "_probe.txt", 'r')
power_wire_attribute += file.readlines()
grid_distance = np.zeros((num_probe_x_tiles, num_probe_y_tiles))
interval_x = target_area_x / num_probe_x_tiles
interval_y = target_area_y / num_probe_y_tiles
VDD = np.array([[(6.689 - layout_min_x) // interval_x, (78.918 - layout_min_y) // interval_y]])
VSS = np.array([[(46.6415 - layout_min_x) // interval_x, (83.958 - layout_min_y) // interval_y]])
for current_grid in range(np.shape(out)[0]):
if 'VDD' in power_wire_attribute[current_grid]:
power_pad = VDD
else:
power_pad = VSS
tmp_x0 = int((out[current_grid, 3] - layout_min_x) // interval_x)
tmp_x1 = int((out[current_grid, 4] - layout_min_x) // interval_x)
if tmp_x0 > tmp_x1:
tmp_x = np.arange(tmp_x1, tmp_x0 + 1, 1)
else:
tmp_x = np.arange(tmp_x0, tmp_x1 + 1, 1)
tmp_y0 = int((out[current_grid, 5] - layout_min_y) // interval_y)
tmp_y1 = int((out[current_grid, 6] - layout_min_y) // interval_y)
if tmp_y0 > tmp_y1:
tmp_y = np.arange(tmp_y1, tmp_y0 + 1, 1)
else:
tmp_y = np.arange(tmp_y0, tmp_y1 + 1, 1)
for x_tile in range(np.shape(tmp_x)[0]):
for y_tile in range(np.shape(tmp_y)[0]):
if 0 <= tmp_x[x_tile] < num_probe_x_tiles and 0 <= tmp_y[y_tile] < num_probe_y_tiles:
# Compute Euclidean Distance tmp_distance0 = np.sqrt((tmp_x[x_tile] - power_pad[0, 0])**2 + (
# tmp_y[y_tile] - power_pad[0, 1])**2) tmp_distance1 = np.sqrt((tmp_x[x_tile] - power_pad[1,
# 0]) ** 2 + (tmp_y[y_tile] - power_pad[1, 1]) ** 2) tmp_distance = 1 / (tmp_distance1 +
# tmp_distance0)
# Compute Manhattan Distance
tmp_distance0 = np.abs(tmp_x[x_tile] - power_pad[0, 0]) + np.abs(tmp_y[y_tile] - power_pad[0, 1])
# tmp_distance1 = np.abs(tmp_x[x_tile] - power_pad[1, 0]) + np.abs(tmp_y[y_tile] - power_pad[1, 1])
tmp_distance = 1 / (tmp_distance0 + 1)
grid_distance[tmp_x[x_tile], tmp_y[y_tile]] = (grid_distance[tmp_x[x_tile], tmp_y[y_tile]] + tmp_distance) / 2
return grid_distance
def main(metal_layers, layout_min_x, layout_min_y, target_area_x, target_area_y, num_probe_x_tiles, num_probe_y_tiles, power_grid_map):
wire_widths, wire_x0, wire_x1, wire_y0, wire_y1, wire_x, wire_y = clean_metal_paths_em_data(metal_layers)
out = calculate_wire_distances_for_field(wire_widths, wire_x0, wire_x1, wire_y0, wire_y1, wire_x, wire_y)
# grid_map = grid_map_feature(out, layout_min_x, layout_min_y, target_area_x, target_area_y, num_probe_x_tiles,
# num_probe_y_tiles) np.save('power_wire_res.npy', out[:, 7]) np.save('grid_map.npy', grid_map) plt.imshow(
# grid_map[0:, :]) # 53 plt.colorbar() plt.show()
grid_distance = grid_distance_feature(out, layout_min_x, layout_min_y, target_area_x, target_area_y, num_probe_x_tiles, num_probe_y_tiles)
np.save(power_grid_map, grid_distance)
plt.imshow(grid_distance[:, :])
plt.colorbar()
plt.show()
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--metal_layers", type=str, default=["../Electromagnetic Computation/metal5", "../Electromagnetic Computation/metal6"],
help="target metal layers")
parser.add_argument("--target_area_x", type=float, default=960,
help="Target simulated area in x axial direction")
parser.add_argument("--target_area_y", type=float, default=960,
help="Target simulated area in y axial direction")
parser.add_argument("--num_probe_x_tiles", type=int, default=48,
help="Number of point grid in x axial direction")
parser.add_argument("--num_probe_y_tiles", type=int, default=48,
help="Number of point grid in y axial direction")
parser.add_argument("--layout_min_x", type=float, default=0,
help="Reference coordinate in x axial direction")
parser.add_argument("--layout_min_y", type=float, default=0,
help="Reference coordinate in y axial direction")
parser.add_argument("--power_grid_map", type=str, default="../GAN Model Training/power_grid_map.npy",
help="generate power gird map for GAN training and EM prediction")
args = parser.parse_args()
metal_layers = args.metal_layers
target_area_x = args.target_area_x
target_area_y = args.target_area_y
num_probe_x_tiles = args.num_probe_x_tiles
num_probe_y_tiles = args.num_probe_y_tiles
layout_min_x = args.layout_min_x
layout_min_y = args.layout_min_y
power_grid_map = args.power_grid_map
start_time = time.time()
try:
sys.exit(main(metal_layers, layout_min_x, layout_min_y, target_area_x, target_area_y, num_probe_x_tiles, num_probe_y_tiles, power_grid_map))
except KeyboardInterrupt:
sys.exit()
finally:
print("Running time:", time.time() - start_time, "seconds")