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