]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - sys/dev/patm/genrtab/genrtab.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / sys / dev / patm / genrtab / genrtab.c
1 /*-
2  * Copyright (c) 2003
3  *      Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4  *      All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  * Author: Hartmut Brandt <harti@freebsd.org>
28  *
29  * This program is used to generate the different rate tables for the IDT77252
30  * driver. The generated tables are slightly different from those in the
31  * IDT manual.
32  */
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35
36 #include <sys/types.h>
37 #include <stdio.h>
38 #include <unistd.h>
39 #include <math.h>
40 #include <ieeefp.h>
41
42 /* verbosity flag */
43 static int verbose;
44
45 /* number of table entries */
46 static const u_int tsize = 256;
47
48 /* number of rate difference tables to create */
49 static const u_int ndtables = 16;
50
51 /* cell rate offset for log 0 */
52 static const double offset = 10.0;
53
54 /*
55  * Make an internal form of the interval and be sure to round down.
56  */
57 static u_int
58 d2interval(double d)
59 {
60         fp_rnd_t r;
61         u_int s, id;
62
63         r = fpsetround(FP_RZ);
64         id = (u_int)rint(32 * d);
65         fpsetround(r);
66
67         s = 0;
68         while (id >= 32 * 32) {
69                 s++;
70                 id >>= 1;
71         }
72         return ((s << 10) | (id));
73 }
74
75 /*
76  * Convert an internal interval back to a real one.
77  */
78 static double
79 interval2d(u_int id)
80 {
81         return ((1 << ((id >> 10) & 0xf)) * ((id & 0x3ff) / 32.0));
82 }
83
84 /*
85  * Convert double to ATM-Forum format. Make sure to round up.
86  */
87 static u_int
88 cps2atmf(double cps)
89 {
90         fp_rnd_t r;
91         u_int s, id;
92
93         if (cps < 1.0)
94                 return (0);
95
96         s = 0;
97         while (cps >= 2.0) {
98                 s++;
99                 cps /= 2;
100         }
101         r = fpsetround(FP_RP);
102         id = (u_int)rint(512 * cps);
103         fpsetround(r);
104
105         return ((1 << 14) | (s << 9) | (id & 0x1ff));
106 }
107
108 /*
109  * Convert ATM forum format to double
110  */
111 static double
112 atmf2cps(u_int atmf)
113 {
114         return (((atmf >> 14) & 1) * (1 << ((atmf >> 9) & 0x1f)) *
115             ((512 + (atmf & 0x1ff)) / 512.0));
116 }
117
118 /*
119  * A cell rate to the logarithmic one
120  */
121 static double
122 cps2log(u_int alink, double lg)
123 {
124         if (lg <= offset)
125                 return (0);
126         if (lg >= alink)
127                 return (tsize - 1);
128
129         return ((tsize - 1) * (1 - log(alink / lg) / log(alink / offset)));
130 }
131
132 /*
133  * Convert log to cell rate
134  */
135 static double
136 log2cps(u_int alink, u_int lg)
137 {
138         return (alink / pow(alink / offset,
139             (double)(tsize - lg - 1) / (tsize - 1)));
140 }
141
142 /*
143  * Convert a double to an internal scaled double
144  */
145 static u_int
146 d2ifp(double fp)
147 {
148         fp_rnd_t r;
149         u_int s, ifp;
150
151         fp *= (1 << 16);
152
153         r = fpsetround(FP_RN);
154         ifp = (u_int)rint(fp);
155         fpsetround(r);
156
157         s = 0;
158         while (ifp >= 1024) {
159                 s++;
160                 ifp >>= 1;
161         }
162         return ((s << 10) | (ifp));
163 }
164
165 /*
166  * Convert internal scaled float to double
167  */
168 static double
169 ifp2d(u_int p)
170 {
171         return ((p & 0x3ff) * (1 << ((p >> 10) & 0xf)) / 65536.0);
172 }
173
174 /*
175  * Generate log to rate conversion table
176  */
177 static void
178 gen_log2rate(u_int alink)
179 {
180         u_int i, iinterval, atmf, n, nrm;
181         double rate, interval, xinterval, cps, xcps;
182
183         for (i = 0; i < 256; i++) {
184                 /* get the desired rate */
185                 rate = alink / pow(alink / offset,
186                     (double)(tsize - i - 1) / (tsize - 1));
187
188                 /* convert this to an interval */
189                 interval = alink / rate;
190
191                 /* make the internal form of this interval, be sure to
192                  * round down */
193                 iinterval = d2interval(interval);
194
195                 /* now convert back */
196                 xinterval = interval2d(iinterval);
197
198                 /* make a cps from this interval */
199                 cps = alink / xinterval;
200
201                 /* convert this to its ATM forum format */
202                 atmf = cps2atmf(cps);
203
204                 /* and back */
205                 xcps = atmf2cps(atmf);
206
207                 /* decide on NRM */
208                 if (xcps < 40.0) {
209                         nrm = 0;
210                         n = 3;
211                 } else if (xcps < 80.0) {
212                         nrm = 1;
213                         n = 4;
214                 } else if (xcps < 160.0) {
215                         nrm = 2;
216                         n = 8;
217                 } else if (xcps < 320.0) {
218                         nrm = 3;
219                         n = 16;
220                 } else {
221                         nrm = 4;
222                         n = 32;
223                 }
224
225                 /* print */
226                 if (verbose)
227                         printf(" 0x%08x, /* %03u: cps=%f nrm=%u int=%f */\n",
228                             (atmf << 17) | (nrm << 14) | iinterval, i,
229                             xcps, n, xinterval);
230                 else
231                         printf("0x%08x,\n", (atmf << 17) | (nrm << 14) |
232                             iinterval);
233         }
234 }
235
236 /*
237  * Generate rate to log conversion table
238  */
239 static void
240 gen_rate2log(u_int alink)
241 {
242         u_int i, atmf, val, ilcr;
243         double cps, lcr;
244         fp_rnd_t r;
245
246         val = 0;
247         for (i = 0; i < 512; i++) {
248                 /* make ATM Forum CPS from index */
249                 atmf = (((i & 0x1f0) >> 4) << 9) |
250                     ((i & 0xf) << 5) | (1 << 14);
251
252                 /* make cps */
253                 cps = atmf2cps(atmf);
254
255                 /* convert to log */
256                 lcr = cps2log(alink, cps);
257
258                 r = fpsetround(FP_RN);
259                 ilcr = (u_int)rint(lcr);
260                 fpsetround(r);
261
262                 /* put together */
263                 val |= ilcr << (8 * (i % 4));
264
265                 /* print */
266                 if (i % 4 == 3) {
267                         if (verbose)
268                                 printf(" 0x%08x,\t", val);
269                         else
270                                 printf("0x%08x,\n", val);
271                         val = 0;
272                 } else if (verbose)
273                         printf("\t\t");
274                 if (verbose)
275                         printf("/* %03u: %f -> %f */\n", i,
276                             cps, log2cps(alink, ilcr));
277         }
278 }
279
280 /*
281  * Generate one entry into the global table
282  */
283 static void
284 gen_glob_entry(u_int alink, u_int fill, u_int ci, u_int ni)
285 {
286         if (verbose)
287                 printf("  0x%08x,       /* %2u/32 %8.6f, %6u, ci=%u, ni=%u */\n",
288                     cps2atmf(alink * fill / 32.0) | (ci << 17) | (ni << 16),
289                     fill, fill / 32.0, alink * fill / 32, ci, ni);
290         else
291                 printf("0x%08x,\n",
292                     cps2atmf(alink * fill / 32.0) | (ci << 17) | (ni << 16));
293 }
294
295 /*
296  * Generate global parameter table
297  */
298 static void
299 gen_glob(u_int alink)
300 {
301         u_int i;
302
303         gen_glob_entry(alink, 32, 0, 0);
304         gen_glob_entry(alink, 16, 0, 0);
305         gen_glob_entry(alink,  8, 0, 1);
306         gen_glob_entry(alink,  4, 0, 1);
307         gen_glob_entry(alink,  2, 1, 1);
308         gen_glob_entry(alink,  1, 1, 1);
309         gen_glob_entry(alink,  0, 1, 1);
310         gen_glob_entry(alink,  0, 1, 1);
311
312         for (i = 0; i < tsize/2 - 8; i++) {
313                 if (i % 16 == 0)
314                         printf(" ");
315                 printf(" 0,");
316                 if (i % 16 == 15)
317                         printf("\n");
318         }
319         printf("\n");
320 }
321
322 /*
323  * Generate additive rate increase tables
324  */
325 static void
326 gen_air(u_int alink)
327 {
328         u_int t, i;
329         double diff;    /* cell rate to increase by */
330         double cps;
331         double add;
332         u_int val, a;
333
334         for (t = 0; t < ndtables; t++) {
335                 diff = (double)alink / (1 << t);
336                 printf("/* AIR %u: diff=%f */\n", t, diff);
337                 val = 0;
338                 for (i = 0; i < tsize; i++) {
339                         cps = log2cps(alink, i);
340                         cps += diff;
341                         if (cps > alink)
342                                 cps = alink;
343
344                         add = cps2log(alink, cps) - i;
345
346                         a = d2ifp(add);
347
348                         if (i % 2) {
349                                 val |= a << 16;
350                                 if (verbose)
351                                         printf("  0x%08x,\t", val);
352                                 else
353                                         printf("0x%08x,\n", val);
354                         } else {
355                                 val = a;
356                                 if (verbose)
357                                         printf("\t\t");
358                         }
359                         if (verbose)
360                                 printf("/* %3u: %f */\n", i, ifp2d(add));
361                 }
362         }
363 }
364
365 /*
366  * Generate rate decrease table
367  */
368 static void
369 gen_rdf(u_int alink)
370 {
371         double d;
372         u_int t, i, f, val, diff;
373
374         for (t = 0; t < ndtables; t++) {
375                 /* compute the log index difference */
376                 if (t == 0) {
377                         d = tsize - 1;
378                 } else {
379                         f = 1 << t;
380                         d = (tsize - 1) / log(alink / offset);
381                         d *= log((double)f / (f - 1));
382                 }
383                 printf(" /* RDF %u: 1/%u: %f */\n", t, 1 << t, d);
384                 val = 0;
385                 for (i = 0; i < tsize; i++) {
386                         if (i < d)
387                                 diff = d2ifp(i);
388                         else
389                                 diff = d2ifp(d);
390                         if (i % 2) {
391                                 val |= diff << 16;
392                                 if (verbose)
393                                         printf("  0x%08x,\t", val);
394                                 else
395                                         printf("0x%08x,\n", val);
396                         } else {
397                                 val = diff;
398                                 if (verbose)
399                                         printf("\t\t");
400                         }
401                         if (verbose)
402                                 printf("/* %3u: %f */\n", i, ifp2d(diff));
403                 }
404         }
405 }
406
407 /*
408  * Create all the tables for a given link cell rate and link bit rate.
409  * The link bit rate is only used to name the table.
410  */
411 static void
412 gen_tables(u_int alink, u_int mbps)
413 {
414         printf("\n");
415         printf("/*\n");
416         printf(" * Tables for %ucps and %uMbps\n", alink, mbps);
417         printf(" */\n");
418         printf("const uint32_t patm_rtables%u[128 * (4 + 2 * %u)] = {\n",
419             mbps, ndtables);
420
421         gen_log2rate(alink);
422         gen_rate2log(alink);
423         gen_glob(alink);
424         gen_air(alink);
425         gen_rdf(alink);
426
427         printf("};\n");
428 }
429
430 int
431 main(int argc, char *argv[])
432 {
433         int opt;
434
435         while ((opt = getopt(argc, argv, "v")) != -1)
436                 switch (opt) {
437
438                   case 'v':
439                         verbose = 1;
440                         break;
441                 }
442
443         printf("/*\n");
444         printf(" * This file was generated by `%s'\n", argv[0]);
445         printf(" */\n");
446         printf("\n");
447         printf("#include <sys/cdefs.h>\n");
448         printf("__FBSDID(\"$FreeBSD$\");\n");
449         printf("\n");
450         printf("#include <sys/types.h>\n");
451         printf("\n");
452         printf("const u_int patm_rtables_size = 128 * (4 + 2 * %u);\n",
453             ndtables);
454         printf("const u_int patm_rtables_ntab = %u;\n", ndtables);
455         gen_tables(352768, 155);
456         gen_tables( 59259,  25);
457         return (0);
458 }