Initial commit of vpp code.
[vpp.git] / vppinfra / vppinfra / test_vec.h
1 /*
2  * Copyright (c) 2015 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 /*
16   Copyright (c) 2001, 2002, 2003 Eliot Dresselhaus
17
18   Permission is hereby granted, free of charge, to any person obtaining
19   a copy of this software and associated documentation files (the
20   "Software"), to deal in the Software without restriction, including
21   without limitation the rights to use, copy, modify, merge, publish,
22   distribute, sublicense, and/or sell copies of the Software, and to
23   permit persons to whom the Software is furnished to do so, subject to
24   the following conditions:
25
26   The above copyright notice and this permission notice shall be
27   included in all copies or substantial portions of the Software.
28
29   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
30   EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
31   MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
32   NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
33   LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
34   OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
35   WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 */
37
38 #ifndef included_test_vec_h
39 #define included_test_vec_h
40
41
42 #include <vppinfra/clib.h>
43 #include <vppinfra/mem.h>
44 #include <vppinfra/format.h>
45 #include <vppinfra/error.h>
46
47
48 extern uword g_verbose;
49 extern u32 g_seed;
50
51 always_inline u8 * format_u32_binary (u8 * s, va_list * va)
52 {
53     u32 val = va_arg (*va, u32);
54     word i = 0;
55     
56     for (i = BITS (val) - 1; i >= 0; i--)
57       {
58         if (val & (1 << i))
59           s = format (s, "1");
60         else
61           s = format (s, "0");
62       }
63     
64     return s;
65 }
66
67 #define VERBOSE1(fmt, args...)                  \
68 do {                                            \
69   if (g_verbose >= 1)                           \
70     fformat (stdout, fmt, ## args);             \
71 } while (0)
72
73 #define VERBOSE2(fmt, args...)                  \
74 do {                                            \
75   if (g_verbose >= 2)                           \
76     fformat (stdout, fmt, ## args);             \
77 } while (0)
78
79 #define VERBOSE3(fmt, args...)                  \
80 do {                                            \
81   if (g_verbose >= 3)                           \
82     fformat (stdout, fmt, ## args);             \
83 } while (0)
84
85 #define clib_mem_free_safe(p)                   \
86 do {                                            \
87   if (p)                                        \
88     {                                           \
89       clib_mem_free (p);                        \
90       (p) = NULL;                               \
91     }                                           \
92 } while (0)
93
94 /* XXX - I get undefined symbol trying to call random_u32() <vppinfra/random.h> */
95 /* Simple random number generator with period 2^31 - 1. */
96 static u32 my_random_u32 (u32 * seed_return)
97 {
98   /* Unlikely mask value to XOR into seed.
99      Otherwise small seed values would give
100      non-random seeming smallish numbers. */
101   const u32 mask = 0x12345678;
102   u32 seed, a, b, result;
103
104   seed = *seed_return;
105   seed ^= mask;
106
107   a = seed / 127773;
108   b = seed % 127773;
109   seed = 16807 * b - 2836 * a;
110
111   if ((i32) seed < 0)
112     seed += ((u32) 1 << 31) - 1;
113
114   result = seed;
115
116   *seed_return = seed ^ mask;
117
118   return result;
119 }
120
121 static u32 bounded_random_u32 (u32 * seed, uword lo, uword hi)
122 {
123   if (lo == hi)
124     return lo;
125
126   ASSERT (lo < hi);
127
128   return ((my_random_u32 (seed) % (hi - lo + ((hi != ~0) ? (1) : (0)))) + lo); 
129 }
130
131 #define fill_with_random_data(ptr, bytes, seed)                 \
132 do {                                                            \
133   u8 * _v(p) = (u8 *) (ptr);                                    \
134   uword _v(b) = (bytes);                                        \
135   uword _v(i);                                                  \
136                                                                 \
137   for (_v(i) = 0; _v(i) < _v(b); _v(i)++)                       \
138     _v(p)[_v(i)] = (u8) bounded_random_u32 (&(seed), 0, 255);   \
139                                                                 \
140 } while (0)
141
142 #define compute_mem_hash(hash, ptr, bytes)      \
143 ({                                              \
144   u8 * _v(p) = (u8 *) (ptr);                    \
145   uword _v(b) = (uword) (bytes);                \
146   uword _v(i);                                  \
147   uword _v(h) = (u8) (hash);                    \
148                                                 \
149   if (_v(p) && _v(b) > 0)                       \
150     {                                           \
151       for (_v(i) = 0; _v(i) < _v(b); _v(i)++)   \
152         _v(h) ^= _v(p)[_v(i)];                  \
153     }                                           \
154                                                 \
155   _v(h);                                        \
156 })
157
158 #define log2_align_down(value, align)           \
159 ({                                              \
160   uword _v = (uword) (value);                   \
161   uword _a = (uword) (align);                   \
162   uword _m = (1 << _a) - 1;                     \
163                                                 \
164   _v = _v & ~_m;                                \
165 })
166
167 #define log2_align_up(value, align)             \
168 ({                                              \
169   uword _v = (uword) (value);                   \
170   uword _a = (uword) (align);                   \
171   uword _m = (1 << _a) - 1;                     \
172                                                 \
173   _v = (_v + _m) & ~_m;                         \
174 })
175
176 #define log2_align_ptr_down(ptr, align) \
177 uword_to_pointer (log2_align_down (pointer_to_uword (ptr), align), void *)
178
179 #define log2_align_ptr_up(ptr, align) \
180 uword_to_pointer (log2_align_up (pointer_to_uword (ptr), align), void *)
181
182 #define MAX_LOG2_ALIGN          6
183 #define MAX_UNALIGN_OFFSET      ((1 << MAX_LOG2_ALIGN) - 1)
184
185 /* Allocates pointer to memory whose address is:
186    addr = <log2_align>-aligned address */
187 always_inline void * alloc_aligned (uword size, uword log2_align, void ** ptr_to_free)
188 {
189   void * p;
190   
191   if (size <= 0)
192     return NULL;
193   
194   p = (void *) clib_mem_alloc (size + (1 << log2_align) - 1);
195   
196   if (ptr_to_free)
197     *ptr_to_free = p;
198
199   return (p) ? log2_align_ptr_up (p, log2_align) : (NULL);
200 }
201
202 /* Allocates pointer to memory whose address is:
203    addr = MAX_LOG2_ALIGN-aligned address + <offset> */
204 always_inline void * alloc_unaligned (uword size, uword offset, void ** ptr_to_free)
205 {
206   void * p;
207
208   if (size <= 0)
209     return NULL;
210
211   ASSERT (offset <= MAX_UNALIGN_OFFSET);
212
213   p = alloc_aligned (size + (1 << MAX_LOG2_ALIGN), MAX_LOG2_ALIGN, ptr_to_free);
214
215   if (! p)
216     return NULL;
217
218   return (void *) ((u8 *) p + (offset % MAX_UNALIGN_OFFSET));
219 }
220
221 #define memory_snap()                                           \
222 do {                                                            \
223   clib_mem_usage_t _usage = { 0 };                              \
224   clib_mem_usage (&_usage);                                     \
225   fformat (stdout, "%U\n", format_clib_mem_usage, _usage, 0);   \
226 } while (0)
227
228
229 #endif /* included_test_vec_h */