--CellsTry --this module attempts to make an initial ordering of the columns DIRECTORY IODefs: FROM "IODefs", CellsDefs: FROM "CellsDefs"; CellsTry:PROGRAM IMPORTS IODefs, CellsDefs EXPORTS CellsDefs= BEGIN OPEN CellsDefs; Error:SIGNAL=CODE; Space:CHARACTER=' ; Ret:CHARACTER=' ; Id:TYPE=INTEGER; Signal:TYPE=INTEGER; Group:TYPE=INTEGER; Remember:TYPE=INTEGER; maxGroup:INTEGER=500; maxIds:INTEGER=2000; maxSignal:INTEGER=signalMax; GroupEntry:TYPE=RECORD[active,chain:Id]; Ids:TYPE=RECORD[sig:Signal, chain:Id, active:BOOLEAN]; Use:TYPE=RECORD[total,used:[0..256)]; RememberEntry:TYPE=RECORD[type:INTEGER, me,friend,other:Signal]; groupsType:TYPE=ARRAY [0..maxGroup) OF GroupEntry; -- a group is all the ids connecting to a particular track signal idsType:TYPE=ARRAY [0..maxIds) OF Ids; --ids are list storage for constructing groups useType:TYPE=ARRAY [0..maxSignal) OF Use; --to keep track of how many instances of a signal name exits rememberType:TYPE=ARRAY [0..maxGroup) OF RememberEntry; columnListType:TYPE=ARRAY [0..maxSignal) OF Signal; groups:LONG POINTER TO groupsType; ids:LONG POINTER TO idsType; use:LONG POINTER TO useType; remember:LONG POINTER TO rememberType; columnList:LONG POINTER TO columnListType; nextId:Id; nextRemember:Remember; groupEnd:INTEGER_0; ClusterColumns:PUBLIC PROCEDURE= {SigToGroups; MakeUseCounts; Reduce; Rebuild; FixEnds; NumberColumns}; SigToGroups:PROCEDURE=BEGIN ids^_ALL[[0,-1,FALSE]]; nextId_0; groups^_ALL[[0,-1]]; groupEnd_0; FOR s:Signal IN [0..maxSignal) DO IF sig[s].def=NIL THEN LOOP; groupEnd_MAX[groupEnd,s+1]; Append[s,s]; SELECT sig[s].def.s.type FROM norPullUp=>BEGIN base:Signal_sig[s].def.s.e; --Append[base,base]; FOR j:TList_sig[s].def.next, j.next UNTIL j=NIL DO IF j.s.type=norPullDown THEN {Append[j.s.d,j.s.d]; Append[j.s.d,base]}; ENDLOOP; END; pass1=>BEGIN --Append[sig[s].def.s.d,sig[s].def.s.d]; Append[sig[s].def.s.d,sig[s].def.s.g]; Append[sig[s].def.s.d,sig[s].def.s.e]; END; ENDCASE; ENDLOOP; FOR s:Signal IN [0..maxSignal) DO IF sig[s].def=NIL THEN LOOP; SELECT sig[s].def.s.type FROM wire=>BEGIN base:Signal_sig[s].def.s.e; FOR j:TList_sig[s].def.next, j.next UNTIL j=NIL DO t:Id=groups[base].chain; q:Id=groups[j.s.d].chain; l:Id_-1; FOR k:Id_q,ids[k].chain UNTIL k=-1 DO l_k; ENDLOOP; groups[base].chain_q; --groupEnd_MAX[groupEnd,base]; IF l#-1 THEN ids[l].chain_t; groups[j.s.d].chain_-1; --groupEnd_MAX[groupEnd,j.s.d]; SubstituteX[base,j.s.d]; ENDLOOP; END; ENDCASE; ENDLOOP; MakeActiveCounts[]; END; SubstituteX:PROCEDURE[new,old:Signal]=BEGIN t,f:Id; IF new=old THEN Error; FOR g:Group IN [0..maxGroup) DO FOR i:Id_groups[g].chain,ids[i].chain UNTIL i=-1 DO IF ~(ids[i].sig=old AND ids[i].active) THEN LOOP; t_-1; FOR j:Id_groups[g].chain,f UNTIL j=-1 DO f_ids[j].chain; IF ids[j].sig=new THEN {IF t=-1 THEN groups[g].chain_f ELSE ids[t].chain_f}; t_j; ENDLOOP; ids[i].sig_new; ENDLOOP; ENDLOOP; END; Append:PROCEDURE[from,to:Signal]=BEGIN t:Id=nextId; FOR i:Id _groups[to].chain,ids[i].chain UNTIL i=-1 DO IF ids[i].sig=from THEN RETURN; ENDLOOP; nextId_nextId+1; IF nextId>=maxIds THEN {Error; RETURN}; ids[t]_[from,groups[to].chain,TRUE]; groups[to].chain_t; END; MakeActiveCounts:PROCEDURE=BEGIN FOR g:Group IN [0..groupEnd) DO n:INTEGER_0; FOR i:Id _groups[g].chain,ids[i].chain UNTIL i=-1 DO IF ids[i].active THEN n_n+1; ENDLOOP; groups[g].active_n; ENDLOOP; END; MakeUseCounts:PROCEDURE=BEGIN use^_ALL[[0,0]]; FOR g:Group IN [0..groupEnd) DO IF groups[g].active=0 THEN LOOP; FOR i:Id _groups[g].chain,ids[i].chain UNTIL i=-1 DO IF ~ids[i].active THEN LOOP; use[ids[i].sig].total_use[ids[i].sig].total+1; ENDLOOP; ENDLOOP; END; Reduce:PROCEDURE=BEGIN remember^_ALL[[0,0,0,-1]]; nextRemember_0; PrintGroups[]; FOR g:Group IN [0..groupEnd) DO IF groups[g].active=1 THEN BEGIN friend:Signal_ids[groups[g].chain].sig; IF use[g].total=0 THEN BEGIN IF g=friend THEN Error; RememberMe[4,g,friend,-1]; END; KillGroup[g]; END; ENDLOOP; DO FOR hard:INTEGER IN [0..2] DO progress:BOOLEAN_FALSE; PrintGroups[]; --PrintUse[]; PrintRemember[]; FOR s:Signal IN [0..maxSignal) DO excess:INTEGER=use[s].total-use[s].used; IF hard=2 THEN {IF excess>0 AND ReduceParallelUses[s] THEN progress_TRUE} ELSE SELECT excess FROM 0=>NULL; 1=>{ReduceSingleUses[s]; progress_TRUE}; 2=>IF hard=1 AND ReduceDoubleUses[s] THEN progress_TRUE; ENDCASE; ENDLOOP; IF progress THEN EXIT; IF hard=2 THEN BEGIN FOR g:Group IN [0..groupEnd) DO IF groups[g].active#0 THEN {ReduceRandomly[g]; progress_TRUE; EXIT}; ENDLOOP; IF progress THEN EXIT; RETURN; END; ENDLOOP; ENDLOOP; END; ReduceRandomly:PROCEDURE[g:Group]=BEGIN FOR i:Id_groups[g].chain,ids[i].chain UNTIL i=-1 DO IF ~ids[i].active THEN LOOP; ids[i].active_FALSE; use[ids[i].sig].used_use[ids[i].sig].used+1; DecrementActive[g]; RETURN; ENDLOOP; Error; END; ReduceSingleUses:PROCEDURE[s:Signal]=BEGIN --s occurs exactly once FOR g:Group IN [0..groupEnd) DO IF groups[g].active=0 THEN LOOP; FOR i:Id_groups[g].chain,ids[i].chain UNTIL i=-1 DO friend,other:Signal; IF ~(ids[i].sig=s AND ids[i].active) THEN LOOP; use[s].used_use[s].total; ids[i].active_FALSE; [friend,other]_AnyMember[g]; RememberMe[1,s,friend,other]; DecrementActive[g]; RETURN; ENDLOOP; ENDLOOP; Error; END; ReduceDoubleUses:PROCEDURE[s:Signal] RETURNS[progress:BOOLEAN]=BEGIN friend,other:Signal; FOR g:Group IN [0..groupEnd) DO IF groups[g].active#2 THEN LOOP; FOR i:Id_groups[g].chain,ids[i].chain UNTIL i=-1 DO IF ~(ids[i].sig=s AND ids[i].active) THEN LOOP; use[s].used_use[s].total; ids[i].active_FALSE; [friend,other]_AnyMember[g]; RememberMe[2,s,friend,other]; groups[g].active_0; Substitute[friend,s]; RETURN[TRUE]; ENDLOOP; ENDLOOP; RETURN[FALSE]; END; ReduceParallelUses:PROCEDURE[s:Signal] RETURNS[progress:BOOLEAN]=BEGIN FOR g:Group IN [0..groupEnd) DO IF groups[g].active=0 THEN LOOP; FOR i:Id_groups[g].chain,ids[i].chain UNTIL i=-1 DO IF ~(ids[i].sig=s AND ids[i].active) THEN LOOP; FOR j:Id_groups[g].chain,ids[j].chain UNTIL j=-1 DO IF ~(ids[j].active AND i#j AND Verify[s,ids[j].sig]) THEN LOOP; RememberMe[3,s,ids[j].sig,-1]; Remove[s]; RETURN[TRUE]; ENDLOOP; ENDLOOP; ENDLOOP; RETURN[FALSE]; END; AnyMember:PROCEDURE[g:Group] RETURNS[a,b:Signal]=BEGIN a_b_-1; FOR i:Id_groups[g].chain,ids[i].chain UNTIL i=-1 DO IF ~ids[i].active THEN LOOP; IF a=-1 THEN a_ids[i].sig ELSE {b_ids[i].sig; RETURN}; ENDLOOP; IF a=-1 THEN Error; END; DecrementActive:PROCEDURE[g:Group]=BEGIN groups[g].active_groups[g].active-1; IF groups[g].active=1 THEN KillGroup[g]; END; KillGroup:PROCEDURE[g:Group]=BEGIN FOR j:Id_groups[g].chain,ids[j].chain UNTIL j=-1 DO IF ~ids[j].active THEN LOOP; ids[j].active_FALSE; use[ids[j].sig].used_use[ids[j].sig].used+1; groups[g].active_0; RETURN; ENDLOOP; Error; END; Substitute:PROCEDURE[new,old:Signal]=BEGIN FOR g:Group IN [0..groupEnd) DO IF groups[g].active=0 THEN LOOP; FOR i:Id_groups[g].chain,ids[i].chain UNTIL i=-1 DO IF ~(ids[i].sig=old AND ids[i].active) THEN LOOP; ids[i].sig_new; FOR j:Id_groups[g].chain,ids[j].chain UNTIL j=-1 DO IF j#i AND ids[j].sig=new AND ids[j].active THEN BEGIN ids[j].active_FALSE; use[new].used_use[new].used+1; DecrementActive[g]; END; ENDLOOP; ENDLOOP; ENDLOOP; END; debug:Signal_-1; Verify:PROCEDURE[s,t:Signal] RETURNS[BOOLEAN]=BEGIN sFound,tFound:BOOLEAN; IF s=debug THEN Error; FOR g:Group IN [0..groupEnd) DO IF groups[g].active=0 THEN LOOP; sFound_tFound_FALSE; FOR i:Id_groups[g].chain,ids[i].chain UNTIL i=-1 DO IF ~ids[i].active THEN LOOP; SELECT ids[i].sig FROM s=>sFound_TRUE; t=>tFound_TRUE; ENDCASE; ENDLOOP; IF sFound AND ~tFound THEN BEGIN IF s=debug THEN Error; RETURN[FALSE]; END; ENDLOOP; RETURN[TRUE]; END; Remove:PROCEDURE[s:Signal]=BEGIN FOR g:Group IN [0..groupEnd) DO IF groups[g].active=0 THEN LOOP; FOR i:Id_groups[g].chain,ids[i].chain UNTIL i=-1 DO IF ~(ids[i].active AND ids[i].sig=s) THEN LOOP; ids[i].active_FALSE; DecrementActive[g]; ENDLOOP; ENDLOOP; use[s].used_use[s].total; END; RememberMe:PROCEDURE[type:INTEGER, me,friend,other:Signal]=BEGIN IF ~(me IN [0..signalMax) AND friend IN [0..signalMax)) THEN Error; begin_friend; remember[nextRemember]_[type,me,friend,other]; nextRemember_nextRemember+1; END; last:Signal; Rebuild:PROCEDURE=BEGIN columnList^_ALL[-1]; last_begin; FOR s:Remember DECREASING IN [0..nextRemember) DO me:Signal=remember[s].me; friend:Signal=remember[s].friend; IF remember[s].type=0 THEN LOOP; IF columnList[me]#-1 THEN Error; Mid[me,friend] ENDLOOP; END; Front:PROCEDURE[s:Signal]={columnList[s]_begin; begin_s}; Back:PROCEDURE[s:Signal]={columnList[last]_s; last_s}; Mid:PROCEDURE[s,t:Signal]=BEGIN q:Signal=columnList[t]; IF q=-1 THEN BEGIN IF t#last THEN columnList[last]_t; last_s; END; columnList[s]_q; columnList[t]_s; END; FixEnds:PROCEDURE=BEGIN FOR s:Signal_begin,columnList[s] UNTIL s=-1 DO last_s; ENDLOOP; FOR s:Signal IN [0..maxSignal) DO SELECT sig[s].fixed FROM hi=> FixEnd[s,TRUE];lo=> FixEnd[s,FALSE]; ENDCASE; ENDLOOP; END; FixEnd:PROCEDURE[f:Signal,hi:BOOLEAN]=BEGIN back:Signal_-1; FOR s:Signal_begin,columnList[s] UNTIL s=-1 DO IF f#s THEN {back_s; LOOP}; IF back=-1 THEN begin_columnList[s] ELSE {columnList[back]_columnList[s]; IF s=last THEN last_back}; columnList[s]_-1; IF hi THEN Back[f] ELSE Front[f]; RETURN; ENDLOOP; Error; END; begin:Signal_-1; NumberColumns:PROCEDURE=BEGIN c:INTEGER_0; column^_ALL[0]; FOR s:Signal_begin,columnList[s] UNTIL s=-1 DO sig[s].columnNum_c; column[c]_s; c_c+1; ENDLOOP; PrintColumns[]; END; PrintColumns:PROCEDURE=BEGIN OPEN IODefs; IF chip THEN RETURN; FOR c:INTEGER IN [0..maxSignal) UNTIL column[c]=0 DO WriteChar[Ret]; WriteDecimal[c]; WriteChar[Space]; WriteString[Lookup2[column[c]]]; ENDLOOP; END; PrintGroups:PROCEDURE=BEGIN OPEN IODefs; k:INTEGER; IF chip THEN RETURN; FOR g:Group IN [0..groupEnd) DO IF groups[g].chain=-1 THEN LOOP; WriteChar[Ret]; WriteDecimal[g]; WriteChar[Space]; WriteDecimal[groups[g].active]; WriteChar[Space]; k_0; FOR i:Id_groups[g].chain,ids[i].chain UNTIL i=-1 OR (k_k+1)>30 DO WriteChar[Space]; WriteChar[IF ids[i].active THEN Space ELSE 'X]; WriteChar[Space]; --WriteDecimal[ids[i].sig]; WriteString[Lookup2[ids[i].sig]]; ENDLOOP; ENDLOOP; END; PrintUse:PROCEDURE=BEGIN OPEN IODefs; IF chip THEN RETURN; FOR s:Group IN [0..maxSignal) DO IF use[s].total=0 THEN LOOP; WriteChar[Ret]; WriteDecimal[s]; WriteChar[Space]; WriteString[Lookup2[s]]; WriteChar[Space]; WriteDecimal[use[s].total]; WriteChar[Space]; WriteDecimal[use[s].used]; ENDLOOP; END; PrintRemember:PROCEDURE=BEGIN OPEN IODefs; FOR s:Remember IN [0..nextRemember) DO WriteChar[Ret]; WriteDecimal[s]; WriteChar[Space]; WriteDecimal[remember[s].type]; WriteChar[Space]; WriteString[Lookup2[remember[s].me]]; WriteChar[Space]; WriteString[Lookup2[remember[s].friend]]; ENDLOOP; END; InitStorage:PROCEDURE=BEGIN groups_zone.NEW[groupsType]; ids_zone.NEW[idsType]; use_zone.NEW[useType]; remember_zone.NEW[rememberType]; columnList_zone.NEW[columnListType]; END; InitStorage; END.. Rebuild:PROCEDURE=BEGIN columnList_ALL[-1]; last_begin; FOR s:Remember DECREASING IN [0..nextRemember) DO me:Signal=remember[s].me; friend:Signal=remember[s].friend; other:Signal=remember[s].other; upSide:BOOLEAN_FALSE; IF remember[s].type=0 THEN LOOP; IF columnList[me]#-1 THEN Error; SELECT other FROM -2,-1 => {Back[me]; LOOP}; -3 => {Front[me]; LOOP}; -4 => upSide_FALSE; -5 => upSide_TRUE; ENDCASE=>FOR s:Signal_friend,columnList[s] UNTIL s=-1 DO IF s=other THEN {upSide_TRUE; EXIT}; ENDLOOP; IF upSide THEN IF last=friend THEN Back[me] ELSE Mid[me,friend] ELSE IF friend=begin THEN Front[me] ELSE FOR t:Signal_begin,columnList[t] UNTIL t=-1 DO IF columnList[t]=friend THEN {Mid[me,t]; EXIT}; ENDLOOP; ENDLOOP; END;