6 $basename= @ARGV ? $ARGV[0] : 'safety';
7 die if $basename =~ m/^\-/;
8 $basename =~ s/\.wiring$//;
10 our ($mistakes, $currentline);
16 # $segs{$seg}{FeatCount} does not include Fixed
17 # $segs{$seg}{Feats}{$pt}{Kind} Point or Fixed
18 # $segs{$seg}{Feats}{$pt}{Weight} ) for Point only
19 # $segs{$seg}{Feats}{$pt}{Posns} ) for Point only
20 # $segs{$seg}{Feats}{$pt}{BoOb}[] ) for Point only
21 # $segs{$seg}{Feats}{$pt}{Fixed} position, for Fixed only
24 # $segs{$seg}{Ends}[$combpos][$end] = [ $node,$side ]
25 # $segs{$seg}{Dist}[$combpos]
28 # $nodes{$node}[$side]{Seg}
29 # $nodes{$node}[$side]{End}
31 our ($nextboardnum,@boardtype,%numboards,$nreverses,@sensesin,@sensesbase);
32 # @boardtype[$boardnum]
36 # $sensesbase[$boardnum]= ($page << 7) | $baselsbyte
40 @objkinds= qw(pt sense reverse);
42 our (%kind_count,%pin_info); # from BOARD.pin-info
44 our ($mode,$invertible);
49 mistake("first input line does not determine phase");
53 our (%syntaxerror_once);
54 return if exists $syntaxerror_once{$mode};
55 $syntaxerror_once{$mode}= 1;
56 mistake("syntax error");
62 print STDERR "ditching $m\n";
65 sub begin_points () { }
67 my ($seg,$pt,@boob,$bodef);
68 m,^\s+(\w+)/([A-Za-z]+)\s+((\d+)\.\d+)\s+(\d*\.\d+)$, or
70 ($seg,$pt,$boob[0],$bodef,$boob[1])=($1,$2,$3,$4,$5);
71 $boob[1] =~ s/^\./$bodef./;
72 mistake("unknown wiring for $seg in $seg/$pt") unless exists $segs{$seg};
73 mistake("duplicate wiring for $seg/$pt") if exists $segs{$seg}{Feats}{$pt};
74 $segs{$seg}{Feats}{$pt}= {
76 Weight => $segs{$seg}{Posns},
78 BoOb => [ map { pa_boob($_) } @boob ]
80 $segs{$seg}{Posns} *= 2;
81 $segs{$seg}{FeatCount}++;
84 sub begin_fixed () { }
87 m,^\s+(\w+)/([A-Za-z]+)(\d+)$, or return syntaxerror();
88 ($seg,$pt,$pos)=($1,$2,$3);
89 mistake("unknown wiring for $seg in $seg/$pt") unless exists $segs{$seg};
90 mistake("duplicate fixed $seg/$pt") if exists $segs{$seg}{Feats}{$pt};
91 $segs{$seg}{Feats}{$pt}= {
97 sub begin_segment () { }
100 m/^\s+(\w+)\s+(\d+\.\d+)$/ or return syntaxerror();
101 ($seg,$boob)=($1,$2);
102 mistake("duplicate topology for $seg") if exists $segs{$seg};
104 BoOb => pa_boob($boob),
112 sub begin_endwiring () {
115 sub begin_boards () {
119 m/^\s+(\d+)\s+(\w+)$/ or return syntaxerror();
120 ($num,$type)=($1,$2);
121 mistake("board $num when expected $nextboardnum")
122 if $num != $nextboardnum;
125 $boardtype[$num]= $type;
127 require "./$type.pin-info";
129 my ($sense_count, $page);
130 $sense_count= $kind_count{$type}{'sense'};
132 $sensesin[$page] + $sense_count > 128;
134 mistake("too many senses for encoding scheme")
137 if $page > $#sensesin;
139 $sensesbase[$num]= ($page << 7) | $sensesin[$page];
140 $sensesin[$page] += $sense_count;
142 &{"line_board_$type"}($num);
145 sub line_board_reversers ($) {
148 for ($i=0; $i<5; $i++) {
149 $objnum= so_boob('reverse', [ $num,$i ]);
150 $nreverses= $objnum+1 if $objnum >= $nreverses;
156 print STDERR "mistake: $m\n in $mode, \`$currentline'\n";
160 sub line_endwiring () {
161 my (@ns,$seg,$subspec,$dist);
162 my ($segr,@subsegil,$feat,$pos,$featr,$combpos,%featposwant);
163 my ($end,$node,$side,$nsr,$endposr);
164 m,^\s*segment\s+(\w+\.\d+)\s+(\w+\.\d+)\s+(\w+)(?:/((?:[A-Za-z]+\d+)+)\*\d+)?\s+([0-9.]+)$, or return syntaxerror();
165 ($ns[0],$ns[1],$seg,$subspec,$dist)=($1,$2,$3,$4,$5);
166 if (!exists $segs{$seg}) {
167 ditch("unwired $seg$subspec");
171 @subsegil= defined $subspec ? $subspec =~ m/([A-Za-z]+)(\d+)/g : ();
173 ($feat,$pos,@subsegil) = @subsegil;
174 if (!exists $segr->{Feats}{$feat}) {
175 mistake("no wiring for $seg/$feat");
178 $featr= $segr->{Feats}{$feat};
179 if (exists $featr->{Fixed}) {
180 if ($pos != $featr->{Fixed}) {
181 ditch("fixed-elsewise $seg$subspec");
185 mistake("position $seg/$feat$pos exceeds wiring")
186 unless $pos < $featr->{Posns};
187 $featposwant{$feat}= $pos;
191 for $feat (keys %{ $segr->{Feats} }) {
192 $featr= $segr->{Feats}{$feat};
193 next if exists $featr->{Fixed};
194 mistake("wiring $seg/$feat not covered by $seg/$subspec")
195 if !exists $featposwant{$feat};
196 $combpos += $featposwant{$feat} * $featr->{Weight};
198 mistake("duplicate topology for $seg/$subspec")
199 if defined $segs{$seg}{Dist}[$combpos];
200 $segs{$seg}{Dist}[$combpos]= $dist;
201 $endposr= $segr->{Ends}[$combpos];
202 die "$seg $combpos @$endposr ?" if defined $endposr && @$endposr;
203 for ($end=0; $end<2; $end++) {
204 $ns[$end] =~ m/^([a-z]\w+)\.([01])$/;
205 ($node,$side)=($1,$2);
206 $nsr= $nodes{$node}[$side];
207 if (!exists $nsr->{Seg}) {
208 $nodes{$node}[$side]= { Seg => $seg, End => $end };
210 $seg eq $nsr->{Seg} or
211 mistake("topology for $node.$side both $seg and $nsr->{Seg}");
212 $end == $nsr->{End} or
213 mistake("topology for $node.$side $seg both ends ($end".
214 " and also $nsr->{End})");
216 $segr->{Ends}[$combpos][$end]= [ $node, $side ];
221 print STDOUT $_[0] or die $!;
226 if ($boob !~ m/^([1-9]\d*|0)\.([1-9]\d*|0)$/) {
227 mistake("invalid board object $boob");
233 # so_boob_KIND($boardnum,$objnum,$boardtype,$pininfo) -> global object number
236 my ($boardnum,$obj)=@_;
237 mistake("point encoding out of range") if $boardnum>31;
239 return ($boardnum << 5) | $obj;
242 sub so_boob_reverse {
243 my ($boardnum,$obj,$boardtype)=@_;
245 # Converts board and object number (in canonical pic number plus
246 # and reverse0...reverse5 as seen on pinout diagrams), to
247 # object number for POLARITY command numbered as shown in
250 # There are three basic stages:
252 # * We invert the on-board mapping; ie, we untangle the
253 # tangling between the message from master to slave pic
254 # and the actual pins (see reverse.asm, polarity_do_here)
256 # * We figure out which bit of which message byte the
257 # object corresponds to. (see reverse.asm, polarity_decode_message)
259 # * We compute the README.protocol bit and byte number.
261 my ($cycle,$boardincycle,$cyclebasebyte,$byte,$bit);
262 die unless $boardtype eq 'reversers';
264 $obj = sprintf '%d', $obj;
265 $obj =~ y/302154/543210/; # mapping due to polarity_do_here
266 $cycle= int(($boardnum+3) / 7);
267 $boardincycle= ($boardnum+3) - $cycle*7;
268 $cyclebasebyte= $cycle*6 - 2;
269 if ($boardnum==2 && $obj > 2) {
270 $byte= 0; $bit= $obj-3;
271 return 3 - $bit; # only these three in byte 0, a special case
272 } elsif ($boardincycle<5) {
273 $byte= $cyclebasebyte + $boardincycle; $bit= $obj;
274 } elsif ($boardincycle==6) {
275 $byte= $cyclebasebyte + 5; $bit= $obj;
276 } elsif ($boardincycle==5) {
277 $byte= $cyclebasebyte + 5 - $bit; $bit= 6;
281 return $byte*7 + 3 - $bit;
284 sub so_boob_sense($$$) {
285 my ($boardnum,$obj)=@_;
287 $inpage= $obj + $sensesbase[$boardnum];
288 die if $inpage > 127;
289 return ($boardnum << 7) | $inpage;
295 my ($board,$obj)= @$bo;
296 my ($objnum,$type,$pi);
297 mistake("unknown board number $board")
298 unless defined $boardtype[$board];
299 $type= $boardtype[$board];
300 $pi= $pin_info{$type}{$kind};
301 mistake("object reference $kind $board.$obj out of range for".
303 unless defined $pi->[$obj];
304 $objnum= &{"so_boob_$kind"}($board,$obj,$type,$pi);
305 $pin_used{$kind}[$objnum]= [ $board, $pi->[$obj], $obj ];
306 return sprintf("%4d /* %d.%-2d*/", $objnum, $board, $obj);
308 return " 0 /*none*/ ";
313 my ($kind,$obj) = @_;
314 return so_boob($kind, defined $obj ? $obj->{BoOb} : undef);
325 if (m/^(invertible|vanilla|points|fixed|endwiring|boards)$/) {
327 $invertible= ($mode eq 'invertible');
328 $mode= 'segment' if $mode =~ m/^(?:vanilla|invertible)$/;
339 $p =~ s/\d{1,6}/ sprintf "%06d%d",$&,$& /ge;
344 my (@segs,$segn,$seg,$segr,$pt,$ptv, $delim);
345 my ($comb,$pi,$feat,$featr,$end,$boob);
346 my ($node,$side,$otherend,$nodeotherside,$otherseg,$otherbackrelus);
347 o("/* autogenerated - do not edit */\n\n");
349 for $seg (sort { nummap($a) cmp nummap($b) } keys %segs) {
350 $segs{$seg}{Num}= @segs;
354 "#define NUM_TRAINS 1000000\n".
355 "#define NUM_SEGMENTS %s\n\n".
356 "#include \"layout-data.h\"\n\n",
358 foreach $seg (@segs) {
361 o("static const SegPosCombInfo spci_${seg}"."[]= {");
363 for ($comb=0; $comb < $segr->{Posns}; $comb++) {
365 foreach $feat (keys %{ $segr->{Feats} }) {
366 $featr= $segr->{Feats}{$feat};
367 next if exists $featr->{Fixed};
368 $pi.= sprintf("%s%d", $feat,
369 ($comb / $featr->{Weight}) % $featr->{Posns});
372 o(sprintf " { %-8s %4d",
373 '"'.$seg.(length $pi ? '/' : '').$pi.'",',
374 $segr->{Dist}[$comb]);
375 for ($end=0; $end<2; $end++) {
377 $otherend= $segr->{Ends}[$comb][$end];
378 defined $otherend or die "$seg $comb $end ?";
379 ($node,$side) = @$otherend;
380 $nodeotherside= $nodes{$node}[1-$side];
381 if (defined $nodeotherside) {
382 $otherseg= $nodeotherside->{Seg};
383 $otherbackrelus= $nodeotherside->{End} ^ $end ^ 1;
384 o(sprintf "/*%5s.%d %-5s*/ %d,%3d",
386 ($otherbackrelus?'-':' ').$otherseg,
388 $segs{$otherseg}{Num});
390 o(sprintf "/*%5s.%d*/ 0,NOTA(Segment)",
400 next unless $segr->{FeatCount};
402 for $pt (keys %{ $segr->{Feats} }) {
403 $ptv= $segr->{Feats}{$pt};
404 next if exists $ptv->{Fixed};
405 o("static const BoardObject mfbo_${seg}_${pt}"."[]= {");
407 foreach $boob (@{ $ptv->{BoOb} }) {
409 o(so_boob('pt',$boob));
415 o("static const MovFeatInfo mfi_${seg}"."[]= {");
417 for $pt (keys %{ $segr->{Feats} }) {
418 $ptv= $segr->{Feats}{$pt};
419 next if exists $ptv->{Fixed};
421 o(" { \"$seg/$pt\", mfk_".lc($ptv->{Kind}).",".
422 " $ptv->{Posns}, $ptv->{Weight}, mfbo_${seg}_$pt }");
427 o("const SegmentNum info_nsegments=NUM_SEGMENTS;\n");
428 o("const SegmentInfo info_segments[NUM_SEGMENTS]= {");
430 foreach $seg (@segs) {
433 o(sprintf " { %-7s %d, %2d,%-9s %3d,%-10s %-6s,%-6s }",
434 "\"$seg\",", $segr->{Inv},
435 $segr->{FeatCount}, ($segr->{FeatCount} ? "mfi_$seg," : '0,'),
436 $segr->{Posns}, "spci_$seg,",
437 so_oboob('sense',$segr),
438 so_oboob('reverse', $segr->{Inv} ? $segr : undef));
448 o("$sec code ${sec}_start");
452 o_section("pindata_pic2detinfo");
453 o("Exists equ 0x8000\n".
454 "Detectors equ 0x0080\n".
455 "Reversers equ 0x0000\n");
456 for ($num=0; $num<@boardtype; $num++) {
457 if (!defined $boardtype[$num]) { o(" dw 0\n"); next; }
458 $base= $sensesbase[$num];
459 o(sprintf " dw Exists | %-10s | 0x%02x%02x\n",
460 ucfirst($boardtype[$num]), $base >> 7, $base & 0x7f);
462 o(sprintf " fill 0, maxboards_count-%d\n", $num);
466 # for $w (qw(pic port bit)) {
469 # o("${k}_${w}_data_section org ${k}_${w}_data\n");
470 # for ($i=0; $i<@{ $pin_used{$k} }; $i++) {
471 # $or= $pin_used{$k}[$i];
473 # $or->[1] =~ m/^(\d+)\,\d+,(\w+)$/;
474 # ($portnum,$bit)= ($1,$2);
475 # $portnum= sprintf "%02x", $portnum + 0x89; # 89=LATA
476 # $bit= sprintf "%02x", hex $bit;
478 # $portnum=$bit='00';
486 # } elsif ($w eq 'port') {
488 # } elsif ($w eq 'bit') {
494 # push @d, 'X' if @d^1;
495 # @d= map { s/^[a-f]/0$&/; sprintf "%3s", $_ } @d;
497 # $d[$each/2] = " $d[$each/2]" if $#d >= $each/2;
498 # last if @d <= $each;
499 # o(" db ". join(',',@d[0..($each-1)]). "\n");
500 # @d= @d[$each..$#d];
502 # o(" db ".join(',',@d)."\n");
504 # o(" if \$ > ${k}_pic_data + ${k}_num_max\n".
505 # " error \"too much ${k}_picdata\"\n".
507 # " fill 0xffff, ${k}_pic_data + ${k}_num_max - \$\n");
512 my ($k,$w,$i,@d,$or,$p,$portnum,$bit,$each);
513 close STDOUT or die $!;
514 open STDOUT, ">$basename-pindata.asm" or die $!;
515 o("; autogenerated - do not edit\n");
516 o(" include pindata.inc\n".