chiark / gitweb /
put %! at start but do not break segcmapreq
[trains.git] / layout / segcmapassign
1 #!/usr/bin/perl -w
2 # input file:
3 #   lines, with one canonical subsegment specification (csss) each
4 #   (need not be unique)
5 # output:
6 #   lines:
7 #
8 # B <datumpart> <numbits> <bottombit>
9 #   ((1u << numbits) - 1) << bottombit is the mask for datumpart
10 #   datumpart may be Segnum Movfeatpos Edge Angle
11 #   B lines are right at the start
12 #
13 # C <csss> 0x<datum> <angle-bits>
14 #   where <csss> is N/[M] (see informat.txt) and <datum>
15 #   is the hex value of the datum (see segcmap.h)
16 #
17 # S <segname> 0x<segnum>
18 # F <segname> 0x<segnum> <featname> 0x<prefix> <configbits>
19 #      where (1<<configbits)-1 are the bits for the config
20 #      and ~((1<<configbits)-1) are the bits for the prefix
21 #
22 # # comments for debugging segcmapassign etc.
23 # E
24 #     final line, always present
25
26 use strict;
27 use IO::Handle;
28
29 our ($seg,$movfeat,$movconf,$si,$fi);
30 our (%seg);
31
32 our %bits;
33
34 sub read_segcmap_h () {
35     my ($p);
36     open H, "< segcmap.h" or die $!;
37     map { $bits{$_}=0 } qw(Angle Movfeatpos Segnum);
38     while (<H>) {
39         next unless m/^\#define\s+([A-Z])([A-Z]*)_BITS\s+([1-9]\d*)\s*$/;
40         $p= uc($1).lc($2);
41         next unless exists $bits{$p};
42         die $p if $bits{$p};
43         $bits{$p}= $3;
44     }
45     map { die $_ unless $bits{$_} } keys %bits;
46 }
47
48 read_segcmap_h();
49
50 sub pf { printf @_ or die $!; }
51
52 pf("B Segnum %d %d\n", $bits{Segnum}, 24-$bits{Movfeatpos}-$bits{Segnum});
53 pf("B Movfeatpos %d %d\n", $bits{Movfeatpos}, 24-$bits{Movfeatpos});
54 pf("B Edge %d %d\n", 1, $bits{Angle});
55 pf("B Angle %d %d\n", $bits{Angle}, 0);
56
57 sub cssnmap ($$$$) {
58     my ($seg,$movfeat,$segnum,$posinfo) = @_;
59     my ($datum);
60     $datum=
61         ($posinfo << (24 - $bits{Movfeatpos})) |
62         ($segnum << (24 - $bits{Movfeatpos} - $bits{Segnum}));
63     pf("C %s/%s 0x%06x %d\n",
64        $seg, $movfeat, $datum, $bits{Angle});
65 }
66
67 while (<>) {
68     m,^(\w*)/([A-Za-z_]*)(\d*)$, or die;
69     ($seg,$movfeat,$movconf)=($1,$2,$3);
70     if (!length $seg) {
71         die "too many $seg $movfeat" if
72             length $movfeat && $movconf >= $bits{Movfeatpos}-1;
73         cssnmap($seg,$movfeat,0,
74                 length $movfeat ? 1<<($bits{Movfeatpos}-1) : 0);
75         next;
76     }
77     die if length $movconf && !length $movfeat;
78     exists $seg{$seg}{Num};
79     $si= $seg{$seg};
80     if (length $movfeat) {
81         exists $si->{Feat}{$movfeat}{Max};
82         $fi= $si->{Feat}{$movfeat};
83         $fi->{Max}=0 unless exists $fi->{Max};
84         $fi->{Max}=$movconf unless $fi->{Max} >= $movconf;
85     }
86 }
87
88 our ($segnum) = 1;
89
90 our ($posbit,$posbiti,$abovenext);
91
92 foreach $seg (sort keys %seg) {
93     $si= $seg{$seg};
94     $si->{Num}= $segnum++;
95     die if $si->{Num} >= 1 << $bits{Segnum};
96     $abovenext= 1 << $bits{Movfeatpos};
97     pf("S %s 0x%x\n",
98        $seg, $si->{Num});
99     cssnmap($seg,'', $si->{Num}, 0x00);
100     foreach $movfeat (sort {
101         $si->{Feat}{$b}{Max} <=> $si->{Feat}{$a}{Max};
102     } keys %{ $si->{Feat} }) {
103         $fi= $si->{Feat}{$movfeat};
104         $posbiti= $fi->{Max}+1;
105         $posbit= 1<<$posbiti;
106         $abovenext -= $posbit;
107         die "too many $seg" if $abovenext <= 0;
108         $fi->{Prefix}= $abovenext;
109         $fi->{ConfigMask}= $posbit-1;
110         $fi->{ConfigBits}= $posbiti;
111         pf("F %s 0x%x %s 0x%x %d\n",
112            $seg, $si->{Num},
113            $movfeat, $fi->{Prefix}, $fi->{ConfigBits});
114         cssnmap($seg, $movfeat, $si->{Num}, $fi->{Prefix});
115     }
116 }
117
118 STDIN->error and die $!;
119 print "E\n" or die $!;