diff --git a/cpp_to_py/gpudp/check/legality_check.cpp b/cpp_to_py/gpudp/check/legality_check.cpp index 4cd20a5..537e022 100644 --- a/cpp_to_py/gpudp/check/legality_check.cpp +++ b/cpp_to_py/gpudp/check/legality_check.cpp @@ -226,24 +226,19 @@ bool overlapCheck(const float* x, // This will cause failure to detect some overlaps. // We need to remove the "small" fixed cell that is inside another. if (!nodes_in_row.empty()) { - std::vector tmp_nodes; - tmp_nodes.reserve(nodes_in_row.size()); - tmp_nodes.push_back(nodes_in_row.front()); - for (int j = 1, je = nodes_in_row.size(); j < je; ++j) { + for (int j = 1; j < nodes_in_row.size(); ++j) { int node_id1 = nodes_in_row.at(j - 1); int node_id2 = nodes_in_row.at(j); // two fixed cells if (node_id1 >= num_movable_nodes && node_id2 >= num_movable_nodes) { float xh1 = getXH(node_id1); float xh2 = getXH(node_id2); - if (xh1 < xh2) { - tmp_nodes.push_back(node_id2); + if (xh1 >= xh2 && !nodes_in_row.empty()) { + nodes_in_row.erase(nodes_in_row.begin() + j); + --j; } - } else { - tmp_nodes.push_back(node_id2); } } - nodes_in_row.swap(tmp_nodes); } } diff --git a/cpp_to_py/gpudp/db/dp_torch.cpp b/cpp_to_py/gpudp/db/dp_torch.cpp index b6e2602..5f89236 100644 --- a/cpp_to_py/gpudp/db/dp_torch.cpp +++ b/cpp_to_py/gpudp/db/dp_torch.cpp @@ -94,21 +94,22 @@ bool DPTorchRawDB::check(float scale_factor) { } void DPTorchRawDB::scale(float scale_factor, bool use_round) { + torch::Tensor scalar_at = torch::tensor({scale_factor}, torch::dtype(torch::kFloat32).device(node_size.device())); if (use_round) { - pin_rel_lpos.mul_(scale_factor); - node_size.mul_(scale_factor).round_(); - node_lpos_init.mul_(scale_factor).round_(); + pin_rel_lpos.mul_(scalar_at); + node_size.mul_(scalar_at).round_(); + node_lpos_init.mul_(scalar_at).round_(); - node_size_x.mul_(scale_factor).round_(); - node_size_y.mul_(scale_factor).round_(); - init_x.mul_(scale_factor).round_(); - init_y.mul_(scale_factor).round_(); - pin_offset_x.mul_(scale_factor).round_(); - pin_offset_y.mul_(scale_factor).round_(); - x.mul_(scale_factor).round_(); - y.mul_(scale_factor).round_(); + node_size_x.mul_(scalar_at).round_(); + node_size_y.mul_(scalar_at).round_(); + init_x.mul_(scalar_at).round_(); + init_y.mul_(scalar_at).round_(); + pin_offset_x.mul_(scalar_at).round_(); + pin_offset_y.mul_(scalar_at).round_(); + x.mul_(scalar_at).round_(); + y.mul_(scalar_at).round_(); - flat_region_boxes.mul_(scale_factor).round_(); + flat_region_boxes.mul_(scalar_at).round_(); site_width = round(site_width * scale_factor); row_height = round(row_height * scale_factor); xl = round(xl * scale_factor); @@ -117,20 +118,23 @@ void DPTorchRawDB::scale(float scale_factor, bool use_round) { yh = round(yh * scale_factor); } else { float inv_scale_factor = std::round(1.0 / scale_factor); - pin_rel_lpos.div_(inv_scale_factor); - node_size.div_(inv_scale_factor); - node_lpos_init.div_(inv_scale_factor); + torch::Tensor inv_scalar_at = + torch::tensor({inv_scale_factor}, torch::dtype(torch::kFloat32).device(node_size.device())); - node_size_x.div_(inv_scale_factor); - node_size_y.div_(inv_scale_factor); - init_x.div_(inv_scale_factor); - init_y.div_(inv_scale_factor); - pin_offset_x.div_(inv_scale_factor); - pin_offset_y.div_(inv_scale_factor); - x.div_(inv_scale_factor); - y.div_(inv_scale_factor); + pin_rel_lpos.div_(inv_scalar_at); + node_size.div_(inv_scalar_at); + node_lpos_init.div_(inv_scalar_at); - flat_region_boxes.div_(inv_scale_factor); + node_size_x.div_(inv_scalar_at); + node_size_y.div_(inv_scalar_at); + init_x.div_(inv_scalar_at); + init_y.div_(inv_scalar_at); + pin_offset_x.div_(inv_scalar_at); + pin_offset_y.div_(inv_scalar_at); + x.div_(inv_scalar_at); + y.div_(inv_scalar_at); + + flat_region_boxes.div_(inv_scalar_at); site_width = site_width / inv_scale_factor; row_height = row_height / inv_scale_factor; xl = xl / inv_scale_factor; diff --git a/cpp_to_py/gpudp/dp/detailed_place_db.cuh b/cpp_to_py/gpudp/dp/detailed_place_db.cuh index 49d6fae..d8e2705 100644 --- a/cpp_to_py/gpudp/dp/detailed_place_db.cuh +++ b/cpp_to_py/gpudp/dp/detailed_place_db.cuh @@ -274,12 +274,60 @@ public: return legal_flag; } + std::vector> reorder_row_map( + const float* host_x, const float* host_y, const float* host_node_size_x, const float* host_node_size_y, std::vector>& row2node_map, int sort_coord) { + if (sort_coord < 0 || sort_coord > 2) sort_coord = 0; + + std::vector> row2node_map_helper; + // copy row2node_map to row2node_map_helper + row2node_map_helper.resize(row2node_map.size()); + for (int i = 0; i < row2node_map.size(); ++i) { + row2node_map_helper[i] = row2node_map[i]; + } + + // sort according to right + for (int i = 0; i < row2node_map.size(); ++i) { + auto& row2nodes = row2node_map_helper[i]; + if (!row2nodes.empty()) { + switch (sort_coord) { + case 0: // center + std::sort(row2nodes.begin(), row2nodes.end(), [&](int node_id1, int node_id2) { + float x1 = host_x[node_id1] + host_node_size_x[node_id1] / 2; + float x2 = host_x[node_id2] + host_node_size_x[node_id2] / 2; + return x1 < x2 || (x1 == x2 && node_id1 < node_id2); + }); + break; + case 1: // left + std::sort(row2nodes.begin(), row2nodes.end(), [&](int node_id1, int node_id2) { + float x1 = host_x[node_id1]; + float x2 = host_x[node_id2]; + return x1 < x2 || (x1 == x2 && node_id1 < node_id2); + }); + break; + case 2: // right + std::sort(row2nodes.begin(), row2nodes.end(), [&](int node_id1, int node_id2) { + float x1 = host_x[node_id1] + host_node_size_x[node_id1]; + float x2 = host_x[node_id2] + host_node_size_x[node_id2]; + return x1 < x2 || (x1 == x2 && node_id1 < node_id2); + }); + break; + default: + break; + } + } + } + + return row2node_map_helper; + } + void make_row2node_map(const float* host_x, const float* host_y, const float* host_node_size_x, const float* host_node_size_y, int host_num_nodes, - std::vector>& row2node_map) { + std::vector>& row2node_map, + int sort_coord = 0) { + if (sort_coord < 0 || sort_coord > 2) sort_coord = 0; // distribute cells to rows for (int i = 0; i < host_num_nodes; ++i) { float node_yl = host_y[i]; @@ -312,10 +360,7 @@ public: return x1 < x2 || (x1 == x2 && node_id1 < node_id2); }); if (!row2nodes.empty()) { - std::vector tmp_nodes; - tmp_nodes.reserve(row2nodes.size()); - tmp_nodes.push_back(row2nodes.front()); - for (int j = 1, je = row2nodes.size(); j < je; ++j) { + for (int j = 1; j < row2nodes.size(); ++j) { int node_id1 = row2nodes.at(j - 1); int node_id2 = row2nodes.at(j); // two fixed cells @@ -327,21 +372,39 @@ public: float xh1 = xl1 + width1; float xh2 = xl2 + width2; // only collect node_id2 if its right edge is righter than node_id1 - if (xh1 < xh2) { - tmp_nodes.push_back(node_id2); + if (xh1 >= xh2 && !row2nodes.empty()) { + row2nodes.erase(row2nodes.begin() + j); + --j; } - } else { - tmp_nodes.push_back(node_id2); } } - row2nodes.swap(tmp_nodes); // sort according to center - std::sort(row2nodes.begin(), row2nodes.end(), [&](int node_id1, int node_id2) { - float x1 = host_x[node_id1] + host_node_size_x[node_id1] / 2; - float x2 = host_x[node_id2] + host_node_size_x[node_id2] / 2; - return x1 < x2 || (x1 == x2 && node_id1 < node_id2); - }); + switch (sort_coord) { + case 0: // center + std::sort(row2nodes.begin(), row2nodes.end(), [&](int node_id1, int node_id2) { + float x1 = host_x[node_id1] + host_node_size_x[node_id1] / 2; + float x2 = host_x[node_id2] + host_node_size_x[node_id2] / 2; + return x1 < x2 || (x1 == x2 && node_id1 < node_id2); + }); + break; + case 1: // left + std::sort(row2nodes.begin(), row2nodes.end(), [&](int node_id1, int node_id2) { + float x1 = host_x[node_id1]; + float x2 = host_x[node_id2]; + return x1 < x2 || (x1 == x2 && node_id1 < node_id2); + }); + break; + case 2: // right + std::sort(row2nodes.begin(), row2nodes.end(), [&](int node_id1, int node_id2) { + float x1 = host_x[node_id1] + host_node_size_x[node_id1]; + float x2 = host_x[node_id2] + host_node_size_x[node_id2]; + return x1 < x2 || (x1 == x2 && node_id1 < node_id2); + }); + break; + default: + break; + } } } } @@ -352,8 +415,12 @@ public: const float* host_node_size_y, std::vector>& row2node_map, std::vector& node2row_map, - std::vector>& spaces) { - make_row2node_map(host_x, host_y, host_node_size_x, host_node_size_y, num_nodes + 2, row2node_map); + std::vector>& spaces, + int sort_coord = 0) { + make_row2node_map(host_x, host_y, host_node_size_x, host_node_size_y, num_nodes + 2, row2node_map, sort_coord); + + // copy row2node_map to row2node_map_helper + std::vector> row2node_map_helper = reorder_row_map(host_x, host_y, host_node_size_x, host_node_size_y, row2node_map, sort_coord); // construct node2row_map for (int i = 0; i < num_sites_y; ++i) { @@ -373,7 +440,10 @@ public: int node_id = row2node_map[i][j]; if (node_id < num_movable_nodes) { assert(j); - int left_node_id = row2node_map[i][j - 1]; + // int left_node_id = row2node_map[i][j - 1]; + int j_helper = std::find(row2node_map_helper[i].begin(), row2node_map_helper[i].end(), node_id) - row2node_map_helper[i].begin(); + int left_node_id = row2node_map[i][j_helper - 1]; + spaces[node_id].xl = host_x[left_node_id] + host_node_size_x[left_node_id]; assert(j + 1 < row2node_map[i].size()); int right_node_id = row2node_map[i][j + 1]; diff --git a/cpp_to_py/gpudp/dp/global_swap_cuda.cu b/cpp_to_py/gpudp/dp/global_swap_cuda.cu index 1cf8b79..bb36382 100644 --- a/cpp_to_py/gpudp/dp/global_swap_cuda.cu +++ b/cpp_to_py/gpudp/dp/global_swap_cuda.cu @@ -911,7 +911,8 @@ void globalSwapCUDA(DPTorchRawDB& at_db, int num_bins_x, int num_bins_y, int bat host_node_size_y.data(), host_row2node_map, host_node2row_map, - host_spaces); + host_spaces, + 1); // distribute movable cells to bins on host, bin map is column-major std::vector> host_bin2node_map(db.num_bins_x * db.num_bins_y); std::vector host_node2bin_map(db.num_movable_nodes); diff --git a/cpp_to_py/gpudp/dp/k_reorder_cuda.cu b/cpp_to_py/gpudp/dp/k_reorder_cuda.cu index 999b9f2..3ef367a 100644 --- a/cpp_to_py/gpudp/dp/k_reorder_cuda.cu +++ b/cpp_to_py/gpudp/dp/k_reorder_cuda.cu @@ -244,10 +244,7 @@ void make_row2node_map(const DetailedPlaceDBType& db, // This will cause failure to detect some overlaps. // We need to remove the "small" fixed cell that is inside another. if (!row2nodes.empty()) { - std::vector tmp_nodes; - tmp_nodes.reserve(row2nodes.size()); - tmp_nodes.push_back(row2nodes.front()); - for (int j = 1, je = row2nodes.size(); j < je; ++j) { + for (int j = 1; j < row2nodes.size(); ++j) { int node_id1 = row2nodes.at(j - 1); int node_id2 = row2nodes.at(j); // two fixed cells @@ -259,14 +256,12 @@ void make_row2node_map(const DetailedPlaceDBType& db, typename DetailedPlaceDBType::type xh1 = xl1 + width1; typename DetailedPlaceDBType::type xh2 = xl2 + width2; // only collect node_id2 if its right edge is righter than node_id1 - if (xh1 < xh2) { - tmp_nodes.push_back(node_id2); + if (xh1 >= xh2 && !row2nodes.empty()) { + row2nodes.erase(row2nodes.begin() + j); + --j; } - } else { - tmp_nodes.push_back(node_id2); } } - row2nodes.swap(tmp_nodes); // sort according to center std::sort(row2nodes.begin(), row2nodes.end(), [&](int node_id1, int node_id2) { @@ -982,16 +977,17 @@ void kReorderCUDA(DPTorchRawDB& at_db, int num_bins_x, int num_bins_y, int K, in allocateCopyCpu(cpu_db.node_size_y, db.node_size_y, db.num_nodes, T); make_row2node_map(cpu_db, cpu_db.x, cpu_db.y, host_row2node_map, db.num_threads); + std::vector> host_row2node_map_left = db.reorder_row_map(cpu_db.x, cpu_db.y, cpu_db.node_size_x, cpu_db.node_size_y, host_row2node_map, 1); host_node_space_x.resize(cpu_db.num_movable_nodes); for (int i = 0; i < cpu_db.num_sites_y; ++i) { - for (unsigned int j = 0; j < host_row2node_map.at(i).size(); ++j) { - int node_id = host_row2node_map[i][j]; + for (unsigned int j = 0; j < host_row2node_map_left.at(i).size(); ++j) { + int node_id = host_row2node_map_left[i][j]; if (node_id < db.num_movable_nodes) { auto& space = host_node_space_x[node_id]; T space_xl = cpu_db.x[node_id]; T space_xh = cpu_db.xh; - if (j + 1 < host_row2node_map[i].size()) { - int right_node_id = host_row2node_map[i][j + 1]; + if (j + 1 < host_row2node_map_left[i].size()) { + int right_node_id = host_row2node_map_left[i][j + 1]; space_xh = min(space_xh, cpu_db.x[right_node_id]); } space = space_xh - space_xl; diff --git a/cpp_to_py/gpudp/lg/greedy_legalize.cpp b/cpp_to_py/gpudp/lg/greedy_legalize.cpp index 8ed8e7d..2c363da 100644 --- a/cpp_to_py/gpudp/lg/greedy_legalize.cpp +++ b/cpp_to_py/gpudp/lg/greedy_legalize.cpp @@ -145,40 +145,56 @@ void distributeBlanks2Bins(const float* x, bin_blanks.at(blank_bin_id).push_back(blank); } + } + } - const std::vector& cells = bin_fixed_cells.at(i); - std::vector>& blanks = bin_blanks.at(blank_bin_id); + for (int i = 0; i < num_bins_x * num_bins_y; i += 1) { + int bin_id_x = i / num_bins_y; + int bin_id_y = i - bin_id_x * num_bins_y; + int blank_num_bins_per_bin = roundDiv(bin_size_y, blank_bin_size_y); + int blank_bin_id_yl = bin_id_y * blank_num_bins_per_bin; + int blank_bin_id_yh = std::min(blank_bin_id_yl + blank_num_bins_per_bin, blank_num_bins_y); + + const std::vector& cells = bin_fixed_cells.at(i); - for (unsigned int bi = 0; bi < blanks.size(); ++bi) { - Blank& blank = blanks.at(bi); - for (unsigned int ci = 0; ci < cells.size(); ++ci) { - int node_id = cells.at(ci); - float node_xl = x[node_id]; - float node_yl = y[node_id]; - float node_xh = node_xl + node_size_x[node_id]; - float node_yh = node_yl + node_size_y[node_id]; + for (unsigned int ci = 0; ci < cells.size(); ++ci) { + int node_id = cells.at(ci); + float node_xl = x[node_id]; + float node_yl = y[node_id]; + float node_xh = node_xl + node_size_x[node_id]; + float node_yh = node_yl + node_size_y[node_id]; - if (node_yh > blank.yl && node_yl < blank.yh && node_xh > blank.xl && - node_xl < blank.xh) // overlap + // int node_2_blank_bin_id_yl = std::max(floorDiv((node_yl - yl), blank_bin_size_y), blank_bin_id_yl); + // int node_2_blank_bin_id_yh = std::min(ceilDiv((node_yh - yl), blank_bin_size_y), blank_bin_id_yh); + + int node_2_blank_bin_id_yl = std::max((node_yl - yl) / blank_bin_size_y, (float)blank_bin_id_yl); + int node_2_blank_bin_id_yh = std::min((int)ceil((node_yh - yl) / blank_bin_size_y), blank_bin_id_yh); + + for (int blank_bin_id_y = node_2_blank_bin_id_yl; blank_bin_id_y < node_2_blank_bin_id_yh; ++blank_bin_id_y) { + int blank_bin_id = bin_id_x * blank_num_bins_y + blank_bin_id_y; + + std::vector>& blanks = bin_blanks.at(blank_bin_id); + + for (unsigned int bi = 0; bi < blanks.size(); ++bi) { + Blank& blank = blanks.at(bi); + if (blank.xh <= node_xl) continue; + if (blank.xl >= node_xh) break; + + if (node_xl <= blank.xl && node_xh >= blank.xh) // erase { - if (node_xl <= blank.xl && node_xh >= blank.xh) // erase - { - bin_blanks.at(blank_bin_id).erase(bin_blanks.at(blank_bin_id).begin() + bi); - --bi; - break; - } else if (node_xl <= blank.xl) { // one blank - blank.xl = ceilDiv((node_xh - xl), site_width) * site_width + xl; // align blanks to sites - } else if (node_xh >= blank.xh) { // one blank - blank.xh = floorDiv((node_xl - xl), site_width) * site_width + xl; // align blanks to sites - } else { // two blanks - Blank new_blank = blank; - blank.xh = floorDiv((node_xl - xl), site_width) * site_width + xl; // align blanks to sites - new_blank.xl = - floorDiv((node_xh - xl), site_width) * site_width + xl; // align blanks to sites - bin_blanks.at(blank_bin_id).insert(bin_blanks.at(blank_bin_id).begin() + bi + 1, new_blank); - --bi; - break; - } + bin_blanks.at(blank_bin_id).erase(bin_blanks.at(blank_bin_id).begin() + bi); + --bi; + } else if (node_xl <= blank.xl) { // one blank + blank.xl = ceilDiv((node_xh - xl), site_width) * site_width + xl; // align blanks to sites + } else if (node_xh >= blank.xh) { // one blank + blank.xh = floorDiv((node_xl - xl), site_width) * site_width + xl; // align blanks to sites + } else { // two blanks + Blank new_blank = blank; + blank.xh = floorDiv((node_xl - xl), site_width) * site_width + xl; // align blanks to sites + new_blank.xl = + floorDiv((node_xh - xl), site_width) * site_width + xl; // align blanks to sites + bin_blanks.at(blank_bin_id).insert(bin_blanks.at(blank_bin_id).begin() + bi + 1, new_blank); + --bi; } } } diff --git a/main.py b/main.py index 5b7de71..a86a9dc 100644 --- a/main.py +++ b/main.py @@ -50,6 +50,7 @@ def get_option(): parser.add_argument('--visualize_cgmap', type=str2bool, default=False, help='visualize congestion map') # detailed placement and evaluation + parser.add_argument('--legalization', type=str2bool, default=True, help='perform lg') parser.add_argument('--detail_placement', type=str2bool, default=True, help='perform dp') parser.add_argument('--dp_engine', type=str, default="default", help='choose dp engine') parser.add_argument('--eval_by_external', type=str2bool, default=False, help='eval dp sol by external binary') diff --git a/src/detail_placement.py b/src/detail_placement.py index c033949..458f1a0 100644 --- a/src/detail_placement.py +++ b/src/detail_placement.py @@ -155,7 +155,11 @@ def setup_detailed_rawdb( # NOTE: we assume all legalized cells are on integer system # this step can avoid some potential floating-point precision errors _, floatmov_rhs, _ = data.node_type_indices[1] - inv_scalar = round(1.0 / get_ori_scale_factor(data)) + inv_scalar = torch.tensor( + [round(1.0 / get_ori_scale_factor(data))], + dtype=torch.float32, + device=node_lpos.device + ) node_lpos[:floatmov_rhs].mul_(inv_scalar).round_().div_(inv_scalar) mov_lhs, mov_rhs = data.movable_index @@ -466,7 +470,11 @@ def run_dp_route_opt(node_pos: torch.Tensor, gpdb, rawdb, ps, data: PlaceData, a ), dim=0).cpu() # this step can avoid some potential floating-point precision errors _, floatmov_rhs, _ = data.node_type_indices[1] - inv_scalar = round(1.0 / get_ori_scale_factor(data)) + inv_scalar = torch.tensor( + [round(1.0 / get_ori_scale_factor(data))], + dtype=torch.float32, + device=node_lpos.device + ) node_lpos[:floatmov_rhs].mul_(inv_scalar).round_().div_(inv_scalar) node_size = data.node_size.cpu() @@ -626,7 +634,8 @@ def external_detail_placement(input_file, data: PlaceData, args, logger, eval_mo logger.info("Write detail placement in %s" % dp_out_file) # del gpdb, rawdb # logger.info("Evaluating detail placement result...") - # data, rawdb, gpdb = load_dataset(args, logger, dp_out_file) + # params = find_design_params(args, logger, dp_out_file) + # data, rawdb, gpdb = load_dataset(args, logger, params) # data = data.to(device).preprocess() # hpwl = get_obj_hpwl(data.node_pos, data, args).item() # info = (iteration + 1, hpwl, data.design_name) @@ -645,10 +654,12 @@ def default_detail_placement(node_pos, gpdb, rawdb, ps, data: PlaceData, args, l torch.cuda.synchronize(node_pos.device) dp_start_time = time.time() - node_pos = run_lg(node_pos, data, args, logger) + if args.legalization: + node_pos = run_lg(node_pos, data, args, logger) torch.cuda.synchronize(node_pos.device) lg_end_time = time.time() - node_pos = run_dp(node_pos, data, args, logger) + if args.detail_placement: + node_pos = run_dp(node_pos, data, args, logger) torch.cuda.synchronize(node_pos.device) node_pos = run_dp_route_opt(node_pos, gpdb, rawdb, ps, data, args, logger) dp_end_time = time.time() @@ -687,8 +698,9 @@ def detail_placement_main(node_pos, gpdb, rawdb, ps, data: PlaceData, args, logg gp_out_file = gp_prefix + post_fix args.write_global_placement = False # we won't write GP solution anymore + args.detail_placement = False if args.legalization is False else args.detail_placement - if args.detail_placement: + if args.detail_placement or args.legalization: logger.info("------- Start DP -------") if args.dp_engine in ["ntuplace3", "ntuplace4dr", "rippledp"]: # use external engine to perform lg/dp and write solution