1010#include < vector>
1111
1212#include " boost/geometry/geometry.hpp"
13+ #include " boost/polygon/polygon.hpp"
1314#include " odb/db.h"
1415#include " odb/geom.h"
1516#include " odb/geom_boost.h"
@@ -18,7 +19,12 @@ namespace pad {
1819
1920RDLRoute::RDLRoute (odb::dbITerm* source,
2021 const std::vector<odb::dbITerm*>& dests)
21- : iterm_(source), priority_(0 ), terminals_(dests)
22+ : iterm_(source),
23+ priority_ (0 ),
24+ route_pending_(false ),
25+ locked_(false ),
26+ routed_(false ),
27+ terminals_(dests)
2228{
2329 terminals_.erase (std::remove_if (terminals_.begin (),
2430 terminals_.end (),
@@ -117,10 +123,18 @@ void RDLRoute::setRoute(
117123 route_edges_.push_back (edge);
118124 }
119125 }
126+
127+ routed_ = true ;
120128}
121129
122130void RDLRoute::resetRoute ()
123131{
132+ if (locked_) {
133+ return ;
134+ }
135+
136+ routed_ = false ;
137+
124138 route_vertex_.clear ();
125139 route_pts_.clear ();
126140 route_edges_.clear ();
@@ -214,4 +228,113 @@ bool RDLRoute::contains(const odb::Point& pt) const
214228 != route_pts_.end ();
215229}
216230
231+ void RDLRoute::preprocess (odb::dbTechLayer* layer, utl::Logger* logger)
232+ {
233+ using namespace boost ::polygon::operators;
234+ using Rectangle = boost::polygon::rectangle_data<int >;
235+ using Polygon90 = boost::polygon::polygon_90_with_holes_data<int >;
236+ using Polygon90Set = boost::polygon::polygon_90_set_data<int >;
237+ using Pt = Polygon90::point_type;
238+
239+ auto rect_to_poly = [](const odb::Rect& rect) -> Polygon90 {
240+ std::array<Pt, 4 > pts = {Pt (rect.xMin (), rect.yMin ()),
241+ Pt (rect.xMax (), rect.yMin ()),
242+ Pt (rect.xMax (), rect.yMax ()),
243+ Pt (rect.xMin (), rect.yMax ())};
244+
245+ Polygon90 poly;
246+ poly.set (pts.begin (), pts.end ());
247+ return poly;
248+ };
249+
250+ Polygon90Set source_iterms;
251+
252+ bool has_layer = false ;
253+ for (const auto & [iterm_layer, iterm_rect] : iterm_->getGeometries ()) {
254+ if (iterm_layer == layer) {
255+ has_layer = true ;
256+ source_iterms += rect_to_poly (iterm_rect);
257+ }
258+ }
259+ if (!has_layer) {
260+ return ;
261+ }
262+
263+ std::map<odb::dbITerm*, Polygon90Set> iterms_geoms;
264+
265+ // Create geom of all shapes
266+ for (odb::dbITerm* iterm : terminals_) {
267+ bool iterm_has_layer = false ;
268+ for (const auto & [iterm_layer, iterm_rect] : iterm->getGeometries ()) {
269+ if (iterm_layer == layer) {
270+ iterm_has_layer = true ;
271+ iterms_geoms[iterm] += rect_to_poly (iterm_rect);
272+ }
273+ }
274+ if (!iterm_has_layer) {
275+ return ;
276+ }
277+ }
278+
279+ // check if route is even needed, ie, shapes overlap
280+ for (const auto & [iterm, polys] : iterms_geoms) {
281+ Polygon90Set check = polys;
282+ check.interact (source_iterms);
283+ if (check.size () > 0 ) {
284+ // There is nothing to do
285+ locked_ = true ;
286+ routed_ = true ;
287+
288+ routed_terminals_.insert (iterm_);
289+ routed_terminals_.insert (iterm);
290+ return ;
291+ }
292+ }
293+
294+ const int min_dist = layer->getSpacing ();
295+
296+ for (const auto & [iterm, polys] : iterms_geoms) {
297+ Polygon90Set check = polys;
298+ check.bloat (min_dist, min_dist, min_dist, min_dist);
299+ check.interact (source_iterms);
300+ if (check.size () > 0 ) {
301+ Polygon90Set source_bloat = source_iterms;
302+ source_bloat.bloat (min_dist, min_dist, min_dist, min_dist);
303+ check += source_bloat;
304+ check.shrink (min_dist, min_dist, min_dist, min_dist);
305+ check -= source_iterms;
306+
307+ std::vector<Rectangle> combined_rects;
308+ check.get_rectangles (combined_rects);
309+ for (const auto & rect : combined_rects) {
310+ stubs_.emplace (xl (rect), yl (rect), xh (rect), yh (rect));
311+ }
312+ // There is nothing to do
313+ locked_ = true ;
314+ routed_ = true ;
315+ routed_terminals_.insert (iterm_);
316+ routed_terminals_.insert (iterm);
317+
318+ return ;
319+ }
320+ }
321+ }
322+
323+ std::set<odb::dbITerm*> RDLRoute::getRoutedTerminals () const
324+ {
325+ if (!routed_terminals_.empty ()) {
326+ return routed_terminals_;
327+ }
328+
329+ std::set<odb::dbITerm*> terms;
330+ if (route_source_) {
331+ terms.insert (route_source_->terminal );
332+ }
333+ if (route_dest_) {
334+ terms.insert (route_dest_->terminal );
335+ }
336+
337+ return terms;
338+ }
339+
217340} // namespace pad
0 commit comments