v2.1.1 (1) support custom_json (2) add visualize_cgmap

This commit is contained in:
liulixinkerry 2024-04-18 12:56:30 +08:00
parent 60f0920cf6
commit 8db7d4f549
24 changed files with 143 additions and 32 deletions

View File

@ -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.

View File

@ -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 != "") {

View File

@ -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) {}

View File

@ -10,6 +10,7 @@ void Setting::reset() {
LefFile = ""; LefFile = "";
LefCell = ""; LefCell = "";
LefTech = ""; LefTech = "";
LefFiles.clear();
Constraints = ""; Constraints = "";
Verilog = ""; Verilog = "";
OutputFile = ""; OutputFile = "";

View File

@ -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 = "";

View File

@ -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];

View File

@ -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());
} }

View File

@ -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]);
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); 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]);

View File

@ -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);
}; };

View File

@ -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"); }

View File

@ -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,10 +33,13 @@ 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;
@ -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++) {
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++) { for (int j = 0; j < markingBufferLUT[i].size(); j++) {
if (markingBufferLUT[i][j].size() == 0) continue; if (markingBufferLUT[i][j].size() == 0) continue;
const auto& buf = markingBufferLUT[i][j]; 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 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++) {

View File

@ -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)

View File

@ -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")) {

View File

@ -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());
} }
} }

View File

@ -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
View 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"
}

View File

@ -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')

View File

@ -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__"):

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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,