diff --git a/src/operation/iRT/source/module/layer_assigner/LayerAssigner.cpp b/src/operation/iRT/source/module/layer_assigner/LayerAssigner.cpp index 03b1db199..d67d97cc6 100644 --- a/src/operation/iRT/source/module/layer_assigner/LayerAssigner.cpp +++ b/src/operation/iRT/source/module/layer_assigner/LayerAssigner.cpp @@ -111,18 +111,34 @@ LANet LayerAssigner::convertToLANet(Net& net) void LayerAssigner::setLAComParam(LAModel& la_model) { - int32_t topo_spilt_length = 1; + int32_t topo_spilt_length = 8; + int32_t mid_topo_spilt_length = 8; + int32_t long_topo_spilt_length = 16; + int32_t short_segment_length = 2; + int32_t mid_segment_length = 5; + int32_t long_segment_length = 20; double prefer_wire_unit = 1; double non_prefer_wire_unit = 2.5 * prefer_wire_unit; double via_unit = 2 * non_prefer_wire_unit; double overflow_unit = 4 * non_prefer_wire_unit; + double layer_bias_unit = via_unit; + double layer_switch_unit = 1.5 * via_unit; /** - * topo_spilt_length, via_unit, overflow_unit + * topo_spilt_length, mid_topo_spilt_length, long_topo_spilt_length, short_segment_length, mid_segment_length, long_segment_length, + * via_unit, overflow_unit, layer_bias_unit, layer_switch_unit */ - LAComParam la_com_param(topo_spilt_length, via_unit, overflow_unit); + LAComParam la_com_param(topo_spilt_length, mid_topo_spilt_length, long_topo_spilt_length, short_segment_length, mid_segment_length, long_segment_length, + via_unit, overflow_unit, layer_bias_unit, layer_switch_unit); RTLOG.info(Loc::current(), "topo_spilt_length: ", la_com_param.get_topo_spilt_length()); + RTLOG.info(Loc::current(), "mid_topo_spilt_length: ", la_com_param.get_mid_topo_spilt_length()); + RTLOG.info(Loc::current(), "long_topo_spilt_length: ", la_com_param.get_long_topo_spilt_length()); + RTLOG.info(Loc::current(), "short_segment_length: ", la_com_param.get_short_segment_length()); + RTLOG.info(Loc::current(), "mid_segment_length: ", la_com_param.get_mid_segment_length()); + RTLOG.info(Loc::current(), "long_segment_length: ", la_com_param.get_long_segment_length()); RTLOG.info(Loc::current(), "via_unit: ", la_com_param.get_via_unit()); RTLOG.info(Loc::current(), "overflow_unit: ", la_com_param.get_overflow_unit()); + RTLOG.info(Loc::current(), "layer_bias_unit: ", la_com_param.get_layer_bias_unit()); + RTLOG.info(Loc::current(), "layer_switch_unit: ", la_com_param.get_layer_switch_unit()); la_model.set_la_com_param(la_com_param); } @@ -302,11 +318,21 @@ void LayerAssigner::routeLATask(LAModel& la_model, LANet* la_task) { initSingleTask(la_model, la_task); if (needRouting(la_model)) { - spiltPlaneTree(la_model); + _refine_layer_hint_list.clear(); buildPillarTree(la_model); assignPillarTree(la_model); - buildLayerTree(la_model); + MTree coord_tree = getAssignedCoordTree(la_model); + + std::vector overflow_edge_list = getOverflowEdgeList(la_model); + if (!overflow_edge_list.empty()) { + splitPlaneTreeByOverflow(la_model, overflow_edge_list); + buildPillarTree(la_model); + assignPillarTree(la_model); + coord_tree = getAssignedCoordTree(la_model); + } + commitLayerTree(la_model, coord_tree); } + _refine_layer_hint_list.clear(); resetSingleTask(la_model); } @@ -322,8 +348,6 @@ bool LayerAssigner::needRouting(LAModel& la_model) void LayerAssigner::spiltPlaneTree(LAModel& la_model) { - int32_t topo_spilt_length = la_model.get_la_com_param().get_topo_spilt_length(); - TNode* planar_tree_root = la_model.get_curr_la_task()->get_planar_tree().get_root(); std::queue*> planar_queue = RTUTIL.initQueue(planar_tree_root); while (!planar_queue.empty()) { @@ -331,6 +355,7 @@ void LayerAssigner::spiltPlaneTree(LAModel& la_model) std::vector*> child_list = planar_node->get_child_list(); for (size_t i = 0; i < child_list.size(); i++) { int32_t length = RTUTIL.getManhattanDistance(planar_node->value().get_planar_coord(), child_list[i]->value().get_planar_coord()); + int32_t topo_spilt_length = getTopoSpiltLength(la_model, length); if (length <= topo_spilt_length) { continue; } @@ -340,15 +365,27 @@ void LayerAssigner::spiltPlaneTree(LAModel& la_model) } } -void LayerAssigner::insertMidPoint(LAModel& la_model, TNode* planar_node, TNode* child_node) +int32_t LayerAssigner::getTopoSpiltLength(LAModel& la_model, int32_t segment_length) { - int32_t topo_spilt_length = la_model.get_la_com_param().get_topo_spilt_length(); + LAComParam& la_com_param = la_model.get_la_com_param(); + if (segment_length <= la_com_param.get_topo_spilt_length()) { + return std::max(1, segment_length); + } + if (segment_length <= la_com_param.get_long_segment_length()) { + return std::max(1, la_com_param.get_mid_topo_spilt_length()); + } + return std::max(1, la_com_param.get_long_topo_spilt_length()); +} +void LayerAssigner::insertMidPoint(LAModel& la_model, TNode* planar_node, TNode* child_node) +{ PlanarCoord& parent_coord = planar_node->value().get_planar_coord(); PlanarCoord& child_coord = child_node->value().get_planar_coord(); if (RTUTIL.isProximal(parent_coord, child_coord)) { return; } + int32_t length = RTUTIL.getManhattanDistance(parent_coord, child_coord); + int32_t topo_spilt_length = getTopoSpiltLength(la_model, length); std::vector mid_coord_list; int32_t x1 = parent_coord.get_x(); int32_t x2 = child_coord.get_x(); @@ -388,6 +425,219 @@ void LayerAssigner::insertMidPoint(LAModel& la_model, TNode* planar_ curr_node->addChild(child_node); } +std::vector LayerAssigner::getOverflowEdgeList(LAModel& la_model) +{ + constexpr int32_t max_refine_edge_num = 6; + constexpr double soft_start_ratio = 0.80; + constexpr double min_soft_score = 0.25; + + std::vector>& layer_node_map = la_model.get_layer_node_map(); + int32_t curr_net_idx = la_model.get_curr_la_task()->get_net_idx(); + + std::vector overflow_edge_list; + TNode* pillar_tree_root = la_model.get_curr_la_task()->get_pillar_tree().get_root(); + std::queue*> pillar_node_queue = RTUTIL.initQueue(pillar_tree_root); + while (!pillar_node_queue.empty()) { + TNode* parent_pillar_node = RTUTIL.getFrontAndPop(pillar_node_queue); + PlanarCoord parent_coord = parent_pillar_node->value().get_planar_coord(); + for (TNode* child_node : parent_pillar_node->get_child_list()) { + PlanarCoord child_coord = child_node->value().get_planar_coord(); + if (RTUTIL.isProximal(parent_coord, child_coord)) { + continue; + } + if (!RTUTIL.isRightAngled(parent_coord, child_coord)) { + RTLOG.error(Loc::current(), "The segment is oblique!"); + } + Direction direction = RTUTIL.getDirection(parent_coord, child_coord); + int32_t layer_idx = child_node->value().get_layer_idx(); + + std::vector> coord_metric_pair_list; + if (RTUTIL.isHorizontal(parent_coord, child_coord)) { + int32_t step = (parent_coord.get_x() < child_coord.get_x()) ? 1 : -1; + for (int32_t x = parent_coord.get_x(); x != child_coord.get_x() + step; x += step) { + LAOverflowMetric metric = layer_node_map[layer_idx][x][parent_coord.get_y()].getOverflowMetric(curr_net_idx, direction); + coord_metric_pair_list.emplace_back(PlanarCoord(x, parent_coord.get_y()), metric); + } + } else { + int32_t step = (parent_coord.get_y() < child_coord.get_y()) ? 1 : -1; + for (int32_t y = parent_coord.get_y(); y != child_coord.get_y() + step; y += step) { + LAOverflowMetric metric = layer_node_map[layer_idx][parent_coord.get_x()][y].getOverflowMetric(curr_net_idx, direction); + coord_metric_pair_list.emplace_back(PlanarCoord(parent_coord.get_x(), y), metric); + } + } + + LAOverflowEdge overflow_edge; + overflow_edge.first_coord = parent_coord; + overflow_edge.second_coord = child_coord; + overflow_edge.layer_idx = layer_idx; + for (auto& coord_metric_pair : coord_metric_pair_list) { + LAOverflowMetric& metric = coord_metric_pair.second; + overflow_edge.total_true_overflow += metric.true_overflow; + overflow_edge.max_true_overflow = std::max(overflow_edge.max_true_overflow, metric.true_overflow); + overflow_edge.total_soft_congestion += metric.soft_congestion; + overflow_edge.max_soft_congestion = std::max(overflow_edge.max_soft_congestion, metric.soft_congestion); + overflow_edge.max_usage_ratio = std::max(overflow_edge.max_usage_ratio, metric.max_usage_ratio); + } + overflow_edge.has_true_overflow = (overflow_edge.max_true_overflow > RT_ERROR); + bool hard_trigger = overflow_edge.has_true_overflow; + bool soft_trigger = (!hard_trigger && overflow_edge.max_usage_ratio >= soft_start_ratio + && overflow_edge.max_soft_congestion >= min_soft_score); + if (!hard_trigger && !soft_trigger) { + continue; + } + + auto getScore = [&overflow_edge](const LAOverflowMetric& metric) { + if (overflow_edge.has_true_overflow) { + return metric.true_overflow; + } + return metric.soft_congestion; + }; + int32_t max_score_idx = -1; + double max_score = -1.0; + for (size_t i = 0; i < coord_metric_pair_list.size(); i++) { + double score = getScore(coord_metric_pair_list[i].second); + if (score > max_score) { + max_score = score; + max_score_idx = static_cast(i); + } + } + if (max_score_idx == -1 || max_score <= 0) { + continue; + } + + double hotspot_threshold = overflow_edge.has_true_overflow ? std::max(RT_ERROR, max_score * 0.5) : std::max(min_soft_score, max_score * 0.5); + int32_t hotspot_first_idx = max_score_idx; + int32_t hotspot_second_idx = max_score_idx; + while (hotspot_first_idx > 0 && getScore(coord_metric_pair_list[hotspot_first_idx - 1].second) >= hotspot_threshold) { + hotspot_first_idx--; + } + while (hotspot_second_idx + 1 < static_cast(coord_metric_pair_list.size()) + && getScore(coord_metric_pair_list[hotspot_second_idx + 1].second) >= hotspot_threshold) { + hotspot_second_idx++; + } + auto pushSplitCoord = [&](int32_t coord_idx) { + if (coord_idx <= 0 || coord_idx >= static_cast(coord_metric_pair_list.size()) - 1) { + return; + } + PlanarCoord split_coord = coord_metric_pair_list[coord_idx].first; + if (split_coord == parent_coord || split_coord == child_coord) { + return; + } + overflow_edge.split_coord_list.push_back(split_coord); + }; + pushSplitCoord(hotspot_first_idx - 1); + pushSplitCoord(hotspot_second_idx + 1); + std::sort(overflow_edge.split_coord_list.begin(), overflow_edge.split_coord_list.end(), CmpPlanarCoordByXASC()); + overflow_edge.split_coord_list.erase(std::unique(overflow_edge.split_coord_list.begin(), overflow_edge.split_coord_list.end()), + overflow_edge.split_coord_list.end()); + if (!overflow_edge.split_coord_list.empty()) { + overflow_edge_list.push_back(overflow_edge); + } + } + RTUTIL.addListToQueue(pillar_node_queue, parent_pillar_node->get_child_list()); + } + + std::sort(overflow_edge_list.begin(), overflow_edge_list.end(), [](const LAOverflowEdge& a, const LAOverflowEdge& b) { + if (a.has_true_overflow != b.has_true_overflow) { + return a.has_true_overflow; + } + if (a.has_true_overflow) { + if (a.max_true_overflow == b.max_true_overflow) { + return a.total_true_overflow > b.total_true_overflow; + } + return a.max_true_overflow > b.max_true_overflow; + } + if (a.max_soft_congestion == b.max_soft_congestion) { + return a.total_soft_congestion > b.total_soft_congestion; + } + return a.max_soft_congestion > b.max_soft_congestion; + }); + if (static_cast(overflow_edge_list.size()) > max_refine_edge_num) { + overflow_edge_list.resize(max_refine_edge_num); + } + return overflow_edge_list; +} + +void LayerAssigner::splitPlaneTreeByOverflow(LAModel& la_model, std::vector& overflow_edge_list) +{ + _refine_layer_hint_list.clear(); + TNode* planar_tree_root = la_model.get_curr_la_task()->get_planar_tree().get_root(); + std::queue*> planar_queue = RTUTIL.initQueue(planar_tree_root); + while (!planar_queue.empty()) { + TNode* planar_node = RTUTIL.getFrontAndPop(planar_queue); + std::vector*> child_list = planar_node->get_child_list(); + for (TNode* child_node : child_list) { + PlanarCoord parent_coord = planar_node->value().get_planar_coord(); + PlanarCoord child_coord = child_node->value().get_planar_coord(); + for (LAOverflowEdge& overflow_edge : overflow_edge_list) { + if (parent_coord != overflow_edge.first_coord || child_coord != overflow_edge.second_coord) { + continue; + } + _refine_layer_hint_list.push_back({overflow_edge.first_coord, overflow_edge.second_coord, overflow_edge.layer_idx}); + insertPointList(planar_node, child_node, overflow_edge.split_coord_list); + break; + } + } + RTUTIL.addListToQueue(planar_queue, child_list); + } +} + +void LayerAssigner::insertPointList(TNode* planar_node, TNode* child_node, std::vector& point_list) +{ + PlanarCoord parent_coord = planar_node->value().get_planar_coord(); + PlanarCoord child_coord = child_node->value().get_planar_coord(); + if (point_list.empty() || RTUTIL.isProximal(parent_coord, child_coord)) { + return; + } + if (!RTUTIL.isRightAngled(parent_coord, child_coord)) { + RTLOG.error(Loc::current(), "The segment is oblique!"); + } + + auto getOffset = [&](PlanarCoord& coord) { + if (RTUTIL.isHorizontal(parent_coord, child_coord)) { + int32_t step = (parent_coord.get_x() < child_coord.get_x()) ? 1 : -1; + return step * (coord.get_x() - parent_coord.get_x()); + } + int32_t step = (parent_coord.get_y() < child_coord.get_y()) ? 1 : -1; + return step * (coord.get_y() - parent_coord.get_y()); + }; + + int32_t segment_length = RTUTIL.getManhattanDistance(parent_coord, child_coord); + std::vector> offset_coord_pair_list; + for (PlanarCoord split_coord : point_list) { + if (split_coord == parent_coord || split_coord == child_coord) { + continue; + } + if (!RTUTIL.isRightAngled(parent_coord, split_coord) || !RTUTIL.isRightAngled(split_coord, child_coord)) { + continue; + } + int32_t offset = getOffset(split_coord); + if (offset <= 0 || segment_length <= offset) { + continue; + } + offset_coord_pair_list.emplace_back(offset, split_coord); + } + std::sort(offset_coord_pair_list.begin(), offset_coord_pair_list.end(), + [](const std::pair& a, const std::pair& b) { return a.first < b.first; }); + offset_coord_pair_list.erase(std::unique(offset_coord_pair_list.begin(), offset_coord_pair_list.end(), + [](const std::pair& a, const std::pair& b) { + return a.first == b.first; + }), + offset_coord_pair_list.end()); + if (offset_coord_pair_list.empty()) { + return; + } + + planar_node->delChild(child_node); + TNode* curr_node = planar_node; + for (auto& [offset, split_coord] : offset_coord_pair_list) { + TNode* split_node = new TNode(LayerCoord(split_coord, 0)); + curr_node->addChild(split_node); + curr_node = split_node; + } + curr_node->addChild(child_node); +} + void LayerAssigner::buildPillarTree(LAModel& la_model) { LANet* curr_la_task = la_model.get_curr_la_task(); @@ -480,15 +730,20 @@ void LayerAssigner::buildLayerCost(LAModel& la_model, LAPackage& la_package) { std::vector& layer_cost_list = la_package.getChildPillar().get_layer_cost_list(); - for (int32_t candidate_layer_idx : getCandidateLayerList(la_model, la_package)) { + std::vector candidate_layer_idx_list = getCandidateLayerList(la_model, la_package); + for (int32_t candidate_layer_idx : candidate_layer_idx_list) { std::pair parent_pillar_cost_pair = getParentPillarCost(la_model, la_package, candidate_layer_idx); double segment_cost = getSegmentCost(la_model, la_package, candidate_layer_idx); + double layer_bias_cost = getLayerBiasCost(la_model, la_package, candidate_layer_idx_list, candidate_layer_idx); + double refine_layer_hint_cost = getRefineLayerHintCost(la_model, la_package, candidate_layer_idx); + double layer_switch_cost = getLayerSwitchCost(la_model, la_package, parent_pillar_cost_pair.first, candidate_layer_idx); double child_pillar_cost = getChildPillarCost(la_model, la_package, candidate_layer_idx); LALayerCost layer_cost; layer_cost.set_parent_layer_idx(parent_pillar_cost_pair.first); layer_cost.set_layer_idx(candidate_layer_idx); - layer_cost.set_history_cost(parent_pillar_cost_pair.second + segment_cost + child_pillar_cost); + layer_cost.set_history_cost(parent_pillar_cost_pair.second + segment_cost + layer_bias_cost + refine_layer_hint_cost + layer_switch_cost + + child_pillar_cost); layer_cost_list.push_back(std::move(layer_cost)); } } @@ -563,6 +818,149 @@ double LayerAssigner::getSegmentCost(LAModel& la_model, LAPackage& la_package, i return node_cost; } +double LayerAssigner::getLayerBiasCost(LAModel& la_model, LAPackage& la_package, std::vector& candidate_layer_idx_list, int32_t candidate_layer_idx) +{ + if (candidate_layer_idx_list.size() <= 1) { + return 0; + } + + int32_t segment_length = RTUTIL.getManhattanDistance(la_package.getParentPillar().get_planar_coord(), la_package.getChildPillar().get_planar_coord()); + if (segment_length == 0) { + return 0; + } + + int32_t layer_rank = -1; + for (size_t i = 0; i < candidate_layer_idx_list.size(); i++) { + if (candidate_layer_idx_list[i] == candidate_layer_idx) { + layer_rank = static_cast(i); + break; + } + } + if (layer_rank == -1) { + RTLOG.error(Loc::current(), "The candidate layer is not found!"); + } + + LAComParam& la_com_param = la_model.get_la_com_param(); + int32_t max_rank = static_cast(candidate_layer_idx_list.size()) - 1; + double layer_bias_unit = la_com_param.get_layer_bias_unit(); + + if (segment_length <= la_com_param.get_short_segment_length()) { + return layer_bias_unit * 2.0 * layer_rank; + } + if (segment_length <= la_com_param.get_mid_segment_length()) { + return layer_bias_unit * 1.0 * layer_rank; + } + if (segment_length <= la_com_param.get_long_segment_length()) { + double target_rank = 0.5 * max_rank; + return layer_bias_unit * 0.4 * std::abs(layer_rank - target_rank); + } + + auto clamp = [](double value, double lower_bound, double upper_bound) { + return std::max(lower_bound, std::min(value, upper_bound)); + }; + auto smooth_step = [&clamp](double value, double lower_bound, double upper_bound) { + double ratio = clamp((value - lower_bound) / (upper_bound - lower_bound), 0.0, 1.0); + return ratio * ratio * (3.0 - 2.0 * ratio); + }; + auto lerp = [](double start, double end, double ratio) { return start + (end - start) * ratio; }; + + double long_segment_length = la_com_param.get_long_segment_length(); + double length_scale = std::min(segment_length / long_segment_length, 4.0); + double old_layer_bias_cost = layer_bias_unit * 0.6 * length_scale * (max_rank - layer_rank); + double candidate_layer_num = static_cast(candidate_layer_idx_list.size()); + double resolution_ratio = clamp(candidate_layer_num - 2.0, 0.0, 1.0); + + double knee1 = long_segment_length * 2.5; + double knee2 = long_segment_length * 5.0; + double knee3 = long_segment_length * 10.0; + + double target_norm_rank = 0.70; + if (segment_length <= knee1) { + target_norm_rank = 0.70; + } else if (segment_length <= knee2) { + target_norm_rank = lerp(0.70, 0.78, smooth_step(segment_length, knee1, knee2)); + } else if (segment_length <= knee3) { + target_norm_rank = lerp(0.78, 0.90, smooth_step(segment_length, knee2, knee3)); + } else { + target_norm_rank = 0.90; + } + + double norm_rank = layer_rank / 1.0 / max_rank; + double rank_distance = std::abs(norm_rank - target_norm_rank); + double normalized_layer_bias_cost = layer_bias_unit * 0.8 * max_rank * rank_distance; + + double top_region_ratio = clamp((norm_rank - 0.8) / 0.2, 0.0, 1.0); + double top_gate_ratio = (1.0 - smooth_step(segment_length, knee1, knee3)) * resolution_ratio; + normalized_layer_bias_cost += layer_bias_unit * 0.6 * length_scale * top_region_ratio * top_gate_ratio; + return lerp(old_layer_bias_cost, normalized_layer_bias_cost, resolution_ratio); +} + +double LayerAssigner::getRefineLayerHintCost(LAModel& la_model, LAPackage& la_package, int32_t candidate_layer_idx) +{ + if (_refine_layer_hint_list.empty()) { + return 0; + } + + PlanarCoord first_coord = la_package.getParentPillar().get_planar_coord(); + PlanarCoord second_coord = la_package.getChildPillar().get_planar_coord(); + if (RTUTIL.isProximal(first_coord, second_coord)) { + return 0; + } + + auto is_on_segment = [](const PlanarCoord& coord, const PlanarCoord& first_coord, const PlanarCoord& second_coord) { + if (RTUTIL.isProximal(first_coord, second_coord)) { + return coord == first_coord; + } + + int32_t first_x = first_coord.get_x(); + int32_t second_x = second_coord.get_x(); + int32_t first_y = first_coord.get_y(); + int32_t second_y = second_coord.get_y(); + RTUTIL.swapByASC(first_x, second_x); + RTUTIL.swapByASC(first_y, second_y); + + if (RTUTIL.isHorizontal(first_coord, second_coord)) { + return coord.get_y() == first_coord.get_y() && first_x <= coord.get_x() && coord.get_x() <= second_x; + } + if (RTUTIL.isVertical(first_coord, second_coord)) { + return coord.get_x() == first_coord.get_x() && first_y <= coord.get_y() && coord.get_y() <= second_y; + } + return false; + }; + + for (LARefineLayerHint& hint : _refine_layer_hint_list) { + if (RTUTIL.getDirection(first_coord, second_coord) != RTUTIL.getDirection(hint.first_coord, hint.second_coord)) { + continue; + } + if (!is_on_segment(first_coord, hint.first_coord, hint.second_coord) || !is_on_segment(second_coord, hint.first_coord, hint.second_coord)) { + continue; + } + if (candidate_layer_idx == hint.layer_idx) { + return 0; + } + return la_model.get_la_com_param().get_layer_bias_unit() * 0.5 * std::abs(candidate_layer_idx - hint.layer_idx); + } + return 0; +} + +double LayerAssigner::getLayerSwitchCost(LAModel& la_model, LAPackage& la_package, int32_t parent_layer_idx, int32_t candidate_layer_idx) +{ + if (parent_layer_idx == candidate_layer_idx) { + return 0; + } + + int32_t segment_length = RTUTIL.getManhattanDistance(la_package.getParentPillar().get_planar_coord(), la_package.getChildPillar().get_planar_coord()); + if (segment_length == 0) { + return 0; + } + + double switch_cost = la_model.get_la_com_param().get_layer_switch_unit() * std::abs(parent_layer_idx - candidate_layer_idx); + if (!la_package.getParentPillar().get_pin_layer_idx_set().empty() || !la_package.getChildPillar().get_pin_layer_idx_set().empty()) { + switch_cost *= 0.5; + } + return switch_cost; +} + double LayerAssigner::getChildPillarCost(LAModel& la_model, LAPackage& la_package, int32_t candidate_layer_idx) { LAPillar& child_pillar = la_package.getChildPillar(); @@ -643,9 +1041,19 @@ int32_t LayerAssigner::getBestLayerByChild(TNode* parent_pillar_node) } void LayerAssigner::buildLayerTree(LAModel& la_model) +{ + MTree coord_tree = getAssignedCoordTree(la_model); + commitLayerTree(la_model, coord_tree); +} + +MTree LayerAssigner::getAssignedCoordTree(LAModel& la_model) { std::vector> routing_segment_list = getRoutingSegmentList(la_model); - MTree coord_tree = getCoordTree(la_model, routing_segment_list); + return getCoordTree(la_model, routing_segment_list); +} + +void LayerAssigner::commitLayerTree(LAModel& la_model, MTree& coord_tree) +{ updateDemandToGraph(la_model, ChangeType::kAdd, coord_tree); uploadNetResult(la_model, coord_tree); } diff --git a/src/operation/iRT/source/module/layer_assigner/LayerAssigner.hpp b/src/operation/iRT/source/module/layer_assigner/LayerAssigner.hpp index 543b8a245..8b4188bd6 100644 --- a/src/operation/iRT/source/module/layer_assigner/LayerAssigner.hpp +++ b/src/operation/iRT/source/module/layer_assigner/LayerAssigner.hpp @@ -38,8 +38,28 @@ class LayerAssigner void assign(); private: + struct LAOverflowEdge + { + PlanarCoord first_coord; + PlanarCoord second_coord; + int32_t layer_idx = -1; + bool has_true_overflow = false; + double total_true_overflow = 0.0; + double max_true_overflow = 0.0; + double total_soft_congestion = 0.0; + double max_soft_congestion = 0.0; + double max_usage_ratio = 0.0; + std::vector split_coord_list; + }; + struct LARefineLayerHint + { + PlanarCoord first_coord; + PlanarCoord second_coord; + int32_t layer_idx = -1; + }; // self static LayerAssigner* _la_instance; + std::vector _refine_layer_hint_list; LayerAssigner() = default; LayerAssigner(const LayerAssigner& other) = delete; @@ -62,7 +82,11 @@ class LayerAssigner void initSingleTask(LAModel& la_model, LANet* la_task); bool needRouting(LAModel& la_model); void spiltPlaneTree(LAModel& la_model); + int32_t getTopoSpiltLength(LAModel& la_model, int32_t segment_length); void insertMidPoint(LAModel& la_model, TNode* planar_node, TNode* child_node); + std::vector getOverflowEdgeList(LAModel& la_model); + void splitPlaneTreeByOverflow(LAModel& la_model, std::vector& overflow_edge_list); + void insertPointList(TNode* planar_node, TNode* child_node, std::vector& point_list); void buildPillarTree(LAModel& la_model); LAPillar convertLAPillar(LayerCoord& layer_coord, std::map, CmpPlanarCoordByXASC>& coord_pin_layer_map); void assignPillarTree(LAModel& la_model); @@ -73,11 +97,16 @@ class LayerAssigner std::pair getParentPillarCost(LAModel& la_model, LAPackage& la_package, int32_t candidate_layer_idx); double getExtraViaCost(LAModel& la_model, std::set& layer_idx_set, int32_t candidate_layer_idx); double getSegmentCost(LAModel& la_model, LAPackage& la_package, int32_t candidate_layer_idx); + double getLayerBiasCost(LAModel& la_model, LAPackage& la_package, std::vector& candidate_layer_idx_list, int32_t candidate_layer_idx); + double getRefineLayerHintCost(LAModel& la_model, LAPackage& la_package, int32_t candidate_layer_idx); + double getLayerSwitchCost(LAModel& la_model, LAPackage& la_package, int32_t parent_layer_idx, int32_t candidate_layer_idx); double getChildPillarCost(LAModel& la_model, LAPackage& la_package, int32_t candidate_layer_idx); void assignBackward(LAModel& la_model); int32_t getBestLayerBySelf(TNode* pillar_node); int32_t getBestLayerByChild(TNode* parent_pillar_node); void buildLayerTree(LAModel& la_model); + MTree getAssignedCoordTree(LAModel& la_model); + void commitLayerTree(LAModel& la_model, MTree& coord_tree); std::vector> getRoutingSegmentList(LAModel& la_model); MTree getCoordTree(LAModel& la_model, std::vector>& routing_segment_list); void uploadNetResult(LAModel& la_model, MTree& coord_tree); diff --git a/src/operation/iRT/source/module/layer_assigner/la_data_manager/LAComParam.hpp b/src/operation/iRT/source/module/layer_assigner/la_data_manager/LAComParam.hpp index af5634d17..86c945f02 100644 --- a/src/operation/iRT/source/module/layer_assigner/la_data_manager/LAComParam.hpp +++ b/src/operation/iRT/source/module/layer_assigner/la_data_manager/LAComParam.hpp @@ -28,20 +28,56 @@ class LAComParam _via_unit = via_unit; _overflow_unit = overflow_unit; } + LAComParam(int32_t topo_spilt_length, int32_t mid_topo_spilt_length, int32_t long_topo_spilt_length, int32_t short_segment_length, + int32_t mid_segment_length, int32_t long_segment_length, double via_unit, double overflow_unit, double layer_bias_unit, + double layer_switch_unit) + { + _topo_spilt_length = topo_spilt_length; + _mid_topo_spilt_length = mid_topo_spilt_length; + _long_topo_spilt_length = long_topo_spilt_length; + _short_segment_length = short_segment_length; + _mid_segment_length = mid_segment_length; + _long_segment_length = long_segment_length; + _via_unit = via_unit; + _overflow_unit = overflow_unit; + _layer_bias_unit = layer_bias_unit; + _layer_switch_unit = layer_switch_unit; + } ~LAComParam() = default; // getter int32_t get_topo_spilt_length() const { return _topo_spilt_length; } + int32_t get_mid_topo_spilt_length() const { return _mid_topo_spilt_length; } + int32_t get_long_topo_spilt_length() const { return _long_topo_spilt_length; } + int32_t get_short_segment_length() const { return _short_segment_length; } + int32_t get_mid_segment_length() const { return _mid_segment_length; } + int32_t get_long_segment_length() const { return _long_segment_length; } double get_via_unit() const { return _via_unit; } double get_overflow_unit() const { return _overflow_unit; } + double get_layer_bias_unit() const { return _layer_bias_unit; } + double get_layer_switch_unit() const { return _layer_switch_unit; } // setter void set_topo_spilt_length(const int32_t topo_spilt_length) { _topo_spilt_length = topo_spilt_length; } + void set_mid_topo_spilt_length(const int32_t mid_topo_spilt_length) { _mid_topo_spilt_length = mid_topo_spilt_length; } + void set_long_topo_spilt_length(const int32_t long_topo_spilt_length) { _long_topo_spilt_length = long_topo_spilt_length; } + void set_short_segment_length(const int32_t short_segment_length) { _short_segment_length = short_segment_length; } + void set_mid_segment_length(const int32_t mid_segment_length) { _mid_segment_length = mid_segment_length; } + void set_long_segment_length(const int32_t long_segment_length) { _long_segment_length = long_segment_length; } void set_via_unit(const double via_unit) { _via_unit = via_unit; } void set_overflow_unit(const double overflow_unit) { _overflow_unit = overflow_unit; } + void set_layer_bias_unit(const double layer_bias_unit) { _layer_bias_unit = layer_bias_unit; } + void set_layer_switch_unit(const double layer_switch_unit) { _layer_switch_unit = layer_switch_unit; } private: int32_t _topo_spilt_length = 0; + int32_t _mid_topo_spilt_length = 0; + int32_t _long_topo_spilt_length = 0; + int32_t _short_segment_length = 0; + int32_t _mid_segment_length = 0; + int32_t _long_segment_length = 0; double _via_unit = 0; double _overflow_unit = 0; + double _layer_bias_unit = 0; + double _layer_switch_unit = 0; }; } // namespace irt diff --git a/src/operation/iRT/source/module/layer_assigner/la_data_manager/LANode.hpp b/src/operation/iRT/source/module/layer_assigner/la_data_manager/LANode.hpp index 05968519a..9a6c06661 100644 --- a/src/operation/iRT/source/module/layer_assigner/la_data_manager/LANode.hpp +++ b/src/operation/iRT/source/module/layer_assigner/la_data_manager/LANode.hpp @@ -24,6 +24,15 @@ namespace irt { +struct LAOverflowMetric +{ + double true_overflow = 0.0; + double soft_congestion = 0.0; + double max_usage_ratio = 0.0; + int32_t overflow_orient_num = 0; + int32_t soft_orient_num = 0; +}; + class LANode : public LayerCoord { public: @@ -129,6 +138,103 @@ class LANode : public LayerCoord cost += (overflow_unit * (boundary_overflow + internal_overflow)); return cost; } + LAOverflowMetric getOverflowMetric(int32_t net_idx, Direction direction) + { + if (!validDemandUnit()) { + RTLOG.error(Loc::current(), "The demand unit is error!"); + } + std::map> orient_net_map = _orient_net_map; + std::map> net_orient_map = _net_orient_map; + if (direction == Direction::kHorizontal) { + for (Orientation orient : {Orientation::kEast, Orientation::kWest}) { + orient_net_map[orient].insert(net_idx); + net_orient_map[net_idx].insert(orient); + } + } else if (direction == Direction::kVertical) { + for (Orientation orient : {Orientation::kSouth, Orientation::kNorth}) { + orient_net_map[orient].insert(net_idx); + net_orient_map[net_idx].insert(orient); + } + } else { + RTLOG.error(Loc::current(), "The direction is error!"); + } + + constexpr double kSoftStartRatio = 0.90; + LAOverflowMetric metric; + auto addDemandSupply = [&metric, kSoftStartRatio](double demand, double supply) { + if (supply <= 0) { + if (demand > 0) { + metric.true_overflow += demand; + metric.max_usage_ratio = std::max(metric.max_usage_ratio, demand + 1.0); + metric.overflow_orient_num++; + } + return; + } + + double usage_ratio = demand / supply; + metric.max_usage_ratio = std::max(metric.max_usage_ratio, usage_ratio); + double overflow = demand - supply; + if (overflow > RT_ERROR) { + metric.true_overflow += overflow; + metric.overflow_orient_num++; + return; + } + if (usage_ratio >= kSoftStartRatio) { + double soft_ratio = (usage_ratio - kSoftStartRatio) / (1.0 - kSoftStartRatio); + metric.soft_congestion += std::pow(soft_ratio, 2); + metric.soft_orient_num++; + } + }; + + for (Orientation orient : {Orientation::kEast, Orientation::kWest, Orientation::kSouth, Orientation::kNorth}) { + double boundary_demand = 0; + if (RTUTIL.exist(orient_net_map, orient)) { + for (int32_t demand_net_idx : orient_net_map[orient]) { + if (RTUTIL.exist(_ignore_net_orient_map, demand_net_idx) && RTUTIL.exist(_ignore_net_orient_map[demand_net_idx], orient)) { + continue; + } + boundary_demand += _boundary_wire_unit; + } + } + double boundary_supply = 0; + if (RTUTIL.exist(_orient_supply_map, orient)) { + boundary_supply = _orient_supply_map[orient]; + } + addDemandSupply(boundary_demand, boundary_supply); + } + { + double internal_demand = 0; + for (Orientation orient : {Orientation::kEast, Orientation::kWest, Orientation::kSouth, Orientation::kNorth}) { + if (RTUTIL.exist(orient_net_map, orient)) { + for (int32_t demand_net_idx : orient_net_map[orient]) { + if (RTUTIL.exist(_ignore_net_orient_map, demand_net_idx) && RTUTIL.exist(_ignore_net_orient_map[demand_net_idx], orient)) { + continue; + } + internal_demand += _internal_wire_unit; + } + } + } + for (auto& [net_idx, orient_set] : net_orient_map) { + if (RTUTIL.exist(_ignore_net_orient_map, net_idx) + && (RTUTIL.exist(_ignore_net_orient_map[net_idx], Orientation::kAbove) || RTUTIL.exist(_ignore_net_orient_map[net_idx], Orientation::kBelow))) { + continue; + } + if (RTUTIL.exist(orient_set, Orientation::kEast) || RTUTIL.exist(orient_set, Orientation::kWest) || RTUTIL.exist(orient_set, Orientation::kSouth) + || RTUTIL.exist(orient_set, Orientation::kNorth)) { + continue; + } + if (RTUTIL.exist(orient_set, Orientation::kAbove) || RTUTIL.exist(orient_set, Orientation::kBelow)) { + internal_demand += _internal_via_unit; + } + } + double internal_supply = 0; + for (auto& [orient, supply] : _orient_supply_map) { + internal_supply += supply; + } + addDemandSupply(internal_demand, internal_supply); + } + return metric; + } bool validDemandUnit() { if (_boundary_wire_unit <= 0) { diff --git a/src/operation/iRT/source/module/topology_generator/TopologyGenerator.cpp b/src/operation/iRT/source/module/topology_generator/TopologyGenerator.cpp index 3106e5e76..4c91018f2 100644 --- a/src/operation/iRT/source/module/topology_generator/TopologyGenerator.cpp +++ b/src/operation/iRT/source/module/topology_generator/TopologyGenerator.cpp @@ -119,11 +119,14 @@ void TopologyGenerator::setTGComParam(TGModel& tg_model) /** * topo_spilt_length, expand_step_num, expand_step_length, overflow_unit */ - TGComParam tg_com_param(topo_spilt_length, expand_step_num, expand_step_length, overflow_unit); + double corner_weight = 0.3; + + TGComParam tg_com_param(topo_spilt_length, expand_step_num, expand_step_length, overflow_unit, corner_weight); RTLOG.info(Loc::current(), "topo_spilt_length: ", tg_com_param.get_topo_spilt_length()); RTLOG.info(Loc::current(), "expand_step_num: ", tg_com_param.get_expand_step_num()); RTLOG.info(Loc::current(), "expand_step_length: ", tg_com_param.get_expand_step_length()); RTLOG.info(Loc::current(), "overflow_unit: ", tg_com_param.get_overflow_unit()); + RTLOG.info(Loc::current(), "corner_weight: ", tg_com_param.get_corner_weight()); tg_model.set_tg_com_param(tg_com_param); } @@ -255,58 +258,107 @@ void TopologyGenerator::initSingleTask(TGModel& tg_model, TGNet* tg_task) std::vector> TopologyGenerator::getRoutingSegmentList(TGModel& tg_model) { - std::vector tg_candidate_list = getTGCandidateList(tg_model); -#pragma omp parallel for + std::vector> planar_topo_list = getPlanarTopoList(tg_model); + std::vector tg_candidate_list = getTGCandidateList(tg_model, planar_topo_list); + + std::map> topo_candidates_map; for (TGCandidate& tg_candidate : tg_candidate_list) { - updateTGCandidate(tg_model, tg_candidate); + topo_candidates_map[tg_candidate.get_topo_idx()].push_back(&tg_candidate); } - std::map topo_candidate_map; - for (TGCandidate& tg_candidate : tg_candidate_list) { - int32_t topo_idx = tg_candidate.get_topo_idx(); - if (!RTUTIL.exist(topo_candidate_map, topo_idx)) { - topo_candidate_map[topo_idx] = &tg_candidate; + + double corner_weight = tg_model.get_tg_com_param().get_corner_weight(); + + auto computeScore = [&](TGCandidate& c) { + return c.get_total_wire_length() + c.get_total_cost() + corner_weight * c.get_total_corner_num(); + }; + + auto isBetterCandidate = [&](TGCandidate& candidate, TGCandidate& current_best) { + bool a_blocked = candidate.get_is_path_blocked(); + bool b_blocked = current_best.get_is_path_blocked(); + if (!a_blocked && b_blocked) { + return true; + } else if (a_blocked && !b_blocked) { + return false; + } + double score_a = computeScore(candidate); + double score_b = computeScore(current_best); + if (std::abs(score_a - score_b) < 1e-9) { + if (candidate.get_saturation_node_num() != current_best.get_saturation_node_num()) { + return candidate.get_saturation_node_num() < current_best.get_saturation_node_num(); + } + if (candidate.get_hotspot_node_num() != current_best.get_hotspot_node_num()) { + return candidate.get_hotspot_node_num() < current_best.get_hotspot_node_num(); + } + if (std::abs(candidate.get_max_usage_ratio() - current_best.get_max_usage_ratio()) >= 1e-9) { + return candidate.get_max_usage_ratio() < current_best.get_max_usage_ratio(); + } + return candidate.get_total_wire_length() < current_best.get_total_wire_length(); + } + return score_a < score_b; + }; + + TGShadowDemandMap self_shadow; + std::map topo_candidate_map; + + for (size_t topo_idx = 0; topo_idx < planar_topo_list.size(); topo_idx++) { + auto it = topo_candidates_map.find(static_cast(topo_idx)); + if (it == topo_candidates_map.end()) { continue; } - TGCandidate* current_best = topo_candidate_map[topo_idx]; - if (!tg_candidate.get_is_path_blocked() && current_best->get_is_path_blocked()) { - topo_candidate_map[topo_idx] = &tg_candidate; - } else if (!tg_candidate.get_is_path_blocked() && !current_best->get_is_path_blocked()) { - if (tg_candidate.get_total_wire_length() < current_best->get_total_wire_length()) { - topo_candidate_map[topo_idx] = &tg_candidate; - } else if (tg_candidate.get_total_wire_length() == current_best->get_total_wire_length()) { - if (tg_candidate.get_total_corner_num() < current_best->get_total_corner_num()) { - topo_candidate_map[topo_idx] = &tg_candidate; - } + std::vector& candidates = it->second; + + const TGShadowDemandMap* shadow_ptr = self_shadow.empty() ? nullptr : &self_shadow; +#pragma omp parallel for + for (TGCandidate* tg_candidate : candidates) { + updateTGCandidate(tg_model, *tg_candidate, shadow_ptr); + } + + for (TGCandidate* tg_candidate : candidates) { + int32_t candidate_topo_idx = tg_candidate->get_topo_idx(); + if (!RTUTIL.exist(topo_candidate_map, candidate_topo_idx)) { + topo_candidate_map[candidate_topo_idx] = *tg_candidate; + continue; } - } else if (tg_candidate.get_is_path_blocked() && current_best->get_is_path_blocked()) { - if (tg_candidate.get_total_overflow_cost() < current_best->get_total_overflow_cost()) { - topo_candidate_map[topo_idx] = &tg_candidate; + TGCandidate& current_best = topo_candidate_map[candidate_topo_idx]; + if (isBetterCandidate(*tg_candidate, current_best)) { + topo_candidate_map[candidate_topo_idx] = *tg_candidate; } } + + addCandidateToShadow(self_shadow, topo_candidate_map[static_cast(topo_idx)]); } + std::vector> routing_segment_list; for (auto& [topo_idx, min_candidate] : topo_candidate_map) { - for (Segment& routing_segment : min_candidate->get_routing_segment_list()) { + for (Segment& routing_segment : min_candidate.get_routing_segment_list()) { routing_segment_list.push_back(routing_segment); } } return routing_segment_list; } -std::vector TopologyGenerator::getTGCandidateList(TGModel& tg_model) +std::vector TopologyGenerator::getTGCandidateList(TGModel& tg_model, std::vector>& planar_topo_list) { - std::vector> planar_topo_list = getPlanarTopoList(tg_model); std::vector>> (TopologyGenerator::*)(TGModel&, Segment&)>> strategy_list; strategy_list.emplace_back(0, &TopologyGenerator::getRoutingSegmentListByStraight); strategy_list.emplace_back(1, &TopologyGenerator::getRoutingSegmentListByLPattern); strategy_list.emplace_back(2, &TopologyGenerator::getRoutingSegmentListByZPattern); - strategy_list.emplace_back(2, &TopologyGenerator::getRoutingSegmentListByUPattern); strategy_list.emplace_back(3, &TopologyGenerator::getRoutingSegmentListByInner3Bends); - strategy_list.emplace_back(3, &TopologyGenerator::getRoutingSegmentListByOuter3Bends); + strategy_list.emplace_back(4, &TopologyGenerator::getRoutingSegmentListByUPattern); + strategy_list.emplace_back(5, &TopologyGenerator::getRoutingSegmentListByOuter3Bends); + + std::vector>> (TopologyGenerator::*)(TGModel&, Segment&)>> + long_oblique_strategy_list; + long_oblique_strategy_list.emplace_back(1, &TopologyGenerator::getRoutingSegmentListByLPattern); + long_oblique_strategy_list.emplace_back(2, &TopologyGenerator::getRoutingSegmentListByZPattern); + long_oblique_strategy_list.emplace_back(3, &TopologyGenerator::getRoutingSegmentListByInner3Bends); + long_oblique_strategy_list.emplace_back(4, &TopologyGenerator::getRoutingSegmentListByUPattern); + long_oblique_strategy_list.emplace_back(5, &TopologyGenerator::getRoutingSegmentListByOuter3Bends); std::vector tg_candidate_list; for (size_t i = 0; i < planar_topo_list.size(); i++) { - for (const auto& [corner_num, getRoutingSegmentList] : strategy_list) { + auto& curr_strategy_list = isLongObliqueTopo(tg_model, planar_topo_list[i]) ? long_oblique_strategy_list : strategy_list; + for (const auto& [corner_num, getRoutingSegmentList] : curr_strategy_list) { for (const std::vector>& routing_segment_list : (this->*getRoutingSegmentList)(tg_model, planar_topo_list[i])) { tg_candidate_list.emplace_back(i, routing_segment_list, corner_num, 0, false, 0); } @@ -317,8 +369,6 @@ std::vector TopologyGenerator::getTGCandidateList(TGModel& tg_model std::vector> TopologyGenerator::getPlanarTopoList(TGModel& tg_model) { - int32_t topo_spilt_length = tg_model.get_tg_com_param().get_topo_spilt_length(); - std::vector planar_coord_list; { for (TGPin& tg_pin : tg_model.get_curr_tg_task()->get_tg_pin_list()) { @@ -329,43 +379,21 @@ std::vector> TopologyGenerator::getPlanarTopoList(TGModel& } std::vector> planar_topo_list; for (Segment& planar_topo : RTI.getPlanarTopoList(planar_coord_list)) { - PlanarCoord& first_coord = planar_topo.get_first(); - PlanarCoord& second_coord = planar_topo.get_second(); - int32_t span_x = std::abs(first_coord.get_x() - second_coord.get_x()); - int32_t span_y = std::abs(first_coord.get_y() - second_coord.get_y()); - if (span_x > 1 && span_y > 1 && (span_x > topo_spilt_length || span_y > topo_spilt_length)) { - int32_t stick_num_x; - if (span_x % topo_spilt_length == 0) { - stick_num_x = (span_x / topo_spilt_length - 1); - } else { - stick_num_x = (span_x < topo_spilt_length) ? (span_x - 1) : (span_x / topo_spilt_length); - } - int32_t stick_num_y; - if (span_y % topo_spilt_length == 0) { - stick_num_y = (span_y / topo_spilt_length - 1); - } else { - stick_num_y = (span_y < topo_spilt_length) ? (span_y - 1) : (span_y / topo_spilt_length); - } - int32_t stick_num = std::min(stick_num_x, stick_num_y); - - std::vector coord_list; - coord_list.push_back(first_coord); - double delta_x = static_cast(second_coord.get_x() - first_coord.get_x()) / (stick_num + 1); - double delta_y = static_cast(second_coord.get_y() - first_coord.get_y()) / (stick_num + 1); - for (int32_t i = 1; i <= stick_num; i++) { - coord_list.emplace_back(std::round(first_coord.get_x() + i * delta_x), std::round(first_coord.get_y() + i * delta_y)); - } - coord_list.push_back(second_coord); - for (size_t i = 1; i < coord_list.size(); i++) { - planar_topo_list.emplace_back(coord_list[i - 1], coord_list[i]); - } - } else { - planar_topo_list.emplace_back(first_coord, second_coord); - } + planar_topo_list.push_back(planar_topo); } return planar_topo_list; } +bool TopologyGenerator::isLongObliqueTopo(TGModel& tg_model, Segment& planar_topo) +{ + int32_t topo_spilt_length = tg_model.get_tg_com_param().get_topo_spilt_length(); + PlanarCoord& first_coord = planar_topo.get_first(); + PlanarCoord& second_coord = planar_topo.get_second(); + int32_t span_x = std::abs(first_coord.get_x() - second_coord.get_x()); + int32_t span_y = std::abs(first_coord.get_y() - second_coord.get_y()); + return (span_x > 1 && span_y > 1 && (span_x > topo_spilt_length || span_y > topo_spilt_length)); +} + std::vector>> TopologyGenerator::getRoutingSegmentListByStraight(TGModel& tg_model, Segment& planar_topo) { PlanarCoord& first_coord = planar_topo.get_first(); @@ -697,22 +725,22 @@ std::vector>> TopologyGenerator::getRoutingSegm return routing_segment_list_list; } -void TopologyGenerator::updateTGCandidate(TGModel& tg_model, TGCandidate& tg_candidate) +void TopologyGenerator::updateTGCandidate(TGModel& tg_model, TGCandidate& tg_candidate, + const TGShadowDemandMap* shadow_demand_map) { double overflow_unit = tg_model.get_tg_com_param().get_overflow_unit(); GridMap& tg_node_map = tg_model.get_tg_node_map(); int32_t curr_net_idx = tg_model.get_curr_tg_task()->get_net_idx(); - int32_t total_wire_length = 0; - bool is_path_blocked = false; - double total_overflow_cost = 0; + TGCandidateCost candidate_cost; + Direction pre_direction = Direction::kNone; for (Segment& coord_segment : tg_candidate.get_routing_segment_list()) { PlanarCoord& first_coord = coord_segment.get_first(); PlanarCoord& second_coord = coord_segment.get_second(); if (!RTUTIL.isRightAngled(first_coord, second_coord)) { RTLOG.error(Loc::current(), "The direction is error!"); } - total_wire_length += RTUTIL.getManhattanDistance(first_coord, second_coord); + candidate_cost.total_wire_length += RTUTIL.getManhattanDistance(first_coord, second_coord); int32_t first_x = first_coord.get_x(); int32_t second_x = second_coord.get_x(); @@ -721,19 +749,42 @@ void TopologyGenerator::updateTGCandidate(TGModel& tg_model, TGCandidate& tg_can RTUTIL.swapByASC(first_x, second_x); RTUTIL.swapByASC(first_y, second_y); Direction direction = RTUTIL.getDirection(first_coord, second_coord); + if (pre_direction != Direction::kNone && pre_direction != direction) { + candidate_cost.total_corner_num++; + } + pre_direction = direction; for (int32_t x = first_x; x <= second_x; x++) { for (int32_t y = first_y; y <= second_y; y++) { - double overflow_cost = tg_node_map[x][y].getOverflowCost(curr_net_idx, direction, overflow_unit); - if (overflow_cost > 1) { - is_path_blocked = true; + const std::set* extra_orients = nullptr; + if (shadow_demand_map) { + PlanarCoord coord(x, y); + auto it = shadow_demand_map->find(coord); + if (it != shadow_demand_map->end()) { + extra_orients = &it->second; + } + } + TGNodeCost node_cost = tg_node_map[x][y].getCost(curr_net_idx, direction, overflow_unit, extra_orients); + if (node_cost.overflow > 0) { + candidate_cost.is_path_blocked = true; + candidate_cost.overflow_node_num++; + } + candidate_cost.total_usage_cost += node_cost.usage_cost; + candidate_cost.total_saturation_cost += node_cost.saturation_cost; + candidate_cost.total_hotspot_cost += node_cost.hotspot_cost; + candidate_cost.total_overflow_cost += node_cost.overflow_cost; + candidate_cost.total_overflow += node_cost.overflow; + candidate_cost.max_usage_ratio = std::max(candidate_cost.max_usage_ratio, node_cost.max_usage_ratio); + if (node_cost.saturation_orient_num > 0) { + candidate_cost.saturation_node_num++; + } + if (node_cost.hotspot_orient_num > 0) { + candidate_cost.hotspot_node_num++; } - total_overflow_cost += overflow_cost; } } } - tg_candidate.set_total_wire_length(total_wire_length); - tg_candidate.set_is_path_blocked(is_path_blocked); - tg_candidate.set_total_overflow_cost(total_overflow_cost); + + tg_candidate.set_candidate_cost(candidate_cost); } MTree TopologyGenerator::getCoordTree(TGModel& tg_model, std::vector>& routing_segment_list) @@ -809,6 +860,39 @@ void TopologyGenerator::updateDemandToGraph(TGModel& tg_model, ChangeType change } } +void TopologyGenerator::addCandidateToShadow(TGShadowDemandMap& shadow_map, TGCandidate& tg_candidate) +{ + for (Segment& coord_segment : tg_candidate.get_routing_segment_list()) { + PlanarCoord& first_coord = coord_segment.get_first(); + PlanarCoord& second_coord = coord_segment.get_second(); + + Orientation orientation = RTUTIL.getOrientation(first_coord, second_coord); + if (orientation == Orientation::kNone || orientation == Orientation::kOblique) { + RTLOG.error(Loc::current(), "The orientation is error!"); + } + Orientation opposite_orientation = RTUTIL.getOppositeOrientation(orientation); + + int32_t first_x = first_coord.get_x(); + int32_t first_y = first_coord.get_y(); + int32_t second_x = second_coord.get_x(); + int32_t second_y = second_coord.get_y(); + RTUTIL.swapByASC(first_x, second_x); + RTUTIL.swapByASC(first_y, second_y); + + for (int32_t x = first_x; x <= second_x; x++) { + for (int32_t y = first_y; y <= second_y; y++) { + PlanarCoord coord(x, y); + if (coord != first_coord) { + shadow_map[coord].insert(opposite_orientation); + } + if (coord != second_coord) { + shadow_map[coord].insert(orientation); + } + } + } + } +} + #endif #if 1 // exhibit diff --git a/src/operation/iRT/source/module/topology_generator/TopologyGenerator.hpp b/src/operation/iRT/source/module/topology_generator/TopologyGenerator.hpp index a90d8eaf9..d3371634c 100644 --- a/src/operation/iRT/source/module/topology_generator/TopologyGenerator.hpp +++ b/src/operation/iRT/source/module/topology_generator/TopologyGenerator.hpp @@ -59,8 +59,9 @@ class TopologyGenerator void routeTGTask(TGModel& tg_model, TGNet* tg_net); void initSingleTask(TGModel& tg_model, TGNet* tg_net); std::vector> getRoutingSegmentList(TGModel& tg_model); - std::vector getTGCandidateList(TGModel& tg_model); + std::vector getTGCandidateList(TGModel& tg_model, std::vector>& planar_topo_list); std::vector> getPlanarTopoList(TGModel& tg_model); + bool isLongObliqueTopo(TGModel& tg_model, Segment& planar_topo); std::vector>> getRoutingSegmentListByStraight(TGModel& tg_model, Segment& planar_topo); std::vector>> getRoutingSegmentListByLPattern(TGModel& tg_model, Segment& planar_topo); std::vector>> getRoutingSegmentListByZPattern(TGModel& tg_model, Segment& planar_topo); @@ -68,13 +69,16 @@ class TopologyGenerator std::vector>> getRoutingSegmentListByUPattern(TGModel& tg_model, Segment& planar_topo); std::vector>> getRoutingSegmentListByInner3Bends(TGModel& tg_model, Segment& planar_topo); std::vector>> getRoutingSegmentListByOuter3Bends(TGModel& tg_model, Segment& planar_topo); - void updateTGCandidate(TGModel& tg_model, TGCandidate& tg_candidate); + using TGShadowDemandMap = std::map, CmpPlanarCoordByXASC>; + void updateTGCandidate(TGModel& tg_model, TGCandidate& tg_candidate, + const TGShadowDemandMap* shadow_demand_map = nullptr); MTree getCoordTree(TGModel& tg_model, std::vector>& routing_segment_list); void uploadNetResult(TGModel& tg_model, MTree& coord_tree); void resetSingleTask(TGModel& tg_model); #if 1 // update env void updateDemandToGraph(TGModel& tg_model, ChangeType change_type, MTree& coord_tree); + void addCandidateToShadow(TGShadowDemandMap& shadow_map, TGCandidate& tg_candidate); #endif #if 1 // exhibit diff --git a/src/operation/iRT/source/module/topology_generator/tg_data_manager/TGCandidate.hpp b/src/operation/iRT/source/module/topology_generator/tg_data_manager/TGCandidate.hpp index 497681edc..473738b8e 100644 --- a/src/operation/iRT/source/module/topology_generator/tg_data_manager/TGCandidate.hpp +++ b/src/operation/iRT/source/module/topology_generator/tg_data_manager/TGCandidate.hpp @@ -22,19 +22,41 @@ namespace irt { +struct TGCandidateCost +{ + int32_t total_corner_num = 0; + int32_t total_wire_length = 0; + bool is_path_blocked = false; + double total_usage_cost = 0.0; + double total_saturation_cost = 0.0; + double total_hotspot_cost = 0.0; + double total_overflow_cost = 0.0; + double total_overflow = 0.0; + double max_usage_ratio = 0.0; + int32_t saturation_node_num = 0; + int32_t hotspot_node_num = 0; + int32_t overflow_node_num = 0; + + double getTotalCost() const { return total_usage_cost + total_saturation_cost + total_hotspot_cost + total_overflow_cost; } +}; + class TGCandidate { public: TGCandidate() = default; TGCandidate(int32_t topo_idx, const std::vector>& routing_segment_list, int32_t total_corner_num, int32_t total_wire_length, - bool is_path_blocked, double total_overflow_cost) + bool is_path_blocked, double total_overflow_cost, double total_usage_cost = 0.0, double total_overflow = 0.0, + int32_t overflow_node_num = 0) { _topo_idx = topo_idx; _routing_segment_list = routing_segment_list; _total_corner_num = total_corner_num; _total_wire_length = total_wire_length; _is_path_blocked = is_path_blocked; + _total_usage_cost = total_usage_cost; _total_overflow_cost = total_overflow_cost; + _total_overflow = total_overflow; + _overflow_node_num = overflow_node_num; } ~TGCandidate() = default; // getter @@ -43,14 +65,46 @@ class TGCandidate int32_t get_total_corner_num() const { return _total_corner_num; } int32_t get_total_wire_length() const { return _total_wire_length; } bool get_is_path_blocked() const { return _is_path_blocked; } + double get_total_usage_cost() const { return _total_usage_cost; } + double get_total_saturation_cost() const { return _total_saturation_cost; } + double get_total_hotspot_cost() const { return _total_hotspot_cost; } double get_total_overflow_cost() const { return _total_overflow_cost; } + double get_total_overflow() const { return _total_overflow; } + double get_max_usage_ratio() const { return _max_usage_ratio; } + int32_t get_saturation_node_num() const { return _saturation_node_num; } + int32_t get_hotspot_node_num() const { return _hotspot_node_num; } + int32_t get_overflow_node_num() const { return _overflow_node_num; } + double get_total_cost() const { return _total_usage_cost + _total_saturation_cost + _total_hotspot_cost + _total_overflow_cost; } // setter void set_topo_idx(const int32_t topo_idx) { _topo_idx = topo_idx; } void set_routing_segment_list(const std::vector>& routing_segment_list) { _routing_segment_list = routing_segment_list; } void set_total_corner_num(const int32_t total_corner_num) { _total_corner_num = total_corner_num; } void set_total_wire_length(const int32_t total_wire_length) { _total_wire_length = total_wire_length; } void set_is_path_blocked(const bool is_path_blocked) { _is_path_blocked = is_path_blocked; } + void set_total_usage_cost(const double total_usage_cost) { _total_usage_cost = total_usage_cost; } + void set_total_saturation_cost(const double total_saturation_cost) { _total_saturation_cost = total_saturation_cost; } + void set_total_hotspot_cost(const double total_hotspot_cost) { _total_hotspot_cost = total_hotspot_cost; } void set_total_overflow_cost(const double total_overflow_cost) { _total_overflow_cost = total_overflow_cost; } + void set_total_overflow(const double total_overflow) { _total_overflow = total_overflow; } + void set_max_usage_ratio(const double max_usage_ratio) { _max_usage_ratio = max_usage_ratio; } + void set_saturation_node_num(const int32_t saturation_node_num) { _saturation_node_num = saturation_node_num; } + void set_hotspot_node_num(const int32_t hotspot_node_num) { _hotspot_node_num = hotspot_node_num; } + void set_overflow_node_num(const int32_t overflow_node_num) { _overflow_node_num = overflow_node_num; } + void set_candidate_cost(const TGCandidateCost& candidate_cost) + { + _total_corner_num = candidate_cost.total_corner_num; + _total_wire_length = candidate_cost.total_wire_length; + _is_path_blocked = candidate_cost.is_path_blocked; + _total_usage_cost = candidate_cost.total_usage_cost; + _total_saturation_cost = candidate_cost.total_saturation_cost; + _total_hotspot_cost = candidate_cost.total_hotspot_cost; + _total_overflow_cost = candidate_cost.total_overflow_cost; + _total_overflow = candidate_cost.total_overflow; + _max_usage_ratio = candidate_cost.max_usage_ratio; + _saturation_node_num = candidate_cost.saturation_node_num; + _hotspot_node_num = candidate_cost.hotspot_node_num; + _overflow_node_num = candidate_cost.overflow_node_num; + } // function private: @@ -59,7 +113,15 @@ class TGCandidate int32_t _total_corner_num = 0; int32_t _total_wire_length = 0; bool _is_path_blocked = false; + double _total_usage_cost = 0.0; + double _total_saturation_cost = 0.0; + double _total_hotspot_cost = 0.0; double _total_overflow_cost = 0.0; + double _total_overflow = 0.0; + double _max_usage_ratio = 0.0; + int32_t _saturation_node_num = 0; + int32_t _hotspot_node_num = 0; + int32_t _overflow_node_num = 0; }; } // namespace irt diff --git a/src/operation/iRT/source/module/topology_generator/tg_data_manager/TGComParam.hpp b/src/operation/iRT/source/module/topology_generator/tg_data_manager/TGComParam.hpp index 0f2620360..f6e6c857b 100644 --- a/src/operation/iRT/source/module/topology_generator/tg_data_manager/TGComParam.hpp +++ b/src/operation/iRT/source/module/topology_generator/tg_data_manager/TGComParam.hpp @@ -22,12 +22,14 @@ class TGComParam { public: TGComParam() = default; - TGComParam(int32_t topo_spilt_length, int32_t expand_step_num, int32_t expand_step_length, double overflow_unit) + TGComParam(int32_t topo_spilt_length, int32_t expand_step_num, int32_t expand_step_length, double overflow_unit, + double corner_weight = 0.3) { _topo_spilt_length = topo_spilt_length; _expand_step_num = expand_step_num; _expand_step_length = expand_step_length; _overflow_unit = overflow_unit; + _corner_weight = corner_weight; } ~TGComParam() = default; // getter @@ -35,17 +37,20 @@ class TGComParam int32_t get_expand_step_num() const { return _expand_step_num; } int32_t get_expand_step_length() const { return _expand_step_length; } double get_overflow_unit() const { return _overflow_unit; } + double get_corner_weight() const { return _corner_weight; } // setter void set_topo_spilt_length(const int32_t topo_spilt_length) { _topo_spilt_length = topo_spilt_length; } void set_expand_step_num(const int32_t expand_step_num) { _expand_step_num = expand_step_num; } void set_expand_step_length(const int32_t expand_step_length) { _expand_step_length = expand_step_length; } void set_overflow_unit(const double overflow_unit) { _overflow_unit = overflow_unit; } + void set_corner_weight(const double corner_weight) { _corner_weight = corner_weight; } private: int32_t _topo_spilt_length = 0; int32_t _expand_step_num = 0; int32_t _expand_step_length = 0; double _overflow_unit = 0; + double _corner_weight = 0.3; }; } // namespace irt diff --git a/src/operation/iRT/source/module/topology_generator/tg_data_manager/TGNode.hpp b/src/operation/iRT/source/module/topology_generator/tg_data_manager/TGNode.hpp index 5cf0a807d..3c1d8d01f 100644 --- a/src/operation/iRT/source/module/topology_generator/tg_data_manager/TGNode.hpp +++ b/src/operation/iRT/source/module/topology_generator/tg_data_manager/TGNode.hpp @@ -24,6 +24,33 @@ namespace irt { +struct TGNodeCost +{ + double usage_cost = 0.0; + double saturation_cost = 0.0; + double hotspot_cost = 0.0; + double overflow_cost = 0.0; + double overflow = 0.0; + double max_usage_ratio = 0.0; + int32_t saturation_orient_num = 0; + int32_t hotspot_orient_num = 0; + int32_t overflow_orient_num = 0; + + double getTotalCost() const { return usage_cost + saturation_cost + hotspot_cost + overflow_cost; } + void addCost(const TGNodeCost& cost) + { + usage_cost += cost.usage_cost; + saturation_cost += cost.saturation_cost; + hotspot_cost += cost.hotspot_cost; + overflow_cost += cost.overflow_cost; + overflow += cost.overflow; + max_usage_ratio = std::max(max_usage_ratio, cost.max_usage_ratio); + saturation_orient_num += cost.saturation_orient_num; + hotspot_orient_num += cost.hotspot_orient_num; + overflow_orient_num += cost.overflow_orient_num; + } +}; + class TGNode : public PlanarCoord { public: @@ -56,13 +83,20 @@ class TGNode : public PlanarCoord } return neighbor_node; } - double getOverflowCost(int32_t net_idx, Direction direction, double overflow_unit) + TGNodeCost getCost(int32_t net_idx, Direction direction, double overflow_unit, + const std::set* extra_orient_set = nullptr) { if (!validDemandUnit()) { RTLOG.error(Loc::current(), "The demand unit is error!"); } std::map> orient_net_map = _orient_net_map; std::map> net_orient_map = _net_orient_map; + if (extra_orient_set) { + for (Orientation orient : *extra_orient_set) { + orient_net_map[orient].insert(net_idx); + net_orient_map[net_idx].insert(orient); + } + } if (direction == Direction::kHorizontal) { for (Orientation orient : {Orientation::kEast, Orientation::kWest}) { orient_net_map[orient].insert(net_idx); @@ -76,7 +110,7 @@ class TGNode : public PlanarCoord } else { RTLOG.error(Loc::current(), "The direction is error!"); } - double boundary_overflow = 0; + TGNodeCost node_cost; for (Orientation orient : {Orientation::kEast, Orientation::kWest, Orientation::kSouth, Orientation::kNorth}) { double boundary_demand = 0; if (RTUTIL.exist(orient_net_map, orient)) { @@ -91,9 +125,8 @@ class TGNode : public PlanarCoord if (RTUTIL.exist(_orient_supply_map, orient)) { boundary_supply = _orient_supply_map[orient]; } - boundary_overflow += calcCost(boundary_demand, boundary_supply); + node_cost.addCost(calcCost(boundary_demand, boundary_supply, overflow_unit)); } - double internal_overflow = 0; { double internal_demand = 0; for (Orientation orient : {Orientation::kEast, Orientation::kWest, Orientation::kSouth, Orientation::kNorth}) { @@ -110,11 +143,14 @@ class TGNode : public PlanarCoord for (auto& [orient, supply] : _orient_supply_map) { internal_supply += supply; } - internal_overflow += calcCost(internal_demand, internal_supply); + node_cost.addCost(calcCost(internal_demand, internal_supply, overflow_unit)); } - double cost = 0; - cost += (overflow_unit * (boundary_overflow + internal_overflow)); - return cost; + return node_cost; + } + double getOverflowCost(int32_t net_idx, Direction direction, double overflow_unit, + const std::set* extra_orient_set = nullptr) + { + return getCost(net_idx, direction, overflow_unit, extra_orient_set).getTotalCost(); } bool validDemandUnit() { @@ -126,15 +162,47 @@ class TGNode : public PlanarCoord } return true; } - double calcCost(double demand, double supply) + TGNodeCost calcCost(double demand, double supply, double overflow_unit) { - double cost = 0; - if (demand == supply) { - cost = 1; - } else if (demand > supply) { - cost = std::pow(demand - supply + 1, 4); - } else if (demand < supply) { - cost = std::pow(demand / supply, 4); + constexpr double kSaturationStartRatio = 0.8; + constexpr double kHotspotStartRatio = 0.9; + constexpr double kFullSupplyPenaltyScale = 1.0; + constexpr double kHotspotPenaltyScale = 2.0; + + TGNodeCost cost; + if (supply <= 0) { + if (demand <= 0) { + return cost; + } + cost.max_usage_ratio = demand + 1.0; + cost.overflow = demand; + cost.overflow_orient_num = 1; + cost.overflow_cost = overflow_unit * std::pow(cost.overflow + 1, 4); + return cost; + } + + double usage_ratio = demand / supply; + cost.max_usage_ratio = usage_ratio; + if (demand > supply) { + cost.overflow = demand - supply; + cost.overflow_orient_num = 1; + cost.overflow_cost = overflow_unit * std::pow(cost.overflow + 1, 4); + return cost; + } + + cost.usage_cost = overflow_unit * std::pow(usage_ratio, 4); + if (usage_ratio >= kSaturationStartRatio) { + double saturation_ratio = (usage_ratio - kSaturationStartRatio) / (1.0 - kSaturationStartRatio); + cost.saturation_orient_num = 1; + cost.saturation_cost = overflow_unit * std::pow(saturation_ratio, 2); + if (usage_ratio >= 1.0) { + cost.saturation_cost += overflow_unit * kFullSupplyPenaltyScale; + } + } + if (usage_ratio >= kHotspotStartRatio) { + double hotspot_ratio = (usage_ratio - kHotspotStartRatio) / (1.0 - kHotspotStartRatio); + cost.hotspot_orient_num = 1; + cost.hotspot_cost = overflow_unit * kHotspotPenaltyScale * std::pow(hotspot_ratio, 2); } return cost; }