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
|
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)
|
## 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.
|
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";
|
setting.Format = "lefdef";
|
||||||
readLEF(setting.LefTech);
|
readLEF(setting.LefTech);
|
||||||
readLEF(setting.LefCell);
|
readLEF(setting.LefCell);
|
||||||
|
} else if (setting.LefFiles.size() > 0) {
|
||||||
|
setting.Format = "lefdef";
|
||||||
|
for (auto lef : setting.LefFiles) {
|
||||||
|
readLEF(lef);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (setting.DefFile != "") {
|
if (setting.DefFile != "") {
|
||||||
|
|||||||
@ -70,8 +70,8 @@ public:
|
|||||||
vector<int> parWidth;
|
vector<int> parWidth;
|
||||||
vector<vector<int>> parWidthSpace; // 2D table: (parWidth, parLength) -> widthSpacing
|
vector<vector<int>> parWidthSpace; // 2D table: (parWidth, parLength) -> widthSpacing
|
||||||
|
|
||||||
Track track;
|
vector<Track> tracks;
|
||||||
Track nonPreferDirTrack;
|
vector<Track> nonPreferDirTracks;
|
||||||
|
|
||||||
Layer(const string& name = "", const char type = 'x') : _name(name), _type(type) {}
|
Layer(const string& name = "", const char type = 'x') : _name(name), _type(type) {}
|
||||||
|
|
||||||
|
|||||||
@ -10,6 +10,7 @@ void Setting::reset() {
|
|||||||
LefFile = "";
|
LefFile = "";
|
||||||
LefCell = "";
|
LefCell = "";
|
||||||
LefTech = "";
|
LefTech = "";
|
||||||
|
LefFiles.clear();
|
||||||
Constraints = "";
|
Constraints = "";
|
||||||
Verilog = "";
|
Verilog = "";
|
||||||
OutputFile = "";
|
OutputFile = "";
|
||||||
|
|||||||
@ -27,6 +27,7 @@ public:
|
|||||||
std::string LefFile = "";
|
std::string LefFile = "";
|
||||||
std::string LefCell = "";
|
std::string LefCell = "";
|
||||||
std::string LefTech = "";
|
std::string LefTech = "";
|
||||||
|
std::vector<std::string> LefFiles;
|
||||||
|
|
||||||
std::string Constraints = "";
|
std::string Constraints = "";
|
||||||
std::string Verilog = "";
|
std::string Verilog = "";
|
||||||
|
|||||||
@ -490,10 +490,10 @@ bool Database::readBSAux(const std::string& auxFile, const std::string& plFile)
|
|||||||
// } else if (i % 2) {
|
// } else if (i % 2) {
|
||||||
if (i % 2) {
|
if (i % 2) {
|
||||||
layer.direction = m2direction;
|
layer.direction = m2direction;
|
||||||
layer.track.direction = m2direction;
|
// layer.track.direction = m2direction;
|
||||||
} else {
|
} else {
|
||||||
layer.direction = m1direction;
|
layer.direction = m1direction;
|
||||||
layer.track.direction = m1direction;
|
// layer.track.direction = m1direction;
|
||||||
}
|
}
|
||||||
if (isDac2012) {
|
if (isDac2012) {
|
||||||
layer.width = bsData.wireWidth[i];
|
layer.width = bsData.wireWidth[i];
|
||||||
|
|||||||
@ -1325,11 +1325,11 @@ int readDefTrack(defrCallbackType_e c, defiTrack* dtrack, defiUserData ud) {
|
|||||||
Layer* layer = db->getLayer(layername);
|
Layer* layer = db->getLayer(layername);
|
||||||
if (layer) {
|
if (layer) {
|
||||||
if (track->direction == 'x' || layer->direction == 'x') {
|
if (track->direction == 'x' || layer->direction == 'x') {
|
||||||
layer->track = *track;
|
layer->tracks.push_back(*track);
|
||||||
} else if (layer->direction == track->direction) {
|
} else if (layer->direction == track->direction) {
|
||||||
layer->track = *track;
|
layer->tracks.push_back(*track);
|
||||||
} else if (layer->direction != track->direction) {
|
} else if (layer->direction != track->direction) {
|
||||||
layer->nonPreferDirTrack = *track;
|
layer->nonPreferDirTracks.push_back(*track);
|
||||||
} else {
|
} else {
|
||||||
logger.error("wrong definition of tracks for layer %s", layername.c_str());
|
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, double, double>& die_info, // after die scale
|
||||||
const std::tuple<double, double>& site_info,
|
const std::tuple<double, double>& site_info,
|
||||||
const std::tuple<double, double>& bin_size_info, // after die scale
|
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
|
// init cairo
|
||||||
|
bool special_cell = !node_special_type.empty();
|
||||||
cairo_surface_t* cs;
|
cairo_surface_t* cs;
|
||||||
if (format == "png") {
|
if (format == "png") {
|
||||||
cs = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
|
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_lx = node_pos_x[i] - node_size_x[i] / 2;
|
||||||
double node_ly = node_pos_y[i] - node_size_y[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]);
|
cairo_rectangle(c, node_lx, node_ly, node_size_x[i], node_size_y[i]);
|
||||||
|
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);
|
set_rgba(node_type);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else set_rgba(node_type);
|
||||||
cairo_fill(c);
|
cairo_fill(c);
|
||||||
if (draw_node_bd) {
|
if (draw_node_bd) {
|
||||||
cairo_rectangle(c, node_lx, node_ly, node_size_x[i], node_size_y[i]);
|
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, double, double>& die_info,
|
||||||
const std::tuple<double, double>& site_info,
|
const std::tuple<double, double>& site_info,
|
||||||
const std::tuple<double, double>& bin_size_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::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<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<std::tuple<std::string, double, double, double, double>>& ele_type_to_rgba_vec,
|
||||||
|
const std::vector<int>& node_special_type,
|
||||||
const std::string& filename,
|
const std::string& filename,
|
||||||
double width,
|
double width,
|
||||||
double height,
|
double height,
|
||||||
@ -25,8 +26,8 @@ bool DrawGlobalPlacement(
|
|||||||
die_info,
|
die_info,
|
||||||
site_info,
|
site_info,
|
||||||
bin_size_info,
|
bin_size_info,
|
||||||
node_types_indices);
|
node_types_indices,
|
||||||
|
node_special_type);
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
PYBIND11_MODULE(TORCH_EXTENSION_NAME, m) { m.def("draw", &DrawGlobalPlacement, "Draw placement results"); }
|
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 {
|
} else {
|
||||||
csrnScale = grSetting.csrnScale;
|
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
|
// 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
|
// designed for the old bookshelf designs. For bookshelf, please consider to use
|
||||||
// NCTU-GR to generate the routing congestion maps. Note that existing bookshelf
|
// NCTU-GR to generate the routing congestion maps. Note that existing bookshelf
|
||||||
@ -33,11 +33,14 @@ GRDatabase::GRDatabase(std::shared_ptr<db::Database> rawdb_, std::shared_ptr<gp:
|
|||||||
auto rLayer = rawdb.getRLayer(l);
|
auto rLayer = rawdb.getRLayer(l);
|
||||||
layerWidth[l] = rLayer->width;
|
layerWidth[l] = rLayer->width;
|
||||||
layerPitch[l] = rLayer->pitch;
|
layerPitch[l] = rLayer->pitch;
|
||||||
db::Track& track = rLayer->track;
|
for (auto& track : rLayer->tracks) {
|
||||||
for (int i = 0; i < track.num; i++) {
|
for (int i = 0; i < track.num; i++) {
|
||||||
tracks[l].emplace_back(i * track.step + track.start);
|
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;
|
m1direction = rawdb.getRLayer(0)->direction == 'v' ? 1 : 0;
|
||||||
microns = rawdb.LefConvertFactor;
|
microns = rawdb.LefConvertFactor;
|
||||||
if (nLayers > 1) {
|
if (nLayers > 1) {
|
||||||
@ -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) {
|
utils::IntervalT<int> GRDatabase::rangeSearchTracks(const utils::IntervalT<int>& locRange, int layerIdx) {
|
||||||
auto& t = tracks[layerIdx];
|
auto& t = tracks[layerIdx];
|
||||||
int lpos = locRange.low / layerPitch[layerIdx];
|
int lpos = lower_bound(t.begin(), t.end(), locRange.low) - t.begin();
|
||||||
while (lpos + 1 < t.size() && t[lpos] < locRange.low) lpos++;
|
lpos = std::min(static_cast<int>(t.size()) - 1, lpos);
|
||||||
while (lpos > 0 && t[lpos - 1] >= locRange.low) lpos--;
|
while (lpos > 0 && t[lpos - 1] >= locRange.low) lpos--;
|
||||||
int hpos = locRange.high / layerPitch[layerIdx];
|
int hpos = upper_bound(t.begin(), t.end(), locRange.high) - t.begin() - 1;
|
||||||
while (hpos > 0 && t[hpos] > locRange.high) hpos--;
|
hpos = std::max(hpos, 0);
|
||||||
return utils::IntervalT<int>(lpos, hpos);
|
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;
|
vector<vector<vector<std::pair<utils::IntervalT<int>, int>>>> markingBufferLUT;
|
||||||
|
|
||||||
auto searchLowerBoundTrack = [&](int p) {
|
auto searchLowerBoundTrack = [&](int p) {
|
||||||
int pos = p / layerPitch[l];
|
int pos = lower_bound(t.begin(), t.end(), p) - t.begin();
|
||||||
while (pos + 1 < t.size() && t[pos] < p) pos++;
|
pos = std::min(static_cast<int>(t.size()) - 1, pos);
|
||||||
while (pos && t[pos - 1] >= p) pos--;
|
while (pos > 0 && t[pos - 1] >= p) pos--;
|
||||||
return pos;
|
return pos;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -561,12 +564,12 @@ void GRDatabase::markObs(std::vector<RectOnLayer>& allObs,
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < markingBufferLUT.size(); i++) {
|
for (int i = 0; i < markingBufferLUT.size(); i++) {
|
||||||
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;
|
utils::IntervalT<int> gridTrackIntvl;
|
||||||
gridTrackIntvl.low = searchLowerBoundTrack(gridlines[1 - dir][i]);
|
gridTrackIntvl.low = searchLowerBoundTrack(gridlines[1 - dir][i]);
|
||||||
gridTrackIntvl.high = searchLowerBoundTrack(gridlines[1 - dir][i + 1]) - 1;
|
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];
|
||||||
vector<int> trackBlocked(gridTrackIntvl.range() + 1, 0); // blocked track length
|
vector<int> trackBlocked(gridTrackIntvl.range() + 1, 0); // blocked track length
|
||||||
for (auto& pair : buf) {
|
for (auto& pair : buf) {
|
||||||
for (int k = pair.first.low; k <= pair.first.high; k++) {
|
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("m1direction", &gp::GPDatabase::getM1Direction, py::return_value_policy::copy)
|
||||||
.def("node_type_indices", &gp::GPDatabase::getNodeTypeIndices, 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_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_lpos_tensor", &gp::GPDatabase::getNodeLPosTensor, py::return_value_policy::move)
|
||||||
.def("node_cpos_tensor", &gp::GPDatabase::getNodeCPosTensor, 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)
|
.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")) {
|
} else if (kwargs.contains("cell_lef") && kwargs.contains("tech_lef")) {
|
||||||
db::setting.LefCell = kwargs["cell_lef"].cast<std::string>();
|
db::setting.LefCell = kwargs["cell_lef"].cast<std::string>();
|
||||||
db::setting.LefTech = kwargs["tech_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")) {
|
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));
|
node.setRegionId(static_cast<index_type>(cell->region->id));
|
||||||
regions[node.getRegionId()].addNode(node.getId());
|
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) {
|
if (cell->fixed() && cell->ctype()->nonRegularRects().size() > 0) {
|
||||||
node.setIsPolygonShape(true);
|
node.setIsPolygonShape(true);
|
||||||
}
|
}
|
||||||
@ -41,6 +44,8 @@ void GPDatabase::addIOPinNode(index_type iopin_id, std::string& node_type) {
|
|||||||
node.setNodeType(node_type);
|
node.setNodeType(node_type);
|
||||||
node.setOriDBId(iopin_id);
|
node.setOriDBId(iopin_id);
|
||||||
|
|
||||||
|
node.setCellTypeName(iopin->name);
|
||||||
|
|
||||||
iopin->gpdb_id = nodes.size() - 1;
|
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.setOrient(-1); // No orientation for placement blockage
|
||||||
node.setNodeType(node_type);
|
node.setNodeType(node_type);
|
||||||
node.setOriDBId(blkg_id);
|
node.setOriDBId(blkg_id);
|
||||||
|
|
||||||
|
node.setCellTypeName(blockage_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPDatabase::addNet(index_type dbnet_id) {
|
void GPDatabase::addNet(index_type dbnet_id) {
|
||||||
@ -270,6 +277,7 @@ void GPDatabase::setupIndexMap() {
|
|||||||
}
|
}
|
||||||
for (auto& node : nodes) {
|
for (auto& node : nodes) {
|
||||||
node_id2node_name.emplace_back(node.getName());
|
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; }
|
const std::string& getNodeType() const { return node_type; }
|
||||||
void setOriDBId(const index_type& ori_db_id_) { ori_db_id = ori_db_id_; }
|
void setOriDBId(const index_type& ori_db_id_) { ori_db_id = ori_db_id_; }
|
||||||
const index_type& getOriDBId() const { return 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_; }
|
void setRegionId(const index_type& region_id_) { region_id = region_id_; }
|
||||||
const index_type& getRegionId() const { return 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
|
index_type region_id = -1; // no region, we should ignore fixed nodes' fence region
|
||||||
std::vector<index_type> pins_id;
|
std::vector<index_type> pins_id;
|
||||||
bool isPolygonShape = false;
|
bool isPolygonShape = false;
|
||||||
|
std::string celltype_name = ""; // CORE/DFF*, BLOCK/RAM*, IOPIN/PinName
|
||||||
};
|
};
|
||||||
|
|
||||||
class GPPin : public Basic {
|
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::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_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_id2node_id; // pin_id to node_id mapping
|
||||||
std::vector<index_type> pin_id2net_id; // pin_id to net_id mapping
|
std::vector<index_type> pin_id2net_id; // pin_id to net_id mapping
|
||||||
@ -199,6 +203,7 @@ public:
|
|||||||
return node_types_indices;
|
return node_types_indices;
|
||||||
}
|
}
|
||||||
const std::vector<std::string>& getNodeId2NodeName() const { return node_id2node_name; }
|
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>& getDieInfo() const { return dieInfo; }
|
||||||
const std::tuple<int, int, int, int>& getCoreInfo() const { return coreInfo; }
|
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('--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('--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_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('--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('--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')
|
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('--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('--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('--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
|
# detailed placement and evaluation
|
||||||
parser.add_argument('--detail_placement', type=str2bool, default=True, help='perform dp')
|
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
|
rawdb, gpdb = None, None
|
||||||
if args.custom_path != "":
|
if args.custom_path != "":
|
||||||
params = get_custom_design_params(args)
|
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:
|
else:
|
||||||
params = get_single_design_params(
|
params = get_single_design_params(
|
||||||
args.dataset_root, args.dataset, args.design_name, placement
|
args.dataset_root, args.dataset, args.design_name, placement
|
||||||
@ -80,6 +83,7 @@ class PlaceData(object):
|
|||||||
site_info=None,
|
site_info=None,
|
||||||
node_type_indices=None,
|
node_type_indices=None,
|
||||||
node_id2node_name=None,
|
node_id2node_name=None,
|
||||||
|
node_id2celltype_name=None,
|
||||||
movable_index=None,
|
movable_index=None,
|
||||||
connected_index=None,
|
connected_index=None,
|
||||||
fixed_index=None,
|
fixed_index=None,
|
||||||
@ -112,6 +116,15 @@ class PlaceData(object):
|
|||||||
self.region_boxes = region_boxes
|
self.region_boxes = region_boxes
|
||||||
self.region_boxes_end = region_boxes_end
|
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 = ""
|
dataset_format = ""
|
||||||
if "aux" in dataset_path.keys():
|
if "aux" in dataset_path.keys():
|
||||||
dataset_format = "bookshelf"
|
dataset_format = "bookshelf"
|
||||||
@ -122,6 +135,7 @@ class PlaceData(object):
|
|||||||
self.__design_name__ = benchmark + "/" + dataset_path["design_name"]
|
self.__design_name__ = benchmark + "/" + dataset_path["design_name"]
|
||||||
|
|
||||||
self.__node_id2node_name__ = node_id2node_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
|
# NOTE: we set float movable node as connected node for convenience purposes
|
||||||
self.__node_type_indices__ = node_type_indices
|
self.__node_type_indices__ = node_type_indices
|
||||||
@ -196,6 +210,11 @@ class PlaceData(object):
|
|||||||
if hasattr(self, "__node_id2node_name__"):
|
if hasattr(self, "__node_id2node_name__"):
|
||||||
return 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
|
@property
|
||||||
def node_type_indices(self):
|
def node_type_indices(self):
|
||||||
if hasattr(self, "__node_type_indices__"):
|
if hasattr(self, "__node_type_indices__"):
|
||||||
|
|||||||
@ -4,11 +4,9 @@ from src import run_placement_main_nesterov
|
|||||||
|
|
||||||
def run_placement_single(args, logger):
|
def run_placement_single(args, logger):
|
||||||
logger.info("=================")
|
logger.info("=================")
|
||||||
logger.info("Start place %s/%s" % (args.dataset , args.design_name))
|
|
||||||
assert torch.cuda.is_available()
|
assert torch.cuda.is_available()
|
||||||
torch.cuda.synchronize("cuda:{}".format(args.gpu))
|
torch.cuda.synchronize("cuda:{}".format(args.gpu))
|
||||||
set_random_seed(args)
|
set_random_seed(args)
|
||||||
setup_dataset_args(args)
|
|
||||||
res = run_placement_main_nesterov(args, logger)
|
res = run_placement_main_nesterov(args, logger)
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
|||||||
@ -13,10 +13,12 @@ def get_trunc_node_pos_fn(mov_node_size, data):
|
|||||||
def run_placement_main_nesterov(args, logger):
|
def run_placement_main_nesterov(args, logger):
|
||||||
total_start = time.time()
|
total_start = time.time()
|
||||||
data, rawdb, gpdb = load_dataset(args, logger)
|
data, rawdb, gpdb = load_dataset(args, logger)
|
||||||
|
setup_dataset_args(args)
|
||||||
device = torch.device(
|
device = torch.device(
|
||||||
"cuda:{}".format(args.gpu) if torch.cuda.is_available() else "cpu"
|
"cuda:{}".format(args.gpu) if torch.cuda.is_available() else "cpu"
|
||||||
)
|
)
|
||||||
assert args.use_eplace_nesterov
|
assert args.use_eplace_nesterov
|
||||||
|
logger.info("Start place %s/%s" % (args.dataset , args.design_name))
|
||||||
logger.info("Use Nesterov optimizer!")
|
logger.info("Use Nesterov optimizer!")
|
||||||
if args.scale_design:
|
if args.scale_design:
|
||||||
logger.warning("Eplace's nesterov optimizer cannot support normalized die. Disable 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:
|
if ps.use_cell_inflate:
|
||||||
output = route_inflation(
|
output = route_inflation(
|
||||||
args, logger, data, rawdb, gpdb, ps, mov_node_pos, mov_node_size, expand_ratio,
|
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
|
) # ps.use_cell_inflate is updated in route_inflation
|
||||||
if not ps.use_cell_inflate:
|
if not ps.use_cell_inflate:
|
||||||
route_early_terminate_signal = True
|
route_early_terminate_signal = True
|
||||||
@ -294,7 +296,7 @@ def run_placement_main_nesterov(args, logger):
|
|||||||
ps.rerun_route = True
|
ps.rerun_route = True
|
||||||
gr_metrics = run_gr_and_fft_main(
|
gr_metrics = run_gr_and_fft_main(
|
||||||
args, logger, data, rawdb, gpdb, ps, mov_node_pos, constraint_fn=trunc_node_pos_fn,
|
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.rerun_route = False
|
||||||
ps.push_gr_sol(gr_metrics, hpwl, overflow, mov_node_pos)
|
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 .logger import setup_logger
|
||||||
from .visualization import *
|
from .visualization import *
|
||||||
from .tools 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
|
from .setup_dataset import setup_dataset_args
|
||||||
|
|||||||
@ -185,3 +185,16 @@ def get_custom_design_params(args):
|
|||||||
args.dataset = params["benchmark"]
|
args.dataset = params["benchmark"]
|
||||||
args.design_name = params["design_name"]
|
args.design_name = params["design_name"]
|
||||||
return params
|
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!")
|
print("Can only support one input format!")
|
||||||
return False
|
return False
|
||||||
if "def" in params.keys():
|
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():
|
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")
|
print("lef or (cell_lef and tech_lef) is not found")
|
||||||
return False
|
return False
|
||||||
@ -171,6 +179,7 @@ class IOParser(object):
|
|||||||
|
|
||||||
node_type_indices = gpdb.node_type_indices()
|
node_type_indices = gpdb.node_type_indices()
|
||||||
node_id2node_name = gpdb.node_id2node_name()
|
node_id2node_name = gpdb.node_id2node_name()
|
||||||
|
node_id2celltype_name = gpdb.node_id2celltype_name()
|
||||||
all_node_types = []
|
all_node_types = []
|
||||||
mov_end_idx = None
|
mov_end_idx = None
|
||||||
fix_end_idx = None
|
fix_end_idx = None
|
||||||
@ -195,6 +204,7 @@ class IOParser(object):
|
|||||||
"dataset_path": self.params,
|
"dataset_path": self.params,
|
||||||
"node_type_indices": node_type_indices,
|
"node_type_indices": node_type_indices,
|
||||||
"node_id2node_name": node_id2node_name,
|
"node_id2node_name": node_id2node_name,
|
||||||
|
"node_id2celltype_name": node_id2celltype_name,
|
||||||
"movable_index": movable_index,
|
"movable_index": movable_index,
|
||||||
"connected_index": connected_index,
|
"connected_index": connected_index,
|
||||||
"fixed_index": fixed_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),
|
("Bin", 0.1, 0.1, 0.1, 1.0),
|
||||||
("Mov", 0.475, 0.706, 0.718, 0.8),
|
("Mov", 0.475, 0.706, 0.718, 0.8),
|
||||||
("Filler", 0.8, 0.8, 0.8, 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
|
width = base_size
|
||||||
height = round(width * (hy - ly) / (hx - lx))
|
height = round(width * (hy - ly) / (hx - lx))
|
||||||
draw_contents: List[str] = ["Nodes", "NodesText"]
|
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,
|
bin_size_info,
|
||||||
node_type_indices,
|
node_type_indices,
|
||||||
ele_type_to_rgba_vec,
|
ele_type_to_rgba_vec,
|
||||||
|
node_special_type,
|
||||||
png_path,
|
png_path,
|
||||||
width,
|
width,
|
||||||
height,
|
height,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user