diff --git a/README.md b/README.md index 90f636f..504be5a 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,7 @@ We are happy to announce that Xplace 2.0 is now released. Compared to [Xplace 1. - Support deterministic mode with only 5~25% extra GP runtime overhead. - Implement an extremely fast GPU-accelerated detailed-routability-driven placement algorithm. - Integrate with a GPU-accelerated detailed placer and a GPU-accelerated global router. +- Support a superfast **GPU-accelerated place and global route flow** ([Xplace](https://dl.acm.org/doi/abs/10.1145/3489517.3530485) + [GGR](https://dl.acm.org/doi/10.1145/3508352.3549474))! Input your LEF/DEF, the flow will output the **placement DEF** and the **global routing guide**! - Provide benchmark download and preprocess scripts, and three routability evaluation scripts. - Code refactoring. @@ -50,7 +51,7 @@ cmake -DPYTHON_EXECUTABLE=$(which python) .. make -j40 && make install ``` -## Prepare Data +## Prepare data The following script will automatically download `ispd2005`, `ispd2015`, and `iccad2019` benchmarks in `./data/raw`. It also preprocesses `ispd2015` benchmark to fix some errors when routing them by Innovus®. ```bash cd $XPLACE_HOME/data @@ -95,15 +96,23 @@ In ./result/exp_id ## Parameters Please refer to `main.py`. +## Run custom dataset +You can use the argument `--custom_path` to run your custom LEF/DEF or bookshelf benchmark. + +Suppose there is a LEF/DEF benchmark named `toy` in `data/raw`, you can use the following command line to run the GP + DP flow: +```bash +python main.py --custom_path lef:data/raw/toy_input.lef,def:data/raw/toy_input.def,design_name:toy,benchmark:test --load_from_raw True --detail_placement True +``` + ## Load design from preprocessed `pt` file (Optional) The following script will dump the parsed design into a single torch `pt` file so Xplace can load the design from the `pt` file instead of parsing the input file from scratch. ```bash cd $XPLACE_HOME/data -python utils/convert_design_to_torch_data.py --dataset ispd2005 -python utils/convert_design_to_torch_data.py --dataset ispd2015_fix -python utils/convert_design_to_torch_data.py --dataset iccad2019 +python convert_design_to_torch_data.py --dataset ispd2005 +python convert_design_to_torch_data.py --dataset ispd2015_fix +python convert_design_to_torch_data.py --dataset iccad2019 ``` Preprocessed data is saved in `./data/cad`. @@ -116,16 +125,26 @@ python main.py --dataset ispd2005 --run_all True --load_from_raw False **NOTE**: 1. Please remember to use the raw mode (set `--load_from_raw True`) when measuring the total running time. 2. We currently do not support `pt` mode in the routability-driven global placement. +3. If you want to run `pt` mode for the custom dataset, you need to add the custom dataset path in `utils/get_design_params.py`. -## Evaluate the Routability of Xplace's Solution +## GPU-accelerated place and global route flow (Xplace + GGR) +Set `--final_route_eval True` in Python arguments to invoke the internal global router [GGR](https://dl.acm.org/doi/10.1145/3508352.3549474) to run GPU-accelerated PnR flow. The flow will output the **placement DEF** and the **global routing guide** in `./result/exp_id/output`. Besides, GR metrics are reported in the log and recorded in `./result/exp_id/log/route.csv`. + +- To run Place and Global Route flow for ISPD2015 dataset: +```bash +python main.py --dataset ispd2015_fix --run_all True --load_from_raw True --detail_placement True --use_cell_inflate True --final_route_eval True +``` + +More details about using GGR in Xplace can be found in [cpp_to_py/gpugr/README.md](cpp_to_py/gpugr/README.md). + +## Evaluate theroutability of Xplace's solution We provide three ways to evaluate the routability of a placement solution: -1. Set `--final_route_eval True` in Python arguments to invoke the internal global router [GGR](https://dl.acm.org/doi/10.1145/3508352.3549474) to evaluate the placement solution. The evaluation metrics are reported in the log and recorded in `./result/exp_id/log/route.csv`. Besides, the route guide file is written in `./result/exp_id/output/design_name.guide`. -More details about using GGR in Xplace can be found in [cpp_to_py/gpugr](cpp_to_py/gpugr). +1. Set `--final_route_eval True` to invoke [GGR](https://dl.acm.org/doi/10.1145/3508352.3549474) to evaluate the placement solution. -2. Use [CU-GR](https://github.com/cuhk-eda/cu-gr) to evaluate the placement solution by global routing. Please refer to [tool/cugr_ispd2015_fix](tool/cugr_ispd2015_fix) for instructions. +2. Use [CU-GR](https://github.com/cuhk-eda/cu-gr) to evaluate the placement solution by global routing. Please refer to [tool/cugr_ispd2015_fix/README.md](tool/cugr_ispd2015_fix/README.md) for instructions. -3. (Optional). If Innovus® has been properly installed in your OS, you may try to use Innovus® to detailedly route the placement solution. Please refer to [tool/innovus_ispd2015_fix](tool/innovus_ispd2015_fix) for instructions. +3. (Optional). If Innovus® has been properly installed in your OS, you may try to use Innovus® to detailedly route the placement solution. Please refer to [tool/innovus_ispd2015_fix/README.md](tool/innovus_ispd2015_fix/README.md) for instructions. ## Citation diff --git a/main.py b/main.py index 397db7b..5419b8a 100644 --- a/main.py +++ b/main.py @@ -7,6 +7,7 @@ def get_option(): parser.add_argument('--dataset_root', type=str, default='data/raw', help='the parent folder of dataset') parser.add_argument('--dataset', type=str, default='ispd2015_fix', help='dataset name') 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('--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') @@ -75,6 +76,9 @@ def get_option(): print("We haven't yet support fence region in ispd2015, use ispd2015_fix instead") args.dataset = "ispd2015_fix" + if args.custom_path != "": + get_custom_design_params(args) + return args def main(): diff --git a/src/database.py b/src/database.py index 3ee1c51..7a2587d 100644 --- a/src/database.py +++ b/src/database.py @@ -1,25 +1,18 @@ -""" -Adapted from torch_geometric/data/data.py -""" import torch import collections import copy import math from utils import * -def get_dataset(args, logger): - with open("./data/cad/%s/datalist.csv" % (args.dataset), "r") as f: - all_files = f.readlines() - all_files = [line[:-1] for line in all_files] - for cur_file in all_files: - yield cur_file - def load_dataset(args, logger, placement=None): rawdb, gpdb = None, None - params = get_single_design_params( - args.dataset_root, args.dataset, args.design_name, placement - ) + if args.custom_path != "": + params = get_custom_design_params(args) + else: + params = get_single_design_params( + args.dataset_root, args.dataset, args.design_name, placement + ) parser = IOParser() if args.load_from_raw: logger.info("loading from original benchmark...") diff --git a/src/param_scheduler.py b/src/param_scheduler.py index b6b5aba..af2874e 100644 --- a/src/param_scheduler.py +++ b/src/param_scheduler.py @@ -525,7 +525,7 @@ class ParamScheduler: def visualize(self, args, logger): - file_prefix = "%s/%s_ms_" % (args.dataset, args.design_name) + file_prefix = "%s_" % args.design_name res_root = os.path.join(args.result_dir, args.exp_id) prefix = os.path.join(res_root, args.eval_dir, file_prefix) if not os.path.exists(os.path.dirname(prefix)): diff --git a/utils/__init__.py b/utils/__init__.py index 71d7f78..9afa578 100644 --- a/utils/__init__.py +++ b/utils/__init__.py @@ -3,5 +3,5 @@ from .timer import Timer from .logger import setup_logger from .visualization import * from .tools import * -from .get_design_params import get_single_design_params, get_multiple_design_params +from .get_design_params import get_single_design_params, get_multiple_design_params, get_custom_design_params from .setup_dataset import setup_dataset_args diff --git a/utils/get_design_params.py b/utils/get_design_params.py index b732c74..18a86d6 100644 --- a/utils/get_design_params.py +++ b/utils/get_design_params.py @@ -130,4 +130,18 @@ def single_iccad2019(dataset_root, design_name, placement=None): "def": "%s/%s/%s.input.def" % (root, design_name, design_name) if placement is None else placement, "design_name": design_name, } + return params + + +def get_custom_design_params(args): + params = dict([ + [item.strip() for item in token.strip().split(":")] + for token in args.custom_path.split(",") if len(token) > 0 + ]) + if "benchmark" not in params.keys(): + raise ValueError("Cannot find 'benchmark' in args.custom_path") + if "design_name" not in params.keys(): + raise ValueError("Cannot find 'design_name' in args.custom_path") + args.dataset = params["benchmark"] + args.design_name = params["design_name"] return params \ No newline at end of file