2 # usage ../make-clocks [<input-file> ...] -Dmclock=khz -Dsclock=khz
7 sub p ($) { print $_[0] or die $!; }
11 p("; autogenerated - do not edit\n");
13 while ($ARGV[$#ARGV] =~ m/^\-/) {
16 die unless m/^\-D(\w+)\=(\w+)$/;
20 our ($name,$ms,$interval,$msclock);
21 # $interval is in seconds
22 # mclock or sclock is in kHz
23 # ourtimerclock is mclock or sclock * 250 (for Fosc/4)
25 # basically interval = cycles / clock
26 # adjusted for units interval = cycles * prescale / (foscscale * msclock)
27 # ie cycles = interval * foscscale * msclock / prescale
28 # or msclock = cycles * prescale / (foscscale * interval)
30 sub scaleable ($$$$$$) {
31 my ($width, $foscscale, $scalebitnums, $scales,
32 $deadcycles, $overflowp) = @_;
33 my ($maxcycles, $scalespec, $scalebits);
34 my ($cycles, $cyequ, @scalebits);
36 $maxcycles = (1 << $width) - $deadcycles;
37 foreach $scalespec (@$scales) {
38 $scalespec =~ m/^0*(\d+)\-([01]+)$/;
39 ($prescale,$scalebits) = ($1,$2);
40 length($scalebits) == @$scalebitnums
41 or die "$scalespec @$scalebitnums";
43 $cycles= $interval * $foscscale * $msclock / $prescale;
44 next if $cycles > $maxcycles;
46 if (length($scalebits)) {
47 p("${name}scale equ ");
48 @scalebits = (map { "(1<<$_)" }
49 grep { $scalebits =~ s/^.// or die; $&; }
51 push @scalebits, '0' unless @scalebits;
52 p(join '|', @scalebits);
56 $cyequ= "${name}cycles";
57 p(sprintf "%s equ %d\n", $cyequ, $cycles);
59 p("${name}init equ ".(1<<$width)." - $cyequ\n");
61 p("${name}inith equ ${name}init / 256\n");
62 p("${name}initl equ ${name}init & 255\n");
67 warn "clock speed too high for $name\n";
71 my (@scales, $pre, $prex, $prebits, $posti, $this);
72 for $pre (qw(1-00 4-01 16-10)) {
73 $pre =~ m/^(\d+)\-([01]+)$/;
74 ($prex,$prebits) = ($1,$2);
75 for ($posti=0; $posti<15; $posti++) {
76 $this= sprintf "%03d-%s%04b", $prex * ($posti+1), $prebits, $posti;
80 local ($name) = "${name}_t2";
81 scaleable(8, 250.0, [qw(T2CKPS1 T2CKPS0 TOUTPS3 TOUTPS2 TOUTPS1 TOUTPS0)],
82 [ sort @scales ], 0, 0);
87 local ($name) = "${name}_t${n}";
88 scaleable(16, 250.0, ["T${n}CKPS1","T${n}CKPS0"],
89 [qw(1-00 2-01 4-10 8-11)], 1, 1);
94 local ($name) = "${name}_t0";
95 scaleable($w, 250.0, ["PSA","T0PS2","T0PS1","T0PS0"],
96 [qw(1-1000 2-0000 4-0001 8-0010 16-0011
97 32-0100 64-0101 128-0110 256-0111)], 1, 1);
100 sub do_T0ov8 { do_T0ov(8); }
101 sub do_T0ov16 { do_T0ov(16); }
102 sub do_T1ov { do_T13ov(1); }
103 sub do_T3ov { do_T13ov(3); }
105 sub provide_interval ($$$$) {
106 my ($iname, $thisval, $unitname, $unitval) = @_;
107 my ($inthisunit, $inthisunitint);
108 $inthisunit= $thisval / $unitval;
109 return if $inthisunit > 256000000.0;
110 $inthisunitint= sprintf "%d", $inthisunit;
111 return if abs(($inthisunitint - $inthisunit) / $inthisunit) > 0.001;
112 p("${iname}_${unitname} equ $inthisunitint\n");
116 my ($orgname,$mswant,$specd,$unit,$cy,$how,$baseinterval);
119 return unless m/^\S/;
121 m/^(\w+)\s+([MST]+)\s+(\w+)\s+([0-9.]+)(s|ms|us|ns|Hz|kHz|MHz)((?:[-+][0-9.]+cy)?)$/;
122 ($orgname,$mswant,$how,$baseinterval,$unit,$cy) = ($1,$2,$3,$4,$5,$6,$7);
123 $specd= $baseinterval.$unit.$cy;
124 if ($unit =~ m/M/) { $baseinterval *= 1.e6; }
125 if ($unit =~ m/k/) { $baseinterval *= 1.e3; }
126 if ($unit =~ m/m/) { $baseinterval *= 1.e-3; }
127 if ($unit =~ m/u/) { $baseinterval *= 1.e-6; }
128 if ($unit =~ m/n/) { $baseinterval *= 1.e-9; }
129 if ($unit =~ s/Hz//) { $baseinterval = 1.0 / $baseinterval; }
130 if ($cy =~ s/cy$//) { $cy *= 4.0; }
131 elsif ($cy = m//) { $cy = 0.0; }
132 else { die "$cy ?"; }
134 p(";========== $orgname ($specd: ${baseinterval}s, ${cy}cy) ==========\n");
135 if ($mswant =~ m/T/) {
136 provide_interval($orgname, $baseinterval, 'us', 1.e-6);
137 provide_interval($orgname, $baseinterval, 'ms', 1.e-3);
138 provide_interval($orgname, $baseinterval, 's', 1.0);
140 foreach $ms (qw(m s)) {
141 next unless $mswant =~ m/$ms/i;
142 $msclock= "${ms}clock";
143 die $msclock unless exists $defs{$msclock};
144 $msclock= $defs{$msclock};
145 $interval= $baseinterval + $cy / ($msclock * 1000.0);
146 p(";---------- $orgname, ${interval}s, ${msclock}kHz ----------\n");
147 $name = $orgname.'_'.($ms eq 'm' ? 'master' : 'slave');