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