Xplace_for_ICCAD/utils/io_parser.py
2024-06-06 14:48:55 +08:00

231 lines
8.8 KiB
Python

import torch
from cpp_to_py import io_parser
import os
class IOParser(object):
def __init__(self) -> None:
super().__init__()
self.params = None
def reset_params(self):
io_parser.load_params({})
def load_params(
self,
params: dict,
verbose_log: bool = False,
log_level: int = 2,
lite_mode: bool = False,
random_place: bool = True,
num_threads: int = 8,
):
check_status = self.check_params(params, verbose_log, log_level, lite_mode, random_place, num_threads)
if not check_status:
raise ValueError(
"Checking failure. Please check the validity of params: %s" % params
)
load_status = io_parser.load_params(self.params)
if not load_status:
raise ValueError(
"Loading failure. Please check the validity of params: %s" % params
)
return load_status
def check_params(
self, params: dict, verbose_log: bool, log_level: int, lite_mode: bool, random_place: bool, num_threads: int = 8
) -> bool:
if "def" not in params.keys() and "aux" not in params.keys():
print("def or aux is not found!")
return False
if "def" in params.keys() and "aux" in params.keys():
print("Can only support one input format!")
return False
if "def" in params.keys():
if "lefs" in params.keys():
valid_flag = True
for lef in params["lefs"]:
if not os.path.exists(lef):
print("lef %s not exists." % lef)
valid_flag = False
if not valid_flag:
return False
elif "lef" not in params.keys():
if "cell_lef" not in params.keys() and "tech_lef" not in params.keys():
print("lef or (cell_lef and tech_lef) is not found")
return False
if not os.path.exists(params["cell_lef"]):
print("cell_lef %s not exists." % params["cell_lef"])
return False
if not os.path.exists(params["tech_lef"]):
print("tech_lef %s not exists." % params["tech_lef"])
return False
else:
if not os.path.exists(params["lef"]):
print("lef %s not exists." % params["lef"])
return False
if "output" in params.keys():
if "def" != params["output"].split(".")[-1]:
print("output format should be .def")
return False
if not os.path.exists(params["def"]):
print("def %s not exists." % params["def"])
return False
if "aux" in params.keys():
if not os.path.exists(params["aux"]):
print("aux %s not exists." % params["aux"])
return False
if "pl" in params.keys() and not os.path.exists(params["pl"]):
print("pl %s not exists." % params["pl"])
return False
if "bookshelf_variety" not in params.keys():
print("Not specify bookshelf_variety. Set to ispd2005.")
params["bookshelf_variety"] = "ispd2005"
if "output" in params.keys():
if "pl" != params["output"].split(".")[-1]:
print("output format should be .pl")
return False
self.params = params
if verbose_log:
self.params["verbose_parser_log"] = True
else:
self.params["verbose_parser_log"] = False
# === LOG_LEVEL ===
# 0: DEBUG, 1: VERBOSE, 2: INFO, 3: NOTICE, 4: WARN, 5: ERROR, 6: FATAL, 7: OK
if log_level < 0:
log_level = 0
elif log_level > 7:
log_level = 2
self.params["global_log_level"] = log_level
if lite_mode:
self.params["lite_mode"] = True
else:
self.params["lite_mode"] = False
if random_place:
self.params["random_place"] = True
else:
self.params["random_place"] = False
self.params["num_threads"] = num_threads
return True
def read(
self,
params: dict,
verbose_log: bool = False,
log_level: int = 2,
lite_mode: bool = False,
random_place: bool = True,
num_threads: int = 8,
debug: bool = False,
):
check_status = self.check_params(params, verbose_log, log_level, lite_mode, random_place, num_threads)
if not check_status:
raise ValueError(
"Checking failure. Please check the validity of params: %s" % params
)
if debug:
load_status = io_parser.load_params(self.params)
if not load_status:
raise ValueError(
"Loading failure. Please check the validity of params: %s" % params
)
rawdb = io_parser.create_database()
rawdb.load()
rawdb.setup()
gpdb = io_parser.create_gpdatabase(rawdb)
gpdb.setup()
else:
rawdb, gpdb = io_parser.start(self.params)
# rawdb and gpdb are both c++ shared pointer
return (rawdb, gpdb)
def preprocess_design_info(self, gpdb):
dieLX, dieHX, dieLY, dieHY = gpdb.coreInfo() # use coreInfo instead of dieInfo
die_info = torch.tensor([dieLX, dieHX, dieLY, dieHY]).float()
# die_shift = torch.tensor([dieLX, dieLY])
# die_scale = torch.tensor([dieHX - dieLX, dieHY - dieLY])
siteWidth = gpdb.siteWidth()
siteHeight = gpdb.siteHeight()
site_info = (float(siteWidth), float(siteHeight))
node_pos = gpdb.node_cpos_tensor()
node_lpos = gpdb.node_lpos_tensor()
node_size = gpdb.node_size_tensor()
pin_rel_cpos = gpdb.pin_rel_cpos_tensor()
pin_rel_lpos = gpdb.pin_rel_lpos_tensor()
pin_size = gpdb.pin_size_tensor()
pin_id2node_id = gpdb.pin_id2node_id_tensor()
(
hyperedge_index,
hyperedge_list,
hyperedge_list_end,
) = gpdb.hyperedge_info_tensor()
(
node2pin_index,
node2pin_list,
node2pin_list_end,
) = gpdb.node2pin_info_tensor()
node_id2region_id, region_boxes, region_boxes_end = gpdb.region_info_tensor()
node_type_indices = gpdb.node_type_indices()
node_id2node_name = gpdb.node_id2node_name()
node_id2celltype_name = gpdb.node_id2celltype_name()
all_node_types = []
mov_end_idx = None
fix_end_idx = None
connected_end_idx = None
for start_idx, end_idx, type_name in node_type_indices:
all_node_types.append(type_name)
if "FloatMov" == type_name:
mov_end_idx = end_idx
if "FloatFix" == type_name:
fix_end_idx = end_idx
if "IOPin" == type_name:
connected_end_idx = end_idx
# Mov + FloatMov
movable_index = (0, mov_end_idx)
# Mov + FloatMov + Fix + IOPin
connected_index = (0, connected_end_idx)
# Fix + IOPin + Blkg + FloatIOPin + FloatFix
fixed_index = (mov_end_idx, fix_end_idx)
design_info = {
"benchmark": self.params["benchmark"],
"dataset_path": self.params,
"node_type_indices": node_type_indices,
"node_id2node_name": node_id2node_name,
"node_id2celltype_name": node_id2celltype_name,
"movable_index": movable_index,
"connected_index": connected_index,
"fixed_index": fixed_index,
"site_info": site_info,
"die_info": die_info,
"node_pos": node_pos.contiguous(),
"node_lpos": node_lpos.contiguous(),
"node_size": node_size.contiguous(),
"pin_rel_cpos": pin_rel_cpos.contiguous(),
"pin_rel_lpos": pin_rel_lpos.contiguous(),
"pin_size": pin_size.contiguous(),
"pin_id2node_id": pin_id2node_id.long().contiguous(),
"hyperedge_index": hyperedge_index.long().contiguous(),
"hyperedge_list": hyperedge_list.long().contiguous(),
"hyperedge_list_end": hyperedge_list_end.long().contiguous(),
"node2pin_index": node2pin_index.long().contiguous(),
"node2pin_list": node2pin_list.long().contiguous(),
"node2pin_list_end": node2pin_list_end.long().contiguous(),
"node_id2region_id": node_id2region_id.long().contiguous(),
"region_boxes": region_boxes.contiguous(),
"region_boxes_end": region_boxes_end.long().contiguous(),
}
return design_info