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 #pragma once
34
35 #include "db.h"
36 #include "odb.h"
37
38 namespace odb {
39
40 ///
41 /// dbWireCodec: - Opcode definitions
42 ///
43 #define WOP_NON_DEFAULT_WIDTH_POINT_CNT \
44 16 // Count of points before a "width" is inserted. Optimization for
45 // searching data-structure. This count is always a power of 2.
46
47 #define WOP_OPCODE_MASK \
48 0x1F // Mask to determine opcode from op-byte. Currently the opcode is 5
49 // bits. There are 3 bits for various flags.
50
51 //
52 // opcodes BIT: 7 6 5 4 3 2 1 0 ---- (W W W) == WOP_<WIRE_TYPE>,
53 // T == WOP_VIA_EXIT_TOP,
54 // E == WOP_EXTENSION,
55 // D == WOP_DEFAULT_WIDTH,
56 // B == WOP_BLOCK_RULE
57 // X == unused bit
58 #define WOP_PATH 0 // W W W X 0 0 0 0 : operand = layer-id
59 #define WOP_SHORT 1 // W W W X 0 0 0 1 : operand = junction-id
60 #define WOP_JUNCTION 2 // W W W X 0 0 1 0 : operand = junction-id
61 #define WOP_RULE 3 // B X X X 0 0 1 1 : operand = rule-id
62 #define WOP_X 4 // E D X X 0 1 0 0 : operand = x-coord
63 #define WOP_Y 5 // E D X X 0 1 0 1 : operand = y-coord
64 #define WOP_COLINEAR 6 // E X X X 0 1 1 0 : operand = (e == 1) ? ext : 0
65 #define WOP_VIA 7 // T X X X 0 1 1 1 : operand = via-id
66 #define WOP_TECH_VIA 8 // T X X X 1 0 0 0 : operand = via-id
67 #define WOP_ITERM 9 // X X X X 1 0 0 1 : operand = iterm-id
68 #define WOP_BTERM 10 // X X X X 1 0 1 0 : operand = bterm-id
69 #define WOP_OPERAND 11 // X X X X 1 0 1 1 : operand = integer operand
70 #define WOP_PROPERTY 12 // X X X X 1 1 0 0 : operand = integer operand
71 #define WOP_VWIRE 13 // W W W X 1 1 0 1 : operand = integer operand
72 #define WOP_RECT 14 // X X X X 1 1 1 0 : operand = first offset
73 #define WOP_NOP 15 // X X X X 1 1 1 1 : operand = 0
74
75 // opcode-flags
76 #define WOP_VIA_EXIT_TOP \
77 0x80 // This flag indicates the path exited through the top or bottom via
78 // layer.
79 #define WOP_DEFAULT_WIDTH \
80 0x40 // This flag indicates the path-width at this point is the default
81 // layer-width.
82 #define WOP_EXTENSION \
83 0x80 // This flag indicates the point/via has an extension operand
84 #define WOP_BLOCK_RULE \
85 0x80 // This flag indicates non-default-rule is a block rule
86
87 // wire-type-flags
88 #define WOP_WIRE_TYPE_MASK 0xE0
89 #define WOP_NONE 0x00
90 #define WOP_COVER 0x20
91 #define WOP_FIXED 0x40
92 #define WOP_ROUTED 0x60
93 #define WOP_NOSHIELD 0x80
94
95 //////////////////////////////////////////////////////////////////////////////////
96 //
97 // getPrevPoint - This function walks backwards from a given index and finds
98 // the previous point relative to that index. If requested,
99 // it keeps walking backward to determine the layer the point is
100 // on.
101 //
102 //////////////////////////////////////////////////////////////////////////////////
103
104 struct WirePoint
105 {
106 int _x;
107 int _y;
108 dbTechLayer* _layer;
109 };
110
111 template <class O, class D>
getPrevPoint(dbTech * tech,dbBlock * block,O & opcodes,D & data,int idx,bool get_layer,WirePoint & pnt)112 inline void getPrevPoint(dbTech* tech,
113 dbBlock* block,
114 O& opcodes,
115 D& data,
116 int idx,
117 bool get_layer,
118 WirePoint& pnt)
119 {
120 unsigned char opcode;
121 bool look_for_x = true;
122 bool look_for_y = true;
123 // quiets compiler warnings
124 pnt._x = 0;
125 pnt._y = 0;
126 pnt._layer = nullptr;
127
128 prevOpCode:
129 ZASSERT(idx >= 0);
130 opcode = opcodes[idx];
131
132 switch (opcode & WOP_OPCODE_MASK) {
133 case WOP_PATH:
134 case WOP_SHORT: {
135 if (get_layer) {
136 pnt._layer = dbTechLayer::getTechLayer(tech, data[idx]);
137
138 if ((look_for_x == false) && (look_for_y == false))
139 return;
140
141 get_layer = false;
142 }
143
144 --idx;
145 goto prevOpCode;
146 }
147
148 case WOP_JUNCTION: {
149 idx = data[idx];
150 goto prevOpCode;
151 }
152
153 case WOP_X: {
154 if (look_for_x) {
155 look_for_x = false;
156 pnt._x = data[idx];
157
158 if ((look_for_y == false) && (get_layer == false))
159 return;
160 }
161
162 --idx;
163 goto prevOpCode;
164 }
165
166 case WOP_Y: {
167 if (look_for_y) {
168 look_for_y = false;
169 pnt._y = data[idx];
170
171 if ((look_for_x == false) && (get_layer == false))
172 return;
173 }
174
175 --idx;
176 goto prevOpCode;
177 }
178
179 case WOP_VIA: {
180 if (get_layer) {
181 dbVia* via = dbVia::getVia(block, data[idx]);
182
183 if (opcode & WOP_VIA_EXIT_TOP)
184 pnt._layer = via->getTopLayer();
185 else
186 pnt._layer = via->getBottomLayer();
187
188 if ((look_for_x == false) && (look_for_y == false))
189 return;
190
191 get_layer = false;
192 }
193
194 --idx;
195 goto prevOpCode;
196 }
197
198 case WOP_TECH_VIA: {
199 if (get_layer) {
200 dbTechVia* via = dbTechVia::getTechVia(tech, data[idx]);
201
202 if (opcode & WOP_VIA_EXIT_TOP)
203 pnt._layer = via->getTopLayer();
204 else
205 pnt._layer = via->getBottomLayer();
206
207 if ((look_for_x == false) && (look_for_y == false))
208 return;
209
210 get_layer = false;
211 }
212
213 --idx;
214 goto prevOpCode;
215 }
216
217 default:
218 --idx;
219 goto prevOpCode;
220 }
221 }
222
223 } // namespace odb
224