From 8db7d4f54982bdd31fac07c14cf8460b501009c7 Mon Sep 17 00:00:00 2001 From: liulixinkerry Date: Thu, 18 Apr 2024 12:56:30 +0800 Subject: [PATCH] v2.1.1 (1) support custom_json (2) add visualize_cgmap --- README.md | 6 ++++ cpp_to_py/common/db/Database.cpp | 5 ++++ cpp_to_py/common/db/Layer.h | 4 +-- cpp_to_py/common/db/Setting.cpp | 1 + cpp_to_py/common/db/Setting.h | 1 + cpp_to_py/common/io/file_bkshf_db.cpp | 4 +-- cpp_to_py/common/io/file_lefdef_db.cpp | 6 ++-- cpp_to_py/draw_placement/Drawer.cpp | 18 ++++++++++-- cpp_to_py/draw_placement/Drawer.h | 3 +- cpp_to_py/draw_placement/draw_placement.cpp | 5 ++-- cpp_to_py/gpugr/db/GRDatabase.cpp | 31 +++++++++++---------- cpp_to_py/io_parser/BindHelper.cpp | 1 + cpp_to_py/io_parser/PyBindCppMain.cpp | 5 ++++ cpp_to_py/io_parser/gp/GPDatabase.cpp | 8 ++++++ cpp_to_py/io_parser/gp/GPDatabase.h | 5 ++++ examples/examples.json | 11 ++++++++ main.py | 2 ++ src/database.py | 19 +++++++++++++ src/run_placement.py | 2 -- src/run_placement_nesterov.py | 6 ++-- utils/__init__.py | 2 +- utils/get_design_params.py | 13 +++++++++ utils/io_parser.py | 12 +++++++- utils/visualization.py | 5 ++++ 24 files changed, 143 insertions(+), 32 deletions(-) create mode 100644 examples/examples.json diff --git a/README.md b/README.md index d0df2f5..bae4f1f 100644 --- a/README.md +++ b/README.md @@ -110,6 +110,12 @@ Suppose there is a LEF/DEF benchmark named `toy` in `data/raw`, you can use the 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 ``` +You can also use the argument `--custom_json` to run multiple LEFs + DEF: +``` +python main.py --custom_json examples/examples.json --load_from_raw True --target_density 0.9 +``` +Please provide your LEFs/DEF in the input `json` file. An example of [ASAP7](https://github.com/The-OpenROAD-Project/asap7) input is given in `./examples/examples.json`. + ## 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. diff --git a/cpp_to_py/common/db/Database.cpp b/cpp_to_py/common/db/Database.cpp index 0782569..a2bc944 100644 --- a/cpp_to_py/common/db/Database.cpp +++ b/cpp_to_py/common/db/Database.cpp @@ -32,6 +32,11 @@ void Database::load() { setting.Format = "lefdef"; readLEF(setting.LefTech); readLEF(setting.LefCell); + } else if (setting.LefFiles.size() > 0) { + setting.Format = "lefdef"; + for (auto lef : setting.LefFiles) { + readLEF(lef); + } } if (setting.DefFile != "") { diff --git a/cpp_to_py/common/db/Layer.h b/cpp_to_py/common/db/Layer.h index 0422ccb..22bcad4 100644 --- a/cpp_to_py/common/db/Layer.h +++ b/cpp_to_py/common/db/Layer.h @@ -70,8 +70,8 @@ public: vector parWidth; vector> parWidthSpace; // 2D table: (parWidth, parLength) -> widthSpacing - Track track; - Track nonPreferDirTrack; + vector tracks; + vector nonPreferDirTracks; Layer(const string& name = "", const char type = 'x') : _name(name), _type(type) {} diff --git a/cpp_to_py/common/db/Setting.cpp b/cpp_to_py/common/db/Setting.cpp index 73e5377..e2a6f7c 100644 --- a/cpp_to_py/common/db/Setting.cpp +++ b/cpp_to_py/common/db/Setting.cpp @@ -10,6 +10,7 @@ void Setting::reset() { LefFile = ""; LefCell = ""; LefTech = ""; + LefFiles.clear(); Constraints = ""; Verilog = ""; OutputFile = ""; diff --git a/cpp_to_py/common/db/Setting.h b/cpp_to_py/common/db/Setting.h index d7613e9..12e422f 100644 --- a/cpp_to_py/common/db/Setting.h +++ b/cpp_to_py/common/db/Setting.h @@ -27,6 +27,7 @@ public: std::string LefFile = ""; std::string LefCell = ""; std::string LefTech = ""; + std::vector LefFiles; std::string Constraints = ""; std::string Verilog = ""; diff --git a/cpp_to_py/common/io/file_bkshf_db.cpp b/cpp_to_py/common/io/file_bkshf_db.cpp index ce38393..939e70b 100644 --- a/cpp_to_py/common/io/file_bkshf_db.cpp +++ b/cpp_to_py/common/io/file_bkshf_db.cpp @@ -490,10 +490,10 @@ bool Database::readBSAux(const std::string& auxFile, const std::string& plFile) // } else if (i % 2) { if (i % 2) { layer.direction = m2direction; - layer.track.direction = m2direction; + // layer.track.direction = m2direction; } else { layer.direction = m1direction; - layer.track.direction = m1direction; + // layer.track.direction = m1direction; } if (isDac2012) { layer.width = bsData.wireWidth[i]; diff --git a/cpp_to_py/common/io/file_lefdef_db.cpp b/cpp_to_py/common/io/file_lefdef_db.cpp index df2a99c..1f56b16 100644 --- a/cpp_to_py/common/io/file_lefdef_db.cpp +++ b/cpp_to_py/common/io/file_lefdef_db.cpp @@ -1325,11 +1325,11 @@ int readDefTrack(defrCallbackType_e c, defiTrack* dtrack, defiUserData ud) { Layer* layer = db->getLayer(layername); if (layer) { if (track->direction == 'x' || layer->direction == 'x') { - layer->track = *track; + layer->tracks.push_back(*track); } else if (layer->direction == track->direction) { - layer->track = *track; + layer->tracks.push_back(*track); } else if (layer->direction != track->direction) { - layer->nonPreferDirTrack = *track; + layer->nonPreferDirTracks.push_back(*track); } else { logger.error("wrong definition of tracks for layer %s", layername.c_str()); } diff --git a/cpp_to_py/draw_placement/Drawer.cpp b/cpp_to_py/draw_placement/Drawer.cpp index 2ffaad6..7197632 100644 --- a/cpp_to_py/draw_placement/Drawer.cpp +++ b/cpp_to_py/draw_placement/Drawer.cpp @@ -101,8 +101,10 @@ bool Drawer::run(const std::vector& node_pos_x, // after die scale const std::tuple& die_info, // after die scale const std::tuple& site_info, const std::tuple& bin_size_info, // after die scale - std::vector> node_types_indices) { + std::vector> node_types_indices, + const std::vector& node_special_type) { // init cairo + bool special_cell = !node_special_type.empty(); cairo_surface_t* cs; if (format == "png") { cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height); @@ -190,7 +192,19 @@ bool Drawer::run(const std::vector& node_pos_x, // after die scale double node_lx = node_pos_x[i] - node_size_x[i] / 2; double node_ly = node_pos_y[i] - node_size_y[i] / 2; cairo_rectangle(c, node_lx, node_ly, node_size_x[i], node_size_y[i]); - set_rgba(node_type); + if (special_cell && i < node_special_type.size() && node_special_type[i] > 0){ + switch (node_special_type[i]) { + case 1: + set_rgba("Buffer"); + break; + case 2: + set_rgba("FF"); + break; + default: + set_rgba(node_type); + break; + } + } else set_rgba(node_type); cairo_fill(c); if (draw_node_bd) { cairo_rectangle(c, node_lx, node_ly, node_size_x[i], node_size_y[i]); diff --git a/cpp_to_py/draw_placement/Drawer.h b/cpp_to_py/draw_placement/Drawer.h index 39325d7..355da7f 100644 --- a/cpp_to_py/draw_placement/Drawer.h +++ b/cpp_to_py/draw_placement/Drawer.h @@ -23,5 +23,6 @@ public: const std::tuple& die_info, const std::tuple& site_info, const std::tuple& bin_size_info, - std::vector> node_types_indices); + std::vector> node_types_indices, + const std::vector& node_special_type); }; diff --git a/cpp_to_py/draw_placement/draw_placement.cpp b/cpp_to_py/draw_placement/draw_placement.cpp index cbd0d7b..1583df0 100644 --- a/cpp_to_py/draw_placement/draw_placement.cpp +++ b/cpp_to_py/draw_placement/draw_placement.cpp @@ -11,6 +11,7 @@ bool DrawGlobalPlacement( const std::tuple& bin_size_info, const std::vector>& node_types_indices, const std::vector>& ele_type_to_rgba_vec, + const std::vector& node_special_type, const std::string& filename, double width, double height, @@ -25,8 +26,8 @@ bool DrawGlobalPlacement( die_info, site_info, bin_size_info, - node_types_indices); + node_types_indices, + node_special_type); return status; } - PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) { m.def("draw", &DrawGlobalPlacement, "Draw placement results"); } diff --git a/cpp_to_py/gpugr/db/GRDatabase.cpp b/cpp_to_py/gpugr/db/GRDatabase.cpp index 79054e7..c6ea54d 100644 --- a/cpp_to_py/gpugr/db/GRDatabase.cpp +++ b/cpp_to_py/gpugr/db/GRDatabase.cpp @@ -15,7 +15,7 @@ GRDatabase::GRDatabase(std::shared_ptr rawdb_, std::shared_ptr rawdb_, std::shared_ptrwidth; layerPitch[l] = rLayer->pitch; - db::Track& track = rLayer->track; - for (int i = 0; i < track.num; i++) { - tracks[l].emplace_back(i * track.step + track.start); + for (auto& track : rLayer->tracks) { + for (int i = 0; i < track.num; i++) { + tracks[l].emplace_back(i * track.step + track.start); + } } + sort(tracks[l].begin(), tracks[l].end()); + tracks[l].erase(unique(tracks[l].begin(), tracks[l].end()), tracks[l].end()); } m1direction = rawdb.getRLayer(0)->direction == 'v' ? 1 : 0; microns = rawdb.LefConvertFactor; @@ -448,11 +451,11 @@ utils::PointT GRDatabase::getObsMargin(RectOnLayer box, AggrParaRunSpace ag utils::IntervalT GRDatabase::rangeSearchTracks(const utils::IntervalT& locRange, int layerIdx) { auto& t = tracks[layerIdx]; - int lpos = locRange.low / layerPitch[layerIdx]; - while (lpos + 1 < t.size() && t[lpos] < locRange.low) lpos++; + int lpos = lower_bound(t.begin(), t.end(), locRange.low) - t.begin(); + lpos = std::min(static_cast(t.size()) - 1, lpos); while (lpos > 0 && t[lpos - 1] >= locRange.low) lpos--; - int hpos = locRange.high / layerPitch[layerIdx]; - while (hpos > 0 && t[hpos] > locRange.high) hpos--; + int hpos = upper_bound(t.begin(), t.end(), locRange.high) - t.begin() - 1; + hpos = std::max(hpos, 0); return utils::IntervalT(lpos, hpos); } @@ -480,9 +483,9 @@ void GRDatabase::markObs(std::vector& allObs, vector, int>>>> markingBufferLUT; auto searchLowerBoundTrack = [&](int p) { - int pos = p / layerPitch[l]; - while (pos + 1 < t.size() && t[pos] < p) pos++; - while (pos && t[pos - 1] >= p) pos--; + int pos = lower_bound(t.begin(), t.end(), p) - t.begin(); + pos = std::min(static_cast(t.size()) - 1, pos); + while (pos > 0 && t[pos - 1] >= p) pos--; return pos; }; @@ -561,12 +564,12 @@ void GRDatabase::markObs(std::vector& allObs, } for (int i = 0; i < markingBufferLUT.size(); i++) { + utils::IntervalT gridTrackIntvl; + gridTrackIntvl.low = searchLowerBoundTrack(gridlines[1 - dir][i]); + gridTrackIntvl.high = searchLowerBoundTrack(gridlines[1 - dir][i + 1]) - 1; for (int j = 0; j < markingBufferLUT[i].size(); j++) { if (markingBufferLUT[i][j].size() == 0) continue; const auto& buf = markingBufferLUT[i][j]; - utils::IntervalT gridTrackIntvl; - gridTrackIntvl.low = searchLowerBoundTrack(gridlines[1 - dir][i]); - gridTrackIntvl.high = searchLowerBoundTrack(gridlines[1 - dir][i + 1]) - 1; vector trackBlocked(gridTrackIntvl.range() + 1, 0); // blocked track length for (auto& pair : buf) { for (int k = pair.first.low; k <= pair.first.high; k++) { diff --git a/cpp_to_py/io_parser/BindHelper.cpp b/cpp_to_py/io_parser/BindHelper.cpp index cf0cbb9..a6960b3 100644 --- a/cpp_to_py/io_parser/BindHelper.cpp +++ b/cpp_to_py/io_parser/BindHelper.cpp @@ -55,6 +55,7 @@ void bindGPDatabase(pybind11::module& m) { .def("m1direction", &gp::GPDatabase::getM1Direction, py::return_value_policy::copy) .def("node_type_indices", &gp::GPDatabase::getNodeTypeIndices, py::return_value_policy::copy) .def("node_id2node_name", &gp::GPDatabase::getNodeId2NodeName, py::return_value_policy::copy) + .def("node_id2celltype_name", &gp::GPDatabase::getNodeId2CellTypeName, py::return_value_policy::copy) .def("node_lpos_tensor", &gp::GPDatabase::getNodeLPosTensor, py::return_value_policy::move) .def("node_cpos_tensor", &gp::GPDatabase::getNodeCPosTensor, py::return_value_policy::move) .def("node_size_tensor", &gp::GPDatabase::getNodeSizeTensor, py::return_value_policy::move) diff --git a/cpp_to_py/io_parser/PyBindCppMain.cpp b/cpp_to_py/io_parser/PyBindCppMain.cpp index 08f1930..3205753 100644 --- a/cpp_to_py/io_parser/PyBindCppMain.cpp +++ b/cpp_to_py/io_parser/PyBindCppMain.cpp @@ -27,6 +27,11 @@ bool loadParams(const py::dict& kwargs) { } else if (kwargs.contains("cell_lef") && kwargs.contains("tech_lef")) { db::setting.LefCell = kwargs["cell_lef"].cast(); db::setting.LefTech = kwargs["tech_lef"].cast(); + } else if (kwargs.contains("lefs")) { + for (auto lef_py : kwargs["lefs"]) { + auto lef = lef_py.cast(); + db::setting.LefFiles.emplace_back(lef); + } } if (kwargs.contains("constraints")) { diff --git a/cpp_to_py/io_parser/gp/GPDatabase.cpp b/cpp_to_py/io_parser/gp/GPDatabase.cpp index 634d0b2..9597dff 100644 --- a/cpp_to_py/io_parser/gp/GPDatabase.cpp +++ b/cpp_to_py/io_parser/gp/GPDatabase.cpp @@ -21,6 +21,9 @@ void GPDatabase::addCellNode(index_type cell_id, std::string& node_type) { node.setRegionId(static_cast(cell->region->id)); regions[node.getRegionId()].addNode(node.getId()); + std::string celltype_name_ = cell->ctype()->cls + "/" + cell->ctype()->name; + node.setCellTypeName(celltype_name_); + if (cell->fixed() && cell->ctype()->nonRegularRects().size() > 0) { node.setIsPolygonShape(true); } @@ -41,6 +44,8 @@ void GPDatabase::addIOPinNode(index_type iopin_id, std::string& node_type) { node.setNodeType(node_type); node.setOriDBId(iopin_id); + node.setCellTypeName(iopin->name); + iopin->gpdb_id = nodes.size() - 1; } @@ -58,6 +63,8 @@ void GPDatabase::addBlockageNode(index_type blkg_id, std::string& node_type) { node.setOrient(-1); // No orientation for placement blockage node.setNodeType(node_type); node.setOriDBId(blkg_id); + + node.setCellTypeName(blockage_name); } void GPDatabase::addNet(index_type dbnet_id) { @@ -270,6 +277,7 @@ void GPDatabase::setupIndexMap() { } for (auto& node : nodes) { node_id2node_name.emplace_back(node.getName()); + node_id2celltype_name.emplace_back(node.getCellTypeName()); } } diff --git a/cpp_to_py/io_parser/gp/GPDatabase.h b/cpp_to_py/io_parser/gp/GPDatabase.h index e7ad338..0c77cef 100644 --- a/cpp_to_py/io_parser/gp/GPDatabase.h +++ b/cpp_to_py/io_parser/gp/GPDatabase.h @@ -42,6 +42,8 @@ public: const std::string& getNodeType() const { return node_type; } void setOriDBId(const index_type& ori_db_id_) { ori_db_id = ori_db_id_; } const index_type& getOriDBId() const { return ori_db_id; } + void setCellTypeName(const std::string& celltype_name_) { celltype_name = celltype_name_; } + const std::string& getCellTypeName() const { return celltype_name; } void setRegionId(const index_type& region_id_) { region_id = region_id_; } const index_type& getRegionId() const { return region_id; } @@ -62,6 +64,7 @@ protected: index_type region_id = -1; // no region, we should ignore fixed nodes' fence region std::vector pins_id; bool isPolygonShape = false; + std::string celltype_name = ""; // CORE/DFF*, BLOCK/RAM*, IOPIN/PinName }; class GPPin : public Basic { @@ -161,6 +164,7 @@ protected: std::vector> node_types_indices; // (start_idx, end_idx, type) std::vector node_id2node_name; + std::vector node_id2celltype_name; std::vector pin_id2node_id; // pin_id to node_id mapping std::vector pin_id2net_id; // pin_id to net_id mapping @@ -199,6 +203,7 @@ public: return node_types_indices; } const std::vector& getNodeId2NodeName() const { return node_id2node_name; } + const std::vector& getNodeId2CellTypeName() const { return node_id2celltype_name; } const std::tuple& getDieInfo() const { return dieInfo; } const std::tuple& getCoreInfo() const { return coreInfo; } diff --git a/examples/examples.json b/examples/examples.json new file mode 100644 index 0000000..983aba8 --- /dev/null +++ b/examples/examples.json @@ -0,0 +1,11 @@ +{ + "benchmark": "custom_asap7", + "design_name": "top", + "lefs": [ + "/PDK/asap7/lef/asap7_tech_1x_201209.lef", + "/PDK/asap7/lef/asap7sc7p5t_28_L_1x_220121a.lef", + "/PDK/asap7/lef/asap7sc7p5t_28_R_1x_220121a.lef", + "/PDK/asap7/lef/asap7sc7p5t_28_SL_1x_220121a.lef" + ], + "def": "/designs/top/def/top.def" +} \ No newline at end of file diff --git a/main.py b/main.py index 91a29ab..5b7de71 100644 --- a/main.py +++ b/main.py @@ -8,6 +8,7 @@ def get_option(): 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('--custom_json', type=str, default='', help='custom json path, support multi-lefs.') 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') @@ -46,6 +47,7 @@ def get_option(): parser.add_argument('--route_weight', type=float, default=0, help='the weight of route') parser.add_argument('--congest_weight', type=float, default=0, help='the weight of congested force') parser.add_argument('--pseudo_weight', type=float, default=0, help='the weight of pseudo net') + parser.add_argument('--visualize_cgmap', type=str2bool, default=False, help='visualize congestion map') # detailed placement and evaluation parser.add_argument('--detail_placement', type=str2bool, default=True, help='perform dp') diff --git a/src/database.py b/src/database.py index b1182b8..a5b430e 100644 --- a/src/database.py +++ b/src/database.py @@ -9,6 +9,9 @@ def load_dataset(args, logger, placement=None): rawdb, gpdb = None, None if args.custom_path != "": params = get_custom_design_params(args) + elif args.custom_json != "": + logger.info("Detect json mode. Please make sure that tech_lef are included first.") + params = get_custom_json_params(args) else: params = get_single_design_params( args.dataset_root, args.dataset, args.design_name, placement @@ -80,6 +83,7 @@ class PlaceData(object): site_info=None, node_type_indices=None, node_id2node_name=None, + node_id2celltype_name=None, movable_index=None, connected_index=None, fixed_index=None, @@ -112,6 +116,15 @@ class PlaceData(object): self.region_boxes = region_boxes self.region_boxes_end = region_boxes_end + # TODO: more cases? + self.node_special_type = torch.zeros(len(node_id2celltype_name), dtype=torch.int32) + if False: + for node_id, celltype_name in enumerate(node_id2celltype_name): + if celltype_name.startswith("CORE/BUF"): + self.node_special_type[node_id] = 1 + if celltype_name.startswith("CORE/DFF"): + self.node_special_type[node_id] = 2 + dataset_format = "" if "aux" in dataset_path.keys(): dataset_format = "bookshelf" @@ -122,6 +135,7 @@ class PlaceData(object): self.__design_name__ = benchmark + "/" + dataset_path["design_name"] self.__node_id2node_name__ = node_id2node_name + self.__node_id2celltype_name__ = node_id2celltype_name # NOTE: we set float movable node as connected node for convenience purposes self.__node_type_indices__ = node_type_indices @@ -196,6 +210,11 @@ class PlaceData(object): if hasattr(self, "__node_id2node_name__"): return self.__node_id2node_name__ + @property + def node_id2celltype_name(self): + if hasattr(self, "__node_id2celltype_name__"): + return self.__node_id2celltype_name__ + @property def node_type_indices(self): if hasattr(self, "__node_type_indices__"): diff --git a/src/run_placement.py b/src/run_placement.py index 5c73792..8b0fa15 100644 --- a/src/run_placement.py +++ b/src/run_placement.py @@ -4,11 +4,9 @@ from src import run_placement_main_nesterov def run_placement_single(args, logger): logger.info("=================") - logger.info("Start place %s/%s" % (args.dataset , args.design_name)) assert torch.cuda.is_available() torch.cuda.synchronize("cuda:{}".format(args.gpu)) set_random_seed(args) - setup_dataset_args(args) res = run_placement_main_nesterov(args, logger) return res diff --git a/src/run_placement_nesterov.py b/src/run_placement_nesterov.py index fb5fd70..0ef60c9 100644 --- a/src/run_placement_nesterov.py +++ b/src/run_placement_nesterov.py @@ -13,10 +13,12 @@ def get_trunc_node_pos_fn(mov_node_size, data): def run_placement_main_nesterov(args, logger): total_start = time.time() data, rawdb, gpdb = load_dataset(args, logger) + setup_dataset_args(args) 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!") if args.scale_design: logger.warning("Eplace's nesterov optimizer cannot support normalized die. Disable scale_design.") @@ -187,7 +189,7 @@ def run_placement_main_nesterov(args, logger): if ps.use_cell_inflate: output = route_inflation( args, logger, data, rawdb, gpdb, ps, mov_node_pos, mov_node_size, expand_ratio, - constraint_fn=trunc_node_pos_fn, + constraint_fn=trunc_node_pos_fn, visualize=args.visualize_cgmap ) # ps.use_cell_inflate is updated in route_inflation if not ps.use_cell_inflate: route_early_terminate_signal = True @@ -294,7 +296,7 @@ def run_placement_main_nesterov(args, logger): ps.rerun_route = True gr_metrics = run_gr_and_fft_main( args, logger, data, rawdb, gpdb, ps, mov_node_pos, constraint_fn=trunc_node_pos_fn, - skip_m1_route=True, report_gr_metrics_only=True + skip_m1_route=True, report_gr_metrics_only=True, visualize=args.visualize_cgmap ) ps.rerun_route = False ps.push_gr_sol(gr_metrics, hpwl, overflow, mov_node_pos) diff --git a/utils/__init__.py b/utils/__init__.py index b14d7a3..5dc804d 100644 --- a/utils/__init__.py +++ b/utils/__init__.py @@ -2,5 +2,5 @@ from .io_parser import IOParser from .logger import setup_logger from .visualization import * from .tools import * -from .get_design_params import get_single_design_params, get_multiple_design_params, get_custom_design_params +from .get_design_params import get_single_design_params, get_multiple_design_params, get_custom_design_params, get_custom_json_params from .setup_dataset import setup_dataset_args diff --git a/utils/get_design_params.py b/utils/get_design_params.py index 28a7095..83a9c7f 100644 --- a/utils/get_design_params.py +++ b/utils/get_design_params.py @@ -185,3 +185,16 @@ def get_custom_design_params(args): args.dataset = params["benchmark"] args.design_name = params["design_name"] return params + + +def get_custom_json_params(args): + import json + with open(args.custom_json, 'r') as f: + params = json.load(f) + 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 diff --git a/utils/io_parser.py b/utils/io_parser.py index 5740bd9..6812ee6 100644 --- a/utils/io_parser.py +++ b/utils/io_parser.py @@ -41,7 +41,15 @@ class IOParser(object): print("Can only support one input format!") return False if "def" in params.keys(): - if "lef" not 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 @@ -171,6 +179,7 @@ class IOParser(object): 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 @@ -195,6 +204,7 @@ class IOParser(object): "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, diff --git a/utils/visualization.py b/utils/visualization.py index afbab0d..140f0fd 100644 --- a/utils/visualization.py +++ b/utils/visualization.py @@ -175,7 +175,11 @@ def draw_fig_with_cairo_cpp(node_pos, node_size, data, info, args, base_size=204 ("Bin", 0.1, 0.1, 0.1, 1.0), ("Mov", 0.475, 0.706, 0.718, 0.8), ("Filler", 0.8, 0.8, 0.8, 0.8), + ("Buffer", 0.65, 0.08, 0.9, 0.8), + ("FF", 0.65, 0.9, 0.08, 0.7), ] + + node_special_type: List[int] = (data.node_special_type.cpu()).tolist() width = base_size height = round(width * (hy - ly) / (hx - lx)) draw_contents: List[str] = ["Nodes", "NodesText"] @@ -191,6 +195,7 @@ def draw_fig_with_cairo_cpp(node_pos, node_size, data, info, args, base_size=204 bin_size_info, node_type_indices, ele_type_to_rgba_vec, + node_special_type, png_path, width, height,