--Cells --this module does three quite independent tasks: -- 1) It reads and parses the input file -- 2) it makes an initial assignment of columns, sources before uses -- 3) it makes an initial assignment of rows, packing upward. DIRECTORY ppdefs, ZoneAllocDefs, IODefs, ImageDefs, CellsDefs, StringDefs, SystemDefs, StreamDefs; Cells:PROGRAM IMPORTS StringDefs, ppdefs, ImageDefs, IODefs, SystemDefs, StreamDefs, ZoneAllocDefs EXPORTS CellsDefs=BEGIN OPEN CellsDefs; Error:SIGNAL=CODE; Done:SIGNAL=CODE; Feed:CHARACTER=14C; Tab:CHARACTER=' ; Comma:CHARACTER=',; SQ:CHARACTER=''; Gets:CHARACTER='←; lParen:CHARACTER='(; rParen:CHARACTER='); Plus:CHARACTER='+; Minus:CHARACTER='-; Del:CHARACTER=377C; --///// PARSE ///// gnd:INTEGER=3; vdd:INTEGER=2; int:INTEGER=1; equalCode:INTEGER=-1; endFileCode:INTEGER=-2; norCode:INTEGER=-3; rtBktCode:INTEGER=-4; aoiCode:INTEGER=-5; passCode:INTEGER=-6; cutCode:INTEGER=-7; wireCode:INTEGER=-8; fixedCode:INTEGER=-9; nearCode:INTEGER=-10; sig:PUBLIC LONG POINTER TO sigType; innstream:StreamDefs.DiskHandle←NIL; fileName:STRING← [50]; ParseInput:PUBLIC PROCEDURE=BEGIN Parse[GetInputFileName[]]; IF TRUE THEN PrintSig[]; END; GetInputFileName:PROCEDURE RETURNS[STRING]=BEGIN ok:BOOLEAN; IF chip THEN BEGIN OPEN ppdefs; [ok, fileName, ] ← typeIn[""L, "input file name= "L,""L]; IF fileName.length=0 OR NOT ok THEN ImageDefs.StopMesa[]; fileName ← FixExtension[fileName, ".txt"L]; RETURN[fileName]; END; AskForFileName["input file name= "]; IF fileName.length=0 THEN ImageDefs.StopMesa[]; StringDefs.AppendString[fileName,".txt"]; RETURN[fileName]; END; FixExtension: PROCEDURE [s, ext: STRING] RETURNS [se: STRING] = BEGIN OPEN ppdefs; FOR i: CARDINAL IN [0..s.length) DO IF s[i] = '. THEN RETURN[s] ENDLOOP; se ← GetString[s.length + ext.length]; StringDefs.AppendString[to: se, from: s]; StringDefs.AppendString[to: se, from: ext]; FreeString[s]; END; AskForFileName:PROCEDURE[s:STRING]= BEGIN i:CARDINAL; IODefs.WriteChar[Ret]; IODefs.WriteString[s]; IODefs.ReadID[fileName !IODefs.Rubout=>RETRY]; FOR i IN [0..fileName.length) DO IF fileName[i]='. THEN BEGIN fileName.length←i; EXIT; END; ENDLOOP; END; Parse:PROCEDURE[file:STRING]=BEGIN innstream←StreamDefs.NewByteStream[file,StreamDefs.Read]; held←Del; sig↑←ALL[NilSig]; hold←FALSE; TListInit[]; DictInit[]; ReadTheFile[]; innstream.destroy[innstream]; END; ReadTheFile:PROCEDURE=BEGIN DO base:INTEGER←0; DO t:INTEGER←GetToken[]; SELECT t FROM >0=>{IF base=0 THEN base←t ELSE Error; LOOP}; =0=>Error; equalCode=>LOOP; endFileCode=>RETURN; nearCode=>{[]←Number[]; Error};--near not implemented fixedCode=>BEGIN x:INTEGER←Number[]; IF sig[base].def=NIL AND x#-1 THEN Error;--parse error SELECT x FROM 0=>sig[base].fixed←lo; -1=>sig[base].fixed←hi; ENDCASE=>{sig[base].columnNum←x; sig[base].fixed←mid}; END; norCode,aoiCode=>BEGIN ptr:TList←GetTlistWithT[]; last:TList←sig[base].def; IF base<=0 THEN Error; ptr.s↑←[type:norPullUp,cutG:FALSE,cutD:FALSE,g:vdd,d:int,e:base]; SetSig[base,ptr,last]; DO t←GetToken[]; SELECT t FROM rtBktCode=>EXIT; <=0=>Error; ENDCASE; ptr←ptr.next←GetTlistWithT[]; ptr.s↑←[type:norPullDown,cutG:FALSE,cutD:FALSE,g:vdd,d:t,e:int]; ptr.next←last; ENDLOOP; END; wireCode=>BEGIN ptr:TList←GetTlistWithT[]; last:TList←sig[base].def; IF base<=0 THEN Error; ptr.s↑←[type:wire,cutG:FALSE,cutD:FALSE,g:vdd,d:int,e:base]; SetSig[base,ptr,last]; DO t←GetToken[]; SELECT t FROM rtBktCode=>EXIT; <=0=>Error; ENDCASE; ptr←ptr.next←GetTlistWithT[]; ptr.s↑←[type:wire,cutG:FALSE,cutD:FALSE,g:vdd,d:t,e:int]; ptr.next←last; ENDLOOP; END; cutCode=>BEGIN IF base<=0 THEN Error; t←GetToken[]; IF t<=0 THEN Error; FOR j:TList←sig[base].def,j.next DO IF j=NIL THEN {Error; EXIT}; IF j.s.d=t THEN {j.s.cutD←TRUE; EXIT}; IF j.s.g=t THEN {j.s.cutG←TRUE; EXIT}; ENDLOOP; END; passCode=>BEGIN a,b:INTEGER; ptr,last:TList; IF base<=0 THEN Error; SELECT a←GetToken[] FROM rtBktCode,<=0=>Error; ENDCASE; SELECT b←GetToken[] FROM rtBktCode,<=0=>Error; ENDCASE; SELECT GetToken[] FROM rtBktCode=>NULL; ENDCASE=>Error; Append[base,a]; Append[b,a]; last←sig[base].def; ptr←GetTlistWithT[]; ptr.s↑←[type:pass1,cutG:FALSE,cutD:FALSE,g:b,d:a,e:base]; SetSig[base,ptr,last]; last←sig[a].def; ptr←GetTlistWithT[]; ptr.s↑←[type:pass2,cutG:FALSE,cutD:FALSE,g:gnd,d:b,e:base]; SetSig[a,ptr,last]; END; -- aoiCode=>BEGIN -- DO -- t←GetToken[]; -- SELECT t FROM rtBktCode=>EXIT; <=0=>Error; ENDCASE; -- ENDLOOP; -- END; ENDCASE=>Error; EXIT; ENDLOOP; ENDLOOP; END; SetSig:PROCEDURE[s:INTEGER,ptr,last:TList]=BEGIN ptr.next←last; sig[s]←NilSig; sig[s].def←ptr; sig[s].printString←dict[dictBase+s].s; END; Append:PROCEDURE[s,a:INTEGER]=BEGIN j:TList←NIL; ptr:TList←GetTlistWithT[]; ptr.s↑←[type:pass,cutG:FALSE,cutD:FALSE,g:gnd,d:a,e:int]; FOR i:TList←sig[s].def, i.next UNTIL i=NIL DO j←i; ENDLOOP; IF j=NIL THEN sig[s].def←ptr ELSE j.next←ptr; END; --////// manage list and transistor storage tListArrayType:TYPE=ARRAY[0..tListMax) OF TListBody; tArrayType:TYPE=ARRAY[0..tMax) OF Transistor; tListArray:LONG POINTER TO tListArrayType; tArray:LONG POINTER TO tArrayType; tListEnd,tEnd:INTEGER; tListMax:INTEGER=3000; tMax:INTEGER=2000; TListInit:PROCEDURE=BEGIN tListEnd←tEnd←0; END; GetTlistWithT:PROCEDURE RETURNS[x:TList]=BEGIN x←@tListArray[tListEnd]; tListEnd←tListEnd+1; x↑←[s:@tArray[tEnd],next:NIL]; tEnd←tEnd+1; END; --////// end of list and transistor storage --////// manage tokens and dictionary dictType:TYPE=ARRAY [0..dictMax) OF Dict; dict:LONG POINTER TO dictType; dictMax:INTEGER=1000; dictEnd:INTEGER←0; dictBase:INTEGER←4; Dict:TYPE=RECORD[s:STRING,v:INTEGER]; DictInit:PROCEDURE=BEGIN dict[0]←["nor",norCode]; dict[1]←["aoi",aoiCode]; dict[2]←["pass",passCode]; dict[3]←["end",endFileCode]; dict[4]←["illegal",0]; dict[5]←["int",int]; dict[6]←["gnd",gnd]; dict[7]←["vdd",vdd]; dict[8]←["cut",cutCode]; dict[9]←["wire",wireCode]; dict[10]←["fixed",fixedCode]; dict[11]←["near",nearCode]; dictEnd←12; END; GetToken:PROCEDURE RETURNS[INTEGER]=BEGIN DO t:STRING←GetRealWords[]; IF t=NIL THEN RETURN[endFileCode]; SELECT t[0] FROM '==>RETURN[equalCode]; ',,'[=>LOOP; ']=>RETURN[rtBktCode]; ENDCASE=>RETURN[Lookup[t]]; ENDLOOP; END; Lookup:PROCEDURE[s:STRING] RETURNS[z:INTEGER]=BEGIN z←dictEnd; FOR i:INTEGER IN [0..z) DO IF SameString[s,dict[i].s] THEN RETURN[dict[i].v]; ENDLOOP; dict[z]←[s,z-dictBase]; dictEnd←dictEnd+1; RETURN[dict[z].v]; END; Lookup2:PUBLIC PROCEDURE[z:INTEGER] RETURNS[STRING]=BEGIN RETURN[dict[z+dictBase].s]; END; hold:BOOLEAN; holdC:CHARACTER←' ; GetRealWords:PROCEDURE RETURNS[t:STRING]=BEGIN s:STRING←GetFreeString[]; c:CHARACTER; s.length←0; t←NIL; IF hold THEN {hold←FALSE; s[0]←holdC; s.length←1; RETURN[s]}; DO IF innstream.endof[innstream] THEN RETURN[NIL]; SELECT c←GetChar[] FROM Space,Ret,Tab,Comma=>IF s.length >0 THEN RETURN[s] ELSE s.length←0; IN ['a..'z],SQ,Gets,lParen,rParen,Plus,Minus, IN ['0..'9]=> {s[s.length]←c; s.length←s.length+1}; IN ['A..'Z]=> {s[s.length]←c-'A+'a; s.length←s.length+1}; '[,'],'==> IF s.length=0 THEN {s[0]←c; s.length←1; RETURN[s];} ELSE {hold←TRUE; holdC←c; RETURN[s]}; ENDCASE=>Error;--illegal character ENDLOOP; END; Number:PROCEDURE RETURNS[INTEGER]=BEGIN found,min:BOOLEAN←FALSE; c:CHARACTER; i:INTEGER←0; DO SELECT c←GetChar[] FROM Space,Ret,Tab,Comma=>IF found THEN RETURN[IF min THEN -i ELSE i]; IN ['0..'9]=>{i←i*10+(c-'0); found←TRUE}; Minus=> min←TRUE; ENDCASE=>Error;--illegal character ENDLOOP; END; Suck:PROCEDURE= {UNTIL SELECT Get[] FROM Ret=>TRUE, ENDCASE=>FALSE DO ENDLOOP}; held:CHARACTER←Del; GetChar:PROCEDURE RETURNS[c:CHARACTER]=BEGIN IF held#Del THEN {c←held; held←Del} ELSE c←Get[]; IF c=Minus AND (held←Get[])=Minus THEN {Suck[]; held←Del; c←Ret}; END; Get:PROCEDURE RETURNS[c:CHARACTER]=--INLINE--BEGIN c←innstream.get[innstream]; END; empties:ARRAY [0..200) OF STRING←ALL[NIL]; emptyEnd:INTEGER←0; GetFreeString:PROCEDURE RETURNS[s:STRING]=BEGIN IF emptyEnd=0 THEN RETURN[SystemDefs.AllocateHeapString[30]]; emptyEnd←emptyEnd-1; RETURN[empties[emptyEnd]]; END; FreeString:PROCEDURE[s:STRING]=BEGIN IF emptyEnd<200 THEN { empties[emptyEnd]←s; emptyEnd←emptyEnd+1} ELSE SystemDefs.FreeHeapString[s]; END; SameString:PROCEDURE[a,b:STRING]RETURNS[BOOLEAN]=BEGIN IF a.length#b.length THEN RETURN[FALSE]; FOR i:CARDINAL IN [0..a.length) DO IF a[i]#b[i] THEN RETURN[FALSE]; ENDLOOP; RETURN[TRUE]; END; PrintSig:PROCEDURE=BEGIN OPEN IODefs; IF ~print THEN RETURN; FOR i:INTEGER IN [8..signalMax) DO IF sig[i].def=NIL THEN LOOP; WriteChar[Ret]; WriteDecimal[i]; WriteChar[' ]; WriteString[Lookup2[i]]; WriteChar[' ]; FOR j:TList←sig[i].def,j.next UNTIL j=NIL DO t:TP←j.s; WriteChar['[]; WriteDecimal[t.g]; WriteChar[' ]; WriteDecimal[t.d]; WriteChar[' ]; WriteDecimal[t.e]; WriteChar[']]; ENDLOOP; ENDLOOP; END; --///// END PARSE ////// --///////////ASSIGN COLUMNS ColumnEntry:TYPE=RECORD[s:INTEGER]; column:PUBLIC LONG POINTER TO columnType; AssignColumns:PUBLIC PROCEDURE=BEGIN c:INTEGER←0; s:INTEGER; IncrementUp:PROCEDURE[i:INTEGER]=BEGIN sig[i].up←sig[i].up+1; END; DecrementUp:PROCEDURE[i:INTEGER]= BEGIN sig[i].up←sig[i].up-1; IF sig[i].up=0 THEN AddToAvailable[i]; END; EnumerateLegs:PROCEDURE[s:INTEGER,c:PROCEDURE[INTEGER]]=BEGIN FOR t:TList←sig[s].def,t.next UNTIL t=NIL DO IF t.s.type=pass THEN LOOP; IF ~(t.s.cutD OR t.s.d=s) THEN c[t.s.d]; IF ~(t.s.cutG OR t.s.g=s OR t.s.type=pass1) THEN c[t.s.g]; ENDLOOP; END; SetColumn:PROCEDURE[s:INTEGER]={column[c]←s; sig[s].columnNum←c; c←c+1}; FOR i:INTEGER IN [1..signalMax) DO EnumerateLegs[i,IncrementUp]; ENDLOOP; availableEnd←0; column↑←ALL[0]; runCount←0; FOR i:INTEGER IN [1..signalMax) DO SELECT sig[i].fixed FROM lo=>SetColumn[i]; mid=>column[sig[i].columnNum]←i; ENDCASE; ENDLOOP; FOR i:INTEGER IN [1..signalMax) DO IF sig[i].def#NIL AND sig[i].up=0 THEN AddToAvailable[i]; ENDLOOP; c←0; UNTIL c>=columnMax DO s←column[c]; IF s=0 THEN SELECT s←GetBestSignal[] FROM 0 => EXIT; -1 => {c←c+1; LOOP}; ENDCASE=>--IF sig[s].def=NIL OR sig[s].def.s.type#wire THEN {column[c]←s; sig[s].columnNum←c}; EnumerateLegs[s,DecrementUp]; c←c+1; ENDLOOP; FOR i:INTEGER IN [1..signalMax) DO IF sig[i].fixed=hi THEN SetColumn[i]; ENDLOOP; RemoveInvisibleColumns[]; IF FALSE THEN PrintColumns[]; IF FALSE THEN DumpCols[]; END; availableType:TYPE=ARRAY[0..availableMax) OF INTEGER; available:LONG POINTER TO availableType; availableMax:INTEGER=400; availableEnd:INTEGER; runCount:INTEGER; AddToAvailable:PROCEDURE[i:INTEGER]=BEGIN IF i=gnd OR i=vdd OR i=int OR sig[i].fixed#none THEN RETURN; available[availableEnd]←i; availableEnd←availableEnd+1; END; GetBestSignal:PROCEDURE RETURNS[n:INTEGER]=BEGIN IF availableEnd=0 THEN RETURN[0]; n←available[availableEnd-1]; --IF sig[n].def#NIL AND sig[n].def.s.type=wire -- THEN {availableEnd←availableEnd-1; RETURN[n]}; IF runCount=2 AND sig[n].def#NIL THEN {runCount←0; IF ~SearchForNonPullup[] THEN RETURN[-1]}; n←available[availableEnd-1]; IF sig[n].def=NIL THEN runCount←0 ELSE runCount←runCount+1; availableEnd←availableEnd-1; END; HasPullup:PROCEDURE[this:INTEGER] RETURNS[BOOLEAN]=BEGIN IF sig[this].def=NIL THEN RETURN[FALSE]; SELECT sig[this].def.s.type FROM norPullUp,aoiPullUp=>RETURN[TRUE]; ENDCASE=>RETURN[FALSE]; END; SearchForNonPullup:PROCEDURE RETURNS[BOOLEAN]=BEGIN FOR i:INTEGER DECREASING IN [0..availableEnd) DO this:INTEGER←available[i]; IF HasPullup[this] THEN LOOP; available[i]←available[availableEnd-1]; available[availableEnd-1]←this; RETURN[TRUE]; ENDLOOP; RETURN[FALSE]; END; PrintColumns:PROCEDURE=BEGIN OPEN IODefs; IF ~print THEN RETURN; FOR i:INTEGER IN [0..columnMax) DO c:INTEGER←column[i]; IF c=0 THEN LOOP; WriteChar[Ret]; WriteDecimal[i]; WriteChar[Space]; WriteDecimal[c]; WriteChar[Space]; WriteString[Lookup2[c]]; ENDLOOP; END; DumpCols:PROCEDURE=BEGIN OPEN IODefs; IF ~print THEN RETURN; WriteChar[Ret]; FOR i:INTEGER IN [8..signalMax) DO ps:STRING; t:INTEGER; s:LONG POINTER TO SignalEntry←@sig[i]; IF s.printString=NIL AND s.def=NIL THEN LOOP; ps←Lookup2[i]; t←IF ps#NIL THEN ps.length ELSE 0; WriteChar[Ret]; WriteDecimal[i]; WriteChar[Space]; IF i<10 THEN WriteChar[Space]; WriteString[ps]; FOR j:INTEGER IN [0..12-t) DO WriteChar[Space]; ENDLOOP; WriteChar[Space]; WriteDecimal[s.columnNum]; WriteChar[Space]; WriteDecimal[s.up]; WriteChar[Space]; WriteChar[SELECT s.fixed FROM mid=>'m,hi=>'h, lo=>'l, ENDCASE=>'x]; ENDLOOP; END; PrintTracks:PUBLIC PROCEDURE=BEGIN OPEN IODefs; IF ~print THEN RETURN; WriteChar[Ret]; WriteChar[Feed]; EnumerateColumns[ShowTrack]; END; EnumerateColumns:PUBLIC PROCEDURE[call:PROCEDURE[c,s,z:INTEGER]]=BEGIN --c is column number including dummy columns, z is true column number. --s is correcponding signal number. n:INTEGER; z:INTEGER←0; FOR i:INTEGER IN [0..signalMax) DO n←column[i]; IF n>=8 AND ~NoContacts[i] THEN {call[i,n,z]; z←z+1}; ENDLOOP; END; ShowTrack:PROCEDURE[c,s,z:INTEGER]=BEGIN OPEN IODefs; ps:STRING←Lookup2[s]; t:INTEGER←IF ps#NIL THEN ps.length ELSE 0; WriteChar[Ret]; WriteDecimal[z]; WriteChar[Space]; IF z<10 THEN WriteChar[Space]; WriteString[ps]; FOR j:INTEGER IN [0..12-t) DO WriteChar[Space]; ENDLOOP; WriteChar[Tab]; PrintTrack[c]; END; track:PUBLIC LONG POINTER TO trackType; Pair:TYPE=RECORD[a,b:INTEGER]; PrintTrack:PROCEDURE[i:INTEGER]=BEGIN OPEN IODefs; IF ~print THEN RETURN; FOR j:INTEGER IN Track DO WriteChar[track[i][j]]; ENDLOOP; END; NoContacts:PROCEDURE[i:INTEGER] RETURNS[BOOLEAN]=BEGIN FOR j:INTEGER IN Track DO SELECT track[i][j] FROM 'B,Space,'-=>NULL; ENDCASE=>RETURN[FALSE]; ENDLOOP; RETURN[TRUE]; END; RemoveInvisibleColumns:PROCEDURE=BEGIN z:INTEGER←0; c:PROCEDURE[k:INTEGER]=BEGIN END; FOR i:INTEGER IN [0..signalMax) DO track[i]←ALL[Space]; sig[i].invisible←FALSE; ENDLOOP; FOR i:INTEGER IN [0..signalMax) DO Fol[i,c]; ENDLOOP; FOR i:INTEGER IN [0..signalMax) DO n:INTEGER←column[i]; IF n>=8 AND ~sig[n].invisible THEN {column[z]←n; z←z+1}; ENDLOOP; FOR i:INTEGER IN [z..signalMax) DO column[i]←0; ENDLOOP; FOR i:INTEGER IN [0..z) DO sig[column[i]].columnNum←i; ENDLOOP; END; MakeTracks:PUBLIC PROCEDURE=BEGIN track↑←ALL[ALL[Space]]; FOR i:INTEGER IN [0..signalMax) DO t:INTEGER; range:Pair; IF sig[i].def=NIL OR sig[i].invisible THEN LOOP; range←FindRange[i]; IF range.a>=range.b THEN LOOP; t←FindTrack[range]; IF t IN Track THEN FillTrack[i,t,range] ELSE IF print THEN IODefs.WriteChar['X]; ENDLOOP; END; FindRange:PROCEDURE[s:INTEGER] RETURNS[Pair]=BEGIN c:PROCEDURE[k:INTEGER]=BEGIN l:INTEGER=sig[k].columnNum; IF l>high THEN high←l; IF l<lo THEN lo←l; END; high:INTEGER←-1; lo:INTEGER←30000; c[s]; Fol[s,c]; SELECT sig[s].def.s.type FROM pass1=>BEGIN c[sig[s].def.s.d]; --c[sig[s].def.s.g]; END; wire=>BEGIN FOR i:TList ← sig[s].def.next, i.next UNTIL i=NIL DO p:INTEGER←i.s.d; e,g:INTEGER; IF sig[p].def=NIL OR sig[p].def.s.type#pass1 THEN Error; e←sig[p].def.s.d; g←sig[p].def.s.g; IF sig[e].columnNum#high THEN LOOP; IF sig[g].columnNum<=high THEN LOOP; high←sig[g].columnNum; ENDLOOP; END; ENDCASE; IF high=lo THEN RETURN[[lo,high]]; IF high MOD 2 = 1 OR Passer[s,high] THEN high←high+1; IF lo#0 AND lo MOD 2 = 0 AND Passer[s,lo] THEN lo←lo-1; RETURN[[lo,high]]; END; Passer:PROCEDURE[s,g:INTEGER]RETURNS[BOOLEAN]=BEGIN FOR t:TList←sig[g].def,t.next UNTIL t=NIL DO IF t.s.type#pass2 THEN LOOP; IF t.s.d=s OR t.s.e=s THEN RETURN[TRUE]; IF sig[s].def=NIL OR sig[s].def.s.type#wire THEN LOOP; FOR q:TList←sig[s].def.next,q.next UNTIL q=NIL DO IF q.s.d=t.s.d OR q.s.d=t.s.e THEN RETURN[TRUE]; ENDLOOP; ENDLOOP; RETURN[FALSE]; END; Fol:PROCEDURE[k:INTEGER,c:PROCEDURE[INTEGER]]=BEGIN going:BOOLEAN←FALSE; IF k<dictBase THEN RETURN; FOR t:TList←sig[k].def,t.next UNTIL t=NIL DO SELECT t.s.type FROM pass1,pass2 =>NULL; wire=>IF going THEN { IF t.s.d>=dictBase THEN {sig[t.s.d].invisible←TRUE; Fol[t.s.d,c]}; IF t.s.g>=dictBase THEN {sig[t.s.g].invisible←TRUE; Fol[t.s.g,c]}; IF t.s.e>=dictBase THEN {sig[t.s.e].invisible←TRUE; Fol[t.s.e,c]}}; ENDCASE=>{IF t.s.d>=dictBase THEN c[t.s.d]; IF t.s.g>=dictBase THEN c[t.s.g]; IF t.s.e>=dictBase THEN c[t.s.e]}; going←TRUE; ENDLOOP; END; FindTrack:PROCEDURE[p:Pair] RETURNS[INTEGER]=BEGIN FOR i:INTEGER IN Track DO found:BOOLEAN←TRUE; FOR j:INTEGER IN [p.a..p.b] DO IF track[j][i]#Space THEN {found←FALSE; EXIT}; ENDLOOP; IF found THEN RETURN[i]; ENDLOOP; RETURN[-1]; END; FillTrack:PROCEDURE[s,t:INTEGER,p:Pair]=BEGIN c:PROCEDURE[k:INTEGER]={track[sig[k].columnNum][t]←'C}; FOR j:INTEGER IN [p.a..p.b) DO track[j][t]←'-; ENDLOOP; track[p.a][t]←track[p.b][t]←'B; --for blank Fol[s,c]; track[p.a][t]←'1; SELECT sig[s].def.s.type FROM pass1=>BEGIN e:INTEGER←sig[s].def.s.d; g:INTEGER←sig[s].def.s.g; track[sig[e].columnNum][t]←'P; track[sig[g].columnNum][t]←'Q; END; wire=>BEGIN FOR i:TList ← sig[s].def.next, i.next UNTIL i=NIL DO m:INTEGER←i.s.d; e,g:INTEGER; IF sig[m].def=NIL OR sig[m].def.s.type#pass1 THEN Error; e←sig[m].def.s.d; g←sig[m].def.s.g; IF sig[e].columnNum#p.b THEN LOOP; IF sig[g].columnNum<=p.b THEN LOOP; track[sig[e].columnNum][t]←'P; track[sig[g].columnNum][t]←'Q; ENDLOOP; END; ENDCASE; track[sig[s].columnNum][t]←'S; END; zone:PUBLIC UNCOUNTED ZONE; InitStorage:PROCEDURE=BEGIN zone←ZoneAllocDefs.GetAnXMZone[]; sig←zone.NEW[sigType]; tListArray←zone.NEW[tListArrayType]; tArray←zone.NEW[tArrayType]; dict←zone.NEW[dictType←ALL[[NIL,0]]]; column←zone.NEW[columnType]; available←zone.NEW[availableType]; track←zone.NEW[trackType]; END; ReturnStorage:PUBLIC PROCEDURE={zone←ZoneAllocDefs.DestroyAnXMZone[zone]}; InitStorage; END..