OpenNSL API Guide and Reference Manual
pbmp.h
Go to the documentation of this file.
1 /*********************************************************************
2  *
3  * (C) Copyright Broadcom Corporation 2013-2017
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  **********************************************************************
18  * File: pbmp.h
19  * Details: Port Bitmap Macros
20  *********************************************************************/
21 
22 #ifndef _SHR_PBMP_H
23 #define _SHR_PBMP_H
24 
25 #include <sal/types.h>
26 /*
27  * Port Bitmap Macros
28  *
29  * These macros are never used directly (well, except in the C code
30  * support routines that are used to help implement the macros).
31  *
32  * This header requires that the uint32 type be defined before inclusion.
33  * Using <sal/types.h> is the simplest (and recommended) way of doing
34  * this.
35  *
36  * There following macros are made available. All have names starting
37  * with _SHR_, which have been elided from this list:
38  *
39  * Constants or Expressions suitable for assignment:
40  * PBMP_PORT_MAX the maximum number of ports supported
41  * PBMP_WORD_MAX the maximum number of words in a bitmap
42  * PBMP_WORD_GET(b, w) return word w (0..WORD_MAX-1) from bitmap b
43  * PBMP_FMT_LEN length of char[] array for PBMP_FMT
44  * PBMP_FMT(b,s) %s'able format of bitmap b into string s
45  * returns s
46  *
47  * Predicates: (return 0 or 1, suitable for using in if statements)
48  * PBMP_MEMBER(b, p) is port p a member of bitmap b?
49  * PBMP_IS_NULL(b) is bitmap b empty?
50  * PBMP_NOT_NULL(b) is bitmap b not empty?
51  * PBMP_EQ(b1, b2) are bitmaps b1 and b2 equal?
52  * PBMP_NEQ(b1, b2) are bitmaps b1 and b2 not equal?
53  * PBMP_PORT_VALID(p) is p a valid port number? (0..PORT_MAX)
54  *
55  * Statements: (cannot be used as a predicate)
56  * PBMP_CLEAR(b) zero out a bitmap
57  * PBMP_COUNT(b, c) store how many bits are on in b into integer c
58  * PBMP_ITER(b, p) {...} iterate over bitmap b, setting p to each bit
59  * PBMP_ASSIGN(b1, b2) copy bitmap b2 into b1
60  * PBMP_AND(b1, b2) and bitmap b2 into b1
61  * PBMP_OR(b1, b2) or bitmap b2 into b1
62  * PBMP_XOR(b1, b2) exclusive or bitmap b2 into b1
63  * PBMP_REMOVE(b1, b2) remove bits in bitmap b2 from b1
64  * PBMP_NEGATE(b1, b2) copy the bitwise negation of bitmap b2 into b1
65  * PBMP_PORT_SET(b, p) clear bitmap b, then turn bit p on
66  * PBMP_PORT_ADD(b, p) turn bit p on in bitmap b
67  * PBMP_PORT_REMOVE(b, p) turn bit p off in bitmap b
68  * PBMP_PORT_FLIP(b, p) flip the sense of bit p on in bitmap b
69  * PBMP_WORD_SET(b, w, v) set word w (0..WORD_MAX-1) from bitmap b to v
70  *
71  * Internal forms: (should not be used outside of this header file)
72  * PBMP_WENT(p) word index for bit p
73  * PBMP_WBIT(p) word bitmask for bit p
74  * PBMP_BMCLEAR(b) clear a bitmap
75  * PBMP_BMNULL(b) is bitmap b empty?
76  * PBMP_BMEQ(b1, b2) are bitmaps b1 and b2 equal?
77  * PBMP_BMOP(b1, b2, op) execute op on a word basis on bitmaps b1, b2
78  * PBMP_ENTRY(b, p) the word of bitmap b that holds bit p
79  *
80  * There are 4 styles of implementation for the bitmap macros supported:
81  * 1. The historic single uint32 implementation (-D_SHR_PBMP_WIDTH=0)
82  * This is expected to be removed after a decent time of mourning.
83  * 2. An array of a single uint32 in a struct (-D_SHR_PBMP_WIDTH=32,
84  * the default). Macros are special cased to handle this efficiently.
85  * 3. An array of two uint32 in a struct (-D_SHR_PBMP_WIDTH=64, used).
86  * Macros are again special cased for efficiency.
87  * 4. An array of more than two uint32 in a struct (-D_SHR_PBMP_WIDTH=256
88  * for example). Most things are done inline, with a couple of helper
89  * functions used to implement some macros.
90  */
91 
92 #ifndef _SHR_PBMP_WIDTH
93 #undef _SHR_PBMP_PORT_MAX
94 #ifndef OPENNSL_PRODUCT_DNX
95 #define _SHR_PBMP_PORT_MAX 256
96 #else
97 #define _SHR_PBMP_PORT_MAX 571
98 #endif
99 
100 #define _SHR_PBMP_WIDTH (((_SHR_PBMP_PORT_MAX + 32 - 1)/32)*32)
101 #endif
102 
103 #ifndef _SHR_PBMP_PORT_MAX
104 #define _SHR_PBMP_PORT_MAX _SHR_PBMP_WIDTH
105 #endif
106 #define _SHR_PBMP_WORD_WIDTH 32
107 #define _SHR_PBMP_WORD_MAX \
108  ((_SHR_PBMP_WIDTH + _SHR_PBMP_WORD_WIDTH-1) / _SHR_PBMP_WORD_WIDTH)
109 
110 typedef struct _shr_pbmp {
112 } _shr_pbmp_t;
113 /* __doxy_func_body_end__ */
114 
115 #define _SHR_PBMP_WORD_GET(bm, word) ((bm).pbits[(word)])
116 #define _SHR_PBMP_WORD_SET(bm, word, val) ((bm).pbits[(word)] = (val))
117 
118 /*
119  * Common cases are one word (1..32 ports) and two words (33..64 ports).
120  * If not the common cases, more complicated code is generated using helper
121  * functions.
122  */
123 #if _SHR_PBMP_WORD_MAX == 1 /* 32 bit maps */
124 #define _SHR_PBMP_WENT(port) (0)
125 #define _SHR_PBMP_WBIT(port) (1U<<(port))
126 
127 /* helper defines used in the generic section below */
128 #define _SHR_PBMP_BMCLEAR(bm) (_SHR_PBMP_WORD_GET(bm, 0) = 0)
129 #define _SHR_PBMP_BMNULL(bm) (_SHR_PBMP_WORD_GET(bm, 0) == 0)
130 #define _SHR_PBMP_BMEQ(bma, bmb) \
131  (_SHR_PBMP_WORD_GET(bma, 0) == _SHR_PBMP_WORD_GET(bmb, 0))
132 #define _SHR_PBMP_BMOP(bma, bmb, op) do { \
133  _SHR_PBMP_WORD_GET(bma, 0) op _SHR_PBMP_WORD_GET(bmb, 0); \
134  } while (0)
135 /* __doxy_func_body_end__ */
136 #define _SHR_PBMP_COUNT(bm, count) \
137  (count = _shr_popcount(_SHR_PBMP_WORD_GET(bm, 0)))
138 
139 #elif _SHR_PBMP_WORD_MAX == 2 /* 64 bit maps */
140 #define _SHR_PBMP_WENT(port) ((port)/_SHR_PBMP_WORD_WIDTH)
141 #define _SHR_PBMP_WBIT(port) (1U<<((port) % _SHR_PBMP_WORD_WIDTH))
142 
143 #define _SHR_PBMP_BMCLEAR(bm) \
144  (_SHR_PBMP_WORD_GET(bm, 0) = _SHR_PBMP_WORD_GET(bm, 1) = 0)
145 #define _SHR_PBMP_BMNULL(bm) \
146  (_SHR_PBMP_WORD_GET(bm, 0) == 0 && _SHR_PBMP_WORD_GET(bm, 1) == 0)
147 #define _SHR_PBMP_BMEQ(bma, bmb) \
148  ((_SHR_PBMP_WORD_GET(bma, 0) == _SHR_PBMP_WORD_GET(bmb, 0)) && \
149  (_SHR_PBMP_WORD_GET(bma, 1) == _SHR_PBMP_WORD_GET(bmb, 1)))
150 #define _SHR_PBMP_BMOP(bma, bmb, op) do { \
151  _SHR_PBMP_WORD_GET(bma, 0) op _SHR_PBMP_WORD_GET(bmb, 0); \
152  _SHR_PBMP_WORD_GET(bma, 1) op _SHR_PBMP_WORD_GET(bmb, 1); \
153  } while (0)
154 /* __doxy_func_body_end__ */
155 #define _SHR_PBMP_COUNT(bm, count) \
156  (count = _shr_popcount(_SHR_PBMP_WORD_GET(bm, 0)) + \
157  _shr_popcount(_SHR_PBMP_WORD_GET(bm, 1)))
158 
159 #elif _SHR_PBMP_WORD_MAX == 3 /* 96 bit maps */
160 #define _SHR_PBMP_WENT(port) ((port)/_SHR_PBMP_WORD_WIDTH)
161 #define _SHR_PBMP_WBIT(port) (1U << ((port) % _SHR_PBMP_WORD_WIDTH))
162 
163 #define _SHR_PBMP_BMCLEAR(bm) \
164  (_SHR_PBMP_WORD_GET(bm, 0) = _SHR_PBMP_WORD_GET(bm, 1) = \
165  _SHR_PBMP_WORD_GET(bm, 2) = 0)
166 #define _SHR_PBMP_BMNULL(bm) \
167  (_SHR_PBMP_WORD_GET(bm, 0) == 0 && _SHR_PBMP_WORD_GET(bm, 1) == 0 && \
168  _SHR_PBMP_WORD_GET(bm, 2) == 0)
169 #define _SHR_PBMP_BMEQ(bma, bmb) \
170  ((_SHR_PBMP_WORD_GET(bma, 0) == _SHR_PBMP_WORD_GET(bmb, 0)) && \
171  (_SHR_PBMP_WORD_GET(bma, 1) == _SHR_PBMP_WORD_GET(bmb, 1)) && \
172  (_SHR_PBMP_WORD_GET(bma, 2) == _SHR_PBMP_WORD_GET(bmb, 2)))
173 #define _SHR_PBMP_BMOP(bma, bmb, op) do { \
174  _SHR_PBMP_WORD_GET(bma, 0) op _SHR_PBMP_WORD_GET(bmb, 0); \
175  _SHR_PBMP_WORD_GET(bma, 1) op _SHR_PBMP_WORD_GET(bmb, 1); \
176  _SHR_PBMP_WORD_GET(bma, 2) op _SHR_PBMP_WORD_GET(bmb, 2); \
177  } while (0)
178 /* __doxy_func_body_end__ */
179 #define _SHR_PBMP_COUNT(bm, count) \
180  (count = _shr_popcount(_SHR_PBMP_WORD_GET(bm, 0)) + \
181  _shr_popcount(_SHR_PBMP_WORD_GET(bm, 1)) + \
182  _shr_popcount(_SHR_PBMP_WORD_GET(bm, 2)))
183 
184 #elif _SHR_PBMP_WORD_MAX == 5 /* 160 bit maps */
185 #define _SHR_PBMP_WENT(port) ((port)/_SHR_PBMP_WORD_WIDTH)
186 #define _SHR_PBMP_WBIT(port) (1U << ((port) % _SHR_PBMP_WORD_WIDTH))
187 
188 #define _SHR_PBMP_BMCLEAR(bm) \
189  (_SHR_PBMP_WORD_GET(bm, 0) = _SHR_PBMP_WORD_GET(bm, 1) = \
190  _SHR_PBMP_WORD_GET(bm, 2) = _SHR_PBMP_WORD_GET(bm, 3) = \
191  _SHR_PBMP_WORD_GET(bm, 4) = 0)
192 #define _SHR_PBMP_BMNULL(bm) \
193  (_SHR_PBMP_WORD_GET(bm, 0) == 0 && _SHR_PBMP_WORD_GET(bm, 1) == 0 && \
194  _SHR_PBMP_WORD_GET(bm, 2) == 0 && _SHR_PBMP_WORD_GET(bm, 3) == 0 && \
195  _SHR_PBMP_WORD_GET(bm, 4) == 0)
196 #define _SHR_PBMP_BMEQ(bma, bmb) \
197  ((_SHR_PBMP_WORD_GET(bma, 0) == _SHR_PBMP_WORD_GET(bmb, 0)) && \
198  (_SHR_PBMP_WORD_GET(bma, 1) == _SHR_PBMP_WORD_GET(bmb, 1)) && \
199  (_SHR_PBMP_WORD_GET(bma, 2) == _SHR_PBMP_WORD_GET(bmb, 2)) && \
200  (_SHR_PBMP_WORD_GET(bma, 3) == _SHR_PBMP_WORD_GET(bmb, 3)) && \
201  (_SHR_PBMP_WORD_GET(bma, 4) == _SHR_PBMP_WORD_GET(bmb, 4)))
202 #define _SHR_PBMP_BMOP(bma, bmb, op) do { \
203  _SHR_PBMP_WORD_GET(bma, 0) op _SHR_PBMP_WORD_GET(bmb, 0); \
204  _SHR_PBMP_WORD_GET(bma, 1) op _SHR_PBMP_WORD_GET(bmb, 1); \
205  _SHR_PBMP_WORD_GET(bma, 2) op _SHR_PBMP_WORD_GET(bmb, 2); \
206  _SHR_PBMP_WORD_GET(bma, 3) op _SHR_PBMP_WORD_GET(bmb, 3); \
207  _SHR_PBMP_WORD_GET(bma, 4) op _SHR_PBMP_WORD_GET(bmb, 4); \
208  } while (0)
209 /* __doxy_func_body_end__ */
210 #define _SHR_PBMP_COUNT(bm, count) \
211  (count = _shr_popcount(_SHR_PBMP_WORD_GET(bm, 0)) + \
212  _shr_popcount(_SHR_PBMP_WORD_GET(bm, 1)) + \
213  _shr_popcount(_SHR_PBMP_WORD_GET(bm, 2)) + \
214  _shr_popcount(_SHR_PBMP_WORD_GET(bm, 3)) + \
215  _shr_popcount(_SHR_PBMP_WORD_GET(bm, 4)))
216 
217 #else /* _SHR_PBMP_WORD_MAX == 4 || > 5 */ /* 144 or > 160 bit maps */
218 
219 /* For use by pbmp.c */
220 #define _SHR_DEFINE_PBMP_FUNCTIONS
221 
222 extern int _shr_pbmp_bmnull(_shr_pbmp_t *);
223 extern int _shr_pbmp_bmeq(_shr_pbmp_t *, _shr_pbmp_t *);
224 
225 #define _SHR_PBMP_WENT(port) ((port)/_SHR_PBMP_WORD_WIDTH)
226 #define _SHR_PBMP_WBIT(port) (1U<<((port) % _SHR_PBMP_WORD_WIDTH))
227 
228 #define _SHR_PBMP_BMCLEAR(bm) do { \
229  int _w; \
230  for (_w = 0; _w < _SHR_PBMP_WORD_MAX; _w++) { \
231  _SHR_PBMP_WORD_GET(bm, _w) = 0; \
232  } \
233  } while (0)
234 /* __doxy_func_body_end__ */
235 #define _SHR_PBMP_BMNULL(bm) (_shr_pbmp_bmnull(&bm))
236 #define _SHR_PBMP_BMEQ(bma, bmb) (_shr_pbmp_bmeq(&bma, &bmb))
237 #define _SHR_PBMP_BMOP(bma, bmb, op) do { \
238  int _w; \
239  for (_w = 0; _w < _SHR_PBMP_WORD_MAX; _w++) { \
240  _SHR_PBMP_WORD_GET(bma, _w) op _SHR_PBMP_WORD_GET(bmb, _w); \
241  } \
242  } while (0)
243 /* __doxy_func_body_end__ */
244 #define _SHR_PBMP_COUNT(bm, count) do { \
245  int _w; \
246  count = 0; \
247  for (_w = 0; _w < _SHR_PBMP_WORD_MAX; _w++) { \
248  count += _shr_popcount(_SHR_PBMP_WORD_GET(bm, _w)); \
249  } \
250  } while(0)
251 /* __doxy_func_body_end__ */
252 
253 #endif /* _SHR_PBMP_WORD_MAX */
254 
255 /* generics that use the previously defined helpers */
256 #define _SHR_PBMP_CLEAR(bm) _SHR_PBMP_BMCLEAR(bm)
257 #define _SHR_PBMP_ITER(bm, port) \
258  for ((port) = 0; (port) < _SHR_PBMP_PORT_MAX; (port)++) \
259  if (_SHR_PBMP_MEMBER((bm), (port)))
260 
261 #define _SHR_PBMP_REVERSE_ITER(bm, port) \
262  for ((port) = _SHR_PBMP_PORT_MAX - 1; (port) > -1; (port)--) \
263  if (_SHR_PBMP_MEMBER((bm), (port)))
264 
265 #define _SHR_PBMP_IS_NULL(bm) (_SHR_PBMP_BMNULL(bm))
266 #define _SHR_PBMP_NOT_NULL(bm) (!_SHR_PBMP_BMNULL(bm))
267 #define _SHR_PBMP_EQ(bma, bmb) (_SHR_PBMP_BMEQ(bma, bmb))
268 #define _SHR_PBMP_NEQ(bma, bmb) (!_SHR_PBMP_BMEQ(bma, bmb))
269 
270 /* Assignment operators */
271 #define _SHR_PBMP_ASSIGN(dst, src) (dst) = (src)
272 #define _SHR_PBMP_AND(bma, bmb) _SHR_PBMP_BMOP(bma, bmb, &=)
273 #define _SHR_PBMP_OR(bma, bmb) _SHR_PBMP_BMOP(bma, bmb, |=)
274 #define _SHR_PBMP_XOR(bma, bmb) _SHR_PBMP_BMOP(bma, bmb, ^=)
275 #define _SHR_PBMP_REMOVE(bma, bmb) _SHR_PBMP_BMOP(bma, bmb, &= ~)
276 #define _SHR_PBMP_NEGATE(bma, bmb) _SHR_PBMP_BMOP(bma, bmb, = ~)
277 
278 /* Port PBMP operators */
279 #define _SHR_PBMP_FIRST(bm, first_port) \
280  do {\
281  _SHR_PBMP_ITER(bm, first_port) {break;} \
282  if (first_port == _SHR_PBMP_PORT_MAX) first_port = -1; \
283  } while(0)
284 /* __doxy_func_body_end__ */
285 
286 #define _SHR_PBMP_LAST(bm, last_port) \
287  do {\
288  _SHR_PBMP_REVERSE_ITER(bm, last_port) {break;} \
289  } while(0)
290 /* __doxy_func_body_end__ */
291 
292 
293 #define _SHR_PBMP_ENTRY(bm, port) \
294  (_SHR_PBMP_WORD_GET(bm,_SHR_PBMP_WENT(port)))
295 #define _SHR_PBMP_MEMBER(bm, port) \
296  ((_SHR_PBMP_ENTRY(bm, port) & _SHR_PBMP_WBIT(port)) != 0)
297 #define _SHR_PBMP_PORT_SET(bm, port) do { \
298  _SHR_PBMP_CLEAR(bm); \
299  _SHR_PBMP_PORT_ADD(bm, port); \
300  } while(0)
301 /* __doxy_func_body_end__ */
302 #define _SHR_PBMP_PORT_ADD(bm, port) \
303  (_SHR_PBMP_ENTRY(bm, port) |= _SHR_PBMP_WBIT(port))
304 #define _SHR_PBMP_PORT_REMOVE(bm, port) \
305  (_SHR_PBMP_ENTRY(bm, port) &= ~_SHR_PBMP_WBIT(port))
306 #define _SHR_PBMP_PORT_FLIP(bm, port) \
307  (_SHR_PBMP_ENTRY(bm, port) ^= _SHR_PBMP_WBIT(port))
308 extern char *_shr_pbmp_format(_shr_pbmp_t, char *);
309 #define _SHR_PBMP_FMT(bm, buf) _shr_pbmp_format(bm, buf)
310 #define _SHR_PBMP_FMT_LEN ((_SHR_PBMP_WORD_MAX*8)+3)
311 
312 #define _SHR_PBMP_PORT_VALID(p) ((p) >= 0 && (p) < _SHR_PBMP_PORT_MAX)
313 
314 #endif /* !_SHR_PBMP_H */