Skip to content

Commit

Permalink
Merge pull request The-OpenROAD-Project#2722 from eder-matheus/ppl_mi…
Browse files Browse the repository at this point in the history
…rrored_pins

ppl: add option to mirror pairs of pins
  • Loading branch information
eder-matheus authored Jan 9, 2023
2 parents 44fb309 + 62308c2 commit 8781b94
Show file tree
Hide file tree
Showing 16 changed files with 676 additions and 62 deletions.
7 changes: 7 additions & 0 deletions src/ppl/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,13 @@ The `-direction` argument is the pin direction (input, output, inout, or
feedthrough). The `-pin_names` argument is a list of names. The `-region`
syntax is the same as that of the `-exclude` syntax.

The `-mirrored_pins` argument is a list of pins that sets pairs of pins
that will be symmetrically placed in the vertical or the horizontal edges.
The number of pins in this list must be even. For example, in
`set_io_pin_constraint -mirrored_pins {pin1 pin2 pin3 pin4 pin5 pin6}`,
the pins `pin1` and `pin2` will be placed symmetrically to each other.
Same for `pin3` and `pin4`, and for `pin5` and `pin6`.

Note that if you call `define_pin_shape_pattern` before
`set_io_pin_constraint`, the `edge` values are (up, top,
bottom, left, right). Where `up` relates to the layer created by
Expand Down
7 changes: 6 additions & 1 deletion src/ppl/include/ppl/IOPlacer.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@

#include <memory>
#include <set>
#include <unordered_map>
#include <vector>

#include "odb/geom.h"
Expand Down Expand Up @@ -72,6 +73,7 @@ using utl::Logger;
// A list of pins that will be placed together in the die boundary
typedef std::set<odb::dbBTerm*> PinList;
typedef std::vector<odb::dbBTerm*> PinGroup;
typedef std::unordered_map<odb::dbBTerm*, odb::dbBTerm*> MirroredPins;

enum class Edge
{
Expand Down Expand Up @@ -110,6 +112,7 @@ class IOPlacer
int begin,
int end);
void addTopLayerConstraint(PinList* pins, const odb::Rect& region);
void addMirroredPins(odb::dbBTerm* bterm1, odb::dbBTerm* bterm2);
void addHorLayer(odb::dbTechLayer* layer);
void addVerLayer(odb::dbTechLayer* layer);
void addPinGroup(PinGroup* group);
Expand Down Expand Up @@ -171,7 +174,8 @@ class IOPlacer
std::vector<Section>& sections);
int assignGroupToSection(const std::vector<int>& io_group,
std::vector<Section>& sections);
std::vector<Section> assignConstrainedPinsToSections(Constraint& constraint);
std::vector<Section> assignConstrainedPinsToSections(Constraint& constraint,
int& mirrored_pins_cnt);
std::vector<int> findPinsForConstraint(const Constraint& constraint,
Netlist* netlist);
int computeIONetsHPWL(Netlist* netlist);
Expand Down Expand Up @@ -215,6 +219,7 @@ class IOPlacer
std::vector<Interval> excluded_intervals_;
std::vector<Constraint> constraints_;
std::vector<PinGroup> pin_groups_;
MirroredPins mirrored_pins_;

Logger* logger_;
std::unique_ptr<Parameters> parms_;
Expand Down
21 changes: 21 additions & 0 deletions src/ppl/src/Core.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,4 +52,25 @@ int Core::getPerimeter() const
return (x + y) * 2;
}

odb::Point Core::getMirroredPosition(const odb::Point& position) const
{
odb::Point mirrored_pos = position;
const int x_min = boundary_.xMin();
const int x_max = boundary_.xMax();
const int y_min = boundary_.yMin();
const int y_max = boundary_.yMax();

if (position.x() == x_min) {
mirrored_pos.setX(x_max);
} else if (position.x() == x_max) {
mirrored_pos.setX(x_min);
} else if (position.y() == y_min) {
mirrored_pos.setY(y_max);
} else {
mirrored_pos.setY(y_min);
}

return mirrored_pos;
}

} // namespace ppl
1 change: 1 addition & 0 deletions src/ppl/src/Core.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ class Core
std::vector<int> getMinWidthY() const { return min_width_y_; }
int getDatabaseUnit() const { return database_unit_; }
int getPerimeter() const;
odb::Point getMirroredPosition(const odb::Point& position) const;

private:
Rect boundary_;
Expand Down
43 changes: 42 additions & 1 deletion src/ppl/src/HungarianMatching.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,11 @@ namespace ppl {

HungarianMatching::HungarianMatching(Section& section,
Netlist* netlist,
Core* core,
std::vector<Slot>& slots,
Logger* logger)
: netlist_(netlist),
core_(core),
pin_indices_(section.pin_indices),
pin_groups_(section.pin_groups),
slots_(slots)
Expand Down Expand Up @@ -96,13 +98,16 @@ inline bool samePos(Point& a, Point& b)
return (a.x() == b.x() && a.y() == b.y());
}

