1 /* 2 PADRING -- a padring generator for ASICs. 3 4 Copyright (c) 2019, Niels Moseley <niels@symbioticeda.com> 5 6 Permission to use, copy, modify, and/or distribute this software for any 7 purpose with or without fee is hereby granted, provided that the above 8 copyright notice and this permission notice appear in all copies. 9 10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 18 */ 19 20 #ifndef padringdb_h 21 #define padringdb_h 22 23 #include "configreader.h" 24 #include "prlefreader.h" 25 #include "layout.h" 26 #include "logging.h" 27 28 class PadringDB : public ConfigReader 29 { 30 public: 31 PadringDB()32 PadringDB() : m_north(Layout::DIR_HORIZONTAL), 33 m_south(Layout::DIR_HORIZONTAL), 34 m_east(Layout::DIR_VERTICAL), 35 m_west(Layout::DIR_VERTICAL), 36 m_grid(1.0) 37 { 38 m_south.setEdgePos(0.0); 39 m_west.setEdgePos(0.0); 40 m_designName = "PADRING"; 41 } 42 43 /** callback for a corner */ onCorner(const std::string & instance,const std::string & location,const std::string & cellname)44 virtual void onCorner( 45 const std::string &instance, 46 const std::string &location, 47 const std::string &cellname) override 48 { 49 PRLEFReader::LEFCellInfo_t *cell = m_lefreader.getCellByName(cellname); 50 if (cell == nullptr) 51 { 52 doLog(LOG_ERROR,"Cannot find cell %s in the LEF database\n", cellname.c_str()); 53 return; 54 } 55 56 LayoutItem *item_x = new LayoutItem(LayoutItem::TYPE_CORNER); 57 item_x->m_instance = instance; 58 item_x->m_cellname = cellname; 59 item_x->m_location = location; 60 item_x->m_size = cell->m_sx; 61 item_x->m_lefinfo = cell; 62 63 LayoutItem *item_y = new LayoutItem(LayoutItem::TYPE_CORNER); 64 item_y->m_instance = instance; 65 item_y->m_cellname = cellname; 66 item_y->m_location = location; 67 item_y->m_size = cell->m_sy; 68 item_y->m_lefinfo = cell; 69 70 // Corner cells should be symmetrical 71 // i.e. width = height. 72 if (location == "NE") 73 { 74 // ROT 180 75 m_north.setLastCorner(item_x); 76 m_east.setLastCorner(item_y); 77 } 78 else if (location == "NW") 79 { 80 // ROT 90 81 m_north.setFirstCorner(item_y); 82 m_west.setLastCorner(item_x); 83 } 84 else if (location == "SE") 85 { 86 // ROT 270 87 m_south.setLastCorner(item_y); 88 m_east.setFirstCorner(item_x); 89 } 90 else if (location == "SW") 91 { 92 // ROT 0 93 m_south.setFirstCorner(item_x); 94 m_west.setFirstCorner(item_y); 95 } 96 } 97 98 /** callback for a pad */ onPad(const std::string & instance,const std::string & location,const std::string & cellname,bool flipped)99 virtual void onPad( 100 const std::string &instance, 101 const std::string &location, 102 const std::string &cellname, 103 bool flipped) override 104 { 105 PRLEFReader::LEFCellInfo_t *cell = m_lefreader.getCellByName(cellname); 106 if (cell == nullptr) 107 { 108 doLog(LOG_ERROR,"Cannot find cell %s in the LEF database\n", cellname.c_str()); 109 return; 110 } 111 112 LayoutItem *item = new LayoutItem(LayoutItem::TYPE_CELL); 113 item->m_instance = instance; 114 item->m_cellname = cellname; 115 item->m_location = location; 116 item->m_size = cell->m_sx; 117 item->m_lefinfo = cell; 118 item->m_flipped = flipped; 119 120 // Corner cells should be symmetrical 121 // i.e. width = height. 122 if (location == "N") 123 { 124 m_north.addItem(item); 125 } 126 else if (location == "W") 127 { 128 m_west.addItem(item); 129 } 130 else if (location == "S") 131 { 132 m_south.addItem(item); 133 } 134 else if (location == "E") 135 { 136 m_east.addItem(item); 137 } 138 else 139 { 140 doLog(LOG_ERROR, "Incorrect location on PAD %s\n", cellname.c_str()); 141 } 142 143 m_lastLocation = location; 144 } 145 146 /** callback for die area in microns */ onArea(double x,double y)147 virtual void onArea(double x, double y) override 148 { 149 m_dieWidth = x; 150 m_dieHeight = y; 151 152 m_north.setDieSize(x); 153 m_south.setDieSize(x); 154 m_east.setDieSize(y); 155 m_west.setDieSize(y); 156 157 m_north.setEdgePos(y); 158 m_east.setEdgePos(x); 159 } 160 161 /** callback for grid spacing in microns */ onGrid(double grid)162 virtual void onGrid(double grid) override 163 { 164 m_grid = grid; 165 } 166 167 /** callback for filler cell prefix string */ onFiller(const std::string & filler)168 virtual void onFiller(const std::string &filler) override 169 { 170 m_fillerPrefix = filler; 171 } 172 173 /** callback for space in microns */ onSpace(double space)174 virtual void onSpace(double space) override 175 { 176 LayoutItem *item = new LayoutItem(LayoutItem::TYPE_FIXEDSPACE); 177 item->m_size = space; 178 179 if (m_lastLocation == "N") 180 { 181 m_north.addItem(item); 182 } 183 else if (m_lastLocation == "W") 184 { 185 m_west.addItem(item); 186 } 187 else if (m_lastLocation == "S") 188 { 189 m_south.addItem(item); 190 } 191 else if (m_lastLocation == "E") 192 { 193 m_east.addItem(item); 194 } 195 } 196 197 /** callback for offset in microns */ onOffset(double offset)198 virtual void onOffset(double offset) override 199 { 200 //FIXME: offset not supported yet! 201 } 202 onDesignName(const std::string & designName)203 virtual void onDesignName(const std::string &designName) override 204 { 205 m_designName = designName; 206 } 207 doLayout()208 void doLayout() 209 { 210 m_north.doLayout(); 211 m_south.doLayout(); 212 m_west.doLayout(); 213 m_east.doLayout(); 214 } 215 216 Layout m_north; 217 Layout m_south; 218 Layout m_east; 219 Layout m_west; 220 221 double m_dieHeight; 222 double m_dieWidth; 223 double m_grid; 224 225 std::string m_designName; 226 227 std::string m_fillerPrefix; 228 std::string m_lastLocation; 229 230 PRLEFReader m_lefreader; 231 }; 232 233 #endif 234