Skip to content

Commit

Permalink
make RoutingVertex handle blocking states, permanent/temporary, like …
Browse files Browse the repository at this point in the history
…RoutingEdge does
  • Loading branch information
growly committed Nov 15, 2024
1 parent 859f423 commit 25487da
Show file tree
Hide file tree
Showing 6 changed files with 161 additions and 99 deletions.
36 changes: 21 additions & 15 deletions src/routing_grid.cc
Original file line number Diff line number Diff line change
Expand Up @@ -233,15 +233,15 @@ void RoutingGrid::ApplyBlockage(
// We use the RoutingGridBlockage to do a hit test; set
// exceptional_nets = nullopt so that no exception is made.
if (blockage.IntersectsPoint(vertex->centre(), 0)) {
vertex->AddUsingNet(blockage.shape().net());
vertex->AddUsingNet(blockage.shape().net(), is_temporary);
VLOG(16) << "Blockage: " << blockage.shape()
<< " intersects " << vertex->centre()
<< " with margin " << 0
<< direction << " direction";
} else if (blockage.Blocks(*vertex, std::nullopt, direction)) {
blocked_at_all = true;
if (net != "") {
vertex->AddBlockingNet(net);
vertex->AddBlockingNet(net, is_temporary);
}
VLOG(16) << "Blockage: " << blockage.shape()
<< " blocks " << vertex->centre()
Expand All @@ -252,7 +252,7 @@ void RoutingGrid::ApplyBlockage(
}

if (!any_access) {
vertex->SetTotallyBlocked(false);
vertex->SetForcedBlocked(true, is_temporary);
if (blocked_vertices) {
blocked_vertices->insert(vertex);
}
Expand All @@ -263,7 +263,7 @@ void RoutingGrid::ApplyBlockage(
// shapes on nets that are temporary blockages? Practically this includes
// via footprints for ports!
if (!is_temporary && !blockage.shape().net().empty()) {
AddOffGridVerticesForBlockage(*grid_geometry, blockage);
AddOffGridVerticesForBlockage(*grid_geometry, blockage, false);
}
}
}
Expand Down Expand Up @@ -303,7 +303,8 @@ void RoutingGrid::ForgetBlockage(
template<typename T>
void RoutingGrid::AddOffGridVerticesForBlockage(
const RoutingGridGeometry &grid_geometry,
const RoutingGridBlockage<T> &blockage) {
const RoutingGridBlockage<T> &blockage,
bool is_temporary) {
auto tracks_and_positions =
grid_geometry.CandidateVertexPositionsOnCrossedTracks(
blockage.shape());
Expand All @@ -323,7 +324,7 @@ void RoutingGrid::AddOffGridVerticesForBlockage(
if (!new_vertex) {
continue;
}
new_vertex->AddBlockingNet(blockage.shape().net());
new_vertex->AddBlockingNet(blockage.shape().net(), is_temporary);
new_vertex->set_explicit_net_layer(blockage.shape().layer());
// TODO(aryap): This actually requires a test on the blockage shape
// accommodating the encap rules as-is, which we could do, but which would
Expand Down Expand Up @@ -1809,6 +1810,11 @@ absl::StatusOr<RoutingPath*> RoutingGrid::FindRouteBetween(
// return true;
//};
TemporaryBlockageInfo temporary_blockages;

// FIXME: short term: copy how RoutingEdge manages temporary OR permanent
// blockages
// FIXME: medium+ term: implement secondary structure to track temporary
// blockages (this will enable multithreading too)
SetUpTemporaryBlockages(avoid, &temporary_blockages);

absl::Cleanup tear_down_temporary_blockages = [&]() {
Expand Down Expand Up @@ -1959,7 +1965,7 @@ absl::StatusOr<RoutingPath*> RoutingGrid::FindRouteToNet(
shortest_path->end_access_layers().insert(
end_layers.begin(), end_layers.end());

if (shortest_path->End()->in_use_by_net() &&
if (shortest_path->End()->InUseBySingleNet() &&
shortest_path->End()->explicit_net_layer()) {
shortest_path->end_access_layers().insert(
*shortest_path->End()->explicit_net_layer());
Expand Down Expand Up @@ -2055,7 +2061,7 @@ void RoutingGrid::InstallVertexInPath(
for (const auto &position : kDisabledNeighbours) {
std::set<RoutingVertex*> neighbours = vertex->GetNeighbours(position);
for (RoutingVertex *neighbour : neighbours) {
neighbour->AddBlockingNet(net);
neighbour->AddBlockingNet(net, true); // Permanent.
}
};
return;
Expand Down Expand Up @@ -2109,7 +2115,7 @@ void RoutingGrid::InstallVertexInPath(

std::set<RoutingTrack*> blocked_tracks;
for (RoutingVertex *enveloping_vertex : inner_vertices) {
enveloping_vertex->AddBlockingNet(net);
enveloping_vertex->AddBlockingNet(net, true); // Permanent.
// We also have to add blockages to the tracks on which these vertices
// appear, since by being off-grid we're _presumably_ too close to
// accomodate both a via and an edge next to each other.
Expand Down Expand Up @@ -2180,7 +2186,7 @@ void RoutingGrid::InstallVertexInPath(
// << " is too close (" << min_distance << " < "
// << min_separation << ") to "
// << *via_encap << " at " << vertex->centre();
enveloping_vertex->AddBlockingNet(net);
enveloping_vertex->AddBlockingNet(net, true); // Permanent.
}
}
}
Expand Down Expand Up @@ -2233,14 +2239,14 @@ absl::Status RoutingGrid::InstallPath(RoutingPath *path) {

size_t i = 0;
RoutingEdge *edge = nullptr;
path->vertices()[0]->AddUsingNet(net);
path->vertices()[0]->AddUsingNet(net, true); // Permanent.
while (i < path->edges().size()) {
RoutingVertex *last_vertex = path->vertices()[i];
RoutingVertex *next_vertex = path->vertices()[i + 1];
RoutingEdge *edge = path->edges()[i];
last_vertex->set_out_edge(edge);
next_vertex->set_in_edge(edge);
next_vertex->AddUsingNet(net);
next_vertex->AddUsingNet(net, true); // Permanent.
++i;
}

Expand Down Expand Up @@ -2270,7 +2276,7 @@ absl::StatusOr<RoutingPath*> RoutingGrid::ShortestPath(
auto path = ShortestPath(
begin,
[&](RoutingVertex *v) {
if (!v->in_use_by_net()) {
if (!v->InUseBySingleNet()) {
return false;
}
// Check that putting a via at this position doesn't conflict with vias
Expand All @@ -2288,7 +2294,7 @@ absl::StatusOr<RoutingPath*> RoutingGrid::ShortestPath(
return false;
}
}
return to_nets.Contains(*v->in_use_by_net());
return to_nets.Contains(*v->InUseBySingleNet());
},
discovered_target,
// Usable vertices are:
Expand Down Expand Up @@ -2998,7 +3004,7 @@ void RoutingGrid::SetUpTemporaryBlockages(
void RoutingGrid::TearDownTemporaryBlockages(
const TemporaryBlockageInfo &blockage_info) {
for (RoutingVertex *const vertex : blockage_info.blocked_vertices) {
vertex->SetTotallyBlocked(false);
vertex->ResetTemporaryStatus();
}
for (RoutingEdge *const edge : blockage_info.blocked_edges) {
// This should clear any used nets and unblock the edge.
Expand Down
3 changes: 2 additions & 1 deletion src/routing_grid.h
Original file line number Diff line number Diff line change
Expand Up @@ -420,7 +420,8 @@ class RoutingGrid {
template<typename T>
void AddOffGridVerticesForBlockage(
const RoutingGridGeometry &grid_geometry,
const RoutingGridBlockage<T> &blockage);
const RoutingGridBlockage<T> &blockage,
bool is_temporary);

absl::StatusOr<RoutingPath*> FindRouteBetween(
const geometry::Port &begin,
Expand Down
6 changes: 3 additions & 3 deletions src/routing_grid_geometry_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -540,13 +540,13 @@ TEST_F(RoutingGridGeometryTestFixture,
RoutingVertex *vertex = new RoutingVertex({i, j});
grid_geometry_.AssignVertexAt(i, j, vertex);
if (j > 0 && i == 3) {
vertex->SetTotallyBlocked(true);
vertex->SetForcedBlocked(true, true); // Permanent.
}
if (j == 1 && i == 5) {
vertex->SetTotallyBlocked(true);
vertex->SetForcedBlocked(true, true);
}
if (j == 2 && i == 4) {
vertex->SetTotallyBlocked(true);
vertex->SetForcedBlocked(true, true);
}
all_vertices.insert(vertex);
}
Expand Down
6 changes: 3 additions & 3 deletions src/routing_track.cc
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ void RoutingTrack::MarkEdgeAsUsed(RoutingEdge *edge, const std::string &net) {
if (EdgeSpansVertex(*edge, *vertex)) {
vertex->set_in_edge(edge);
vertex->set_out_edge(edge);
vertex->AddUsingNet(net);
vertex->AddUsingNet(net, true); // Permanent.
}
}
}
Expand Down Expand Up @@ -1181,9 +1181,9 @@ void RoutingTrack::ApplyVertexBlockage(
if (net != "") {
// TODO(aryap): Put these on temporary mutation plane so that they can
// be undone.
vertex->AddBlockingNet(net);
vertex->AddBlockingNet(net, is_temporary);
} else {
vertex->SetTotallyBlocked(true);
vertex->SetForcedBlocked(true, is_temporary);
}
if (blocked_vertices)
blocked_vertices->insert(vertex);
Expand Down
112 changes: 94 additions & 18 deletions src/routing_vertex.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "routing_vertex.h"

#include "equivalent_nets.h"
#include "geometry/compass.h"
#include "geometry/layer.h"
#include "geometry/point.h"
Expand All @@ -23,24 +24,95 @@ bool RoutingVertex::Compare(RoutingVertex *lhs, RoutingVertex *rhs) {
return Compare(*lhs, *rhs);
}

void RoutingVertex::AddUsingNet(const std::string &net) {
totally_available_ = false;
if (!in_use_by_net_) {
in_use_by_net_ = net;
} else {
in_use_by_net_ = std::nullopt;
totally_blocked_ = true;
void RoutingVertex::UpdateCachedStatus() {
totally_available_ = !forced_blocked_ && !temporarily_forced_blocked_ &&
in_use_by_nets_.empty() &&
blocked_by_nearby_nets_.empty();
}

// This mutates blocking state and should call UpdateCachedStatus().
void RoutingVertex::AddUsingNet(const std::string &net, bool temporary) {
auto it = in_use_by_nets_.find(net);
if (it == in_use_by_nets_.end()) {
in_use_by_nets_[net] = temporary;
return;
}
// If the blockage was previously temporary but is now not, override it as permanent.
// We trade one check of the existing value for what might be an unnecessary write.
if (!temporary) {
it->second = temporary;
}
UpdateCachedStatus();
}

// This mutates blocking state and should call UpdateCachedStatus().
void RoutingVertex::AddBlockingNet(const std::string &net, bool temporary) {
auto it = blocked_by_nearby_nets_.find(net);
if (it == blocked_by_nearby_nets_.end()) {
blocked_by_nearby_nets_[net] = temporary;
return;
}
// If the blockage was previously temporary but is now not, override it as permanent.
// We trade one check of the existing value for what might be an unnecessary write.
if (!temporary) {
it->second = temporary;
}
UpdateCachedStatus();
}

// This mutates blocking state and should call UpdateCachedStatus().
void RoutingVertex::SetForcedBlocked(bool blocked, bool temporary) {
bool &forced_blocked =
temporary ? temporarily_forced_blocked_ : forced_blocked_;
forced_blocked = blocked;
UpdateCachedStatus();
}

// This mutates blocking state and should call UpdateCachedStatus().
void RoutingVertex::ResetTemporaryStatus() {
temporarily_forced_blocked_ = false;

auto remove_temporaries_fn = [](std::map<std::string, bool> *container) {
for (auto it = container->begin(); it != container->end();) {
if (it->second) {
it = container->erase(it);
continue;
}
++it;
}
};
remove_temporaries_fn(&in_use_by_nets_);
remove_temporaries_fn(&blocked_by_nearby_nets_);

UpdateCachedStatus();
}

std::optional<std::string> RoutingVertex::InUseBySingleNet() const {
if (in_use_by_nets_.size() != 1) {
return std::nullopt;
}
return in_use_by_nets_.begin()->first;
}

void RoutingVertex::AddBlockingNet(const std::string &net) {
totally_available_ = false;
if (!blocked_by_nearby_net_) {
blocked_by_nearby_net_ = net;
} else {
blocked_by_nearby_net_ = std::nullopt;
totally_blocked_ = true;
std::optional<std::string> RoutingVertex::BlockedBySingleNearbyNet() const {
if (blocked_by_nearby_nets_.size() != 1) {
return std::nullopt;
}
return blocked_by_nearby_nets_.begin()->first;
}

bool RoutingVertex::AvailableForNets(const EquivalentNets &nets) const {
if (Available()) {
return true;
}
std::optional<std::string> in_use_by_net = InUseBySingleNet();
std::optional<std::string> blocked_by_nearby_net = BlockedBySingleNearbyNet();
if (in_use_by_net && blocked_by_nearby_net &&
*in_use_by_net != *blocked_by_nearby_net) {
return false;
}
return (in_use_by_net && nets.Contains(*in_use_by_net)) ||
(blocked_by_nearby_net && nets.Contains(*blocked_by_nearby_net));
}

std::optional<geometry::Layer> RoutingVertex::ConnectedLayerOtherThan(
Expand Down Expand Up @@ -155,11 +227,15 @@ std::vector<RoutingTrack*> RoutingVertex::TracksInDirection(
std::ostream &operator<<(std::ostream &os, const RoutingVertex &vertex) {
os << vertex.centre();
os << (vertex.Available() ? " available" : " not_available");
if (vertex.in_use_by_net()) {
os << " in_use_by_net:\"" << *vertex.in_use_by_net() << "\"";

std::optional<std::string> in_use_by_net = vertex.InUseBySingleNet();
if (in_use_by_net) {
os << " in_use_by_net:\"" << *in_use_by_net << "\"";
}
if (vertex.blocked_by_nearby_net()) {
os << " blocked_by_nearby_net:\"" << *vertex.blocked_by_nearby_net()
std::optional<std::string> blocked_by_nearby_net =
vertex.BlockedBySingleNearbyNet();
if (blocked_by_nearby_net) {
os << " blocked_by_nearby_net:\"" << *blocked_by_nearby_net
<< "\"";
}
return os;
Expand Down
Loading

0 comments on commit 25487da

Please sign in to comment.