void HungarianMatching::getFinalAssignment(std::vector<IOPin>& assigment) const
void HungarianMatching::getFinalAssignment(std::vector<IOPin>& assigment,
MirroredPins& mirrored_pins,
bool assign_mirrored) const
{
size_t rows = non_blocked_slots_;
size_t col = 0;
int slot_index = 0;
for (int idx : pin_indices_) {
IOPin& io_pin = netlist_->getIoPin(idx);

if (!io_pin.isInGroup()) {
slot_index = begin_slot_;
for (size_t row = 0; row < rows; row++) {
Expand All @@ -119,10 +124,33 @@ void HungarianMatching::getFinalAssignment(std::vector<IOPin>& assigment) const
"Not enough space.",
io_pin.getName().c_str());
}

// Make this check here to avoid messing up the correlation between the
// pin sorting and the hungarian matrix values
if ((assign_mirrored
&& mirrored_pins.find(io_pin.getBTerm()) == mirrored_pins.end())
|| io_pin.isPlaced()) {
continue;
}
io_pin.setPos(slots_[slot_index].pos);
io_pin.setLayer(slots_[slot_index].layer);
io_pin.setPlaced();
assigment.push_back(io_pin);
slots_[slot_index].used = true;

if (assign_mirrored) {
odb::dbBTerm* mirrored_term = mirrored_pins[io_pin.getBTerm()];
int mirrored_pin_idx = netlist_->getIoPinIdx(mirrored_term);
IOPin& mirrored_pin = netlist_->getIoPin(mirrored_pin_idx);

odb::Point mirrored_pos = core_->getMirroredPosition(io_pin.getPos());
mirrored_pin.setPos(mirrored_pos);
mirrored_pin.setLayer(slots_[slot_index].layer);
mirrored_pin.setPlaced();
assigment.push_back(mirrored_pin);
slot_index = getSlotIdxByPosition(mirrored_pos);
slots_[slot_index].used = true;
}
break;
}
col++;
Expand Down Expand Up @@ -238,4 +266,17 @@ void HungarianMatching::getAssignmentForGroups(std::vector<IOPin>& assigment)
assignment_.clear();
}

int HungarianMatching::getSlotIdxByPosition(const odb::Point& position) const
{
int slot_idx = -1;
for (int i = 0; i < slots_.size(); i++) {
if (slots_[i].pos == position) {
slot_idx = i;
break;
}
}

return slot_idx;
}

} // namespace ppl
8 changes: 7 additions & 1 deletion src/ppl/src/HungarianMatching.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
#include <list>
#include <utility>

#include "Core.h"
#include "Hungarian.h"
#include "Netlist.h"
#include "Slots.h"
Expand All @@ -62,19 +63,23 @@ class HungarianMatching
public:
HungarianMatching(Section& section,
Netlist* netlist,
Core* core,
std::vector<Slot>& slots,
Logger* logger);
virtual ~HungarianMatching() = default;
void findAssignment();
void findAssignmentForGroups();
void getFinalAssignment(std::vector<IOPin>& assigment) const;
void getFinalAssignment(std::vector<IOPin>& assigment,
MirroredPins& mirrored_pins,
bool assign_mirrored) const;
void getAssignmentForGroups(std::vector<IOPin>& assigment);

private:
std::vector<std::vector<int>> hungarian_matrix_;
std::vector<int> assignment_;
HungarianAlgorithm hungarian_solver_;
Netlist* netlist_;
Core* core_;
const std::vector<int>& pin_indices_;
const std::vector<std::vector<int>>& pin_groups_;
std::vector<Slot>& slots_;
Expand All @@ -92,6 +97,7 @@ class HungarianMatching

void createMatrix();
void createMatrixForGroups();
int getSlotIdxByPosition(const odb::Point& position) const;
};

} // namespace ppl
59 changes: 51 additions & 8 deletions src/ppl/src/IOPlacer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -603,7 +603,8 @@ void IOPlacer::createSections()
}

