openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

pbmp.h (15538B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * Port Bitmap Macros
      8  */
      9 
     10 #ifndef _SHR_PBMP_H
     11 #define _SHR_PBMP_H
     12 
     13 #include <shared/types.h>
     14 
     15 /*
     16  * Port Bitmap Macros
     17  *
     18  * These macros are never used directly (well, except in the C code
     19  * support routines that are used to help implement the macros).
     20  * For many macro here, there are BCM_* and SOC_* versions that are
     21  * defined in <bcm/types.h> and <soc/types.h>. SDK and customer code
     22  * should use those macros, not these.
     23  *
     24  * This header requires that the uint32 type be defined before inclusion.
     25  * Using <sal/types.h> is the simplest (and recommended) way of doing
     26  * this.
     27  *
     28  * There following macros are made available.  All have names starting
     29  * with _SHR_, which have been elided from this list:
     30  *
     31  * Constants or Expressions suitable for assignment:
     32  * PBMP_PORT_MAX		the maximum number of ports supported
     33  * PBMP_WORD_MAX		the maximum number of words in a bitmap
     34  * PBMP_WORD_GET(b, w)		return word w (0..WORD_MAX-1) from bitmap b
     35  * PBMP_FMT_LEN			length of char[] array for PBMP_FMT
     36  * PBMP_FMT(b,s)		%s'able format of bitmap b into string s
     37  *				returns s
     38  *
     39  * Predicates: (return 0 or 1, suitable for using in if statements)
     40  * PBMP_MEMBER(b, p)		is port p a member of bitmap b?
     41  * PBMP_IS_NULL(b)		is bitmap b empty?
     42  * PBMP_NOT_NULL(b)		is bitmap b not empty?
     43  * PBMP_EQ(b1, b2)		are bitmaps b1 and b2 equal?
     44  * PBMP_NEQ(b1, b2)		are bitmaps b1 and b2 not equal?
     45  * PBMP_PORT_VALID(p)		is p a valid port number? (0..PORT_MAX)
     46  *
     47  * Statements: (cannot be used as a predicate)
     48  * PBMP_CLEAR(b)		zero out a bitmap
     49  * PBMP_COUNT(b, c)		store how many bits are on in b into integer c
     50  * PBMP_ITER(b, p) {...}	iterate over bitmap b, setting p to each bit
     51  * PBMP_ASSIGN(b1, b2)		copy bitmap b2 into b1
     52  * PBMP_AND(b1, b2)		and bitmap b2 into b1
     53  * PBMP_OR(b1, b2)		or bitmap b2 into b1
     54  * PBMP_XOR(b1, b2)		exclusive or bitmap b2 into b1
     55  * PBMP_REMOVE(b1, b2)		remove bits in bitmap b2 from b1
     56  * PBMP_NEGATE(b1, b2)		copy the bitwise negation of bitmap b2 into b1
     57  * PBMP_PORT_SET(b, p)		clear bitmap b, then turn bit p on
     58  * PBMP_PORT_ADD(b, p)		turn bit p on in bitmap b
     59  * PBMP_PORT_REMOVE(b, p)	turn bit p off in bitmap b
     60  * PBMP_PORT_FLIP(b, p)		flip the sense of bit p on in bitmap b
     61  * PBMP_WORD_SET(b, w, v)	set word w (0..WORD_MAX-1) from bitmap b to v
     62  *
     63  * Internal forms: (should not be used outside of this header file)
     64  * PBMP_WENT(p)			word index for bit p
     65  * PBMP_WBIT(p)			word bitmask for bit p
     66  * PBMP_BMCLEAR(b)		clear a bitmap
     67  * PBMP_BMNULL(b)		is bitmap b empty?
     68  * PBMP_BMEQ(b1, b2)		are bitmaps b1 and b2 equal?
     69  * PBMP_BMOP(b1, b2, op)	execute op on a word basis on bitmaps b1, b2
     70  * PBMP_ENTRY(b, p)		the word of bitmap b that holds bit p
     71  *
     72  * There are 4 styles of implementation for the bitmap macros supported:
     73  * 1. The historic single uint32 implementation (-D_SHR_PBMP_WIDTH=0)
     74  *    This is expected to be removed after a decent time of mourning.
     75  * 2. An array of a single uint32 in a struct (-D_SHR_PBMP_WIDTH=32,
     76  *    the default).  Macros are special cased to handle this efficiently.
     77  * 3. An array of two uint32 in a struct (-D_SHR_PBMP_WIDTH=64, used
     78  *    when BCM_TUCANA_SUPPORT is defined).  Macros are again special
     79  *    cased for efficiency.
     80  * 4. An array of more than two uint32 in a struct (-D_SHR_PBMP_WIDTH=256
     81  *    for example).  Most things are done inline, with a couple of helper
     82  *    functions used to implement some macros.
     83  */
     84 
     85 #ifndef	_SHR_PBMP_WIDTH
     86 /*
     87  * Could get this from <soc/mcm/allenum.h> (SOC_MAX_NUM_PORTS)
     88  * but that makes every file include allenum.h and grow somewhat
     89  * large...
     90  */
     91 #ifdef	BCM_ESW_SUPPORT
     92 #define	_SHR_PBMP_PORT_MAX	256
     93 #else
     94 #define	_SHR_PBMP_PORT_MAX      64
     95 #endif  /* BCM_ESW_SUPPORT */
     96 
     97 #ifdef BCM_PETRA_SUPPORT
     98 #if 571 > _SHR_PBMP_PORT_MAX
     99 #undef   _SHR_PBMP_PORT_MAX
    100 #define  _SHR_PBMP_PORT_MAX 571
    101 #endif
    102 #endif /* BCM_PETRA_SUPPORT */
    103 
    104 #ifdef BCM_DNX_SUPPORT
    105 #if 624 > _SHR_PBMP_PORT_MAX
    106 #undef   _SHR_PBMP_PORT_MAX
    107 #define  _SHR_PBMP_PORT_MAX 624
    108 #endif
    109 #endif /* BCM_PETRA_SUPPORT */
    110 #ifdef BCM_DFE_SUPPORT
    111 #if 145 > _SHR_PBMP_PORT_MAX
    112 #undef   _SHR_PBMP_PORT_MAX
    113 #define  _SHR_PBMP_PORT_MAX 145
    114 #endif
    115 #endif /* BCM_DFE_SUPPORT */
    116 
    117 #ifdef BCM_DNXF_SUPPORT
    118 #if 193 > _SHR_PBMP_PORT_MAX
    119 #undef _SHR_PBMP_PORT_MAX
    120 #define _SHR_PBMP_PORT_MAX 193
    121 #endif
    122 #endif /* BCM_DNXF_SUPPORT */
    123 
    124 #define	_SHR_PBMP_WIDTH		(((_SHR_PBMP_PORT_MAX + 32 - 1)/32)*32)
    125 #endif
    126 
    127 #if _SHR_PBMP_WIDTH == 0		/* old style */
    128 typedef uint32 _shr_pbmp_t;
    129 
    130 #ifndef	_SHR_PBMP_PORT_MAX
    131 #define	_SHR_PBMP_PORT_MAX		32
    132 #endif
    133 #define	_SHR_PBMP_WORD_MAX		1
    134 #define	_SHR_PBMP_WBIT(port)		(1U<<(port))
    135 #define	_SHR_PBMP_WORD_GET(pbm, word)	(pbm)
    136 #define	_SHR_PBMP_WORD_SET(pbm, word, val)	((pbm) = (val))
    137 
    138 #define _SHR_PBMP_CLEAR(pbm)		((pbm) = 0)
    139 #define _SHR_PBMP_MEMBER(bmp, port)	(((bmp) & _SHR_PBMP_WBIT(port)) != 0)
    140 #define	_SHR_PBMP_COUNT(bmp, count)	(count = _shr_popcount(bmp))
    141 #define _SHR_PBMP_ITER(bmp, port) \
    142         for ((port) = 0; (port) < 32; (port)++) \
    143             if (_SHR_PBMP_MEMBER((bmp), (port)))
    144 
    145 #define _SHR_PBMP_REVERSE_ITER(bmp, port) \
    146         for ((port) = 31; (port) > -1; (port)--) \
    147             if (_SHR_PBMP_MEMBER((bmp), (port)))
    148 
    149 #define _SHR_PBMP_IS_NULL(pbm)           ((pbm) == 0)
    150 #define _SHR_PBMP_NOT_NULL(pbm)          ((pbm) != 0)
    151 #define _SHR_PBMP_EQ(pbm_a, pbm_b)       ((pbm_a) == (pbm_b))
    152 #define _SHR_PBMP_NEQ(pbm_a, pbm_b)      ((pbm_a) != (pbm_b))
    153 
    154 /* Assignment operators */
    155 #define _SHR_PBMP_ASSIGN(dst, src)       (dst) = (src)
    156 #define _SHR_PBMP_AND(pbm_a, pbm_b)      ((pbm_a) &= (pbm_b))
    157 #define _SHR_PBMP_OR(pbm_a, pbm_b)       ((pbm_a) |= (pbm_b))
    158 #define _SHR_PBMP_XOR(pbm_a, pbm_b)      ((pbm_a) ^= (pbm_b))
    159 #define _SHR_PBMP_REMOVE(pbm_a, pbm_b)   ((pbm_a) &= ~(pbm_b))
    160 #define _SHR_PBMP_NEGATE(pbm_a, pbm_b)   ((pbm_a) = ~(pbm_b))
    161 
    162 /* Port PBMP operators */
    163 #define _SHR_PBMP_PORT_SET(pbm, port)    ((pbm) = (1U << (port)))
    164 #define _SHR_PBMP_PORT_ADD(pbm, port)    ((pbm) |= (1U << (port)))
    165 #define _SHR_PBMP_PORT_REMOVE(pbm, port) ((pbm) &= ~(1U << (port)))
    166 #define _SHR_PBMP_PORT_FLIP(pbm, port)	 ((pbm) ^= (1U << (port)))
    167 
    168 #define _SHR_PBMP_PORTS_RANGE_ADD(bm, first_port, range) \
    169     do {\
    170         uint32 _mask_ = ~0;\
    171         _mask_ >>= (_SHR_PBMP_PORT_MAX - _range_);\
    172         _mask_ <<= (_first_port_ % _SHR_PBMP_WORD_WIDTH);\
    173         _SHR_PBMP_ENTRY(bm, _first_port_) |= _mask_; \
    174     } while (0); 
    175 
    176 #else	/* _SHR_PBMP_WIDTH == 0 */
    177 
    178 #ifndef	_SHR_PBMP_PORT_MAX
    179 #define	_SHR_PBMP_PORT_MAX		_SHR_PBMP_WIDTH
    180 #endif
    181 #define	_SHR_PBMP_WORD_WIDTH		32
    182 #define	_SHR_PBMP_WORD_MAX		\
    183 	((_SHR_PBMP_WIDTH + _SHR_PBMP_WORD_WIDTH-1) / _SHR_PBMP_WORD_WIDTH)
    184 
    185 typedef struct _shr_pbmp {
    186 	uint32	pbits[_SHR_PBMP_WORD_MAX];
    187 } _shr_pbmp_t;
    188 
    189 #define	_SHR_PBMP_WORD_GET(bm, word)		((bm).pbits[(word)])
    190 #define	_SHR_PBMP_WORD_SET(bm, word, val)	((bm).pbits[(word)] = (val))
    191 
    192 /*
    193  * Common cases are one word (1..32 ports) and two words (33..64 ports).
    194  * If not the common cases, more complicated code is generated using helper
    195  * functions.
    196  */
    197 #if	_SHR_PBMP_WORD_MAX == 1		/* 32 bit maps */
    198 #define	_SHR_PBMP_WENT(port)		(0)
    199 #define	_SHR_PBMP_WBIT(port)		(1U<<(port))
    200 
    201 /* helper defines used in the generic section below */
    202 #define _SHR_PBMP_BMCLEAR(bm)		(_SHR_PBMP_WORD_GET(bm, 0) = 0)
    203 #define _SHR_PBMP_BMNULL(bm)		(_SHR_PBMP_WORD_GET(bm, 0) == 0)
    204 #define _SHR_PBMP_BMEQ(bma, bmb)	\
    205 	(_SHR_PBMP_WORD_GET(bma, 0) == _SHR_PBMP_WORD_GET(bmb, 0))
    206 #define _SHR_PBMP_BMOP(bma, bmb, op)	do { \
    207 		_SHR_PBMP_WORD_GET(bma, 0) op _SHR_PBMP_WORD_GET(bmb, 0); \
    208 	} while (0)
    209 #define	_SHR_PBMP_COUNT(bm, count)	\
    210 	(count = _shr_popcount(_SHR_PBMP_WORD_GET(bm, 0)))
    211 
    212 #elif	_SHR_PBMP_WORD_MAX == 2		/* 64 bit maps */
    213 #define	_SHR_PBMP_WENT(port)		((port)/_SHR_PBMP_WORD_WIDTH)
    214 #define	_SHR_PBMP_WBIT(port)		(1U<<((port) % _SHR_PBMP_WORD_WIDTH))
    215 
    216 #define _SHR_PBMP_BMCLEAR(bm)		\
    217 	(_SHR_PBMP_WORD_GET(bm, 0) = _SHR_PBMP_WORD_GET(bm, 1) = 0)
    218 #define _SHR_PBMP_BMNULL(bm)		\
    219 	(_SHR_PBMP_WORD_GET(bm, 0) == 0 && _SHR_PBMP_WORD_GET(bm, 1) == 0)
    220 #define _SHR_PBMP_BMEQ(bma, bmb)	\
    221 	((_SHR_PBMP_WORD_GET(bma, 0) == _SHR_PBMP_WORD_GET(bmb, 0)) && \
    222 	 (_SHR_PBMP_WORD_GET(bma, 1) == _SHR_PBMP_WORD_GET(bmb, 1)))
    223 #define _SHR_PBMP_BMOP(bma, bmb, op)	do { \
    224 	_SHR_PBMP_WORD_GET(bma, 0) op _SHR_PBMP_WORD_GET(bmb, 0); \
    225 	_SHR_PBMP_WORD_GET(bma, 1) op _SHR_PBMP_WORD_GET(bmb, 1); \
    226 	} while (0)
    227 #define	_SHR_PBMP_COUNT(bm, count)	\
    228 	(count = _shr_popcount(_SHR_PBMP_WORD_GET(bm, 0)) + \
    229 		 _shr_popcount(_SHR_PBMP_WORD_GET(bm, 1)))
    230 
    231 #elif	_SHR_PBMP_WORD_MAX == 3		/* 96 bit maps */
    232 #define	_SHR_PBMP_WENT(port)		((port)/_SHR_PBMP_WORD_WIDTH)
    233 #define	_SHR_PBMP_WBIT(port)		(1U << ((port) % _SHR_PBMP_WORD_WIDTH))
    234 
    235 #define _SHR_PBMP_BMCLEAR(bm)		\
    236 	(_SHR_PBMP_WORD_GET(bm, 0) = _SHR_PBMP_WORD_GET(bm, 1) = \
    237          _SHR_PBMP_WORD_GET(bm, 2) = 0)
    238 #define _SHR_PBMP_BMNULL(bm)		\
    239 	(_SHR_PBMP_WORD_GET(bm, 0) == 0 && _SHR_PBMP_WORD_GET(bm, 1) == 0 && \
    240          _SHR_PBMP_WORD_GET(bm, 2) == 0)
    241 #define _SHR_PBMP_BMEQ(bma, bmb)	\
    242 	((_SHR_PBMP_WORD_GET(bma, 0) == _SHR_PBMP_WORD_GET(bmb, 0)) && \
    243 	 (_SHR_PBMP_WORD_GET(bma, 1) == _SHR_PBMP_WORD_GET(bmb, 1)) && \
    244 	 (_SHR_PBMP_WORD_GET(bma, 2) == _SHR_PBMP_WORD_GET(bmb, 2)))
    245 #define _SHR_PBMP_BMOP(bma, bmb, op)	do { \
    246 	_SHR_PBMP_WORD_GET(bma, 0) op _SHR_PBMP_WORD_GET(bmb, 0); \
    247 	_SHR_PBMP_WORD_GET(bma, 1) op _SHR_PBMP_WORD_GET(bmb, 1); \
    248 	_SHR_PBMP_WORD_GET(bma, 2) op _SHR_PBMP_WORD_GET(bmb, 2); \
    249 	} while (0)
    250 #define	_SHR_PBMP_COUNT(bm, count)	\
    251 	(count = _shr_popcount(_SHR_PBMP_WORD_GET(bm, 0)) + \
    252 		 _shr_popcount(_SHR_PBMP_WORD_GET(bm, 1)) + \
    253 		 _shr_popcount(_SHR_PBMP_WORD_GET(bm, 2)))
    254 
    255 #elif	_SHR_PBMP_WORD_MAX == 5		/* 160 bit maps */
    256 #define	_SHR_PBMP_WENT(port)		((port)/_SHR_PBMP_WORD_WIDTH)
    257 #define	_SHR_PBMP_WBIT(port)		(1U << ((port) % _SHR_PBMP_WORD_WIDTH))
    258 
    259 #define _SHR_PBMP_BMCLEAR(bm)		\
    260 	(_SHR_PBMP_WORD_GET(bm, 0) = _SHR_PBMP_WORD_GET(bm, 1) = \
    261 	 _SHR_PBMP_WORD_GET(bm, 2) = _SHR_PBMP_WORD_GET(bm, 3) = \
    262          _SHR_PBMP_WORD_GET(bm, 4) = 0)
    263 #define _SHR_PBMP_BMNULL(bm)		\
    264 	(_SHR_PBMP_WORD_GET(bm, 0) == 0 && _SHR_PBMP_WORD_GET(bm, 1) == 0 && \
    265          _SHR_PBMP_WORD_GET(bm, 2) == 0 && _SHR_PBMP_WORD_GET(bm, 3) == 0 && \
    266          _SHR_PBMP_WORD_GET(bm, 4) == 0)
    267 #define _SHR_PBMP_BMEQ(bma, bmb)	\
    268 	((_SHR_PBMP_WORD_GET(bma, 0) == _SHR_PBMP_WORD_GET(bmb, 0)) && \
    269 	 (_SHR_PBMP_WORD_GET(bma, 1) == _SHR_PBMP_WORD_GET(bmb, 1)) && \
    270 	 (_SHR_PBMP_WORD_GET(bma, 2) == _SHR_PBMP_WORD_GET(bmb, 2)) && \
    271 	 (_SHR_PBMP_WORD_GET(bma, 3) == _SHR_PBMP_WORD_GET(bmb, 3)) && \
    272 	 (_SHR_PBMP_WORD_GET(bma, 4) == _SHR_PBMP_WORD_GET(bmb, 4)))
    273 #define _SHR_PBMP_BMOP(bma, bmb, op)	do { \
    274 	_SHR_PBMP_WORD_GET(bma, 0) op _SHR_PBMP_WORD_GET(bmb, 0); \
    275 	_SHR_PBMP_WORD_GET(bma, 1) op _SHR_PBMP_WORD_GET(bmb, 1); \
    276 	_SHR_PBMP_WORD_GET(bma, 2) op _SHR_PBMP_WORD_GET(bmb, 2); \
    277 	_SHR_PBMP_WORD_GET(bma, 3) op _SHR_PBMP_WORD_GET(bmb, 3); \
    278 	_SHR_PBMP_WORD_GET(bma, 4) op _SHR_PBMP_WORD_GET(bmb, 4); \
    279 	} while (0)
    280 #define	_SHR_PBMP_COUNT(bm, count)	\
    281 	(count = _shr_popcount(_SHR_PBMP_WORD_GET(bm, 0)) + \
    282 		 _shr_popcount(_SHR_PBMP_WORD_GET(bm, 1)) + \
    283 		 _shr_popcount(_SHR_PBMP_WORD_GET(bm, 2)) + \
    284 		 _shr_popcount(_SHR_PBMP_WORD_GET(bm, 3)) + \
    285 		 _shr_popcount(_SHR_PBMP_WORD_GET(bm, 4)))
    286 
    287 #else	/* _SHR_PBMP_WORD_MAX == 4 || > 5 */	/* 144 or > 160 bit maps */
    288 
    289 /* For use by pbmp.c */
    290 #define _SHR_DEFINE_PBMP_FUNCTIONS
    291 
    292 extern int	_shr_pbmp_bmnull(_shr_pbmp_t *);
    293 extern int	_shr_pbmp_bmeq(_shr_pbmp_t *, _shr_pbmp_t *);
    294 
    295 #define	_SHR_PBMP_WENT(port)		((port)/_SHR_PBMP_WORD_WIDTH)
    296 #define	_SHR_PBMP_WBIT(port)		(1U<<((port) % _SHR_PBMP_WORD_WIDTH))
    297 
    298 #define _SHR_PBMP_BMCLEAR(bm)		do { \
    299 		int	_w; \
    300 		for (_w = 0; _w < _SHR_PBMP_WORD_MAX; _w++) { \
    301 			_SHR_PBMP_WORD_GET(bm, _w) = 0; \
    302 		} \
    303 	} while (0)
    304 #define _SHR_PBMP_BMNULL(bm)		(_shr_pbmp_bmnull(&bm))
    305 #define _SHR_PBMP_BMEQ(bma, bmb)	(_shr_pbmp_bmeq(&bma, &bmb))
    306 #define _SHR_PBMP_BMOP(bma, bmb, op)	do { \
    307 		int	_w; \
    308 		for (_w = 0; _w < _SHR_PBMP_WORD_MAX; _w++) { \
    309 			_SHR_PBMP_WORD_GET(bma, _w) op _SHR_PBMP_WORD_GET(bmb, _w); \
    310 		} \
    311 	} while (0)
    312 #define	_SHR_PBMP_COUNT(bm, count)	do { \
    313 		int	_w; \
    314 		count = 0; \
    315 		for (_w = 0; _w < _SHR_PBMP_WORD_MAX; _w++) { \
    316 			count += _shr_popcount(_SHR_PBMP_WORD_GET(bm, _w)); \
    317 		} \
    318 	} while(0)
    319 
    320 #endif	/* _SHR_PBMP_WORD_MAX */
    321 
    322 /* generics that use the previously defined helpers */
    323 #define _SHR_PBMP_CLEAR(bm)		_SHR_PBMP_BMCLEAR(bm)
    324 #define _SHR_PBMP_ITER(bm, port)	\
    325 	for ((port) = 0; (port) < _SHR_PBMP_PORT_MAX; (port)++) \
    326 		if (_SHR_PBMP_MEMBER((bm), (port)))
    327 
    328 #define _SHR_PBMP_REVERSE_ITER(bm, port)	\
    329 	for ((port) = _SHR_PBMP_PORT_MAX - 1; (port) > -1; (port)--) \
    330 		if (_SHR_PBMP_MEMBER((bm), (port)))
    331 
    332 #define _SHR_PBMP_IS_NULL(bm)		(_SHR_PBMP_BMNULL(bm))
    333 #define _SHR_PBMP_NOT_NULL(bm)		(!_SHR_PBMP_BMNULL(bm))
    334 #define _SHR_PBMP_EQ(bma, bmb)		(_SHR_PBMP_BMEQ(bma, bmb))
    335 #define _SHR_PBMP_NEQ(bma, bmb)		(!_SHR_PBMP_BMEQ(bma, bmb))
    336 
    337 /* Assignment operators */
    338 #define _SHR_PBMP_ASSIGN(dst, src)	(dst) = (src)
    339 #define _SHR_PBMP_AND(bma, bmb)		_SHR_PBMP_BMOP(bma, bmb, &=)
    340 #define _SHR_PBMP_OR(bma, bmb)		_SHR_PBMP_BMOP(bma, bmb, |=)
    341 #define _SHR_PBMP_XOR(bma, bmb)		_SHR_PBMP_BMOP(bma, bmb, ^=)
    342 #define _SHR_PBMP_REMOVE(bma, bmb)	_SHR_PBMP_BMOP(bma, bmb, &= ~)
    343 #define _SHR_PBMP_NEGATE(bma, bmb)	_SHR_PBMP_BMOP(bma, bmb, = ~)
    344 
    345 /* Port PBMP operators */
    346 #define	_SHR_PBMP_FIRST(bm, first_port)	\
    347     do {\
    348 	    _SHR_PBMP_ITER(bm, first_port) {break;} \
    349         if (first_port == _SHR_PBMP_PORT_MAX) first_port = -1; \
    350     } while(0)
    351 
    352 #define	_SHR_PBMP_LAST(bm, last_port)	\
    353     do {\
    354 	    _SHR_PBMP_REVERSE_ITER(bm, last_port) {break;} \
    355     } while(0)
    356 
    357     
    358 #define	_SHR_PBMP_ENTRY(bm, port)	\
    359 	(_SHR_PBMP_WORD_GET(bm,_SHR_PBMP_WENT(port)))
    360 #define _SHR_PBMP_MEMBER(bm, port)	\
    361 	((_SHR_PBMP_ENTRY(bm, port) & _SHR_PBMP_WBIT(port)) != 0)
    362 #define _SHR_PBMP_PORT_SET(bm, port)	do { \
    363 		_SHR_PBMP_CLEAR(bm); \
    364 		_SHR_PBMP_PORT_ADD(bm, port); \
    365 	} while(0)
    366 #define _SHR_PBMP_PORT_ADD(bm, port)	\
    367 	(_SHR_PBMP_ENTRY(bm, port) |= _SHR_PBMP_WBIT(port))
    368 #define _SHR_PBMP_PORT_REMOVE(bm, port)	\
    369 	(_SHR_PBMP_ENTRY(bm, port) &= ~_SHR_PBMP_WBIT(port))
    370 #define _SHR_PBMP_PORT_FLIP(bm, port)	\
    371 	(_SHR_PBMP_ENTRY(bm, port) ^= _SHR_PBMP_WBIT(port))
    372 
    373 #define _SHR_PBMP_PORTS_RANGE_ADD(bm, first_port, range) \
    374     do {\
    375         uint32 _mask_;\
    376         int _first_port_, _range_;\
    377         _first_port_ = first_port; _range_ = range;\
    378         while (_range_ > 0) {\
    379             _mask_ = ~0;\
    380             if (_range_ < _SHR_PBMP_WORD_WIDTH) _mask_ >>= (_SHR_PBMP_WORD_WIDTH - _range_);\
    381             _mask_ <<= (_first_port_ % _SHR_PBMP_WORD_WIDTH);\
    382             _SHR_PBMP_ENTRY(bm, _first_port_) |= _mask_; \
    383             _range_ += (_first_port_ % _SHR_PBMP_WORD_WIDTH) - _SHR_PBMP_WORD_WIDTH;\
    384             _first_port_ +=  _SHR_PBMP_WORD_WIDTH - (_first_port_ % _SHR_PBMP_WORD_WIDTH);\
    385         }\
    386     } while (0); 
    387         
    388 
    389 #endif	/* _SHR_PBMP_WIDTH == 0 */
    390 
    391 extern int _shr_pbmp_parse(char *s, _shr_pbmp_t *pbmp, uint32 *arr, uint8 *is_hex);
    392 extern char		*_shr_pbmp_format(_shr_pbmp_t, char *);
    393 char            *shr_pbmp_range_format(_shr_pbmp_t bmp, char *buf, int buf_size);
    394 extern int		_shr_pbmp_decode(char *, _shr_pbmp_t *);
    395 
    396 #define	_SHR_PBMP_FMT(bm, buf)		_shr_pbmp_format(bm, buf)
    397 #define	_SHR_PBMP_FMT_LEN		((_SHR_PBMP_WORD_MAX*8)+3)
    398 
    399 #define	_SHR_PBMP_PORT_VALID(p)		((p) >= 0 && (p) < _SHR_PBMP_PORT_MAX)
    400 
    401 #endif	/* !_SHR_PBMP_H */