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