--routeChecker.mesa DIRECTORY RouteDefs, IODefs; RouteChecker:PROGRAM IMPORTS RouteDefs EXPORTS RouteDefs=BEGIN OPEN RouteDefs; Error:SIGNAL=CODE;--internal consistancy CheckerComplaint:SIGNAL=CODE; testList:SiliconListPtr_NIL; start:Silicon_[]; solid:BOOLEAN; Ugly:TYPE=RECORD[a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p:BOOLEAN_FALSE]; circuitsTested:ARRAY [0..100) OF Ugly; CheckLayout:PUBLIC CtlProc=BEGIN ShowLabel["CHECKER"]; IF layout=NIL THEN RETURN[-1]; IF testList#NIL THEN Error; circuitsTested_ALL[[]]; EnumerateSilicon[InitSilicon]; EnumerateAllSignals[DoTheWork]; EnumerateSilicon[LogOpens]; RETURN[-1]; END; InitSilicon:PROCEDURE[s:SiliconPtr]={s.circuit_0; s.solid_FALSE}; LogOpens:PROCEDURE[s:SiliconPtr]={IF ~s.solid THEN LogWire[s,"loose wire!"]}; DoTheWork:PROCEDURE[c:CellPtr,s:SignalPtr]= {FollowCircuit[GetSeed[c,s]]}; GetSeed:PROCEDURE[cell:CellPtr,signal:SignalPtr] RETURNS[SiliconPtr]=BEGIN width:Lambda=SELECT signal.level FROM red=>2, blue=>3, ENDCASE=>4; a,b:CoordL_cell.pos; IF signal.circuit=0 OR testList#NIL THEN Error; SELECT signal.side FROM e=>a_[a.x+cell.sizeL.x-1, a.y+signal.offset]; w=>a_[a.x, a.y+signal.offset]; n=>a_[a.x+signal.offset, a.y+cell.sizeL.y-1]; s=>a_[a.x+signal.offset, a.y]; ENDCASE=>Error; SELECT signal.side FROM e,w=>b_[a.x+1,a.y+width]; ENDCASE=>b_[a.x+width,a.y+1]; start_[a,b,both,TRUE,signal.circuit]; RETURN[@start]; END; FollowCircuit:PROCEDURE[sil:SiliconPtr]=BEGIN VerifyCellContact:PROCEDURE[cell:CellPtr]=BEGIN IF ~Overlap2[cell,this] THEN RETURN ELSE BEGIN onE:BOOLEAN=cell.pos.x+cell.sizeL.x=this.pos.x; onW:BOOLEAN=cell.pos.x=this.pos2.x; onN:BOOLEAN=cell.pos.y+cell.sizeL.y=this.pos.y; onS:BOOLEAN=cell.pos.y=this.pos2.y; FOR sl:SignalListPtr_cell.signals,sl.t UNTIL sl=NIL DO signal:SignalPtr=sl.h; IF signal.circuit=this.circuit THEN BEGIN yAll:BOOLEAN=cell.pos.y+signal.offset IN [this.pos2.y-4..this.pos.y]; xAll:BOOLEAN=cell.pos.x+signal.offset IN [this.pos2.x-4..this.pos.x]; SELECT signal.side FROM e=>IF onE AND yAll THEN RETURN; w=>IF onW AND yAll THEN RETURN; n=>IF onN AND xAll THEN RETURN; s=>IF onS AND xAll THEN RETURN; ENDCASE=>{Return[]; ShowString["short to cell"L]}; END; ENDLOOP; END; END; this:SiliconPtr; circuit:Circuit_sil.circuit; old:BOOLEAN_SetBit[circuit]; Push[sil]; UNTIL (this_Pop[])=NIL DO IF this.circuit#circuit THEN Error; FOR sl:SiliconListPtr_layout,sl.t UNTIL sl=NIL DO s:SiliconPtr=sl.h; IF s=this OR s.circuit=circuit AND s.solid OR ~Overlap[s,this] THEN LOOP; IF s.circuit#0 AND s.circuit#circuit THEN {LogWire[this," shorted to "]; ShowWire[s]; LOOP}; s.circuit_circuit; s.solid_solid;--set by Overlap IF solid AND old THEN {LogWire[this," open"]; old_FALSE}; IF solid THEN Push[s]; ENDLOOP; EnumerateCells[VerifyCellContact]; ENDLOOP; END; Push:PROCEDURE[a:SiliconPtr]=BEGIN t:SiliconListPtr_AllocateList[]; t^_[a,testList]; testList_t; END; Pop:PROCEDURE RETURNS[a:SiliconPtr]=BEGIN new:SiliconListPtr_testList; IF new=NIL THEN RETURN[NIL]; a_new.h; testList_new.t; FreeList[new]; END; Overlap:PROCEDURE[a,b:SiliconPtr] RETURNS[BOOLEAN]=BEGIN dx,dy:Lambda; width:Lambda=SELECT a.level FROM red=>IF b.level=blue THEN 0 ELSE 2, blue=>IF b.level=red THEN 0 ELSE 3, ENDCASE=>IF b.level=red THEN 2 ELSE 3; IF width=0 THEN RETURN[FALSE]; IF a.pos.x>=b.pos2.x+width THEN RETURN[FALSE]; IF a.pos.y>=b.pos2.y+width THEN RETURN[FALSE]; IF b.pos.x>=a.pos2.x+width THEN RETURN[FALSE]; IF b.pos.y>=a.pos2.y+width THEN RETURN[FALSE]; dx_MIN[a.pos2.x,b.pos2.x]-MAX[a.pos.x,b.pos.x]; dy_MIN[a.pos2.y,b.pos2.y]-MAX[a.pos.y,b.pos.y]; solid_dx>=width AND dy>=0 OR dy>=width AND dx>=0; RETURN[TRUE]; END; Overlap2:PROCEDURE[a:CellPtr,b:SiliconPtr] RETURNS[BOOLEAN]=BEGIN width:Lambda=IF b.level=red THEN 2 ELSE 3; IF a.pos.x>=b.pos2.x+width THEN RETURN[FALSE]; IF a.pos.y>=b.pos2.y+width THEN RETURN[FALSE]; IF b.pos.x>=a.pos.x+a.sizeL.x+width THEN RETURN[FALSE]; IF b.pos.y>=a.pos.y+a.sizeL.y+width THEN RETURN[FALSE]; RETURN[TRUE]; END; SetBit:PROCEDURE[c:[0..1600)]RETURNS[x:BOOLEAN]=BEGIN index:[0..100)_c/16; word:Ugly_circuitsTested[index]; SELECT c MOD 16 FROM 0=>{x_word.a; word.a_TRUE}; 1=>{x_word.b; word.b_TRUE}; 2=>{x_word.c; word.c_TRUE}; 3=>{x_word.d; word.d_TRUE}; 4=>{x_word.e; word.e_TRUE}; 5=>{x_word.f; word.f_TRUE}; 6=>{x_word.g; word.g_TRUE}; 7=>{x_word.h; word.h_TRUE}; 8=>{x_word.i; word.i_TRUE}; 9=>{x_word.j; word.j_TRUE}; 10=>{x_word.k; word.k_TRUE}; 11=>{x_word.l; word.l_TRUE}; 12=>{x_word.m; word.m_TRUE}; 13=>{x_word.n; word.n_TRUE}; 14=>{x_word.o; word.o_TRUE}; 15=>{x_word.p; word.p_TRUE}; ENDCASE=>Error; circuitsTested[index]_word; END; first:BOOLEAN_TRUE; LogWire:PROCEDURE[w:SiliconPtr,s:STRING]=BEGIN IF NOT (w.pos2.y-w.pos.y=1 OR w.pos2.x-w.pos.x=1) AND first THEN {first_FALSE; CheckerComplaint}; Return[]; ShowWire[w]; ShowString[s]; END; END. Time: (layout+signals) squared IDs: about 60 Space: about 100 CallStructure: Checklayout(GetSeed FollowCircuit(Push Pop SetBit Overlap VerifyCellContact(Overlap2))) everybody uses LogWire