-- wiresPlace6.mesa -- reject wires -- ties to middles and to ends -- alternate paths -- follow around nil ends DIRECTORY SystemDefs:FROM"SystemDefs", WiresDefs:FROM"WiresDefs", IODefs:FROM"IODefs"; WiresPlace:PROGRAM IMPORTS SystemDefs, IODefs, WiresDefs=BEGIN OPEN WiresDefs; Error:SIGNAL=CODE; debugLevel: INTEGER _ 2; --//////////////CONTROL/////////////// Main:PROCEDURE=BEGIN AllocateStuffForCreate[PrintStks]; AllocateStuffForSeg[]; AllocateStuffForPlace[]; Go[]; END; Go:PROCEDURE=BEGIN i,j: INTEGER; GetInput[TRUE]; MakeWireList[TRUE]; InitRejectWires[]; PlaceSimpleWires[TRUE]; [i,j]_TurnToStks[TRUE]; DoOutputs["wires3",i,j]; END; AllocateStuffForPlace:PROCEDURE=BEGIN OPEN SystemDefs; rejectWireList_AllocateSegment[SIZE[rejectWireListArray]]; hopperList_AllocateSegment[SIZE[hopperListArray]]; END; --/////////////REJECT WIRES /////////////// rejectWireListArray:TYPE=ARRAY [0..maxRejectWire] OF WirePtr; rejectWireList:POINTER TO rejectWireListArray_NIL; topRejectWire:INTEGER; maxRejectWire:INTEGER=40; InitRejectWires:PROCEDURE=BEGIN topRejectWire_0; END; AddRejectWire:PROCEDURE[w:WirePtr]=BEGIN rejectWireList[topRejectWire]_w; topRejectWire_topRejectWire+1; IF topRejectWire>maxRejectWire THEN Error; END; --////// PLACE SIMPLE WIRES/////////////// PlaceSimpleWires:PROCEDURE[print:BOOLEAN]= BEGIN InitSegs[]; EnumerateWires[PlaceOneWire]; IF print THEN BEGIN PrintSegs[]; debugPrint_TRUE; EnumerateGrid[PrintOrientations]; debugPrint_FALSE END; END; PlaceOneWire:PROCEDURE[wire:WirePtr]= BEGIN BackwardRun[wire,ForwardRun[wire]]; END; ForwardRun:PROCEDURE[w:WirePtr]RETURNS[done:NodePtr]=BEGIN OneNode:PROCEDURE[n:NodePtr]RETURNS[BOOLEAN]= BEGIN RETURN[n.hop>maxLength OR EnumerateFollow[n,OnePlace]]; END; OnePlace:PROCEDURE[n:NodePtr,s:SegPtr,level:BOOLEAN]RETURNS[BOOLEAN]= BEGIN done_AddHopper[s,n.hop+1,n,TRUE,level]; IF IllegalNode[done] THEN Error; RETURN[done#NIL]; END; SetEnd:PROCEDURE[s:SegPtr, c: Contact]RETURNS[BOOLEAN]= BEGIN done_AlsoAdd[s,none,terminalHop]; done.contact_c; IF IllegalNode[done] THEN Error; RETURN[done#NIL]; END; SetStart:PROCEDURE[s:SegPtr, c: Contact]RETURNS[BOOLEAN]= BEGIN done_AlsoAdd[s,none,0]; done.contact_c; IF IllegalNode[done] THEN Error; RETURN[done#NIL]; END; -- BEGIN Body of ForwardRun maxLength:INTEGER_WireLength[w.a,w.b]+7; done_NIL; ClearHopper[]; IF w.a.i=w.b.i AND w.a.j=w.b.j THEN RETURN; -- do nothing for pullups IF ~EnumerateOrient[w.b,SetEnd] AND ~EnumerateOrient[w.a,SetStart] THEN EnumerateHopper[OneNode]; END; AlsoAdd:PROCEDURE[s:SegPtr,t:Twist,h:INTEGER]RETURNS[done:NodePtr]=BEGIN level:BOOLEAN_s.xy.l; IF s=NIL OR s.dummy AND t=n THEN RETURN[NIL]; done_AddHopper[s,h,NIL,TRUE,level]; IF t=none AND ~s.dummy AND ~s.nc THEN RETURN; IF done=NIL AND (t=s OR t=f) AND ~s.bc AND ~s.dummy THEN done_AddHopper[s.back,h,NIL,FALSE,level]; IF done=NIL AND t#n AND s.bc THEN done_AlsoAdd[s.back,b,h]; IF done=NIL AND t#b AND s.nc THEN done_AlsoAdd[s.next,n,h]; IF done=NIL AND t#s AND ~s.dummy THEN done_AlsoAdd[s.first,f,h]; IF done=NIL AND t#f AND ~s.dummy THEN done_AlsoAdd[s.second,s,h]; IF done=NIL AND t#a AND ~s.dummy THEN done_AlsoAdd[s.across,a,h]; END; BackwardRun:PROCEDURE[w:WirePtr,n:NodePtr]=BEGIN where:SegPtr_NIL; down,free:BOOLEAN; color:Color_IF w.a.contact=gate OR w.b.contact=gate THEN r ELSE g; IF IllegalNode[n] THEN Error; IF debugLevel>10 THEN ShowHopper[]; IF n=NIL THEN BEGIN IF w.a.i=w.b.i AND w.a.j=w.b.j THEN SetPullup[w.a] ELSE AddRejectWire[w]; RETURN; END; [down,free]_SetInitialSegment[w.b,n,w.circuit]; IF PreviousHopper[n]=NIL THEN where_(IF down THEN n.s ELSE n.s.next) ELSE FOR n_n,PreviousHopper[n] UNTIL n=NIL DO where_SetSeg[from:n,col:color,circuit:w.circuit,old:where, tieN:~free AND ~down, tieB:~free AND down]; free _ TRUE ENDLOOP; SetFinalSegment[l:w.a,s:where, n:n, circuit: w.circuit]; IF debugLevel>10 THEN BEGIN debugPrint_TRUE; EnumerateGrid[PrintOrientations]; debugPrint_FALSE; END; END; --/////// START HOPPER /////// --The hopper is a fifo into which one can insert nodes. Duplicate entries --will be suppressed (thereby suppressing longer passes to the same place --one can also backtrack through the hopper chain hopperListArray:TYPE=ARRAY [0..maxHopper] OF Node; maxHopper:INTEGER=400; hopperList:POINTER TO hopperListArray_NIL; hopperInsert,hopperRemove:INTEGER; IllegalNode:PROCEDURE[n:NodePtr] RETURNS[BOOLEAN]=BEGIN foo1:CARDINAL_LOOPHOLE[n]; foo2:CARDINAL_LOOPHOLE[@hopperList[0]]; foo3:CARDINAL_LOOPHOLE[@hopperList[maxHopper]]; RETURN[n#NIL AND foo1 NOT IN [foo2..foo3]]; END; ClearHopper:PROCEDURE=BEGIN hopperInsert_hopperRemove_0; END; AddHopper:PROCEDURE[s:SegPtr,h:Hop,bk:NodePtr,nor,l:BOOLEAN] RETURNS[NodePtr]=BEGIN i:INTEGER; t:NodePtr; IF s.w=l OR s.w=d THEN RETURN[NIL]; IF ~s.dummy AND s.xy.l#l THEN BEGIN Error; RETURN[NIL]; END; FOR i IN [0..hopperInsert) DO t_@hopperList[i]; IF s=t.s AND l=t.l THEN BEGIN IF t.hop=terminalHop AND h#terminalHop THEN t.back_bk ELSE t_NIL; RETURN[t]; END; ENDLOOP; t_AddToHopper[]; t^_[s:s,hop:h,back:bk,normal:nor,movingLD:LD[bk.s,s],l:l, contact: none]; RETURN[NIL]; END; AddToHopper:PROCEDURE RETURNS[f:NodePtr]=BEGIN f_@hopperList[hopperInsert]; IF (hopperInsert_ hopperInsert+1) >= maxHopper THEN Error; END; EnumerateHopper:PROCEDURE[call:PROCEDURE[NodePtr]RETURNS[BOOLEAN]]=BEGIN node:NodePtr; FOR hopperRemove_hopperRemove,hopperRemove+1 WHILE hopperRemove