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