timeconst.pl 9.4 KB

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