diff --git a/src/ioPlacer/include/ioplacer/IOPlacer.h b/src/ioPlacer/include/ioplacer/IOPlacer.h index d4313024d79..55c3b8851b3 100644 --- a/src/ioPlacer/include/ioplacer/IOPlacer.h +++ b/src/ioPlacer/include/ioplacer/IOPlacer.h @@ -53,7 +53,7 @@ namespace odb { class dbDatabase; class dbTech; class dbBlock; -} +} // namespace odb namespace ppl { @@ -86,9 +86,7 @@ struct Interval int begin; int end; Interval() = default; - Interval(Edge edg, int b, int e) : - edge(edg), begin(b), end(e) - {} + Interval(Edge edg, int b, int e) : edge(edg), begin(b), end(e) {} Edge getEdge() { return edge; } int getBegin() { return begin; } int getEnd() { return end; } @@ -99,9 +97,10 @@ struct Constraint std::string name; Direction direction; Interval interval; - Constraint(std::string name, Direction dir, Interval interv) : - name(name), direction(dir), interval(interv) - {} + Constraint(std::string name, Direction dir, Interval interv) + : name(name), direction(dir), interval(interv) + { + } }; class IOPlacer @@ -116,10 +115,11 @@ class IOPlacer Parameters* getParameters() { return parms_; } int returnIONetsHPWL(); void excludeInterval(Edge edge, int begin, int end); - void addDirectionConstraint(Direction direction, Edge edge, - int begin, int end); - void addNameConstraint(std::string name, Edge edge, - int begin, int end); + void addDirectionConstraint(Direction direction, + Edge edge, + int begin, + int end); + void addNameConstraint(std::string name, Edge edge, int begin, int end); void addHorLayer(int layer) { hor_layers_.insert(layer); } void addVerLayer(int layer) { ver_layers_.insert(layer); } Edge getEdge(std::string edge); @@ -144,7 +144,8 @@ class IOPlacer private: void makeComponents(); void deleteComponents(); - void initNetlistAndCore(std::set hor_layer_idx, std::set ver_layer_idx); + void initNetlistAndCore(std::set hor_layer_idx, + std::set ver_layer_idx); void initIOLists(); void initParms(); void randomPlacement(const RandomMode); @@ -160,14 +161,15 @@ class IOPlacer bool checkBlocked(Edge edge, int pos); // db functions - void populateIOPlacer(std::set hor_layer_idx, std::set ver_layer_idx); + void populateIOPlacer(std::set hor_layer_idx, + std::set ver_layer_idx); void commitIOPlacementToDB(std::vector& assignment); void initCore(std::set hor_layer_idxs, std::set ver_layer_idxs); void initNetlist(); void initTracks(); ord::OpenRoad* openroad_; - Logger *logger_; + Logger* logger_; Parameters* parms_; Netlist netlist_io_pins_; SlotVector slots_; diff --git a/src/ioPlacer/src/Core.cpp b/src/ioPlacer/src/Core.cpp index d66d0b8bc84..4fed8903b57 100644 --- a/src/ioPlacer/src/Core.cpp +++ b/src/ioPlacer/src/Core.cpp @@ -34,6 +34,7 @@ /////////////////////////////////////////////////////////////////////////////// #include "Core.h" + #include namespace ppl { diff --git a/src/ioPlacer/src/HungarianMatching.cpp b/src/ioPlacer/src/HungarianMatching.cpp index b9e65b2a5d6..1e223406b80 100644 --- a/src/ioPlacer/src/HungarianMatching.cpp +++ b/src/ioPlacer/src/HungarianMatching.cpp @@ -34,11 +34,14 @@ /////////////////////////////////////////////////////////////////////////////// #include "HungarianMatching.h" + #include "utility/Logger.h" namespace ppl { -HungarianMatching::HungarianMatching(Section& section, SlotVector& slots, Logger *logger) +HungarianMatching::HungarianMatching(Section& section, + SlotVector& slots, + Logger* logger) : netlist_(section.net), slots_(slots) { num_io_pins_ = netlist_.numIOPins(); @@ -96,8 +99,11 @@ void HungarianMatching::getFinalAssignment(std::vector& assigment) continue; } if (hungarian_matrix_[row][col] == hungarian_fail) { - logger_->warn(utl::PPL, 33, "I/O pin {} cannot be placed in the specified region. Not enough space", - io_pin.getName().c_str()); + logger_->warn(utl::PPL, + 33, + "I/O pin {} cannot be placed in the specified region. " + "Not enough space", + io_pin.getName().c_str()); } io_pin.setPos(slots_[slot_index].pos); io_pin.setLayer(slots_[slot_index].layer); diff --git a/src/ioPlacer/src/HungarianMatching.h b/src/ioPlacer/src/HungarianMatching.h index a3325ffbe7b..8238648e873 100644 --- a/src/ioPlacer/src/HungarianMatching.h +++ b/src/ioPlacer/src/HungarianMatching.h @@ -43,9 +43,9 @@ #include #include "Hungarian.h" -#include "ioplacer/IOPlacer.h" #include "Netlist.h" #include "Slots.h" +#include "ioplacer/IOPlacer.h" namespace utl { class Logger; @@ -72,12 +72,12 @@ class HungarianMatching int non_blocked_slots_; Edge edge_; const int hungarian_fail = std::numeric_limits::max(); - Logger *logger_; + Logger* logger_; void createMatrix(std::vector& constraints); public: - HungarianMatching(Section&, SlotVector&, Logger *logger); + HungarianMatching(Section&, SlotVector&, Logger* logger); virtual ~HungarianMatching() = default; void findAssignment(std::vector& constraints); void getFinalAssignment(std::vector&); diff --git a/src/ioPlacer/src/IOPlacer.cpp b/src/ioPlacer/src/IOPlacer.cpp index 94e294c9541..5773180a36a 100644 --- a/src/ioPlacer/src/IOPlacer.cpp +++ b/src/ioPlacer/src/IOPlacer.cpp @@ -35,11 +35,12 @@ #include "ioplacer/IOPlacer.h" -#include #include +#include + #include "opendb/db.h" -#include "utility/Logger.h" #include "openroad/OpenRoad.hh" +#include "utility/Logger.h" namespace ppl { @@ -85,7 +86,8 @@ IOPlacer::~IOPlacer() deleteComponents(); } -void IOPlacer::initNetlistAndCore(std::set hor_layer_idx, std::set ver_layer_idx) +void IOPlacer::initNetlistAndCore(std::set hor_layer_idx, + std::set ver_layer_idx) { populateIOPlacer(hor_layer_idx, ver_layer_idx); } @@ -129,7 +131,7 @@ void IOPlacer::randomPlacement(const RandomMode mode) const double seed = parms_->getRandSeed(); SlotVector valid_slots; - for (Slot &slot : slots_) { + for (Slot& slot : slots_) { if (!slot.blocked) { valid_slots.push_back(slot); } @@ -244,9 +246,8 @@ void IOPlacer::initIOLists() bool IOPlacer::checkBlocked(Edge edge, int pos) { for (Interval blocked_interval : excluded_intervals_) { - if (blocked_interval.getEdge() == edge && - pos >= blocked_interval.getBegin() && - pos <= blocked_interval.getEnd()) { + if (blocked_interval.getEdge() == edge && pos >= blocked_interval.getBegin() + && pos <= blocked_interval.getEnd()) { return true; } } @@ -274,32 +275,34 @@ void IOPlacer::findSlots(const std::set& layers, Edge edge) for (int layer : layers) { int curr_x, curr_y, start_idx, end_idx; - int min_dst_pins = vertical ? core_.getMinDstPinsX()[i] * parms_->getMinDistance() - : core_.getMinDstPinsY()[i] * parms_->getMinDistance(); - int init_tracks = vertical ? core_.getInitTracksX()[i] - : core_.getInitTracksY()[i]; - int num_tracks = vertical ? core_.getNumTracksX()[i] - : core_.getNumTracksY()[i]; + int min_dst_pins + = vertical ? core_.getMinDstPinsX()[i] * parms_->getMinDistance() + : core_.getMinDstPinsY()[i] * parms_->getMinDistance(); + int init_tracks + = vertical ? core_.getInitTracksX()[i] : core_.getInitTracksY()[i]; + int num_tracks + = vertical ? core_.getNumTracksX()[i] : core_.getNumTracksY()[i]; - float thickness_multiplier = vertical ? parms_->getVerticalThicknessMultiplier() - : parms_->getHorizontalThicknessMultiplier(); + float thickness_multiplier + = vertical ? parms_->getVerticalThicknessMultiplier() + : parms_->getHorizontalThicknessMultiplier(); int half_width = vertical ? int(ceil(core_.getMinWidthX()[i] / 2.0)) - : int(ceil(core_.getMinWidthY()[i] / 2.0)); + : int(ceil(core_.getMinWidthY()[i] / 2.0)); half_width *= thickness_multiplier; - int num_tracks_offset - = std::ceil(offset / (std::max(core_.getMinDstPinsX()[i] * parms_->getMinDistance(), - core_.getMinDstPinsY()[i] * parms_->getMinDistance()))); + int num_tracks_offset = std::ceil( + offset + / (std::max(core_.getMinDstPinsX()[i] * parms_->getMinDistance(), + core_.getMinDstPinsY()[i] * parms_->getMinDistance()))); start_idx - = std::max(0.0, - ceil((min + half_width - init_tracks) / min_dst_pins)) + = std::max(0.0, ceil((min + half_width - init_tracks) / min_dst_pins)) + num_tracks_offset; end_idx = std::min((num_tracks - 1), - (int)floor((max - half_width - init_tracks) / min_dst_pins)) + (int) floor((max - half_width - init_tracks) / min_dst_pins)) - num_tracks_offset; if (vertical) { curr_x = init_tracks + start_idx * min_dst_pins; @@ -327,7 +330,8 @@ void IOPlacer::findSlots(const std::set& layers, Edge edge) for (Point pos : slots) { curr_x = pos.getX(); curr_y = pos.getY(); - bool blocked = vertical ? checkBlocked(edge, curr_x) : checkBlocked(edge, curr_y); + bool blocked + = vertical ? checkBlocked(edge, curr_x) : checkBlocked(edge, curr_y); slots_.push_back({blocked, false, Point(curr_x, curr_y), layer}); } i++; @@ -393,10 +397,13 @@ void IOPlacer::createSections() int begin_slot = 0; int end_slot = 0; - int slots_per_edge = num_slots/slots_per_section_; + int slots_per_edge = num_slots / slots_per_section_; if (slots_per_edge < 4) { slots_per_section_ = num_slots / 4; - logger_->warn(PPL, 34, "Redefining the number of slots per section to have at least one section per edge"); + logger_->warn(PPL, + 34, + "Redefining the number of slots per section to have at least " + "one section per edge"); } while (end_slot < num_slots) { @@ -457,10 +464,12 @@ bool IOPlacer::assignPinsSections() std::vector dst(sections.size()); std::vector inst_pins_vector; for (int i = 0; i < sections.size(); i++) { - dst[i] = net.computeIONetHPWL(idx, sections[i].pos, sections[i].edge, constraints_); + dst[i] = net.computeIONetHPWL( + idx, sections[i].pos, sections[i].edge, constraints_); } - net.forEachSinkOfIO( - idx, [&](InstancePin& inst_pin) { inst_pins_vector.push_back(inst_pin); }); + net.forEachSinkOfIO(idx, [&](InstancePin& inst_pin) { + inst_pins_vector.push_back(inst_pin); + }); for (auto i : sortIndexes(dst)) { if (sections[i].cur_slots < sections[i].max_slots) { sections[i].net.addIONet(io_pin, inst_pins_vector); @@ -491,7 +500,8 @@ void IOPlacer::printConfig() { logger_->info(PPL, 1, " * Num of slots {}", slots_.size()); logger_->info(PPL, 2, " * Num of I/O {}", netlist_.numIOPins()); - logger_->info(PPL, 3, " * Num of I/O w/sink {}", netlist_io_pins_.numIOPins()); + logger_->info( + PPL, 3, " * Num of I/O w/sink {}", netlist_io_pins_.numIOPins()); logger_->info(PPL, 4, " * Num of I/O w/o sink {}", zero_sink_ios_.size()); logger_->info(PPL, 5, " * Slots Per Section {}", slots_per_section_); logger_->info(PPL, 6, " * Slots Increase Factor {}", slots_increase_factor_); @@ -514,16 +524,22 @@ void IOPlacer::setupSections() usage_per_section_ *= (1 + usage_increase_factor_); slots_per_section_ *= (1 + slots_increase_factor_); if (sections_.size() > MAX_SECTIONS_RECOMMENDED) { - logger_->warn(PPL, 36, "Number of sections is {}" - " while the maximum recommended value is {}" - " this may negatively affect performance", - sections_.size(), MAX_SECTIONS_RECOMMENDED); + logger_->warn(PPL, + 36, + "Number of sections is {}" + " while the maximum recommended value is {}" + " this may negatively affect performance", + sections_.size(), + MAX_SECTIONS_RECOMMENDED); } if (slots_per_section_ > MAX_SLOTS_RECOMMENDED) { - logger_->warn(PPL, 37, "Number of slots per sections is {}" - " while the maximum recommended value is {}" - " this may negatively affect performance", - slots_per_section_, MAX_SLOTS_RECOMMENDED); + logger_->warn(PPL, + 37, + "Number of slots per sections is {}" + " while the maximum recommended value is {}" + " this may negatively affect performance", + slots_per_section_, + MAX_SLOTS_RECOMMENDED); } } while (!all_assigned); } @@ -594,9 +610,11 @@ void IOPlacer::updatePinArea(IOPin& pin) if (pin.getOrientation() == Orientation::north || pin.getOrientation() == Orientation::south) { float thickness_multiplier = parms_->getVerticalThicknessMultiplier(); - int half_width = int(ceil(core_.getMinWidthX()[index] / 2.0)) * thickness_multiplier; - int height = int(std::max(2.0 * half_width, - ceil(core_.getMinAreaX()[index] / (2.0 * half_width)))); + int half_width + = int(ceil(core_.getMinWidthX()[index] / 2.0)) * thickness_multiplier; + int height + = int(std::max(2.0 * half_width, + ceil(core_.getMinAreaX()[index] / (2.0 * half_width)))); int ext = 0; if (parms_->getVerticalLength() != -1) { @@ -619,9 +637,11 @@ void IOPlacer::updatePinArea(IOPin& pin) if (pin.getOrientation() == Orientation::west || pin.getOrientation() == Orientation::east) { float thickness_multiplier = parms_->getHorizontalThicknessMultiplier(); - int half_width = int(ceil(core_.getMinWidthY()[index] / 2.0)) * thickness_multiplier; - int height = int(std::max(2.0 * half_width, - ceil(core_.getMinAreaY()[index] / (2.0 * half_width)))); + int half_width + = int(ceil(core_.getMinWidthY()[index] / 2.0)) * thickness_multiplier; + int height + = int(std::max(2.0 * half_width, + ceil(core_.getMinAreaY()[index] / (2.0 * half_width)))); int ext = 0; if (parms_->getHorizontalLengthExtend() != -1) { @@ -660,27 +680,33 @@ int IOPlacer::returnIONetsHPWL() void IOPlacer::excludeInterval(Edge edge, int begin, int end) { - Interval excluded_interv - = Interval(edge, begin, end); + Interval excluded_interv = Interval(edge, begin, end); excluded_intervals_.push_back(excluded_interv); } -void IOPlacer::addDirectionConstraint(Direction direction, Edge edge, - int begin, int end) { +void IOPlacer::addDirectionConstraint(Direction direction, + Edge edge, + int begin, + int end) +{ Interval interval(edge, begin, end); Constraint constraint("INVALID", direction, interval); constraints_.push_back(constraint); } -void IOPlacer::addNameConstraint(std::string name, Edge edge, - int begin, int end) { +void IOPlacer::addNameConstraint(std::string name, + Edge edge, + int begin, + int end) +{ Interval interval(edge, begin, end); Constraint constraint(name, Direction::invalid, interval); constraints_.push_back(constraint); } -Edge IOPlacer::getEdge(std::string edge) { +Edge IOPlacer::getEdge(std::string edge) +{ if (edge == "top") { return Edge::top; } else if (edge == "bottom") { @@ -694,7 +720,8 @@ Edge IOPlacer::getEdge(std::string edge) { return Edge::invalid; } -Direction IOPlacer::getDirection(std::string direction) { +Direction IOPlacer::getDirection(std::string direction) +{ if (direction == "input") { return Direction::input; } else if (direction == "output") { @@ -765,7 +792,11 @@ void IOPlacer::run(bool random_mode) } if (assignment_.size() != (int) netlist_.numIOPins()) { - logger_->error(PPL, 41, "Assigned {} pins out of {} IO pins", assignment_.size(), netlist_.numIOPins()); + logger_->error(PPL, + 41, + "Assigned {} pins out of {} IO pins", + assignment_.size(), + netlist_.numIOPins()); } if (report_hpwl_) { @@ -782,7 +813,8 @@ void IOPlacer::run(bool random_mode) } // db functions -void IOPlacer::populateIOPlacer(std::set hor_layer_idx, std::set ver_layer_idx) +void IOPlacer::populateIOPlacer(std::set hor_layer_idx, + std::set ver_layer_idx) { tech_ = db_->getTech(); block_ = db_->getChip()->getBlock(); @@ -790,7 +822,8 @@ void IOPlacer::populateIOPlacer(std::set hor_layer_idx, std::set ver_l initCore(hor_layer_idx, ver_layer_idx); } -void IOPlacer::initCore(std::set hor_layer_idxs, std::set ver_layer_idxs) +void IOPlacer::initCore(std::set hor_layer_idxs, + std::set ver_layer_idxs) { int database_unit = tech_->getLefUnits(); @@ -817,7 +850,8 @@ void IOPlacer::initCore(std::set hor_layer_idxs, std::set ver_layer_id odb::dbTechLayer* hor_layer = tech_->findRoutingLayer(hor_layer_idx); odb::dbTrackGrid* hor_track_grid = block_->findTrackGrid(hor_layer); - hor_track_grid->getGridPatternY(0, init_track_y, num_track_y, min_spacing_y); + hor_track_grid->getGridPatternY( + 0, init_track_y, num_track_y, min_spacing_y); min_area_y = hor_layer->getArea() * database_unit * database_unit; min_width_y = hor_layer->getWidth(); @@ -836,9 +870,10 @@ void IOPlacer::initCore(std::set hor_layer_idxs, std::set ver_layer_id int min_width_x = 0; int num_track_x = 0; - odb::dbTechLayer* ver_layer = tech_->findRoutingLayer(ver_layer_idx); + odb::dbTechLayer* ver_layer = tech_->findRoutingLayer(ver_layer_idx); odb::dbTrackGrid* ver_track_grid = block_->findTrackGrid(ver_layer); - ver_track_grid->getGridPatternX(0, init_track_x, num_track_x, min_spacing_x); + ver_track_grid->getGridPatternX( + 0, init_track_x, num_track_x, min_spacing_x); min_area_x = ver_layer->getArea() * database_unit * database_unit; min_width_x = ver_layer->getWidth(); @@ -851,17 +886,17 @@ void IOPlacer::initCore(std::set hor_layer_idxs, std::set ver_layer_id } core_ = Core(boundary, - min_spacings_x, - min_spacings_y, - init_tracks_x, - init_tracks_y, - num_tracks_x, - num_tracks_y, - min_areas_x, - min_areas_y, - min_widths_x, - min_widths_y, - database_unit); + min_spacings_x, + min_spacings_y, + init_tracks_x, + init_tracks_y, + num_tracks_x, + num_tracks_y, + min_areas_x, + min_areas_y, + min_widths_x, + min_widths_y, + database_unit); } void IOPlacer::initNetlist() @@ -874,8 +909,7 @@ void IOPlacer::initNetlist() odb::dbBTerm* cur_b_term = *bt_iter; odb::dbNet* net = cur_b_term->getNet(); if (!net) { - logger_->warn(PPL, 38, "Pin {} without net!", - cur_b_term->getConstName()); + logger_->warn(PPL, 38, "Pin {} without net!", cur_b_term->getConstName()); } Direction dir = Direction::inout; @@ -896,12 +930,12 @@ void IOPlacer::initNetlist() Point bounds(0, 0); IOPin io_pin(cur_b_term->getConstName(), - Point(x_pos, y_pos), - dir, - bounds, - bounds, - net->getConstName(), - "FIXED"); + Point(x_pos, y_pos), + dir, + bounds, + bounds, + net->getConstName(), + "FIXED"); std::vector inst_pins; odb::dbSet iterms = net->getITerms(); @@ -949,9 +983,9 @@ void IOPlacer::commitIOPlacementToDB(std::vector& assignment) int y_min = lower_bound.y(); int x_max = upper_bound.x(); int y_max = upper_bound.y(); - - int origin_x = x_max - int((x_max - x_min)/2); - int origin_y = y_max - int((y_max - y_min)/2); + + int origin_x = x_max - int((x_max - x_min) / 2); + int origin_y = y_max - int((y_max - y_min) / 2); odb::dbBox::create(bpin, layer, x_min, y_min, x_max, y_max); bpin->setPlacementStatus(odb::dbPlacementStatus::PLACED); } diff --git a/src/ioPlacer/src/MakeIoplacer.cpp b/src/ioPlacer/src/MakeIoplacer.cpp index cc703143abc..84e4956f892 100644 --- a/src/ioPlacer/src/MakeIoplacer.cpp +++ b/src/ioPlacer/src/MakeIoplacer.cpp @@ -35,8 +35,8 @@ #include "ioplacer/MakeIoplacer.h" -#include "ioplacer/IOPlacer.h" #include "Parameters.h" +#include "ioplacer/IOPlacer.h" #include "openroad/OpenRoad.hh" #include "sta/StaMain.hh" diff --git a/src/ioPlacer/src/Netlist.cpp b/src/ioPlacer/src/Netlist.cpp index 09f3515ca93..f165f6a466c 100644 --- a/src/ioPlacer/src/Netlist.cpp +++ b/src/ioPlacer/src/Netlist.cpp @@ -34,6 +34,7 @@ /////////////////////////////////////////////////////////////////////////////// #include "Netlist.h" + #include "Slots.h" #include "ioplacer/IOPlacer.h" @@ -67,8 +68,7 @@ void Netlist::forEachIOPin( } } -void Netlist::forEachSinkOfIO(int idx, - std::function func) +void Netlist::forEachSinkOfIO(int idx, std::function func) { int net_start = net_pointer_[idx]; int net_end = net_pointer_[idx + 1]; @@ -149,7 +149,9 @@ int Netlist::computeIONetHPWL(int idx, Point slot_pos) return (x + y); } -int Netlist::computeIONetHPWL(int idx, Point slot_pos, Edge edge, +int Netlist::computeIONetHPWL(int idx, + Point slot_pos, + Edge edge, std::vector& constraints) { int hpwl; @@ -173,35 +175,38 @@ int Netlist::computeDstIOtoPins(int idx, Point slot_pos) for (int idx = net_start; idx < net_end; ++idx) { Point pin_pos = inst_pins_[idx].getPos(); total_distance += std::abs(pin_pos.x() - slot_pos.x()) - + std::abs(pin_pos.y() - slot_pos.y()); + + std::abs(pin_pos.y() - slot_pos.y()); } return total_distance; } -bool Netlist::checkSlotForPin(IOPin& pin, Edge edge, odb::Point& point, - std::vector constraints) +bool Netlist::checkSlotForPin(IOPin& pin, + Edge edge, + odb::Point& point, + std::vector constraints) { bool valid_slot = true; for (Constraint constraint : constraints) { - int pos = (edge == Edge::top || edge == Edge::bottom) ? - point.x() : point.y(); + int pos + = (edge == Edge::top || edge == Edge::bottom) ? point.x() : point.y(); if (pin.getDirection() == constraint.direction) { valid_slot = checkInterval(constraint, edge, pos); } else if (pin.getName() == constraint.name) { - valid_slot = checkInterval(constraint, edge, pos); + valid_slot = checkInterval(constraint, edge, pos); } } return valid_slot; } -bool Netlist::checkInterval(Constraint constraint, Edge edge, int pos) { - return (constraint.interval.getEdge() == edge && - pos >= constraint.interval.getBegin() && - pos <= constraint.interval.getEnd()); +bool Netlist::checkInterval(Constraint constraint, Edge edge, int pos) +{ + return (constraint.interval.getEdge() == edge + && pos >= constraint.interval.getBegin() + && pos <= constraint.interval.getEnd()); } void Netlist::clear() diff --git a/src/ioPlacer/src/Netlist.h b/src/ioPlacer/src/Netlist.h index a952e7e010f..40185b92c40 100644 --- a/src/ioPlacer/src/Netlist.h +++ b/src/ioPlacer/src/Netlist.h @@ -120,8 +120,14 @@ class IOPin : public InstancePin void setY(const int y) { pos_.setY(y); } void setPos(const odb::Point pos) { pos_ = pos; } void setPos(const int x, const int y) { pos_ = odb::Point(x, y); } - void setLowerBound(const int x, const int y) { lower_bound_ = odb::Point(x, y); }; - void setUpperBound(const int x, const int y) { upper_bound_ = odb::Point(x, y); }; + void setLowerBound(const int x, const int y) + { + lower_bound_ = odb::Point(x, y); + }; + void setUpperBound(const int x, const int y) + { + upper_bound_ = odb::Point(x, y); + }; void setLayer(const int layer) { layer_ = layer; } Direction getDirection() const { return direction_; } odb::Point getLowerBound() const { return lower_bound_; }; @@ -138,7 +144,9 @@ class Netlist std::vector net_pointer_; std::vector io_pins_; - bool checkSlotForPin(IOPin& pin, Edge edge, odb::Point& point, + bool checkSlotForPin(IOPin& pin, + Edge edge, + odb::Point& point, std::vector restrictions); bool checkInterval(Constraint constraint, Edge edge, int pos); diff --git a/src/ioPlacer/src/Parameters.h b/src/ioPlacer/src/Parameters.h index a256cc53ced..d7ef66dac1a 100644 --- a/src/ioPlacer/src/Parameters.h +++ b/src/ioPlacer/src/Parameters.h @@ -77,7 +77,10 @@ class Parameters horizontal_length_extend_ = length; } float getHorizontalLengthExtend() const { return horizontal_length_extend_; } - void setVerticalLengthExtend(float length) { vertical_length_extend_ = length; } + void setVerticalLengthExtend(float length) + { + vertical_length_extend_ = length; + } float getVerticalLengthExtend() const { return vertical_length_extend_; } void setHorizontalLength(float length) { horizontal_length_ = length; } float getHorizontalLength() const { return horizontal_length_; } diff --git a/src/ioPlacer/src/Slots.h b/src/ioPlacer/src/Slots.h index 39eca09cf6f..cbd720a1485 100644 --- a/src/ioPlacer/src/Slots.h +++ b/src/ioPlacer/src/Slots.h @@ -38,9 +38,9 @@ #define MAX_SLOTS_RECOMMENDED 600 #define MAX_SECTIONS_RECOMMENDED 600 +#include #include #include -#include #include "Netlist.h" diff --git a/src/ioPlacer/src/munkres/src/Hungarian.cpp b/src/ioPlacer/src/munkres/src/Hungarian.cpp index c3e3c8b67c4..6cb82c9faa8 100644 --- a/src/ioPlacer/src/munkres/src/Hungarian.cpp +++ b/src/ioPlacer/src/munkres/src/Hungarian.cpp @@ -1,396 +1,502 @@ /////////////////////////////////////////////////////////////////////////////// // Hungarian.cpp: Implementation file for Class HungarianAlgorithm. -// -// This is a C++ wrapper with slight modification of a hungarian algorithm implementation by Markus Buehren. -// The original implementation is a few mex-functions for use in MATLAB, found here: +// +// This is a C++ wrapper with slight modification of a hungarian algorithm +// implementation by Markus Buehren. The original implementation is a few +// mex-functions for use in MATLAB, found here: // http://www.mathworks.com/matlabcentral/fileexchange/6543-functions-for-the-rectangular-assignment-problem -// +// // Both this code and the orignal code are published under the BSD license. // by Cong Ma, 2016 -// +// -#include -#include // for DBL_MAX -#include // for fabs() -#include #include "Hungarian.h" +#include -HungarianAlgorithm::HungarianAlgorithm(){} -HungarianAlgorithm::~HungarianAlgorithm(){} +#include // for DBL_MAX +#include // for fabs() +#include +HungarianAlgorithm::HungarianAlgorithm() +{ +} +HungarianAlgorithm::~HungarianAlgorithm() +{ +} //********************************************************// // A single function wrapper for solving assignment problem. //********************************************************// -int HungarianAlgorithm::solve(vector >& dist_matrix, vector& assignment) +int HungarianAlgorithm::solve(vector >& dist_matrix, + vector& assignment) { - int n_rows = dist_matrix.size(); - int n_cols = dist_matrix[0].size(); - - int *dist_matrix_in = new int[n_rows * n_cols]; - int *tmp_assignment = new int[n_rows]; - int cost = 0.0; - - // Fill in the distMatrixIn. Mind the index is "i + nRows * j". - // Here the cost matrix of size MxN is defined as a int precision array of N*M elements. - // In the solving functions matrices are seen to be saved MATLAB-internally in row-order. - // (i.e. the matrix [1 2; 3 4] will be stored as a vector [1 3 2 4], NOT [1 2 3 4]). - for (int i = 0; i < n_rows; i++) - for (int j = 0; j < n_cols; j++) - dist_matrix_in[i + n_rows * j] = dist_matrix[i][j]; - - // call solving function - assignmentoptimal(tmp_assignment, &cost, dist_matrix_in, n_rows, n_cols); - - assignment.clear(); - for (int r = 0; r < n_rows; r++) - assignment.push_back(tmp_assignment[r]); - - delete[] dist_matrix_in; - delete[] tmp_assignment; - return cost; + int n_rows = dist_matrix.size(); + int n_cols = dist_matrix[0].size(); + + int* dist_matrix_in = new int[n_rows * n_cols]; + int* tmp_assignment = new int[n_rows]; + int cost = 0.0; + + // Fill in the distMatrixIn. Mind the index is "i + nRows * j". + // Here the cost matrix of size MxN is defined as a int precision array of N*M + // elements. In the solving functions matrices are seen to be saved + // MATLAB-internally in row-order. (i.e. the matrix [1 2; 3 4] will be stored + // as a vector [1 3 2 4], NOT [1 2 3 4]). + for (int i = 0; i < n_rows; i++) + for (int j = 0; j < n_cols; j++) + dist_matrix_in[i + n_rows * j] = dist_matrix[i][j]; + + // call solving function + assignmentoptimal(tmp_assignment, &cost, dist_matrix_in, n_rows, n_cols); + + assignment.clear(); + for (int r = 0; r < n_rows; r++) + assignment.push_back(tmp_assignment[r]); + + delete[] dist_matrix_in; + delete[] tmp_assignment; + return cost; } - //********************************************************// -// Solve optimal solution for assignment problem using Munkres algorithm, also known as Hungarian Algorithm. +// Solve optimal solution for assignment problem using Munkres algorithm, also +// known as Hungarian Algorithm. //********************************************************// -void HungarianAlgorithm::assignmentoptimal(int *assignment, int *cost, int *dist_matrix_in, int n_of_rows, int n_of_columns) +void HungarianAlgorithm::assignmentoptimal(int* assignment, + int* cost, + int* dist_matrix_in, + int n_of_rows, + int n_of_columns) { - int *dist_matrix, *dist_matrix_temp, *dist_matrix_end, *column_end, value, min_value; - bool *covered_columns, *covered_rows, *star_matrix, *new_star_matrix, *prime_matrix; - int n_of_elements, min_dim, row, col; - - /* initialization */ - *cost = 0; - for (row = 0; row nOfColumns) */ - { - min_dim = n_of_columns; - - for (col = 0; col nOfColumns) */ + { + min_dim = n_of_columns; + + for (col = 0; col < n_of_columns; col++) { + /* find the smallest element in the column */ + dist_matrix_temp = dist_matrix + n_of_rows * col; + column_end = dist_matrix_temp + n_of_rows; + + min_value = *dist_matrix_temp++; + while (dist_matrix_temp < column_end) { + value = *dist_matrix_temp++; + if (value < min_value) + min_value = value; + } + + /* subtract the smallest element from each element of the column */ + dist_matrix_temp = dist_matrix + n_of_rows * col; + while (dist_matrix_temp < column_end) + *dist_matrix_temp++ -= min_value; + } + + /* Steps 1 and 2a */ + for (col = 0; col < n_of_columns; col++) + for (row = 0; row < n_of_rows; row++) + if (fabs(dist_matrix[row + n_of_rows * col]) < DBL_EPSILON) + if (!covered_rows[row]) { + star_matrix[row + n_of_rows * col] = true; + covered_columns[col] = true; + covered_rows[row] = true; + break; + } + for (row = 0; row < n_of_rows; row++) + covered_rows[row] = false; + } + + /* move to step 2b */ + step2b(assignment, + dist_matrix, + star_matrix, + new_star_matrix, + prime_matrix, + covered_columns, + covered_rows, + n_of_rows, + n_of_columns, + min_dim); + + /* compute cost and remove invalid assignments */ + computeassignmentcost(assignment, cost, dist_matrix_in, n_of_rows); + + /* free allocated memory */ + free(dist_matrix); + free(covered_columns); + free(covered_rows); + free(star_matrix); + free(prime_matrix); + free(new_star_matrix); + + return; } /********************************************************/ -void HungarianAlgorithm::buildassignmentvector(int *assignment, bool *star_matrix, int n_of_rows, int n_of_columns) +void HungarianAlgorithm::buildassignmentvector(int* assignment, + bool* star_matrix, + int n_of_rows, + int n_of_columns) { - int row, col; + int row, col; - for (row = 0; row= 0) - *cost += dist_matrix[row + n_of_rows*col]; - } + int row, col; + + for (row = 0; row < n_of_rows; row++) { + col = assignment[row]; + if (col >= 0) + *cost += dist_matrix[row + n_of_rows * col]; + } } /********************************************************/ -void HungarianAlgorithm::step2a(int *assignment, int *dist_matrix, bool *star_matrix, bool *new_star_matrix, bool *prime_matrix, bool *covered_columns, bool *covered_rows, int n_of_rows, int n_of_columns, int min_dim) +void HungarianAlgorithm::step2a(int* assignment, + int* dist_matrix, + bool* star_matrix, + bool* new_star_matrix, + bool* prime_matrix, + bool* covered_columns, + bool* covered_rows, + int n_of_rows, + int n_of_columns, + int min_dim) { - bool *star_matrix_temp, *column_end; - int col; - - /* cover every column containing a starred zero */ - for (col = 0; col::max(); - for (row = 0; row::max(); + for (row = 0; row < n_of_rows; row++) + if (!covered_rows[row]) + for (col = 0; col < n_of_columns; col++) + if (!covered_columns[col]) { + value = dist_matrix[row + n_of_rows * col]; + if (value < h) + h = value; + } + + /* add h to each covered row */ + for (row = 0; row < n_of_rows; row++) + if (covered_rows[row]) + for (col = 0; col < n_of_columns; col++) + dist_matrix[row + n_of_rows * col] += h; + + /* subtract h from each uncovered column */ + for (col = 0; col < n_of_columns; col++) + if (!covered_columns[col]) + for (row = 0; row < n_of_rows; row++) + dist_matrix[row + n_of_rows * col] -= h; + + /* move to step 3 */ + step3(assignment, + dist_matrix, + star_matrix, + new_star_matrix, + prime_matrix, + covered_columns, + covered_rows, + n_of_rows, + n_of_columns, + min_dim); } diff --git a/src/ioPlacer/src/munkres/src/Hungarian.h b/src/ioPlacer/src/munkres/src/Hungarian.h index b23941986ff..968db8c1cf0 100644 --- a/src/ioPlacer/src/munkres/src/Hungarian.h +++ b/src/ioPlacer/src/munkres/src/Hungarian.h @@ -1,13 +1,14 @@ /////////////////////////////////////////////////////////////////////////////// // Hungarian.h: Header file for Class HungarianAlgorithm. -// -// This is a C++ wrapper with slight modification of a hungarian algorithm implementation by Markus Buehren. -// The original implementation is a few mex-functions for use in MATLAB, found here: +// +// This is a C++ wrapper with slight modification of a hungarian algorithm +// implementation by Markus Buehren. The original implementation is a few +// mex-functions for use in MATLAB, found here: // http://www.mathworks.com/matlabcentral/fileexchange/6543-functions-for-the-rectangular-assignment-problem -// +// // Both this code and the orignal code are published under the BSD license. // by Cong Ma, 2016 -// +// #pragma once @@ -16,21 +17,77 @@ using namespace std; - class HungarianAlgorithm { -public: - HungarianAlgorithm(); - ~HungarianAlgorithm(); - int solve(vector >& dist_matrix, vector& assignment); + public: + HungarianAlgorithm(); + ~HungarianAlgorithm(); + int solve(vector >& dist_matrix, vector& assignment); -private: - void assignmentoptimal(int *assignment, int *cost, int *dist_matrix, int n_of_rows, int n_of_columns); - void buildassignmentvector(int *assignment, bool *star_matrix, int n_of_rows, int n_of_columns); - void computeassignmentcost(int *assignment, int *cost, int *dist_matrix, int n_of_rows); - void step2a(int *assignment, int *dist_matrix, bool *star_matrix, bool *new_star_matrix, bool *prime_matrix, bool *covered_columns, bool *covered_rows, int n_of_rows, int n_of_columns, int min_dim); - void step2b(int *assignment, int *dist_matrix, bool *star_matrix, bool *new_star_matrix, bool *prime_matrix, bool *covered_columns, bool *covered_rows, int n_of_rows, int n_of_columns, int min_dim); - void step3(int *assignment, int *dist_matrix, bool *star_matrix, bool *new_star_matrix, bool *prime_matrix, bool *covered_columns, bool *covered_rows, int n_of_rows, int n_of_columns, int min_dim); - void step4(int *assignment, int *dist_matrix, bool *star_matrix, bool *new_star_matrix, bool *prime_matrix, bool *covered_columns, bool *covered_rows, int n_of_rows, int n_of_columns, int min_dim, int row, int col); - void step5(int *assignment, int *dist_matrix, bool *star_matrix, bool *new_star_matrix, bool *prime_matrix, bool *covered_columns, bool *covered_rows, int n_of_rows, int n_of_columns, int min_dim); + private: + void assignmentoptimal(int* assignment, + int* cost, + int* dist_matrix, + int n_of_rows, + int n_of_columns); + void buildassignmentvector(int* assignment, + bool* star_matrix, + int n_of_rows, + int n_of_columns); + void computeassignmentcost(int* assignment, + int* cost, + int* dist_matrix, + int n_of_rows); + void step2a(int* assignment, + int* dist_matrix, + bool* star_matrix, + bool* new_star_matrix, + bool* prime_matrix, + bool* covered_columns, + bool* covered_rows, + int n_of_rows, + int n_of_columns, + int min_dim); + void step2b(int* assignment, + int* dist_matrix, + bool* star_matrix, + bool* new_star_matrix, + bool* prime_matrix, + bool* covered_columns, + bool* covered_rows, + int n_of_rows, + int n_of_columns, + int min_dim); + void step3(int* assignment, + int* dist_matrix, + bool* star_matrix, + bool* new_star_matrix, + bool* prime_matrix, + bool* covered_columns, + bool* covered_rows, + int n_of_rows, + int n_of_columns, + int min_dim); + void step4(int* assignment, + int* dist_matrix, + bool* star_matrix, + bool* new_star_matrix, + bool* prime_matrix, + bool* covered_columns, + bool* covered_rows, + int n_of_rows, + int n_of_columns, + int min_dim, + int row, + int col); + void step5(int* assignment, + int* dist_matrix, + bool* star_matrix, + bool* new_star_matrix, + bool* prime_matrix, + bool* covered_columns, + bool* covered_rows, + int n_of_rows, + int n_of_columns, + int min_dim); };