]>
Commit | Line | Data |
---|---|---|
bdc80787 PA |
1 | #!/usr/bin/perl |
2 | # ----------------------------------------------------------------------- | |
3 | # | |
b9095fd8 | 4 | # Copyright 2007-2008 rPath, Inc. - All Rights Reserved |
bdc80787 PA |
5 | # |
6 | # This file is part of the Linux kernel, and is made available under | |
7 | # the terms of the GNU General Public License version 2 or (at your | |
8 | # option) any later version; incorporated herein by reference. | |
9 | # | |
10 | # ----------------------------------------------------------------------- | |
11 | # | |
12 | ||
13 | # | |
14 | # Usage: timeconst.pl HZ > timeconst.h | |
15 | # | |
16 | ||
17 | # Precomputed values for systems without Math::BigInt | |
18 | # Generated by: | |
19 | # timeconst.pl --can 24 32 48 64 100 122 128 200 250 256 300 512 1000 1024 1200 | |
20 | %canned_values = ( | |
21 | 24 => [ | |
22 | '0xa6aaaaab','0x2aaaaaa',26, | |
bdc80787 PA |
23 | 125,3, |
24 | '0xc49ba5e4','0x1fbe76c8b4',37, | |
bdc80787 PA |
25 | 3,125, |
26 | '0xa2c2aaab','0xaaaa',16, | |
bdc80787 PA |
27 | 125000,3, |
28 | '0xc9539b89','0x7fffbce4217d',47, | |
bdc80787 PA |
29 | 3,125000, |
30 | ], 32 => [ | |
31 | '0xfa000000','0x6000000',27, | |
bdc80787 PA |
32 | 125,4, |
33 | '0x83126e98','0xfdf3b645a',36, | |
bdc80787 PA |
34 | 4,125, |
35 | '0xf4240000','0x0',17, | |
bdc80787 PA |
36 | 31250,1, |
37 | '0x8637bd06','0x3fff79c842fa',46, | |
bdc80787 PA |
38 | 1,31250, |
39 | ], 48 => [ | |
40 | '0xa6aaaaab','0x6aaaaaa',27, | |
bdc80787 PA |
41 | 125,6, |
42 | '0xc49ba5e4','0xfdf3b645a',36, | |
bdc80787 PA |
43 | 6,125, |
44 | '0xa2c2aaab','0x15555',17, | |
bdc80787 PA |
45 | 62500,3, |
46 | '0xc9539b89','0x3fffbce4217d',46, | |
bdc80787 PA |
47 | 3,62500, |
48 | ], 64 => [ | |
49 | '0xfa000000','0xe000000',28, | |
bdc80787 PA |
50 | 125,8, |
51 | '0x83126e98','0x7ef9db22d',35, | |
bdc80787 PA |
52 | 8,125, |
53 | '0xf4240000','0x0',18, | |
bdc80787 PA |
54 | 15625,1, |
55 | '0x8637bd06','0x1fff79c842fa',45, | |
bdc80787 PA |
56 | 1,15625, |
57 | ], 100 => [ | |
58 | '0xa0000000','0x0',28, | |
bdc80787 PA |
59 | 10,1, |
60 | '0xcccccccd','0x733333333',35, | |
bdc80787 PA |
61 | 1,10, |
62 | '0x9c400000','0x0',18, | |
bdc80787 PA |
63 | 10000,1, |
64 | '0xd1b71759','0x1fff2e48e8a7',45, | |
bdc80787 PA |
65 | 1,10000, |
66 | ], 122 => [ | |
67 | '0x8325c53f','0xfbcda3a',28, | |
bdc80787 PA |
68 | 500,61, |
69 | '0xf9db22d1','0x7fbe76c8b',35, | |
bdc80787 PA |
70 | 61,500, |
71 | '0x8012e2a0','0x3ef36',18, | |
bdc80787 PA |
72 | 500000,61, |
73 | '0xffda4053','0x1ffffbce4217',45, | |
bdc80787 PA |
74 | 61,500000, |
75 | ], 128 => [ | |
76 | '0xfa000000','0x1e000000',29, | |
bdc80787 PA |
77 | 125,16, |
78 | '0x83126e98','0x3f7ced916',34, | |
bdc80787 PA |
79 | 16,125, |
80 | '0xf4240000','0x40000',19, | |
bdc80787 PA |
81 | 15625,2, |
82 | '0x8637bd06','0xfffbce4217d',44, | |
bdc80787 PA |
83 | 2,15625, |
84 | ], 200 => [ | |
85 | '0xa0000000','0x0',29, | |
bdc80787 PA |
86 | 5,1, |
87 | '0xcccccccd','0x333333333',34, | |
bdc80787 PA |
88 | 1,5, |
89 | '0x9c400000','0x0',19, | |
bdc80787 PA |
90 | 5000,1, |
91 | '0xd1b71759','0xfff2e48e8a7',44, | |
bdc80787 PA |
92 | 1,5000, |
93 | ], 250 => [ | |
94 | '0x80000000','0x0',29, | |
bdc80787 PA |
95 | 4,1, |
96 | '0x80000000','0x180000000',33, | |
bdc80787 PA |
97 | 1,4, |
98 | '0xfa000000','0x0',20, | |
bdc80787 PA |
99 | 4000,1, |
100 | '0x83126e98','0x7ff7ced9168',43, | |
bdc80787 PA |
101 | 1,4000, |
102 | ], 256 => [ | |
103 | '0xfa000000','0x3e000000',30, | |
bdc80787 PA |
104 | 125,32, |
105 | '0x83126e98','0x1fbe76c8b',33, | |
bdc80787 PA |
106 | 32,125, |
107 | '0xf4240000','0xc0000',20, | |
bdc80787 PA |
108 | 15625,4, |
109 | '0x8637bd06','0x7ffde7210be',43, | |
bdc80787 PA |
110 | 4,15625, |
111 | ], 300 => [ | |
112 | '0xd5555556','0x2aaaaaaa',30, | |
bdc80787 PA |
113 | 10,3, |
114 | '0x9999999a','0x1cccccccc',33, | |
bdc80787 PA |
115 | 3,10, |
116 | '0xd0555556','0xaaaaa',20, | |
bdc80787 PA |
117 | 10000,3, |
118 | '0x9d495183','0x7ffcb923a29',43, | |
bdc80787 PA |
119 | 3,10000, |
120 | ], 512 => [ | |
121 | '0xfa000000','0x7e000000',31, | |
bdc80787 PA |
122 | 125,64, |
123 | '0x83126e98','0xfdf3b645',32, | |
bdc80787 PA |
124 | 64,125, |
125 | '0xf4240000','0x1c0000',21, | |
bdc80787 PA |
126 | 15625,8, |
127 | '0x8637bd06','0x3ffef39085f',42, | |
bdc80787 PA |
128 | 8,15625, |
129 | ], 1000 => [ | |
130 | '0x80000000','0x0',31, | |
bdc80787 PA |
131 | 1,1, |
132 | '0x80000000','0x0',31, | |
bdc80787 PA |
133 | 1,1, |
134 | '0xfa000000','0x0',22, | |
bdc80787 PA |
135 | 1000,1, |
136 | '0x83126e98','0x1ff7ced9168',41, | |
bdc80787 PA |
137 | 1,1000, |
138 | ], 1024 => [ | |
139 | '0xfa000000','0xfe000000',32, | |
bdc80787 PA |
140 | 125,128, |
141 | '0x83126e98','0x7ef9db22',31, | |
bdc80787 PA |
142 | 128,125, |
143 | '0xf4240000','0x3c0000',22, | |
bdc80787 PA |
144 | 15625,16, |
145 | '0x8637bd06','0x1fff79c842f',41, | |
bdc80787 PA |
146 | 16,15625, |
147 | ], 1200 => [ | |
148 | '0xd5555556','0xd5555555',32, | |
bdc80787 PA |
149 | 5,6, |
150 | '0x9999999a','0x66666666',31, | |
bdc80787 PA |
151 | 6,5, |
152 | '0xd0555556','0x2aaaaa',22, | |
bdc80787 PA |
153 | 2500,3, |
154 | '0x9d495183','0x1ffcb923a29',41, | |
bdc80787 PA |
155 | 3,2500, |
156 | ] | |
157 | ); | |
158 | ||
159 | $has_bigint = eval 'use Math::BigInt qw(bgcd); 1;'; | |
160 | ||
161 | sub bint($) | |
162 | { | |
163 | my($x) = @_; | |
164 | return Math::BigInt->new($x); | |
165 | } | |
166 | ||
167 | # | |
168 | # Constants for division by reciprocal multiplication. | |
169 | # (bits, numerator, denominator) | |
170 | # | |
171 | sub fmul($$$) | |
172 | { | |
173 | my ($b,$n,$d) = @_; | |
174 | ||
175 | $n = bint($n); | |
176 | $d = bint($d); | |
177 | ||
178 | return scalar (($n << $b)+$d-bint(1))/$d; | |
179 | } | |
180 | ||
181 | sub fadj($$$) | |
182 | { | |
183 | my($b,$n,$d) = @_; | |
184 | ||
185 | $n = bint($n); | |
186 | $d = bint($d); | |
187 | ||
188 | $d = $d/bgcd($n, $d); | |
189 | return scalar (($d-bint(1)) << $b)/$d; | |
190 | } | |
191 | ||
192 | sub fmuls($$$) { | |
193 | my($b,$n,$d) = @_; | |
194 | my($s,$m); | |
195 | my($thres) = bint(1) << ($b-1); | |
196 | ||
197 | $n = bint($n); | |
198 | $d = bint($d); | |
199 | ||
200 | for ($s = 0; 1; $s++) { | |
201 | $m = fmul($s,$n,$d); | |
202 | return $s if ($m >= $thres); | |
203 | } | |
204 | return 0; | |
205 | } | |
206 | ||
b9095fd8 PA |
207 | # Generate a hex value if the result fits in 64 bits; |
208 | # otherwise skip. | |
209 | sub bignum_hex($) { | |
210 | my($x) = @_; | |
211 | my $s = $x->as_hex(); | |
212 | ||
213 | return (length($s) > 18) ? undef : $s; | |
214 | } | |
215 | ||
bdc80787 PA |
216 | # Provides mul, adj, and shr factors for a specific |
217 | # (bit, time, hz) combination | |
218 | sub muladj($$$) { | |
219 | my($b, $t, $hz) = @_; | |
220 | my $s = fmuls($b, $t, $hz); | |
221 | my $m = fmul($s, $t, $hz); | |
222 | my $a = fadj($s, $t, $hz); | |
b9095fd8 | 223 | return (bignum_hex($m), bignum_hex($a), $s); |
bdc80787 PA |
224 | } |
225 | ||
226 | # Provides numerator, denominator values | |
227 | sub numden($$) { | |
228 | my($n, $d) = @_; | |
229 | my $g = bgcd($n, $d); | |
230 | return ($n/$g, $d/$g); | |
231 | } | |
232 | ||
233 | # All values for a specific (time, hz) combo | |
234 | sub conversions($$) { | |
235 | my ($t, $hz) = @_; | |
236 | my @val = (); | |
237 | ||
238 | # HZ_TO_xx | |
239 | push(@val, muladj(32, $t, $hz)); | |
bdc80787 PA |
240 | push(@val, numden($t, $hz)); |
241 | ||
242 | # xx_TO_HZ | |
243 | push(@val, muladj(32, $hz, $t)); | |
bdc80787 PA |
244 | push(@val, numden($hz, $t)); |
245 | ||
246 | return @val; | |
247 | } | |
248 | ||
249 | sub compute_values($) { | |
250 | my($hz) = @_; | |
251 | my @val = (); | |
252 | my $s, $m, $a, $g; | |
253 | ||
254 | if (!$has_bigint) { | |
255 | die "$0: HZ == $hz not canned and ". | |
256 | "Math::BigInt not available\n"; | |
257 | } | |
258 | ||
259 | # MSEC conversions | |
260 | push(@val, conversions(1000, $hz)); | |
261 | ||
262 | # USEC conversions | |
263 | push(@val, conversions(1000000, $hz)); | |
264 | ||
265 | return @val; | |
266 | } | |
267 | ||
b9095fd8 PA |
268 | sub outputval($$) |
269 | { | |
270 | my($name, $val) = @_; | |
271 | my $csuf; | |
272 | ||
273 | if (defined($val)) { | |
274 | if ($name !~ /SHR/) { | |
275 | $val = "U64_C($val)"; | |
276 | } | |
277 | printf "#define %-23s %s\n", $name.$csuf, $val.$csuf; | |
278 | } | |
279 | } | |
280 | ||
bdc80787 PA |
281 | sub output($@) |
282 | { | |
283 | my($hz, @val) = @_; | |
284 | my $pfx, $bit, $suf, $s, $m, $a; | |
285 | ||
286 | print "/* Automatically generated by kernel/timeconst.pl */\n"; | |
287 | print "/* Conversion constants for HZ == $hz */\n"; | |
288 | print "\n"; | |
289 | print "#ifndef KERNEL_TIMECONST_H\n"; | |
290 | print "#define KERNEL_TIMECONST_H\n"; | |
291 | print "\n"; | |
292 | ||
293 | print "#include <linux/param.h>\n"; | |
b9095fd8 | 294 | print "#include <linux/types.h>\n"; |
bdc80787 PA |
295 | |
296 | print "\n"; | |
297 | print "#if HZ != $hz\n"; | |
298 | print "#error \"kernel/timeconst.h has the wrong HZ value!\"\n"; | |
299 | print "#endif\n"; | |
300 | print "\n"; | |
301 | ||
302 | foreach $pfx ('HZ_TO_MSEC','MSEC_TO_HZ', | |
c98aa86d | 303 | 'HZ_TO_USEC','USEC_TO_HZ') { |
b9095fd8 | 304 | foreach $bit (32) { |
bdc80787 | 305 | foreach $suf ('MUL', 'ADJ', 'SHR') { |
b9095fd8 | 306 | outputval("${pfx}_$suf$bit", shift(@val)); |
bdc80787 PA |
307 | } |
308 | } | |
309 | foreach $suf ('NUM', 'DEN') { | |
b9095fd8 | 310 | outputval("${pfx}_$suf", shift(@val)); |
bdc80787 PA |
311 | } |
312 | } | |
313 | ||
314 | print "\n"; | |
315 | print "#endif /* KERNEL_TIMECONST_H */\n"; | |
316 | } | |
317 | ||
b9095fd8 PA |
318 | # Pretty-print Perl values |
319 | sub perlvals(@) { | |
320 | my $v; | |
321 | my @l = (); | |
322 | ||
323 | foreach $v (@_) { | |
324 | if (!defined($v)) { | |
325 | push(@l, 'undef'); | |
326 | } elsif ($v =~ /^0x/) { | |
327 | push(@l, "\'".$v."\'"); | |
328 | } else { | |
329 | push(@l, $v.''); | |
330 | } | |
331 | } | |
332 | return join(',', @l); | |
333 | } | |
334 | ||
bdc80787 PA |
335 | ($hz) = @ARGV; |
336 | ||
337 | # Use this to generate the %canned_values structure | |
338 | if ($hz eq '--can') { | |
339 | shift(@ARGV); | |
340 | @hzlist = sort {$a <=> $b} (@ARGV); | |
341 | ||
342 | print "# Precomputed values for systems without Math::BigInt\n"; | |
343 | print "# Generated by:\n"; | |
344 | print "# timeconst.pl --can ", join(' ', @hzlist), "\n"; | |
345 | print "\%canned_values = (\n"; | |
346 | my $pf = "\t"; | |
347 | foreach $hz (@hzlist) { | |
348 | my @values = compute_values($hz); | |
349 | print "$pf$hz => [\n"; | |
350 | while (scalar(@values)) { | |
351 | my $bit; | |
b9095fd8 | 352 | foreach $bit (32) { |
bdc80787 PA |
353 | my $m = shift(@values); |
354 | my $a = shift(@values); | |
355 | my $s = shift(@values); | |
b9095fd8 | 356 | print "\t\t", perlvals($m,$a,$s), ",\n"; |
bdc80787 PA |
357 | } |
358 | my $n = shift(@values); | |
359 | my $d = shift(@values); | |
b9095fd8 | 360 | print "\t\t", perlvals($n,$d), ",\n"; |
bdc80787 PA |
361 | } |
362 | print "\t]"; | |
363 | $pf = ', '; | |
364 | } | |
365 | print "\n);\n"; | |
366 | } else { | |
367 | $hz += 0; # Force to number | |
368 | if ($hz < 1) { | |
369 | die "Usage: $0 HZ\n"; | |
370 | } | |
371 | ||
372 | @val = @{$canned_values{$hz}}; | |
373 | if (!defined(@val)) { | |
374 | @val = compute_values($hz); | |
375 | } | |
376 | output($hz, @val); | |
377 | } | |
378 | exit 0; |