std::vector<Section> IOPlacer::assignConstrainedPinsToSections(
Constraint& constraint)
Constraint& constraint,
int& mirrored_pins_cnt)
{
bool top_layer = constraint.interval.getEdge() == Edge::invalid;
std::vector<Slot>& slots = top_layer ? top_layer_slots_ : slots_;
Expand Down Expand Up @@ -634,6 +635,9 @@ std::vector<Section> IOPlacer::assignConstrainedPinsToSections(

for (int idx : pin_indices) {
IOPin& io_pin = netlist_io_pins_->getIoPin(idx);
if (mirrored_pins_.find(io_pin.getBTerm()) != mirrored_pins_.end()) {
mirrored_pins_cnt++;
}
assignPinToSection(io_pin, idx, constraint.sections);
}

Expand Down Expand Up @@ -729,7 +733,19 @@ bool IOPlacer::assignPinsToSections(int assigned_pins_count)

int total_pins_assigned = assignGroupsToSections();

// Mirrored pins first
int idx = 0;
for (IOPin& io_pin : net->getIOPins()) {
if (mirrored_pins_.find(io_pin.getBTerm()) != mirrored_pins_.end()) {
if (assignPinToSection(io_pin, idx, sections)) {
total_pins_assigned += 2;
}
}
idx++;
}

// Remaining pins
idx = 0;
for (IOPin& io_pin : net->getIOPins()) {
if (assignPinToSection(io_pin, idx, sections)) {
total_pins_assigned++;
Expand Down Expand Up @@ -769,6 +785,15 @@ bool IOPlacer::assignPinToSection(IOPin& io_pin,
sections[i].used_slots++;
pin_assigned = true;
io_pin.assignToSection();

if (mirrored_pins_.find(io_pin.getBTerm()) != mirrored_pins_.end()) {
odb::dbBTerm* mirrored_term = mirrored_pins_[io_pin.getBTerm()];
int mirrored_pin_idx = netlist_io_pins_->getIoPinIdx(mirrored_term);
IOPin& mirrored_pin = netlist_io_pins_->getIoPin(mirrored_pin_idx);
// Mark mirrored pin as assigned to section to prevent assigning it to
// another section that is not aligned with his pair
mirrored_pin.assignToSection();
}
break;
}
}
Expand Down Expand Up @@ -1038,6 +1063,11 @@ void IOPlacer::addTopLayerConstraint(PinList* pins, const odb::Rect& region)
constraints_.push_back(constraint);
}

void IOPlacer::addMirroredPins(odb::dbBTerm* bterm1, odb::dbBTerm* bterm2)
{
mirrored_pins_[bterm1] = bterm2;
}

void IOPlacer::addHorLayer(odb::dbTechLayer* layer)
{
hor_layers_.insert(layer->getRoutingLevel());
Expand Down Expand Up @@ -1175,12 +1205,18 @@ void IOPlacer::findPinAssignment(std::vector<Section>& sections)
for (int idx = 0; idx < sections.size(); idx++) {
if (sections[idx].pin_indices.size() > 0) {
if (sections[idx].edge == Edge::invalid) {
HungarianMatching hg(
sections[idx], netlist_io_pins_.get(), top_layer_slots_, logger_);
HungarianMatching hg(sections[idx],
netlist_io_pins_.get(),
core_.get(),
top_layer_slots_,
logger_);
hg_vec.push_back(hg);
} else {
HungarianMatching hg(
sections[idx], netlist_io_pins_.get(), slots_, logger_);
HungarianMatching hg(sections[idx],
netlist_io_pins_.get(),
core_.get(),
slots_,
logger_);
hg_vec.push_back(hg);
}
}
Expand All @@ -1198,8 +1234,14 @@ void IOPlacer::findPinAssignment(std::vector<Section>& sections)
hg_vec[idx].findAssignment();
}

if (!mirrored_pins_.empty()) {
for (int idx = 0; idx < hg_vec.size(); idx++) {
hg_vec[idx].getFinalAssignment(assignment_, mirrored_pins_, true);
}
}

for (int idx = 0; idx < hg_vec.size(); idx++) {
hg_vec[idx].getFinalAssignment(assignment_);
hg_vec[idx].getFinalAssignment(assignment_, mirrored_pins_, false);
}
}

Expand Down Expand Up @@ -1231,10 +1273,11 @@ void IOPlacer::run(bool random_mode)
} else {
int constrained_pins_cnt = 0;
for (Constraint& constraint : constraints_) {
int mirrored_pins_cnt = 0;
std::vector<Section> sections_for_constraint
= assignConstrainedPinsToSections(constraint);
= assignConstrainedPinsToSections(constraint, mirrored_pins_cnt);
for (Section& sec : sections_for_constraint) {
constrained_pins_cnt += sec.pin_indices.size();
constrained_pins_cnt += sec.pin_indices.size() + mirrored_pins_cnt;
}

findPinAssignment(sections_for_constraint);
Expand Down
6 changes: 6 additions & 0 deletions src/ppl/src/IOPlacer.i
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,12 @@ add_top_layer_constraint(PinList *pin_list,
getIOPlacer()->addTopLayerConstraint(pin_list, odb::Rect(x1, y1, x2, y2));
}

void
add_mirrored_pins(odb::dbBTerm* bterm1, odb::dbBTerm* bterm2)
{
getIOPlacer()->addMirroredPins(bterm1, bterm2);
}

void
set_hor_length(int length)
{
Expand Down
Loading

0 comments on commit 8781b94

Please sign in to comment.