diff --git a/main.py b/main.py index 23c5f5e..e3b3f4e 100644 --- a/main.py +++ b/main.py @@ -9,6 +9,7 @@ def get_option(): parser.add_argument('--design_name', type=str, default='mgc_superblue12', help='design name') parser.add_argument('--custom_path', type=str, default='', help='custom design path, set it as token1:path1,token2:path2 e.g. lef:data/test.lef,def:data/test.def,design_name:mydesign,benchmark:mybenchmark') parser.add_argument('--custom_json', type=str, default='', help='custom json path, support multi-lefs.') + parser.add_argument('--given_solution', type=str, default='', help='Given placement solution. Will overwrite other given .pl and .def.') parser.add_argument('--load_from_raw', type=str2bool, default=True, help='If True, parse and load from benchmark files. If False, load from pt') parser.add_argument('--run_all', type=str2bool, default=False, help='If True, run all designs in the given dataset. If False, run the given design_name only.') parser.add_argument('--seed', type=int, default=0, help='seed to initialize all the random modules') @@ -17,6 +18,7 @@ def get_option(): parser.add_argument('--deterministic', type=str2bool, default=True, help='use deterministic mode') # global placement params + parser.add_argument('--global_placement', type=str2bool, default=True, help='perform gp') parser.add_argument('--lr', type=float, default=0.01, help='learning rate') parser.add_argument('--inner_iter', type=int, default=10000, help='#inner iters') parser.add_argument('--wa_coeff', type=float, default=4.0, help='wa coeff') diff --git a/src/run_placement_nesterov.py b/src/run_placement_nesterov.py index c0d8803..df3fb6d 100644 --- a/src/run_placement_nesterov.py +++ b/src/run_placement_nesterov.py @@ -10,24 +10,22 @@ def get_trunc_node_pos_fn(mov_node_size, data): return x return trunc_node_pos_fn -def run_placement_main_nesterov(args, logger): - total_start = time.time() - params = find_design_params(args, logger) - data, rawdb, gpdb = load_dataset(args, logger, params) - device = torch.device( - "cuda:{}".format(args.gpu) if torch.cuda.is_available() else "cpu" - ) - assert args.use_eplace_nesterov - logger.info("Start place %s/%s" % (args.dataset , args.design_name)) - logger.info("Use Nesterov optimizer!") - data = data.to(device) - data = data.preprocess() - logger.info(data) - logger.info(data.node_type_indices) - # args.num_bin_x = args.num_bin_y = 2 ** math.ceil(math.log2(max(data.die_info).item() // 25)) +def global_placement_main(gpdb, rawdb, ps: ParamScheduler, data: PlaceData, args, logger): + init_density_map = data.init_density_map + if not args.global_placement: + logger.info("Global placement is switched off. Please make sure the input " + "placement solution is already placed globally.") + node_pos, iteration = data.node_pos, 0 + hpwl, overflow = evaluate_placement(node_pos, init_density_map, ps, data, args) + hpwl, overflow = hpwl.item(), overflow.item() + info = ("%d_gp" % (iteration + 1), hpwl, data.design_name) + if args.draw_placement: + draw_fig_with_cairo_cpp(node_pos, data.node_size, data, info, args) + logger.info("Input solution, exact HPWL: %.6E exact Overflow: %.4f" % (hpwl, overflow)) + gp_hpwl, overflow, gp_time, gp_per_iter = hpwl, overflow, 0, -1 + return node_pos, iteration, gp_hpwl, overflow, gp_time, gp_per_iter - init_density_map = get_init_density_map(rawdb, gpdb, data, args, logger) - data.init_filler() + device = data.device mov_lhs, mov_rhs = data.movable_index mov_node_pos, mov_node_size, expand_ratio = data.get_mov_node_info() mov_node_pos = mov_node_pos.requires_grad_(True) @@ -45,7 +43,6 @@ def run_placement_main_nesterov(args, logger): return overflow_sum / data.total_mov_area_without_filler overflow_helper = (mov_lhs, mov_rhs, overflow_fn) - ps = ParamScheduler(data, args, logger) density_map_layer = ElectronicDensityLayer( unit_len=data.unit_len, num_bin_x=data.num_bin_x, @@ -391,6 +388,33 @@ def run_placement_main_nesterov(args, logger): gp_time = gp_end_time - gp_start_time iteration += 1 # increase 1 For DP drawing + return node_pos, iteration, gp_hpwl, overflow, gp_time, gp_per_iter + + +def run_placement_main_nesterov(args, logger): + total_start = time.time() + params = find_design_params(args, logger) + data, rawdb, gpdb = load_dataset(args, logger, params) + device = torch.device( + "cuda:{}".format(args.gpu) if torch.cuda.is_available() else "cpu" + ) + assert args.use_eplace_nesterov + logger.info("Start place %s/%s" % (args.dataset , args.design_name)) + logger.info("Use Nesterov optimizer!") + data = data.to(device) + data = data.preprocess() + logger.info(data) + logger.info(data.node_type_indices) + # args.num_bin_x = args.num_bin_y = 2 ** math.ceil(math.log2(max(data.die_info).item() // 25)) + get_init_density_map(rawdb, gpdb, data, args, logger) + data.init_filler() + + ps = ParamScheduler(data, args, logger) + + # global placement + node_pos, iteration, gp_hpwl, overflow, gp_time, gp_per_iter = global_placement_main( + gpdb, rawdb, ps, data, args, logger + ) # detail placement node_pos, dp_hpwl, top5overflow, lg_time, dp_time = detail_placement_main( node_pos, gpdb, rawdb, ps, data, args, logger diff --git a/utils/io_parser.py b/utils/io_parser.py index f8770d1..a5c9ca1 100644 --- a/utils/io_parser.py +++ b/utils/io_parser.py @@ -77,6 +77,9 @@ class IOParser(object): 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") diff --git a/utils/setup_dataset.py b/utils/setup_dataset.py index ed37355..8e7aded 100644 --- a/utils/setup_dataset.py +++ b/utils/setup_dataset.py @@ -10,11 +10,28 @@ def find_design_params(args, logger, placement=None): params = get_single_design_params( args.dataset_root, args.dataset, args.design_name, placement ) + setup_given_solution(args, logger, params, placement) log_design_params(logger, params) setup_design_args(args) return params +def setup_given_solution(args, logger, params, placement=None): + if placement is not None: + args.given_solution = placement + if args.given_solution != "": + placement = args.given_solution + logger.info("Find given placement solution: %s" % placement) + if ".pl" in placement: + if "pl" in params.keys(): + logger.info("Overwrite pl file %s by %s" % (params["pl"], placement)) + params["pl"] = placement + elif ".def" in placement: + if "def" in params.keys(): + logger.info("Overwrite def file %s by %s" % (params["def"], placement)) + params["def"] = placement + + def log_design_params(logger, params: dict): content = "Design Info:\n" num_items = 0