1 ///////////////////////////////////////////////////////////////////////////////
2 // BSD 3-Clause License
3 //
4 // Copyright (c) 2019, The Regents of the University of California
5 // All rights reserved.
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions are met:
9 //
10 // * Redistributions of source code must retain the above copyright notice, this
11 //   list of conditions and the following disclaimer.
12 //
13 // * Redistributions in binary form must reproduce the above copyright notice,
14 //   this list of conditions and the following disclaimer in the documentation
15 //   and/or other materials provided with the distribution.
16 //
17 // * Neither the name of the copyright holder nor the names of its
18 //   contributors may be used to endorse or promote products derived from
19 //   this software without specific prior written permission.
20 //
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 // POSSIBILITY OF SUCH DAMAGE.
32 
33 #pragma once
34 
35 #include <QFrame>
36 #include <QLine>
37 #include <QMainWindow>
38 #include <QMap>
39 #include <QMenu>
40 #include <QOpenGLWidget>
41 #include <QScrollArea>
42 #include <QShortcut>
43 #include <map>
44 #include <vector>
45 
46 #include "gui/gui.h"
47 #include "opendb/dbBlockCallBackObj.h"
48 #include "options.h"
49 #include "search.h"
50 
51 namespace utl {
52 class Logger;
53 }
54 
55 namespace odb {
56 class dbBlock;
57 class dbDatabase;
58 class dbInst;
59 class dbMaster;
60 class dbTransform;
61 class dbTechLayer;
62 }  // namespace odb
63 
64 namespace gui {
65 
66 class LayoutScroll;
67 
68 // This class draws the layout.  It supports:
69 //   * zoom in/out with ctrl-mousewheel
70 //   * rubber band zoom with right mouse button
71 //   * fit with 'F' key
72 // The display follows the display options for visibility.
73 //
74 // This object resizes with zooming but only the visible
75 // portion of this widget is ever drawn.
76 class LayoutViewer : public QWidget, public odb::dbBlockCallBackObj
77 {
78   Q_OBJECT
79 
80  public:
81   enum CONTEXT_MENU_ACTIONS
82   {
83     SELECT_CONNECTED_INST_ACT,
84     SELECT_OUTPUT_NETS_ACT,
85     SELECT_INPUT_NETS_ACT,
86     SELECT_ALL_NETS_ACT,
87 
88     HIGHLIGHT_CONNECTED_INST_ACT,
89     HIGHLIGHT_OUTPUT_NETS_ACT,
90     HIGHLIGHT_INPUT_NETS_ACT,
91     HIGHLIGHT_ALL_NETS_ACT,
92 
93     VIEW_ZOOMIN_ACT,
94     VIEW_ZOOMOUT_ACT,
95     VIEW_ZOOMFIT_ACT,
96 
97     CLEAR_SELECTIONS_ACT,
98     CLEAR_HIGHLIGHTS_ACT,
99     CLEAR_RULERS_ACT,
100     CLEAR_ALL_ACT
101   };
102   // makeSelected is so that we don't have to pass in the whole
103   // MainWindow just to get access to one method.  Communication
104   // should happen through signals & slots in all other cases.
105   LayoutViewer(Options* options,
106                const SelectionSet& selected,
107                const HighlightSet& highlighted,
108                const std::vector<QLine>& rulers,
109                std::function<Selected(const std::any&)> makeSelected,
110                QWidget* parent = nullptr);
111 
112   void setDb(odb::dbDatabase* db);
113   void setLogger(utl::Logger* logger);
getPixelsPerDBU()114   qreal getPixelsPerDBU() { return pixels_per_dbu_; }
115   void setScroller(LayoutScroll* scroller);
116 
117   // From QWidget
118   virtual void paintEvent(QPaintEvent* event) override;
119   virtual void resizeEvent(QResizeEvent* event) override;
120   virtual void mousePressEvent(QMouseEvent* event) override;
121   virtual void mouseMoveEvent(QMouseEvent* event) override;
122   virtual void mouseReleaseEvent(QMouseEvent* event) override;
123 
124   // From dbBlockCallBackObj
125   virtual void inDbNetDestroy(odb::dbNet* net) override;
126   virtual void inDbInstDestroy(odb::dbInst* inst) override;
127   virtual void inDbInstSwapMasterAfter(odb::dbInst* inst) override;
128   virtual void inDbInstPlacementStatusBefore(
129       odb::dbInst* inst,
130       const odb::dbPlacementStatus& status) override;
131   virtual void inDbPostMoveInst(odb::dbInst* inst) override;
132   virtual void inDbBPinDestroy(odb::dbBPin* pin) override;
133   virtual void inDbFillCreate(odb::dbFill* fill) override;
134   virtual void inDbWireCreate(odb::dbWire* wire) override;
135   virtual void inDbWireDestroy(odb::dbWire* wire) override;
136   virtual void inDbSWireCreate(odb::dbSWire* wire) override;
137   virtual void inDbSWireDestroy(odb::dbSWire* wire) override;
138   virtual void inDbBlockSetDieArea(odb::dbBlock* block) override;
139 
140  signals:
141   void location(qreal x, qreal y);
142   void selected(const Selected& selected, bool showConnectivity = false);
143   void addSelected(const Selected& selected);
144   void addRuler(int x0, int y0, int x1, int y1);
145 
146  public slots:
147   void zoomIn();
148   void zoomOut();
149   void zoomTo(const odb::Rect& rect_dbu);
150   void designLoaded(odb::dbBlock* block);
151   void fit();  // fit the whole design in the window
152 
153   void selectHighlightConnectedInst(bool selectFlag);
154   void selectHighlightConnectedNets(bool selectFlag, bool output, bool input);
155 
156   void updateContextMenuItems();
157   void showLayoutCustomMenu(QPoint pos);
158 
159  private:
160   struct Boxes
161   {
162     std::vector<QRect> obs;
163     std::vector<QRect> mterms;
164   };
165 
166   struct GCellData
167   {
168     int hor_capacity_;
169     int hor_usage_;
170     int ver_capacity_;
171     int ver_usage_;
172 
173     GCellData(int h_cap = 0, int h_usage = 0, int v_cap = 0, int v_usage = 0)
hor_capacity_GCellData174         : hor_capacity_(h_cap),
175           hor_usage_(h_usage),
176           ver_capacity_(v_cap),
177           ver_usage_(v_usage)
178     {
179     }
180   };
181   using LayerBoxes = std::map<odb::dbTechLayer*, Boxes>;
182   using CellBoxes = std::map<odb::dbMaster*, LayerBoxes>;
183 
184   void boxesByLayer(odb::dbMaster* master, LayerBoxes& boxes);
185   const Boxes* boxesByLayer(odb::dbMaster* master, odb::dbTechLayer* layer);
186   odb::dbBlock* getBlock();
187   void setPixelsPerDBU(qreal pixels_per_dbu);
188   void drawBlock(QPainter* painter,
189                  const odb::Rect& bounds,
190                  odb::dbBlock* block,
191                  int depth,
192                  const QTransform& base_tx);
193   void addInstTransform(QTransform& xfm, const odb::dbTransform& inst_xfm);
194   QColor getColor(odb::dbTechLayer* layer);
195   Qt::BrushStyle getPattern(odb::dbTechLayer* layer);
196   void updateRubberBandRegion();
197   void drawTracks(odb::dbTechLayer* layer,
198                   odb::dbBlock* block,
199                   QPainter* painter,
200                   const odb::Rect& bounds);
201 
202   void drawRows(odb::dbBlock* block,
203                 QPainter* painter,
204                 const odb::Rect& bounds);
205   void drawSelected(Painter& painter);
206   void drawHighlighted(Painter& painter);
207   void drawCongestionMap(Painter& painter, const odb::Rect& bounds);
208   void drawPinMarkers(QPainter* painter,
209                       const odb::Rect& bounds,
210                       odb::dbBlock* block);
211   void drawRulers(Painter& painter);
212   Selected selectAtPoint(odb::Point pt_dbu);
213 
214   odb::Rect screenToDBU(const QRect& rect);
215   odb::Point screenToDBU(const QPoint& point);
216   QRectF dbuToScreen(const odb::Rect& dbu_rect);
217 
218   void addMenuAndActions();
219   void updateShapes();
220 
221   odb::dbDatabase* db_;
222   Options* options_;
223   const SelectionSet& selected_;
224   const HighlightSet& highlighted_;
225   const std::vector<QLine>& rulers_;
226   LayoutScroll* scroller_;
227   qreal pixels_per_dbu_;
228   qreal fit_pixels_per_dbu_;
229   int min_depth_;
230   int max_depth_;
231   Search search_;
232   bool search_init_;
233   CellBoxes cell_boxes_;
234   QRect rubber_band_;  // screen coordinates
235   QPoint mouse_press_pos_;
236   QPoint mouse_move_pos_;
237   bool rubber_band_showing_;
238   std::function<Selected(const std::any&)> makeSelected_;
239 
240   utl::Logger* logger_;
241   bool design_loaded_;
242 
243   QMenu* layout_context_menu_;
244   QMap<CONTEXT_MENU_ACTIONS, QAction*> menu_actions_;
245 };
246 
247 // The LayoutViewer widget can become quite large as you zoom
248 // in so it is stored in a scroll area.
249 class LayoutScroll : public QScrollArea
250 {
251   Q_OBJECT
252  public:
253   LayoutScroll(LayoutViewer* viewer, QWidget* parent = 0);
254 
255  public slots:
256   void zoomIn();
257   void zoomOut();
258 
259  protected:
260   void wheelEvent(QWheelEvent* event) override;
261 
262  private:
263   LayoutViewer* viewer_;
264 };
265 
266 }  // namespace gui
267