From: ian Date: Sun, 13 Apr 2008 17:25:08 +0000 (+0000) Subject: interferences generated X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ijackson/git?a=commitdiff_plain;h=ee2ddb164b48d5f769573b20564d23b80b9843ad;p=trains.git interferences generated --- diff --git a/hostside/safety.c b/hostside/safety.c index 624eb7e..c4bb33b 100644 --- a/hostside/safety.c +++ b/hostside/safety.c @@ -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; diff --git a/layout/data2safety b/layout/data2safety index 7e8e0eb..a9a1876 100755 --- a/layout/data2safety +++ b/layout/data2safety @@ -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; diff --git a/layout/layout-data.h b/layout/layout-data.h index cbdfcce..bf57f2c 100644 --- a/layout/layout-data.h +++ b/layout/layout-data.h @@ -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 diff --git a/layout/ours.wiring b/layout/ours.wiring index 84e643e..77f6222 100644 --- a/layout/ours.wiring +++ b/layout/ours.wiring @@ -38,4 +38,8 @@ fixed A5/J0 A2/P0 +interferences + X1 X2 + A5/P0J1 A6/P0J1 + endwiring