1 ///////////////////////////////////////////////////////////////////////////////
2 // BSD 3-Clause License
3 //
4 // Copyright (c) 2019, Nefelus Inc
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 #include "create_box.h"
34 
35 #include <stdio.h>
36 
37 #include "utl/Logger.h"
38 namespace odb {
39 
create_box(dbSWire * wire,dbWireShapeType type,dbTechLayer * layer,int prev_x,int prev_y,int prev_ext,bool has_prev_ext,int cur_x,int cur_y,int cur_ext,bool has_cur_ext,int width,utl::Logger * logger)40 void create_box(dbSWire* wire,
41                 dbWireShapeType type,
42                 dbTechLayer* layer,
43                 int prev_x,
44                 int prev_y,
45                 int prev_ext,
46                 bool has_prev_ext,
47                 int cur_x,
48                 int cur_y,
49                 int cur_ext,
50                 bool has_cur_ext,
51                 int width,
52                 utl::Logger* logger)
53 {
54   int x1, x2, y1, y2;
55   int dw = width >> 1;
56 
57   if ((cur_x == prev_x) && (cur_y == prev_y))  // single point
58   {
59     logger->warn(utl::ODB,
60                  274,
61                  "Zero length path segment ({},{}) ({},{})",
62                  prev_x,
63                  prev_y,
64                  cur_x,
65                  cur_y);
66     return;
67   } else if (cur_x == prev_x)  // vert. path
68   {
69     x1 = cur_x - dw;
70     x2 = cur_x + dw;
71 
72     if (cur_y > prev_y) {
73       if (has_prev_ext)
74         y1 = prev_y - prev_ext;
75       else
76         y1 = prev_y;
77 
78       if (has_cur_ext)
79         y2 = cur_y + cur_ext;
80       else
81         y2 = cur_y;
82     } else {
83       if (has_cur_ext)
84         y1 = cur_y - cur_ext;
85       else
86         y1 = cur_y;
87 
88       if (has_prev_ext)
89         y2 = prev_y + prev_ext;
90       else
91         y2 = prev_y;
92     }
93 
94     dbSBox::create(wire, layer, x1, y1, x2, y2, type, dbSBox::VERTICAL);
95   } else if (cur_y == prev_y)  // horiz. path
96   {
97     y1 = cur_y - dw;
98     y2 = cur_y + dw;
99 
100     if (cur_x > prev_x) {
101       if (has_prev_ext)
102         x1 = prev_x - prev_ext;
103       else
104         x1 = prev_x;
105 
106       if (has_cur_ext)
107         x2 = cur_x + cur_ext;
108       else
109         x2 = cur_x;
110     } else {
111       if (has_cur_ext)
112         x1 = cur_x - cur_ext;
113       else
114         x1 = cur_x;
115 
116       if (has_prev_ext)
117         x2 = prev_x + prev_ext;
118       else
119         x2 = prev_x;
120     }
121     dbSBox::create(wire, layer, x1, y1, x2, y2, type, dbSBox::HORIZONTAL);
122   } else if (abs(cur_x - prev_x) == abs(cur_y - prev_y)) {  // 45-degree path
123     dbSBox::create(wire,
124                    layer,
125                    prev_x,
126                    prev_y,
127                    cur_x,
128                    cur_y,
129                    type,
130                    dbSBox::OCTILINEAR,
131                    width);
132   } else {
133     assert(
134         0
135         && "not orthogonal nor 45-degree path segment");  // illegal:
136                                                           // non-orthogonal-path
137   }
138 }
139 
create_via_array(dbSWire * wire,dbWireShapeType type,dbTechLayer * layer,dbTechVia * via,int orig_x,int orig_y,int numX,int numY,int stepX,int stepY,utl::Logger * logger)140 dbTechLayer* create_via_array(dbSWire* wire,
141                               dbWireShapeType type,
142                               dbTechLayer* layer,
143                               dbTechVia* via,
144                               int orig_x,
145                               int orig_y,
146                               int numX,
147                               int numY,
148                               int stepX,
149                               int stepY,
150                               utl::Logger* logger)
151 {
152   if (via->getBBox() == NULL) {
153     std::string n = via->getName();
154     logger->warn(utl::ODB,
155                  241,
156                  "error: Cannot create a via instance, via ({}) has no shapes",
157                  n.c_str());
158     return NULL;
159   }
160 
161   int i, j;
162   int x = orig_x;
163 
164   for (i = 0; i < numX; ++i) {
165     int y = orig_y;
166 
167     for (j = 0; j < numY; ++j) {
168       dbSBox::create(wire, via, x, y, type);
169       y += stepY;
170     }
171 
172     x += stepX;
173   }
174 
175   dbTechLayer* top = via->getTopLayer();
176   dbTechLayer* bottom = via->getBottomLayer();
177 
178   // VIA: implicit layer change...
179   if ((top != layer) && (bottom != layer)) {
180     std::string vname = via->getName();
181     std::string lname = layer->getName();
182 
183     logger->warn(utl::ODB,
184                  242,
185                  "error: Can not determine which direction to continue path,");
186     logger->info(
187         utl::ODB,
188         243,
189         "       via ({}) spans above and below the current layer ({}).",
190         vname.c_str(),
191         lname.c_str());
192     return NULL;
193   }
194 
195   if (top != layer)
196     layer = top;
197 
198   else if (bottom != layer)
199     layer = bottom;
200 
201   return layer;
202 }
203 
create_via_array(dbSWire * wire,dbWireShapeType type,dbTechLayer * layer,dbVia * via,int orig_x,int orig_y,int numX,int numY,int stepX,int stepY,utl::Logger * logger)204 dbTechLayer* create_via_array(dbSWire* wire,
205                               dbWireShapeType type,
206                               dbTechLayer* layer,
207                               dbVia* via,
208                               int orig_x,
209                               int orig_y,
210                               int numX,
211                               int numY,
212                               int stepX,
213                               int stepY,
214                               utl::Logger* logger)
215 {
216   if (via->getBBox() == NULL) {
217     std::string vname = via->getName();
218     logger->warn(utl::ODB,
219                  244,
220                  "error: Cannot create a via instance, via ({}) has no shapes",
221                  vname.c_str());
222     return NULL;
223   }
224 
225   int i, j;
226   int x = orig_x;
227 
228   for (i = 0; i < numX; ++i) {
229     int y = orig_y;
230 
231     for (j = 0; j < numY; ++j) {
232       dbSBox::create(wire, via, x, y, type);
233       y += stepY;
234     }
235 
236     x += stepX;
237   }
238 
239   dbTechLayer* top = via->getTopLayer();
240   dbTechLayer* bottom = via->getBottomLayer();
241 
242   // VIA: implicit layer change...
243   if ((top != layer) && (bottom != layer)) {
244     std::string vname = via->getName();
245     std::string lname = layer->getName();
246 
247     logger->warn(
248         utl::ODB,
249         245,
250         "error: Net {}: Can not determine which direction to continue path,",
251         wire->getNet()->getConstName());
252     logger->info(
253         utl::ODB,
254         276,
255         "       via ({}) spans above and below the current layer ({}).",
256         vname.c_str(),
257         lname.c_str());
258     return NULL;
259   }
260 
261   if (top != layer)
262     layer = top;
263 
264   else if (bottom != layer)
265     layer = bottom;
266 
267   return layer;
268 }
269 
270 }  // namespace odb
271