From 09115657363d18d4fa13c9ca56cd211f419c18ea Mon Sep 17 00:00:00 2001 From: Eder Monteiro Date: Mon, 10 Feb 2025 17:48:21 -0300 Subject: [PATCH 1/3] ppl: small code refactoring Signed-off-by: Eder Monteiro --- src/ppl/include/ppl/IOPlacer.h | 8 +- src/ppl/src/IOPlacer.cpp | 309 +++++++++++++++++++-------------- 2 files changed, 181 insertions(+), 136 deletions(-) diff --git a/src/ppl/include/ppl/IOPlacer.h b/src/ppl/include/ppl/IOPlacer.h index ec2b3ebd47f..a61183e8382 100644 --- a/src/ppl/include/ppl/IOPlacer.h +++ b/src/ppl/include/ppl/IOPlacer.h @@ -190,11 +190,12 @@ class IOPlacer std::vector getValidSlots(int first, int last, bool top_layer); std::vector findValidSlots(const Constraint& constraint, bool top_layer); void randomPlacement(); - void randomPlacement(std::vector pin_indices, - std::vector slot_indices, + void randomPlacement(const std::vector& pin_indices, + const std::vector& slot_indices, Edge edge, bool top_layer, bool is_group); + std::string getSlotsLocation(Edge edge, bool top_layer); int placeFallbackPins(bool random); void assignMirroredPins(IOPin& io_pin, MirroredPins& mirrored_pins, @@ -210,6 +211,8 @@ class IOPlacer void placeFallbackGroup(const std::pair, bool>& group, int place_slot); void findSlots(const std::set& layers, Edge edge); + std::vector findLayerSlots(int layer, Edge edge); + int computeDistanceBetweenPins(const int layer, const int min_distance); void findSlotsForTopLayer(); void filterObstructedSlotsForTopLayer(); std::vector
findSectionsForTopLayer(const odb::Rect& region); @@ -275,6 +278,7 @@ class IOPlacer int num_pins, int& new_begin, int& new_end); + int getMinDistanceForInterval(const Interval& interval); int64_t computeIncrease(int min_dist, int64_t num_pins, int64_t curr_length); // db functions diff --git a/src/ppl/src/IOPlacer.cpp b/src/ppl/src/IOPlacer.cpp index 89737362957..85bdd57a19d 100644 --- a/src/ppl/src/IOPlacer.cpp +++ b/src/ppl/src/IOPlacer.cpp @@ -191,6 +191,8 @@ std::vector IOPlacer::findValidSlots(const Constraint& constraint, void IOPlacer::randomPlacement() { + // start the random placement by assigning the pins constrained to specific + // regions in the die boundaries or in the top layer grid. for (Constraint& constraint : constraints_) { const Edge edge = constraint.interval.getEdge(); bool top_layer = edge == Edge::invalid; @@ -223,6 +225,7 @@ void IOPlacer::randomPlacement() std::move(pin_indices), std::move(valid_slots), edge, top_layer, false); } + // place the pin groups that are not constrained to any region for (auto& io_group : netlist_->getIOGroups()) { IOPin& io_pin = netlist_->getIoPin(io_group.pin_indices[0]); if (io_pin.isPlaced() || io_pin.inFallback()) { @@ -238,7 +241,6 @@ void IOPlacer::randomPlacement() } std::vector valid_slots = getValidSlots(0, slots_.size() - 1, false); - std::vector pin_indices; for (int i = 0; i < netlist_->numIOPins(); i++) { IOPin& io_pin = netlist_->getIoPin(i); @@ -247,16 +249,20 @@ void IOPlacer::randomPlacement() } } + // place the remaining pins randomPlacement(std::move(pin_indices), std::move(valid_slots), Edge::invalid, false, false); + + // try placing pin groups or constrained pins that failed in the first try + // with relaxed constraints. placeFallbackPins(true); } -void IOPlacer::randomPlacement(std::vector pin_indices, - std::vector slot_indices, +void IOPlacer::randomPlacement(const std::vector& pin_indices, + const std::vector& slot_indices, const Edge edge, bool top_layer, bool is_group) @@ -272,50 +278,38 @@ void IOPlacer::randomPlacement(std::vector pin_indices, return; } - std::string slots_location; - if (top_layer) { - slots_location = "top layer grid"; - } else if (edge != Edge::invalid) { - slots_location = getEdgeString(edge) + " edge"; - } else { - slots_location = "die boundaries."; - } - logger_->error(PPL, 72, "The number of pins ({}) exceeds the number of valid " "positions ({}) in the {}.", pin_indices.size(), slot_indices.size(), - slots_location); + getSlotsLocation(edge, top_layer)); } const auto seed = parms_->getRandSeed(); - const int num_i_os = pin_indices.size(); - if (num_i_os == 0) { + const int pin_count = pin_indices.size(); + if (pin_count == 0) { return; } - const int num_slots = slot_indices.size(); - const double shift = is_group ? 1 : num_slots / double(num_i_os); - std::vector vSlots(num_slots); - std::vector io_pin_indices(num_i_os); - std::vector instPins; + const int num_slots = slot_indices.size(); + const double shift = is_group ? 1 : num_slots / double(pin_count); + std::vector io_pin_indices(pin_count); - std::mt19937 g; - g.seed(seed); + std::mt19937 generator; + generator.seed(seed); for (size_t i = 0; i < io_pin_indices.size(); ++i) { io_pin_indices[i] = i; } if (io_pin_indices.size() > 1 && !is_group) { - utl::shuffle(io_pin_indices.begin(), io_pin_indices.end(), g); + utl::shuffle(io_pin_indices.begin(), io_pin_indices.end(), generator); } std::vector& slots = top_layer ? top_layer_slots_ : slots_; - std::vector& io_pins = netlist_->getIOPins(); int io_idx = 0; for (bool assign_mirrored : {true, false}) { @@ -393,6 +387,20 @@ void IOPlacer::randomPlacement(std::vector pin_indices, } } +std::string IOPlacer::getSlotsLocation(Edge edge, bool top_layer) +{ + std::string slots_location; + if (top_layer) { + slots_location = "top layer grid"; + } else if (edge != Edge::invalid) { + slots_location = getEdgeString(edge) + " edge"; + } else { + slots_location = "die boundaries."; + } + + return slots_location; +} + int IOPlacer::placeFallbackPins(bool random) { int placed_pins_cnt = 0; @@ -833,6 +841,21 @@ void IOPlacer::computeRegionIncrease(const Interval& interval, interval_length -= interval_end - blocked_coord_max; } + int min_dist = getMinDistanceForInterval(interval); + + const int increase = computeIncrease(min_dist, num_pins, interval_length); + + if (interval_end > blocked_coord_max) { + new_begin -= increase; + } else { + new_end += increase; + } +} + +int IOPlacer::getMinDistanceForInterval(const Interval& interval) +{ + const bool vertical_pin + = interval.getEdge() == Edge::top || interval.getEdge() == Edge::bottom; int min_dist = std::numeric_limits::min(); if (interval.getLayer() != -1) { @@ -840,31 +863,19 @@ void IOPlacer::computeRegionIncrease(const Interval& interval, = vertical_pin ? core_->getMinDstPinsX().at(interval.getLayer()) : core_->getMinDstPinsY().at(interval.getLayer()); min_dist = *(std::max_element(min_distances.begin(), min_distances.end())); - } else if (vertical_pin) { - for (int layer_idx : ver_layers_) { - std::vector layer_min_distances - = core_->getMinDstPinsX().at(layer_idx); - const int layer_min_dist = *(std::max_element(layer_min_distances.begin(), - layer_min_distances.end())); - min_dist = std::max(layer_min_dist, min_dist); - } } else { - for (int layer_idx : hor_layers_) { + const std::set& layers = vertical_pin ? ver_layers_ : hor_layers_; + for (int layer_idx : layers) { std::vector layer_min_distances - = core_->getMinDstPinsY().at(layer_idx); + = vertical_pin ? core_->getMinDstPinsX().at(layer_idx) + : core_->getMinDstPinsY().at(layer_idx); const int layer_min_dist = *(std::max_element(layer_min_distances.begin(), layer_min_distances.end())); min_dist = std::max(layer_min_dist, min_dist); } } - const int increase = computeIncrease(min_dist, num_pins, interval_length); - - if (interval_end > blocked_coord_max) { - new_begin -= increase; - } else { - new_end += increase; - } + return min_dist; } int64_t IOPlacer::computeIncrease(int min_dist, @@ -888,107 +899,18 @@ int64_t IOPlacer::computeIncrease(int min_dist, void IOPlacer::findSlots(const std::set& layers, Edge edge) { - Point lb = core_->getBoundary().ll(); - Point ub = core_->getBoundary().ur(); - - int lb_x = lb.x(); - int lb_y = lb.y(); - int ub_x = ub.x(); - int ub_y = ub.y(); - bool vertical_pin = (edge == Edge::top || edge == Edge::bottom); - int min = vertical_pin ? lb_x : lb_y; - int max = vertical_pin ? ub_x : ub_y; - corner_avoidance_ = parms_->getCornerAvoidance(); - bool dist_in_tracks = parms_->getMinDistanceInTracks(); for (int layer : layers) { const std::vector& layer_min_distances = vertical_pin ? core_->getMinDstPinsX().at(layer) : core_->getMinDstPinsY().at(layer); - const std::vector& layer_init_tracks - = vertical_pin ? core_->getInitTracksX().at(layer) - : core_->getInitTracksY().at(layer); - const std::vector& layer_num_tracks - = vertical_pin ? core_->getNumTracksX().at(layer) - : core_->getNumTracksY().at(layer); - - std::vector slots; - int min_dst_pins = 0; - for (int l = 0; l < layer_min_distances.size(); l++) { - int curr_x, curr_y, start_idx, end_idx; - int tech_min_dst = layer_min_distances[l]; - min_dst_pins - = dist_in_tracks - ? tech_min_dst * parms_->getMinDistance() - : tech_min_dst - * std::ceil(static_cast(parms_->getMinDistance()) - / tech_min_dst); - - min_dst_pins = (min_dst_pins == 0) ? default_min_dist_ * tech_min_dst - : min_dst_pins; - - if (corner_avoidance_ == -1) { - corner_avoidance_ = num_tracks_offset_ * tech_min_dst; - // limit default offset to 1um - if (corner_avoidance_ > getBlock()->micronsToDbu(1.0)) { - corner_avoidance_ = getBlock()->micronsToDbu(1.0); - } - } - - int init_tracks = layer_init_tracks[l]; - int num_tracks = layer_num_tracks[l]; - - float thickness_multiplier - = vertical_pin ? parms_->getVerticalThicknessMultiplier() - : parms_->getHorizontalThicknessMultiplier(); - - int half_width = vertical_pin - ? int(ceil(core_->getMinWidthX()[layer] / 2.0)) - : int(ceil(core_->getMinWidthY()[layer] / 2.0)); - half_width *= thickness_multiplier; + std::vector slots = findLayerSlots(layer, edge); - int num_tracks_offset - = std::ceil(static_cast(corner_avoidance_) / min_dst_pins); - - start_idx - = std::max(0.0, - ceil(static_cast((min + half_width - init_tracks)) - / min_dst_pins)) - + num_tracks_offset; - end_idx = std::min((num_tracks - 1), - static_cast((max - half_width - init_tracks) - / min_dst_pins)) - - num_tracks_offset; - if (vertical_pin) { - curr_x = init_tracks + start_idx * min_dst_pins; - curr_y = (edge == Edge::bottom) ? lb_y : ub_y; - } else { - curr_y = init_tracks + start_idx * min_dst_pins; - curr_x = (edge == Edge::left) ? lb_x : ub_x; - } - - for (int i = start_idx; i <= end_idx; ++i) { - odb::Point pos(curr_x, curr_y); - slots.push_back(pos); - if (vertical_pin) { - curr_x += min_dst_pins; - } else { - curr_y += min_dst_pins; - } - } - } - - std::sort(slots.begin(), - slots.end(), - [&](const odb::Point& p1, const odb::Point& p2) { - if (vertical_pin) { - return p1.getX() < p2.getX(); - } - - return p1.getY() < p2.getY(); - }); + int tech_min_dst = *(std::max_element(layer_min_distances.begin(), + layer_min_distances.end())); + int min_dst_pins = computeDistanceBetweenPins(layer, tech_min_dst); // Remove slots that violates the min distance before reversing the vector. // This ensures that mirrored positions will exists for every slot. @@ -1015,6 +937,125 @@ void IOPlacer::findSlots(const std::set& layers, Edge edge) } } +std::vector IOPlacer::findLayerSlots(const int layer, const Edge edge) +{ + Point lb = core_->getBoundary().ll(); + Point ub = core_->getBoundary().ur(); + + int lb_x = lb.x(); + int lb_y = lb.y(); + int ub_x = ub.x(); + int ub_y = ub.y(); + + bool vertical_pin = (edge == Edge::top || edge == Edge::bottom); + int min = vertical_pin ? lb_x : lb_y; + int max = vertical_pin ? ub_x : ub_y; + + corner_avoidance_ = parms_->getCornerAvoidance(); + + const std::vector& layer_min_distances + = vertical_pin ? core_->getMinDstPinsX().at(layer) + : core_->getMinDstPinsY().at(layer); + + const std::vector& layer_init_tracks + = vertical_pin ? core_->getInitTracksX().at(layer) + : core_->getInitTracksY().at(layer); + + const std::vector& layer_num_tracks + = vertical_pin ? core_->getNumTracksX().at(layer) + : core_->getNumTracksY().at(layer); + + std::vector slots; + for (int l = 0; l < layer_min_distances.size(); l++) { + int tech_min_dst = layer_min_distances[l]; + int min_dst_pins = computeDistanceBetweenPins(l, tech_min_dst); + + min_dst_pins + = (min_dst_pins == 0) ? default_min_dist_ * tech_min_dst : min_dst_pins; + + if (corner_avoidance_ == -1) { + corner_avoidance_ = num_tracks_offset_ * tech_min_dst; + // limit default offset to 1um + if (corner_avoidance_ > getBlock()->micronsToDbu(1.0)) { + corner_avoidance_ = getBlock()->micronsToDbu(1.0); + } + } + + int init_tracks = layer_init_tracks[l]; + int num_tracks = layer_num_tracks[l]; + + float thickness_multiplier + = vertical_pin ? parms_->getVerticalThicknessMultiplier() + : parms_->getHorizontalThicknessMultiplier(); + + int half_width = vertical_pin + ? int(ceil(core_->getMinWidthX()[layer] / 2.0)) + : int(ceil(core_->getMinWidthY()[layer] / 2.0)); + + half_width *= thickness_multiplier; + + int num_tracks_offset + = std::ceil(static_cast(corner_avoidance_) / min_dst_pins); + + int curr_x, curr_y, start_idx, end_idx; + start_idx + = std::max(0.0, + ceil(static_cast((min + half_width - init_tracks)) + / min_dst_pins)) + + num_tracks_offset; + end_idx = std::min((num_tracks - 1), + static_cast((max - half_width - init_tracks) + / min_dst_pins)) + - num_tracks_offset; + if (vertical_pin) { + curr_x = init_tracks + start_idx * min_dst_pins; + curr_y = (edge == Edge::bottom) ? lb_y : ub_y; + } else { + curr_y = init_tracks + start_idx * min_dst_pins; + curr_x = (edge == Edge::left) ? lb_x : ub_x; + } + + for (int i = start_idx; i <= end_idx; ++i) { + odb::Point pos(curr_x, curr_y); + slots.push_back(pos); + if (vertical_pin) { + curr_x += min_dst_pins; + } else { + curr_y += min_dst_pins; + } + } + } + + std::sort(slots.begin(), + slots.end(), + [&](const odb::Point& p1, const odb::Point& p2) { + if (vertical_pin) { + return p1.getX() < p2.getX(); + } + + return p1.getY() < p2.getY(); + }); + + return slots; +} + +int IOPlacer::computeDistanceBetweenPins(const int layer, + const int min_distance) +{ + bool dist_in_tracks = parms_->getMinDistanceInTracks(); + int min_dst_pins + = dist_in_tracks + ? min_distance * parms_->getMinDistance() + : min_distance + * std::ceil(static_cast(parms_->getMinDistance()) + / min_distance); + + min_dst_pins + = (min_dst_pins == 0) ? default_min_dist_ * min_distance : min_dst_pins; + + return min_dst_pins; +} + void IOPlacer::defineSlots() { /******************************************* From 8916e73647b5c9c127ff4b1b8a1b02c150dd5710 Mon Sep 17 00:00:00 2001 From: Eder Monteiro Date: Mon, 24 Feb 2025 19:58:47 -0300 Subject: [PATCH 2/3] ppl: clang-format Signed-off-by: Eder Monteiro --- src/ppl/src/IOPlacer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ppl/src/IOPlacer.cpp b/src/ppl/src/IOPlacer.cpp index 85bdd57a19d..bbb13d5cd0e 100644 --- a/src/ppl/src/IOPlacer.cpp +++ b/src/ppl/src/IOPlacer.cpp @@ -1040,7 +1040,7 @@ std::vector IOPlacer::findLayerSlots(const int layer, const Edge edge) } int IOPlacer::computeDistanceBetweenPins(const int layer, - const int min_distance) + const int min_distance) { bool dist_in_tracks = parms_->getMinDistanceInTracks(); int min_dst_pins From 28b4292f6f6214b27beee9fa9700d78e1d750770 Mon Sep 17 00:00:00 2001 From: Eder Monteiro Date: Mon, 24 Feb 2025 20:23:26 -0300 Subject: [PATCH 3/3] ppl: clang-tidy Signed-off-by: Eder Monteiro --- src/ppl/include/ppl/IOPlacer.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ppl/include/ppl/IOPlacer.h b/src/ppl/include/ppl/IOPlacer.h index a61183e8382..26fa72ee1bc 100644 --- a/src/ppl/include/ppl/IOPlacer.h +++ b/src/ppl/include/ppl/IOPlacer.h @@ -212,7 +212,7 @@ class IOPlacer int place_slot); void findSlots(const std::set& layers, Edge edge); std::vector findLayerSlots(int layer, Edge edge); - int computeDistanceBetweenPins(const int layer, const int min_distance); + int computeDistanceBetweenPins(int layer, int min_distance); void findSlotsForTopLayer(); void filterObstructedSlotsForTopLayer(); std::vector
findSectionsForTopLayer(const odb::Rect& region);