v2.1.1 (1) support custom_json (2) add visualize_cgmap
This commit is contained in:
parent
60f0920cf6
commit
8db7d4f549
@ -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.
|
||||
|
||||
@ -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 != "") {
|
||||
|
||||
@ -70,8 +70,8 @@ public:
|
||||
vector<int> parWidth;
|
||||
vector<vector<int>> parWidthSpace; // 2D table: (parWidth, parLength) -> widthSpacing
|
||||
|
||||
Track track;
|
||||
Track nonPreferDirTrack;
|
||||
vector<Track> tracks;
|
||||
vector<Track> nonPreferDirTracks;
|
||||
|
||||
Layer(const string& name = "", const char type = 'x') : _name(name), _type(type) {}
|
||||
|
||||
|
||||
@ -10,6 +10,7 @@ void Setting::reset() {
|
||||
LefFile = "";
|
||||
LefCell = "";
|
||||
LefTech = "";
|
||||
LefFiles.clear();
|
||||
Constraints = "";
|
||||
Verilog = "";
|
||||
OutputFile = "";
|
||||
|
||||
@ -27,6 +27,7 @@ public:
|
||||
std::string LefFile = "";
|
||||
std::string LefCell = "";
|
||||
std::string LefTech = "";
|
||||
std::vector<std::string> LefFiles;
|
||||
|
||||
std::string Constraints = "";
|
||||
std::string Verilog = "";
|
||||
|
||||
@ -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];
|
||||
|
||||
@ -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());
|
||||
}
|
||||
|
||||
@ -101,8 +101,10 @@ bool Drawer::run(const std::vector<double>& node_pos_x, // after die scale
|
||||
const std::tuple<double, double, double, double>& die_info, // after die scale
|
||||
const std::tuple<double, double>& site_info,
|
||||
const std::tuple<double, double>& bin_size_info, // after die scale
|
||||
std::vector<std::tuple<index_type, index_type, std::string>> node_types_indices) {
|
||||
std::vector<std::tuple<index_type, index_type, std::string>> node_types_indices,
|
||||
const std::vector<int>& 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<double>& 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]);
|
||||
|
||||
@ -23,5 +23,6 @@ public:
|
||||
const std::tuple<double, double, double, double>& die_info,
|
||||
const std::tuple<double, double>& site_info,
|
||||
const std::tuple<double, double>& bin_size_info,
|
||||
std::vector<std::tuple<index_type, index_type, std::string>> node_types_indices);
|
||||
std::vector<std::tuple<index_type, index_type, std::string>> node_types_indices,
|
||||
const std::vector<int>& node_special_type);
|
||||
};
|
||||
|
||||
@ -11,6 +11,7 @@ bool DrawGlobalPlacement(
|
||||
const std::tuple<double, double>& bin_size_info,
|
||||
const std::vector<std::tuple<index_type, index_type, std::string>>& node_types_indices,
|
||||
const std::vector<std::tuple<std::string, double, double, double, double>>& ele_type_to_rgba_vec,
|
||||
const std::vector<int>& 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"); }
|
||||
|
||||
@ -15,7 +15,7 @@ GRDatabase::GRDatabase(std::shared_ptr<db::Database> rawdb_, std::shared_ptr<gp:
|
||||
} else {
|
||||
csrnScale = grSetting.csrnScale;
|
||||
}
|
||||
if (db::setting.BookshelfVariety != "" || db::setting.LefFile == "") {
|
||||
if (db::setting.BookshelfVariety != "" || db::setting.Format != "lefdef") {
|
||||
// NOTE: GGR is a LEFDEF based detailed-routability driven global placer and it is not
|
||||
// designed for the old bookshelf designs. For bookshelf, please consider to use
|
||||
// NCTU-GR to generate the routing congestion maps. Note that existing bookshelf
|
||||
@ -33,10 +33,13 @@ GRDatabase::GRDatabase(std::shared_ptr<db::Database> rawdb_, std::shared_ptr<gp:
|
||||
auto rLayer = rawdb.getRLayer(l);
|
||||
layerWidth[l] = rLayer->width;
|
||||
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<int> GRDatabase::getObsMargin(RectOnLayer box, AggrParaRunSpace ag
|
||||
|
||||
utils::IntervalT<int> GRDatabase::rangeSearchTracks(const utils::IntervalT<int>& 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<int>(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<int>(lpos, hpos);
|
||||
}
|
||||
|
||||
@ -480,9 +483,9 @@ void GRDatabase::markObs(std::vector<RectOnLayer>& allObs,
|
||||
vector<vector<vector<std::pair<utils::IntervalT<int>, 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<int>(t.size()) - 1, pos);
|
||||
while (pos > 0 && t[pos - 1] >= p) pos--;
|
||||
return pos;
|
||||
};
|
||||
|
||||
@ -561,12 +564,12 @@ void GRDatabase::markObs(std::vector<RectOnLayer>& allObs,
|
||||
}
|
||||
|
||||
for (int i = 0; i < markingBufferLUT.size(); i++) {
|
||||
utils::IntervalT<int> 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<int> gridTrackIntvl;
|
||||
gridTrackIntvl.low = searchLowerBoundTrack(gridlines[1 - dir][i]);
|
||||
gridTrackIntvl.high = searchLowerBoundTrack(gridlines[1 - dir][i + 1]) - 1;
|
||||
vector<int> trackBlocked(gridTrackIntvl.range() + 1, 0); // blocked track length
|
||||
for (auto& pair : buf) {
|
||||
for (int k = pair.first.low; k <= pair.first.high; k++) {
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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<std::string>();
|
||||
db::setting.LefTech = kwargs["tech_lef"].cast<std::string>();
|
||||
} else if (kwargs.contains("lefs")) {
|
||||
for (auto lef_py : kwargs["lefs"]) {
|
||||
auto lef = lef_py.cast<std::string>();
|
||||
db::setting.LefFiles.emplace_back(lef);
|
||||
}
|
||||
}
|
||||
|
||||
if (kwargs.contains("constraints")) {
|
||||
|
||||
@ -21,6 +21,9 @@ void GPDatabase::addCellNode(index_type cell_id, std::string& node_type) {
|
||||
node.setRegionId(static_cast<index_type>(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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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<index_type> 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<std::tuple<index_type, index_type, std::string>> node_types_indices; // (start_idx, end_idx, type)
|
||||
std::vector<std::string> node_id2node_name;
|
||||
std::vector<std::string> node_id2celltype_name;
|
||||
|
||||
std::vector<index_type> pin_id2node_id; // pin_id to node_id mapping
|
||||
std::vector<index_type> pin_id2net_id; // pin_id to net_id mapping
|
||||
@ -199,6 +203,7 @@ public:
|
||||
return node_types_indices;
|
||||
}
|
||||
const std::vector<std::string>& getNodeId2NodeName() const { return node_id2node_name; }
|
||||
const std::vector<std::string>& getNodeId2CellTypeName() const { return node_id2celltype_name; }
|
||||
|
||||
const std::tuple<int, int, int, int>& getDieInfo() const { return dieInfo; }
|
||||
const std::tuple<int, int, int, int>& getCoreInfo() const { return coreInfo; }
|
||||
|
||||
11
examples/examples.json
Normal file
11
examples/examples.json
Normal file
@ -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"
|
||||
}
|
||||
2
main.py
2
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')
|
||||
|
||||
@ -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__"):
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user