44#include " RDLRoute.h"
55
66#include < algorithm>
7+ #include < array>
78#include < map>
89#include < memory>
10+ #include < set>
911#include < tuple>
1012#include < vector>
1113
1214#include " boost/geometry/geometry.hpp"
15+ #include " boost/polygon/polygon_90_set_data.hpp"
16+ #include " boost/polygon/polygon_90_with_holes_data.hpp"
17+ #include " boost/polygon/rectangle_concept.hpp"
18+ #include " boost/polygon/rectangle_data.hpp"
1319#include " odb/db.h"
1420#include " odb/geom.h"
1521#include " odb/geom_boost.h"
@@ -18,7 +24,12 @@ namespace pad {
1824
1925RDLRoute::RDLRoute (odb::dbITerm* source,
2026 const std::vector<odb::dbITerm*>& dests)
21- : iterm_(source), priority_(0 ), terminals_(dests)
27+ : iterm_(source),
28+ priority_ (0 ),
29+ route_pending_(false ),
30+ locked_(false ),
31+ routed_(false ),
32+ terminals_(dests)
2233{
2334 terminals_.erase (std::remove_if (terminals_.begin (),
2435 terminals_.end (),
@@ -117,10 +128,18 @@ void RDLRoute::setRoute(
117128 route_edges_.push_back (edge);
118129 }
119130 }
131+
132+ routed_ = true ;
120133}
121134
122135void RDLRoute::resetRoute ()
123136{
137+ if (locked_) {
138+ return ;
139+ }
140+
141+ routed_ = false ;
142+
124143 route_vertex_.clear ();
125144 route_pts_.clear ();
126145 route_edges_.clear ();
@@ -214,4 +233,115 @@ bool RDLRoute::contains(const odb::Point& pt) const
214233 != route_pts_.end ();
215234}
216235
236+ void RDLRoute::preprocess (odb::dbTechLayer* layer, utl::Logger* logger)
237+ {
238+ using boost::polygon::operators::operator +=;
239+ using boost::polygon::operators::operator -=;
240+
241+ using Rectangle = boost::polygon::rectangle_data<int >;
242+ using Polygon90 = boost::polygon::polygon_90_with_holes_data<int >;
243+ using Polygon90Set = boost::polygon::polygon_90_set_data<int >;
244+ using Pt = Polygon90::point_type;
245+
246+ auto rect_to_poly = [](const odb::Rect& rect) -> Polygon90 {
247+ std::array<Pt, 4 > pts = {Pt (rect.xMin (), rect.yMin ()),
248+ Pt (rect.xMax (), rect.yMin ()),
249+ Pt (rect.xMax (), rect.yMax ()),
250+ Pt (rect.xMin (), rect.yMax ())};
251+
252+ Polygon90 poly;
253+ poly.set (pts.begin (), pts.end ());
254+ return poly;
255+ };
256+
257+ Polygon90Set source_iterms;
258+
259+ bool has_layer = false ;
260+ for (const auto & [iterm_layer, iterm_rect] : iterm_->getGeometries ()) {
261+ if (iterm_layer == layer) {
262+ has_layer = true ;
263+ source_iterms += rect_to_poly (iterm_rect);
264+ }
265+ }
266+ if (!has_layer) {
267+ return ;
268+ }
269+
270+ std::map<odb::dbITerm*, Polygon90Set> iterms_geoms;
271+
272+ // Create geom of all shapes
273+ for (odb::dbITerm* iterm : terminals_) {
274+ bool iterm_has_layer = false ;
275+ for (const auto & [iterm_layer, iterm_rect] : iterm->getGeometries ()) {
276+ if (iterm_layer == layer) {
277+ iterm_has_layer = true ;
278+ iterms_geoms[iterm] += rect_to_poly (iterm_rect);
279+ }
280+ }
281+ if (!iterm_has_layer) {
282+ return ;
283+ }
284+ }
285+
286+ // check if route is even needed, ie, shapes overlap
287+ for (const auto & [iterm, polys] : iterms_geoms) {
288+ Polygon90Set check = polys;
289+ check.interact (source_iterms);
290+ if (!check.empty ()) {
291+ // There is nothing to do
292+ locked_ = true ;
293+ routed_ = true ;
294+
295+ routed_terminals_.insert (iterm_);
296+ routed_terminals_.insert (iterm);
297+ return ;
298+ }
299+ }
300+
301+ const int min_dist = layer->getSpacing ();
302+
303+ for (const auto & [iterm, polys] : iterms_geoms) {
304+ Polygon90Set check = polys;
305+ check.bloat (min_dist, min_dist, min_dist, min_dist);
306+ check.interact (source_iterms);
307+ if (!check.empty ()) {
308+ Polygon90Set source_bloat = source_iterms;
309+ source_bloat.bloat (min_dist, min_dist, min_dist, min_dist);
310+ check += source_bloat;
311+ check.shrink (min_dist, min_dist, min_dist, min_dist);
312+ check -= source_iterms;
313+
314+ std::vector<Rectangle> combined_rects;
315+ check.get_rectangles (combined_rects);
316+ for (const auto & rect : combined_rects) {
317+ stubs_.emplace (xl (rect), yl (rect), xh (rect), yh (rect));
318+ }
319+ // There is nothing to do
320+ locked_ = true ;
321+ routed_ = true ;
322+ routed_terminals_.insert (iterm_);
323+ routed_terminals_.insert (iterm);
324+
325+ return ;
326+ }
327+ }
328+ }
329+
330+ std::set<odb::dbITerm*> RDLRoute::getRoutedTerminals () const
331+ {
332+ if (!routed_terminals_.empty ()) {
333+ return routed_terminals_;
334+ }
335+
336+ std::set<odb::dbITerm*> terms;
337+ if (route_source_) {
338+ terms.insert (route_source_->terminal );
339+ }
340+ if (route_dest_) {
341+ terms.insert (route_dest_->terminal );
342+ }
343+
344+ return terms;
345+ }
346+
217347} // namespace pad
0 commit comments