chiark / gitweb /
interferences generated
authorian <ian>
Sun, 13 Apr 2008 17:25:08 +0000 (17:25 +0000)
committerian <ian>
Sun, 13 Apr 2008 17:25:08 +0000 (17:25 +0000)
hostside/safety.c
layout/data2safety
layout/layout-data.h
layout/ours.wiring

index 624eb7ef63ac37b404d54546ec7ddc24c5d1946b..c4bb33b8e2e539e57fce35f9abe06e26239d6223 100644 (file)
@@ -30,6 +30,47 @@ typedef struct {
   Segment *invert_forcer; /* the unswitchable which forces */
 } LayTrainState;
 
+static void lay_train_check_clash(LayTrainState *l, Segment *check,
+                                 Segment *report) {
+  const char *exi1="", *exi2="";
+  if (check!=report) { exi1= " at "; exi2= check->i->pname; }
+  
+  if (seg->tr_updated) {
+    l->ec= safety_problem(l->tra, report, "self-collision%s%s", exi1,exi2);
+    return;
+  }
+  if (seg->owner) {
+    if (seg->owner != l->tra) {
+      l->ec= safety_problem(l->tra, tloc.seg, "collision with %s"
+                           "%s%s", seg->owner->pname, exi1,exi2);
+      return;
+    }
+  }
+}
+
+static Segment *interferes(Segment *base) {
+  const SegmentInfo *basei, *interi;
+  SegmentNum intern;
+  Segment *inter;
+
+  basei= base->i;
+  intern= seg->i->interferes;
+
+  if (!SOMEP(intern)) return 0;
+  if (!(segi->interferes_movposcomb_map & (1u << base->movposcomb)))
+    return 0;
+
+  inter= &segments[intern];
+  interi= &info_segments[intern];
+
+  assert(base == &info_segments[interi->interferes]);
+  if (!inter->moving &&
+      !(interi->interferes_movposcomb_map & (1u << inter->movposcomb)))
+     return 0;
+
+  return inter;
+}
+
 static void lay_train_pass(LayTrainState *l,
                           TrackLocation tloc, long advance,
                           long speed, unsigned backwards,
@@ -49,19 +90,11 @@ static void lay_train_pass(LayTrainState *l,
     seg= tloc.seg;
 
     if (check_clash) {
-      if (seg->tr_updated) {
-       l->ec= safety_problem(l->tra, tloc.seg, "self-collision");
-       return;
-      }
-      if (seg->owner) {
-       if (seg->owner != l->tra) {
-         l->ec= safety_problem(l->tra, tloc.seg, "collision with %s",
-                               seg->owner->pname);
-         return;
-       }
-      }
+      lay_train_check_clash(l,seg,seg);
+      inter= interfere_physical(seg);
+      if (inter) lay_train_check_clash(l,inter,seg);
     }
-    
+
     seg->owner= l->tra;
     seg->tr_backwards= tloc.backwards ^ backwards;
     seg->tr_updated= 1;
index 7e8e0eb7b50f8b6e625b54add34a302962bbe406..a9a18766e9da003d4d08923046c32fb224552b68 100755 (executable)
@@ -19,11 +19,16 @@ our (%segs);
 # $segs{$seg}{Feats}{$pt}{Posns}      ) for Point only
 # $segs{$seg}{Feats}{$pt}{BoOb}[]     ) for Point only
 # $segs{$seg}{Feats}{$pt}{Fixed}      position, for Fixed only
+# $segs{$seg}{Inter}{Seg}            ) calculated
+# $segs{$seg}{Inter}{Map}             )  in writeout
 
 # $segs{$seg}{Num}
 # $segs{$seg}{Ends}[$combpos][$end] = [ $node,$side ]
 # $segs{$seg}{Dist}[$combpos]
 
+our (@interferences);
+# $interferences[][] = "$seg/$posre"   "/.*" added during parsing if necc.
+
 our (%nodes);
 # $nodes{$node}[$side]{Seg}
 # $nodes{$node}[$side]{End}
@@ -62,7 +67,7 @@ sub syntaxerror () {
 
 sub ditch ($) {
     my ($m) = @_;
-    print STDERR "ditching $m\n";
+    print STDERR "info: ditching $m\n";
 }
 
 sub begin_points () { }
@@ -154,12 +159,28 @@ sub line_segment_invertible ($) {
     $reversersboardnum[$boob->[0]]= -1;
 }
 
+sub begin_interferences () {
+}
+sub line_interferences () {
+    s/^\s+// or return syntaxerror();
+    my ($is) = [ split /\s+/, $_ ];
+    map { s,$,/.*, unless m,/,; } @$is;
+    return syntaxerror() if grep { !m,^\w+/, } @$is;
+    push @interferences, $is;
+}
+
 sub mistake ($) {
     my ($m) = @_;
     print STDERR "mistake: $m\n in $mode, \`$currentline'\n";
     $mistakes++;
 }
 
+sub endmistake ($) {
+    my ($m) = @_;
+    print STDERR "mistake: $m\n";
+    $mistakes++;
+}
+
 sub line_endwiring () {
     my (@ns,$seg,$subspec,$dist);
     my ($segr,@subsegil,$feat,$pos,$featr,$combpos,%featposwant);
@@ -167,7 +188,7 @@ sub line_endwiring () {
     m,^\s*segment\s+(\w+\.\d+)\s+(\w+\.\d+)\s+(\w+)(?:/((?:[A-Za-z]+\d+)+)\*\d+)?\s+([0-9.]+)$, or return syntaxerror();
     ($ns[0],$ns[1],$seg,$subspec,$dist)=($1,$2,$3,$4,$5);
     if (!exists $segs{$seg}) {
-       ditch("unwired $seg$subspec");
+       ditch("unwired $seg/$subspec");
        return;
     }
     $segr= $segs{$seg};
@@ -181,7 +202,7 @@ sub line_endwiring () {
        $featr= $segr->{Feats}{$feat};
        if (exists $featr->{Fixed}) {
            if ($pos != $featr->{Fixed}) {
-               ditch("fixed-elsewise $seg$subspec");
+               ditch("fixed-elsewise $seg/$subspec");
                return;
            }
        } else {
@@ -345,18 +366,15 @@ sub so_boob ($$$;$) {
        return sprintf("%#5x /* %d.%-2d*/", $objnum, $board, $obj);
     } else {
 #print "so_boob >$objnum_rr|$$objnum_rr< -\n";
-       return "   0 /*none*/ ";
+       return "    0 /*none*/ ";
     }
 }
 
 sub so_objboob ($$$;$) {
     my ($kind,$mkused,$obj, $objnum_rr) = @_;
-#    return so_boob($kind,$mkused, defined $obj ? $obj->{BoOb} : undef );
-#print "so_objboob >$objnum_rr|$$objnum_rr<\n";
     return so_boob($kind,$mkused,
-                  defined $obj ? $obj->{BoOb} : undef
-                  , $objnum_rr
-                  );
+                  defined $obj ? $obj->{BoOb} : undef,
+                  $objnum_rr);
 }
 
 sub mainread () {
@@ -367,7 +385,7 @@ sub mainread () {
        s/\s+$//;
        next unless m/\S/;
        last if m/^end$/;
-       if (m/^(invertible|vanilla|points|fixed|endwiring|boards)$/) {
+       if (m/^(invertible|vanilla|points|fixed|endwiring|boards|interferences)$/) {
            $mode= $1;
            $invertible= ($mode eq 'invertible');
            $mode= 'segment' if $mode =~ m/^(?:vanilla|invertible)$/;
@@ -404,6 +422,7 @@ sub writeout () {
     my (@segs,$segn,$seg,$segr,$pt,$ptv, $delim);
     my ($comb,$pi,$feat,$featr,$end,$boob);
     my ($node,$side,$otherend,$nodeotherside,$otherseg,$otherbackrelus);
+    my ($ourinter,$pcname,$inter,$intother);
     o("/* autogenerated - do not edit */\n\n");
     @segs=();
     for $seg (sort { nummap($a) cmp nummap($b) } keys %segs) {
@@ -419,6 +438,9 @@ sub writeout () {
 
        o("static const SegPosCombInfo spci_${seg}"."[]= {");
        $delim='';
+
+       $segr->{Inter}{Map}= 0;
+       $ourinter= $segr->{Inter};
        for ($comb=0; $comb < $segr->{Posns}; $comb++) {
            $pi='';
            foreach $feat (keys %{ $segr->{Feats} }) {
@@ -428,11 +450,11 @@ sub writeout () {
                              ($comb / $featr->{Weight}) % $featr->{Posns});
            }
            o("$delim\n");
-           o(sprintf "  { %-8s %4d",
+           o(sprintf " { %-7s%4d",
              '"'.$pi.'",',
              $segr->{Dist}[$comb]);
            for ($end=0; $end<2; $end++) {
-               o(", { ");
+               o(", {");
                $otherend= $segr->{Ends}[$comb][$end];
                defined $otherend or die "$seg $comb $end ?";
                ($node,$side) = @$otherend;
@@ -440,7 +462,7 @@ sub writeout () {
                if (defined $nodeotherside) {
                    $otherseg= $nodeotherside->{Seg};
                    $otherbackrelus= $nodeotherside->{End} ^ $end ^ 1;
-                   o(sprintf "/*%5s.%d %-5s*/ %d,%3d",
+                   o(sprintf "/*%4s.%d %-5s*/ %d,%3d",
                      $node,$side,
                      ($otherbackrelus?'-':' ').$otherseg,
                      $otherbackrelus,
@@ -453,6 +475,33 @@ sub writeout () {
            }
            o(sprintf " }");
            $delim= ',';
+
+           $pcname= "$seg/$pi";
+           for $inter (@interferences) {
+               next unless grep {
+                   if ($pcname =~ m/^$_$/) {
+                       s,/.*,/ ?,; 1;
+                   } else {
+                       0;
+                   }
+               } @$inter;
+               for $intother (@$inter) {
+                   $intother =~ m,^(\w+)/, or die "$intother ?";
+                   next if $1 eq $seg;
+                   exists $segs{$1} or
+                       endmistake("unknown segment $1 in interference");
+                   if (defined $ourinter->{Seg}) {
+                       $1 eq $ourinter->{Seg} or
+                           endmistake("unsupported complicated interference ".
+                                      "involving $seg, $1, $ourinter->{Seg}");
+                   } else {
+                       $ourinter->{Seg}= $1;
+                   }
+               }
+               endmistake("unsupported too-moveable interference")
+                   if $comb>7;
+               $ourinter->{Map} |= 1 << $comb;
+           }
        }
        o("\n};\n");
 
@@ -483,6 +532,12 @@ sub writeout () {
        }
        o("\n};\n");
     }
+    for $inter (@interferences) {
+       map {
+           warn "warning: unused interference specification $_\n" unless m, ,;
+       } @$inter;
+    }
+
     o("const SegmentNum info_nsegments=NUM_SEGMENTS;\n");
     o("const SegmentInfo info_segments[NUM_SEGMENTS]= {");
     my (@sensemap,$segnum,$sensenum,$i);
@@ -491,14 +546,21 @@ sub writeout () {
     foreach $seg (@segs) {
        $segr= $segs{$seg};
        o("$delim\n");
-       o(sprintf "  { %-7s %d, %2d,%-9s %3d,%-10s %-6s,%-6s }",
-         "\"$seg\",", $segr->{Inv},
+       o(sprintf " { %-6s%d,%2d,%-8s%d,%-9s%-6s,%-7s",
+         "\"$seg\",",$segr->{Inv},
          $segr->{FeatCount}, ($segr->{FeatCount} ? "mfi_$seg," : '0,'),
          $segr->{Posns}, "spci_$seg,",
          so_objboob('sense',1, $segr, \$sensenum),
-         so_objboob('reverse',1, $segr->{Inv} ? $segr : undef));
+         so_objboob('reverse',1, $segr->{Inv} ? $segr : undef).',');
+       $ourinter= $segr->{Inter};
+       if (defined $ourinter->{Seg}) {
+           o(sprintf "%2d/*%s*/,0%o", $segs{$ourinter->{Seg}}{Num},
+             $ourinter->{Seg}, $ourinter->{Map});
+       } else {
+           o(" -1");
+       }
+       o(" }");
        $delim= ',';
-       o("/* sensmap[$sensenum]=$segnum */");
        $sensemap[$sensenum]= $segnum++;
     }
     o("\n};\n");
@@ -668,3 +730,4 @@ mainread();
 redaction();
 writeout();
 writeasm();
+exit 1 if $mistakes;
index cbdfcceff45fde345a224bd11a65cfa7f7553f6e..bf57f2ca4f3838c51aea89eddabad77a0b8044f9 100644 (file)
@@ -58,6 +58,8 @@ typedef struct {
   MovPosComb n_poscombs;
   const SegPosCombInfo *poscombs;
   BoardObject sense, invert;
+  SegmentNum interferes;
+  unsigned char interferes_movposcomb_map;
 } SegmentInfo;
 
 /* This data array has no sentinel member.  Use the info_nsegments
index 84e643e0c0bbc761678fb17a2d57a0b3a407313b..77f62228017398c4879323ea4c5f1e146fe4933c 100644 (file)
@@ -38,4 +38,8 @@ fixed
        A5/J0
        A2/P0
 
+interferences
+       X1 X2
+       A5/P0J1 A6/P0J1
+
 endwiring